ProjectZombie/src/projectzombie/entity/EntityZombie.java

230 lines
5.6 KiB
Java
Executable File

package projectzombie.entity;
import java.util.Random;
import bdf.types.BdfNamedList;
import bdf.types.BdfObject;
import projectzombie.Main;
import projectzombie.init.Models;
import projectzombie.model.Model;
import projectzombie.util.gl.texture.TextureReference;
import projectzombie.util.math.astar.AStar;
import projectzombie.util.math.astar.AStarSearcher;
import projectzombie.util.math.random.OpenSimplexNoise;
import gl_engine.vec.Vec2d;
import gl_engine.vec.Vec2i;
import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer;
public class EntityZombie extends Entity implements EntityAlive, EntityKillWithParticles
{
protected OpenSimplexNoise noise_movement;
protected OpenSimplexNoise noise_gun_fire;
protected OpenSimplexNoise noise_gun_angle;
protected OpenSimplexNoise noise_target_x;
protected OpenSimplexNoise noise_target_y;
protected long seed;
protected double time;
protected double health_max = 100;
protected double health = health_max;
protected int gun_interval = 0;
protected int gun_level = 0;
private Vec2i walk_direction;
private int walk_scan_cooldown = 0;
private boolean can_see_player = false;
private int walking_for = 0;
public EntityZombie(BdfObject bdf) {
super(bdf);
// Set some settings
hitbox = 0.5;
isSolid = true;
goThroughSolid = false;
crossUnWalkable = false;
}
@Override
public void BdfClassLoad(BdfObject bdf) {
super.BdfClassLoad(bdf);
BdfNamedList nl = bdf.getNamedList();
health_max = nl.get("max_health").getDouble();
health = nl.get("health").getDouble();
gun_interval = nl.get("gun_interval").getInteger();
gun_level = nl.get("gun_level").getInteger();
seed = nl.get("seed").getLong();
Random rand = new Random(seed);
noise_movement = new OpenSimplexNoise(rand.nextLong());
noise_gun_fire = new OpenSimplexNoise(rand.nextLong());
noise_gun_angle = new OpenSimplexNoise(rand.nextLong());
noise_target_x = new OpenSimplexNoise(rand.nextLong());
noise_target_y = new OpenSimplexNoise(rand.nextLong());
}
@Override
public void BdfClassSave(BdfObject bdf) {
super.BdfClassSave(bdf);
BdfNamedList nl = bdf.getNamedList();
nl.set("max_health", BdfObject.withDouble(health_max));
nl.set("health", BdfObject.withDouble(health));
nl.set("gun_interval", BdfObject.withInteger(gun_interval));
nl.set("gun_level", BdfObject.withInteger(gun_level));
nl.set("seed", BdfObject.withLong(seed));
}
public EntityZombie(Vec2d pos) {
super(pos);
seed = rand.nextLong();
Random rand = new Random(seed);
noise_movement = new OpenSimplexNoise(rand.nextLong());
noise_gun_fire = new OpenSimplexNoise(rand.nextLong());
noise_gun_angle = new OpenSimplexNoise(rand.nextLong());
noise_target_x = new OpenSimplexNoise(rand.nextLong());
noise_target_y = new OpenSimplexNoise(rand.nextLong());
time = 0;
// Set some settings
hitbox = 0.5;
isSolid = true;
goThroughSolid = false;
crossUnWalkable = false;
}
@Override
public void tick(Chunk chunk, Layer layer) {
super.tick(chunk, layer);
//System.out.println(walk_direction != null ? (walk_direction.x + ", " + walk_direction.y + ": " + pos.toInt().x + ", " + pos.toInt().y) : "null");
if(walk_direction == null) {
walk_scan_cooldown -= 1;
}
if(
(walk_direction != null && pos.toInt().equal(walk_direction) &&
pos.squareDistance(Main.player.pos) > 2) ||
walk_scan_cooldown < 1 || walking_for > 200)
{
AStar astar = new AStar(pos.toInt(), 16, new AStarSearcher(layer, crossUnWalkable));
Vec2i path[] = astar.getPath(Main.player.pos.toInt());
walk_scan_cooldown = 100;
walking_for = 0;
if(path != null && path.length > 1) {
walk_direction = path[1];
} else {
walk_direction = Main.player.pos.toInt();
}
can_see_player = (path != null);
}
// Walk towards the player
if(walk_direction != null)
{
double angle = Math.toDegrees(Math.atan2(
walk_direction.x - (this.pos.x - 0.5) + noise_target_x.eval(time, pos.x/10, pos.y/10),
walk_direction.y - (this.pos.y - 0.5) + noise_target_y.eval(time, pos.x/10, pos.y/10)));
this.moveTowards(angle);
walking_for += 1;
}
if(can_see_player && noise_gun_fire.eval(time, 0) > 0 && !Main.player.dead && !Main.player.in_animation)
{
// Get the angle between the player and the zombie
double angle_fire = Math.atan2(pos.x - Main.player.pos.x, pos.y - Main.player.pos.y);
gun_interval += 1;
gun_interval %= 10;
if(gun_interval == 0)
{
// Aim the gun at the player
double angle_gun = Math.toDegrees(angle_fire) + 180;
angle_gun += noise_gun_angle.eval(time, 0)*20;
// Fire the gun
int d = (int)(1 + gun_level / 5.0);
layer.spawnEntity(new EntityBullet(pos.copy(), this, angle_gun, 20*d*d, 60));
}
}
// Increase time
time += 0.001;
}
@Override
public Model getModel() {
return Models.ENTITY_ZOMBIE_F;
}
public void moveInVector(Vec2d vec) {
super.moveInVector(vec, 0.06);
}
public void moveTowards(double angle) {
super.moveTowards(angle, 0.06);
}
@Override
public void addHealth(double amount) {
health += amount;
}
@Override
public void removeHealth(double amount) {
health -= amount;
}
@Override
public double getHealth() {
return health;
}
@Override
public void resetHealth() {
health = health_max;
}
@Override
public void clearHealth() {
health = 0;
}
@Override
public double maxHealth() {
return health_max;
}
@Override
public void setHealth(double health) {
this.health = health;
}
@Override
public int bloodParticles() {
return 10;
}
@Override
public void killWithParticles() {
// TODO Auto-generated method stub
}
}