From 6f8e35a9f19658daaef8da4d8b605df1ff2189d4 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Sun, 2 Mar 2025 11:54:46 +0100 Subject: [PATCH] feat: Added cow --- .../java/cz/jzitnik/game/SpriteLoader.java | 9 +- .../items/registry/blocks/IronOreBlock.java | 16 ++ .../items/registry/items/CoalItem.java | 13 ++ .../items/registry/items/IronOreItem.java | 13 ++ .../entities/items/registry/mobs/Cow.java | 19 ++ .../game/mobs/services/cow/CowData.java | 12 + .../game/mobs/services/cow/CowLogic.java | 205 ++++++++++++++++++ .../java/cz/jzitnik/game/sprites/Cow.java | 29 +++ src/main/resources/textures/mobs/cow/left.ans | 25 +++ .../resources/textures/mobs/cow/lefthurt.ans | 25 +++ .../resources/textures/mobs/cow/right.ans | 25 +++ .../resources/textures/mobs/cow/righthurt.ans | 25 +++ 12 files changed, 409 insertions(+), 7 deletions(-) create mode 100644 src/main/java/cz/jzitnik/game/entities/items/registry/blocks/IronOreBlock.java create mode 100644 src/main/java/cz/jzitnik/game/entities/items/registry/items/CoalItem.java create mode 100644 src/main/java/cz/jzitnik/game/entities/items/registry/items/IronOreItem.java create mode 100644 src/main/java/cz/jzitnik/game/entities/items/registry/mobs/Cow.java create mode 100644 src/main/java/cz/jzitnik/game/mobs/services/cow/CowData.java create mode 100644 src/main/java/cz/jzitnik/game/mobs/services/cow/CowLogic.java create mode 100644 src/main/java/cz/jzitnik/game/sprites/Cow.java create mode 100644 src/main/resources/textures/mobs/cow/left.ans create mode 100644 src/main/resources/textures/mobs/cow/lefthurt.ans create mode 100644 src/main/resources/textures/mobs/cow/right.ans create mode 100644 src/main/resources/textures/mobs/cow/righthurt.ans diff --git a/src/main/java/cz/jzitnik/game/SpriteLoader.java b/src/main/java/cz/jzitnik/game/SpriteLoader.java index 15803f0..be9bf08 100644 --- a/src/main/java/cz/jzitnik/game/SpriteLoader.java +++ b/src/main/java/cz/jzitnik/game/SpriteLoader.java @@ -41,6 +41,7 @@ public class SpriteLoader { STEVE, PIG, SHEEP, + COW, // UI BREAKING, @@ -147,6 +148,7 @@ public class SpriteLoader { SPRITES_MAP.put(SPRITES.STEVE, new Steve()); SPRITES_MAP.put(SPRITES.PIG, new Pig()); SPRITES_MAP.put(SPRITES.SHEEP, new Sheep()); + SPRITES_MAP.put(SPRITES.COW, new Cow()); // UI SPRITES_MAP.put(SPRITES.BREAKING, new Breaking()); @@ -215,13 +217,6 @@ public class SpriteLoader { SPRITES_MAP.put(SPRITES.ITEM_COOKED_PORKCHOP, new SimpleSprite("items/cooked_porkchop.ans")); SPRITES_MAP.put(SPRITES.ITEM_MUTTON, new SimpleSprite("items/mutton.ans")); SPRITES_MAP.put(SPRITES.ITEM_COOKED_MUTTON, new SimpleSprite("items/cooked_mutton.ans")); - - - - - - - } public static SpriteList load() { diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/IronOreBlock.java b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/IronOreBlock.java new file mode 100644 index 0000000..21cc506 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/IronOreBlock.java @@ -0,0 +1,16 @@ +package cz.jzitnik.game.entities.items.registry.blocks; + +import cz.jzitnik.game.SpriteLoader; +import cz.jzitnik.game.annotations.BlockRegistry; +import cz.jzitnik.game.entities.Block; +import cz.jzitnik.game.entities.items.ItemType; +import cz.jzitnik.game.entities.items.ToolVariant; + +import java.util.Arrays; + +@BlockRegistry("iron_ore") +public class IronOreBlock extends Block { + public IronOreBlock() { + super("iron_ore", SpriteLoader.SPRITES.IRON_ORE, 15, ItemType.PICKAXE, Arrays.stream(ToolVariant.values()).toList()); + } +} diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/items/CoalItem.java b/src/main/java/cz/jzitnik/game/entities/items/registry/items/CoalItem.java new file mode 100644 index 0000000..68e11ab --- /dev/null +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/items/CoalItem.java @@ -0,0 +1,13 @@ +package cz.jzitnik.game.entities.items.registry.items; + +import cz.jzitnik.game.SpriteLoader; +import cz.jzitnik.game.annotations.ItemRegistry; +import cz.jzitnik.game.entities.items.Item; +import cz.jzitnik.game.entities.items.ItemType; + +@ItemRegistry("coal") +public class CoalItem extends Item { + public CoalItem() { + super("coal", "Coal", ItemType.USELESS_ITEM, SpriteLoader.SPRITES.ITEM_COAL_ORE); + } +} diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/items/IronOreItem.java b/src/main/java/cz/jzitnik/game/entities/items/registry/items/IronOreItem.java new file mode 100644 index 0000000..ff3bed3 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/items/IronOreItem.java @@ -0,0 +1,13 @@ +package cz.jzitnik.game.entities.items.registry.items; + +import cz.jzitnik.game.SpriteLoader; +import cz.jzitnik.game.annotations.ItemRegistry; +import cz.jzitnik.game.entities.items.Item; +import cz.jzitnik.game.entities.items.ItemType; + +@ItemRegistry("iron_ore") +public class IronOreItem extends Item { + public IronOreItem() { + super("iron_ore", "Iron ore", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_IRON_ORE); + } +} diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/mobs/Cow.java b/src/main/java/cz/jzitnik/game/entities/items/registry/mobs/Cow.java new file mode 100644 index 0000000..32052bf --- /dev/null +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/mobs/Cow.java @@ -0,0 +1,19 @@ +package cz.jzitnik.game.entities.items.registry.mobs; + +import cz.jzitnik.game.SpriteLoader; +import cz.jzitnik.game.annotations.EntityRegistry; +import cz.jzitnik.game.entities.Block; +import cz.jzitnik.game.mobs.services.cow.CowData; + +@EntityRegistry("cow") +public class Cow extends Block { + public Cow() { + super("cow", SpriteLoader.SPRITES.COW); + setMob(true); + setGhost(true); + setSpriteState(cz.jzitnik.game.sprites.Cow.CowState.RIGHT); + setMineable(false); + setData(new CowData()); + setHp(10); + } +} diff --git a/src/main/java/cz/jzitnik/game/mobs/services/cow/CowData.java b/src/main/java/cz/jzitnik/game/mobs/services/cow/CowData.java new file mode 100644 index 0000000..37db14f --- /dev/null +++ b/src/main/java/cz/jzitnik/game/mobs/services/cow/CowData.java @@ -0,0 +1,12 @@ +package cz.jzitnik.game.mobs.services.cow; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CowData { + private int lastDirection = 1; // 1 = right, -1 = left + private int movementCooldown = 0; + private int jumpAttempts = 0; +} diff --git a/src/main/java/cz/jzitnik/game/mobs/services/cow/CowLogic.java b/src/main/java/cz/jzitnik/game/mobs/services/cow/CowLogic.java new file mode 100644 index 0000000..273ede5 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/mobs/services/cow/CowLogic.java @@ -0,0 +1,205 @@ +package cz.jzitnik.game.mobs.services.cow; + +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.sprites.Cow; +import cz.jzitnik.tui.ScreenMovingCalculationProvider; +import org.jline.terminal.Terminal; + +import java.util.*; + +import static cz.jzitnik.game.sprites.Cow.CowState.*; + +@EntitySpawn +@EntityLogic("cow") +@EntityHurtAnimationHandler("cow") +@EntityKillHandler("cow") +public class CowLogic implements EntityLogicInterface, EntitySpawnInterface, EntityHurtAnimationChanger, EntityKillInterface { + private final Random random = new Random(); + + @Override + public void nextIteration(EntityLogicProvider.EntityLogicMobDTO entityLogicMobDTO) { + int cowX = entityLogicMobDTO.getX(); + int cowY = entityLogicMobDTO.getY(); + var game = entityLogicMobDTO.getGame(); + var cow = entityLogicMobDTO.getMob(); + var world = game.getWorld(); + var cowData = (CowData) cow.getData(); + + boolean updated = false; + int newCowX = cowX; + int newCowY = cowY; + + if (cowData.getMovementCooldown() > 0) { + cowData.setMovementCooldown(cowData.getMovementCooldown() - 1); + return; + } + + int direction = cowData.getLastDirection(); + if (random.nextInt(10) < 1) { // 10% chance to change direction + direction = -direction; + } + cowData.setLastDirection(direction); + + if (direction == 1) { + if (cow.getSpriteState().get() == RIGHT_HURT || cow.getSpriteState().get() == LEFT_HURT) { + cow.setSpriteState(RIGHT_HURT); + } else { + cow.setSpriteState(RIGHT); + } + } else { + if (cow.getSpriteState().get() == RIGHT_HURT || cow.getSpriteState().get() == LEFT_HURT) { + cow.setSpriteState(LEFT_HURT); + } else { + cow.setSpriteState(LEFT); + } + } + + List blocksAhead = world[cowY][cowX + direction]; + if (!game.isSolid(blocksAhead)) { + world[cowY][cowX].remove(cow); + world[cowY][cowX + direction].add(cow); + newCowX = cowX + direction; + updated = true; + cowData.setJumpAttempts(0); + } else { + List blocksAboveAhead = world[cowY - 1][cowX + direction]; + List blocksTwoAboveAhead = world[cowY - 2][cowX + direction]; + + if (!game.isSolid(blocksAboveAhead) && game.isSolid(blocksAhead) && !game.isSolid(blocksTwoAboveAhead)) { + if (cowData.getJumpAttempts() < 2) { + world[cowY][cowX].remove(cow); + world[cowY - 1][cowX + direction].add(cow); + newCowX = cowX + direction; + newCowY = cowY - 1; + updated = true; + cowData.setJumpAttempts(cowData.getJumpAttempts() + 1); + } + } + } + + while (updated) { + if (!game.isSolid(world[newCowY + 1][newCowX])) { + if (newCowY - cowY < 3) { + world[newCowY][newCowX].remove(cow); + world[newCowY + 1][newCowX].add(cow); + newCowY++; + } else { + updated = false; + } + } else { + updated = false; + } + } + + cowData.setMovementCooldown(random.nextInt(3) + 1); // 1-3 iterations cooldown + } + + @Override + public void spawn(int playerX, int playerY, Game game, Terminal terminal) { + // Cordinates where player can see + int[] data = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), game.getWorld()[0].length, game.getWorld().length); + var world = game.getWorld(); + int startX = data[0]; + int endX = data[1]; + + // Left side + int lstartX = startX - 20; + int lendX = startX - 5; + int lstartY = playerY - 15; + int lendY = playerY + 15; + + if (countCows(lstartX, lendX, lstartY, lendY, game) < 3 && random.nextInt(100) < 100) { + var spawnLocations = cowCanSpawn(lstartX, lendX, playerY, game); + if (!spawnLocations.isEmpty()) { + for (int i = 0; i < Math.min(4, spawnLocations.size()); i++) { + var randomLocation = getRandomEntry(spawnLocations); + int x = randomLocation.getKey(); + int y = randomLocation.getValue(); + + world[y][x].add(ItemBlockSupplier.getEntity("cow")); + } + } + } + + // Right side + int rstartX = endX + 5; + int rendX = endX + 20; + int rstartY = playerY - 15; + int rendY = playerY + 15; + + if (countCows(rstartX, rendX, rstartY, rendY, game) < 3 && random.nextInt(100) < 2) { + var spawnLocations = cowCanSpawn(rstartX, rendX, playerY, game); + if (!spawnLocations.isEmpty()) { + for (int i = 0; i < Math.min(random.nextInt(3) + 2, spawnLocations.size()); i++) { + var randomLocation = getRandomEntry(spawnLocations); + int x = randomLocation.getKey(); + int y = randomLocation.getValue(); + + world[y][x].add(ItemBlockSupplier.getEntity("cow")); + } + } + } + } + + public static Map.Entry getRandomEntry(HashMap map) { + List> entryList = new ArrayList<>(map.entrySet()); + Random random = new Random(); + return entryList.get(random.nextInt(entryList.size())); + } + + private HashMap cowCanSpawn(int startX, int endX, int playerY, Game game) { + var map = new HashMap(); + var world = game.getWorld(); + for (int x = startX; x <= endX; x++) { + for (int y = Math.max(0, playerY - 30); y < Math.min(world.length, playerY + 30); y++) { + if (world[y][x].stream().anyMatch(i -> i.getBlockId().equals("grass"))) { + map.put(x, y - 1); + } + } + } + + return map; + } + + private long countCows(int startX, int endX, int startY, int endY, Game game) { + long cowAmount = 0; + for (int y = startY; y <= endY; y++) { + for (int x = startX; x <= endX; x++) { + cowAmount += game.getWorld()[y][x].stream().filter(i -> i.getBlockId().equals("cow")).count(); + } + } + + return cowAmount; + } + + public Cow.CowState setHurtAnimation(boolean hurt, Enum current) { + if (hurt) { + return switch (current) { + case LEFT_HURT,LEFT -> LEFT_HURT; + case RIGHT_HURT,RIGHT -> RIGHT_HURT; + default -> throw new IllegalStateException("Unexpected value: " + current); + }; + } + + return switch (current) { + case LEFT_HURT,LEFT -> LEFT; + case RIGHT_HURT,RIGHT -> RIGHT; + default -> throw new IllegalStateException("Unexpected value: " + current); + }; + } + + @Override + public void killed(Game game, Block mob) { + /*int amount = random.nextInt(2) + 1; + InventoryItem inventoryItem = new InventoryItem(amount, ItemBlockSupplier.getItem("mutton")); + game.getInventory().addItem(inventoryItem);*/ + } +} diff --git a/src/main/java/cz/jzitnik/game/sprites/Cow.java b/src/main/java/cz/jzitnik/game/sprites/Cow.java new file mode 100644 index 0000000..8a8b9cb --- /dev/null +++ b/src/main/java/cz/jzitnik/game/sprites/Cow.java @@ -0,0 +1,29 @@ +package cz.jzitnik.game.sprites; + +import cz.jzitnik.tui.ResourceLoader; +import cz.jzitnik.tui.Sprite; + +public class Cow extends Sprite { + public enum CowState{ + LEFT, + RIGHT, + LEFT_HURT, + RIGHT_HURT + } + + public String getSprite() { + return getSprite(CowState.RIGHT); + } + + public String getSprite(Enum e) { + return ResourceLoader.loadResource( + switch (e) { + case CowState.LEFT -> "mobs/cow/left.ans"; + case CowState.RIGHT -> "mobs/cow/right.ans"; + case CowState.LEFT_HURT -> "mobs/cow/lefthurt.ans"; + case CowState.RIGHT_HURT -> "mobs/cow/righthurt.ans"; + default -> throw new IllegalStateException("Unexpected value: " + e); + } + ); + } +} diff --git a/src/main/resources/textures/mobs/cow/left.ans b/src/main/resources/textures/mobs/cow/left.ans new file mode 100644 index 0000000..107fc42 --- /dev/null +++ b/src/main/resources/textures/mobs/cow/left.ans @@ -0,0 +1,25 @@ +                                                 +                                              +                                              +                  +                    +                    +                       +                      +                         +                               +                         +                              +                            +                                          +                                           +                                       +                                           +                                         +                                           +                                         +                                           +                                           +                                          +                                       +                                     diff --git a/src/main/resources/textures/mobs/cow/lefthurt.ans b/src/main/resources/textures/mobs/cow/lefthurt.ans new file mode 100644 index 0000000..ac1263f --- /dev/null +++ b/src/main/resources/textures/mobs/cow/lefthurt.ans @@ -0,0 +1,25 @@ +                                                 +                                             +                                              +                      +                     +                      +                +                  +                         +                             +                         +                             +                          +                                         +                                           +                                        +                                          +                                        +                                           +                                           +                                         +                                         +                                          +                                       +                                     diff --git a/src/main/resources/textures/mobs/cow/right.ans b/src/main/resources/textures/mobs/cow/right.ans new file mode 100644 index 0000000..e68a859 --- /dev/null +++ b/src/main/resources/textures/mobs/cow/right.ans @@ -0,0 +1,25 @@ +                                                 +                                              +                                              +               +                    +                     +            +                +                       +                                +                         +                           +                          +                                         +                                           +                                        +                                          +                                         +                                           +                                        +                                         +                                        +                                         +                                       +                                     diff --git a/src/main/resources/textures/mobs/cow/righthurt.ans b/src/main/resources/textures/mobs/cow/righthurt.ans new file mode 100644 index 0000000..01364c1 --- /dev/null +++ b/src/main/resources/textures/mobs/cow/righthurt.ans @@ -0,0 +1,25 @@ +                                                 +                                              +                                              +                   +                     +                        +                      +                  +                          +                               +                             +                           +                             +                                         +                                           +                                           +                                          +                                        +                                           +                                          +                                          +                                       +                                          +                                       +