feat: Hurt animation and killing of zombie
This commit is contained in:
@ -57,7 +57,9 @@ public class Game {
|
||||
private transient GameStates gameStates = new GameStates(this);
|
||||
private Stats stats = new Stats();
|
||||
|
||||
/** Current time of day in the game (0–600 range). */
|
||||
/**
|
||||
* Current time of day in the game (0–600 range).
|
||||
*/
|
||||
@Setter
|
||||
private int daytime = 0;
|
||||
//
|
||||
@ -83,9 +85,9 @@ public class Game {
|
||||
var steveData = (SteveData) block.getData();
|
||||
|
||||
if (steveData.isTop()) {
|
||||
return new int[] { j, i + 1 };
|
||||
return new int[]{j, i + 1};
|
||||
} else {
|
||||
return new int[] { j, i };
|
||||
return new int[]{j, i};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,12 +210,16 @@ public class Game {
|
||||
int dealDamage = inventory.getItemInHand().map(Item::getDealDamage).orElse(1);
|
||||
if (mob.getHp() - dealDamage <= 0) {
|
||||
// Mob is killed
|
||||
gameStates.dependencies.entityKill.get(mob.getBlockId()).killed(this, mob);
|
||||
gameStates.dependencies.entityKill.get(mob.getBlockId()).killed(this, mob, x, y);
|
||||
world[y][x].remove(mob);
|
||||
} else {
|
||||
mob.decreaseHp(dealDamage);
|
||||
mob.setSpriteState(gameStates.dependencies.entityHurtAnimation.get(mob.getBlockId())
|
||||
.setHurtAnimation(true, mob.getSpriteState().get()));
|
||||
if (mob.getLinkedMobTexture() != null) {
|
||||
mob.getLinkedMobTexture().setSpriteState(gameStates.dependencies.entityHurtAnimation.get(mob.getBlockId())
|
||||
.setHurtAnimation(true, mob.getLinkedMobTexture().getSpriteState().get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
screenRenderer.render(this);
|
||||
@ -228,6 +234,11 @@ public class Game {
|
||||
for (Block mob : mobs) {
|
||||
mob.setSpriteState(gameStates.dependencies.entityHurtAnimation.get(mob.getBlockId())
|
||||
.setHurtAnimation(false, mob.getSpriteState().get()));
|
||||
|
||||
if (mob.getLinkedMobTexture() != null) {
|
||||
mob.getLinkedMobTexture().setSpriteState(gameStates.dependencies.entityHurtAnimation.get(mob.getBlockId())
|
||||
.setHurtAnimation(false, mob.getLinkedMobTexture().getSpriteState().get()));
|
||||
}
|
||||
}
|
||||
screenRenderer.render(this);
|
||||
}).start();
|
||||
@ -387,9 +398,9 @@ public class Game {
|
||||
/**
|
||||
* Checks whether a block is valid for mining based on proximity and visibility.
|
||||
*
|
||||
* @param x x-coordinate.
|
||||
* @param y y-coordinate.
|
||||
* @param terminal terminal context used to determine screen bounds.
|
||||
* @param x x-coordinate.
|
||||
* @param y y-coordinate.
|
||||
* @param terminal terminal context used to determine screen bounds.
|
||||
* @return true if mineable, false otherwise.
|
||||
*/
|
||||
public boolean isMineable(int x, int y, Terminal terminal) {
|
||||
@ -420,9 +431,9 @@ public class Game {
|
||||
/**
|
||||
* Checks whether a block is valid for hitting (attacking).
|
||||
*
|
||||
* @param x x-coordinate.
|
||||
* @param y y-coordinate.
|
||||
* @param terminal terminal context used to determine screen bounds.
|
||||
* @param x x-coordinate.
|
||||
* @param y y-coordinate.
|
||||
* @param terminal terminal context used to determine screen bounds.
|
||||
* @return true if a mob can be hit at the given location.
|
||||
*/
|
||||
public boolean isHitable(int x, int y, Terminal terminal) {
|
||||
|
@ -32,6 +32,7 @@ public class Block {
|
||||
private boolean onFire = false;
|
||||
private int burningTime = 0;
|
||||
private int burningTime2 = 0;
|
||||
private Block linkedMobTexture;
|
||||
|
||||
public Block(String blockId, SpriteLoader.SPRITES sprite) {
|
||||
this.blockId = blockId;
|
||||
|
@ -4,5 +4,5 @@ import cz.jzitnik.game.Game;
|
||||
import cz.jzitnik.game.entities.Block;
|
||||
|
||||
public interface EntityKillInterface {
|
||||
void killed(Game game, Block mob);
|
||||
void killed(Game game, Block mob, int x, int y);
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ public class CowLogic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void killed(Game game, Block mob) {
|
||||
public void killed(Game game, Block mob, int x, int y) {
|
||||
int leatherAmount = random.nextInt(3);
|
||||
InventoryItem inventoryItem = new InventoryItem(leatherAmount, ItemBlockSupplier.getItem("leather"));
|
||||
int beefAmount = random.nextInt(3) + 1;
|
||||
|
@ -199,7 +199,7 @@ public class PigLogic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void killed(Game game, Block mob) {
|
||||
public void killed(Game game, Block mob, int x, int y) {
|
||||
int amount = random.nextInt(2) + 1;
|
||||
InventoryItem inventoryItem = new InventoryItem(amount, ItemBlockSupplier.getItem("porkchop"));
|
||||
game.getInventory().addItem(inventoryItem);
|
||||
|
@ -242,7 +242,7 @@ public class SheepLogic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void killed(Game game, Block mob) {
|
||||
public void killed(Game game, Block mob, int x, int y) {
|
||||
int amount = random.nextInt(3) + 1;
|
||||
var sheepData = (SheepData) mob.getData();
|
||||
|
||||
|
@ -0,0 +1,49 @@
|
||||
package cz.jzitnik.game.mobs.services.zombie;
|
||||
|
||||
import cz.jzitnik.game.Game;
|
||||
import cz.jzitnik.game.annotations.EntityHurtAnimationHandler;
|
||||
import cz.jzitnik.game.annotations.EntityKillHandler;
|
||||
import cz.jzitnik.game.entities.Block;
|
||||
import cz.jzitnik.game.mobs.*;
|
||||
import cz.jzitnik.game.sprites.Zombie;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static cz.jzitnik.game.sprites.Zombie.ZombieState.*;
|
||||
|
||||
@EntityHurtAnimationHandler("zombie")
|
||||
@EntityKillHandler("zombie")
|
||||
public class ZombieHurtKillLogic implements EntityHurtAnimationChanger, EntityKillInterface {
|
||||
private final Random random = new Random();
|
||||
|
||||
public Zombie.ZombieState setHurtAnimation(boolean hurt, Enum current) {
|
||||
if (hurt) {
|
||||
return switch (current) {
|
||||
case TOP, TOP_HURT -> TOP_HURT;
|
||||
case BOTTOM, BOTTOM_HURT -> BOTTOM_HURT;
|
||||
default -> throw new IllegalStateException("Unexpected state: " + current);
|
||||
};
|
||||
}
|
||||
|
||||
return switch (current) {
|
||||
case TOP, TOP_HURT -> TOP;
|
||||
case BOTTOM, BOTTOM_HURT -> BOTTOM;
|
||||
default -> throw new IllegalStateException("Unexpected state: " + current);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void killed(Game game, Block mob, int x, int y) {
|
||||
int rottenFlesh = random.nextInt(3) + 1;
|
||||
|
||||
boolean isTop = mob.getSpriteState().isPresent() && (mob.getSpriteState().get().equals(TOP_HURT) || mob.getSpriteState().get().equals(TOP));
|
||||
int newY = isTop ? y + 1 : y - 1;
|
||||
|
||||
game.getWorld()[newY][x].remove(mob.getLinkedMobTexture());
|
||||
|
||||
// Rotten flesh is currently not an item. So this is commented out
|
||||
// TODO: Add rotten flesh to the game
|
||||
//InventoryItem drop = new InventoryItem(rottenFlesh, ItemBlockSupplier.getItem("rotten_flesh"));
|
||||
//game.getInventory().addItem(drop);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package cz.jzitnik.game.mobs.services.zombie;
|
||||
|
||||
import cz.jzitnik.game.annotations.EntityLogic;
|
||||
import cz.jzitnik.game.mobs.EntityLogicInterface;
|
||||
import cz.jzitnik.game.mobs.EntityLogicProvider;
|
||||
|
||||
@EntityLogic("zombie")
|
||||
public class ZombieMoveLogic implements EntityLogicInterface {
|
||||
@Override
|
||||
public void nextIteration(EntityLogicProvider.EntityLogicMobDTO entityLogicMobDTO) {
|
||||
|
||||
}
|
||||
}
|
@ -1,49 +1,30 @@
|
||||
package cz.jzitnik.game.mobs.services.zombie;
|
||||
|
||||
import cz.jzitnik.game.Game;
|
||||
import cz.jzitnik.game.annotations.EntityHurtAnimationHandler;
|
||||
import cz.jzitnik.game.annotations.EntityKillHandler;
|
||||
import cz.jzitnik.game.annotations.EntityLogic;
|
||||
import cz.jzitnik.game.annotations.EntitySpawn;
|
||||
import cz.jzitnik.game.entities.Block;
|
||||
import cz.jzitnik.game.entities.items.InventoryItem;
|
||||
import cz.jzitnik.game.entities.items.ItemBlockSupplier;
|
||||
import cz.jzitnik.game.mobs.*;
|
||||
import cz.jzitnik.game.mobs.EntitySpawnInterface;
|
||||
import cz.jzitnik.game.sprites.Zombie;
|
||||
import cz.jzitnik.game.sprites.Zombie.ZombieState;
|
||||
import cz.jzitnik.tui.ScreenMovingCalculationProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jline.terminal.Terminal;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static cz.jzitnik.game.sprites.Zombie.ZombieState.*;
|
||||
|
||||
@Slf4j
|
||||
@EntitySpawn
|
||||
@EntityLogic("zombie")
|
||||
@EntityHurtAnimationHandler("zombie")
|
||||
@EntityKillHandler("zombie")
|
||||
public class ZombieLogic
|
||||
implements EntityLogicInterface, EntitySpawnInterface, EntityHurtAnimationChanger, EntityKillInterface {
|
||||
|
||||
public class ZombieSpawnLogic implements EntitySpawnInterface {
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
public void nextIteration(EntityLogicProvider.EntityLogicMobDTO entityLogicMobDTO) {
|
||||
log.debug("Running zombie logic");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn(int playerX, int playerY, Game game, Terminal terminal) {
|
||||
int[] view = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), game.getWorld()[0].length, game.getWorld().length);
|
||||
int startX = view[0];
|
||||
int endX = view[1];
|
||||
|
||||
//attemptZombieSpawn(startX - 20, startX - 5, playerY, game);
|
||||
//attemptZombieSpawn(endX + 5, endX + 20, playerY, game);
|
||||
attemptZombieSpawn(startX - 20, startX - 5, playerY, game);
|
||||
attemptZombieSpawn(endX + 5, endX + 20, playerY, game);
|
||||
}
|
||||
|
||||
|
||||
private void attemptZombieSpawn(int startX, int endX, int centerY, Game game) {
|
||||
if (countZombies(startX, endX, centerY - 15, centerY + 15, game) < 3 && random.nextInt(100) < 2) {
|
||||
var spawnLocations = zombieCanSpawn(startX, endX, centerY, game);
|
||||
@ -54,10 +35,13 @@ public class ZombieLogic
|
||||
int y = loc.getValue();
|
||||
|
||||
var top = ItemBlockSupplier.getEntity("zombie");
|
||||
top.setSpriteState(ZombieState.TOP);
|
||||
top.setSpriteState(Zombie.ZombieState.TOP);
|
||||
|
||||
var bottom = ItemBlockSupplier.getEntity("zombie");
|
||||
bottom.setSpriteState(ZombieState.BOTTOM);
|
||||
bottom.setSpriteState(Zombie.ZombieState.BOTTOM);
|
||||
|
||||
top.setLinkedMobTexture(bottom);
|
||||
bottom.setLinkedMobTexture(top);
|
||||
|
||||
game.getWorld()[y - 1][x].add(top);
|
||||
game.getWorld()[y][x].add(bottom);
|
||||
@ -66,6 +50,7 @@ public class ZombieLogic
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private HashMap<Integer, Integer> zombieCanSpawn(int startX, int endX, int playerY, Game game) {
|
||||
var map = new HashMap<Integer, Integer>();
|
||||
var world = game.getWorld();
|
||||
@ -89,29 +74,6 @@ public class ZombieLogic
|
||||
return count / 2; // Each zombie has two parts
|
||||
}
|
||||
|
||||
public Zombie.ZombieState setHurtAnimation(boolean hurt, Enum current) {
|
||||
if (hurt) {
|
||||
return switch (current) {
|
||||
case TOP, TOP_HURT -> TOP_HURT;
|
||||
case BOTTOM, BOTTOM_HURT -> BOTTOM_HURT;
|
||||
default -> throw new IllegalStateException("Unexpected state: " + current);
|
||||
};
|
||||
}
|
||||
|
||||
return switch (current) {
|
||||
case TOP, TOP_HURT -> TOP;
|
||||
case BOTTOM, BOTTOM_HURT -> BOTTOM;
|
||||
default -> throw new IllegalStateException("Unexpected state: " + current);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void killed(Game game, Block mob) {
|
||||
int rottenFlesh = random.nextInt(3) + 1;
|
||||
//InventoryItem drop = new InventoryItem(rottenFlesh, ItemBlockSupplier.getItem("rotten_flesh"));
|
||||
//game.getInventory().addItem(drop);
|
||||
}
|
||||
|
||||
public static <K, V> Map.Entry<K, V> getRandomEntry(HashMap<K, V> map) {
|
||||
List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
|
||||
return list.get(new Random().nextInt(list.size()));
|
Reference in New Issue
Block a user