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 } }