Fixed image loading, added rendering, added JMenu
| @@ -1,11 +1,11 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <classpath> | ||||
| 	<classpathentry kind="src" path="src"/> | ||||
| 	<classpathentry kind="src" path="res"/> | ||||
| 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"> | ||||
| 		<attributes> | ||||
| 			<attribute name="module" value="true"/> | ||||
| 		</attributes> | ||||
| 	</classpathentry> | ||||
| 	<classpathentry kind="lib" path="res"/> | ||||
| 	<classpathentry kind="output" path="bin"/> | ||||
| </classpath> | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								res/Flag.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 70 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Mine.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 118 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Mine2.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 126 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Mine3.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 105 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Mine4.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 102 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Smiley.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 100 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Smiley1.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 92 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Smiley2.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 97 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Smiley3.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 46 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Tile.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 61 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Tile2.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 60 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Tile3.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 71 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/Tile4.ico
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 58 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/flag.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/mine.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 9.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/mine2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 8.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/mine3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/mine4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/smiley.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 8.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/smiley1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/smiley2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/smiley3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 28 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/tile.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/tile2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/tile3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								res/tile4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.9 KiB | 
| @@ -1,12 +1,17 @@ | ||||
| package dev.kske.minesweeper; | ||||
|  | ||||
| import java.awt.Color; | ||||
| import java.awt.Font; | ||||
| import java.awt.FontMetrics; | ||||
| import java.awt.Graphics; | ||||
| import java.awt.Image; | ||||
| import java.awt.Point; | ||||
| import java.awt.Rectangle; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.Random; | ||||
|  | ||||
| import javax.swing.JFrame; | ||||
| import javax.swing.JPanel; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>Minesweeper</strong><br> | ||||
| @@ -14,23 +19,34 @@ import javax.swing.JFrame; | ||||
|  * Created: <strong>22.03.2019</strong><br> | ||||
|  * Author: <strong>Kai S. K. Engelbart</strong> | ||||
|  */ | ||||
| public class Board { | ||||
| public class Board extends JPanel { | ||||
|  | ||||
| 	private int			tileSize, width, height; | ||||
| 	private static final long	serialVersionUID	= -279269871397851420L; | ||||
| 	private static final int	tileSize			= 32; | ||||
|  | ||||
| 	private static Map<String, Image> icons; | ||||
|  | ||||
| 	private int			width, height; | ||||
| 	private Rectangle	screen; | ||||
|  | ||||
| 	private GameState	gameState; | ||||
| 	private int			mines, activeTiles, flaggedTiles; | ||||
| 	private Tile[][]	board; | ||||
|  | ||||
| 	private final JFrame viewport; | ||||
| 	static { | ||||
| 		icons = new HashMap<>(); | ||||
| 		final String[] names = { "mine2", "mine4", "tile", "tile3", "flag" }; | ||||
| 		for (String name : names) { | ||||
| 			icons.put(name, TextureLoader.loadScaledImage(name, tileSize)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public Board(int x, int y, int width, int height, int tileSize, int mines, JFrame viewport) { | ||||
| 		this.tileSize	= tileSize; | ||||
| 	public Board(int x, int y, int width, int height, int mines) { | ||||
| 		// Not using a layout manager | ||||
| 		super(null); | ||||
| 		this.width	= width; | ||||
| 		this.height	= height; | ||||
| 		screen		= new Rectangle(x, y, x + width * tileSize, y + height * tileSize); | ||||
| 		this.viewport	= viewport; | ||||
|  | ||||
| 		gameState		= GameState.ACTIVE; | ||||
| 		this.mines		= mines; | ||||
| @@ -43,6 +59,56 @@ public class Board { | ||||
| 				board[i][j] = new Tile(); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void paintComponent(Graphics g) { | ||||
| 		super.paintComponent(g); | ||||
| 		for (int i = 0; i < width; i++) | ||||
| 			for (int j = 0; j < height; j++) { | ||||
| 				Tile	tile	= board[i][j]; | ||||
| 				int		x		= screen.x + i * tileSize, y = screen.y + j * tileSize; | ||||
|  | ||||
| 				// Draw background with grid | ||||
| 				g.setColor(Color.gray); | ||||
| 				g.fillRect(x, y, x + tileSize, y + tileSize); | ||||
| 				g.setColor(Color.black); | ||||
| 				g.drawRect(x, y, x + tileSize, y + tileSize); | ||||
|  | ||||
| 				// Draw all mines when the game is won or lost | ||||
| 				switch (gameState) { | ||||
| 					case LOST: | ||||
| 						// Draw tile with normal mine | ||||
| 						g.drawImage(icons.get("mine2"), x, y, this); | ||||
| 						break; | ||||
| 					case WON: | ||||
| 						// Draw tile with diffused mine | ||||
| 						g.drawImage(icons.get("mine4"), x, y, this); | ||||
| 						break; | ||||
| 					default: | ||||
| 						if (tile.isTouched()) { | ||||
|  | ||||
| 							// Draw tile with mine | ||||
| 							if (tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this); | ||||
|  | ||||
| 							// Draw flagged tile | ||||
| 							else if (tile.isDrawSurroundingMines() && tile.getSurroundingMines() > 0) { | ||||
| 								// Draw number of surrounding mines | ||||
| 								String		numStr	= String.valueOf(tile.getSurroundingMines()); | ||||
| 								FontMetrics	fm		= g.getFontMetrics(); | ||||
| 								int			w		= fm.stringWidth(numStr), h = fm.getHeight(); | ||||
| 								g.setFont(new Font("Helvetica", Font.PLAIN, 12)); | ||||
| 								g.drawString(numStr, x + tileSize / 2 - w / 2, y + tileSize / 2 - h / 2); | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| 						// Draw flagged tile | ||||
| 						else if (tile.isFlagged()) g.drawImage(icons.get("flag"), x, y, this); | ||||
|  | ||||
| 						// Draw normal tile | ||||
| 						else g.drawImage(icons.get("tile"), x, y, this); | ||||
| 				} | ||||
| 			} | ||||
| 	} | ||||
|  | ||||
| 	public Point getTilePos(int x, int y) { | ||||
| 		return new Point((x - screen.x) / tileSize, (y - screen.y) / tileSize); | ||||
| 	} | ||||
| @@ -95,7 +161,7 @@ public class Board { | ||||
| 				touchTile(i, j); | ||||
|  | ||||
| 			// Redraw the touched tile | ||||
| 			drawTile(n, m); | ||||
| 			repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -109,28 +175,7 @@ public class Board { | ||||
| 				tile.setFlagged(true); | ||||
| 				flaggedTiles++; | ||||
| 			} | ||||
| 			drawTile(n, m); | ||||
| 			repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public void draw() { | ||||
| 		for(int i = 0; i < width; i++) | ||||
| 			for (int j = 0; j < height; j++) | ||||
| 				drawTile(i, j); | ||||
| 	} | ||||
|  | ||||
| 	public void drawTile(int n, int m) { | ||||
| 		Tile	tile	= board[n][m]; | ||||
| 		int		x		= screen.x + n * tileSize, y = screen.y + m * tileSize; | ||||
| 		Graphics	g		= viewport.getGraphics(); | ||||
|  | ||||
| 		// Draw background with grid | ||||
| 		g.setColor(Color.gray); | ||||
| 		g.fillRect(x, y, x + tileSize, y + tileSize); | ||||
| 		g.setColor(Color.black); | ||||
| 		g.drawRect(x, y, x + tileSize, y + tileSize); | ||||
|  | ||||
| 		// Draw all mines if the game is lost | ||||
| 		// if(gameState == GameState.LOST) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,15 @@ | ||||
| package dev.kske.minesweeper; | ||||
|  | ||||
| import java.awt.BorderLayout; | ||||
| import java.awt.EventQueue; | ||||
| import java.awt.event.KeyEvent; | ||||
|  | ||||
| import javax.swing.JButton; | ||||
| import javax.swing.JFrame; | ||||
| import javax.swing.JMenu; | ||||
| import javax.swing.JMenuBar; | ||||
| import javax.swing.JMenuItem; | ||||
| import javax.swing.JOptionPane; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>Minesweeper</strong><br> | ||||
| @@ -12,6 +19,8 @@ import javax.swing.JFrame; | ||||
|  */ | ||||
| public class Minesweeper { | ||||
|  | ||||
| 	private static final String VERSION = "1.0 JE"; | ||||
|  | ||||
| 	private JFrame mframe; | ||||
|  | ||||
| 	private Board board; | ||||
| @@ -50,8 +59,44 @@ public class Minesweeper { | ||||
| 		mframe.setBounds(100, 100, 450, 300); | ||||
| 		mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|  | ||||
| 		board = new Board(0, 0, 10, 10, 32, 10, mframe); | ||||
| 		board.draw(); | ||||
| 		createMenuBar(); | ||||
|  | ||||
| 		board = new Board(0, 0, 10, 10, 10); | ||||
| 		mframe.getContentPane().add(board); | ||||
|  | ||||
| 		JButton btnRestart = new JButton("Restart"); | ||||
| 		mframe.getContentPane().add(btnRestart, BorderLayout.NORTH); | ||||
| 	} | ||||
|  | ||||
| 	private void createMenuBar() { | ||||
| 		var menubar = new JMenuBar(); | ||||
|  | ||||
| 		var gameMenu = new JMenu("Game"); | ||||
| 		var	aboutMenuItem	= new JMenuItem("About"); | ||||
|  | ||||
| 		var	easyMenuItem	= new JMenuItem("Easy"); | ||||
| 		var	mediumMenuItem	= new JMenuItem("Medium"); | ||||
| 		var	hardMenuItem	= new JMenuItem("Hard"); | ||||
| 		var	customMenuItem	= new JMenuItem("Custom"); | ||||
|  | ||||
| 		gameMenu.setMnemonic(KeyEvent.VK_G); | ||||
| 		easyMenuItem.setMnemonic(KeyEvent.VK_E); | ||||
| 		mediumMenuItem.setMnemonic(KeyEvent.VK_M); | ||||
| 		hardMenuItem.setMnemonic(KeyEvent.VK_H); | ||||
| 		customMenuItem.setMnemonic(KeyEvent.VK_C); | ||||
|  | ||||
| 		aboutMenuItem.addActionListener((event) -> { | ||||
| 			JOptionPane.showMessageDialog(board, "Minesweeper version " + VERSION + "\nby Kai S. K. Engelbart"); | ||||
| 		}); | ||||
| 		 | ||||
| 		gameMenu.add(easyMenuItem); | ||||
| 		gameMenu.add(mediumMenuItem); | ||||
| 		gameMenu.add(hardMenuItem); | ||||
| 		gameMenu.addSeparator(); | ||||
| 		gameMenu.add(customMenuItem); | ||||
| 		menubar.add(gameMenu); | ||||
| 		menubar.add(aboutMenuItem); | ||||
|  | ||||
| 		mframe.setJMenuBar(menubar); | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										38
									
								
								src/dev/kske/minesweeper/TextureLoader.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,38 @@ | ||||
| package dev.kske.minesweeper; | ||||
|  | ||||
| import java.awt.Image; | ||||
| import java.awt.image.BufferedImage; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
|  | ||||
| import javax.imageio.ImageIO; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>Minesweeper</strong><br> | ||||
|  * File: <strong>TextureLoader.java</strong><br> | ||||
|  * Created: <strong>25.03.2019</strong><br> | ||||
|  * Author: <strong>Kai S. K. Engelbart</strong> | ||||
|  */ | ||||
| public class TextureLoader { | ||||
|  | ||||
| 	private TextureLoader() {} | ||||
|  | ||||
| 	/** | ||||
| 	 * Loads an image from the resource folder and scales it to a square. | ||||
| 	 *  | ||||
| 	 * @param name  The name of the file without the PNG extension in the resource | ||||
| 	 *              folder | ||||
| 	 * @param scale The side length of the square to which the image will be scaled | ||||
| 	 * @return The scaled image | ||||
| 	 */ | ||||
| 	public static Image loadScaledImage(String name, int scale) { | ||||
| 		BufferedImage in = null; | ||||
| 		try { | ||||
| 			in = ImageIO.read(new File("res" + File.separator + name + ".png")); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 		Image scaled = in.getScaledInstance(scale, scale, Image.SCALE_SMOOTH); | ||||
| 		return scaled; | ||||
| 	} | ||||
| } | ||||
| @@ -1,13 +1,5 @@ | ||||
| package dev.kske.minesweeper; | ||||
|  | ||||
| import java.awt.image.BufferedImage; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| import javax.imageio.ImageIO; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>Minesweeper</strong><br> | ||||
|  * File: <strong>Tile.java</strong><br> | ||||
| @@ -16,27 +8,11 @@ import javax.imageio.ImageIO; | ||||
|  */ | ||||
| public class Tile { | ||||
|  | ||||
| 	private static Map<String, BufferedImage> icons; | ||||
|  | ||||
| 	private boolean mine, flagged, touched; | ||||
|  | ||||
| 	private boolean	drawSurroundingMines; | ||||
| 	private int		surroundingMines; | ||||
|  | ||||
| 	static { | ||||
| 		icons = new HashMap<>(); | ||||
| 		final String[] names = { "Mine2", "Mine4", "Tile", "Tile3" }; | ||||
| 		for (String name : names) { | ||||
| 			URL file = Tile.class.getResource(name + ".ico"); | ||||
| 			try { | ||||
| 				icons.put(name, ImageIO.read(file)); | ||||
| 			} catch (IOException e) { | ||||
| 				System.err.println("Error loading texture: " + name); | ||||
| 				e.printStackTrace(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public Tile() { | ||||
| 		mine = flagged = touched = drawSurroundingMines = false; | ||||
|  | ||||
|   | ||||