import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.util.ArrayList; import java.util.Random; /** * This class creates the game display and setups locations of the game objects * * @author * @version November 2, 2017 * Lab 11 */ public class GameView { /** Random used for moving the villain and determining obstacle locations */ private Random rand; /** Number of grid blocks wide */ private int nBlocksWide; /** Number of grid blocks tall */ private int nBlocksTall; /** Width in pixels of a game frame */ private int nPixelsWide; /** Height in pixels of a game frame */ private int nPixelsTall; /** Keeps track of the locations of obstacles */ private ArrayList rows; /** the player's current position */ private int[] playerPos; /** the villain's current position */ private int[] villainPos; /** the length of the game in frames */ private int gameLength; /** Has the game ended */ private boolean isGameOver; /** The background image */ private Image background; /** The hero's image */ private Image hero; /** The image of the obstacles */ private Image obstacle; /** The villain's image */ private Image villain; /** * Constructor for the game display, determining the frame and tile sizes * * @param nBlocksWide Width in number of blocks (or tiles) * @param nBlocksTall Height in number of blocks (or tiles) * @param nPixelsWide Width in pixels of the frame * @param nPixelsTall Height in pixels of the frame * @param ahero Superhero to be save the day */ public GameView(int nBlocksWide, int nBlocksTall, int nPixelsWide, int nPixelsTall, Superhero ahero) { rand = new Random(); // set the difficulty level int difficultyLevel = ahero.getDifficultyLevel(); // set nBlocksWide and nBlocksTall this.nBlocksWide = nBlocksWide; this.nBlocksTall = nBlocksTall; // Pixel size this.nPixelsWide = nPixelsWide; this.nPixelsTall = nPixelsTall; // set game length gameLength = ahero.getFightLength(); isGameOver = false; // create the images hero = ahero.getBattleImage(); villain = ahero.getVillain(); background = ahero.getBattleCity(); obstacle = Toolkit.getDefaultToolkit().getImage("resources/villains/bomb.png"); // where does the player start? playerPos = new int[2]; playerPos[0] = 2; playerPos[1] = nBlocksTall - 1; // where does the villain start? villainPos = new int[2]; villainPos[0] = nBlocksWide - 2; villainPos[1] = 1; // set up obstacles rows = new ArrayList(); for (int i = 0; i < nBlocksTall; i++) { rows.add(new GameRow()); for (int o = 0; o <= difficultyLevel; o++) { // create obstacles in locations the hero and villain are not if (i != playerPos[1] && i != villainPos[1]) { // create obstacles in every other row if (i % 2 == 0) { rows.get(i).addToOccupiedSpaces(rand.nextInt(nBlocksWide)); } } } } } /** * draw the game * * @param graphics A Graphics object used to draw the hero, villain, and obstacles */ public void draw(Graphics graphics) { // draw the background image first graphics.drawImage(background, 0, 0, nPixelsWide, nPixelsTall, null); // how big is each 'block'? int blockWidth = nPixelsWide / nBlocksWide; int blockHeight = nPixelsTall / nBlocksTall; // paint each row int y = 0; for (int i = 0; i < rows.size(); i++) { GameRow row = rows.get(i); drawRow(y, blockWidth, blockHeight, row, graphics); // increase the block for drawing every time a row is drawn y += blockHeight; } drawVillain(blockWidth, blockHeight, graphics); drawPlayer(blockWidth, blockHeight, graphics); } /** * draw a row of obstacle images * * @param y y-coordinate of the image * @param blockWidth width of the obstacle image in pixels * @param blockHeight height of the obstacle image in pixels * @param row one row of obstacle images * @param graphics A Graphics object used for drawing the rows */ private void drawRow(int y, int blockWidth, int blockHeight, GameRow row, Graphics graphics) { // If this is an empty row, don't draw anything if (row.isEmptySpace()) { return; } // Draw any obstacles for (int i = 0; i < nBlocksWide; i++) { // If this is not a free space, draw the obstacle if (row.getOccupiedPositions().contains(i)) { graphics.drawImage(obstacle, i * blockWidth, y, blockWidth, blockHeight, null); } } } /** * draw player image * * @param blockWidth nBlocksWide of the player image in pixels * @param blockHeight nBlocksTall of the player image in pixels * @param graphics A Graphics object used for drawing the hero */ private void drawPlayer(int blockWidth, int blockHeight, Graphics graphics) { // TODO: draw the hero's image in the appropriate position } /** * draw villain image * * @param blockWidth nBlocksWide of the player image in pixels * @param blockHeight nBlocksTall of the player image in pixels * @param graphics A Graphics object used for drawing the villain */ private void drawVillain(int blockWidth, int blockHeight, Graphics graphics) { // TODO: draw the villain's image in the appropriate position } /** * move the villain randomly, with wrapping in the x direction * * @param framenum The current frame we are on of the game * @param framesToMove The number of frames you want the villain to move after * @return villainPos int[] with the x,y - location of the villain in tiles */ public int[] moveVillainRandom(int framenum, int framesToMove) { // Move the villain every framesToMove frames if (framenum % framesToMove == 0 && !isGameOver) { // direction to move int dir = rand.nextInt(3) - 1; int newX = villainPos[0]; int newY = villainPos[1]; // move in the x direction if (rand.nextFloat() > .5) { // wrap the villain if (dir < 0) { newX = (villainPos[0] + dir + nBlocksWide) % nBlocksWide; } else { newX = (villainPos[0] + dir) % nBlocksWide; } } // move in the y direction else if (newY + dir < rows.size() && newY + dir >= 0) { newY = villainPos[1] + dir; } // if the space the villain is to move is available, update the location if (rows.get(newY).isEmptySpace(newX)) { villainPos[0] = newX; villainPos[1] = newY; } } return villainPos; } /** * move player to the right (with wrapping) * * @return new position after player moves right (in tiles) */ public int movePlayerRight() { // TODO: update the hero's position in the frame return playerPos[0]; } /** * move player to the left (with wrapping) * * @return new position after player moves left (in tiles) */ public int movePlayerLeft() { // TODO: update the hero's position in the frame return playerPos[0]; } /** * move player to the up (without wrapping) * * @return new position after player moves up (in tiles) */ public int movePlayerUp() { // TODO: update the hero's position in the frame return playerPos[1]; } /** * move player to the down (without wrapping) * * @return new position after player moves down (in tiles) */ public int movePlayerDown() { // TODO: update the hero's position in the frame return playerPos[1]; } /** * Can the player move to a specified location? * * @param deltaX amount to change the player's x location (either -1, 0, or 1) * @param deltaY amount to change the player's y location (either -1, 0, or 1) * @return true if the player can move by the designated amount */ public boolean canPlayerMove(int deltaX, int deltaY) { /* TODO: determine if the player can move to the new location computed from the players old position plus the delta values */ return true; } /** * check if the game is over * * @param framenum the current frame of the game * @return true if player is dead i.e. we have reached the * last frame and the villain has not been caught */ public boolean playerIsDead(int framenum) { return framenum == gameLength - 1; } /** * check if the player has won * * @return true once the player is in the same space as the villain */ public boolean playerHasWon() { if (playerPos[0] == villainPos[0] && playerPos[1] == villainPos[1]) { isGameOver = true; } return isGameOver; } /** * Get the player's position * * @return the array with the player's current location */ public int[] getPlayerPosition() { return playerPos; } /** * Get the villain's position * * @return the array with the villain's current location */ public int[] getVillainPosition() { return villainPos; } /** * Is there an obstacle within this row at the specified column index? * * @param row int for the row index of interest * @param space int for the column index within the row of interest * @return true if there is not an obstacle within the space for the given row */ public boolean isEmptySpace(int row, int space) { return rows.get(row).isEmptySpace(space); } /** * Remove all the obstacles in each row */ public void clearObstacles() { for (GameRow row : rows) { row.clearOccupiedSpaces(); } } }