feat: Mouse events

This commit is contained in:
Jakub Žitník 2025-02-18 06:38:10 +01:00
parent f0f1047078
commit 5127b9ee5f
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
4 changed files with 149 additions and 4 deletions

View File

@ -13,17 +13,42 @@ public class Main {
try {
// Set up terminal with JLine
Terminal terminal = TerminalBuilder.terminal();
terminal.enterRawMode(); // Switch to raw mode to capture keys immediately
terminal.enterRawMode();
var spriteList = SpriteLoader.load();
var screenRenderer = new ScreenRenderer(spriteList);
var game = new Game();
final boolean[] isRunning = {true};
// Enable mouse tracking
terminal.writer().print("\033[?1003h\n"); // Enable mouse move events
terminal.writer().flush();
Thread inputThread = new Thread(() -> {
try {
while (isRunning[0]) {
int key = terminal.reader().read();
// Check for mouse event sequence
if (key == 27) { // ESC
key = terminal.reader().read();
if (key == '[') {
key = terminal.reader().read();
if (key == 'M') {
int buttonCode = terminal.reader().read() - 32;
int x = terminal.reader().read() - 32;
int y = terminal.reader().read() - 32;
if (buttonCode == 0) {
game.handleMouseClick(x, y);
throw new RuntimeException("sad");
//screenRenderer.render(game.getWorld());
}
}
}
}
// Handle keyboard input as before
switch (key) {
case 'a':
game.movePlayerLeft(screenRenderer);
@ -38,7 +63,7 @@ public class Main {
screenRenderer.render(game.getWorld());
break;
case 'm':
System.out.println("Mine pressed");
game.mine(screenRenderer);
break;
case 'q':
System.out.println("Exiting game...");
@ -59,12 +84,16 @@ public class Main {
while (isRunning[0]) {
screenRenderer.render(game.getWorld());
try {
Thread.sleep(1000); // Control game loop speed
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Disable mouse tracking on exit
terminal.writer().print("\033[?1003l\n");
terminal.writer().flush();
terminal.close();
} catch (IOException e) {
e.printStackTrace();

View File

@ -1,5 +1,6 @@
package cz.jzitnik.game;
import cz.jzitnik.game.sprites.Breaking;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.Getter;
import java.util.ArrayList;
@ -9,6 +10,7 @@ import java.util.List;
public class Game {
private List<Block>[][] world = new ArrayList[50][50];
private Block player;
private boolean mining;
public Game() {
for (int i = 0; i < 50; i++) {
@ -147,4 +149,67 @@ public class Game {
}
}).start();
}
public void mine(ScreenRenderer screenRenderer) {
int[] cords = getPlayerCords();
if (world[cords[1] + 1][cords[0]].stream().allMatch(Block::isGhost)) {
return;
}
world[cords[1] + 1][cords[0]].clear();
world[cords[1] + 1][cords[0]].add(new Block("air", SpriteLoader.SPRITES.AIR, true));
screenRenderer.render(world);
new Thread(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int[] cords2 = getPlayerCords();
if (world[cords2[1] + 1][cords2[0]].stream().anyMatch(Block::isGhost)) {
world[cords2[1] + 1][cords2[0]].add(player);
world[cords2[1]][cords2[0]].remove(player);
screenRenderer.render(world);
}
}).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;
// Calculate visible area boundaries
int startX = Math.max(0, playerX - viewXRadius);
int endX = Math.min(world[0].length, playerX + viewXRadius + 1);
int startY = Math.max(0, playerY - viewUpRadius);
int endY = Math.min(world.length, playerY + viewDownRadius + 1);
// 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.");
}
}
}

View File

@ -0,0 +1,25 @@
package cz.jzitnik.game.sprites;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;
public class Breaking extends Sprite {
enum BreakingState {
FIRST,
SECOND,
THIRD
}
public String getSprite() {
return ResourceLoader.loadResource("breaking/1.ans");
}
public String getSprite(Enum key) {
return ResourceLoader.loadResource(switch (key) {
case BreakingState.FIRST -> "breaking/1.ans";
case BreakingState.SECOND -> "breaking/2.ans";
case BreakingState.THIRD -> "breaking/3.ans";
default -> throw new IllegalStateException("Unexpected value: " + key);
});
}
}

View File

@ -0,0 +1,26 @@
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  
                             ▓▓▓                  
                             ▓▓▓                  
                             ▓▓▓                  
             ▓▓▒             ▓▓▓▓▓▓▓▓▓            
         ░░░ ▓▓░             ▓▓▓▓▓▓▓▓▓            
         ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓            
         ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
         ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
                   ▓▓▓                            
                   ▓▓▓                            
                   ▓▓▓                            
                   ▓▓▓