GUI updates. Added sound effect for playing a stone.
This commit is contained in:
@@ -39,7 +39,13 @@ public class Referee {
|
||||
GameRecord gameRecord = new GameRecord(gameConfig);
|
||||
|
||||
System.out.println("Game started.");
|
||||
|
||||
|
||||
GameState initialGameState = gameRecord.getGameState(gameRecord.getNumTurns());
|
||||
|
||||
//Allow policy / GUI to do setup.
|
||||
blackPolicy.setState(initialGameState);
|
||||
whitePolicy.setState(initialGameState);
|
||||
|
||||
try {
|
||||
while (!gameRecord.isFinished()) {
|
||||
GameState gameState = gameRecord.getGameState(gameRecord.getNumTurns());
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.woodyfolsom.msproj.gui;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
@@ -12,16 +14,32 @@ import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
import net.woodyfolsom.msproj.sfx.SfxPlayer;
|
||||
|
||||
public class Goban extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private GridPanel gridPanel;
|
||||
private SfxPlayer sfxPlayer;
|
||||
|
||||
public Goban(GameConfig gameConfig, Player guiPlayer) {
|
||||
setLayout(new BorderLayout());
|
||||
this.gridPanel = new GridPanel(gameConfig, guiPlayer);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
sfxPlayer.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
sfxPlayer = new SfxPlayer();
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Unable to initialize click sound due to: " + ex.getMessage());
|
||||
}
|
||||
|
||||
this.gridPanel = new GridPanel(gameConfig, guiPlayer, sfxPlayer);
|
||||
add(gridPanel,BorderLayout.CENTER);
|
||||
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.woodyfolsom.msproj.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
@@ -19,14 +20,15 @@ import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
import net.woodyfolsom.msproj.sfx.SfxPlayer;
|
||||
|
||||
public class GridPanel extends JPanel implements MouseListener,
|
||||
MouseMotionListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int BOARD_HEIGHT = 300;
|
||||
private static final int BOARD_WIDTH = 300;
|
||||
private final int boardPixelWidth;
|
||||
|
||||
private static final int BORDER_WIDTH = 10;
|
||||
|
||||
private static final int DOT_WIDTH = 5;
|
||||
@@ -37,43 +39,36 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
|
||||
private int mouseX = 0;
|
||||
private int mouseY = 0;
|
||||
|
||||
//
|
||||
private char[][] board;
|
||||
//private static final char WHITE = 'O';
|
||||
//private static final char BLACK = 'X';
|
||||
private static final char EMPTY = '.';
|
||||
//
|
||||
|
||||
|
||||
private GameState gameState;
|
||||
private LinkedBlockingQueue<Action> actionQueue = new LinkedBlockingQueue<Action>();
|
||||
|
||||
private Player guiPlayer;
|
||||
|
||||
private String[] COLS = { "A", "B", "C", "D", "E", "F", "G", "H", "J" };
|
||||
private SfxPlayer sfxPlayer;
|
||||
private String[] COLS = { "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T" };
|
||||
private String[] ROWS;
|
||||
|
||||
public GridPanel(GameConfig gameConfig, Player guiPlayer) {
|
||||
public GridPanel(GameConfig gameConfig, Player guiPlayer, SfxPlayer sfxPlayer) {
|
||||
this.guiPlayer = guiPlayer;
|
||||
|
||||
this.sfxPlayer = sfxPlayer;
|
||||
this.boardSize = gameConfig.getSize();
|
||||
|
||||
initRows(this.boardSize);
|
||||
|
||||
this.setPreferredSize(new Dimension(BOARD_WIDTH + BORDER_WIDTH * 2,
|
||||
BOARD_HEIGHT + BORDER_WIDTH * 2));
|
||||
if (boardSize <= 9) {
|
||||
boardPixelWidth = 300;
|
||||
} else if (boardSize <= 13) {
|
||||
boardPixelWidth = 434;
|
||||
} else {
|
||||
boardPixelWidth = 634;
|
||||
}
|
||||
this.setPreferredSize(new Dimension(boardPixelWidth + BORDER_WIDTH * 2,
|
||||
boardPixelWidth + BORDER_WIDTH * 2));
|
||||
URL urlBackgroundImg = getClass().getResource("wood3.jpg");
|
||||
this.backgroundImg = new ImageIcon(urlBackgroundImg).getImage();
|
||||
this.addMouseListener(this);
|
||||
this.addMouseMotionListener(this);
|
||||
|
||||
//
|
||||
board = new char[boardSize][boardSize];
|
||||
for (int i = 0; i < boardSize; i++) {
|
||||
for (int j = 0; j < boardSize; j++) {
|
||||
board[i][j] = EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addAction(Action action) {
|
||||
@@ -106,7 +101,7 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
// Given a pair of (x,y) coordinates (pixels), returns a row index in the
|
||||
// range [0..(boardSize-1)].
|
||||
private int getColumn(int x, int y) {
|
||||
int intersectionSize = BOARD_WIDTH / boardSize;
|
||||
int intersectionSize = boardPixelWidth / boardSize;
|
||||
|
||||
return (x - BORDER_WIDTH/*- centerOffset*/) / intersectionSize;
|
||||
}
|
||||
@@ -114,7 +109,7 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
// Given a pair of (x,y) coordinates (pixels), returns a row index in the
|
||||
// range [0..(boardSize-1)].
|
||||
private int getRow(int x, int y) {
|
||||
int intersectionSize = BOARD_WIDTH / boardSize;
|
||||
int intersectionSize = boardPixelWidth / boardSize;
|
||||
|
||||
return (y - BORDER_WIDTH/*- centerOffset*/) / intersectionSize;
|
||||
}
|
||||
@@ -134,19 +129,13 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
}
|
||||
}
|
||||
|
||||
int intersectionSize = BOARD_WIDTH / boardSize;
|
||||
int intersectionSize = boardPixelWidth / boardSize;
|
||||
int centerOffset = intersectionSize / 2;
|
||||
|
||||
g.translate(BORDER_WIDTH, BORDER_WIDTH);
|
||||
|
||||
for (int row = 0; row < boardSize; row++) {
|
||||
for (int col = 0; col < boardSize; col++) {
|
||||
g.fillOval(intersectionSize * col + centerOffset - DOT_WIDTH,
|
||||
intersectionSize * row + centerOffset - DOT_WIDTH,
|
||||
DOT_WIDTH * 2, DOT_WIDTH * 2);
|
||||
}
|
||||
}
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
|
||||
for (int row = 0; row < boardSize; row++) {
|
||||
g.drawLine(centerOffset, centerOffset + row * intersectionSize,
|
||||
intersectionSize * boardSize - centerOffset, centerOffset
|
||||
@@ -159,31 +148,17 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
* boardSize - centerOffset);
|
||||
}
|
||||
|
||||
Color defaultColor = g.getColor();
|
||||
g.setColor(Color.YELLOW);
|
||||
|
||||
int stoneX = getColumn(mouseX, mouseY) * intersectionSize
|
||||
+ centerOffset;
|
||||
int stoneY = getRow(mouseX, mouseY) * intersectionSize + centerOffset;
|
||||
|
||||
g.drawOval(stoneX - STONE_WIDTH, stoneY - STONE_WIDTH, STONE_WIDTH * 2,
|
||||
STONE_WIDTH * 2);
|
||||
|
||||
g.setColor(defaultColor);
|
||||
int mouseCol = getColumn(mouseX, mouseY);
|
||||
int mouseRow = getRow(mouseX, mouseY);
|
||||
|
||||
for (int col = 0; col < boardSize; col++) {
|
||||
// g.drawLine(centerOffset + col * intersectionSize, centerOffset,
|
||||
// centerOffset + col * intersectionSize, intersectionSize *
|
||||
// boardSize - centerOffset);
|
||||
g.drawBytes(COLS[col].getBytes(), 0, 1, centerOffset + col
|
||||
* intersectionSize - 5, BOARD_WIDTH + 5);
|
||||
* intersectionSize - 5, boardPixelWidth + 5);
|
||||
}
|
||||
|
||||
for (int row = 0; row < boardSize; row++) {
|
||||
// g.drawLine(centerOffset + col * intersectionSize, centerOffset,
|
||||
// centerOffset + col * intersectionSize, intersectionSize *
|
||||
// boardSize - centerOffset);
|
||||
g.drawBytes(ROWS[row].getBytes(), 0, 1, BOARD_WIDTH - 5,
|
||||
byte[] bytes = ROWS[row].getBytes();
|
||||
g.drawBytes(bytes, 0, bytes.length, boardPixelWidth - 5,
|
||||
centerOffset + row * intersectionSize + 5);
|
||||
}
|
||||
|
||||
@@ -196,19 +171,44 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
char symbol = gameBoard.getSymbolAt(col,boardSize - row - 1);
|
||||
|
||||
switch (symbol) {
|
||||
case 'X' :
|
||||
case GameBoard.BLACK_STONE :
|
||||
g.setColor(Color.BLACK);
|
||||
g.fillOval(intersectionSize * col + centerOffset - STONE_WIDTH,
|
||||
intersectionSize * row + centerOffset - STONE_WIDTH,
|
||||
STONE_WIDTH * 2, STONE_WIDTH * 2);
|
||||
break;
|
||||
case 'O' :
|
||||
case GameBoard.WHITE_STONE :
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillOval(intersectionSize * col + centerOffset - STONE_WIDTH,
|
||||
intersectionSize * row + centerOffset - STONE_WIDTH,
|
||||
STONE_WIDTH * 2, STONE_WIDTH * 2);
|
||||
break;
|
||||
case GameBoard.EMPTY_INTERSECTION :
|
||||
if (row == mouseRow && col == mouseCol && gameState.getPlayerToMove() == guiPlayer) {
|
||||
if (guiPlayer == Player.BLACK) {
|
||||
g.setColor(Color.BLACK);
|
||||
} else if (guiPlayer == Player.WHITE) {
|
||||
g.setColor(Color.WHITE);
|
||||
} else {
|
||||
throw new RuntimeException("Invalid guiPlayer: " + guiPlayer);
|
||||
}
|
||||
g.fillOval(intersectionSize * col + centerOffset - STONE_WIDTH,
|
||||
intersectionSize * row + centerOffset - STONE_WIDTH,
|
||||
STONE_WIDTH * 2, STONE_WIDTH * 2);
|
||||
g.setColor(Color.RED);
|
||||
g.drawOval(intersectionSize * col + centerOffset - STONE_WIDTH,
|
||||
intersectionSize * row + centerOffset - STONE_WIDTH,
|
||||
STONE_WIDTH * 2, STONE_WIDTH * 2);
|
||||
} else {
|
||||
g.setColor(Color.BLACK);
|
||||
g.fillOval(intersectionSize * col + centerOffset - DOT_WIDTH,
|
||||
intersectionSize * row + centerOffset - DOT_WIDTH,
|
||||
DOT_WIDTH * 2, DOT_WIDTH * 2);
|
||||
}
|
||||
break;
|
||||
default :
|
||||
continue;
|
||||
}
|
||||
|
||||
g.fillOval(intersectionSize * col + centerOffset - STONE_WIDTH,
|
||||
intersectionSize * row + centerOffset - STONE_WIDTH,
|
||||
STONE_WIDTH * 2, STONE_WIDTH * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,7 +216,21 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
|
||||
public void setGameState(GameState gameState) {
|
||||
this.gameState = gameState;
|
||||
|
||||
if (gameState.getPlayerToMove() == guiPlayer || gameState.isTerminal()) {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
} else {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
}
|
||||
|
||||
this.repaint();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
sfxPlayer.play();
|
||||
}}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -248,6 +262,14 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
int row = getRow(mouseX, mouseY);
|
||||
int column = getColumn(mouseX, mouseY);
|
||||
|
||||
if (row < 0 || row >= boardSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (column < 0 || column >= boardSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player currentPlayer = gameState.getPlayerToMove();
|
||||
if (currentPlayer == guiPlayer) {
|
||||
// gameState.playStone(guiPlayer, Action.getInstance(COLS[row] +
|
||||
|
||||
Binary file not shown.
41
src/net/woodyfolsom/msproj/sfx/SfxPlayer.java
Normal file
41
src/net/woodyfolsom/msproj/sfx/SfxPlayer.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package net.woodyfolsom.msproj.sfx;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Clip;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
|
||||
public class SfxPlayer {
|
||||
private static final String clickFilename = "Click-SoundBible.com-1387633738.wav";
|
||||
private Clip clip;
|
||||
|
||||
public SfxPlayer() throws LineUnavailableException, IOException, UnsupportedAudioFileException {
|
||||
init();
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
if (clip != null) {
|
||||
clip.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void init() throws LineUnavailableException, IOException, UnsupportedAudioFileException {
|
||||
if (clip != null) {
|
||||
clip.close();
|
||||
}
|
||||
|
||||
InputStream inputStream = SfxPlayer.class.getResourceAsStream(clickFilename);
|
||||
clip = AudioSystem.getClip();
|
||||
clip.open(AudioSystem.getAudioInputStream(inputStream));
|
||||
}
|
||||
|
||||
public void play() {
|
||||
if (clip!= null && !clip.isActive()) {
|
||||
clip.setFramePosition(0);
|
||||
clip.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user