feat: Implemented mouse events and block breaking
This commit is contained in:
parent
b4641c5c86
commit
a359bedd3a
@ -1,8 +1,10 @@
|
|||||||
package cz.jzitnik;
|
package cz.jzitnik;
|
||||||
|
|
||||||
import cz.jzitnik.game.Game;
|
import cz.jzitnik.game.Game;
|
||||||
|
import cz.jzitnik.game.MouseHandler;
|
||||||
import cz.jzitnik.game.SpriteLoader;
|
import cz.jzitnik.game.SpriteLoader;
|
||||||
import cz.jzitnik.tui.ScreenRenderer;
|
import cz.jzitnik.tui.ScreenRenderer;
|
||||||
|
import org.jline.terminal.MouseEvent;
|
||||||
import org.jline.terminal.Terminal;
|
import org.jline.terminal.Terminal;
|
||||||
import org.jline.terminal.TerminalBuilder;
|
import org.jline.terminal.TerminalBuilder;
|
||||||
|
|
||||||
@ -11,18 +13,22 @@ import java.io.IOException;
|
|||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
// Set up terminal with JLine
|
|
||||||
Terminal terminal = TerminalBuilder.terminal();
|
Terminal terminal = TerminalBuilder.terminal();
|
||||||
terminal.enterRawMode();
|
terminal.enterRawMode();
|
||||||
|
terminal.trackMouse(Terminal.MouseTracking.Any);
|
||||||
|
|
||||||
|
if (!terminal.hasMouseSupport()) {
|
||||||
|
System.out.println("Error: This terminal does not support mouse.");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
var spriteList = SpriteLoader.load();
|
var spriteList = SpriteLoader.load();
|
||||||
var screenRenderer = new ScreenRenderer(spriteList, terminal);
|
var screenRenderer = new ScreenRenderer(spriteList, terminal);
|
||||||
var game = new Game();
|
var game = new Game();
|
||||||
|
|
||||||
final boolean[] isRunning = {true};
|
MouseHandler mouseHandler = new MouseHandler(game, terminal, screenRenderer);
|
||||||
|
|
||||||
// Enable mouse tracking
|
final boolean[] isRunning = {true};
|
||||||
terminal.writer().print("\033[?1003h\n"); // Enable mouse move events
|
|
||||||
terminal.writer().flush();
|
|
||||||
|
|
||||||
Thread inputThread = new Thread(() -> {
|
Thread inputThread = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
@ -35,14 +41,8 @@ public class Main {
|
|||||||
if (key == '[') {
|
if (key == '[') {
|
||||||
key = terminal.reader().read();
|
key = terminal.reader().read();
|
||||||
if (key == 'M') {
|
if (key == 'M') {
|
||||||
int buttonCode = terminal.reader().read() - 32;
|
MouseEvent mouseEvent = terminal.readMouseEvent();
|
||||||
int x = terminal.reader().read() - 32;
|
mouseHandler.handle(mouseEvent);
|
||||||
int y = terminal.reader().read() - 32;
|
|
||||||
|
|
||||||
if (buttonCode == 0) {
|
|
||||||
game.handleMouseClick(x, y);
|
|
||||||
//screenRenderer.render(game.getWorld());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,9 +60,6 @@ public class Main {
|
|||||||
game.movePlayerUp(screenRenderer);
|
game.movePlayerUp(screenRenderer);
|
||||||
screenRenderer.render(game.getWorld());
|
screenRenderer.render(game.getWorld());
|
||||||
break;
|
break;
|
||||||
case 'm':
|
|
||||||
game.mine(screenRenderer);
|
|
||||||
break;
|
|
||||||
case 'q':
|
case 'q':
|
||||||
System.out.println("Exiting game...");
|
System.out.println("Exiting game...");
|
||||||
isRunning[0] = false;
|
isRunning[0] = false;
|
||||||
@ -89,8 +86,7 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable mouse tracking on exit
|
// Disable mouse tracking on exit
|
||||||
terminal.writer().print("\033[?1003l\n");
|
terminal.trackMouse(Terminal.MouseTracking.Off);
|
||||||
terminal.writer().flush();
|
|
||||||
|
|
||||||
terminal.close();
|
terminal.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -2,6 +2,7 @@ package cz.jzitnik.game;
|
|||||||
|
|
||||||
import cz.jzitnik.tui.ScreenRenderer;
|
import cz.jzitnik.tui.ScreenRenderer;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ public class Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Block steveBlock = new Block("steve", SpriteLoader.SPRITES.STEVE);
|
Block steveBlock = new Block("steve", SpriteLoader.SPRITES.STEVE);
|
||||||
|
world[9][0].add(new Block("grass", SpriteLoader.SPRITES.GRASS));
|
||||||
player = steveBlock;
|
player = steveBlock;
|
||||||
|
|
||||||
for (int i = 0; i < 50; i++) {
|
for (int i = 0; i < 50; i++) {
|
||||||
@ -45,7 +47,7 @@ public class Game {
|
|||||||
world[10][0].add(steveBlock);
|
world[10][0].add(steveBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] getPlayerCords() {
|
public int[] getPlayerCords() {
|
||||||
for (int i = 0; i < world.length; i++) {
|
for (int i = 0; i < world.length; i++) {
|
||||||
for (int j = 0; j < world[i].length; j++) {
|
for (int j = 0; j < world[i].length; j++) {
|
||||||
for (Block block : world[i][j]) {
|
for (Block block : world[i][j]) {
|
||||||
@ -148,15 +150,25 @@ public class Game {
|
|||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mine(ScreenRenderer screenRenderer) {
|
public void mine(ScreenRenderer screenRenderer, int x, int y) {
|
||||||
int[] cords = getPlayerCords();
|
int[] cords = getPlayerCords();
|
||||||
|
|
||||||
if (world[cords[1] + 1][cords[0]].stream().allMatch(Block::isGhost)) {
|
int playerX = cords[0];
|
||||||
|
int playerY = cords[1];
|
||||||
|
|
||||||
|
int distanceX = Math.abs(playerX - x);
|
||||||
|
int distanceY = Math.abs(playerY - y);
|
||||||
|
|
||||||
|
if (distanceX > 5 || distanceY > 5) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
world[cords[1] + 1][cords[0]].clear();
|
if (world[y][x].stream().allMatch(Block::isGhost)) {
|
||||||
world[cords[1] + 1][cords[0]].add(new Block("air", SpriteLoader.SPRITES.AIR, true));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
world[y][x].clear();
|
||||||
|
world[y][x].add(new Block("air", SpriteLoader.SPRITES.AIR, true));
|
||||||
screenRenderer.render(world);
|
screenRenderer.render(world);
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
@ -175,33 +187,4 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleMouseClick(int mouseX, int mouseY) {
|
|
||||||
/*int[] cords = getPlayerCords();
|
|
||||||
if (cords == null) return;
|
|
||||||
|
|
||||||
int playerX = cords[0];
|
|
||||||
int playerY = cords[1];
|
|
||||||
int viewXRadius = 5;
|
|
||||||
int viewUpRadius = 4;
|
|
||||||
int viewDownRadius = 3;
|
|
||||||
|
|
||||||
// Convert mouse coordinates to world coordinates
|
|
||||||
int blockX = startX + (mouseX / 50); // 50 chars wide per sprite
|
|
||||||
int blockY = startY + (mouseY / 25); // 25 lines high per sprite
|
|
||||||
|
|
||||||
// Check if within bounds
|
|
||||||
if (blockY >= startY && blockY < endY && blockX >= startX && blockX < endX) {
|
|
||||||
List<Block> blocks = world[blockY][blockX];
|
|
||||||
if (!blocks.isEmpty()) {
|
|
||||||
Block topBlock = blocks.get(blocks.size() - 1); // Get topmost block
|
|
||||||
System.out.println("Mouse clicked on block: " + topBlock.getBlockId() +
|
|
||||||
" at World Coordinates: [" + blockX + ", " + blockY + "]");
|
|
||||||
} else {
|
|
||||||
System.out.println("No block at the clicked position.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.println("Clicked outside the visible area.");
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
}
|
101
src/main/java/cz/jzitnik/game/MouseHandler.java
Normal file
101
src/main/java/cz/jzitnik/game/MouseHandler.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package cz.jzitnik.game;
|
||||||
|
|
||||||
|
import cz.jzitnik.tui.ScreenMovingCalculationProvider;
|
||||||
|
import cz.jzitnik.tui.ScreenRenderer;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jline.terminal.MouseEvent;
|
||||||
|
import org.jline.terminal.Terminal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MouseHandler {
|
||||||
|
private Game game;
|
||||||
|
private Terminal terminal;
|
||||||
|
private ScreenRenderer screenRenderer;
|
||||||
|
|
||||||
|
public void handle(MouseEvent mouseEvent) {
|
||||||
|
if (mouseEvent.getButton() == MouseEvent.Button.Button1 && mouseEvent.getType() == MouseEvent.Type.Pressed) {
|
||||||
|
leftClick(mouseEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseEvent.getType() == MouseEvent.Type.Moved) {
|
||||||
|
move(mouseEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leftClick(MouseEvent mouseEvent) {
|
||||||
|
int mouseX = mouseEvent.getX();
|
||||||
|
int mouseY = mouseEvent.getY();
|
||||||
|
|
||||||
|
int[] cords = game.getPlayerCords();
|
||||||
|
if (cords == null) return;
|
||||||
|
|
||||||
|
int playerX = cords[0];
|
||||||
|
int playerY = cords[1];
|
||||||
|
|
||||||
|
int[] data = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), game.getWorld()[0].length, game.getWorld().length);
|
||||||
|
|
||||||
|
int startX = data[0];
|
||||||
|
int endX = data[1];
|
||||||
|
int startY = data[2];
|
||||||
|
int endY = data[3];
|
||||||
|
|
||||||
|
int blockX = startX + (mouseX / 50); // 50 chars wide per sprite
|
||||||
|
int blockY = startY + (mouseY / 25); // 25 lines high per sprite
|
||||||
|
|
||||||
|
if (blockY == playerX && blockY == playerY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockY >= startY && blockY < endY && blockX >= startX && blockX < endX) {
|
||||||
|
List<Block> blocks = game.getWorld()[blockY][blockX];
|
||||||
|
System.out.println(blockX);
|
||||||
|
System.out.println(blockY);
|
||||||
|
if (!blocks.isEmpty()) {
|
||||||
|
game.mine(screenRenderer, blockX, blockY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void move(MouseEvent mouseEvent) {
|
||||||
|
int mouseX = mouseEvent.getX();
|
||||||
|
int mouseY = mouseEvent.getY();
|
||||||
|
|
||||||
|
int[] cords = game.getPlayerCords();
|
||||||
|
if (cords == null) return;
|
||||||
|
|
||||||
|
int playerX = cords[0];
|
||||||
|
int playerY = cords[1];
|
||||||
|
|
||||||
|
int[] data = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), game.getWorld()[0].length, game.getWorld().length);
|
||||||
|
|
||||||
|
int startX = data[0];
|
||||||
|
int endX = data[1];
|
||||||
|
int startY = data[2];
|
||||||
|
int endY = data[3];
|
||||||
|
|
||||||
|
int blockX = startX + (mouseX / 50); // 50 chars wide per sprite
|
||||||
|
int blockY = startY + (mouseY / 25); // 25 lines high per sprite
|
||||||
|
|
||||||
|
if (blockY == playerX && blockY == playerY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Block> blocks = game.getWorld()[blockY][blockX];
|
||||||
|
|
||||||
|
if (blockY >= startY && blockY < endY && blockX >= startX && blockX < endX && !blocks.stream().allMatch(block -> block.getBlockId().equals("air"))) {
|
||||||
|
List<Integer> list = new ArrayList<>();
|
||||||
|
list.add(blockX);
|
||||||
|
list.add(blockY);
|
||||||
|
screenRenderer.setSelectedBlock(Optional.of(list));
|
||||||
|
} else {
|
||||||
|
screenRenderer.setSelectedBlock(Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
screenRenderer.render(game.getWorld());
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,29 @@
|
|||||||
package cz.jzitnik.tui;
|
package cz.jzitnik.tui;
|
||||||
|
|
||||||
import cz.jzitnik.game.Block;
|
import cz.jzitnik.game.Block;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
import org.jline.terminal.Terminal;
|
import org.jline.terminal.Terminal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ScreenRenderer {
|
public class ScreenRenderer {
|
||||||
private SpriteList spriteList;
|
private SpriteList spriteList;
|
||||||
private Terminal terminal;
|
private Terminal terminal;
|
||||||
|
|
||||||
|
public ScreenRenderer(SpriteList spriteList, Terminal terminal) {
|
||||||
|
this.spriteList = spriteList;
|
||||||
|
this.terminal = terminal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Optional<List<Integer>> selectedBlock = Optional.empty();
|
||||||
|
|
||||||
private int[] getPlayerCords(List<Block>[][] world) {
|
private int[] getPlayerCords(List<Block>[][] world) {
|
||||||
for (int i = 0; i < world.length; i++) {
|
for (int i = 0; i < world.length; i++) {
|
||||||
for (int j = 0; j < world[i].length; j++) {
|
for (int j = 0; j < world[i].length; j++) {
|
||||||
@ -50,9 +63,9 @@ public class ScreenRenderer {
|
|||||||
if (visibleWidth % 2 != 0) {
|
if (visibleWidth % 2 != 0) {
|
||||||
endX = Math.max(startX, endX - 1);
|
endX = Math.max(startX, endX - 1);
|
||||||
}
|
}
|
||||||
/*if (visibleHeight % 2 != 0) {
|
if (visibleHeight % 2 != 0) {
|
||||||
endY = Math.max(startY, endY - 1);
|
endY = Math.max(startY, endY - 1);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
StringBuilder[] lines = new StringBuilder[(endY - startY) * 26];
|
StringBuilder[] lines = new StringBuilder[(endY - startY) * 26];
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
@ -63,9 +76,36 @@ public class ScreenRenderer {
|
|||||||
for (int y = startY; y < endY; y++) {
|
for (int y = startY; y < endY; y++) {
|
||||||
for (int x = startX; x < endX; x++) {
|
for (int x = startX; x < endX; x++) {
|
||||||
List<Block> blocks = world[y][x];
|
List<Block> blocks = world[y][x];
|
||||||
String sprite = SpriteCombiner.combineSprites(blocks.stream()
|
List<String> sprites = new ArrayList<>(blocks.stream()
|
||||||
.map(block -> spriteList.getSprite(block.getSprite()).getSprite())
|
.map(block -> spriteList.getSprite(block.getSprite()).getSprite()).toList());
|
||||||
.toArray(String[]::new));
|
|
||||||
|
if (selectedBlock.isPresent() && selectedBlock.get().get(0) == x && selectedBlock.get().get(1) == y) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
stringBuilder.append("\033[38;5;231;48;5;231m▓");
|
||||||
|
}
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < 23; i++) {
|
||||||
|
stringBuilder.append("\033[38;5;231;48;5;231m▓");
|
||||||
|
for (int j = 0; j < 48; j++) {
|
||||||
|
stringBuilder.append("\033[0m ");
|
||||||
|
}
|
||||||
|
stringBuilder.append("\033[38;5;231;48;5;231m▓");
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
stringBuilder.append("\033[38;5;231;48;5;231m▓");
|
||||||
|
}
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
|
||||||
|
sprites.add(stringBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
String sprite = SpriteCombiner.combineSprites(sprites.toArray(String[]::new));
|
||||||
|
|
||||||
|
|
||||||
String[] spriteLines = sprite.split("\n");
|
String[] spriteLines = sprite.split("\n");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user