diff --git a/MerchantRPGCSE2102/src/model/Map.java b/MerchantRPGCSE2102/src/model/Map.java index 8d3a388..6ffaf97 100644 --- a/MerchantRPGCSE2102/src/model/Map.java +++ b/MerchantRPGCSE2102/src/model/Map.java @@ -18,27 +18,27 @@ public Map(int rows, int cols) { /** * This method stores the sepcified instance of Player at the specified position on the map * @param player The player to be initialized - * @param x The x coordinate of the player's location - * @param y The y coordinate of the player's location + * @param row The row of the player's location + * @param column The column of the player's location */ - public void initializePlayer(Player player, int x, int y) { + public void initializePlayer(Player player, int row, int col) { _player = player; - int vertexNum = y*_cols + x; - player.setCol(x); - player.setRow(y); + int vertexNum = row*_cols + col; + player.setCol(col); + player.setRow(row); _mapGraph.getVertex(vertexNum).setOccupant(player); } /** * This method stores the sepcified instance of Merchant at the specified position on the map * @param player The merchant to be initialized - * @param x The x coordinate of the merchant's location - * @param y The y coordinate of the merchant's location + * @param row The row of the merchant's location + * @param col The column of the merchant's location */ - public void initializeMerchant(Merchant merchant, int x, int y) { - int vertexNum = y*_cols + x; - merchant.setCol(x); - merchant.setRow(y); + public void initializeMerchant(Merchant merchant, int row, int col) { + int vertexNum = row*_cols + col; + merchant.setCol(col); + merchant.setRow(row); _mapGraph.getVertex(vertexNum).setOccupant(merchant); } @@ -47,45 +47,45 @@ public void initializeMerchant(Merchant merchant, int x, int y) { * @param String The direction to be moved (north, west, east, or south) */ public void movePlayer(String direction) { - int currentX = _player.getCol(); - int currentY = _player.getRow(); + int currentCol = _player.getCol(); + int currentRow = _player.getRow(); if (direction.equals("north")) { - if (currentY != 0) { - if (!isOccupied(currentX, currentY - 1)) { - _mapGraph.getVertex(currentY*_cols + currentX).setOccupant(null); - _mapGraph.getVertex((currentY - 1)*_cols + currentX).setOccupant(_player); - _player.setRow(currentY - 1); + if (currentRow != 0) { + if (!isOccupied(currentCol, currentRow - 1)) { + _mapGraph.getVertex(currentRow*_cols + currentCol).setOccupant(null); + _mapGraph.getVertex((currentRow - 1)*_cols + currentCol).setOccupant(_player); + _player.setRow(currentRow - 1); } } } if (direction.equals("east")) { - if (currentX != _cols - 1) { - if (!isOccupied(currentX + 1, currentY)) { - _mapGraph.getVertex(currentY*_cols + currentX).setOccupant(null); - _mapGraph.getVertex(currentY*_cols + (currentX + 1)).setOccupant(_player); - _player.setCol(currentX + 1); + if (currentCol != _cols - 1) { + if (!isOccupied(currentCol + 1, currentRow)) { + _mapGraph.getVertex(currentRow*_cols + currentCol).setOccupant(null); + _mapGraph.getVertex(currentRow*_cols + (currentCol + 1)).setOccupant(_player); + _player.setCol(currentCol + 1); } } } if (direction.equals("south")) { - if (currentY != _rows - 1) { - if (!isOccupied(currentX, currentY + 1)) { - _mapGraph.getVertex(currentY*_cols + currentX).setOccupant(null); - _mapGraph.getVertex((currentY + 1)*_cols + currentX).setOccupant(_player); - _player.setRow(currentY + 1); + if (currentRow != _rows - 1) { + if (!isOccupied(currentCol, currentRow + 1)) { + _mapGraph.getVertex(currentRow*_cols + currentCol).setOccupant(null); + _mapGraph.getVertex((currentRow + 1)*_cols + currentCol).setOccupant(_player); + _player.setRow(currentRow + 1); } } } if (direction.equals("west")) { - if (currentX != 0) { - if (!isOccupied(currentX - 1, currentY)) { - _mapGraph.getVertex(currentY*_cols + currentX).setOccupant(null); - _mapGraph.getVertex(currentY*_cols + (currentX - 1)).setOccupant(_player); - _player.setCol(currentX - 1); + if (currentCol != 0) { + if (!isOccupied(currentCol - 1, currentRow)) { + _mapGraph.getVertex(currentRow*_cols + currentCol).setOccupant(null); + _mapGraph.getVertex(currentRow*_cols + (currentCol - 1)).setOccupant(_player); + _player.setCol(currentCol - 1); } } } @@ -115,13 +115,21 @@ public boolean isOccupied(int col, int row) { public boolean collisionTo(String direction) { if (direction.equals("north")) - return isOccupied(_player.getCol(), _player.getRow() + 1); - if (direction.equals("south")) return isOccupied(_player.getCol(), _player.getRow() - 1); + if (direction.equals("south")) + return isOccupied(_player.getCol(), _player.getRow() + 1); if (direction.equals("east")) return isOccupied(_player.getCol() + 1, _player.getRow()); if (direction.equals("west")) return isOccupied(_player.getCol() - 1, _player.getRow()); + if (direction.equals("northwest")) + return isOccupied(_player.getCol() - 1, _player.getRow() - 1); + if (direction.equals("southwest")) + return isOccupied(_player.getCol() - 1, _player.getRow() + 1); + if (direction.equals("northeast")) + return isOccupied(_player.getCol() + 1, _player.getRow() - 1); + if (direction.equals("southeast")) + return isOccupied(_player.getCol() + 1, _player.getRow() + 1); return false; } diff --git a/MerchantRPGCSE2102/src/sprites/PlayerSprite.java b/MerchantRPGCSE2102/src/sprites/PlayerSprite.java index 09a944b..220e65a 100644 --- a/MerchantRPGCSE2102/src/sprites/PlayerSprite.java +++ b/MerchantRPGCSE2102/src/sprites/PlayerSprite.java @@ -2,80 +2,84 @@ import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.event.KeyEvent; - import view.MapUI; public class PlayerSprite { - private static final int WIDTH = 30; - MapUI mapui; - public int x, y = 0; - public int row, col; - int dx, dy = 0; - public int changeInX = 15; - public int changeInY = 15; - Color color = new Color(0, 0, 0); - boolean leftBeingPressed = false; - boolean rightBeingPressed = false; - boolean downBeingPressed = false; - boolean upBeingPressed = false; - - public PlayerSprite(MapUI mapui) { + MapUI mapui; // Instance of MapUI which created this PlayerSprite + private static final int WIDTH = 30; // Width of the PlayerSprite + private Color color = new Color(0, 0, 0); // Color of the PlayerSprite (this will no longer be needed once we have a sprite sheet) + + private int x, y; // x and y coordinates (in pixels) + private int dx, dy = 0; // Velocity of the sprite + private int changeInX = 15; // Counts the number of pixels moved between vertices (in reference to the center of the sprite) + private int changeInY = 15; + + // Keep track of which keys are currently being pressed + private boolean leftBeingPressed = false; + private boolean rightBeingPressed = false; + private boolean downBeingPressed = false; + private boolean upBeingPressed = false; + + public PlayerSprite(MapUI mapui, int row, int col) { + this.x = col*WIDTH; + this.y = row*WIDTH; this.mapui = mapui; } - + + /** + * Changes the sprite's velocity based on which key is being pressed + * @param e The KeyEvent detected by the system + */ public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_LEFT) { dx = -1; - if (mapui.getMap().collisionTo("west") && changeInX == 15) - dx = 0; leftBeingPressed = true; } if (e.getKeyCode() == KeyEvent.VK_RIGHT) { dx = 1; - if (mapui.getMap().collisionTo("east") && changeInX == 15) - dx = 0; rightBeingPressed = true; } + if (e.getKeyCode() == KeyEvent.VK_UP) { dy = -1; - if (mapui.getMap().collisionTo("north") && changeInY == 15) - dx = 0; upBeingPressed = true; } if (e.getKeyCode() == KeyEvent.VK_DOWN) { dy = 1; - if (mapui.getMap().collisionTo("south") && changeInY == 15) - dx = 0; downBeingPressed = true; } } - + + /** + * Changes the sprite's velocity based on which key is released + * @param e The KeyEvent detected by the system + */ public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_LEFT) { leftBeingPressed = false; - if (rightBeingPressed == false) + if (rightBeingPressed == false) // Sprite will stop only when the RIGHT key is not being pressed dx = 0; } - + if (e.getKeyCode() == KeyEvent.VK_RIGHT) { rightBeingPressed = false; - if (leftBeingPressed == false) + if (leftBeingPressed == false) // Sprite will stop only when the LEFT key is not being pressed dx = 0; } - if (e.getKeyCode() == KeyEvent.VK_UP) { upBeingPressed = false; - if (downBeingPressed == false) + if (downBeingPressed == false) // Sprite will stop only when the DOWN key is not being pressed dy = 0; } - + if (e.getKeyCode() == KeyEvent.VK_DOWN) { downBeingPressed = false; - if (upBeingPressed == false) + if (upBeingPressed == false) // Sprite will stop only when the UP key is not being pressed dy = 0; } - + // This fixes some bugs with holding three keys down at once and letting go of two (Basically ensures that dx and dy match which keys are currently being held) if(leftBeingPressed) dx = -1; @@ -85,22 +89,139 @@ public void keyReleased(KeyEvent e) { dy = 1; if(upBeingPressed) dy = -1; - + } + /** + * Moves the sprite using the current velocity and detects for collisions + */ public void move() { - if (x + dx >= 0 && x + dx <= mapui.getWidth() - WIDTH && y + dy >= 0 && y + dy <= mapui.getHeight() - WIDTH) { - x = x + dx; - changeInX = changeInX + dx; - y = y + dy; - changeInY = changeInY + dy; + if (collision()) { + + // If there is a collision, we check from which direction the collision occurs. During each collision the sprite is stopped and their position is reset so they are no longer collided. + if (mapui.getMap().collisionTo("east")) { + dx = 0; + setChangeInX(getChangeInX() - 1); + setX(getX() - 1); + } + if (mapui.getMap().collisionTo("west")) { + dx = 0; + setChangeInX(getChangeInX() + 1); + setX(getX() + 1); + } + if (mapui.getMap().collisionTo("north")) { + dy = 0; + setChangeInY(getChangeInY() + 1); + setY(getY() + 1); + } + if (mapui.getMap().collisionTo("south")) { + dy = 0; + setChangeInY(getChangeInY() - 1); + setY(getY() - 1); + } + if (mapui.getMap().collisionTo("northwest")) { + dy = 0; + dx = 0; + setChangeInY(getChangeInY() + 1); + setChangeInX(getChangeInX() + 1); + setY(getY() + 1); + setX(getX() + 1); + } + if (mapui.getMap().collisionTo("southwest")) { + dy = 0; + dx = 0; + setChangeInY(getChangeInY() - 1); + setChangeInX(getChangeInX() + 1); + setY(getY() - 1); + setX(getX() + 1); + } + if (mapui.getMap().collisionTo("northeast")) { + dy = 0; + dx = 0; + setChangeInY(getChangeInY() + 1); + setChangeInX(getChangeInX() - 1); + setY(getY() + 1); + setX(getX() - 1); + } + if (mapui.getMap().collisionTo("southeast")) { + dy = 0; + dx = 0; + setChangeInY(getChangeInY() - 1); + setChangeInX(getChangeInX() - 1); + setY(getY() - 1); + setX(getX() - 1); + } + + } + + // Checks that the sprite is moving within the bounds of the panel + if (getX() + dx >= 0 && getX() + dx <= mapui.getWidth() - WIDTH && getY() + dy >= 0 && getY() + dy <= mapui.getHeight() - WIDTH) { + setX(getX() + dx); + setChangeInX(getChangeInX() + dx); + setY(getY() + dy); + setChangeInY(getChangeInY() + dy); } - + } - + + /** + * Paints the sprite at its current location + * @param g Graphics2D for painting + */ public void paint(Graphics2D g) { g.setColor(color); - g.fillOval(x, y, WIDTH, WIDTH); + g.fillOval(getX(), getY(), WIDTH, WIDTH); + } + + /** + * Gets the bounds of the sprite in the form of a Rectangle + * @return the Rectangle formed by the sprite + */ + public Rectangle getBounds() { + return new Rectangle(getX(), getY(), WIDTH, WIDTH); + } + + /** + * Detects a collision between the PlayerSprite and any of the Merchantsprites + * @return + */ + public boolean collision() { + for (MerchantSprite merchant : mapui.getMerchants()) + if (merchant.getBounds().intersects(getBounds())) + return true; + return false; + } + + public int getChangeInX() { + return changeInX; + } + + public void setChangeInX(int changeInX) { + this.changeInX = changeInX; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getChangeInY() { + return changeInY; + } + + public void setChangeInY(int changeInY) { + this.changeInY = changeInY; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; } } diff --git a/MerchantRPGCSE2102/src/tests/MockGame.java b/MerchantRPGCSE2102/src/tests/MockGame.java index f7bd93a..f4b2692 100644 --- a/MerchantRPGCSE2102/src/tests/MockGame.java +++ b/MerchantRPGCSE2102/src/tests/MockGame.java @@ -11,25 +11,45 @@ public class MockGame { public static void main(String[] args) throws InterruptedException { - // This sets up the window for the game which is a 300 by 300 pixels JFrame - Player player = new Player("TestPlayer", 0, null); - Merchant merch = new Merchant("merch", 0, null); + + // SETTING UP PLAYER AND MERCHANT + Player player = new Player("Player", 0, null); + Merchant merch1 = new Merchant("Bill", 0, null); + Merchant merch2 = new Merchant("Joe", 0, null); + Merchant merch3 = new Merchant("Sam", 0, null); + + // CREATING MAP AND INITIALIZE PLAYER AND MERCHANTS Map map = new Map(30, 40); - map.initializePlayer(player, 0, 0); - map.initializeMerchant(merch, 10, 10); + map.initializePlayer(player, 15, 20); + map.initializeMerchant(merch1, 15, 0); + map.initializeMerchant(merch2, 29, 20); + map.initializeMerchant(merch3, 15, 39); + + // CREATING JFRAME WINDOW JFrame frame = new JFrame("Merchant RPG"); + + // CREATING MAPUI AND SPRITES MapUI mapui = new MapUI(map); + mapui.createPlayerSprite(15, 20); + mapui.addMerchantSprite(15, 0); + mapui.addMerchantSprite(29, 20); + mapui.addMerchantSprite(15, 39); + + // ADDING MAPUI TO JFRAME frame.add(mapui); + + // SETTING PROPERTIES OF JFRAME frame.setSize(RPGame.WIDTH, RPGame.HEIGHT); frame.setResizable(false); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); + // MAIN GAME LOOP while (true) { mapui.move(); mapui.repaint(); - Thread.sleep(10); + Thread.sleep(100/12); // Controls the speed of the game (currently 120 frames/second) } } diff --git a/MerchantRPGCSE2102/src/view/MapUI.java b/MerchantRPGCSE2102/src/view/MapUI.java index 1dc83e1..044fec6 100644 --- a/MerchantRPGCSE2102/src/view/MapUI.java +++ b/MerchantRPGCSE2102/src/view/MapUI.java @@ -7,17 +7,20 @@ import java.awt.RenderingHints; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.util.ArrayList; import javax.swing.JPanel; import model.Map; +import sprites.MerchantSprite; import sprites.PlayerSprite; @SuppressWarnings("serial") public class MapUI extends JPanel { - PlayerSprite player = new PlayerSprite(this); - Map map; + private Map map; + private PlayerSprite player; + private ArrayList merchants = new ArrayList(); public MapUI(Map map) { @@ -48,47 +51,88 @@ public void keyTyped(KeyEvent e) { @Override public void paint(Graphics g) { - super.paint(g); + super.paint(g); // repaints the canvas + Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Prevents aliasing + + // For testing purposes. Creates a grid of lines on the canvas for (int i = 0; i < map.getGraph().getCols(); i++) { for (int j = 0; j < map.getGraph().getRows(); j++) { g2d.fillRect(i*30, j*30, 1, 30); g2d.fillRect(i*30, j*30, 30, 1); } } + + // Paints the player onto the canvas player.paint(g2d); + // Paints each merchant onto the canvas + for (MerchantSprite merchant : merchants) + merchant.paint(g2d); + + // For testing purposes. Showes the Player's current x and y position as well as the current Vertex g2d.setColor(Color.GRAY); g2d.setFont(new Font("Verdana", Font.BOLD, 20)); - g2d.drawString("x: " + player.x + " y : " + player.y, 10, 20); - g2d.drawString("delta X: " + player.changeInX +" delta Y: " + player.changeInY, 10, 50); - g2d.drawString("Vertex: (" + map.getPlayer().getCol() + ", " + map.getPlayer().getRow() + ")", 1000, 20); + g2d.drawString("x: " + player.getX() + " y : " + player.getY(), 10, 20); + g2d.drawString("delta X: " + player.getChangeInX() +" delta Y: " + player.getChangeInY(), 10, 50); + g2d.drawString("Vertex: (" + map.getPlayer().getRow() + ", " + map.getPlayer().getCol() + ")", 1000, 20); + } + + /** + * Adds a MerchantSprite to the list of MerchantSprite's to be painted on the canvas + * @param row The row of the merchant + * @param col The column of the merchant + */ + public void addMerchantSprite(int row, int col) { + MerchantSprite merchant = new MerchantSprite(row, col); + merchants.add(merchant); + } + + /** + * Creates a player sprite to be painted on the canvas + * @param row The row of the player + * @param y The column of the player + */ + public void createPlayerSprite(int row, int col) { + player = new PlayerSprite(this, row, col); } + /** + * Moves the PlayerSprite as well as the Map's instance of Player + */ public void move() { player.move(); - if (player.changeInX == 31) { + // Every 30 pixels, the player will move to a new Vertex + // I used the values 0, 1, 30, 31 to establish a border between crossing Vertices + // For example, if the player reaches a changeInX of 31, this means they are moving to a Vertex in the east direction and their changeInX is reset to 1 + // if they then decide to move west, they will move to the next Vertex when their changeInX reaches 0. + // Thus, the border shared by two vertices is inbetween 0 and 1 as well as 30 and 31. + if (player.getChangeInX() == 31) { map.movePlayer("east"); - player.changeInX = 1; + player.setChangeInX(1); } - if (player.changeInX == 0) { + if (player.getChangeInX() == 0) { map.movePlayer("west"); - player.changeInX = 30; + player.setChangeInX(30); } - if (player.changeInY == 0) { + if (player.getChangeInY() == 0) { map.movePlayer("north"); - player.changeInY = 30; + player.setChangeInY(30); } - if (player.changeInY == 31) { + if (player.getChangeInY() == 31) { map.movePlayer("south"); - player.changeInY = 1; + player.setChangeInY(1); } } public Map getMap() { return map; } + + public ArrayList getMerchants() { + return merchants; + } }