Fixed image loading, added rendering, added JMenu

This commit is contained in:
Kai S. K. Engelbart 2019-03-26 13:45:41 +01:00
parent 6e5befdbe8
commit 892d6be2ef
Signed by: kske
GPG Key ID: 8BEB13EC5DF7EF13
31 changed files with 164 additions and 60 deletions

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

BIN
res/flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
res/mine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
res/mine2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
res/mine3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
res/mine4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
res/smiley.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
res/smiley1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
res/smiley2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
res/smiley3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
res/tile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
res/tile2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
res/tile3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
res/tile4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -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;
this.width = width;
this.height = height;
screen = new Rectangle(x, y, x + width * tileSize, y + height * tileSize);
this.viewport = viewport;
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);
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)
}
}

View File

@ -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);
}
}

View 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;
}
}

View File

@ -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;