www.pudn.com > Bluegammon蓝牙的应用编程.rar > PieceMoveAnim.java


// 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.animation; 
 
import javax.microedition.lcdui.Graphics; 
 
import bluegammon.Audio; 
import bluegammon.gui.BoardCanvas; 
import bluegammon.gui.Context3D; 
import bluegammon.logic.Board; 
import bluegammon.logic.BoardMediator; 
 
/** 
 * Animation of a piece moving from an source index to a destination index. 
 *  
 * @author Peter Andersson 
 */ 
public class PieceMoveAnim extends Animation 
{ 
  protected static int SIZE = 7; 
  /** Number of frames in this animation */ 
  protected int m_frames; 
  /** True for white piece, false for black */ 
  protected boolean m_white; 
  /** Piece source position on board */ 
  protected int m_source; 
  /** Piece destination position on board */ 
  protected int m_dest; 
  /** Piece source x coordinate */ 
  protected int m_x0; 
  /** Piece source y coordinate */ 
  protected int m_y0; 
  /** Piece destination x coordinate */ 
  protected int m_x1; 
  /** Piece destination y coordinate */ 
  protected int m_y1; 
  /** How to tilt the piece */ 
  protected float m_angleSign = 1; 
  /** Current frame */ 
  protected int m_frame = 0; 
  /** Current piece coordinates */ 
  protected float m_x, m_y; 
  /** Flag indicating if sinus distortion is applied vertically */ 
  protected boolean m_vertSin = false; 
  /** The factor of the sinus distortion */ 
  protected float m_sinFact = 0; 
  /** The delta of the sinus distortion angle */ 
  protected float m_sinStep; 
  /** Current sinus distortion angle */ 
  protected float m_sinAngle; 
  /** RGB buffer for transparant piece shadow */ 
  protected static int[] m_shadow; 
 
  /** 
   * Initializes this animation with the size of the piece, which is depending 
   * on the canvas size. 
   *  
   * @param pieceSize  The size of the piece. 
   */ 
  public static void init(int pieceSize) 
  { 
    SIZE = pieceSize; 
    m_shadow = Context3D.createShadowRGB(SIZE, 0); 
  } 
 
  /** 
   * Creates a new piece movement animation. 
   *  
   * @param white   True for white piece, false for black. 
   * @param source  Source index of piece. 
   * @param dest    Destination index of piece. 
   * @param piecesOnSource 
   *          Number of pieces on source index. 
   * @param piecesOnDest 
   *          Number of pieces on destination index. 
   */ 
  public PieceMoveAnim(boolean white, int source, int dest, int piecesOnSource, 
      int piecesOnDest) 
  { 
    BoardCanvas canvas = BoardCanvas.getInstance(); 
 
    m_white = white; 
    m_source = source; 
    m_dest = dest; 
    m_angleSign = (source < Board.MAX_POS / 2) ? 1f : -1f; 
 
    // Get source and destination coordinates 
    m_x0 = canvas.getPieceX(source, piecesOnSource, white); 
    m_y0 = canvas.getPieceY(source, piecesOnSource, white); 
    m_x1 = canvas.getPieceX(dest, piecesOnDest, white); 
    m_y1 = canvas.getPieceY(dest, piecesOnDest, white); 
    m_x = m_x0; 
    m_y = m_y0; 
 
    // Calculate number of animation frames for this move 
    int dx = Math.abs(m_x1 - m_x0); 
    int dy = Math.abs(m_y1 - m_y0); 
    m_frames = Math.max(dx, dy); 
    m_frames = ((4 * m_frames) / canvas.getHeight()); 
    m_frames = Math.max(10, m_frames); 
    m_frames = Math.min(30, m_frames); 
    if (m_dest == Board.POS_GUARD) 
    { 
      m_frames = 30; 
    } 
 
    // Decide if distort vertically or horizontally 
    if ((source < 12 && dest < 12) || 
        (source > 11 && dest > 11) ||  
        dest == Board.POS_OUT) 
    { 
      m_vertSin = false; 
    }  
    else 
    { 
      m_vertSin = dy < dx; 
    } 
 
    // Calculate parameter for horizontal/vertical move 
    if (m_vertSin) 
    { 
      m_sinFact = (float)canvas.getBoardHeight() / 8f; 
    } 
    else 
    { 
      m_sinFact = (float)canvas.getWidth() / 8f; 
    } 
    if (dest < 12 || (dest == Board.POS_OUT && !white)) 
      m_sinFact = -m_sinFact; 
 
    // Calculate sinus step 
    m_sinStep = (float)Math.PI / (float)(m_frames - 1); 
    m_sinAngle = m_sinStep / 2f; 
  } 
 
  public void onStart() 
  { 
    // Remove start piece from canvas, now on move 
    BoardCanvas.getInstance().removePiece(m_white, m_source); 
  } 
 
  public void paint(Graphics g) 
  { 
    if (m_frame <= m_frames) 
    { 
      float frameRatio = (float)m_frame / (float)m_frames; 
      float dz = 0f; 
      float angle = 0f; 
      dz = (float) Math.sin(Math.PI * frameRatio); 
      if (m_dest == Board.POS_GUARD) 
      { 
        // Moving to guard, rotate it 
        angle = 540f * frameRatio; 
        dz *= 25f; 
      } 
      else if (m_dest == Board.POS_OUT) 
      { 
        // Moving out, tilt it so it reaches 60 degrees at end 
        angle = (m_white ? -1 : 1) * 60f * frameRatio; 
        dz *= 10f; 
      } 
      else 
      { 
        // Moving on board, tilt it 
        angle = m_angleSign * 75f * (float)Math.sin(Math.PI * frameRatio); 
        dz *= 10f; 
      } 
 
      // Draw shadow 
      Context3D c3d = Context3D.getInstance(); 
      g.drawRGB(m_shadow, 0, SIZE, 
          (int)(m_x - c3d.toScreenCoordinateX(c3d.getShadowProjectionDeltaX(dz), 
              BoardCanvas.PIECE_Z)), 
          (int)(m_y), 
          SIZE, SIZE, true); 
 
      // Draw piece 
      BoardCanvas.getInstance().drawPiece( 
          (int)m_x, (int)m_y, angle, false, dz, m_white, g); 
    } 
  } 
 
  public void next() 
  { 
    // Calculate new piece position 
    if (m_frame < m_frames) 
    { 
      BoardCanvas canvas = BoardCanvas.getInstance(); 
 
      // Linear move 
      m_x = ((float) (m_x1 - m_x0) * m_frame) / (float) (m_frames) + m_x0; 
      m_y = ((float) (m_y1 - m_y0) * m_frame) / (float) (m_frames) + m_y0; 
 
      // Add sinus distortion 
      if (m_vertSin) 
      { 
        m_y -= (m_sinFact * Math.sin(m_sinAngle)); 
      } 
      else 
      { 
        m_x -= (m_sinFact * Math.sin(m_sinAngle)); 
      } 
      m_sinAngle += m_sinStep; 
 
      // Repaint 
      canvas.requestRepaint(); 
    } 
    m_frame++; 
  } 
 
  public boolean isFinished() 
  { 
    return m_frame >= m_frames; 
  } 
 
  public void onExit() 
  { 
    BoardCanvas canvas = BoardCanvas.getInstance(); 
    // Add end piece on canvas, now static 
    canvas.addPiece(m_white, m_dest); 
    canvas.requestRepaint(); 
    if (!BoardMediator.isGameFinished()) 
      Audio.playSound(Audio.PIECE); 
  } 
 
  public long getInterval() 
  { 
    return 20; 
  } 
}