feat: Killing mob

This commit is contained in:
2026-01-01 14:47:31 +01:00
parent ba26b633af
commit 59803e46f5
4 changed files with 111 additions and 4 deletions

View File

@@ -1,15 +1,54 @@
package cz.jzitnik.game.mobs;
import com.googlecode.lanterna.TerminalPosition;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.FullRoomDraw;
import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.utils.RoomCords;
import cz.jzitnik.states.ScreenBuffer;
import cz.jzitnik.states.TerminalState;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.RerenderUtils;
import cz.jzitnik.utils.events.EventManager;
import cz.jzitnik.utils.roomtasks.RoomTask;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import java.awt.image.BufferedImage;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@Slf4j
public abstract class HittableMob extends Mob {
public abstract void onKilled();
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
protected int health;
private ScheduledFuture<?> currentTimeoutHitAnimation = null;
@Getter
private boolean hitAnimationOn = false;
@InjectDependency
private EventManager eventManager;
@InjectState
private GameState gameState;
@InjectDependency
private ResourceManager resourceManager;
@InjectState
private TerminalState terminalState;
@InjectState
private ScreenBuffer screenBuffer;
@InjectConfig
private Debugging debugging;
public HittableMob(BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth) {
super(texture, task, cords);
@@ -18,16 +57,71 @@ public abstract class HittableMob extends Mob {
@Override
public void interact(DependencyManager dm) {
dm.inject(this);
// TODO: Swords in hand will deal more damage, for now deal always one
health--;
log.debug("Health: {}", health);
if (health <= 0) {
onKilled();
gameState.getCurrentRoom().getMobs().remove(this);
rerender();
return;
}
// play animation
if (hitAnimationOn) {
if (currentTimeoutHitAnimation != null && !currentTimeoutHitAnimation.isDone()) {
currentTimeoutHitAnimation.cancel(false);
}
} else {
hitAnimationOn = true;
log.debug("Hitting start");
rerender();
}
currentTimeoutHitAnimation = scheduler.schedule(() -> {
hitAnimationOn = false;
log.debug("Hitting end");
rerender();
}, 250, TimeUnit.MILLISECONDS);
}
private void rerender() {
int forStartX = cords.getX();
int forStartY = cords.getY();
int forEndX = cords.getX() + texture.getWidth() - 1;
int forEndY = cords.getY() + texture.getHeight();
GameRoom currentRoom = gameState.getCurrentRoom();
BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
Player player = gameState.getPlayer();
BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
var start = RerenderUtils.getStart(room, terminalState.getTerminalScreen().getTerminalSize());
int startX = start.getX();
int startY = start.getY();
RerenderUtils.rerenderPart(
forStartX,
forEndX,
forStartY,
forEndY,
startX,
startY,
currentRoom,
room,
player,
playerTexture,
screenBuffer,
resourceManager,
debugging
);
eventManager.emitEvent(new RerenderScreen(new RerenderScreen.ScreenPart(
new TerminalPosition(forStartX, forStartY),
new TerminalPosition(forEndX * 2 + 1 + startX, forEndY + startY)
)));
}
}

View File

@@ -13,9 +13,9 @@ import java.awt.image.BufferedImage;
@Getter
@RequiredArgsConstructor
public abstract class Mob implements Renderable, Selectable {
private final BufferedImage texture;
protected final BufferedImage texture;
private final RoomTask task;
private final RoomCords cords;
protected final RoomCords cords;
@Setter
private boolean selected = false;

View File

@@ -3,10 +3,17 @@ package cz.jzitnik.game.setup.mobs;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.mobs.HittableMob;
import cz.jzitnik.game.utils.RoomCords;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Zombie extends HittableMob {
public Zombie(ResourceManager resourceManager, RoomCords cords) {
super(resourceManager.getResource(ResourceManager.Resource.CHEST), null, cords, 10);
}
@Override
public void onKilled() {
log.debug("Zombie killed");
}
}

View File

@@ -7,6 +7,7 @@ import cz.jzitnik.events.handlers.FullRoomDrawHandler;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.mobs.HittableMob;
import cz.jzitnik.game.mobs.Mob;
import cz.jzitnik.game.objects.GameObject;
import cz.jzitnik.game.utils.RoomCords;
@@ -21,6 +22,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Slf4j
public class RerenderUtils {
public static RoomCords getStart(BufferedImage room, TerminalSize terminalSize) {
int width = room.getWidth();
@@ -96,9 +98,13 @@ public class RerenderUtils {
int g = (pixel >> 8) & 0xff;
int b = pixel & 0xff;
float factor = 1.5f; // brightness multiplier
float redFactor = 2f;
if (alpha != 0) {
if (isSelected) {
if (object instanceof HittableMob mob && mob.isHitAnimationOn()) {
r = Math.min(255, (int)(r * redFactor));
pixel = (alpha << 24) | (r << 16) | (g << 8) | b;
} else if (isSelected) {
r = Math.min(255, (int)(r * factor));
g = Math.min(255, (int)(g * factor));
b = Math.min(255, (int)(b * factor));