feat: Mobs following player logic
This commit is contained in:
@@ -6,6 +6,6 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
@Config
|
@Config
|
||||||
public class Debugging {
|
public class Debugging {
|
||||||
private final boolean renderColliders = false;
|
private final boolean renderColliders = true;
|
||||||
private final boolean renderPlayerCollider = false;
|
private final boolean renderPlayerCollider = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,31 +28,28 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@EventHandler(FullRoomDraw.class)
|
@EventHandler(FullRoomDraw.class)
|
||||||
public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
||||||
|
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||||
@InjectState
|
@InjectState
|
||||||
private GameState gameState;
|
private GameState gameState;
|
||||||
|
|
||||||
@InjectState
|
@InjectState
|
||||||
private ScreenBuffer screenBuffer;
|
private ScreenBuffer screenBuffer;
|
||||||
|
|
||||||
@InjectDependency
|
@InjectDependency
|
||||||
private ResourceManager resourceManager;
|
private ResourceManager resourceManager;
|
||||||
|
|
||||||
@InjectState
|
@InjectState
|
||||||
private TerminalState terminalState;
|
private TerminalState terminalState;
|
||||||
|
|
||||||
@InjectDependency
|
@InjectDependency
|
||||||
private EventManager eventManager;
|
private EventManager eventManager;
|
||||||
|
|
||||||
@InjectState
|
@InjectState
|
||||||
private RenderState renderState;
|
private RenderState renderState;
|
||||||
|
|
||||||
@InjectConfig
|
@InjectConfig
|
||||||
private Debugging debugging;
|
private Debugging debugging;
|
||||||
|
|
||||||
@InjectDependency
|
@InjectDependency
|
||||||
private RoomTaskScheduler roomTaskScheduler;
|
private RoomTaskScheduler roomTaskScheduler;
|
||||||
|
|
||||||
@@ -90,7 +87,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
|||||||
if (renderState.isFirstRender() || event.isFullRerender()) {
|
if (renderState.isFirstRender() || event.isFullRerender()) {
|
||||||
eventManager.emitEvent(RerenderScreen.full(terminalSize));
|
eventManager.emitEvent(RerenderScreen.full(terminalSize));
|
||||||
renderState.setFirstRender(false);
|
renderState.setFirstRender(false);
|
||||||
|
scheduler.schedule(() -> {
|
||||||
roomTaskScheduler.setupNewSchedulers(currentRoom);
|
roomTaskScheduler.setupNewSchedulers(currentRoom);
|
||||||
|
}, 200, TimeUnit.MILLISECONDS);
|
||||||
} else {
|
} else {
|
||||||
eventManager.emitEvent(new RerenderScreen(partsToRerender.toArray(RerenderScreen.ScreenPart[]::new)));
|
eventManager.emitEvent(new RerenderScreen(partsToRerender.toArray(RerenderScreen.ScreenPart[]::new)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,22 +14,25 @@ import cz.jzitnik.utils.events.EventManager;
|
|||||||
import cz.jzitnik.utils.roomtasks.RoomTaskScheduler;
|
import cz.jzitnik.utils.roomtasks.RoomTaskScheduler;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@EventHandler(RoomChangeEvent.class)
|
@EventHandler(RoomChangeEvent.class)
|
||||||
public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent> {
|
public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent> {
|
||||||
|
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||||
|
@InjectState
|
||||||
|
private GameState gameState;
|
||||||
|
@InjectDependency
|
||||||
|
private EventManager eventManager;
|
||||||
|
@InjectDependency
|
||||||
|
private RoomTaskScheduler roomTaskScheduler;
|
||||||
|
|
||||||
public RoomChangeEventHandler(DependencyManager dm) {
|
public RoomChangeEventHandler(DependencyManager dm) {
|
||||||
super(dm);
|
super(dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectState
|
|
||||||
private GameState gameState;
|
|
||||||
|
|
||||||
@InjectDependency
|
|
||||||
private EventManager eventManager;
|
|
||||||
|
|
||||||
@InjectDependency
|
|
||||||
private RoomTaskScheduler roomTaskScheduler;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(RoomChangeEvent event) {
|
public void handle(RoomChangeEvent event) {
|
||||||
RoomCords playerCords = gameState.getPlayer().getPlayerCords();
|
RoomCords playerCords = gameState.getPlayer().getPlayerCords();
|
||||||
@@ -53,7 +56,9 @@ public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
gameState.setCurrentRoom(newRoom);
|
gameState.setCurrentRoom(newRoom);
|
||||||
|
scheduler.schedule(() -> {
|
||||||
roomTaskScheduler.setupNewSchedulers(newRoom);
|
roomTaskScheduler.setupNewSchedulers(newRoom);
|
||||||
|
}, 200, TimeUnit.MILLISECONDS);
|
||||||
eventManager.emitEvent(new FullRoomDraw());
|
eventManager.emitEvent(new FullRoomDraw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import cz.jzitnik.utils.DependencyManager;
|
|||||||
import cz.jzitnik.utils.RerenderUtils;
|
import cz.jzitnik.utils.RerenderUtils;
|
||||||
import cz.jzitnik.utils.events.EventManager;
|
import cz.jzitnik.utils.events.EventManager;
|
||||||
import cz.jzitnik.utils.roomtasks.RoomTask;
|
import cz.jzitnik.utils.roomtasks.RoomTask;
|
||||||
|
import cz.jzitnik.utils.roomtasks.RoomTaskScheduler;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@@ -49,6 +50,8 @@ public abstract class HittableMob extends Mob {
|
|||||||
private ScreenBuffer screenBuffer;
|
private ScreenBuffer screenBuffer;
|
||||||
@InjectConfig
|
@InjectConfig
|
||||||
private Debugging debugging;
|
private Debugging debugging;
|
||||||
|
@InjectDependency
|
||||||
|
private RoomTaskScheduler roomTaskScheduler;
|
||||||
|
|
||||||
public HittableMob(BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth) {
|
public HittableMob(BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth) {
|
||||||
super(texture, task, cords);
|
super(texture, task, cords);
|
||||||
@@ -66,6 +69,9 @@ public abstract class HittableMob extends Mob {
|
|||||||
|
|
||||||
if (health <= 0) {
|
if (health <= 0) {
|
||||||
onKilled();
|
onKilled();
|
||||||
|
if (task != null) {
|
||||||
|
roomTaskScheduler.stopTask(task);
|
||||||
|
}
|
||||||
gameState.getCurrentRoom().getMobs().remove(this);
|
gameState.getCurrentRoom().getMobs().remove(this);
|
||||||
rerender();
|
rerender();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,18 +5,24 @@ import cz.jzitnik.game.utils.RoomCords;
|
|||||||
import cz.jzitnik.game.utils.Selectable;
|
import cz.jzitnik.game.utils.Selectable;
|
||||||
import cz.jzitnik.utils.roomtasks.RoomTask;
|
import cz.jzitnik.utils.roomtasks.RoomTask;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
|
||||||
public abstract class Mob implements Renderable, Selectable {
|
public abstract class Mob implements Renderable, Selectable {
|
||||||
protected final BufferedImage texture;
|
protected final BufferedImage texture;
|
||||||
private final RoomTask task;
|
|
||||||
|
@Setter
|
||||||
|
protected RoomTask task;
|
||||||
protected final RoomCords cords;
|
protected final RoomCords cords;
|
||||||
|
|
||||||
|
public Mob(BufferedImage texture, RoomTask task, RoomCords cords) {
|
||||||
|
this.texture = texture;
|
||||||
|
this.task = task;
|
||||||
|
this.cords = cords;
|
||||||
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private boolean selected = false;
|
private boolean selected = false;
|
||||||
}
|
}
|
||||||
|
|||||||
133
src/main/java/cz/jzitnik/game/mobs/tasks/AStarAlg.java
Normal file
133
src/main/java/cz/jzitnik/game/mobs/tasks/AStarAlg.java
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package cz.jzitnik.game.mobs.tasks;
|
||||||
|
|
||||||
|
import cz.jzitnik.game.GameRoomPart;
|
||||||
|
import cz.jzitnik.game.utils.RoomCords;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AStarAlg {
|
||||||
|
|
||||||
|
// Boundaries matching your Player switch statement
|
||||||
|
// Player: if (x <= 30) return -> means 30 is the edge, valid area is > 30?
|
||||||
|
// User Update: "he can be on 30". So valid range is [30, 155]
|
||||||
|
private static final int MIN_X = 30;
|
||||||
|
private static final int MAX_X = 155;
|
||||||
|
private static final int MIN_Y = 10;
|
||||||
|
private static final int MAX_Y = 113;
|
||||||
|
|
||||||
|
public static List<RoomCords> findPath(RoomCords start, RoomCords target, List<GameRoomPart> colliders) {
|
||||||
|
PriorityQueue<Node> openSet = new PriorityQueue<>(Comparator.comparingInt(n -> n.f));
|
||||||
|
Set<String> closedSet = new HashSet<>();
|
||||||
|
|
||||||
|
// We use Chebyshev distance for the heuristic (best for 8-way movement)
|
||||||
|
Node startNode = new Node(start.getX(), start.getY(), 0, getHeuristic(start, target), null);
|
||||||
|
openSet.add(startNode);
|
||||||
|
|
||||||
|
while (!openSet.isEmpty()) {
|
||||||
|
Node current = openSet.poll();
|
||||||
|
|
||||||
|
// Reached target?
|
||||||
|
if (current.x == target.getX() && current.y == target.getY()) {
|
||||||
|
return reconstructPath(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = current.x + "," + current.y;
|
||||||
|
if (closedSet.contains(key)) continue;
|
||||||
|
closedSet.add(key);
|
||||||
|
|
||||||
|
for (Node neighbor : getNeighbors(current, target)) {
|
||||||
|
String neighborKey = neighbor.x + "," + neighbor.y;
|
||||||
|
if (closedSet.contains(neighborKey)) continue;
|
||||||
|
|
||||||
|
// Check collisions and boundaries
|
||||||
|
if (!isValidPosition(neighbor.x, neighbor.y, colliders)) {
|
||||||
|
// EDGE CASE FIX:
|
||||||
|
// If the Player (target) is standing exactly on a wall/edge that the Mob considers invalid,
|
||||||
|
// A* will usually fail.
|
||||||
|
// We add a check: if this neighbor IS the target, we allow it.
|
||||||
|
// This lets the mob walk right up to the player's face even if they are hugging the wall.
|
||||||
|
if (neighbor.x != target.getX() || neighbor.y != target.getY()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int newG = current.g + 1;
|
||||||
|
neighbor.g = newG;
|
||||||
|
neighbor.f = newG + neighbor.h;
|
||||||
|
neighbor.parent = current;
|
||||||
|
|
||||||
|
openSet.add(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Node> getNeighbors(Node current, RoomCords target) {
|
||||||
|
List<Node> neighbors = new ArrayList<>();
|
||||||
|
|
||||||
|
// Added Diagonal Directions
|
||||||
|
int[][] directions = {
|
||||||
|
{0, 1}, {0, -1}, {1, 0}, {-1, 0}, // Up, Down, Right, Left
|
||||||
|
{1, 1}, {1, -1}, {-1, 1}, {-1, -1} // Diagonals
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int[] dir : directions) {
|
||||||
|
int newX = current.x + dir[0];
|
||||||
|
int newY = current.y + dir[1];
|
||||||
|
int h = getHeuristic(new RoomCords(newX, newY), target);
|
||||||
|
neighbors.add(new Node(newX, newY, 0, h, null));
|
||||||
|
}
|
||||||
|
return neighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isValidPosition(int x, int y, List<GameRoomPart> colliders) {
|
||||||
|
// Updated checks to be inclusive so 30 is valid.
|
||||||
|
// Valid X: 30 to 155
|
||||||
|
if (x < MIN_X || x > MAX_X) return false;
|
||||||
|
|
||||||
|
// Valid Y: 10 to 110
|
||||||
|
if (y < MIN_Y || y > MAX_Y) return false;
|
||||||
|
|
||||||
|
// Check Colliders
|
||||||
|
RoomCords temp = new RoomCords(x, y);
|
||||||
|
for (GameRoomPart part : colliders) {
|
||||||
|
if (part.isWithin(temp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<RoomCords> reconstructPath(Node endNode) {
|
||||||
|
List<RoomCords> path = new ArrayList<>();
|
||||||
|
Node current = endNode;
|
||||||
|
while (current != null) {
|
||||||
|
path.add(new RoomCords(current.x, current.y));
|
||||||
|
current = current.parent;
|
||||||
|
}
|
||||||
|
Collections.reverse(path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changed to Chebyshev Distance for better diagonal estimation
|
||||||
|
private static int getHeuristic(RoomCords a, RoomCords b) {
|
||||||
|
int dx = Math.abs(a.getX() - b.getX());
|
||||||
|
int dy = Math.abs(a.getY() - b.getY());
|
||||||
|
return Math.max(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Node {
|
||||||
|
int x, y;
|
||||||
|
int g, h, f;
|
||||||
|
Node parent;
|
||||||
|
|
||||||
|
public Node(int x, int y, int g, int h, Node parent) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.g = g;
|
||||||
|
this.h = h;
|
||||||
|
this.f = g + h;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package cz.jzitnik.game.mobs.tasks;
|
||||||
|
|
||||||
|
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.game.GameState;
|
||||||
|
import cz.jzitnik.game.ResourceManager;
|
||||||
|
import cz.jzitnik.game.mobs.Mob;
|
||||||
|
import cz.jzitnik.game.utils.RoomCords;
|
||||||
|
import cz.jzitnik.states.ScreenBuffer;
|
||||||
|
import cz.jzitnik.states.SoundState;
|
||||||
|
import cz.jzitnik.states.TerminalState;
|
||||||
|
import cz.jzitnik.utils.events.EventManager;
|
||||||
|
import cz.jzitnik.utils.roomtasks.RoomTask;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class BlindMobFollowingPlayerTask extends RoomTask {
|
||||||
|
public BlindMobFollowingPlayerTask(Mob mob, int speed, int updateRate) {
|
||||||
|
super(new Task(mob, speed), updateRate, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
private static class Task implements Runnable {
|
||||||
|
private final Mob mob;
|
||||||
|
private final int speed;
|
||||||
|
private RoomCords playerCords;
|
||||||
|
@InjectState
|
||||||
|
private GameState gameState;
|
||||||
|
|
||||||
|
@InjectDependency
|
||||||
|
private EventManager eventManager;
|
||||||
|
|
||||||
|
@InjectDependency
|
||||||
|
private ResourceManager resourceManager;
|
||||||
|
|
||||||
|
@InjectState
|
||||||
|
private TerminalState terminalState;
|
||||||
|
|
||||||
|
@InjectState
|
||||||
|
private ScreenBuffer screenBuffer;
|
||||||
|
|
||||||
|
@InjectConfig
|
||||||
|
private Debugging debugging;
|
||||||
|
|
||||||
|
@InjectState
|
||||||
|
private SoundState soundState;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (playerCords == null || (soundState.isMicrophoneSetup() && soundState.getSoundVolume() > 2f)) {
|
||||||
|
playerCords = gameState.getPlayer().getPlayerCords().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
MobFollowingPlayerTask.Task.moveMob(playerCords, mob, gameState, speed, resourceManager, terminalState, screenBuffer, debugging, eventManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package cz.jzitnik.game.mobs.tasks;
|
||||||
|
|
||||||
|
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.RerenderScreen;
|
||||||
|
import cz.jzitnik.game.GameRoomPart;
|
||||||
|
import cz.jzitnik.game.GameState;
|
||||||
|
import cz.jzitnik.game.Player;
|
||||||
|
import cz.jzitnik.game.ResourceManager;
|
||||||
|
import cz.jzitnik.game.mobs.Mob;
|
||||||
|
import cz.jzitnik.game.utils.RoomCords;
|
||||||
|
import cz.jzitnik.states.ScreenBuffer;
|
||||||
|
import cz.jzitnik.states.TerminalState;
|
||||||
|
import cz.jzitnik.utils.RerenderUtils;
|
||||||
|
import cz.jzitnik.utils.events.EventManager;
|
||||||
|
import cz.jzitnik.utils.roomtasks.RoomTask;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class MobFollowingPlayerTask extends RoomTask {
|
||||||
|
public MobFollowingPlayerTask(Mob mob, int speed, int updateRate) {
|
||||||
|
super(new Task(mob, speed), updateRate, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
static class Task implements Runnable {
|
||||||
|
private final Mob mob;
|
||||||
|
private final int speed;
|
||||||
|
|
||||||
|
@InjectState
|
||||||
|
private GameState gameState;
|
||||||
|
|
||||||
|
@InjectDependency
|
||||||
|
private EventManager eventManager;
|
||||||
|
|
||||||
|
@InjectDependency
|
||||||
|
private ResourceManager resourceManager;
|
||||||
|
|
||||||
|
@InjectState
|
||||||
|
private TerminalState terminalState;
|
||||||
|
|
||||||
|
@InjectState
|
||||||
|
private ScreenBuffer screenBuffer;
|
||||||
|
|
||||||
|
@InjectConfig
|
||||||
|
private Debugging debugging;
|
||||||
|
|
||||||
|
protected static void moveMob(RoomCords playerCords, Mob mob, GameState gameState, int speed, ResourceManager resourceManager, TerminalState terminalState, ScreenBuffer screenBuffer, Debugging debugging, EventManager eventManager) {
|
||||||
|
RoomCords mobCords = mob.getCords();
|
||||||
|
List<GameRoomPart> solidParts = gameState.getCurrentRoom().getColliders();
|
||||||
|
List<RoomCords> path = AStarAlg.findPath(mobCords, playerCords, solidParts);
|
||||||
|
|
||||||
|
if (path.size() > 1) {
|
||||||
|
int targetIndex = Math.min(speed, path.size() - 1);
|
||||||
|
|
||||||
|
RoomCords newCords = path.get(targetIndex);
|
||||||
|
|
||||||
|
mob.getCords().updateCords(newCords.getX(), newCords.getY());
|
||||||
|
|
||||||
|
int forStartX = Math.min(mobCords.getX(), newCords.getX());
|
||||||
|
int forStartY = Math.min(mobCords.getY(), newCords.getY());
|
||||||
|
int forEndX = Math.max(mobCords.getX(), newCords.getX()) + mob.getTexture().getWidth() + 1;
|
||||||
|
int forEndY = Math.max(mobCords.getY(), newCords.getY()) + mob.getTexture().getHeight() + 1;
|
||||||
|
|
||||||
|
BufferedImage room = resourceManager.getResource(gameState.getCurrentRoom().getTexture());
|
||||||
|
var start = RerenderUtils.getStart(room, terminalState.getTerminalScreen().getTerminalSize());
|
||||||
|
int startX = start.getX();
|
||||||
|
int startY = start.getY();
|
||||||
|
|
||||||
|
Player player = gameState.getPlayer();
|
||||||
|
BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
|
||||||
|
|
||||||
|
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, gameState.getCurrentRoom(), room, player, playerTexture, screenBuffer, resourceManager, debugging);
|
||||||
|
|
||||||
|
eventManager.emitEvent(new RerenderScreen(
|
||||||
|
new RerenderScreen.ScreenPart(
|
||||||
|
new TerminalPosition(forStartX + startX, forStartY + startY),
|
||||||
|
new TerminalPosition(forEndX + 1 + startX, forEndY + startY)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
log.debug("Mob is effectively at the target or trapped.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
moveMob(gameState.getPlayer().getPlayerCords(), mob, gameState, speed, resourceManager, terminalState, screenBuffer, debugging, eventManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package cz.jzitnik.game.setup.mobs;
|
|||||||
|
|
||||||
import cz.jzitnik.game.ResourceManager;
|
import cz.jzitnik.game.ResourceManager;
|
||||||
import cz.jzitnik.game.mobs.HittableMob;
|
import cz.jzitnik.game.mobs.HittableMob;
|
||||||
|
import cz.jzitnik.game.mobs.tasks.MobFollowingPlayerTask;
|
||||||
import cz.jzitnik.game.utils.RoomCords;
|
import cz.jzitnik.game.utils.RoomCords;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@@ -9,7 +10,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
public class Zombie extends HittableMob {
|
public class Zombie extends HittableMob {
|
||||||
|
|
||||||
public Zombie(ResourceManager resourceManager, RoomCords cords) {
|
public Zombie(ResourceManager resourceManager, RoomCords cords) {
|
||||||
super(resourceManager.getResource(ResourceManager.Resource.CHEST), null, cords, 10);
|
super(resourceManager.getResource(ResourceManager.Resource.PLAYER_FRONT), null, cords, 10);
|
||||||
|
//setTask(new BlindMobFollowingPlayerTask(this, 1, 100));
|
||||||
|
setTask(new MobFollowingPlayerTask(this, 1, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@ToString
|
@ToString
|
||||||
@Getter
|
@Getter
|
||||||
public class RoomCords {
|
public class RoomCords implements Cloneable {
|
||||||
private int x;
|
private int x;
|
||||||
private int y;
|
private int y;
|
||||||
|
|
||||||
@@ -29,4 +29,13 @@ public class RoomCords {
|
|||||||
}
|
}
|
||||||
updateCords(x, y);
|
updateCords(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoomCords clone() {
|
||||||
|
try {
|
||||||
|
return (RoomCords) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ import lombok.Data;
|
|||||||
@State
|
@State
|
||||||
public class SoundState {
|
public class SoundState {
|
||||||
private double soundVolume;
|
private double soundVolume;
|
||||||
|
private boolean microphoneSetup = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class MicrophoneThread extends ShutdownableThread {
|
|||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
double volume = calculateRMS(buffer, bytesRead);
|
double volume = calculateRMS(buffer, bytesRead);
|
||||||
soundState.setSoundVolume(volume);
|
soundState.setSoundVolume(volume);
|
||||||
|
soundState.setMicrophoneSetup(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (LineUnavailableException e) {
|
} catch (LineUnavailableException e) {
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
package cz.jzitnik.utils.roomtasks;
|
package cz.jzitnik.utils.roomtasks;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public record RoomTask(Runnable task, long rate, TimeUnit rateUnit) {
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class RoomTask {
|
||||||
|
private final Runnable task;
|
||||||
|
private final long rate;
|
||||||
|
private final TimeUnit rateUnit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ package cz.jzitnik.utils.roomtasks;
|
|||||||
import cz.jzitnik.annotations.Dependency;
|
import cz.jzitnik.annotations.Dependency;
|
||||||
import cz.jzitnik.annotations.PostInit;
|
import cz.jzitnik.annotations.PostInit;
|
||||||
import cz.jzitnik.annotations.injectors.InjectConfig;
|
import cz.jzitnik.annotations.injectors.InjectConfig;
|
||||||
|
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||||
import cz.jzitnik.config.ThreadPoolConfig;
|
import cz.jzitnik.config.ThreadPoolConfig;
|
||||||
import cz.jzitnik.game.GameRoom;
|
import cz.jzitnik.game.GameRoom;
|
||||||
import cz.jzitnik.game.mobs.Mob;
|
import cz.jzitnik.game.mobs.Mob;
|
||||||
|
import cz.jzitnik.utils.DependencyManager;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -18,6 +22,10 @@ public class RoomTaskScheduler {
|
|||||||
ScheduledExecutorService scheduler;
|
ScheduledExecutorService scheduler;
|
||||||
@InjectConfig
|
@InjectConfig
|
||||||
private ThreadPoolConfig threadPoolConfig;
|
private ThreadPoolConfig threadPoolConfig;
|
||||||
|
@InjectDependency
|
||||||
|
private DependencyManager dependencyManager;
|
||||||
|
|
||||||
|
private HashMap<RoomTask, ScheduledFuture<?>> tasks = new HashMap<>();
|
||||||
|
|
||||||
private boolean firstRun = true;
|
private boolean firstRun = true;
|
||||||
|
|
||||||
@@ -46,6 +54,16 @@ public class RoomTaskScheduler {
|
|||||||
shutdownAll();
|
shutdownAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stopTask(RoomTask task) {
|
||||||
|
if (!tasks.containsKey(task)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledFuture<?> future = tasks.get(task);
|
||||||
|
future.cancel(true);
|
||||||
|
tasks.remove(task);
|
||||||
|
}
|
||||||
|
|
||||||
public void setupNewSchedulers(GameRoom currentRoom) {
|
public void setupNewSchedulers(GameRoom currentRoom) {
|
||||||
if (!firstRun) {
|
if (!firstRun) {
|
||||||
shutdownAll();
|
shutdownAll();
|
||||||
@@ -54,8 +72,11 @@ public class RoomTaskScheduler {
|
|||||||
|
|
||||||
for (Mob mob : currentRoom.getMobs()) {
|
for (Mob mob : currentRoom.getMobs()) {
|
||||||
RoomTask task = mob.getTask();
|
RoomTask task = mob.getTask();
|
||||||
|
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
scheduler.scheduleAtFixedRate(task.task(), 0, task.rate(), task.rateUnit());
|
dependencyManager.inject(task.getTask());
|
||||||
|
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task.getTask(), 0, task.getRate(), task.getRateUnit());
|
||||||
|
tasks.put(task, future);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user