Commit 6856a143 authored by Anders H. Rebner's avatar Anders H. Rebner
Browse files

Pieces are movable through UI, model pieces instantiated

parent d7d11ca6
......@@ -72,6 +72,8 @@ public class UniCheckersClient extends ApplicationAdapter {
//gvm.push(new CinematicView(gvm, playerController, assetManager, stage, skin));
PlayView playView = new PlayView(gvm, playerController, assetManager, stage, skin, null);
gameController = new GameController(model, playView);
playView.setGameController(gameController);
gvm.push(playView);
}
......
......@@ -4,36 +4,55 @@ import com.badlogic.gdx.math.Vector3;
import com.mygdx.game.model.Game;
import com.mygdx.game.views.Constants;
import com.mygdx.game.views.PlayView;
import java.util.ArrayList;
import java.util.List;
import com.mygdx.game.views.tokens.StarPiece;
public class GameController {
private Game model;
private PlayView view;
private final Game model;
private final PlayView view;
Float HEX_SIDE_LENGTH;
private StarPiece activePiece; // Previously clicked piece
private Vector3 previousCoordinateClicked; // Previously clicked coordinate
public GameController(Game model, PlayView view) {
this.model = model;
this.view = view;
this.HEX_SIDE_LENGTH = Constants.HEX_SIDE_LENGTH;
List<List<Vector3>> startFieldCoordinates = this.model.getStartFieldCoordinates();
List<List<Float[]>> startFieldCoordinatesPixel = new ArrayList<>();
this.activePiece = null;
this.previousCoordinateClicked = null;
for (List<Vector3> coordinateSet : startFieldCoordinates) {
List<Float[]> coordinateSetPixel = new ArrayList<>();
this.view.initializePieces(this.model.getStartFieldCoordinates());
}
for (Vector3 coordinate : coordinateSet) {
coordinateSetPixel.add(UtilsKt.cubeToPixel(coordinate, HEX_SIDE_LENGTH));
public void handleClick(float x, float y) {
Vector3 cubeCoordinates = UtilsKt.pixelToCube(x, y, Constants.HEX_SIDE_LENGTH);
// If field exists at clicked coordinates
if (this.model.fieldExists(cubeCoordinates)) {
// If field has piece
if (this.model.fieldHasPiece(cubeCoordinates)) {
// If another piece is already active, deactivate it
if (activePiece != null) {
activePiece.setRotateHead(false);
}
// TODO: Check if the piece is owned by this player
activePiece = this.view.getPiece(cubeCoordinates);
activePiece.setRotateHead(true);
previousCoordinateClicked = cubeCoordinates;
} else { // Field does NOT have piece
if (activePiece != null) {
// TODO: Check if it is the players turn (could be done in model)
// Try to move piece in model, if successful, move piece in view
if (this.model.movePiece(previousCoordinateClicked, cubeCoordinates)) {
this.view.movePiece(activePiece, cubeCoordinates);
activePiece.setRotateHead(false);
activePiece = null;
previousCoordinateClicked = null;
// TODO: Check if all pieces are in goal?
} else {
// TODO: Give feedback (move was not valid/not executed)
}
}
}
startFieldCoordinatesPixel.add(coordinateSetPixel);
}
this.view.initializePieces(startFieldCoordinatesPixel);
}
}
......@@ -2,6 +2,7 @@ package com.mygdx.game.controllers
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.math.Vector3
import kotlin.math.roundToInt
import kotlin.math.sqrt
// https://stackoverflow.com/questions/2459402/hexagonal-grid-coordinates-to-pixel-coordinates
......@@ -20,15 +21,15 @@ fun cubeToPixel(vector: Vector3, hexSideLength: Float = 1F): Array<Float> {
return arrayOf(pixelX, pixelY)
}
fun pixelToCube(x: Float, y: Float, hexSideLength: Float= 1F) : Vector3 {
val cubeX = (sqrt(3F) / 3F * x - y / 3F) / hexSideLength
val cubeY = -(sqrt(3F) / 3F * x + y / 3F) / hexSideLength
val cubeZ = 2F / 3F * y / hexSideLength
fun pixelToCube(x: Float, y: Float, hexSideLength: Float = 1F) : Vector3 {
val cubeX = ((sqrt(3F) / 3F * x - y / 3F) / hexSideLength).roundToInt()
val cubeY = (-(sqrt(3F) / 3F * x + y / 3F) / hexSideLength).roundToInt()
val cubeZ = (2F / 3F * y / hexSideLength).roundToInt()
return Vector3(cubeX, cubeY, cubeZ)
return Vector3(cubeX.toFloat(), cubeY.toFloat(), cubeZ.toFloat())
}
fun pixelToCube(vector: Vector2, hexSideLength: Float= 1F) : Array<Float> {
fun pixelToCube(vector: Vector2, hexSideLength: Float = 1F) : Array<Float> {
val x = vector.x
val y = vector.y
......@@ -37,4 +38,4 @@ fun pixelToCube(vector: Vector2, hexSideLength: Float= 1F) : Array<Float> {
val cubeZ = 2F / 3F * y / hexSideLength
return arrayOf(cubeX, cubeY, cubeZ)
}
\ No newline at end of file
}
......@@ -24,6 +24,10 @@ class Field {
return this.piece
}
fun hasPiece(): Boolean {
return this.piece != null
}
fun removePiece() {
this.piece = null
}
......
......@@ -16,4 +16,19 @@ class Game(gameState: GameState) {
fun getStartFieldCoordinates(): List<List<Vector3>>? {
return this.gameState.getRules()?.generateStartFields()
}
fun fieldExists(cubeCoordinates: Vector3): Boolean {
return this.gameState.getBoardState()?.fieldExists(cubeCoordinates) ?: false
}
fun fieldHasPiece(cubeCoordinates: Vector3): Boolean {
print(this.gameState.getBoardState()?.fields?.get(cubeCoordinates)?.hasPiece())
return this.gameState.getBoardState()?.fields?.get(cubeCoordinates)?.hasPiece() == true
}
fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean {
// TODO: Check if valid move
return this.gameState.getBoardState()?.movePiece(fromCoordinates, toCoordinates) ?: false
}
}
\ No newline at end of file
package com.mygdx.game.model
import com.mygdx.game.model.gamemodes.rules.DefaultRules
/*
Holds the state of the game and all data related to this.
*/
......@@ -17,6 +19,7 @@ class GameState(gameMode: GameMode? = null) {
} else {
this.rules = gameMode.getRules()
this.boardState = gameMode.getBoard()
this.rules?.let { this.boardState?.placePiecesAtStart(this.rules!!, it.generateStartFields()) }
}
this.isStarted = false
this.winner = null
......@@ -24,6 +27,7 @@ class GameState(gameMode: GameMode? = null) {
fun setBoardState(boardState: AbstractBoard) {
this.boardState = boardState
this.rules?.let { this.boardState!!.placePiecesAtStart(this.rules!!, it.generateStartFields()) }
}
fun getBoardState(): AbstractBoard? {
......
......@@ -8,4 +8,6 @@ abstract class AbstractBoard {
abstract fun computeFields() // Computes all fields on the board
abstract fun fieldExists(coordinates: Vector3): Boolean
abstract fun placePiecesAtStart(rules: AbstractRules, startFieldCoordinates: List<List<Vector3>>)
abstract fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean
}
\ No newline at end of file
//General board class
package com.mygdx.game.model
import com.badlogic.gdx.math.Vector3
import java.lang.Integer.max
import java.lang.Integer.min
......@@ -18,7 +19,7 @@ class DefaultBoard: AbstractBoard() {
val z = -x - y
val coordinates = Vector3(x.toFloat(), y.toFloat(), z.toFloat())
if (!fieldExists(coordinates)) {
if (!fieldShouldBeAddedToBoard(coordinates)) {
continue@loop
}
fields[coordinates] = Field()
......@@ -26,7 +27,34 @@ class DefaultBoard: AbstractBoard() {
}
}
override fun fieldExists(coordinates: Vector3) : Boolean {
override fun placePiecesAtStart(rules: AbstractRules, startFieldCoordinates: List<List<Vector3>>) {
var playerId = 0
for (coordinateSet: List<Vector3> in startFieldCoordinates) {
val player = Player(playerId++)
for (coordinate: Vector3 in coordinateSet) {
val piece = Piece(player)
fields[coordinate]?.setPiece(piece)
}
}
}
override fun fieldExists(coordinates: Vector3): Boolean {
return fields[coordinates] != null
}
override fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean {
val piece = fields[fromCoordinates]?.getPiece()
if (piece != null) {
fields[toCoordinates]?.setPiece(piece)
fields[fromCoordinates]?.removePiece()
return true
}
return false
}
private fun fieldShouldBeAddedToBoard(coordinates: Vector3) : Boolean {
val x = coordinates.x
val y = coordinates.y
val z = coordinates.z
......
......@@ -5,11 +5,14 @@ import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.Scaling;
import com.mygdx.game.controllers.GameController;
import com.mygdx.game.controllers.PlayerController;
import com.mygdx.game.controllers.UtilsKt;
import com.mygdx.game.views.enums.PlayAssets;
import com.mygdx.game.views.tokens.AnimatedSprite;
import com.mygdx.game.views.tokens.StarPiece;
......@@ -17,20 +20,19 @@ import com.mygdx.game.views.tokens.StarPiece;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class PlayView extends View{
private Texture background;
private Image backgroundImage;
Float BOARD_SCALE_FACTOR;
int Help_Guides = 12;
int row_height = Gdx.graphics.getHeight() / Help_Guides;
int col_width = Gdx.graphics.getWidth() / Help_Guides;
Float BOARD_SCALE_FACTOR = Constants.SCALE_FACTOR_BOARD;
List<Color> PIECE_COLORS = Arrays.asList(Color.PINK, Color.CYAN, Color.LIME, Color.GOLD, Color.LIGHT_GRAY, Color.PURPLE);
Texture starPieceBase;
Texture starPieceBaseBorder;
Texture starPieceMast;
......@@ -38,15 +40,15 @@ public class PlayView extends View{
Texture starPieceHead;
Texture starPieceHeadBorder;
HashMap<Float[], StarPiece> pieces;
HashMap<Vector3, StarPiece> pieces;
GameController gameController;
public PlayView(GameViewManager gvm, PlayerController playerController, AssetManager assetManager, Stage stage, Skin skin, ArrayList<AnimatedSprite> lobbyAvatars) {
super(gvm, playerController, assetManager, stage, skin);
background = new Texture("Game/1x/GameBoard@1x.png");
this.backgroundImage = new Image(background);
this.BOARD_SCALE_FACTOR = Constants.SCALE_FACTOR_BOARD;
// Create and downscale background image
Texture background = new Texture("Game/1x/GameBoard@1x.png");
Image backgroundImage = new Image(background);
backgroundImage.setScaleX(BOARD_SCALE_FACTOR);
backgroundImage.setScaleY(BOARD_SCALE_FACTOR);
//backgroundImage.setScaling(Scaling.fit);
......@@ -71,6 +73,10 @@ public class PlayView extends View{
this.pieces = new HashMap<>();
}
public void setGameController(GameController gameController) {
this.gameController = gameController;
}
private void isGameOver(){
boolean someCondition = false;
if (someCondition){
......@@ -80,12 +86,11 @@ public class PlayView extends View{
@Override
public void handleInput(float dt) {
if(Gdx.input.isTouched()) {
if(Gdx.input.justTouched()) {
int x = Gdx.input.getX() - (Gdx.graphics.getWidth() / 2);
int y = Gdx.input.getY() - (Gdx.graphics.getHeight() / 2);
System.out.println("Centered: " + x + ", " + y);
System.out.println("Normal : " + Gdx.input.getX() + ", " + Gdx.input.getY());
gameController.handleClick(x, y);
}
}
......@@ -104,25 +109,30 @@ public class PlayView extends View{
stage.draw();
for (StarPiece piece : pieces.values()) {
for (StarPiece piece : this.pieces.values()) {
piece.draw(stage.getBatch());
}
}
public void initializePieces(List<List<Float[]>> coordinates) {
List<Color> colors = Arrays.asList(Color.PINK, Color.CYAN, Color.LIME, Color.GOLD, Color.LIGHT_GRAY, Color.PURPLE);
public void initializePieces(List<List<Vector3>> startFieldCubeCoordinates) { // Create and draw pieces at their starting positions
Color color;
int colorCounter = 0;
for (List<Float[]> coordinateSet : coordinates) {
for (Float[] coordinate : coordinateSet) {
coordinate[0] += Gdx.graphics.getWidth() / 2F - (starPieceBase.getWidth() * 0.035F) / 2F;
coordinate[1] = Gdx.graphics.getHeight() / 2F - coordinate[1] - (starPieceBase.getHeight() * 0.035F) / 2F; // Adjust for inverted y-axis
// Convert to pixel coordinates
List<List<Float[]>> startFieldPixelCoordinates = cubeCoordinateSetToPixel(startFieldCubeCoordinates);
for (int i = 0; i < startFieldPixelCoordinates.size(); i++) {
for (int j = 0; j < startFieldPixelCoordinates.get(i).size(); j++) {
float coordinateX = startFieldPixelCoordinates.get(i).get(j)[0];
float coordinateY = startFieldPixelCoordinates.get(i).get(j)[1];
color = colors.get(colorCounter);
StarPiece piece = new StarPiece(coordinate[0], coordinate[1], color, starPieceBase, starPieceBaseBorder, starPieceMast, starPieceMastBorder, starPieceHead, starPieceHeadBorder);
piece.setRotateHead(true);
pieces.put(coordinate, piece);
coordinateX += Gdx.graphics.getWidth() / 2F - (starPieceBase.getWidth() * Constants.SCALE_FACTOR_PIECE) / 2F;
coordinateY = Gdx.graphics.getHeight() / 2F - coordinateY - (starPieceBase.getHeight() * Constants.SCALE_FACTOR_PIECE) / 2F; // Adjusted for inverted y-axis
color = PIECE_COLORS.get(colorCounter);
StarPiece piece = new StarPiece(coordinateX, coordinateY, color, starPieceBase, starPieceBaseBorder, starPieceMast, starPieceMastBorder, starPieceHead, starPieceHeadBorder);
this.pieces.put(startFieldCubeCoordinates.get(i).get(j), piece);
}
colorCounter++;
}
......@@ -160,6 +170,35 @@ public class PlayView extends View{
}
}
public StarPiece getPiece(Vector3 coordinates) {
return this.pieces.get(coordinates);
}
private List<List<Float[]>> cubeCoordinateSetToPixel(List<List<Vector3>> cubeCoordinateSet) {
// Convert to pixel coordinates
List<List<Float[]>> startFieldCoordinatesPixel = new ArrayList<>();
for (List<Vector3> coordinateSet : cubeCoordinateSet) {
List<Float[]> coordinateSetPixel = new ArrayList<>();
for (Vector3 coordinate : coordinateSet) {
coordinateSetPixel.add(UtilsKt.cubeToPixel(coordinate, Constants.HEX_SIDE_LENGTH));
}
startFieldCoordinatesPixel.add(coordinateSetPixel);
}
return startFieldCoordinatesPixel;
}
public void movePiece(StarPiece piece, Vector3 toCoordinates) {
Float[] pixelCoordinates = UtilsKt.cubeToPixel(toCoordinates, Constants.HEX_SIDE_LENGTH);
piece.setX((Gdx.graphics.getWidth() / 2F) + pixelCoordinates[0] - ((starPieceBase.getWidth() * Constants.SCALE_FACTOR_PIECE) / 2F));
piece.setY(Gdx.graphics.getHeight() / 2F - pixelCoordinates[1] - ((starPieceBase.getHeight() * Constants.SCALE_FACTOR_PIECE) / 2F));
// Replace key
pieces.values().remove(piece);
pieces.put(toCoordinates, piece);
}
private void debugDraw(SpriteBatch sb, String text, int xPos, int yPos){
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment