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

📄 boardcanvas.java

📁 --- --- --- 基于J2ME的游戏程序--------很有技巧性的程序
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// Copyright (c) 2005 Sony Ericsson Mobile Communications AB
//
// This software is provided "AS IS," without a warranty of any kind. 
// ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 
// INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
// PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 
//
// THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se)

package bluegammon.gui;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.TextField;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Transform;

import bluegammon.Bluegammon;
import bluegammon.Resources;
import bluegammon.gui.animation.Animation;
import bluegammon.gui.animation.AnimationEngine;
import bluegammon.gui.animation.CommitMoveAnim;
import bluegammon.gui.animation.CursorAnim;
import bluegammon.gui.animation.DicesNewTurnAnim;
import bluegammon.gui.animation.DicesSelectTurnAnim;
import bluegammon.gui.animation.PieceMoveAnim;
import bluegammon.gui.animation.RepaintRequestable;
import bluegammon.gui.animation.WinnerAnim;
import bluegammon.gui.animation.WinnerPieceMoveAnim;
import bluegammon.logic.Board;
import bluegammon.logic.BoardMediator;
import bluegammon.logic.BoardState;
import bluegammon.logic.LocalPlayer;

/**
 </p><p>
 * Singleton class handling all graphical details of a backgammon view.
 * There can only be one <code>BoardCanvas</code> per device, thus
 * the singleton pattern.</p><p>
 * <code>BoardCanvas</code> handles the BackGammon board gui view.
 * Contains functionality for signalling gui changes on
 * user interaction. Uses a <code>Board</code> instance for
 * representation of gui state of the backgammon board.
 * </p><p>
 * The <code>BoardCanvas</code> also contains drawing primitives for
 * the backgammon board.
 * </p>
 * 
 * @see bluegammon.logic.BoardMediator
 * @see bluegammon.logic.BoardState
 * @author Peter Andersson
 */
public class BoardCanvas extends PopupCanvas
  implements CommandListener, RepaintRequestable
{
  /** The 3d z depth of a piece lying on backgammon board */
  public static final float PIECE_Z = -55f;

  /** Singleton instance */
  protected static BoardCanvas m_inst;
    
  // Gui colors
  protected static final int COL_BOARD = 0x008800;
  protected static final int COL_BOARD_LT = 0x00aa00;
  protected static final int COL_BOARD_DK = 0x006600;
  protected static final int COL_WHITE_DIAG = 0xdddddd;
  protected static final int COL_BLACK_DIAG = 0x222222;
  protected static final int COL_WHITE_PIECE = 0xffffff;
  protected static final int COL_BLACK_PIECE = 0x000000;
  protected static final int COL_WHITE_PIECE_DK = 0xbbbbbb;
  protected static final int COL_BLACK_PIECE_DK = 0x444444;
  
  protected static final int[] COL_BLACK_DICE_VAL =
    {0x000000, 0x333333, 0x666666, 0x000000};
  protected static final int[] COL_WHITE_DICE_VAL =
    {0xffffff, 0xcccccc, 0x999999, 0x666666};

  /** Dice value unit, will be set depending on screen size */ 
  protected static int m_diceValueUnit = 1;
  /** Undo command */
  public static final Command CMD_UNDO =
    new Command(Resources.getString(Resources.TXT_C_UNDO), Command.CANCEL, 1);
  /** Exit command */
  public static final Command CMD_EXIT =
    new Command(Resources.getString(Resources.TXT_C_QUIT), Command.BACK, 1);
  
  /** Represents the gui state of backgammon board */
  protected Board m_board = new Board();
  /** Board's softbutton control */
  protected SoftButtonControl m_softbuttons = new SoftButtonControl();

  /** Canvas width in pixels */
  protected int m_width;
  /** Canvas height in pixels */
  protected int m_height;
  /** Backgammon diagonal width in pixels */
  protected int m_diagW;
  /** Backgammon diagonal height in pixels */
  protected int m_diagH;
  /** Backgammon diagonal deltaX/deltaY value */
  protected int m_triangK;
  /** Backgammon board height in pixels */
  protected int m_boardH;
  /** Backgammon piece size in pixels */
  protected int m_pieceDiameter;
  /**
   * Cache of backgammon board regions per index,
   * defined by [index][x = 0, y = 1, width = 2, height = 3]
   */
  protected int[][] m_boardRegions = new int[Board.MAX_POS][4];
  /**
   * Point coordinates for dicevalue graphics, specified in an array
   * as [diceValue][Xn][Yn], where n can be 0..diceValue, and diceValue
   * is 0..5 representing different faces of a dice. 
   */
  protected int[][][] m_diceValPts = new int[6][][];

  // The board graphics consists of a two level buffer
  /** First buffer level of board graphics, a clean board without pieces */
  protected Image m_cleanBoardImg;
  /** 
   * Second buffer level of board graphics, the board with pieces of
   * current state, i.e. all static pieces.
   */
  protected Image m_pieceBoardImg;
  
  /** Flags indicating what backgammon board indices needs to be repainted */
  protected boolean[] m_dirtyRows = new boolean[Board.MAX_POS];
  protected boolean m_undoOn = false;

  /** The animation engine */
  protected AnimationEngine m_animationEngine;
  
  /** Current local player */
  protected LocalPlayer m_player;
  
  /**
   * Current index in possible movement vector of
   * user piece movement cursor
   */
  protected int m_cursor = 0;
  /** User piece movement cursor animation */
  protected CursorAnim m_cursorAnimation;

  /** Dice value vector, one value for each dice */
  protected int[] m_diceValues = new int[2];
  /**
   * Dice consume status vector, one status for each dicevalue
   * in m_diceValues. 0 indicates unconsumed, 1 indicates semiconsumed 
   * (used for double throws), 2 means consumed.
   */
  protected int[] m_consumeStatuses = new int[2];
  
  /** Flag indicating if user can interact */
  protected boolean m_allowInteraction = false;
  /** Flag indicating if user is queried of committing moves */
  protected boolean m_queryCommit = false;

  /** Dice animation */
  protected Animation m_diceAnimation = null;
  /** Flag indicating if dicevalues should be drawn */
  protected boolean m_drawDiceValues = false;
  
  /** Request repaint flag */
  protected volatile boolean m_repaint = false;
  
  /** 3d transform cache instance */
  protected Transform m_transform = new Transform();
  
  // Control methods

  /**
   * Sets up start positions for white and black player
   */
  public void setStartPositions()
  {
    m_board.setStartPositions();
    for (int i = 0; i < Board.MAX_POS; i++)
    {
      m_dirtyRows[i] = true;
    }
  }
  
  
  /**
   * Called from logic on a new game, when
   * players toss one dice each and the one with 
   * highest value starts.
   * @param wDice  value of white dice
   * @param bDice  value of black dice
   */
  public void selectTurns(int wDice, int bDice)
  {
    m_animationEngine.addAnimation(
      new DicesSelectTurnAnim(wDice, bDice, getWidth(), getBoardHeight()));
  }
  
  /**
   * Called from logic when dices are thrown on a new turn,
   * starts the dice animation.
   * @param white  the color of dices
   */
  public void throwDices(boolean white)
  {
    if (m_diceAnimation != null)
      m_animationEngine.remove(m_diceAnimation);
    m_diceAnimation = 
      new DicesNewTurnAnim(
        white,
        BoardMediator.getDiceValue(0),
        BoardMediator.getDiceValue(1));
    m_animationEngine.addAnimation(m_diceAnimation);
    setDiceValues(
      BoardMediator.getDiceValue(0),
      BoardMediator.getDiceValue(1));
    updateCursor();
  }
  
  /**
   * Called from logic when a piece is moved.
   * @param white   Color of piece
   * @param from    From index.
   * @param to    To index.
   * @param piecesOnSrc  Number of pieces on source index
   * @param piecesOnDst  Number of pieces on dest index
   */
  public void movePiece(boolean white, int from, int to, int piecesOnSrc, int piecesOnDst)
  {
    m_animationEngine.addAnimation(new PieceMoveAnim(white, from, to, piecesOnSrc, piecesOnDst));
  }

  /**
   * Called from logic when user has made a move
   * using specified dice value. Updates consume status.
   * @param diceVal  The dice value used
   */
  public void consumeDiceValue(int diceVal)
  {
    if (m_diceValues[0] == m_diceValues[1])
    {
      if (m_consumeStatuses[0] == 2)
        m_consumeStatuses[1]++;
      else
        m_consumeStatuses[0]++;
    }
    else
    {
      if (m_diceValues[0] == diceVal)
        m_consumeStatuses[0] = 2;
      else
        m_consumeStatuses[1] = 2;
    }
  }
  
  /**
   * Called from logic when user  has undoed a
   * move based on specified dice value. Updates 
   * specified dicevalue consume status.
   * @param diceVal  The dice value being undoed
   */
  public void undoConsumedDiceValue(int diceVal)
  {
    if (m_diceValues[0] == m_diceValues[1])
    {
      if (m_consumeStatuses[1] == 0)
        m_consumeStatuses[0]--;
      else
        m_consumeStatuses[1]--;
    }
    else
    {
      if (m_diceValues[0] == diceVal)
        m_consumeStatuses[0] = 0;
      else
        m_consumeStatuses[1] = 0;
    }
  }

  /**
   * Called from logic when the user should commit his/her moves
   * or when the user has commited.
   * @param commit	True if user should commit, false if user has commited.
   */
  public void setQueryCommit(boolean commit)
  {
    m_queryCommit = commit;
    if (commit)
    {
      m_cursor = -1;
      m_animationEngine.addAnimation(new CommitMoveAnim(!BoardMediator.isCurrentPlayerWhite()));
    }
    else
    {
      m_cursor = 0;
      updateUndoCommand();
    }
  }
  
  /**
   * Setups gui when there is a winner.
   * @param white  The color of the winner.
   * @param pieces   Pieces left for loser.
   * @param pts    Points per piece,
   */
  public void finishGame(boolean white, int pieces, int pts)
  {
    m_animationEngine.addAnimation(new WinnerAnim(white, pieces, pts));
  }
  
  /**
   * Invalidates this canvas, forcing a full repaint on
   * next call to paint()
   */
  public void invalidate()
  {
    m_pieceBoardImg.getGraphics().drawImage(
        getBoardImage(), 0, 0, Graphics.TOP | Graphics.LEFT);

    // repaint all rows
    for (int i = 0; i < Board.MAX_POS; i++)
    {
      m_dirtyRows[i] = true;
    }
    
    drawBoard(null);
    
    // clean up animation engine
    if (m_cursorAnimation != null) m_cursorAnimation.stop();
    m_cursorAnimation = null;
    m_diceAnimation = null;
    m_animationEngine.removeAll();
    
    updateUndoCommand();

    if (BoardMediator.countPossibleMoves() > 0)
    {
      cursorNearestIndex(0, 0);
    }
    else
    {
      m_cursor = -1;
    }
    updateCursor();
  }
  
  /**
   * Shuts down the canvas logic.
   */
  public void shutdown()
  {
    m_inst = null;
    m_animationEngine.shutdown();
  }
  
  // BoardCanvas state manipulation methods
  
  /**
   * Set the local player that will receive interaction
   * calls made on this canvas.
   * @param player  The local player, or null if current player is not local.
   */
  public void setCurrentLocalPlayer(LocalPlayer player)
  {
    m_player = player;
    updateCursor();
  }
  
  /**
   * Adds a new piece to the canvas
   * @param white    true if white piece, false if black
   * @param index    where to place the piece
   */
  public void addPiece(boolean white, int index)
  {
    m_board.addPiece(white, index);
    m_dirtyRows[index] = true;
    requestRepaint();
  }
  
  /**
   * Removes a  piece from the canvas
   * @param white    true if white piece, false if black
   * @param index    where from to remove the piece
   */
  public void removePiece(boolean white, int index)
  {
    m_board.removePiece(white, index);
    m_dirtyRows[index] = true;
    requestRepaint();
  }
  
  /**
   * Sets number of pieces on specified index
   * @param white    true if white piece, false if black
   * @param index    The board index
   * @param pieces  Number of pieces
   */
  public void setPieces(boolean white, int index, int pieces)
  {
    m_board.setPieces(white, index, pieces);
    m_dirtyRows[index] = true;
    requestRepaint();
  }

  /**
   * Returns number pieces on specified index
   * @param index    The board index
   * @return      Number of pieces
   */
  public int getPieces(int index)
  {
    return m_board.countPieces(index);
  }
  
  /**
   * Returns number of pieces on specified index of specified color
   * @param white    true if white piece, false if black
   * @param index    The board index
   * @return      Number of pieces
   */
  public int getPieces(boolean white, int index)
  {
    return m_board.countPieces(white, index);
  }
    
  /**
   * Returns true if there are white pieces on specified index,
   * returns false if there are black or no pieces.
   * @param index  The board index
   * @return    true if white, false if black.
   */
  public boolean isWhite(int index)
  {
    return m_board.isWhite(index);
  }
  
  // Low level canvas state methods
  
  /**
   * Returns whether the player can move any pieces or not.
   * @return  true if user can move pieces, false if not.
   */
  public boolean isUserMovable()
  {
    return m_allowInteraction && !BoardMediator.isRemoteTurn();
  }
  
  /**
   * Returns current cursor index of possible moves.
   * @return the cursor index.
   */
  public int getCurrentCursorIndex()
  {
    return m_cursor;
  }
  
  /**
   * Returns whether the canvas is waiting for the user
   * to commit his/her moves.
   * @return true if waiting for commit, false if not.
   */
  public boolean waitingForCommit()
  {
    return m_queryCommit;
  }
  
  /**
   * Updates the cursor. Called when possible moves has been altered.
   * Stops any current cursor animation and creates a new
   * one if there are possible moves.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -