Gjør den del nødvendige forandringer for å kunne tegne det nye brettet

Oppdaterer IDrawableObject og IDrawableGame og implementerende klasser
Legger til en utility klasse for input og output
Legger til manglende metoder i TextureConverterUtil
Oppdaterer noen tester med nye datatyper
This commit is contained in:
Kristian Knarvik 2020-02-24 18:07:26 +01:00
parent 354542414a
commit f731ebe5cf
12 changed files with 311 additions and 73 deletions

View File

@ -7,10 +7,12 @@ import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import inf112.fiasko.roborally.element_properties.GameTexture;
import inf112.fiasko.roborally.game.Game;
import inf112.fiasko.roborally.game.IDrawableGame;
import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.utility.IOUtil;
import java.util.List;
/**
* This class renders a game using libgdx
@ -23,6 +25,8 @@ public class GameLauncher extends ApplicationAdapter {
private Texture robotTexture;
private Texture textureSheet;
private final int tileDimensions = 64;
@Override
public void create() {
//Loads some textures
@ -31,8 +35,11 @@ public class GameLauncher extends ApplicationAdapter {
game = new Game();
camera = new OrthographicCamera();
camera.setToOrtho(false, game.getWidth(), game.getHeight());
camera.setToOrtho(false, game.getWidth() * tileDimensions,
game.getHeight() * tileDimensions);
batch = new SpriteBatch();
/*MyTextInputListener listener = new MyTextInputListener();
Gdx.input.getTextInput(listener, "Input name", "", "Name");*/
}
/**
@ -45,8 +52,12 @@ public class GameLauncher extends ApplicationAdapter {
batch.setProjectionMatrix(camera.combined);
batch.begin();
//Draws all elements the game wants to draw
for (IDrawableObject object : game.getObjectsToDraw()) {
TextureRegion objectTextureRegion = gameTextureToTextureRegion(object.getTexture());
List<IDrawableObject> elementsToDraw = IOUtil.getDrawableObjectsFromGame(game, tileDimensions, tileDimensions);
for (IDrawableObject object : elementsToDraw) {
TextureRegion objectTextureRegion = object.getTexture();
/*System.out.println(object.getTexture() + " " + object.getXPosition() + " " + object.getYPosition() + " " + object.getWidth() + " " +
object.getHeight() + " " + object.getRotation() + " " + objectTextureRegion.getRegionX() + " " +
objectTextureRegion.getRegionY() + " " + objectTextureRegion.getRegionWidth() + " " + objectTextureRegion.getRegionHeight());*/
batch.draw(objectTextureRegion.getTexture(), object.getXPosition(), object.getYPosition(),
(float)object.getWidth()/2, (float)object.getHeight()/2,
object.getWidth(), object.getHeight(), 1, 1, object.getRotation(),
@ -64,22 +75,14 @@ public class GameLauncher extends ApplicationAdapter {
batch.dispose();
}
/**
* Turns a GameTexture element into a TextureRegion element
*
* This is necessary to keep all libgdx logic in this class only. Otherwise, testing would be painful.
*
* @param gameTexture A GameTexture enum
* @return A Gdx TextureRegion
*/
private TextureRegion gameTextureToTextureRegion(GameTexture gameTexture) {
switch (gameTexture) {
case ROBOT:
return new TextureRegion(robotTexture, 0, 0, 64, 64);
case TILE:
return new TextureRegion(textureSheet, 4*300, 0, 300, 300);
default:
throw new IllegalArgumentException("Non existing texture encountered.");
/*public static class MyTextInputListener implements Input.TextInputListener {
@Override
public void input (String text) {
System.out.println(text);
}
}
@Override
public void canceled () {
}
}*/
}

View File

@ -1,9 +0,0 @@
package inf112.fiasko.roborally.element_properties;
/**
* This enum represents a drawable texture
*/
public enum GameTexture {
ROBOT,
TILE
}

View File

@ -1,53 +1,77 @@
package inf112.fiasko.roborally.game;
import inf112.fiasko.roborally.element_properties.GameTexture;
import inf112.fiasko.roborally.element_properties.Direction;
import inf112.fiasko.roborally.element_properties.Position;
import inf112.fiasko.roborally.element_properties.RobotID;
import inf112.fiasko.roborally.objects.Board;
import inf112.fiasko.roborally.objects.DrawableObject;
import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.objects.Robot;
import inf112.fiasko.roborally.objects.Tile;
import inf112.fiasko.roborally.objects.Wall;
import inf112.fiasko.roborally.utility.BoardLoaderUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* This class represent a game which is drawable using libgdx
*/
public class Game implements IDrawableGame {
private final int TILE_SIZE = 64;
private Board gameBoard;
public Game() {
try {
List<Robot> robots = new ArrayList<>();
robots.add(new Robot(RobotID.ROBOT_1, new Position(1, 1)));
gameBoard = BoardLoaderUtil.loadBoard("boards/Checkmate.txt", robots);
new Thread(() -> {
try {
runGameLoop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
private void runGameLoop() throws InterruptedException {
TimeUnit.SECONDS.sleep(10);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.NORTH);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.EAST);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.NORTH);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.WEST);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.WEST);
}
@Override
public int getWidth() {
return gameBoard.getBoardWidth() * TILE_SIZE;
return gameBoard.getBoardWidth();
}
@Override
public int getHeight() {
return gameBoard.getBoardHeight() * TILE_SIZE;
return gameBoard.getBoardHeight();
}
@Override
public List<IDrawableObject> getObjectsToDraw() {
List<IDrawableObject> list = new ArrayList<>();
for (int i = 0; i < gameBoard.getBoardWidth(); i++) {
for (int j = 0; j < gameBoard.getBoardHeight(); j++) {
DrawableObject tile = new DrawableObject(GameTexture.TILE, i * TILE_SIZE, j * TILE_SIZE);
list.add(tile);
}
}
DrawableObject robot = new DrawableObject(GameTexture.ROBOT, TILE_SIZE, TILE_SIZE);
list.add(robot);
return list;
public List<Tile> getTilesToDraw() {
return gameBoard.getTiles();
}
@Override
public List<Wall> getWallsToDraw() {
return gameBoard.getWalls();
}
@Override
public List<Robot> getRobotsToDraw() {
return gameBoard.getAliveRobots();
}
}

View File

@ -1,6 +1,8 @@
package inf112.fiasko.roborally.game;
import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.objects.Robot;
import inf112.fiasko.roborally.objects.Tile;
import inf112.fiasko.roborally.objects.Wall;
import java.util.List;
@ -10,21 +12,41 @@ import java.util.List;
public interface IDrawableGame {
/**
* Gets the screen width of the game
* Gets the number of tiles in the x direction
* @return A positive integer
*/
int getWidth();
/**
* Gets the screen height of the game
* Gets the number of tiles in the y direction
* @return A positive integer
*/
int getHeight();
/**
* Gets a list of objects which are to be drawn
* @return A list of drawable objects in the order they are to be drawn
* Gets a list of all the tiles to be drawn
*
* Should return a list readable from top-left to top-right and so on. In other words, the first getWidth() tiles
* should be drawn on the top row from left to right.
*
* @return A list of tiles
*/
List<IDrawableObject> getObjectsToDraw();
List<Tile> getTilesToDraw();
/**
* Gets a list of all the walls to be drawn
*
* Should return a list readable from top-left to top-right and so on. In other words, the first getWidth() walls
* should be drawn on the top row from left to right.
*
* @return A list of walls
*/
List<Wall> getWallsToDraw();
/**
* Gets a list of all robots to draw
* @return A list of all robots to draw
*/
List<Robot> getRobotsToDraw();
}

View File

@ -81,6 +81,22 @@ public class Board {
return new ArrayList<>(robots.values());
}
/**
* Gets all the tiles from the board
* @return A list of all tiles on the board
*/
public List<Tile> getTiles() {
return getAllElementsFromGrid(tiles);
}
/**
* Gets all the walls from the board
* @return A list of all the walls on the board
*/
public List<Wall> getWalls() {
return getAllElementsFromGrid(walls);
}
/**
* Removes a dead robot from the board over to the dead robot list
* @param robot the dead robot
@ -265,4 +281,20 @@ public class Board {
throw new IllegalArgumentException("It's not possible to move in that direction.");
}
}
/**
* Gets all elements on a grid
* @param grid The grid to get elements from
* @param <K> The type of the elements int the grid
* @return A list containing all the elements in the grid
*/
private <K> List<K> getAllElementsFromGrid(IGrid<K> grid) {
List<K> elements = new ArrayList<>();
for (int x = grid.getWidth() - 1; x >= 0; x--) {
for (int y = 0; y < grid.getHeight(); y++) {
elements.add(grid.getElement(x, y));
}
}
return elements;
}
}

View File

@ -1,12 +1,12 @@
package inf112.fiasko.roborally.objects;
import inf112.fiasko.roborally.element_properties.GameTexture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
/**
* This class represents an object that can be drawn using libgdx
*/
public class DrawableObject implements IDrawableObject {
private final GameTexture texture;
private final TextureRegion texture;
private final int xPos;
private final int yPos;
private int width = 64;
@ -26,7 +26,7 @@ public class DrawableObject implements IDrawableObject {
* @param flipX Whether to flip/mirror the element over the x axis
* @param flipY Whether to flip/mirror the element over the y axis
*/
public DrawableObject(GameTexture texture, int xPos, int yPos, int width, int height, int rotation, boolean flipX,
public DrawableObject(TextureRegion texture, int xPos, int yPos, int width, int height, int rotation, boolean flipX,
boolean flipY) {
this.xPos = xPos;
this.yPos = yPos;
@ -38,20 +38,38 @@ public class DrawableObject implements IDrawableObject {
this.flipY = flipY;
}
/**
* Initializes a drawable object
* @param texture The texture to use for drawing the element
* @param xPos The pixel to start drawing on for the x axis
* @param yPos The pixel to start drawing on for the y axis
* @param width The width of the element
* @param height The height of the element
* @param rotation The amount of degrees to rotate the element counterclockwise
*/
public DrawableObject(TextureRegion texture, int xPos, int yPos, int width, int height, int rotation) {
this.xPos = xPos;
this.yPos = yPos;
this.rotation = rotation;
this.texture = texture;
this.width = width;
this.height = height;
}
/**
* Initializes a new drawable object
* @param texture The texture to use for drawing the element
* @param xPos The pixel to start drawing on for the x axis
* @param yPos The pixel to start drawing on for the y axis
*/
public DrawableObject(GameTexture texture, int xPos, int yPos) {
public DrawableObject(TextureRegion texture, int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
this.texture = texture;
}
@Override
public GameTexture getTexture() {
public TextureRegion getTexture() {
return texture;
}

View File

@ -77,7 +77,7 @@ public class Grid<K> implements IGrid<K> {
*/
private void makeSureCoordinatesAreWithinBounds(int x, int y) {
if (x < 0 || x >= width || y < 0 || y >= height) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("Coordinates are outside the bounds of the board.");
}
}
}

View File

@ -1,6 +1,6 @@
package inf112.fiasko.roborally.objects;
import inf112.fiasko.roborally.element_properties.GameTexture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
/**
* This interface describes an object drawable using libgdx
@ -11,7 +11,7 @@ public interface IDrawableObject {
* Gets the texture to use for drawing the object
* @return The texture of the object
*/
GameTexture getTexture();
TextureRegion getTexture();
/**
* Gets the x position the object should be drawn on

View File

@ -0,0 +1,129 @@
package inf112.fiasko.roborally.utility;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import inf112.fiasko.roborally.element_properties.Direction;
import inf112.fiasko.roborally.element_properties.Position;
import inf112.fiasko.roborally.game.IDrawableGame;
import inf112.fiasko.roborally.objects.DrawableObject;
import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.objects.Robot;
import inf112.fiasko.roborally.objects.Tile;
import inf112.fiasko.roborally.objects.Wall;
import java.util.ArrayList;
import java.util.List;
public class IOUtil {
private IOUtil() {}
/**
* Gets a list of all elements which should be drawn from the game provided
* @param game A game implementing IDrawableGame
* @param tileWidth The with of all tiles to be drawn
* @param tileHeight The height of all tiles to be drawn
* @return A list of drawable objects
*/
public static List<IDrawableObject> getDrawableObjectsFromGame(IDrawableGame game, int tileWidth, int tileHeight) {
List<IDrawableObject> drawableObjects = new ArrayList<>();
List<Tile> tilesToDraw = game.getTilesToDraw();
List<Wall> wallsToDraw = game.getWallsToDraw();
List<Robot> robotsToDraw = game.getRobotsToDraw();
int gameWidth = game.getWidth();
int gameHeight = game.getHeight();
drawableObjects.addAll(getDrawableObjectsFromElementList(tilesToDraw, gameWidth, gameHeight, tileWidth, tileHeight));
drawableObjects.addAll(getDrawableObjectsFromElementList(wallsToDraw, gameWidth, gameHeight, tileWidth, tileHeight));
drawableObjects.addAll(getDrawableRobots(robotsToDraw, gameWidth, gameHeight, tileWidth, tileHeight));
return drawableObjects;
}
private static List<IDrawableObject> getDrawableRobots(List<Robot> robots, int gameWidth, int gameHeight, int tileWidth, int tileHeight) {
List<IDrawableObject> drawableObjects = new ArrayList<>();
for (Robot robot : robots) {
TextureRegion region = TextureConverterUtil.convertElement(robot);
Position robotPosition = robot.getPosition();
int rotation = getElementRotation(robot);
IDrawableObject drawableObject = new DrawableObject(region, robotPosition.getXCoordinate() * tileWidth,
(-robotPosition.getYCoordinate() + gameHeight - 1) * tileHeight, tileWidth, tileHeight, rotation);
drawableObjects.add(drawableObject);
}
return drawableObjects;
}
/**
* Gets a list of drawable objects with correct positions from a list of elements
* @param elementsToDraw A list of elements to draw
* @param gameWidth The width of the game board in tiles
* @param gameHeight The height of the game board in tiles
* @param tileWidth The width of a tile
* @param tileHeight The height of a tile
* @param <K> Should be type Robot, Tile or Wall
* @return A list of drawable objects
*/
private static <K> List<IDrawableObject> getDrawableObjectsFromElementList(List<K> elementsToDraw, int gameWidth,
int gameHeight, int tileWidth,
int tileHeight) {
List<IDrawableObject> drawableObjects = new ArrayList<>();
for (int j = 0; j < gameHeight; j++) {
for (int i = j * gameWidth; i < (j + 1) * gameWidth; i++) {
K currentElement = elementsToDraw.get(i);
if (currentElement == null) {
continue;
}
TextureRegion region;
if (currentElement.getClass().isAssignableFrom(Tile.class)) {
Tile tile = (Tile) currentElement;
region = TextureConverterUtil.convertElement(tile);
} else if (currentElement.getClass().isAssignableFrom(Wall.class)) {
Wall wall = (Wall) currentElement;
region = TextureConverterUtil.convertElement(wall);
} else {
throw new IllegalArgumentException("Unknown element type passed to function.");
}
int rotation = getElementRotation(currentElement);
IDrawableObject drawableObject = new DrawableObject(region,
(i % gameWidth) * tileWidth, j * tileHeight, tileWidth, tileHeight, rotation);
drawableObjects.add(drawableObject);
}
}
return drawableObjects;
}
private static <K> int getElementRotation(K element) {
boolean hasRotatedTexture;
Direction direction;
if (element.getClass().isAssignableFrom(Robot.class)) {
Robot robot = (Robot) element;
hasRotatedTexture = TextureConverterUtil.hasRotatedTexture(robot);
direction = robot.getFacingDirection();
} else if (element.getClass().isAssignableFrom(Tile.class)) {
Tile tile = (Tile) element;
hasRotatedTexture = TextureConverterUtil.hasRotatedTexture(tile);
direction = tile.getDirection();
} else if (element.getClass().isAssignableFrom(Wall.class)) {
Wall wall = (Wall) element;
hasRotatedTexture = TextureConverterUtil.hasRotatedTexture(wall);
direction = wall.getDirection();
} else {
throw new IllegalArgumentException("Unknown element type passed to function.");
}
if (hasRotatedTexture) {
return 0;
}
switch (direction) {
case NORTH:
case NORTH_EAST:
return 0;
case WEST:
case NORTH_WEST:
return 90;
case SOUTH:
case SOUTH_WEST:
return 180;
case EAST:
case SOUTH_EAST:
return 270;
default:
throw new IllegalArgumentException("Invalid element direction encountered.");
}
}
}

View File

@ -67,6 +67,9 @@ public final class TextureConverterUtil {
e.printStackTrace();
}
}
if (wall == null) {
return null;
}
Direction direction = wall.getDirection();
TextureConverterContainer converterContainer = tileSheetWallTextureMappings.get(wall.getWallType());
if (converterContainer != null) {
@ -104,6 +107,24 @@ public final class TextureConverterUtil {
return tileSheetTileHasRotatedTextureMappings.get(tile.getTileType());
}
/**
* Checks whether a wall has textures for different rotations
* @param wall The wall to check
* @return True if rotated versions of the texture exists. False otherwise
*/
public static boolean hasRotatedTexture(Wall wall) {
return true;
}
/**
* Checks whether a robot has textures for different rotations
* @param robot The robot to check
* @return True if rotated versions of the texture exists. False otherwise
*/
public static boolean hasRotatedTexture(Robot robot) {
return false;
}
/**
* Loads mappings between a tile and texture
*

View File

@ -1,10 +1,6 @@
package inf112.fiasko.roborally.game;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import inf112.fiasko.roborally.game.Game;
import inf112.fiasko.roborally.game.IDrawableGame;
import org.junit.Before;
import org.junit.Test;
@ -35,9 +31,4 @@ public class GameTest {
public void gameHeightIsMaximumFullHD() {
assertTrue(game.getHeight() <= 1080);
}
@Test
public void getObjectsToDrawReturnsNonemptyList() {
assertFalse(game.getObjectsToDraw().isEmpty());
}
}

View File

@ -1,17 +1,24 @@
package inf112.fiasko.roborally.objects;
import inf112.fiasko.roborally.element_properties.GameTexture;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import inf112.fiasko.roborally.GdxTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertFalse;
@RunWith(GdxTestRunner.class)
public class DrawableObjectTest {
public static final GameTexture TEXTURE_MIN_ARG = GameTexture.TILE;
public static final GameTexture TEXTURE_MAX_ARG = GameTexture.ROBOT;
private static final Texture textureSheet = new Texture(Gdx.files.internal("assets/tiles.png"));
private static final Texture robotTexture = new Texture(Gdx.files.internal("assets/Robot.png"));
public static final TextureRegion TEXTURE_MIN_ARG = new TextureRegion(textureSheet, 4*300, 0, 300, 300);
public static final TextureRegion TEXTURE_MAX_ARG = new TextureRegion(robotTexture, 0, 0, 64, 64);
public static final int X_POSITION_MIN_ARG = 5;
public static final int Y_POSITION_MIN_ARG = 8;
public static final int X_POSITION_MAX_ARG = 6;