3d promote (Fixes #14)
All checks were successful
Linux arm64 / Build (push) Successful in 35s

This commit is contained in:
2025-05-18 12:18:09 +02:00
parent fd9aabb6a1
commit 523eb094e1
11 changed files with 82 additions and 37 deletions

View File

@@ -11,7 +11,7 @@ public class OpenGLMain {
Game game = new Game(); Game game = new Game();
CommandExecutor commandExecutor = new CommandExecutor(game); CommandExecutor commandExecutor = new CommandExecutor(game);
PgnFileSimulator fileSimulator = new PgnFileSimulator(commandExecutor, "games/FoolCheckmate.pgn"); PgnFileSimulator fileSimulator = new PgnFileSimulator(commandExecutor, "games/PromoteTest.pgn");
DDDView ddd = new DDDView(commandExecutor); DDDView ddd = new DDDView(commandExecutor);

View File

@@ -11,6 +11,7 @@ import chess.controller.event.EmptyGameDispatcher;
import chess.controller.event.GameAdapter; import chess.controller.event.GameAdapter;
import chess.model.ChessBoard; import chess.model.ChessBoard;
import chess.model.Color; import chess.model.Color;
import chess.model.Coordinate;
import chess.model.Game; import chess.model.Game;
import chess.model.Move; import chess.model.Move;
import chess.model.PermissiveGame; import chess.model.PermissiveGame;
@@ -26,7 +27,7 @@ public class GameSimulation extends GameAdapter implements CommandSender {
} }
@Override @Override
public void onPawnPromoted(PromoteType promotion) { public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {
sendPawnPromotion(promotion); sendPawnPromotion(promotion);
} }

View File

@@ -56,7 +56,7 @@ public class PromoteCommand extends PlayerCommand {
this.oldPawn = pawn; this.oldPawn = pawn;
board.pieceComes(createPiece(this.promoteType, pawn.getColor()), this.pieceCoords); board.pieceComes(createPiece(this.promoteType, pawn.getColor()), this.pieceCoords);
outputSystem.onPawnPromoted(this.promoteType); outputSystem.onPawnPromoted(this.promoteType, this.pieceCoords);
// invalidate the last move cache // invalidate the last move cache
board.setLastMove(null); board.setLastMove(null);

View File

@@ -101,8 +101,8 @@ public class AsyncGameDispatcher extends GameDispatcher {
} }
@Override @Override
public void onPawnPromoted(PromoteType promotion) { public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {
asyncForEachCall((l) -> l.onPawnPromoted(promotion)); asyncForEachCall((l) -> l.onPawnPromoted(promotion, coordinate));
} }
@Override @Override

View File

@@ -64,7 +64,7 @@ public class EmptyGameDispatcher extends GameDispatcher {
} }
@Override @Override
public void onPawnPromoted(PromoteType promotion) { public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {
} }
@Override @Override

View File

@@ -50,6 +50,6 @@ public abstract class GameAdapter implements GameListener {
public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) {} public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) {}
@Override @Override
public void onPawnPromoted(PromoteType promotion) {} public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {}
} }

View File

@@ -99,8 +99,8 @@ public interface GameListener {
* Invoked when a pawn is promoted * Invoked when a pawn is promoted
* *
* @param promotion the type of promotion * @param promotion the type of promotion
* @param player the player who promoted the pawns * @param coordinate the coordinate of the old pawn
*/ */
void onPawnPromoted(PromoteType promotion); void onPawnPromoted(PromoteType promotion, Coordinate coordinate);
} }

View File

@@ -6,6 +6,7 @@ import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import chess.controller.commands.*; import chess.controller.commands.*;
import chess.controller.commands.PromoteCommand.PromoteType;
import imgui.ImGui; import imgui.ImGui;
import imgui.ImVec2; import imgui.ImVec2;
import imgui.flag.ImGuiCond; import imgui.flag.ImGuiCond;
@@ -242,6 +243,15 @@ public class DDDView extends GameAdapter implements CommandSender {
} }
} }
private PieceEntity createDefault(Piece piece, Coordinate coordinate) throws IOException {
Vector2f pieceBoardPos = DDDPlacement.coordinatesToVector(coordinate);
Vector3f pieceWorldPos = new Vector3f(pieceBoardPos.x(), 0, pieceBoardPos.y());
return new PieceEntity(piece, pieceWorldPos,
piece.getColor() == Color.White ? WHITE : BLACK,
piece.getColor() == Color.White ? 0.0f : (float) Math.PI);
}
private void initBoard() throws IOException { private void initBoard() throws IOException {
for (int i = 0; i < Coordinate.VALUE_MAX; i++) { for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
for (int j = 0; j < Coordinate.VALUE_MAX; j++) { for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
@@ -250,14 +260,7 @@ public class DDDView extends GameAdapter implements CommandSender {
if (piece == null) if (piece == null)
continue; continue;
Vector2f pieceBoardPos = DDDPlacement.coordinatesToVector(pos); this.world.addPiece(createDefault(piece, pos), pos);
Vector3f pieceWorldPos = new Vector3f(pieceBoardPos.x(), 0, pieceBoardPos.y());
PieceEntity entity = new PieceEntity(piece, pieceWorldPos,
piece.getColor() == Color.White ? WHITE : BLACK,
piece.getColor() == Color.White ? 0.0f : (float) Math.PI);
this.world.addPiece(entity, pos);
} }
} }
this.boardEntity = new BoardEntity(); this.boardEntity = new BoardEntity();
@@ -319,9 +322,12 @@ public class DDDView extends GameAdapter implements CommandSender {
Vector2f pieceDestBoardPos = DDDPlacement.coordinatesToVector(move.getFinish()); Vector2f pieceDestBoardPos = DDDPlacement.coordinatesToVector(move.getFinish());
Vector3f pieceDestWorldPos = new Vector3f(pieceDestBoardPos.x(), 0, pieceDestBoardPos.y()); Vector3f pieceDestWorldPos = new Vector3f(pieceDestBoardPos.x(), 0, pieceDestBoardPos.y());
if (move.getDeadPieceCoords() != null) { final PieceEntity pDead = this.world.getPiece(move.getDeadPieceCoords());
this.world.ejectPiece(move.getDeadPieceCoords()); this.world.setPieceCoords(null, move.getDeadPieceCoords());
}
// we must do that on the rendering thread to avoid
// ConcurrentModificationException
this.window.scheduleTask(() -> this.world.ejectPiece(pDead));
pEntity.setPosition(pieceDestWorldPos); pEntity.setPosition(pieceDestWorldPos);
@@ -371,25 +377,47 @@ public class DDDView extends GameAdapter implements CommandSender {
} }
} }
private void renderPopup(String title, String text) { private void renderPopup(String title, Runnable content) {
ImVec2 center = ImGui.getMainViewport().getCenter(); ImVec2 center = ImGui.getMainViewport().getCenter();
ImGui.setNextWindowPos(center, ImGuiCond.Appearing, new ImVec2(0.5f, 0.5f)); ImGui.setNextWindowPos(center, ImGuiCond.Appearing, new ImVec2(0.5f, 0.5f));
if (ImGui.beginPopupModal(title, null, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoMove)) { if (ImGui.beginPopupModal(title, null, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoMove)) {
ImGui.text(text); content.run();
if (ImGui.button("Close")) { if (ImGui.button("Close")) {
ImGui.closeCurrentPopup(); closeCurrentPopup();
synchronized (this) {
notifyAll();
}
} }
ImGui.endPopup(); ImGui.endPopup();
} }
} }
private void closeCurrentPopup() {
ImGui.closeCurrentPopup();
synchronized (this) {
notifyAll();
}
}
private void renderPopup(String title, String text) {
renderPopup(title, () -> ImGui.text(text));
}
private void renderPromoteDialog() {
renderPopup("Promotion", () -> {
ImGui.text("Select the promotion type :");
for (PromoteType promoteType : PromoteType.values()) {
if (ImGui.button(promoteType.toString())) {
sendPawnPromotion(promoteType);
closeCurrentPopup();
}
ImGui.sameLine();
}
ImGui.newLine();
});
}
private void renderPopups() { private void renderPopups() {
renderPopup("Check", "Your king is in check"); renderPopup("Check", "Your king is in check");
renderPopup("Checkmate", "Checkmate, it's a win!"); renderPopup("Checkmate", "Checkmate, it's a win!");
renderPopup("Promotion", "Please promote your pawn."); renderPromoteDialog();
renderPopup("Pat", "It's a pat!"); renderPopup("Pat", "It's a pat!");
renderPopup("Tie", "It's a tie!"); renderPopup("Tie", "It's a tie!");
renderPopup("White surrender", "The white player has surrendered!"); renderPopup("White surrender", "The white player has surrendered!");
@@ -451,4 +479,21 @@ public class DDDView extends GameAdapter implements CommandSender {
public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) { public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) {
move3DPieces(List.of(kingMove, rookMove)); move3DPieces(List.of(kingMove, rookMove));
} }
@Override
public void onPromotePawn(Coordinate pieceCoords) {
openPopup("Promotion");
}
@Override
public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {
this.window.scheduleTask(() -> {
this.world.ejectPiece(this.world.getPiece(coordinate));
try {
this.world.addPiece(createDefault(getPieceAt(coordinate), coordinate), coordinate);
} catch (IOException e) {
e.printStackTrace();
}
});
}
} }

View File

@@ -36,7 +36,7 @@ public class World implements Closeable{
setPieceCoords(entity, coordinate); setPieceCoords(entity, coordinate);
} }
private void setPieceCoords(PieceEntity entity, Coordinate coordinate) { public void setPieceCoords(PieceEntity entity, Coordinate coordinate) {
pieces[coordinate.toIndex()] = entity; pieces[coordinate.toIndex()] = entity;
} }
@@ -45,11 +45,9 @@ public class World implements Closeable{
setPieceCoords(null, move.getStart()); setPieceCoords(null, move.getStart());
} }
public void ejectPiece(Coordinate coordinate) { public void ejectPiece(PieceEntity entity) {
PieceEntity entity = getPiece(coordinate);
if (entity != null) if (entity != null)
this.entites.remove(entity); this.entites.remove(entity);
setPieceCoords(null, coordinate);
} }
public PieceEntity getPiece(Coordinate coordinate) { public PieceEntity getPiece(Coordinate coordinate) {

View File

@@ -2,6 +2,7 @@ package chess.view.audio;
import chess.controller.commands.PromoteCommand.PromoteType; import chess.controller.commands.PromoteCommand.PromoteType;
import chess.controller.event.GameAdapter; import chess.controller.event.GameAdapter;
import chess.model.Coordinate;
import chess.model.Move; import chess.model.Move;
public class GameAudio extends GameAdapter { public class GameAudio extends GameAdapter {
@@ -51,7 +52,7 @@ public class GameAudio extends GameAdapter {
} }
@Override @Override
public void onPawnPromoted(PromoteType promotion) { public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {
playSound("promote"); playSound("promote");
} }

View File

@@ -291,7 +291,7 @@ public class Window extends JFrame implements GameListener, CommandSender {
public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) {} public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) {}
@Override @Override
public void onPawnPromoted(PromoteType promotion) {} public void onPawnPromoted(PromoteType promotion, Coordinate coordinate) {}
@Override @Override
public CommandExecutor getCommandExecutor() { public CommandExecutor getCommandExecutor() {