Compare commits
1 Commits
f8ae19fee8
...
failed
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ac7b4ad65 |
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
*.glb filter=lfs diff=lfs merge=lfs -text
|
||||
*.fbx filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
|
||||
@@ -26,13 +26,11 @@ dependencies {
|
||||
implementation "org.lwjgl:lwjgl:$lwjgl_version"
|
||||
implementation "org.lwjgl:lwjgl-opengl:$lwjgl_version"
|
||||
implementation "org.lwjgl:lwjgl-glfw:$lwjgl_version"
|
||||
implementation "org.lwjgl:lwjgl-assimp:$lwjgl_version"
|
||||
implementation "org.joml:joml:1.10.8"
|
||||
|
||||
implementation "org.lwjgl:lwjgl::$lwjgl_natives"
|
||||
implementation "org.lwjgl:lwjgl-opengl::$lwjgl_natives"
|
||||
implementation "org.lwjgl:lwjgl-glfw::$lwjgl_natives"
|
||||
implementation "org.lwjgl:lwjgl-assimp::$lwjgl_natives"
|
||||
}
|
||||
|
||||
application {
|
||||
@@ -47,10 +45,6 @@ jar {
|
||||
}
|
||||
}
|
||||
|
||||
run {
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
// Use JUnit Platform for unit tests.
|
||||
useJUnitPlatform()
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package chess;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
import chess.view.consolerender.Colors;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
System.out.println(Colors.RED + "Credits: Grenier Lilas, Pribylski Simon." + Colors.RESET);
|
||||
System.out.println("""
|
||||
Pick the version to use:
|
||||
1 - Console
|
||||
2 - Window
|
||||
3 - 3D.""");
|
||||
2 - Window.""");
|
||||
switch (new Scanner(System.in).nextLine()) {
|
||||
case "1", "Console", "console":
|
||||
ConsoleMain.main(args);
|
||||
@@ -19,9 +18,6 @@ public class App {
|
||||
case "2", "Window", "window":
|
||||
SwingMain.main(args);
|
||||
break;
|
||||
case "3", "3D", "3d":
|
||||
OpenGLMain.main(args);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Invalid input");
|
||||
break;
|
||||
|
||||
@@ -5,17 +5,26 @@ package chess;
|
||||
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.NewGameCommand;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Game;
|
||||
import chess.simulator.PromoteTest;
|
||||
import chess.view.consolerender.Console;
|
||||
|
||||
public class ConsoleMain {
|
||||
public static void main(String[] args) {
|
||||
Game game = new Game();
|
||||
Game game = new Game(new ChessBoard());
|
||||
CommandExecutor commandExecutor = new CommandExecutor(game);
|
||||
|
||||
PromoteTest promoteTest = new PromoteTest(commandExecutor);
|
||||
commandExecutor.addListener(promoteTest);
|
||||
|
||||
Console console = new Console(commandExecutor);
|
||||
commandExecutor.addListener(console);
|
||||
|
||||
promoteTest.onComplete.connect(() -> {
|
||||
console.setCaptureInput(true);
|
||||
});
|
||||
|
||||
commandExecutor.executeCommand(new NewGameCommand());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
package chess;
|
||||
|
||||
import chess.ai.DumbAI;
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.NewGameCommand;
|
||||
import chess.controller.event.GameAdaptator;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Color;
|
||||
import chess.model.Game;
|
||||
import chess.view.DDDrender.DDDView;
|
||||
import chess.pgn.PgnExport;
|
||||
import chess.view.render.Window;
|
||||
|
||||
public class OpenGLMain {
|
||||
public static void main(String[] args) {
|
||||
Game game = new Game();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Game game = new Game(new ChessBoard());
|
||||
CommandExecutor commandExecutor = new CommandExecutor(game);
|
||||
|
||||
DDDView ddd = new DDDView(commandExecutor);
|
||||
commandExecutor.addListener(ddd);
|
||||
|
||||
Window window = new Window(commandExecutor);
|
||||
commandExecutor.addListener(window);
|
||||
|
||||
// DumbAI ai = new DumbAI(commandExecutor, Color.Black);
|
||||
// commandExecutor.addListener(ai);
|
||||
|
||||
// DumbAI ai2 = new DumbAI(commandExecutor, Color.White);
|
||||
// commandExecutor.addListener(ai2);
|
||||
|
||||
commandExecutor.executeCommand(new NewGameCommand());
|
||||
|
||||
ddd.run();
|
||||
commandExecutor.close();
|
||||
window.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package chess;
|
||||
|
||||
import chess.ai.DumbAI;
|
||||
import chess.ai.HungryAI;
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.NewGameCommand;
|
||||
import chess.controller.event.GameAdaptator;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Color;
|
||||
import chess.model.Game;
|
||||
import chess.pgn.PgnExport;
|
||||
@@ -12,7 +12,7 @@ import chess.view.simplerender.Window;
|
||||
|
||||
public class SwingMain {
|
||||
public static void main(String[] args) {
|
||||
Game game = new Game();
|
||||
Game game = new Game(new ChessBoard());
|
||||
CommandExecutor commandExecutor = new CommandExecutor(game);
|
||||
|
||||
Window window = new Window(commandExecutor, false);
|
||||
@@ -21,7 +21,7 @@ public class SwingMain {
|
||||
DumbAI ai = new DumbAI(commandExecutor, Color.Black);
|
||||
commandExecutor.addListener(ai);
|
||||
|
||||
HungryAI ai2 = new HungryAI(commandExecutor, Color.White);
|
||||
DumbAI ai2 = new DumbAI(commandExecutor, Color.White);
|
||||
commandExecutor.addListener(ai2);
|
||||
|
||||
commandExecutor.addListener(new GameAdaptator(){
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package chess.ai;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.GetPieceAtCommand;
|
||||
import chess.controller.commands.GetPlayerMovesCommand;
|
||||
import chess.controller.commands.GetAllowedCastlingsCommand;
|
||||
import chess.controller.commands.GetAllowedCastlingsCommand.CastlingResult;
|
||||
import chess.controller.event.GameAdaptator;
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Move;
|
||||
import chess.model.Piece;
|
||||
|
||||
public abstract class AI extends GameAdaptator{
|
||||
|
||||
protected final CommandExecutor commandExecutor;
|
||||
protected final Color color;
|
||||
|
||||
public AI(CommandExecutor commandExecutor, Color color) {
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
protected abstract void play();
|
||||
protected abstract void promote(Coordinate pawnCoords);
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(Color color, boolean undone) {
|
||||
if (this.color != color || undone)
|
||||
return;
|
||||
|
||||
play();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPromotePawn(Coordinate pieceCoords) {
|
||||
Piece pawn = pieceAt(pieceCoords);
|
||||
if (pawn.getColor() != this.color)
|
||||
return;
|
||||
promote(pieceCoords);
|
||||
}
|
||||
|
||||
protected Piece pieceAt(Coordinate coordinate) {
|
||||
GetPieceAtCommand command = new GetPieceAtCommand(coordinate);
|
||||
sendCommand(command);
|
||||
return command.getPiece();
|
||||
}
|
||||
|
||||
protected List<Move> getAllowedMoves() {
|
||||
GetPlayerMovesCommand cmd = new GetPlayerMovesCommand();
|
||||
sendCommand(cmd);
|
||||
return cmd.getMoves();
|
||||
}
|
||||
|
||||
protected CastlingResult getAllowedCastlings() {
|
||||
GetAllowedCastlingsCommand cmd2 = new GetAllowedCastlingsCommand();
|
||||
sendCommand(cmd2);
|
||||
return cmd2.getCastlingResult();
|
||||
}
|
||||
|
||||
protected void sendCommand(Command command) {
|
||||
this.commandExecutor.executeCommand(command);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,28 +3,46 @@ package chess.ai;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import chess.controller.Command;
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.CastlingCommand;
|
||||
import chess.controller.commands.GetAllowedCastlingsCommand.CastlingResult;
|
||||
import chess.controller.commands.GetAllowedCastlingsCommand;
|
||||
import chess.controller.commands.GetPieceAtCommand;
|
||||
import chess.controller.commands.GetPlayerMovesCommand;
|
||||
import chess.controller.commands.MoveCommand;
|
||||
import chess.controller.commands.PromoteCommand;
|
||||
import chess.controller.commands.GetAllowedCastlingsCommand.CastlingResult;
|
||||
import chess.controller.commands.PromoteCommand.PromoteType;
|
||||
import chess.controller.event.GameAdaptator;
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Move;
|
||||
import chess.model.Piece;
|
||||
|
||||
public class DumbAI extends AI {
|
||||
public class DumbAI extends GameAdaptator {
|
||||
|
||||
private final Color player;
|
||||
private final CommandExecutor commandExecutor;
|
||||
private final Random random = new Random();
|
||||
|
||||
public DumbAI(CommandExecutor commandExecutor, Color color) {
|
||||
super(commandExecutor, color);
|
||||
this.player = color;
|
||||
this.commandExecutor = commandExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void play() {
|
||||
CastlingResult castlings = getAllowedCastlings();
|
||||
List<Move> moves = getAllowedMoves();
|
||||
public void onPlayerTurn(Color color) {
|
||||
if (color != player)
|
||||
return;
|
||||
|
||||
GetPlayerMovesCommand cmd = new GetPlayerMovesCommand();
|
||||
sendCommand(cmd);
|
||||
|
||||
GetAllowedCastlingsCommand cmd2 = new GetAllowedCastlingsCommand();
|
||||
sendCommand(cmd2);
|
||||
|
||||
CastlingResult castlings = cmd2.getCastlingResult();
|
||||
List<Move> moves = cmd.getMoves();
|
||||
|
||||
switch (castlings) {
|
||||
case Both: {
|
||||
@@ -35,12 +53,20 @@ public class DumbAI extends AI {
|
||||
return;
|
||||
}
|
||||
|
||||
case Small:
|
||||
case Small: {
|
||||
int randomMove = this.random.nextInt(moves.size() + 1);
|
||||
if (randomMove != moves.size())
|
||||
break;
|
||||
this.commandExecutor.executeCommand(new CastlingCommand(false));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
case Big: {
|
||||
int randomMove = this.random.nextInt(moves.size() + 1);
|
||||
if (randomMove != moves.size())
|
||||
break;
|
||||
this.commandExecutor.executeCommand(new CastlingCommand(castlings == CastlingResult.Big));
|
||||
this.commandExecutor.executeCommand(new CastlingCommand(true));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,12 +76,27 @@ public class DumbAI extends AI {
|
||||
|
||||
int randomMove = this.random.nextInt(moves.size());
|
||||
this.commandExecutor.executeCommand(new MoveCommand(moves.get(randomMove)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void promote(Coordinate pawnCoords) {
|
||||
public void onPromotePawn(Coordinate pieceCoords) {
|
||||
Piece pawn = pieceAt(pieceCoords);
|
||||
if (pawn.getColor() != this.player)
|
||||
return;
|
||||
|
||||
int promote = this.random.nextInt(PromoteType.values().length);
|
||||
this.commandExecutor.executeCommand(new PromoteCommand(PromoteType.values()[promote]));
|
||||
}
|
||||
|
||||
private Piece pieceAt(Coordinate coordinate) {
|
||||
GetPieceAtCommand command = new GetPieceAtCommand(coordinate);
|
||||
sendCommand(command);
|
||||
return command.getPiece();
|
||||
}
|
||||
|
||||
private void sendCommand(Command command) {
|
||||
this.commandExecutor.executeCommand(command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package chess.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.MoveCommand;
|
||||
import chess.controller.commands.PromoteCommand;
|
||||
import chess.controller.commands.PromoteCommand.PromoteType;
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Move;
|
||||
import chess.model.Piece;
|
||||
|
||||
public class HungryAI extends AI {
|
||||
|
||||
private final PieceCost pieceCost;
|
||||
private final Random random;
|
||||
|
||||
public HungryAI(CommandExecutor commandExecutor, Color color) {
|
||||
super(commandExecutor, color);
|
||||
this.pieceCost = new PieceCost(color);
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
private int getMoveCost(Move move) {
|
||||
Piece piece = pieceAt(move.getDeadPieceCoords());
|
||||
return pieceCost.getCost(piece);
|
||||
}
|
||||
|
||||
private List<Move> getBestMoves() {
|
||||
List<Move> moves = getAllowedMoves();
|
||||
List<Move> bestMoves = new ArrayList<>();
|
||||
int bestCost = 0;
|
||||
for (Move move : moves) {
|
||||
int moveCost = getMoveCost(move);
|
||||
if (moveCost == bestCost) {
|
||||
bestMoves.add(move);
|
||||
} else if (moveCost > bestCost) {
|
||||
bestMoves.clear();
|
||||
bestMoves.add(move);
|
||||
bestCost = moveCost;
|
||||
}
|
||||
}
|
||||
return bestMoves;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void play() {
|
||||
List<Move> bestMoves = getBestMoves();
|
||||
int randomMove = this.random.nextInt(bestMoves.size());
|
||||
this.commandExecutor.executeCommand(new MoveCommand(bestMoves.get(randomMove)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void promote(Coordinate pawnCoords) {
|
||||
sendCommand(new PromoteCommand(PromoteType.Queen));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package chess.ai;
|
||||
|
||||
import chess.model.Color;
|
||||
import chess.model.Piece;
|
||||
import chess.model.PieceVisitor;
|
||||
import chess.model.pieces.Bishop;
|
||||
import chess.model.pieces.King;
|
||||
import chess.model.pieces.Knight;
|
||||
import chess.model.pieces.Pawn;
|
||||
import chess.model.pieces.Queen;
|
||||
import chess.model.pieces.Rook;
|
||||
|
||||
public class PieceCost implements PieceVisitor<Integer> {
|
||||
|
||||
private final Color player;
|
||||
|
||||
public PieceCost(Color color) {
|
||||
this.player = color;
|
||||
}
|
||||
|
||||
public int getCost(Piece piece) {
|
||||
if (piece == null)
|
||||
return 0;
|
||||
int cost = visit(piece);
|
||||
if (piece.getColor() == player)
|
||||
cost = -cost;
|
||||
return cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitPiece(Bishop bishop) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitPiece(King king) {
|
||||
return 90;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitPiece(Knight knight) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitPiece(Pawn pawn) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitPiece(Queen queen) {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitPiece(Rook rook) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -57,14 +57,14 @@ public class CommandExecutor {
|
||||
this.dispatcher.onGameEnd();
|
||||
return;
|
||||
}
|
||||
switchPlayerTurn(command instanceof UndoCommand);
|
||||
switchPlayerTurn();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void switchPlayerTurn(boolean undone) {
|
||||
private void switchPlayerTurn() {
|
||||
this.game.switchPlayerTurn();
|
||||
this.dispatcher.onPlayerTurn(this.game.getPlayerTurn(), undone);
|
||||
this.dispatcher.onPlayerTurn(this.game.getPlayerTurn());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,7 +51,7 @@ public class NewGameCommand extends Command {
|
||||
game.reset();
|
||||
|
||||
outputSystem.onGameStart();
|
||||
outputSystem.onPlayerTurn(game.getPlayerTurn(), false);
|
||||
outputSystem.onPlayerTurn(game.getPlayerTurn());
|
||||
|
||||
return CommandResult.NotMoved;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class EmptyGameDispatcher extends GameDispatcher {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(Color color, boolean undone) {
|
||||
public void onPlayerTurn(Color color) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,7 +7,7 @@ import chess.model.Move;
|
||||
public abstract class GameAdaptator implements GameListener {
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(Color color, boolean undone) {}
|
||||
public void onPlayerTurn(Color color) {}
|
||||
|
||||
@Override
|
||||
public void onWin(Color color) {}
|
||||
|
||||
@@ -29,8 +29,8 @@ public class GameDispatcher implements GameListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(Color color, boolean undone) {
|
||||
asyncForEachCall((l) -> l.onPlayerTurn(color, undone));
|
||||
public void onPlayerTurn(Color color) {
|
||||
asyncForEachCall((l) -> l.onPlayerTurn(color));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -56,9 +56,8 @@ public interface GameListener {
|
||||
/**
|
||||
* Invoked when it's the player turn
|
||||
* @param color the color of the player who should play
|
||||
* @param undone true if it's a result of an undo command
|
||||
*/
|
||||
void onPlayerTurn(Color color, boolean undone);
|
||||
void onPlayerTurn(Color color);
|
||||
|
||||
/**
|
||||
* Invoked when a pawn should be promoted
|
||||
|
||||
@@ -20,8 +20,8 @@ public class Game {
|
||||
Draw, Check, CheckMate, OnGoing, Pat;
|
||||
}
|
||||
|
||||
public Game() {
|
||||
this.board = new ChessBoard();
|
||||
public Game(ChessBoard board) {
|
||||
this.board = board;
|
||||
this.movesHistory = new Stack<>();
|
||||
this.traitsPos = new HashMap<>();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import chess.controller.commands.MoveCommand;
|
||||
import chess.controller.commands.NewGameCommand;
|
||||
import chess.controller.commands.PromoteCommand;
|
||||
import chess.controller.event.EmptyGameDispatcher;
|
||||
import chess.model.ChessBoard;
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Game;
|
||||
@@ -21,7 +22,7 @@ import chess.model.pieces.Pawn;
|
||||
public class PgnExport {
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// final Game game = new Game();
|
||||
// final Game game = new Game(new ChessBoard());
|
||||
// final CommandExecutor commandExecutor = new CommandExecutor(game);
|
||||
|
||||
// DumbAI ai1 = new DumbAI(commandExecutor, Color.White);
|
||||
@@ -189,7 +190,8 @@ public class PgnExport {
|
||||
|
||||
public static String exportGame(Game game) {
|
||||
|
||||
Game virtualGame = new Game();
|
||||
ChessBoard board = new ChessBoard();
|
||||
Game virtualGame = new Game(board);
|
||||
|
||||
CommandExecutor executor = new CommandExecutor(virtualGame, new EmptyGameDispatcher());
|
||||
executor.executeCommand(new NewGameCommand());
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package chess.simulator;
|
||||
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Move;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class EnPassantTest extends Simulator{
|
||||
|
||||
public EnPassantTest(CommandExecutor commandExecutor) {
|
||||
super(commandExecutor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<Move> getMoves() {
|
||||
return Arrays.asList(
|
||||
// white pawn
|
||||
new Move(new Coordinate(4, 6), new Coordinate(4, 4)),
|
||||
// black pawn 1
|
||||
new Move(new Coordinate(4, 1), new Coordinate(4, 2)),
|
||||
// white pawn
|
||||
new Move(new Coordinate(4, 4), new Coordinate(4, 3)),
|
||||
// black pawn #2
|
||||
new Move(new Coordinate(3, 1), new Coordinate(3, 3)));
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package chess.view.DDDrender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DDDModel {
|
||||
private final List<VertexArray> vaos;
|
||||
|
||||
public DDDModel(List<VertexArray> vaos) {
|
||||
this.vaos = vaos;
|
||||
}
|
||||
|
||||
public List<VertexArray> getVaos() {
|
||||
return vaos;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package chess.view.DDDrender;
|
||||
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import chess.model.Coordinate;
|
||||
|
||||
class DDDPlacement {
|
||||
static public Vector2f coordinates_to_vector(Coordinate coo) {
|
||||
return new Vector2f(1.0f - 0.125f - coo.getX() * 0.250f, 1.0f - 0.125f - coo.getY() * 0.250f);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package chess.view.DDDrender;
|
||||
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.event.GameAdaptator;
|
||||
|
||||
public class DDDView extends GameAdaptator{
|
||||
|
||||
private final CommandExecutor commandExecutor;
|
||||
private final Window window;
|
||||
private final Renderer renderer;
|
||||
|
||||
public DDDView(CommandExecutor commandExecutor) {
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.renderer = new Renderer();
|
||||
this.window = new Window(commandExecutor, this.renderer);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
this.window.run();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
package chess.view.DDDrender;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.assimp.AIFace.Buffer;
|
||||
import org.lwjgl.assimp.AIMesh;
|
||||
import org.lwjgl.assimp.AINode;
|
||||
import org.lwjgl.assimp.AIScene;
|
||||
import org.lwjgl.assimp.AIVector3D;
|
||||
import org.lwjgl.assimp.Assimp;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import chess.view.AssetManager;
|
||||
|
||||
public class ModelLoader {
|
||||
|
||||
private static final int VERTEX_SIZE = 3;
|
||||
private static final int UV_SIZE = 2;
|
||||
private static final int VERTEX_POSITION_INDEX = 0;
|
||||
private static final int VERTEX_UV_INDEX = 1;
|
||||
private static final int VERTEX_NORMAL_INDEX = 2;
|
||||
|
||||
private static float[] toFloatArray(List<Float> list) {
|
||||
float[] result = new float[list.size()];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
result[i] = list.get(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] toIntArray(List<Integer> list) {
|
||||
int[] result = new int[list.size()];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
result[i] = list.get(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static VertexArray processMesh(AIMesh mesh, AIScene scene) {
|
||||
List<Float> positions = new ArrayList<>();
|
||||
List<Float> textureCoords = new ArrayList<>();
|
||||
List<Float> normals = new ArrayList<>();
|
||||
|
||||
List<Integer> indicies = new ArrayList<>();
|
||||
|
||||
Buffer faces = mesh.mFaces();
|
||||
int faceNumber = mesh.mNumFaces();
|
||||
|
||||
for (int i = 0; i < faceNumber; i++) {
|
||||
int offset = indicies.size();
|
||||
int numIndices = faces.get(i).mNumIndices();
|
||||
IntBuffer faceIndicies = faces.get(i).mIndices();
|
||||
// IntStream.of(faceIndicies.array()).forEach(indicies::add);
|
||||
for (int j = 0; j < faceIndicies.capacity(); j++) {
|
||||
indicies.add(faceIndicies.get(j));
|
||||
}
|
||||
}
|
||||
|
||||
int vertNumber = mesh.mNumVertices();
|
||||
org.lwjgl.assimp.AIVector3D.Buffer vertecies = mesh.mVertices();
|
||||
for (int i = 0; i < vertNumber; i++) {
|
||||
AIVector3D vertex = vertecies.get(i);
|
||||
positions.add(vertex.x());
|
||||
positions.add(vertex.y());
|
||||
positions.add(vertex.z());
|
||||
}
|
||||
|
||||
org.lwjgl.assimp.AIVector3D.Buffer vertexNormals = mesh.mNormals();
|
||||
for (int i = 0; i < vertNumber; i++) {
|
||||
AIVector3D normal = vertexNormals.get(i);
|
||||
normals.add(normal.x());
|
||||
normals.add(normal.y());
|
||||
normals.add(normal.z());
|
||||
}
|
||||
|
||||
PointerBuffer vertexTexture = mesh.mTextureCoords();
|
||||
for (int i = 0; i < vertNumber; i++) {
|
||||
// PointerBuffer buff = mesh.mTextureCoords();
|
||||
// textureCoords.add(buff.get(i).x());
|
||||
// textureCoords.add(buff.get(i).y());
|
||||
}
|
||||
|
||||
VertexBuffer positionVBO = new VertexBuffer(toFloatArray(positions), VERTEX_SIZE);
|
||||
positionVBO.AddVertexAttribPointer(VERTEX_POSITION_INDEX, VERTEX_SIZE, 0);
|
||||
VertexBuffer textureVBO = new VertexBuffer(toFloatArray(textureCoords), UV_SIZE);
|
||||
textureVBO.AddVertexAttribPointer(VERTEX_UV_INDEX, UV_SIZE, 0);
|
||||
VertexBuffer normalVBO = new VertexBuffer(toFloatArray(normals), VERTEX_SIZE);
|
||||
normalVBO.AddVertexAttribPointer(VERTEX_NORMAL_INDEX, VERTEX_SIZE, 0);
|
||||
|
||||
VertexArray vao = new VertexArray(new ElementBuffer(toIntArray(indicies)));
|
||||
vao.Bind();
|
||||
vao.BindVertexBuffer(positionVBO);
|
||||
vao.BindVertexBuffer(textureVBO);
|
||||
vao.BindVertexBuffer(normalVBO);
|
||||
vao.Unbind();
|
||||
return vao;
|
||||
|
||||
}
|
||||
|
||||
private static void processNode(AINode node, AIScene scene, List<VertexArray> meshes) {
|
||||
for (int i = 0; i < node.mNumChildren(); i++) {
|
||||
AINode child = AINode.create(node.mChildren().get(i));
|
||||
processNode(child, scene, meshes);
|
||||
}
|
||||
for (int i = 0; i < node.mNumMeshes(); i++) {
|
||||
AIMesh mesh = AIMesh.create(scene.mMeshes().get(node.mMeshes().get(i)));
|
||||
meshes.add(processMesh(mesh, scene));
|
||||
}
|
||||
}
|
||||
|
||||
public static DDDModel loadModel(String filename) throws IOException {
|
||||
InputStream input = AssetManager.getResource(filename);
|
||||
byte[] buffer = input.readAllBytes();
|
||||
ByteBuffer data = MemoryUtil.memCalloc(buffer.length);
|
||||
data.put(buffer);
|
||||
data.flip();
|
||||
|
||||
AIScene scene = Assimp.aiImportFileFromMemory(
|
||||
data,
|
||||
Assimp.aiProcess_Triangulate | Assimp.aiProcess_PreTransformVertices | Assimp.aiProcess_GlobalScale
|
||||
| Assimp.aiProcess_ValidateDataStructure,
|
||||
"");
|
||||
|
||||
if (scene == null)
|
||||
System.err.println(Assimp.aiGetErrorString());
|
||||
|
||||
List<VertexArray> vertecies = new ArrayList<>();
|
||||
|
||||
processNode(scene.mRootNode(), scene, vertecies);
|
||||
|
||||
MemoryUtil.memFree(data);
|
||||
|
||||
return new DDDModel(vertecies);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package chess.view.DDDrender;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import chess.model.Color;
|
||||
import chess.model.Piece;
|
||||
import chess.model.PieceVisitor;
|
||||
import chess.model.pieces.Bishop;
|
||||
import chess.model.pieces.King;
|
||||
import chess.model.pieces.Knight;
|
||||
import chess.model.pieces.Pawn;
|
||||
import chess.model.pieces.Queen;
|
||||
import chess.model.pieces.Rook;
|
||||
|
||||
public class PieceModel implements PieceVisitor<String> {
|
||||
|
||||
private static final String basePath = "3d/";
|
||||
private static final Map<String, DDDModel> cache = new HashMap<>();
|
||||
|
||||
public DDDModel getModel(Piece piece) throws IOException {
|
||||
if (piece == null)
|
||||
return null;
|
||||
|
||||
String path = basePath + colorToString(piece.getColor()) + "-" + visit(piece) + ".fbx";
|
||||
return getModel(path);
|
||||
}
|
||||
|
||||
private DDDModel getModel(String path) throws IOException {
|
||||
DDDModel model = cache.get(path);
|
||||
if (model != null)
|
||||
return model;
|
||||
|
||||
model = ModelLoader.loadModel(path);
|
||||
cache.put(path, model);
|
||||
return model;
|
||||
}
|
||||
|
||||
private String colorToString(Color color) {
|
||||
return color == Color.Black ? "black" : "white";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitPiece(Bishop bishop) {
|
||||
return "bishop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitPiece(King king) {
|
||||
return "king";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitPiece(Knight knight) {
|
||||
return "knight";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitPiece(Pawn pawn) {
|
||||
return "pawn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitPiece(Queen queen) {
|
||||
return "queen";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitPiece(Rook rook) {
|
||||
return "rook";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package chess.view.DDDrender;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Piece;
|
||||
import chess.view.DDDrender.shader.BoardShader;
|
||||
import chess.view.DDDrender.shader.PieceShader;
|
||||
import chess.view.DDDrender.shader.ShaderProgram;
|
||||
|
||||
public class Renderer {
|
||||
private BoardShader boardShader;
|
||||
private PieceShader pieceShader;
|
||||
private VertexArray boardVao;
|
||||
private final PieceModel models;
|
||||
|
||||
private static final Vector3f BLACK = new Vector3f(0.1f, 0.1f, 0.1f);
|
||||
private static final Vector3f WHITE = new Vector3f(0.7f, 0.7f, 0.7f);
|
||||
|
||||
public Renderer() {
|
||||
this.boardShader = new BoardShader();
|
||||
this.pieceShader = new PieceShader();
|
||||
this.models = new PieceModel();
|
||||
}
|
||||
|
||||
public void Init() {
|
||||
boardShader.LoadShader();
|
||||
pieceShader.LoadShader();
|
||||
this.boardVao = BoardModelLoader.GetBoardModel();
|
||||
}
|
||||
|
||||
public void RenderPiece(Piece piece, Coordinate pos) {
|
||||
try {
|
||||
DDDModel pieceModel = this.models.getModel(piece);
|
||||
Render(pieceModel, piece.getColor() == Color.White ? WHITE : BLACK, DDDPlacement.coordinates_to_vector(pos),
|
||||
piece.getColor() == Color.White ? 0.0f : 3.14f);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(Camera cam) {
|
||||
this.boardShader.Start();
|
||||
this.boardShader.SetCamMatrix(cam.getMatrix());
|
||||
this.pieceShader.Start();
|
||||
this.pieceShader.SetCamMatrix(cam.getMatrix());
|
||||
RenderVao(this.boardShader, this.boardVao);
|
||||
}
|
||||
|
||||
public void Render(DDDModel model, Vector3f color, Vector2f position, float rotation) {
|
||||
Vector3f realPos = new Vector3f(position.x(), 0, position.y());
|
||||
this.pieceShader.Start();
|
||||
this.pieceShader.setModelColor(color);
|
||||
this.pieceShader.setModelTransform(new Matrix4f().translate(realPos).rotate(rotation, new Vector3f(0, 1, 0)));
|
||||
Render(model);
|
||||
}
|
||||
|
||||
public void Render(DDDModel model) {
|
||||
for (int i = 0; i < model.getVaos().size(); i++) {
|
||||
VertexArray vao = model.getVaos().get(i);
|
||||
RenderVao(this.pieceShader, vao);
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderVao(ShaderProgram shader, VertexArray vertexArray) {
|
||||
shader.Start();
|
||||
vertexArray.Bind();
|
||||
GL30.glDrawElements(GL30.GL_TRIANGLES, vertexArray.GetVertexCount(), GL_UNSIGNED_INT, 0);
|
||||
vertexArray.Unbind();
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package chess.view.DDDrender.shader;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class PieceShader extends ShaderProgram {
|
||||
|
||||
private static String vertexShader = """
|
||||
#version 330
|
||||
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in vec2 uv;
|
||||
layout(location = 2) in vec3 normal;
|
||||
|
||||
uniform mat4 camMatrix;
|
||||
uniform mat4 modelTransform;
|
||||
uniform vec3 lightPosition = vec3(0, 1, 0);
|
||||
|
||||
out vec3 toLightVector;
|
||||
out vec3 surfaceNormal;
|
||||
|
||||
void main(void){
|
||||
vec4 worldPos = modelTransform * vec4(position, 1.0);
|
||||
|
||||
toLightVector = lightPosition - worldPos.xyz;
|
||||
surfaceNormal = (modelTransform * vec4(normal, 0.0)).xyz;
|
||||
|
||||
gl_Position = camMatrix * worldPos;
|
||||
}
|
||||
""";
|
||||
|
||||
private static String fragmentShader = """
|
||||
#version 330
|
||||
|
||||
in vec3 toLightVector;
|
||||
in vec3 surfaceNormal;
|
||||
|
||||
uniform vec3 modelColor = vec3(1, 1, 1);
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main(void){
|
||||
vec3 unitNormal = normalize(surfaceNormal);
|
||||
vec3 unitLightVector = normalize(toLightVector);
|
||||
|
||||
float diffuse = max(0.5, dot(unitNormal, unitLightVector));
|
||||
|
||||
float brightness = diffuse;
|
||||
|
||||
out_color = vec4(modelColor, 1.0) * brightness;
|
||||
out_color.w = 1.0;
|
||||
|
||||
}
|
||||
""";
|
||||
|
||||
private int location_CamMatrix = 0;
|
||||
private int location_ModelTransform = 0;
|
||||
private int location_ModelColor = 0;
|
||||
|
||||
public PieceShader() {
|
||||
|
||||
}
|
||||
|
||||
public void LoadShader() {
|
||||
super.LoadProgram(vertexShader, fragmentShader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void GetAllUniformLocation() {
|
||||
location_CamMatrix = GetUniformLocation("camMatrix");
|
||||
location_ModelTransform = GetUniformLocation("modelTransform");
|
||||
location_ModelColor = GetUniformLocation("modelColor");
|
||||
}
|
||||
|
||||
public void SetCamMatrix(Matrix4f mat) {
|
||||
LoadMat4(location_CamMatrix, mat);
|
||||
}
|
||||
|
||||
public void setModelTransform(Matrix4f mat) {
|
||||
LoadMat4(location_ModelTransform, mat);
|
||||
}
|
||||
|
||||
public void setModelColor(Vector3f color) {
|
||||
LoadVector(location_ModelColor, color);
|
||||
}
|
||||
}
|
||||
@@ -20,17 +20,12 @@ public class Console implements GameListener {
|
||||
private final Scanner scanner = new Scanner(System.in);
|
||||
private final CommandExecutor commandExecutor;
|
||||
private final ConsolePieceName consolePieceName = new ConsolePieceName();
|
||||
private boolean captureInput;
|
||||
private boolean captureInput = false;
|
||||
private final ExecutorService executor;
|
||||
|
||||
public Console(CommandExecutor commandExecutor, boolean captureInput) {
|
||||
public Console(CommandExecutor commandExecutor) {
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.executor = Executors.newSingleThreadExecutor();
|
||||
this.captureInput = captureInput;
|
||||
}
|
||||
|
||||
public Console(CommandExecutor commandExecutor) {
|
||||
this(commandExecutor, true);
|
||||
}
|
||||
|
||||
private Piece pieceAt(int x, int y) {
|
||||
@@ -66,7 +61,7 @@ public class Console implements GameListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(Color color, boolean undone) {
|
||||
public void onPlayerTurn(Color color) {
|
||||
if (!captureInput)
|
||||
return;
|
||||
System.out.println(Colors.RED + "Player turn: " + color + Colors.RESET);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class Camera {
|
||||
public static final float fov = 70.0f;
|
||||
// should be changed to match screen
|
||||
public static final float aspect = 1.0f;
|
||||
public static final float zNear = 0.01f;
|
||||
public static final float zFar = 1000.0f;
|
||||
|
||||
private float aspectRatio;
|
||||
public static final float zFar = 100.0f;
|
||||
|
||||
private Vector3f pos;
|
||||
|
||||
@@ -16,7 +16,7 @@ public class Camera {
|
||||
private float pitch = 0.0f;
|
||||
|
||||
public Camera() {
|
||||
this.pos = new Vector3f(1.5f, 1.5f, 0);
|
||||
this.pos = new Vector3f(0, 2.0f, 0);
|
||||
setRotation(0.0f, -3.14150f / 2.0f);
|
||||
}
|
||||
|
||||
@@ -115,13 +115,14 @@ public class Camera {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public void setAspectRatio(float aspectRatio) {
|
||||
this.aspectRatio = aspectRatio;
|
||||
}
|
||||
|
||||
public Matrix4f getMatrix() {
|
||||
Vector3f forward = new Vector3f(
|
||||
(float) (Math.cos(yaw) * Math.cos(pitch)),
|
||||
(float) (Math.sin(pitch)),
|
||||
(float) (Math.sin(yaw) * Math.cos(pitch)));
|
||||
|
||||
return new Matrix4f()
|
||||
.perspective((float) (Math.toRadians(fov)), aspectRatio, zNear, zFar)
|
||||
.lookAt(pos, new Vector3f(0.0f, 0, 0), new Vector3f(0.0f, 1.0f, 0.0f));
|
||||
.perspective((float) (Math.toRadians(fov)), aspect, zNear, zFar)
|
||||
.lookAt(pos, forward, new Vector3f(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.opengl.*;
|
||||
|
||||
public class BoardModelLoader {
|
||||
import chess.model.Coordinate;
|
||||
import chess.view.render.shader.BoardShader;
|
||||
|
||||
import static org.lwjgl.opengl.GL30.*;
|
||||
|
||||
public class Renderer {
|
||||
private BoardShader shader;
|
||||
private VertexArray vao;
|
||||
|
||||
private static int BOARD_WIDTH = 8;
|
||||
private static int BOARD_HEIGHT = 8;
|
||||
private static int BOARD_SIZE = BOARD_WIDTH * BOARD_HEIGHT;
|
||||
private static int SQUARE_VERTEX_COUNT = 4;
|
||||
|
||||
private static float[] GetBoardPositions() {
|
||||
public Renderer() {
|
||||
this.shader = new BoardShader();
|
||||
}
|
||||
|
||||
public void Init() {
|
||||
shader.LoadShader();
|
||||
InitBoard();
|
||||
}
|
||||
|
||||
private float[] GetBoardPositions() {
|
||||
float[] positions = new float[BOARD_SIZE * SQUARE_VERTEX_COUNT * 3];
|
||||
for (int i = 0; i < BOARD_WIDTH; i++) {
|
||||
for (int j = 0; j < BOARD_HEIGHT; j++) {
|
||||
@@ -43,16 +60,42 @@ public class BoardModelLoader {
|
||||
return positions;
|
||||
}
|
||||
|
||||
private static float[] GetBoardColors() {
|
||||
private Coordinate GetCellFromColor(Vector3f color) {
|
||||
int offset = 1;
|
||||
|
||||
if (color.x > 0.5) {
|
||||
color = new Vector3f(1.0f, 1.0f, 1.0f).sub(color);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
int r = (int) (color.x * 255.0f);
|
||||
int g = (int) (color.y * 255.0f);
|
||||
int b = (int) (color.z * 255.0f);
|
||||
|
||||
int index = (r + g + b) * 2 + offset;
|
||||
|
||||
return Coordinate.fromIndex(index);
|
||||
}
|
||||
|
||||
private Vector3f GetCellColor(int x, int y) {
|
||||
float index = (y * BOARD_WIDTH + x) / 2.0f;
|
||||
float r = (int) (index / 3) / 255.0f;
|
||||
float g = (int) ((index + 1) / 3) / 255.0f;
|
||||
float b = (int) ((index + 2) / 3) / 255.0f;
|
||||
if ((x + y) % 2 != 0) {
|
||||
System.out.println(GetCellFromColor(new Vector3f(1.0f - r - 1.0f / 255.0f, 1.0f - g - 1.0f / 255.0f, 1.0f - b - 1.0f / 255.0f)));
|
||||
return new Vector3f(1.0f - r - 1.0f / 255.0f, 1.0f - g - 1.0f / 255.0f, 1.0f - b - 1.0f / 255.0f);
|
||||
} else {
|
||||
System.out.println(GetCellFromColor(new Vector3f(r, g, b)));
|
||||
return new Vector3f(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
private float[] GetBoardColors() {
|
||||
float[] colors = new float[BOARD_SIZE * SQUARE_VERTEX_COUNT * 3];
|
||||
for (int i = 0; i < BOARD_WIDTH; i++) {
|
||||
for (int j = 0; j < BOARD_HEIGHT; j++) {
|
||||
Vector3f color;
|
||||
if ((i + j) % 2 == 0) {
|
||||
color = new Vector3f(1.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
color = new Vector3f(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
for (int j = 0; j < BOARD_HEIGHT; j++) {
|
||||
for (int i = 0; i < BOARD_WIDTH; i++) {
|
||||
Vector3f color = GetCellColor(i, j);
|
||||
int squareIndex = i * BOARD_WIDTH + j;
|
||||
for (int k = 0; k < SQUARE_VERTEX_COUNT; k++) {
|
||||
colors[squareIndex * SQUARE_VERTEX_COUNT * 3 + k * 3] = color.x;
|
||||
@@ -64,7 +107,7 @@ public class BoardModelLoader {
|
||||
return colors;
|
||||
}
|
||||
|
||||
private static int[] GetBoardIndicies() {
|
||||
private int[] GetBoardIndicies() {
|
||||
int[] indices = new int[BOARD_SIZE * 6];
|
||||
for (int i = 0; i < BOARD_SIZE; i++) {
|
||||
indices[i * 6] = i * 4;
|
||||
@@ -77,9 +120,9 @@ public class BoardModelLoader {
|
||||
return indices;
|
||||
}
|
||||
|
||||
public static VertexArray GetBoardModel() {
|
||||
private void InitBoard() {
|
||||
ElementBuffer eBuffer = new ElementBuffer(GetBoardIndicies());
|
||||
VertexArray vao = new VertexArray(eBuffer);
|
||||
this.vao = new VertexArray(eBuffer);
|
||||
|
||||
VertexBuffer positionBuffer = new VertexBuffer(GetBoardPositions(), 3);
|
||||
positionBuffer.AddVertexAttribPointer(0, 3, 0);
|
||||
@@ -87,10 +130,28 @@ public class BoardModelLoader {
|
||||
VertexBuffer colorBuffer = new VertexBuffer(GetBoardColors(), 3);
|
||||
colorBuffer.AddVertexAttribPointer(1, 3, 0);
|
||||
|
||||
vao.Bind();
|
||||
vao.BindVertexBuffer(positionBuffer);
|
||||
vao.BindVertexBuffer(colorBuffer);
|
||||
vao.Unbind();
|
||||
return vao;
|
||||
this.vao.Bind();
|
||||
this.vao.BindVertexBuffer(positionBuffer);
|
||||
this.vao.BindVertexBuffer(colorBuffer);
|
||||
this.vao.Unbind();
|
||||
}
|
||||
|
||||
public Coordinate GetSelectedCell() {
|
||||
float pixels[] = new float[3];
|
||||
GL30.glReadPixels(500, 500, 1, 1, GL_RGB, GL_FLOAT, pixels);
|
||||
return GetCellFromColor(new Vector3f(pixels[0], pixels[1], pixels[2]));
|
||||
}
|
||||
|
||||
public void Render(Camera cam) {
|
||||
this.shader.Start();
|
||||
this.shader.SetCamMatrix(cam.getMatrix());
|
||||
RenderVao(vao);
|
||||
}
|
||||
|
||||
public void RenderVao(VertexArray vertexArray) {
|
||||
this.shader.Start();
|
||||
vertexArray.Bind();
|
||||
GL30.glDrawElements(GL30.GL_TRIANGLES, vertexArray.GetVertexCount(), GL_UNSIGNED_INT, 0);
|
||||
vertexArray.Unbind();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -1,4 +1,4 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
public record VertexAttribPointer(int index, int size, int offset) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_FLOAT;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package chess.view.DDDrender;
|
||||
package chess.view.render;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.*;
|
||||
import org.lwjgl.glfw.*;
|
||||
import org.lwjgl.opengl.*;
|
||||
import org.lwjgl.system.*;
|
||||
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.GetPieceAtCommand;
|
||||
import chess.controller.event.GameListener;
|
||||
import chess.model.Color;
|
||||
import chess.model.Coordinate;
|
||||
import chess.model.Piece;
|
||||
import chess.model.Move;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.*;
|
||||
|
||||
import static org.lwjgl.glfw.Callbacks.*;
|
||||
@@ -20,19 +19,20 @@ import static org.lwjgl.opengl.GL11.*;
|
||||
import static org.lwjgl.system.MemoryStack.*;
|
||||
import static org.lwjgl.system.MemoryUtil.*;
|
||||
|
||||
public class Window {
|
||||
public class Window implements GameListener{
|
||||
|
||||
// The window handle
|
||||
private long window;
|
||||
|
||||
private Renderer renderer;
|
||||
private Camera cam;
|
||||
private final CommandExecutor commandExecutor;
|
||||
|
||||
public Window(CommandExecutor commandExecutor, Renderer renderer) {
|
||||
private Renderer renderer;
|
||||
private Camera cam;
|
||||
|
||||
public Window(CommandExecutor commandExecutor) {
|
||||
this.renderer = new Renderer();
|
||||
this.cam = new Camera();
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.commandExecutor = new CommandExecutor();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
@@ -97,35 +97,8 @@ public class Window {
|
||||
}
|
||||
|
||||
private void render() {
|
||||
final float angle = 0.01f;
|
||||
float x = cam.getPos().x();
|
||||
float y = cam.getPos().z();
|
||||
cam.setPosition(new Vector3f(x * (float) Math.cos(angle) - y * (float) Math.sin(angle), 1.0f,
|
||||
x * (float) Math.sin(angle) + y * (float) Math.cos(angle)));
|
||||
int width[] = new int[1];
|
||||
int height[] = new int[1];
|
||||
glfwGetWindowSize(window, width, height);
|
||||
cam.setAspectRatio((float) width[0] / (float) height[0]);
|
||||
cam.rotate(0.01f, 0.01f);
|
||||
renderer.Render(cam);
|
||||
renderPieces();
|
||||
}
|
||||
|
||||
private Piece pieceAt(Coordinate pos) {
|
||||
GetPieceAtCommand cmd = new GetPieceAtCommand(pos);
|
||||
this.commandExecutor.executeCommand(cmd);
|
||||
return cmd.getPiece();
|
||||
}
|
||||
|
||||
private void renderPieces() {
|
||||
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
||||
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
||||
Coordinate pos = new Coordinate(i, j);
|
||||
Piece piece = pieceAt(pos);
|
||||
if (piece == null)
|
||||
continue;
|
||||
this.renderer.RenderPiece(pieceAt(pos), pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loop() {
|
||||
@@ -139,9 +112,7 @@ public class Window {
|
||||
renderer.Init();
|
||||
|
||||
// Set the clear color
|
||||
glClearColor(0.4f, 0.4f, 0.6f, 1.0f);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
@@ -152,6 +123,8 @@ public class Window {
|
||||
|
||||
render();
|
||||
|
||||
System.out.println(this.renderer.GetSelectedCell());
|
||||
|
||||
glfwSwapBuffers(window); // swap the color buffers
|
||||
|
||||
// Poll for window events. The key callback above will only be
|
||||
@@ -170,4 +143,82 @@ public class Window {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBoardUpdate() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onBoardUpdate'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onDraw'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameEnd() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onGameEnd'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameStart() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onGameStart'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKingInCheck() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onKingInCheck'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKingInMat() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onKingInMat'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMove(Move move) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onMove'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveNotAllowed(Move move) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onMoveNotAllowed'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatSituation() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onPatSituation'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(Color color) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onPlayerTurn'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPromotePawn(Coordinate pieceCoords) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onPromotePawn'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurrender(Color coward) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onSurrender'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWin(Color winner) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onWin'");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package chess.view.DDDrender.shader;
|
||||
package chess.view.render.shader;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
@@ -11,19 +11,13 @@ public class BoardShader extends ShaderProgram {
|
||||
layout(location = 1) in vec3 color;
|
||||
|
||||
uniform mat4 camMatrix;
|
||||
uniform vec3 lightPosition;
|
||||
|
||||
flat out vec3 pass_color;
|
||||
out vec3 toLightVector;
|
||||
|
||||
void main(void){
|
||||
gl_Position = camMatrix * vec4(position, 1.0);
|
||||
|
||||
toLightVector = lightPosition - position;
|
||||
|
||||
pass_color = color;
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
private static String fragmentShader = """
|
||||
@@ -31,34 +25,11 @@ public class BoardShader extends ShaderProgram {
|
||||
|
||||
flat in vec3 pass_color;
|
||||
|
||||
in vec3 toLightVector;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main(void){
|
||||
const float shineDamper = 10.0;
|
||||
const float reflectivity = 1.0;
|
||||
|
||||
float lightDistance = length(toLightVector);
|
||||
|
||||
const vec3 attenuation = vec3(0.3, 0.03, 0);
|
||||
float attenuationFactor = attenuation.x + attenuation.y * lightDistance + attenuation.z * lightDistance * lightDistance;
|
||||
|
||||
vec3 unitNormal = vec3(0, 1, 0);
|
||||
vec3 unitLightVector = normalize(toLightVector);
|
||||
|
||||
vec3 lightDirection = -unitLightVector;
|
||||
vec3 reflectedLightDirection = reflect(lightDirection, unitNormal);
|
||||
|
||||
float diffuse = max(0.2, dot(unitNormal, unitLightVector));
|
||||
|
||||
float brightness = diffuse / attenuationFactor;
|
||||
|
||||
out_color = brightness * vec4(pass_color, 1.0);
|
||||
out_color.w = 1.0;
|
||||
|
||||
out_color = vec4(pass_color, 1.0);
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
private int location_CamMatrix = 0;
|
||||
@@ -1,4 +1,4 @@
|
||||
package chess.view.DDDrender.shader;
|
||||
package chess.view.render.shader;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
@@ -213,7 +213,7 @@ public class Window extends JFrame implements GameListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTurn(chess.model.Color color, boolean undone) {
|
||||
public void onPlayerTurn(chess.model.Color color) {
|
||||
this.displayText.setText("Current turn: " + color);
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,20 +3,24 @@
|
||||
*/
|
||||
package chess;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import chess.ai.DumbAI;
|
||||
import chess.controller.Command;
|
||||
import chess.controller.CommandExecutor;
|
||||
import chess.controller.commands.NewGameCommand;
|
||||
import chess.controller.commands.UndoCommand;
|
||||
import chess.controller.event.GameAdaptator;
|
||||
import chess.model.Color;
|
||||
import chess.model.Game;
|
||||
import chess.model.*;
|
||||
import chess.model.pieces.*;
|
||||
import chess.simulator.Simulator;
|
||||
import chess.view.simplerender.Window;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
class AppTest {
|
||||
@Test void functionalRollback(){
|
||||
Game game = new Game();
|
||||
Game game = new Game(new ChessBoard());
|
||||
CommandExecutor commandExecutor = new CommandExecutor(game);
|
||||
|
||||
DumbAI ai = new DumbAI(commandExecutor, Color.Black);
|
||||
@@ -34,9 +38,9 @@ class AppTest {
|
||||
result = commandExecutor.executeCommand(new UndoCommand());
|
||||
} while (result != Command.CommandResult.NotAllowed);
|
||||
|
||||
Game initialGame = new Game();
|
||||
Game initialGame = new Game(new ChessBoard());
|
||||
CommandExecutor initialCommandExecutor = new CommandExecutor(initialGame);
|
||||
initialCommandExecutor.executeCommand(new NewGameCommand());
|
||||
commandExecutor.executeCommand(new NewGameCommand());
|
||||
|
||||
assert(game.getBoard().equals(initialGame.getBoard()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user