diff --git a/resources/texmap.png b/resources/texmap.png index b727656..855021c 100644 Binary files a/resources/texmap.png and b/resources/texmap.png differ diff --git a/resources/texmap.xcf b/resources/texmap.xcf index d5e6740..cdad716 100644 Binary files a/resources/texmap.xcf and b/resources/texmap.xcf differ diff --git a/src/shootergame/display/DisplayRenderUI.java b/src/shootergame/display/DisplayRenderUI.java index d03e9db..27ad0c7 100644 --- a/src/shootergame/display/DisplayRenderUI.java +++ b/src/shootergame/display/DisplayRenderUI.java @@ -1,6 +1,7 @@ package shootergame.display; import shootergame.Main; +import shootergame.display.bossbar.BossBars; import shootergame.entity.player.EntityPlayer; import shootergame.init.Textures; import shootergame.inventory.Inventory; @@ -139,6 +140,9 @@ public class DisplayRenderUI GlHelpers.popMatrix(); } + // Render the boss bars + BossBars.render(); + // Render the loaded menu Main.menu.render(); } diff --git a/src/shootergame/display/bossbar/BossBars.java b/src/shootergame/display/bossbar/BossBars.java new file mode 100644 index 0000000..dace10f --- /dev/null +++ b/src/shootergame/display/bossbar/BossBars.java @@ -0,0 +1,53 @@ +package shootergame.display.bossbar; + +import java.util.ArrayList; + +import shootergame.init.Textures; +import shootergame.util.gl.GlHelpers; +import shootergame.util.gl.texture.TextureReference; + +public class BossBars +{ + private static final ArrayList bossbars = new ArrayList(); + + public static void register(IBossBar bossbar) { + bossbars.add(bossbar); + } + + public static void render() + { + TextureReference health_fg = Textures.UI_HEALTH_FG; + TextureReference health_bg = Textures.UI_HEALTH_BG; + ArrayList toRemove = new ArrayList(); + + // Render the boss bars + int i = 0; + for(IBossBar bossbar : bossbars) + { + double max_health = bossbar.maxHealth(); + double a = 1 - (bossbar.getHealth() / max_health); + GlHelpers.begin(); + + health_bg.texCoord(0, 1); GlHelpers.vertex2(-3.2, 8.5 - i); + health_bg.texCoord(0, 0); GlHelpers.vertex2(-3.2, 9.0 - i); + health_bg.texCoord(1, 0); GlHelpers.vertex2(3.2, 9.0 - i); + health_bg.texCoord(1, 1); GlHelpers.vertex2(3.2, 8.5 - i); + + health_fg.texCoord(0, 1); GlHelpers.vertex2(-3.2, 8.5 - i); + health_fg.texCoord(0, 0); GlHelpers.vertex2(-3.2, 9.0 - i); + health_fg.texCoord(1-a, 0); GlHelpers.vertex2(3.2-a*6.4, 9.0 - i); + health_fg.texCoord(1-a, 1); GlHelpers.vertex2(3.2-a*6.4, 8.5 - i); + + GlHelpers.end(); + i += 1; + + if(!bossbar.displayBossBar()) { + toRemove.add(bossbar); + } + } + + for(IBossBar bossbar : toRemove) { + bossbars.remove(toRemove); + } + } +} diff --git a/src/shootergame/display/bossbar/IBossBar.java b/src/shootergame/display/bossbar/IBossBar.java new file mode 100644 index 0000000..f61d8ca --- /dev/null +++ b/src/shootergame/display/bossbar/IBossBar.java @@ -0,0 +1,9 @@ +package shootergame.display.bossbar; + +import shootergame.entity.EntityAlive; + +public interface IBossBar extends EntityAlive +{ + public String getName(); + public boolean displayBossBar(); +} diff --git a/src/shootergame/entity/Entity.java b/src/shootergame/entity/Entity.java index 8bdcd76..313e058 100644 --- a/src/shootergame/entity/Entity.java +++ b/src/shootergame/entity/Entity.java @@ -242,7 +242,7 @@ public class Entity implements ITransparentObject @Override public void MainLoopUpdate() { if(!Main.game_paused) { - moveTowards(angle, a[0]/100.0); + moveTowards(Math.toRadians(angle) + 180, a[0]/100.0); a[0] -= a[0] / 100.0; } } diff --git a/src/shootergame/entity/EntityAlive.java b/src/shootergame/entity/EntityAlive.java index f786445..4ec531d 100644 --- a/src/shootergame/entity/EntityAlive.java +++ b/src/shootergame/entity/EntityAlive.java @@ -1,5 +1,7 @@ package shootergame.entity; +import shootergame.world.layer.Layer; + public interface EntityAlive { public void addHealth(double amount); @@ -10,4 +12,7 @@ public interface EntityAlive public double maxHealth(); public void setHealth(double health); public int bloodParticles(); + + public default void onDeath(Layer layer) { + } } diff --git a/src/shootergame/entity/EntityBoss.java b/src/shootergame/entity/EntityBoss.java new file mode 100644 index 0000000..0dc0512 --- /dev/null +++ b/src/shootergame/entity/EntityBoss.java @@ -0,0 +1,226 @@ +package shootergame.entity; + +import shootergame.Main; +import shootergame.display.Camera; +import shootergame.display.bossbar.BossBars; +import shootergame.display.bossbar.IBossBar; +import shootergame.init.Items; +import shootergame.init.Textures; +import shootergame.time.GameTimer; +import shootergame.util.gl.texture.TextureReference; +import shootergame.util.math.ItemStack; +import shootergame.util.math.MathHelpers; +import shootergame.util.math.random.OpenSimplexNoise; +import shootergame.util.math.random.RandomHelpers; +import shootergame.util.math.vec.Vec2d; +import shootergame.util.math.vec.Vec3d; +import shootergame.world.chunk.Chunk; +import shootergame.world.layer.Layer; + +public class EntityBoss extends EntityVertical implements IBossBar +{ + private boolean moving = false; + private boolean firing = false; + private double max_health = 25000; + private double health = max_health; + private int bullet_frequency = 0; + private int spawn_frequency = 0; + + private OpenSimplexNoise noise_gun; + private OpenSimplexNoise noise_walk; + private OpenSimplexNoise noise_spawn; + + public EntityBoss(Vec2d pos) { + super(null, new Vec2d(4, 4)); + + this.isSolid = true; + this.goThroughSolid = false; + this.crossUnWalkable = false; + this.hitbox = 1; + + this.noise_gun = new OpenSimplexNoise(rand.nextLong()); + this.noise_walk = new OpenSimplexNoise(rand.nextLong()); + this.noise_spawn = new OpenSimplexNoise(rand.nextLong()); + + Main.player.gun_level = 4; + Main.player.defence_level = 4; + Main.player.getInventory().setItem(new ItemStack(Items.HEALTH_POTION, 100, (byte)50), 0); + Main.player.getInventory().setItem(new ItemStack(Items.TNT, 100, (byte)10), 1); + Main.player.getInventory().setItem(new ItemStack(Items.GRAPPLING_HOOK, 100, (byte)2), 2); + + BossBars.register(this); + } + + @Override + public void tick(Chunk chunk, Layer layer) { + super.tick(chunk, layer); + + double angle = Math.atan2(pos.x - Main.player.pos.x, pos.y - Main.player.pos.y); + this.angle = Math.toDegrees(angle) + 180; + + if(this.noise_spawn.eval(GameTimer.getTime() / 5000.0, 0) > 0.2) { + if(spawn_frequency == 0) { + EntityZombie zombie = new EntityZombie(); + int r = 2; + zombie.pos = this.pos.add(new Vec2d( + RandomHelpers.randrange(rand, -r, r), + RandomHelpers.randrange(rand, -r, r))); + layer.spawnEntity(zombie); + spawn_frequency = 50; + } + spawn_frequency -= 1; + } + + if(this.noise_gun.eval(GameTimer.getTime() / 5000.0, 0) > 0 && !Main.player.dead && !Main.player.in_animation) { + + if(bullet_frequency == 0) + { + Vec2d gun_offset = MathHelpers.moveTowards2(1, Math.toRadians(90 + this.angle)); + + Vec3d pos1 = new Vec3d(pos.x + gun_offset.x, pos.y + gun_offset.y, 1); + double distance_1 = pos1.distance(new Vec3d(pos.x, pos.y, pos1.z)); + double angle1_0 = Math.toDegrees(Math.atan2( + pos1.x - Main.player.pos.x, pos1.y - Main.player.pos.y)) + 180; + double angle1_1 = Math.toDegrees(Math.atan2(distance_1, pos1.z - 1)) - 90; + + Vec3d pos2 = new Vec3d(pos.x - gun_offset.x, pos.y - gun_offset.y, 1); + double distance_2 = pos2.distance(new Vec3d(pos.x, pos.y, pos2.z)); + double angle2_0 = Math.toDegrees(Math.atan2(pos2.x - Main.player.pos.x, pos2.y - Main.player.pos.y)) + 180; + double angle2_1 = Math.toDegrees(Math.atan2(distance_2, pos2.z - 1)) - 90; + + layer.spawnEntity(new EntityBullet(pos.add(gun_offset), this, angle1_0, 20, 5, 1000 + ).withHeight(angle1_1, pos1.z)); + layer.spawnEntity(new EntityBullet(pos.subtract(gun_offset), this, angle2_0, 20, 5, 1000 + ).withHeight(angle2_1, pos2.z)); + bullet_frequency = 10; + } + + bullet_frequency -= 1; + } + + if(this.noise_gun.eval(GameTimer.getTime() / 5000.0, 0) > -0.2) { + this.firing = true; + } + + else { + this.firing = false; + } + + if(this.noise_walk.eval(GameTimer.getTime() / 5000.0, 0) > -0.4) { + this.moveForward(); + this.moving = true; + } + + else { + this.moving = false; + } + } + + @Override + public void render(Vec2d pos, Camera camera, TextureReference tex, Vec2d size) + { + // Get the boss texture + if(moving && firing) { + tex = Textures.ENTITY_BOSS_WALKING_AND_FIRING; + } else if(moving) { + tex = Textures.ENTITY_BOSS_WALKING; + } else if(firing) { + tex = Textures.ENTITY_BOSS_FIRING; + } else { + tex = Textures.ENTITY_BOSS_IDLE; + } + + // Call render + super.render(pos, camera, tex, size); + } + + @Override + public void addHealth(double amount) { + this.health += amount; + } + + @Override + public void removeHealth(double amount) { + this.health -= amount; + } + + @Override + public double getHealth() { + return health; + } + + @Override + public void resetHealth() { + this.health = max_health; + } + + @Override + public void clearHealth() { + this.health = 0; + } + + @Override + public double maxHealth() { + return max_health; + } + + @Override + public void setHealth(double health) { + this.health = health; + } + + @Override + public int bloodParticles() { + return 5; + } + + @Override + public String getName() { + return "Final Boss"; + } + + @Override + public boolean displayBossBar() { + return health >= 0; + } + + @Override + public void moveTowards(double angle) { + this.moveTowards(angle, 0.02); + } + + @Override + public void moveBackward() { + this.moveBackward(0.02); + } + + @Override + public void moveForward() { + this.moveForward(0.02); + } + + @Override + public void onDeath(Layer layer) { + IBossBar.super.onDeath(layer); + + /* + Drop some powerful loot + */ + + // Pick level 5 defence or level 5 gun upgrade + ItemStack stack; + if(rand.nextBoolean()) { + stack = new ItemStack(Items.DEFENCE_UPGRADE, 1, (byte)6); + } else { + stack = new ItemStack(Items.GUN_UPGRADE, 1, (byte)6); + } + + // Spawn the loot + layer.spawnEntity(new EntityItem(pos.copy(), stack)); + layer.spawnEntity(new EntityItem(pos.copy(), new ItemStack( + Items.HEALTH_POTION, RandomHelpers.randrange(rand, 20), (byte)50))); + layer.spawnEntity(new EntityItem(pos.copy(), new ItemStack( + Items.AMMO, RandomHelpers.randrange(rand, 200), (byte)50))); + layer.spawnEntity(new EntityItem(pos.copy(), new ItemStack(Items.GRAPPLING_HOOK, 1, (byte)2))); + } +} diff --git a/src/shootergame/entity/EntityBullet.java b/src/shootergame/entity/EntityBullet.java index 3779b10..8db47f3 100644 --- a/src/shootergame/entity/EntityBullet.java +++ b/src/shootergame/entity/EntityBullet.java @@ -21,7 +21,10 @@ public class EntityBullet extends EntityParticle private double damage; private int breakchance; - public EntityBullet(Vec2d pos, Entity parent, double angle, double damage, int breakchance) { + private double height = 0.2; + private double height_angle = 0; + + public EntityBullet(Vec2d pos, Entity parent, double angle, double damage, int breakchance, int despawn_time) { super(0.2, 0.4); // Store some specified values @@ -30,17 +33,39 @@ public class EntityBullet extends EntityParticle this.parent = parent; this.damage = damage; this.breakchance = breakchance; + this.time = despawn_time; // Play the gun sound Sounds.GUN.play(new Vec3d(pos.x, pos.y, 0.4), 2); } + public EntityBullet withHeight(double angle, double height) { + this.height_angle = angle; + this.height = height; + return this; + } + @Override public void tick(Chunk chunk, Layer layer) { super.tick(chunk, layer); // Move forward in the bullets angle, very quickly - this.moveForward(0.2); + Vec3d pos3 = MathHelpers.moveTowards3(0.2, new Vec2d(Math.toRadians(this.angle), + Math.toRadians(this.height_angle))).add( + new Vec3d(pos.x, pos.y, height)); + height = pos3.z; + + if(moveIsLegal(new Vec2d(pos3.x, pos.y))) { + pos.x = pos3.x; + } if(moveIsLegal(new Vec2d(pos.x, pos3.x))) { + pos.y = pos3.y; + } + + if(height < 0 || height > 16) { + kill(); + return; + } + chunk = layer.getChunk(pos); // Is the bullets new position intersecting a solid object @@ -79,10 +104,10 @@ public class EntityBullet extends EntityParticle } // Loop over the nearby entities - for(Entity e : layer.getNearbyEntities(pos, 0.5)) + for(Entity e : layer.getNearbyEntities(pos, 1)) { // Is this entity alive and not the parent - if(e instanceof EntityAlive && e != parent) + if(e instanceof EntityAlive && e != parent && e.pos.squareDistance(this.pos) < e.hitbox) { // Get the alive entity EntityAlive ea = (EntityAlive)e; @@ -107,10 +132,10 @@ public class EntityBullet extends EntityParticle } } - // Increase time - time++; + // Decrease time + time -= 1; - if(time > 60) { + if(time <= 0) { chunk.killEntity(this); } } @@ -123,6 +148,9 @@ public class EntityBullet extends EntityParticle MathHelpers.floor(pos.x), MathHelpers.floor(pos.y))); GlHelpers.color3(1 * light, 0.8 * light, 0.3 * light); + // Set the height + this.setHeight(height); + // Call super super.render(pos, camera); GlHelpers.color3(1, 1, 1); diff --git a/src/shootergame/entity/EntityGrapplingHook.java b/src/shootergame/entity/EntityGrapplingHook.java new file mode 100644 index 0000000..afe761f --- /dev/null +++ b/src/shootergame/entity/EntityGrapplingHook.java @@ -0,0 +1,88 @@ +package shootergame.entity; + +import shootergame.Main; +import shootergame.display.Camera; +import shootergame.entity.player.EntityPlayer; +import shootergame.init.Layers; +import shootergame.init.Textures; +import shootergame.util.gl.GlHelpers; +import shootergame.util.math.vec.Vec2d; +import shootergame.world.chunk.Chunk; +import shootergame.world.layer.Layer; +import shootergame.world.layer.layergen.LayerGenRememberPlayerPos; + +public class EntityGrapplingHook extends EntityVertical +{ + private int layerId; + private double height; + private Entity entity; + + public EntityGrapplingHook(Vec2d pos, int layerId, Entity entity) { + super(Textures.ENTITY_GRAPPLING_HOOK, new Vec2d(1, 16)); + + this.layerId = layerId; + this.height = -16; + this.entity = entity; + this.pos = pos; + + if(entity instanceof EntityPlayer) { + EntityPlayer ep = (EntityPlayer)entity; + ep.in_animation = true; + } + } + + @Override + public void tick(Chunk chunk, Layer layer) { + super.tick(chunk, layer); + + if(entity instanceof EntityHeight) { + EntityHeight ea = (EntityHeight)entity; + + if(height >= -8) + { + double h = ea.getHeight(); + ea.setHeight(h + 0.02); + + if(entity instanceof EntityPlayer) { + EntityPlayer ep = (EntityPlayer)entity; + ep.moving = true; + } + + if(h >= 8) + { + ea.setHeight(0); + Main.world.setLayer(Layers.getLayer(layerId)); + + if(entity instanceof EntityPlayer) + { + EntityPlayer ep = (EntityPlayer)entity; + ep.in_animation = false; + ep.moving = false; + } + + + if(layer instanceof LayerGenRememberPlayerPos) { + LayerGenRememberPlayerPos lgrpp = (LayerGenRememberPlayerPos)layer; + entity.pos = lgrpp.getPlayerPos(); + } + + kill(); + return; + } + } + + else { + height += 0.05; + } + } + } + + @Override + public void render(Vec2d pos, Camera camera) { + GlHelpers.pushMatrix(); + GlHelpers.translate(0, 0, height); + super.render(pos, camera); + GlHelpers.popMatrix(); + } + +} diff --git a/src/shootergame/entity/EntityHeight.java b/src/shootergame/entity/EntityHeight.java new file mode 100644 index 0000000..5cfa23b --- /dev/null +++ b/src/shootergame/entity/EntityHeight.java @@ -0,0 +1,7 @@ +package shootergame.entity; + +public interface EntityHeight +{ + public double getHeight(); + public void setHeight(double height); +} diff --git a/src/shootergame/entity/EntityParticle.java b/src/shootergame/entity/EntityParticle.java index 4af6f5c..c9e9be8 100644 --- a/src/shootergame/entity/EntityParticle.java +++ b/src/shootergame/entity/EntityParticle.java @@ -24,6 +24,10 @@ public class EntityParticle extends Entity this.size = size; } + public void setHeight(double height) { + this.height = height; + } + @Override public void tick(Chunk chunk, Layer layer) { super.tick(chunk, layer); diff --git a/src/shootergame/entity/EntityZombie.java b/src/shootergame/entity/EntityZombie.java index 53cd582..87c850b 100644 --- a/src/shootergame/entity/EntityZombie.java +++ b/src/shootergame/entity/EntityZombie.java @@ -44,7 +44,7 @@ public class EntityZombie extends EntityVertical implements EntityAlive this.angle += noise_movement.eval(time, 0)*80; this.moveForward(); - if(noise_gun_fire.eval(time, 0) > 0) + if(noise_gun_fire.eval(time, 0) > 0 && !Main.player.dead && !Main.player.in_animation) { gun_interval += 1; gun_interval %= 10; @@ -58,7 +58,7 @@ public class EntityZombie extends EntityVertical implements EntityAlive // Fire the gun int d = (int)(1 + gun_level / 5.0); int b = (int)(1 - gun_level / 5.0); - layer.spawnEntity(new EntityBullet(pos.copy(), this, angle_gun, 20*d*d, 5*b*b)); + layer.spawnEntity(new EntityBullet(pos.copy(), this, angle_gun, 20*d*d, 5*b*b, 60)); } } @@ -72,7 +72,7 @@ public class EntityZombie extends EntityVertical implements EntityAlive } @Override - public void moveBackward(double speed) { + public void moveBackward() { super.moveBackward(0.06); } diff --git a/src/shootergame/entity/player/EntityPlayer.java b/src/shootergame/entity/player/EntityPlayer.java index b3ec9ab..144d8ff 100644 --- a/src/shootergame/entity/player/EntityPlayer.java +++ b/src/shootergame/entity/player/EntityPlayer.java @@ -6,6 +6,7 @@ import shootergame.display.Camera; import shootergame.entity.Entity; import shootergame.entity.EntityAlive; import shootergame.entity.EntityBullet; +import shootergame.entity.EntityHeight; import shootergame.entity.EntityInventory; import shootergame.entity.EntityItem; import shootergame.entity.EntityVertical; @@ -20,7 +21,7 @@ import shootergame.util.math.vec.Vec2i; import shootergame.world.chunk.Chunk; import shootergame.world.layer.Layer; -public class EntityPlayer extends EntityVertical implements EntityAlive, EntityInventory +public class EntityPlayer extends EntityVertical implements EntityAlive, EntityInventory, EntityHeight { public boolean MOVE_FORWARD = false; public boolean MOVE_BACKWARD = false; @@ -185,7 +186,7 @@ public class EntityPlayer extends EntityVertical implements EntityAlive, EntityI int d = (int)(1 + gun_level / 4.0); int b = (int)(1 + gun_level / 4.0); Main.world.getLayer().spawnEntity(new EntityBullet(pos.copy(), this, angle + this.angle, - 20*d*d, 5/b)); + 20*d*d, 5/b, 60)); } } @@ -262,4 +263,14 @@ public class EntityPlayer extends EntityVertical implements EntityAlive, EntityI public int bloodParticles() { return 5; } + + @Override + public double getHeight() { + return height; + } + + @Override + public void setHeight(double height) { + this.height = height; + } } diff --git a/src/shootergame/init/Items.java b/src/shootergame/init/Items.java index dd187fa..f852aa0 100644 --- a/src/shootergame/init/Items.java +++ b/src/shootergame/init/Items.java @@ -5,6 +5,7 @@ import shootergame.items.ItemAmmo; import shootergame.items.ItemDefenceUpgrade; import shootergame.items.ItemEmpty; import shootergame.items.ItemFlare; +import shootergame.items.ItemGrapplingHook; import shootergame.items.ItemGunUpgrade; import shootergame.items.ItemHealthPotion; import shootergame.items.ItemLantern; @@ -20,4 +21,5 @@ public class Items public static final Item TNT = new ItemTnt("tnt"); public static final Item LANTERN = new ItemLantern("lantern"); public static final Item FLARE = new ItemFlare("flare"); + public static final Item GRAPPLING_HOOK = new ItemGrapplingHook("grappling_hook"); } diff --git a/src/shootergame/init/Layers.java b/src/shootergame/init/Layers.java index 97fc396..86c7587 100644 --- a/src/shootergame/init/Layers.java +++ b/src/shootergame/init/Layers.java @@ -4,10 +4,11 @@ import java.util.ArrayList; import java.util.Random; import shootergame.Main; +import shootergame.util.math.vec.Vec2d; import shootergame.world.World; import shootergame.world.layer.Layer; +import shootergame.world.layer.layergen.LayerGenBossArena; import shootergame.world.layer.layergen.LayerGenCaves; -import shootergame.world.layer.layergen.LayerGenEarth; import shootergame.world.layer.layergen.LayerGenLavaCaves; public class Layers @@ -17,7 +18,7 @@ public class Layers public static void init(long seed) { // Create all the layers - EARTH = new Layer(new Random(seed), new LayerGenEarth(), 0); + EARTH = new Layer(new Random(seed), new LayerGenBossArena(), 0); CAVES = new Layer(new Random(seed), new LayerGenCaves(), 1); LAVA_CAVES = new Layer(new Random(seed), new LayerGenLavaCaves(), 2); diff --git a/src/shootergame/init/Textures.java b/src/shootergame/init/Textures.java index 6d2cdad..dc0a630 100644 --- a/src/shootergame/init/Textures.java +++ b/src/shootergame/init/Textures.java @@ -40,6 +40,33 @@ public class Textures public static final TextureReference TILE_CHEST = texmap.getTextureReference(2, 3, 4, 5); public static final TextureReference ENTITY_FLARE = texmap.getTextureReference(6, 7, 15, 16); public static final TextureReference ENTITY_DUMMY = texmap.getTextureReference(7, 8, 15, 16); + public static final TextureReference TILE_BOSS_PORTAL = texmap.getTextureReference(18, 20, 0, 2); + public static final TextureReference ITEM_GRAPPLING_HOOK = texmap.getTextureReference(18, 19, 2, 3); + public static final TextureReference ENTITY_GRAPPLING_HOOK = texmap.getTextureReference(17, 18, 0, 16); + + public static final AnimationReference ENTITY_BOSS_IDLE = new AnimationReference(50, + texmap.getTextureReference(20, 22, 0, 2), + texmap.getTextureReference(22, 24, 0, 2), + texmap.getTextureReference(24, 26, 0, 2), + texmap.getTextureReference(26, 28, 0, 2)); + + public static final AnimationReference ENTITY_BOSS_FIRING = new AnimationReference(50, + texmap.getTextureReference(20, 22, 2, 4), + texmap.getTextureReference(22, 24, 2, 4), + texmap.getTextureReference(24, 26, 2, 4), + texmap.getTextureReference(26, 28, 2, 4)); + + public static final AnimationReference ENTITY_BOSS_WALKING = new AnimationReference(50, + texmap.getTextureReference(20, 22, 4, 6), + texmap.getTextureReference(22, 24, 4, 6), + texmap.getTextureReference(24, 26, 4, 6), + texmap.getTextureReference(26, 28, 4, 6)); + + public static final AnimationReference ENTITY_BOSS_WALKING_AND_FIRING = new AnimationReference(50, + texmap.getTextureReference(20, 22, 6, 8), + texmap.getTextureReference(22, 24, 6, 8), + texmap.getTextureReference(24, 26, 6, 8), + texmap.getTextureReference(26, 28, 6, 8)); public static final AnimationReference TILE_LANTERN = new AnimationReference(10, texmap.getTextureReference(8, 9, 15, 16), diff --git a/src/shootergame/init/Tiles.java b/src/shootergame/init/Tiles.java index 3d2e0d0..5d160d7 100644 --- a/src/shootergame/init/Tiles.java +++ b/src/shootergame/init/Tiles.java @@ -17,6 +17,7 @@ import shootergame.tiles.TileStone; import shootergame.tiles.TileTree; import shootergame.tiles.TileVoid; import shootergame.tiles.TileWall; +import shootergame.tiles.TileWallUnbreakable; import shootergame.tiles.TileWater; import shootergame.tiles.TileWaterFlow; @@ -40,4 +41,5 @@ public class Tiles public static final Tile LADDER_UP = new TileLadderUp("ladder_up"); public static final Tile CHEST = new TileChest("chest"); public static final Tile LANTERN = new TileLantern("lantern"); + public static final Tile WALL_UNBREAKABLE = new TileWallUnbreakable("wall_unbreakable"); } diff --git a/src/shootergame/items/ItemFlare.java b/src/shootergame/items/ItemFlare.java index 3879964..1d75255 100644 --- a/src/shootergame/items/ItemFlare.java +++ b/src/shootergame/items/ItemFlare.java @@ -22,4 +22,9 @@ public class ItemFlare extends Item layer.spawnEntity(new EntityFlare(entity.pos.copy(), entity.angle)); } + @Override + public String getName(short meta) { + return "Flare"; + } + } diff --git a/src/shootergame/items/ItemGrapplingHook.java b/src/shootergame/items/ItemGrapplingHook.java new file mode 100644 index 0000000..7b3ed68 --- /dev/null +++ b/src/shootergame/items/ItemGrapplingHook.java @@ -0,0 +1,37 @@ +package shootergame.items; + +import shootergame.Main; +import shootergame.entity.Entity; +import shootergame.entity.EntityGrapplingHook; +import shootergame.init.Layers; +import shootergame.init.Textures; +import shootergame.util.math.ItemStack; +import shootergame.util.math.MathHelpers; +import shootergame.util.math.vec.Vec2d; +import shootergame.world.World; +import shootergame.world.chunk.Chunk; +import shootergame.world.layer.Layer; + +public class ItemGrapplingHook extends Item +{ + + public ItemGrapplingHook(String id) { + super(id); + + this.texture = Textures.ITEM_GRAPPLING_HOOK; + } + + @Override + public String getName(short meta) { + return "Grappling Hook"; + } + + @Override + public void onAction(ItemStack stack, Layer layer, Chunk chunk, Entity entity) { + super.onAction(stack, layer, chunk, entity); + + Vec2d pos = entity.pos.add(MathHelpers.moveTowards2(0.01, Math.toRadians(entity.angle))); + layer.spawnEntity(new EntityGrapplingHook(pos, stack.meta, entity)); + } + +} diff --git a/src/shootergame/items/ItemLantern.java b/src/shootergame/items/ItemLantern.java index 80a6886..5e9b7ba 100644 --- a/src/shootergame/items/ItemLantern.java +++ b/src/shootergame/items/ItemLantern.java @@ -27,5 +27,10 @@ public class ItemLantern extends Item super.onAction(stack, layer, chunk, entity); } } + + @Override + public String getName(short meta) { + return "Lantern"; + } } diff --git a/src/shootergame/tiles/TileWallUnbreakable.java b/src/shootergame/tiles/TileWallUnbreakable.java new file mode 100644 index 0000000..ef32153 --- /dev/null +++ b/src/shootergame/tiles/TileWallUnbreakable.java @@ -0,0 +1,12 @@ +package shootergame.tiles; + +public class TileWallUnbreakable extends TileWall +{ + + public TileWallUnbreakable(String id) { + super(id); + + this.unbreakable = true; + } + +} diff --git a/src/shootergame/util/gl/VerticalRender.java b/src/shootergame/util/gl/VerticalRender.java index d1c1934..2aa27dc 100644 --- a/src/shootergame/util/gl/VerticalRender.java +++ b/src/shootergame/util/gl/VerticalRender.java @@ -25,10 +25,10 @@ public class VerticalRender // Render the tile GlHelpers.begin(); - tex.texCoord(1, 1); GlHelpers.vertex3(0.5-w, 0.5, 0); - tex.texCoord(0, 1); GlHelpers.vertex3(0.5+w, 0.5, 0); - tex.texCoord(0, 0); GlHelpers.vertex3(0.5+w, 0.5, h); - tex.texCoord(1, 0); GlHelpers.vertex3(0.5-w, 0.5, h); + tex.texCoord(0, 1); GlHelpers.vertex3(0.5-w, 0.5, 0); + tex.texCoord(1, 1); GlHelpers.vertex3(0.5+w, 0.5, 0); + tex.texCoord(1, 0); GlHelpers.vertex3(0.5+w, 0.5, h); + tex.texCoord(0, 0); GlHelpers.vertex3(0.5-w, 0.5, h); GlHelpers.end(); // Pop the matrix diff --git a/src/shootergame/world/chunk/Chunk.java b/src/shootergame/world/chunk/Chunk.java index af6ef69..044ca71 100644 --- a/src/shootergame/world/chunk/Chunk.java +++ b/src/shootergame/world/chunk/Chunk.java @@ -33,12 +33,14 @@ public class Chunk public ArrayList entities = new ArrayList(); private Layer layer; private Vec2i c_pos; + public boolean dirty; public Chunk(Layer layer, Vec2i c_pos, Random rand) { // Set some specified values this.layer = layer; this.c_pos = c_pos; + this.dirty = false; // Loop over all the tiles in the chunk for(int i=0;i chunks; + private Map2D dirty_chunks; public LayerGen layergen; private Random rand; private long seed; @@ -30,6 +32,7 @@ public class Layer this.seed = rand.nextLong(); this.rand = new Random(); this.chunks = new Map2D(layergen); + this.dirty_chunks = new Map2D(layergen); this.id = id; } @@ -54,6 +57,7 @@ public class Layer { // Tick every entity and every tile in every loaded chunk for(Map2DElement e : chunks) { + layergen.tickLayer(this, e.o); e.o.tickEntities(); e.o.tickRandomly(); } @@ -159,15 +163,33 @@ public class Layer public void loadChunk(Vec2i pos) { - // Create a unique seed specific to this chunk - long cseed = new Random(pos.x).nextLong() + new Random(pos.y).nextLong() + seed; + // Has the chunk been saved for later + if(dirty_chunks.contains(pos)) { + chunks.set(pos, dirty_chunks.get(pos)); + } - Chunk chunk = new Chunk(this, pos, rand); - chunks.set(pos, chunk); - layergen.generateChunk(chunk, this, seed, new Random(cseed), pos); + else + { + // Create a unique seed specific to this chunk + long cseed = new Random(pos.x).nextLong() + new Random(pos.y).nextLong() + seed; + + // Create and generate the chunk + Chunk chunk = new Chunk(this, pos, rand); + chunks.set(pos, chunk); + layergen.generateChunk(chunk, this, seed, new Random(cseed), pos); + chunk.dirty = false; + } } - public void unloadChunk(Vec2i pos) { + public void unloadChunk(Vec2i pos) + { + // Store the chunk if its a dirty chunk + Chunk chunk = chunks.get(pos); + if(chunk.dirty) { + dirty_chunks.set(pos, chunk); + } + + // Remove the chunk chunks.remove(pos); } diff --git a/src/shootergame/world/layer/layergen/LayerGen.java b/src/shootergame/world/layer/layergen/LayerGen.java index 5c1092a..0039b3d 100644 --- a/src/shootergame/world/layer/layergen/LayerGen.java +++ b/src/shootergame/world/layer/layergen/LayerGen.java @@ -19,4 +19,7 @@ public abstract class LayerGen implements IMap2D public Chunk getEmpty(Vec2i pos) { return Chunk.CHUNK_EMPTY; } + + public void tickLayer(Layer layer, Chunk chunk) { + } } diff --git a/src/shootergame/world/layer/layergen/LayerGenBossArena.java b/src/shootergame/world/layer/layergen/LayerGenBossArena.java new file mode 100644 index 0000000..8a6338c --- /dev/null +++ b/src/shootergame/world/layer/layergen/LayerGenBossArena.java @@ -0,0 +1,109 @@ +package shootergame.world.layer.layergen; + +import java.util.Random; + +import shootergame.entity.EntityBoss; +import shootergame.entity.player.EntityPlayer; +import shootergame.init.Tiles; +import shootergame.util.math.MathHelpers; +import shootergame.util.math.TileState; +import shootergame.util.math.random.RandomHelpers; +import shootergame.util.math.vec.Vec2d; +import shootergame.util.math.vec.Vec2i; +import shootergame.world.chunk.Chunk; +import shootergame.world.layer.Layer; + +public class LayerGenBossArena extends LayerGen implements LayerGenRememberPlayerPos +{ + private final Vec2i center = new Vec2i(0, 0); + private final int size = 10; + private Vec2d player_pos = new Vec2d(0, 0); + + @Override + public void generateChunk(Chunk chunk, Layer layer, long seed, Random rand, Vec2i pos) + { + // Fill with stone + for(int i=0;i size) { + chunk.setBackTile(Tiles.WALL_UNBREAKABLE.getDefaultState(), tpos); + } + + else if(tpos.squareDistance(center) == size) + { + // Arena decoration wall + if(MathHelpers.positive(tpos.x) == MathHelpers.positive(tpos.y)) { + chunk.setBackTile(Tiles.WALL_UNBREAKABLE.getDefaultState(), tpos); + } + + // Arena lava well + else { + chunk.setFrontTile(Tiles.LAVA.getDefaultState(), tpos); + } + } + + // Arena lava well + else if( + MathHelpers.positive(tpos.x) > size - 2 && + MathHelpers.positive(tpos.y) > size - 2) { + chunk.setFrontTile(Tiles.LAVA.getDefaultState(), tpos); + } + + if(tpos.x == 0 && tpos.y == 0) { + chunk.spawnEntity(new EntityBoss(new Vec2d(0, 0))); + } + } + } + + int t = 16; + for(int i=0;i