Commit 14d67b8b authored by morkolai's avatar morkolai
Browse files

merge in default game, rules are now working

parents 26344985 67428d70
......@@ -4,21 +4,21 @@ size: 2048, 2048
format: RGBA8888
filter: Nearest, Nearest
repeat: none
RocketGuy1x
RocketGuy1
rotate: false
xy: 2, 1004
xy: 2, 2
size: 1000, 1000
orig: 1000, 1000
offset: 0, 0
index: -1
RocketGuy2x
RocketGuy2
rotate: false
xy: 2, 2
xy: 2, 1004
size: 1000, 1000
orig: 1000, 1000
offset: 0, 0
index: -1
RocketGuy3x
RocketGuy3
rotate: false
xy: 1004, 1004
size: 1000, 1000
......
......@@ -14,10 +14,10 @@ public class GameController {
private final Game model;
private final PlayView view;
private StarPiece activePiece; // Previously clicked piece
private Vector3 previousCoordinateClicked; // Previously clicked coordinate
private StarPiece activePiece; // Previously clicked piece
private Vector3 previousCoordinateClicked; // Previously clicked coordinate
private final List<List<Float>> playerNameTextFieldCoordinates; // Coordinates of playernames
private final PlayerController playerController;
private final List<List<Float>> playerNameTextFieldCoordinates;
public GameController(Game model, PlayView view, PlayerController playerController) {
this.model = model;
......@@ -27,14 +27,15 @@ public class GameController {
this.activePiece = null;
this.previousCoordinateClicked = null;
// Get used boardslots and coordinates to place name of players
// Get used boardslots and coordinates to place playernames
List<Integer> usedBoardSlots = this.model.getUsedBoardSlots();
playerNameTextFieldCoordinates = this.model.getPlayerNameCoordinates(this.view.hex_side_length);
// Initialize pieces, place playernames and place turn-indicator
// Initialize pieces, place playernames, turn-indicator and leave-button
this.view.initializePieces(this.model.getStartFieldCoordinates());
this.view.placePlayerNames(usedBoardSlots, playerNameTextFieldCoordinates);
this.view.placeTurnIndicator(playerNameTextFieldCoordinates.get(this.model.getPlayerTurnSlot()));
this.view.placeLeaveButton();
}
public void handleClick(float x, float y) {
......@@ -47,12 +48,15 @@ public class GameController {
// If another piece is already active, deactivate it
if (activePiece != null) {
activePiece.setRotateHead(false);
this.view.removePossibleMoves();
}
// If clicked piece is owned by player and player is not finished, activate piece
if(this.model.getPieceOwnerId(cubeCoordinates) == playerController.getPlayer().getID() && !this.model.isPlayerFinished(playerController.getPlayer().getID())) {
activePiece = this.view.getPiece(cubeCoordinates);
activePiece.setRotateHead(true);
previousCoordinateClicked = cubeCoordinates;
this.view.placePossibleMoves(model.getPossibleMoves(previousCoordinateClicked));
}
} else { // Field does NOT have piece
......@@ -61,10 +65,15 @@ public class GameController {
if (this.model.movePiece(previousCoordinateClicked, cubeCoordinates, playerController.getPlayer().getID(), this)) {
this.view.movePiece(activePiece, cubeCoordinates);
activePiece.setRotateHead(false);
activePiece = null;
playerController.getNetWorkController().sendToServer(new cPlayerPieceMove(previousCoordinateClicked, cubeCoordinates, playerController.getLobby().getID(), playerController.getPlayer().getID()));
// Reset previously clicked piece and coordinate
activePiece = null;
previousCoordinateClicked = null;
// Remove possible move indicators and place turn indicator at next player
this.view.removePossibleMoves();
this.view.placeTurnIndicator(playerNameTextFieldCoordinates.get(this.model.getPlayerTurnSlot()));
} else {
System.out.println("Move was not allowed"); // TODO: Give feedback (move was not valid/not executed)
......@@ -74,8 +83,9 @@ public class GameController {
}
}
// External player moved piece (called by cPlayerPieceMove command)
public void playerMovedPiece(Vector3 fromCoordinates, Vector3 toCoordinates, int playerId) {
// Try to move piece in model. If successful, move piece in view and place turn indicator at next player
if (this.model.movePiece(fromCoordinates, toCoordinates, playerId, this)) {
this.view.moveOtherPlayerPiece(fromCoordinates, toCoordinates);
this.view.placeTurnIndicator(playerNameTextFieldCoordinates.get(this.model.getPlayerTurnSlot()));
......@@ -84,6 +94,14 @@ public class GameController {
}
}
// External player left midgame (called by CLobbyLeave command)
public void setPlayerLeftMidGame(int playerId) {
System.out.println("Player with id " + playerId + " left");
model.setPlayerLeftMidGame(playerId);
setPlayerFinished(playerId, -1);
this.view.placeTurnIndicator(playerNameTextFieldCoordinates.get(model.getPlayerTurnSlot()));
}
public void setPlayerFinished(int playerId, int place) {
int playerIndex;
......@@ -93,12 +111,13 @@ public class GameController {
if (player.getID() == playerId) {
playerIndex = players.indexOf(player);
this.view.setPlayerFinished(playerIndex, place);
break;
}
}
}
public void setGameFinished() {
this.view.removeTurnIndicator();
this.view.placeHomeButton();
this.view.placeExitButton();
}
}
......@@ -14,16 +14,15 @@ import java.util.Arrays;
public class NetworkController {
private Client client;
private Kryo kryo;
private final Client client;
private final Kryo kryo;
private boolean devMode = false;
private final boolean devMode = false;
public NetworkController(){
this.client = new Client();
client.start();
try {
String IP4_LAN_ADDRESS = "192.168.0.109";
client.connect(10000, IP4_LAN_ADDRESS, 54555);
......
......@@ -6,27 +6,25 @@ import com.mygdx.game.controllers.commands.*;
import com.mygdx.game.model.Lobby;
import com.mygdx.game.model.Player;
import org.javatuples.Pair;
import java.util.ArrayList;
import java.util.LinkedList;
public class PlayerController {
private NetworkController net;
private LinkedList<Command> receivedCommands;
private Player player; //This is the current player
private Lobby lobby; //Current lobby
private ArrayList<Lobby> lobbies; //List of all lobbies
private final NetworkController net;
private final LinkedList<Command> receivedCommands;
private Player player; // This is the current player
private Lobby lobby; // Current lobby
private ArrayList<Lobby> lobbies; // List of all lobbies
private GameController gameController;
public PlayerController(NetworkController networkController){
net = networkController;
player = new Player(-1);
lobby = new Lobby(-1);
lobbies = new ArrayList<Lobby>();
receivedCommands = new LinkedList<Command>();
lobbies = new ArrayList<>();
receivedCommands = new LinkedList<>();
net.getClient().addListener(new Listener() {
public void received (Connection connection, Object object) {
......@@ -67,7 +65,7 @@ public class PlayerController {
public void joinLobby(int id){ sendCommand(new cLobbyJoin(id)); }
public void leaveLobby(int id) { sendCommand(new cLobbyLeave(id)); }
public void leaveLobby(int id) { sendCommand(new cLobbyLeave(id, getPlayer().getID())); }
public Lobby getLobby(){ return lobby; }
......@@ -86,12 +84,7 @@ public class PlayerController {
if(lobby==null){
return false;
}
else if(lobby.getID() == -1){
return false;
}
else{
return true;
}
else return lobby.getID() != -1;
}catch (NullPointerException e){
return false;
}
......
package com.mygdx.game.controllers
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.math.Vector3
import java.util.*
import kotlin.math.roundToInt
import kotlin.math.sqrt
// The calculations in the two following functions were found here:
// https://stackoverflow.com/questions/2459402/hexagonal-grid-coordinates-to-pixel-coordinates
fun cubeToPixel(x: Float, y: Float, z: Float, hexSideLength: Float = 1F): Array<Float> {
val pixelX = sqrt(3F) * hexSideLength * ( (z / 2F) + x )
val pixelY = 3F/2F * hexSideLength * z
return arrayOf(pixelX, pixelY)
}
fun cubeToPixel(vector: Vector3, hexSideLength: Float = 1F): Array<Float> {
val pixelX = sqrt(3F) * hexSideLength * ( (vector.z / 2F) + vector.x )
val pixelY = 3F/2F * hexSideLength * vector.z
......@@ -29,13 +23,16 @@ fun pixelToCube(x: Float, y: Float, hexSideLength: Float = 1F) : Vector3 {
return Vector3(cubeX.toFloat(), cubeY.toFloat(), cubeZ.toFloat())
}
fun pixelToCube(vector: Vector2, hexSideLength: Float = 1F) : Array<Float> {
val x = vector.x
val y = vector.y
fun cubeCoordinateSetToPixel(cubeCoordinateSet: List<List<Vector3>>, hexSideLength: Float = 1F): List<List<Array<Float>>> {
val startFieldCoordinatesPixel: MutableList<List<Array<Float>>> = ArrayList()
val cubeX = (sqrt(3F) / 3F * x - y / 3F) / hexSideLength
val cubeY = -(sqrt(3F) / 3F * x + y / 3F) / hexSideLength
val cubeZ = 2F / 3F * y / hexSideLength
for (coordinateSet in cubeCoordinateSet) {
val coordinateSetPixel: MutableList<Array<Float>> = ArrayList()
return arrayOf(cubeX, cubeY, cubeZ)
}
for (coordinate in coordinateSet) {
coordinateSetPixel.add(cubeToPixel(coordinate, hexSideLength))
}
startFieldCoordinatesPixel.add(coordinateSetPixel)
}
return startFieldCoordinatesPixel
}
\ No newline at end of file
package com.mygdx.game.controllers.commands;
import com.esotericsoftware.kryonet.Connection;
import com.mygdx.game.controllers.GameController;
import com.mygdx.game.controllers.PlayerController;
import com.mygdx.game.model.Lobby;
import java.util.ArrayList;
import java.util.List;
public class cLobbyLeave extends Command{
public cLobbyLeave() { super("cLobbyLeave"); }
public cLobbyLeave(int id) { super("cLobbyLeave", (Integer) id); }
int lobbyId;
int playerId;
public cLobbyLeave(int id, int playerId) {
super("cLobbyLeave");
this.lobbyId = id;
this.playerId = playerId;
ArrayList<Object> data = new ArrayList<Object>();
data.add(lobbyId);
data.add(playerId);
this.data = data;
}
@Override
public void execute(PlayerController playerController, Connection connection){
if(data instanceof Lobby){
Lobby lobby = (Lobby) data;
if(lobby.getID() != -1){
if (lobby.getPlayersID().contains((Integer) connection.getID())) {
//Somebody else left
System.out.println("Somebody left the lobby");
playerController.setLobby(lobby);
}
else{
//The current player left
playerController.setLobby(new Lobby(-1));
System.out.println("Request to leave lobby successful");
if (data instanceof ArrayList) {
List<Object> receivedData = (ArrayList<Object>) data;
lobbyId = (int) receivedData.get(0);
playerId = (int) receivedData.get(1);
if (playerId == playerController.getPlayer().getID()) {
System.out.println("Request to leave lobby successful");
playerController.setLobby(new Lobby(-1));
} else {
System.out.println("Player with id " + playerId + " left");
GameController gameController = playerController.getGameController();
if (gameController != null) {
gameController.setPlayerLeftMidGame(playerId);
}
}
else{
System.out.println("Received leaveLobby command with an error");
playerController.getLobby().removePlayer(playerId);
}
}
}
......
......@@ -28,7 +28,7 @@ public class cSetPlayerReady extends Command{
boolean isPlayerReady = (Boolean) data;
if(playerID == playerController.getPlayer().getID()) playerController.getPlayer().setIsPlayerReady(isPlayerReady);
playerController.getLobby().getPlayerByID(playerID).setIsPlayerReady(isPlayerReady);
//System.out.println("value of playerID" + playerID);
System.out.printf("Player status updated. Is player %d currently ready? %b \n", playerID, isPlayerReady);
}
}
......
package com.mygdx.game.managers
class ViewManager {
}
\ No newline at end of file
......@@ -11,6 +11,7 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
private var playerTurnIndex: Int = 0 // TODO: Random from server
private var playerTurnSlot: Int
private var playerFinishedIds: List<Int> = listOf()
private var playerLeftIds: List<Int> = listOf()
private var usedBoardSlots: List<Int>
init {
......@@ -35,8 +36,8 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
return this.gameState.getBoardState().fields[cubeCoordinates]?.hasPiece() == true
}
fun isLegalMove(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean {
return getGameState()?.getGameMode()?.getPossibleMoves(fromCoordinates)?.contains(toCoordinates) ?: false
private fun isLegalMove(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean {
return getGameState().getGameMode().getPossibleMoves(fromCoordinates).contains(toCoordinates)
}
fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3, playerId: Int, gameController: GameController): Boolean {
......@@ -55,7 +56,7 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
this.gameState.setWinner(playerId)
}
// All players are finished
if (playerFinishedIds.size == playerIds.size) {
if (playerFinishedIds.size == playerIds.size - playerLeftIds.size) {
gameController.setGameFinished()
this.gameState.setFinished()
}
......@@ -69,6 +70,10 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
}
}
fun getPossibleMoves(fromCoordinates: Vector3): ArrayList<Vector3> {
return getGameState().getGameMode().getPossibleMoves(fromCoordinates)
}
fun getPlayerTurnId(): Int {
return playerTurnId
}
......@@ -84,7 +89,7 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
playerTurnIndex = 0
}
playerTurnId = playerIds.elementAt(playerTurnIndex)
} while (playerFinishedIds.contains(playerTurnId) && playerFinishedIds.size < playerIds.size)
} while (playerFinishedIds.contains(playerTurnId) && thereArePlayersLeft() || playerLeftIds.contains(playerTurnId))
}
fun getPieceOwnerId(coordinates: Vector3): Int {
......@@ -109,7 +114,7 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
return true
}
fun getGameState(): GameState? {
private fun getGameState(): GameState {
return this.gameState
}
......@@ -120,4 +125,15 @@ class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
fun getPlayerNameCoordinates(hex_side_length: Float): List<List<Float>> {
return gameState.getRules().getPlayerNameCoordinates(hex_side_length)
}
}
\ No newline at end of file
fun setPlayerLeftMidGame(playerId: Int) {
playerLeftIds = playerLeftIds + playerId
if (playerTurnId == playerId) {
nextPlayer()
}
}
private fun thereArePlayersLeft(): Boolean {
return playerFinishedIds.size < playerIds.size - playerLeftIds.size
}
}
......@@ -2,7 +2,7 @@ package com.mygdx.game.model
import com.badlogic.gdx.math.Vector3
//Holds a ruleset and a board
// Holds a ruleset and a board, which combined is a gamemode
class GameMode(rules:AbstractRules, board:AbstractBoard) {
......@@ -31,7 +31,7 @@ class GameMode(rules:AbstractRules, board:AbstractBoard) {
}
private fun getPosition(currentPosition: Vector3, direction: Vector3, numberOfSteps: Int = 1): Vector3 {
var v = currentPosition.cpy()
val v = currentPosition.cpy()
for (i in 1..numberOfSteps) {
v.add(direction)
}
......@@ -39,8 +39,7 @@ class GameMode(rules:AbstractRules, board:AbstractBoard) {
}
private fun isFieldClear(field: Vector3): Boolean {
if (this.board?.fieldExists(field) == false ||
this.board?.fields?.get(field)?.hasPiece() == true) {
if (!this.board.fieldExists(field) || this.board.fields[field]?.hasPiece() == true) {
return false
}
return true
......@@ -51,7 +50,7 @@ class GameMode(rules:AbstractRules, board:AbstractBoard) {
val v = position.cpy().add(direction)
while (v != destination) {
if (isFieldClear(v) || this.board?.fieldExists(v) == false) {
if (isFieldClear(v) || !this.board.fieldExists(v)) {
return false
}
v.add(direction)
......@@ -98,7 +97,8 @@ class GameMode(rules:AbstractRules, board:AbstractBoard) {
// Choice of gamemode should be implemented here in the future
fun getPossibleMoves(position: Vector3): ArrayList<Vector3> {
val possibleMoves: ArrayList<Vector3> = arrayListOf() //val?????
val possibleMoves: ArrayList<Vector3> = arrayListOf()
getBasicMoves(position, this.rules.moveRange, possibleMoves)
getDefaultJumps(position, this.rules.jumpRange,possibleMoves, this.rules.maxJumps,0)
return possibleMoves
......
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.
*/
......@@ -30,7 +28,7 @@ class GameState(gameMode: GameMode) {
return rules
}
fun getGameMode(): GameMode? {
fun getGameMode(): GameMode {
return this.gameMode
}
......
package com.mygdx.game.model;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
public class Lobby {
......@@ -16,14 +15,14 @@ public class Lobby {
public Lobby(int ID){
this.ID = ID;
players = new ArrayList<Player>();
players = new ArrayList<>();
}
public Lobby(int ID, String name, int MAX_PLAYERS){
this.ID = ID;
this.name = name;
this.MAX_PLAYERS = MAX_PLAYERS;
players = new ArrayList<Player>();
players = new ArrayList<>();
}
public int getID(){ return ID; }
......@@ -70,6 +69,18 @@ public class Lobby {
return set;
}
public void removePlayer(int playerID) {
Player leavingPlayer = null;
for (Player player : players) {
if (player.getID() == playerID) {
leavingPlayer = player;
}
}
if (leavingPlayer != null) {
players.remove(leavingPlayer);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
......
......@@ -4,10 +4,10 @@ import com.badlogic.gdx.math.Vector3
abstract class AbstractBoard {
var fields = HashMap<Vector3, Field>()
var fields = HashMap<Vector3, Field>() // Hashmap containing all fields
abstract fun computeFields() // Computes all fields on the board
abstract fun fieldExists(coordinates: Vector3): Boolean
abstract fun placePiecesAtStart(rules: AbstractRules, playerIds: HashSet<Int>)
abstract fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean
abstract fun computeFields() // Computes all fields on the board
abstract fun fieldExists(coordinates: Vector3): Boolean // Returns whether a field exists on board
abstract fun placePiecesAtStart(rules: AbstractRules, playerIds: HashSet<Int>) // Places pieces at startfields
abstract fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean // Moves piece
}
\ No newline at end of file
......@@ -10,7 +10,6 @@ abstract class AbstractRules {
abstract var jumpRange: Int // How many pieces a piece can jump over
abstract var maxJumps: Int // How many jumps can a piece do after each other
abstract fun getPlayerStartfields(boardSlot: Int) : List<Vector3> // Returns a list of startfields for a given player
abstract fun getPlayerTargetFields(boardSlot: Int) : List<Vector3> // Returns a list of targetfields for a given player
abstract fun generateStartFields(playerCount: Int = 6): List<List<Vector3>> // Returns a list with lists of startfields
......
......@@ -17,7 +17,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.mygdx.game.controllers.PlayerController;
public abstract class View extends ApplicationAdapter {
public abstract class AbstractView extends ApplicationAdapter {
protected OrthographicCamera cam;
protected float[] lastTouch = new float[2];;
......@@ -44,7 +44,7 @@ public abstract class View extends ApplicationAdapter {
protected boolean startFadeIn;
protected Texture fadeOverlayTexture;
protected View(GameViewManager gvm, PlayerController playerController, AssetManager assetManager, Stage stage, Skin skin){
protected AbstractView(GameViewManager gvm, PlayerController playerController, AssetManager assetManager, Stage stage, Skin skin){
this.gvm = gvm;
this.stage = stage;
this.assetManager = assetManager;
......