diff --git a/MerchantRPGCSE2102/src/controller/RPGame.java b/MerchantRPGCSE2102/src/controller/RPGame.java index a643482..9711281 100644 --- a/MerchantRPGCSE2102/src/controller/RPGame.java +++ b/MerchantRPGCSE2102/src/controller/RPGame.java @@ -5,10 +5,15 @@ import java.util.ArrayList; import java.util.Scanner; +import javax.swing.JFrame; + import model.Merchant; import model.Player; +import view.MapUI; public class RPGame { + public static final int WIDTH = 1206; + public static final int HEIGHT = 929; private ArrayList merchantInventoryList1 = new ArrayList(); // merchant 1's inventory list private ArrayList merchantInventoryList2 = new ArrayList(); // merchant 2's inventory list private ArrayList merchantInventoryList3 = new ArrayList(); // merchant 3's inventory list @@ -250,8 +255,9 @@ public int getDay() /** * Main method used to test the GUI components since test classes do not maintain the GUI * @param args no need for input + * @throws InterruptedException */ - public static void main(String[] args) + public static void main(String[] args) throws InterruptedException { RPGame _rpg = new RPGame(); _rpg.buildMerchants(); diff --git a/MerchantRPGCSE2102/src/graph/Graph.java b/MerchantRPGCSE2102/src/graph/Graph.java index 1acff8b..ce7dc19 100644 --- a/MerchantRPGCSE2102/src/graph/Graph.java +++ b/MerchantRPGCSE2102/src/graph/Graph.java @@ -3,12 +3,14 @@ public class Graph { private Vertex[] _vertexList; - private int _size; + private int _rows; + private int _cols; - public Graph(int size) + public Graph(int rows, int cols) { - _size = size; - _vertexList = new Vertex[size*size]; + _rows = rows; + _cols = cols; + _vertexList = new Vertex[rows*cols]; } public void initializeGraph() { @@ -17,24 +19,25 @@ public void initializeGraph() { } public void initializeVertices() { - for (int row = 0; row < _size; row++) { - for (int col = 0; col < _size; col++) { - int cellNum = row*_size + col; - Vertex v = new Vertex(cellNum, _size); + for (int row = 0; row < _rows; row++) { + for (int col = 0; col < _cols; col++) { + int cellNum = row*_cols + col; + Vertex v = new Vertex(cellNum, row, col); setVertex(cellNum, v); } } } public void initializeEdges() { - for (int row = 0; row < _size; row++) { - for (int col = 0; col < _size; col++) { + for (int row = 0; row < _rows; row++) { + for (int col = 0; col < _cols; col++) { - if (row !=0) - connectWithEdge(getVertex(_size*row + col), getVertex(_size*(row - 1) + col)); + if (row !=0) { + connectWithEdge(getVertex(_cols*row + col), getVertex(_cols*(row - 1) + col)); + } - if (col != _size - 1) - connectWithEdge(getVertex(_size*row + col), getVertex(_size*row + col + 1)); + if (col != _cols - 1) + connectWithEdge(getVertex(_cols*row + col), getVertex(_cols*row + col + 1)); } } } @@ -47,9 +50,14 @@ public void connectWithEdge(Vertex v, Vertex w) { edge.setW(w); } - public int getSize() + public int getRows() { - return _size; + return _rows; + } + + public int getCols() + { + return _cols; } public Vertex getVertex(int vertexNum) diff --git a/MerchantRPGCSE2102/src/graph/Vertex.java b/MerchantRPGCSE2102/src/graph/Vertex.java index 4b69807..c904344 100644 --- a/MerchantRPGCSE2102/src/graph/Vertex.java +++ b/MerchantRPGCSE2102/src/graph/Vertex.java @@ -11,15 +11,10 @@ public class Vertex private LinkedList _incidentEdges = new LinkedList(); - public Vertex(int cellNum, int n) { + public Vertex(int cellNum, int row, int col) { + _row = row; + _col = col; _cellNum = cellNum; - _row = 0; - int temp = _cellNum; - while (temp - n >= 0) { // Calculates the row of the vertex - temp = temp - n; - _row++; - } - _col = _cellNum - _row*n; // Calculates the column of the vertex } public void addEdge(Edge edge) { diff --git a/MerchantRPGCSE2102/src/images/background.jpg b/MerchantRPGCSE2102/src/images/background.jpg new file mode 100644 index 0000000..4c64943 Binary files /dev/null and b/MerchantRPGCSE2102/src/images/background.jpg differ diff --git a/MerchantRPGCSE2102/src/images/icon.png b/MerchantRPGCSE2102/src/images/icon.png new file mode 100644 index 0000000..b5d509b Binary files /dev/null and b/MerchantRPGCSE2102/src/images/icon.png differ diff --git a/MerchantRPGCSE2102/src/model/Map.java b/MerchantRPGCSE2102/src/model/Map.java index a27537c..78ae804 100644 --- a/MerchantRPGCSE2102/src/model/Map.java +++ b/MerchantRPGCSE2102/src/model/Map.java @@ -4,13 +4,14 @@ public class Map { - private Graph _mapGraph; // Graph representation of the map - private int _mapSize; // The n*n dimension of the map + private Graph _mapGraph; // Graph representation of the map + private int _rows, _cols; // The n*n dimension of the map private Player _player; - public Map(int size) { - _mapSize = size; - _mapGraph = new Graph(_mapSize); + public Map(int rows, int cols) { + _rows = rows; + _cols = cols; + _mapGraph = new Graph(_rows, _cols); _mapGraph.initializeGraph(); } @@ -21,8 +22,8 @@ public Map(int size) { * @param y The y coordinate of the player's location */ public void initializePlayer(Player player, int x, int y) { - _player = player; - int vertexNum = y*_mapSize + x; + _player = player; + int vertexNum = y*_cols + x; player.setX(x); player.setY(y); _mapGraph.getVertex(vertexNum).setOccupant(player); @@ -35,7 +36,7 @@ public void initializePlayer(Player player, int x, int y) { * @param y The y coordinate of the merchant's location */ public void initializeMerchant(Merchant merchant, int x, int y) { - int vertexNum = y*_mapSize + x; + int vertexNum = y*_cols + x; merchant.setX(x); merchant.setY(y); _mapGraph.getVertex(vertexNum).setOccupant(merchant); @@ -51,29 +52,29 @@ public void movePlayer(String direction) { if (direction.equals("north")) { if (currentY != 0) { - if (!isOccupied(currentX, currentY - 1)) { - _mapGraph.getVertex(currentY*_mapSize + currentX).setOccupant(null); - _mapGraph.getVertex((currentY - 1)*_mapSize + currentX).setOccupant(_player); + if (!isOccupied(currentX, currentY - 1)) { + _mapGraph.getVertex(currentY*_cols + currentX).setOccupant(null); + _mapGraph.getVertex((currentY - 1)*_cols + currentX).setOccupant(_player); _player.setY(currentY - 1); } } } if (direction.equals("east")) { - if (currentX != _mapSize - 1) { - if (!isOccupied(currentX + 1, currentY)) { - _mapGraph.getVertex(currentY*_mapSize + currentX).setOccupant(null); - _mapGraph.getVertex(currentY*_mapSize + (currentX + 1)).setOccupant(_player); + 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.setX(currentX + 1); } } } if (direction.equals("south")) { - if (currentY != _mapSize - 1) { - if (!isOccupied(currentX, currentY + 1)) { - _mapGraph.getVertex(currentY*_mapSize + currentX).setOccupant(null); - _mapGraph.getVertex((currentY + 1)*_mapSize + currentX).setOccupant(_player); + 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.setY(currentY + 1); } } @@ -81,13 +82,14 @@ public void movePlayer(String direction) { if (direction.equals("west")) { if (currentX != 0) { - if (!isOccupied(currentX - 1, currentY)) { - _mapGraph.getVertex(currentY*_mapSize + currentX).setOccupant(null); - _mapGraph.getVertex(currentY*_mapSize + (currentX - 1)).setOccupant(_player); + if (!isOccupied(currentX - 1, currentY)) { + _mapGraph.getVertex(currentY*_cols + currentX).setOccupant(null); + _mapGraph.getVertex(currentY*_cols + (currentX - 1)).setOccupant(_player); _player.setX(currentX - 1); } } } + System.out.println("Player is at vertex (" + _player.getX() + ", " + _player.getY() + ")"); } /** @@ -105,7 +107,7 @@ public Graph getGraph() { * @return Boolean value */ public boolean isOccupied(int x, int y) { - return _mapGraph.getVertex(y*_mapSize + x).getOccupant() != null; + return _mapGraph.getVertex(y*_cols + x).getOccupant() != null; } } diff --git a/MerchantRPGCSE2102/src/sprites/PlayerSprite.java b/MerchantRPGCSE2102/src/sprites/PlayerSprite.java new file mode 100644 index 0000000..9b1f91f --- /dev/null +++ b/MerchantRPGCSE2102/src/sprites/PlayerSprite.java @@ -0,0 +1,98 @@ +package sprites; + +import java.awt.Color; +import java.awt.Graphics2D; +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 = 0; + public int changeInY = 0; + Color color = new Color(0, 0, 0); + boolean leftBeingPressed = false; + boolean rightBeingPressed = false; + boolean downBeingPressed = false; + boolean upBeingPressed = false; + + public PlayerSprite(MapUI mapui) { + this.mapui = mapui; + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_LEFT) { + dx = -1; + leftBeingPressed = true; + } + if (e.getKeyCode() == KeyEvent.VK_RIGHT) { + dx = 1; + rightBeingPressed = true; + } + if (e.getKeyCode() == KeyEvent.VK_UP) { + dy = -1; + upBeingPressed = true; + } + if (e.getKeyCode() == KeyEvent.VK_DOWN) { + dy = 1; + downBeingPressed = true; + } + } + + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_LEFT) { + leftBeingPressed = false; + if (rightBeingPressed == false) + dx = 0; + } + + if (e.getKeyCode() == KeyEvent.VK_RIGHT) { + rightBeingPressed = false; + if (leftBeingPressed == false) + dx = 0; + } + + if (e.getKeyCode() == KeyEvent.VK_UP) { + upBeingPressed = false; + if (downBeingPressed == false) + dy = 0; + } + + if (e.getKeyCode() == KeyEvent.VK_DOWN) { + downBeingPressed = false; + if (upBeingPressed == false) + 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; + if(rightBeingPressed) + dx = 1; + if(downBeingPressed) + dy = 1; + if(upBeingPressed) + dy = -1; + + } + + 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; + } + + } + + public void paint(Graphics2D g) { + g.setColor(color); + g.fillOval(x, y, WIDTH, WIDTH); + } + +} diff --git a/MerchantRPGCSE2102/src/tests/MockGame.java b/MerchantRPGCSE2102/src/tests/MockGame.java new file mode 100644 index 0000000..1856265 --- /dev/null +++ b/MerchantRPGCSE2102/src/tests/MockGame.java @@ -0,0 +1,33 @@ +package tests; + +import javax.swing.JFrame; + +import model.Map; +import model.Player; +import view.MapUI; +import controller.RPGame; + +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); + Map map = new Map(30, 40); + map.initializePlayer(player, 0, 0); + JFrame frame = new JFrame("Merchant RPG"); + MapUI mapui = new MapUI(map); + frame.add(mapui); + frame.setSize(RPGame.WIDTH, RPGame.HEIGHT); + frame.setResizable(false); + frame.setVisible(true); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + + while (true) { + mapui.move(); + mapui.repaint(); + Thread.sleep(10); + } + } + +} diff --git a/MerchantRPGCSE2102/src/tests/TestMap.java b/MerchantRPGCSE2102/src/tests/TestMap.java index 0c99c18..3475d69 100644 --- a/MerchantRPGCSE2102/src/tests/TestMap.java +++ b/MerchantRPGCSE2102/src/tests/TestMap.java @@ -23,7 +23,7 @@ public void test() { } public void setup() { - map = new Map(4); + map = new Map(4, 4); } public void testMapInit() { diff --git a/MerchantRPGCSE2102/src/view/BackgroundPanel.java b/MerchantRPGCSE2102/src/view/BackgroundPanel.java new file mode 100644 index 0000000..48434ed --- /dev/null +++ b/MerchantRPGCSE2102/src/view/BackgroundPanel.java @@ -0,0 +1,262 @@ +package view; +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; + +/* + * Support custom painting on a panel in the form of + * + * a) images - that can be scaled, tiled or painted at original size + * b) non solid painting - that can be done by using a Paint object + * + * Also, any component added directly to this panel will be made + * non-opaque so that the custom painting can show through. + */ +public class BackgroundPanel extends JPanel +{ + public static final int SCALED = 0; + public static final int TILED = 1; + public static final int ACTUAL = 2; + + private Paint painter; + private Image image; + private int style = SCALED; + private float alignmentX = 0.5f; + private float alignmentY = 0.5f; + private boolean isTransparentAdd = true; + + /* + * Set image as the background with the SCALED style + */ + public BackgroundPanel(Image image) + { + this(image, SCALED); + } + + /* + * Set image as the background with the specified style + */ + public BackgroundPanel(Image image, int style) + { + setImage( image ); + setStyle( style ); + setLayout( new BorderLayout() ); + } + + /* + * Set image as the backround with the specified style and alignment + */ + public BackgroundPanel(Image image, int style, float alignmentX, float alignmentY) + { + setImage( image ); + setStyle( style ); + setImageAlignmentX( alignmentX ); + setImageAlignmentY( alignmentY ); + setLayout( new BorderLayout() ); + } + + /* + * Use the Paint interface to paint a background + */ + public BackgroundPanel(Paint painter) + { + setPaint( painter ); + setLayout( new BorderLayout() ); + } + + /* + * Set the image used as the background + */ + public void setImage(Image image) + { + this.image = image; + repaint(); + } + + /* + * Set the style used to paint the background image + */ + public void setStyle(int style) + { + this.style = style; + repaint(); + } + + /* + * Set the Paint object used to paint the background + */ + public void setPaint(Paint painter) + { + this.painter = painter; + repaint(); + } + + /* + * Specify the horizontal alignment of the image when using ACTUAL style + */ + public void setImageAlignmentX(float alignmentX) + { + this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX; + repaint(); + } + + /* + * Specify the horizontal alignment of the image when using ACTUAL style + */ + public void setImageAlignmentY(float alignmentY) + { + this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY; + repaint(); + } + + /* + * Override method so we can make the component transparent + */ + public void add(JComponent component) + { + add(component, null); + } + + /* + * Override to provide a preferred size equal to the image size + */ + @Override + public Dimension getPreferredSize() + { + if (image == null) + return super.getPreferredSize(); + else + return new Dimension(image.getWidth(null), image.getHeight(null)); + } + + /* + * Override method so we can make the component transparent + */ + public void add(JComponent component, Object constraints) + { + if (isTransparentAdd) + { + makeComponentTransparent(component); + } + + super.add(component, constraints); + } + + /* + * Controls whether components added to this panel should automatically + * be made transparent. That is, setOpaque(false) will be invoked. + * The default is set to true. + */ + public void setTransparentAdd(boolean isTransparentAdd) + { + this.isTransparentAdd = isTransparentAdd; + } + + /* + * Try to make the component transparent. + * For components that use renderers, like JTable, you will also need to + * change the renderer to be transparent. An easy way to do this it to + * set the background of the table to a Color using an alpha value of 0. + */ + private void makeComponentTransparent(JComponent component) + { + component.setOpaque( false ); + + if (component instanceof JScrollPane) + { + JScrollPane scrollPane = (JScrollPane)component; + JViewport viewport = scrollPane.getViewport(); + viewport.setOpaque( false ); + Component c = viewport.getView(); + + if (c instanceof JComponent) + { + ((JComponent)c).setOpaque( false ); + } + } + } + + /* + * Add custom painting + */ + @Override + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + + // Invoke the painter for the background + + if (painter != null) + { + Dimension d = getSize(); + Graphics2D g2 = (Graphics2D) g; + g2.setPaint(painter); + g2.fill( new Rectangle(0, 0, d.width, d.height) ); + } + + // Draw the image + + if (image == null ) return; + + switch (style) + { + case SCALED : + drawScaled(g); + break; + + case TILED : + drawTiled(g); + break; + + case ACTUAL : + drawActual(g); + break; + + default: + drawScaled(g); + } + } + + /* + * Custom painting code for drawing a SCALED image as the background + */ + private void drawScaled(Graphics g) + { + Dimension d = getSize(); + g.drawImage(image, 0, 0, d.width, d.height, null); + } + + /* + * Custom painting code for drawing TILED images as the background + */ + private void drawTiled(Graphics g) + { + Dimension d = getSize(); + int width = image.getWidth( null ); + int height = image.getHeight( null ); + + for (int x = 0; x < d.width; x += width) + { + for (int y = 0; y < d.height; y += height) + { + g.drawImage( image, x, y, null, null ); + } + } + } + + /* + * Custom painting code for drawing the ACTUAL image as the background. + * The image is positioned in the panel based on the horizontal and + * vertical alignments specified. + */ + private void drawActual(Graphics g) + { + Dimension d = getSize(); + Insets insets = getInsets(); + int width = d.width - insets.left - insets.right; + int height = d.height - insets.top - insets.left; + float x = (width - image.getWidth(null)) * alignmentX; + float y = (height - image.getHeight(null)) * alignmentY; + g.drawImage(image, (int)x + insets.left, (int)y + insets.top, this); + } +} \ No newline at end of file diff --git a/MerchantRPGCSE2102/src/view/MapUI.java b/MerchantRPGCSE2102/src/view/MapUI.java new file mode 100644 index 0000000..68294ac --- /dev/null +++ b/MerchantRPGCSE2102/src/view/MapUI.java @@ -0,0 +1,83 @@ +package view; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.JPanel; + +import model.Map; +import sprites.PlayerSprite; + +@SuppressWarnings("serial") +public class MapUI extends JPanel { + + PlayerSprite player = new PlayerSprite(this); + Map map; + + + public MapUI(Map map) { + this.map = map; + addKeyListener(new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + player.keyPressed(e); + + } + + @Override + public void keyReleased(KeyEvent e) { + player.keyReleased(e); + + } + + @Override + public void keyTyped(KeyEvent e) { + + } + + }); + setFocusable(true); + } + + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + player.paint(g2d); + 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); + } + + public void move() { + player.move(); + + if (player.changeInX == 30) { + map.movePlayer("east"); + player.changeInX = 0; + } + if (player.changeInX == -30) { + map.movePlayer("west"); + player.changeInX = 0; + } + if (player.changeInY == -30) { + map.movePlayer("north"); + player.changeInY = 0; + } + if (player.changeInY == 30) { + map.movePlayer("south"); + player.changeInY = 0; + } + } + + +} diff --git a/MerchantRPGCSE2102/src/view/StartScreen.java b/MerchantRPGCSE2102/src/view/StartScreen.java new file mode 100644 index 0000000..d7e8e4a --- /dev/null +++ b/MerchantRPGCSE2102/src/view/StartScreen.java @@ -0,0 +1,82 @@ +package view; + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +public class StartScreen extends JFrame { + private static final long serialVersionUID = 1L; + JPanel startMenu = new JPanel(); + + public static void main(String[] args) throws IOException { + new StartScreen(); + } + + public StartScreen() throws IOException { + Image icon, background; + icon = loadIcon(); + background = loadBackground(); + BackgroundPanel panel = new BackgroundPanel(background, BackgroundPanel.ACTUAL, 1.0f, 0.5f); + this.setIconImage(icon); + this.setTitle("The Merchant RPG"); + this.setSize(1500, 844); + this.setLocationRelativeTo(null); + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + this.setResizable(false); + this.setVisible(true); + JButton start = new JButton("Start"); + start.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e){ + System.out.println("Game started"); + } + }); + JButton instructions = new JButton("Instructions"); + instructions.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e){ + System.out.println("Instructions opened"); + } + }); + this.getContentPane().setLayout(null); + start.setBounds(650, 382, 200, 80); + instructions.setBounds(650, 482, 200, 40); + panel.setBounds(0, 0, 1500, 844); + start.setBackground(null); + instructions.setBackground(null); + this.add(panel); + this.add(instructions); + this.add(start); + } + + public BufferedImage loadIcon() throws IOException { + BufferedImage img = null; + try { + img = ImageIO.read(new File("src/images/icon.png")); + return img; + } catch (IOException e) { + System.out.println("File not found"); + return null; + } + } + + public BufferedImage loadBackground() throws IOException { + BufferedImage img = null; + try { + img = ImageIO.read(new File("src/images/background.jpg")); + return img; + } catch (IOException e) { + System.out.println("File not found"); + return null; + } + } + +}