⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boardcanvas.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
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 + -