📄 boardcanvas.java
字号:
package ergo.ui;
// $Id: BoardCanvas.java,v 1.6 1999/08/27 03:07:55 sigue Exp $
/*
* Copyright (C) 1999 Carl L. Gay and Antranig M. Basman.
* See the file copyright.txt, distributed with this software,
* for further information.
*/
import ergo.util.Util;
import ergo.GlobalOptions;
import ergo.util.Debug;
import ergo.util.ILMV;
import ergo.util.Position;
import ergo.util.PositionVector;
import ergo.logic.Move;
import ergo.logic.StoneMove;
import ergo.logic.GameResultMove;
import ergo.logic.StoneStasher;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.MemoryImageSource;
import java.util.Vector;
/**
* The BoardCanvas class is responsible for drawing the board and the stones.
*/
public class BoardCanvas extends ErgoCanvas
implements Optionizable, Refreshable, UpdatableBoard, Styles {
private static final int PREFERRED_CELL_SIZE = 19;
private Color blackColor = Color.black;
private Color whiteColor = Color.white;
// ---*** Plan is to gradually remove dependence on gwin. This field should
// be removed eventually. AMB
// ---*** The way to do this is to create a GobanListener interface which at
// first just provides all the methods from GameWindow that we're
// currently using, and then whittle it down to the few necessary
// callbacks. I believe that only 2 or 3 are needed:
//
// positionChanged(...row, col...) tells the GobanListener that the pointer
// has moved from one position on the goban to another (or off the board).
//
// positionClicked(...row, col...) tells the GobanListener that the pointer
// was clicked over the given row/column. -sigue
private GameWindow gwin; // window I belong to
private StoneStasher ss;
private int gameSize;
private Move currentMove;
private Position koPosition;
// even if the canvas isn't perfectly square, the board must be,
// and it should be centered in the canvas.
private int xoffset; // offsets of pixel 0 0 position from board 0 0 position.
private int yoffset;
private int sideSize; // pixels per side of board.
private int cellSize; // pixels per cell
public int getBevelWidth () {
return 5 + (19 - gameSize) / 2; // width of border of board in pixels
}
private Image offscreen;
private Graphics offg;
private Graphics staticg;
// Option stuff - much more to come.
private String variationfontString = "Variation font";
private Color boardColor; // Optionized.
private int boardStyle; // Optionized.
private Font variationFont; // Optionized.
private boolean showVariations; // Optionized.
private Optionizer opser = ergo.Ergo.opser;
// +++ Gradually remove dependency on win.
//
BoardCanvas (GameWindow win, int gameSize1, StoneStasher ss1) {
gwin = win;
gameSize = gameSize1;
ss = ss1;
currentMove = ss.getCurrentMove();
ss.associateUpdatable(this);
// 229 188 102 = light wood
try {
opser.expressOwnership(variationfontString,
Optionizer.TYPE_FONT, this, null);
opser.expressOwnership(GlobalOptions.variationString,
Optionizer.TYPE_BOOLEAN, this, new Boolean(true));
opser.expressOwnership(GlobalOptions.boardColorString,
Optionizer.TYPE_COLOR, this, new ColorSpec("213 182 85"));
//("229 188 102"));
opser.expressOwnership(GlobalOptions.stoneString,
Optionizer.TYPE_INTEGER, this, new Integer(STONE_3D));
opser.expressOwnership(GlobalOptions.boardStyleString,
Optionizer.TYPE_INTEGER, this, new Integer(BOARD_WOOD));
}
catch (Exception e) { Debug.backtrace(e);}
variationFont = opser.getFontOption(variationfontString);
setFont(variationFont);
boardColor = opser.getColorOption(GlobalOptions.boardColorString);
boardStyle = opser.getIntegerOption(GlobalOptions.boardStyleString);
setBackground(boardColor);
setForeground(Color.black);
showVariations = opser.getBooleanOption(GlobalOptions.variationString);
addMouseListener(new mouseListener());
addMouseMotionListener(new mouseMotionListener());
}
public boolean isReady () {
return (offscreen != null
&& offg != null
&& whiteStone != null
&& blackStone != null
&& whiteShadowStone != null
&& blackShadowStone != null
&& hoshiIm != null);
}
public Dimension getMinimumSize () {
int size = gameSize * 5;
return new Dimension(size, size);
}
public Dimension getPreferredSize () {
int size = gameSize * PREFERRED_CELL_SIZE;
return new Dimension(size, size);
}
public void optionEvent (String keyword, Object value) {
if (opser.isSameKey(keyword, variationfontString)) {
variationFont = (Font)value;
setFont(variationFont);
// noteMove();
}
else if (opser.isSameKey(keyword, GlobalOptions.variationString)) {
showVariations = opser.getBooleanOption(GlobalOptions.variationString);
refreshLocal();
}
else if (opser.isSameKey(keyword, GlobalOptions.boardColorString)) {
boardColor = opser.getColorOption(GlobalOptions.boardColorString);
refreshLocal();
}
else if (opser.isSameKey(keyword, GlobalOptions.stoneString)) {
stoneManufac();
refreshLocal();
}
else if (opser.isSameKey(keyword, GlobalOptions.boardStyleString)) {
boardStyle = opser.getIntegerOption(GlobalOptions.boardStyleString);
if (boardStyle == BOARD_BASIC) {
setWoodBoard(null);
refreshLocal();
}
else {
setWoodBoard(WoodGenerator.request(sideSize, getBevelWidth(), this));
if (oodboard != null)
refreshLocal();
}
}
}
// Convert a color code to a color object.
//
private Color codeToColor (int colorCode) {
switch (colorCode) {
case Move.WHITE:
case Move.WHITETERRITORY:
return whiteColor;
case Move.BLACK:
case Move.BLACKTERRITORY:
return blackColor;
default:
return getForeground();
}
}
// Some standard conversions from screen coords to row, column.
// The board on screen and Ergo use a first quadrant coordinate system,
// whereas the AWT uses a fourth quadrant system.
// these functions return the top left corner of the stone square - AMB.
//
private final int coltox (int col) { return xoffset + col * cellSize; }
public final int xtocol (int x) { return (x - xoffset) / cellSize; }
private final int rowtoy (int row) {
return yoffset + (gameSize - row - 1) * cellSize;
}
public final int ytorow (int y) {
return (gameSize - (y - yoffset) / cellSize) - 1;
}
/*********************************
* Utility Inner Class: *
* i) star point determination. *
*********************************/
/**
* Determine whether the given position is a "star point", i.e., one
* that should be drawn specially on the board.
*/
class StarPoints {
private PositionVector starPoints;
public boolean isStarPoint (int row, int column) {
points(); // make sure star points cached.
for (int i = 0; i < starPoints.size(); i++) {
Position p = starPoints.elementAt(i);
if (p.column == column && p.row == row)
return true;
}
return false;
}
public PositionVector points () {
if (starPoints != null)
return starPoints;
else {
int start = 3; // initialize to 13x13/19x19 values
int step = 6;
switch (gameSize) {
case 8:
start = 2;
step = 3;
break;
case 9:
start = 2;
step = 4;
break;
default:
if (gameSize > 9) {
if (gameSize % 2 == 0) // even size
step = gameSize - 7; // 4,4 points only
else
step = (gameSize - 7) / 2; // 4,4s and central points
}
}
starPoints = new PositionVector(9);
for (int row = start; row <= gameSize - start; row += step)
for (int col = start; col <= gameSize - start; col += step)
starPoints.addElement(new Position(row, col));
if (gameSize % 2 == 1) {
int center = gameSize / 2;
if (!starPoints.isMember(center, center))
starPoints.addElement(new Position(center, center));
}
return starPoints;
}
} // end manufacture starpoints
} // end inner class starpoints
private StarPoints starpoints = new StarPoints();
private Circle circle = new Circle();
private Line line = new Line();
/***************************
* BASE level drawing routines - these actually manipulate the bitmaps,,,
***************************/
private RawImage oodboard; // rather hefty array for wooden board
private RawImage whiteStone;
private RawImage blackStone;
private RawImage whiteShadowStone;
private RawImage blackShadowStone;
private RawImage hoshi;
private Image hoshiIm;
// Temporary large array for rendering anti-aliased STONE_ANTIN stones.
private RawImage tempblit = new RawImage();
private Image tempblitIm;
private void blitIt (int row, int col) {
int left = coltox(col);
int top = rowtoy(row);
// tempblit.mis().newPixels(0, 0, cellSize, cellSize);
// Painful trial and error indicates the following mysterious
// pair of lines accomplish blitting without calling constructors...!
// More trial and error saves 90ms blitting, but doesn't solve
// OS/2 performance problem. Fuck it, let's go bowling. AMB 0.12
// long time = System.currentTimeMillis();
// tempblitIm.flush();
// System.out.print("Flush - "+ (System.currentTimeMillis() - time));
tempblit.mis().newPixels();
// System.out.print(" newp - "+ (System.currentTimeMillis() - time));
// tempblitIm = createImage(tempblit.mis());
offg.drawImage(tempblitIm, left, top, this);
// System.out.println(" draw - "+ (System.currentTimeMillis() - time));
}
private void makeEmptyImage (int row, int col) {
makeEmptyImage(row, col, false);
}
private void makeEmptyImage (int row, int col, boolean nohoshi) {
// no sync for speed...!
if (boardStyle == BOARD_BASIC || oodboard == null)
tempblit.blank(boardColor.getRGB());
else
ImArith.apsubio(tempblit, oodboard, coltox(col), rowtoy(row));
int left = 0; int right = cellSize - 1;
int top = 0; int bottom = cellSize - 1;
if (col == 0) left = cellSize/2;
if (row == 0) bottom = cellSize/2;
if (col == gameSize - 1) right = cellSize/2;
if (row == gameSize - 1) top = cellSize/2;
int linecol = 0xff000000; // getForeground.getRGB();
line.line(tempblit, linecol, left, cellSize/2, right, cellSize/2);
line.line(tempblit, linecol, cellSize/2, top, cellSize/2, bottom);
if (starpoints.isStarPoint(row, col) && !nohoshi)
ImArith.api(tempblit, hoshi);
}
private void stoneManufac () {
int stoneStyle = opser.getIntegerOption(GlobalOptions.stoneString);
double adjustwhite = 0.0; int backcoldark = 0, backcollight = 0;
if (currentBoardStyle() == BOARD_WOOD) {
backcoldark = OodInnaBox.getDarkColor();
backcollight = OodInnaBox.getAverageColor();
adjustwhite = -0.5;
}
else {
backcoldark = backcollight = boardColor.getRGB();
adjustwhite = 0.0;
}
whiteStone = StoneMaker.makeStoneImage(Move.WHITE, false, cellSize,
stoneStyle, backcoldark, adjustwhite);
blackStone = StoneMaker.makeStoneImage(Move.BLACK, false, cellSize,
stoneStyle, backcollight, 0.0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -