Behold Vilya, Ring of Air and repository for our game and virtual worldly
extensions to the distributed environment provided by Narya. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@1 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// $Id: DropBlockSprite.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
/**
|
||||
* The drop block sprite represents a block of multiple pieces that can be
|
||||
* rotated to any of the four cardinal compass directions. As such, it
|
||||
* may span multiple columns or rows depending on its orientation. The
|
||||
* block has a "central" piece around which it rotates, with the other
|
||||
* pieces referred to as "external" pieces.
|
||||
*/
|
||||
public class DropBlockSprite extends DropSprite
|
||||
{
|
||||
/**
|
||||
* Constructs a drop block sprite and starts it dropping.
|
||||
*
|
||||
* @param view the board view upon which this sprite will be displayed.
|
||||
* @param col the column of the central piece.
|
||||
* @param row the row of the central piece.
|
||||
* @param orient the orientation of the sprite.
|
||||
* @param pieces the pieces displayed by the sprite.
|
||||
*/
|
||||
public DropBlockSprite (
|
||||
DropBoardView view, int col, int row, int orient, int[] pieces)
|
||||
{
|
||||
super(view, col, row, pieces, 0);
|
||||
|
||||
_orient = orient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a drop block sprite and starts it dropping.
|
||||
*
|
||||
* @param view the board view upon which this sprite will be displayed.
|
||||
* @param col the column of the central piece.
|
||||
* @param row the row of the central piece.
|
||||
* @param orient the orientation of the sprite.
|
||||
* @param pieces the pieces displayed by the sprite.
|
||||
* @param renderOrder the rendering order of the sprite.
|
||||
*/
|
||||
public DropBlockSprite (
|
||||
DropBoardView view, int col, int row, int orient, int[] pieces,
|
||||
int renderOrder)
|
||||
{
|
||||
super(view, col, row, pieces, 0, renderOrder);
|
||||
|
||||
_orient = orient;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void init ()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setOrientation(_orient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the row numbers containing the block pieces.
|
||||
* The first index is the row of the central piece. The array is
|
||||
* cached and re-used internally and so the caller should make their
|
||||
* own copy if they care to modify it.
|
||||
*/
|
||||
public int[] getRows ()
|
||||
{
|
||||
return _rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the column numbers containing the block pieces.
|
||||
* The first index is the column of the central piece. The array is
|
||||
* cached and re-used internally and so the caller should make their
|
||||
* own copy if they care to modify it.
|
||||
*/
|
||||
public int[] getColumns ()
|
||||
{
|
||||
return _cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bounds of the block in board piece coordinates. The
|
||||
* bounds rectangle is cached and re-used internally and so the caller
|
||||
* should make their own copy if they care to modify it.
|
||||
*/
|
||||
public Rectangle getBoardBounds ()
|
||||
{
|
||||
return _dbounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row the external piece is located in.
|
||||
*/
|
||||
public int getExternalRow ()
|
||||
{
|
||||
return _erow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column the external piece is located in.
|
||||
*/
|
||||
public int getExternalColumn ()
|
||||
{
|
||||
return _ecol;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setColumn (int col)
|
||||
{
|
||||
super.setColumn(col);
|
||||
updateDropInfo();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setRow (int row)
|
||||
{
|
||||
super.setRow(row);
|
||||
updateDropInfo();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setBoardLocation (int row, int col)
|
||||
{
|
||||
super.setBoardLocation(row, col);
|
||||
updateDropInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sprite image offset to reflect the direction in which
|
||||
* the external piece is hanging.
|
||||
*/
|
||||
public void setOrientation (int orient)
|
||||
{
|
||||
super.setOrientation(orient);
|
||||
|
||||
int edx = 0, edy = 0;
|
||||
if (orient == NORTH) {
|
||||
edy = -1;
|
||||
} else if (orient == WEST) {
|
||||
edx = -1;
|
||||
}
|
||||
|
||||
// update the sprite image offset
|
||||
setRowOffset(edy);
|
||||
setColumnOffset(edx);
|
||||
|
||||
// update the external piece position and drop block bounds
|
||||
updateDropInfo();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void toString (StringBuilder buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", erow=").append(_erow);
|
||||
buf.append(", ecol=").append(_ecol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this sprite pop-up a row on a forgiving rotation?
|
||||
*/
|
||||
public boolean canPopup ()
|
||||
{
|
||||
return (_popups > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if we pop up to decrement the remaining popups we have.
|
||||
*/
|
||||
public void didPopup ()
|
||||
{
|
||||
_popups--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-calculates the external piece position and bounds of the drop
|
||||
* block.
|
||||
*/
|
||||
protected void updateDropInfo ()
|
||||
{
|
||||
// update the external piece location
|
||||
_erow = calculateExternalRow();
|
||||
_ecol = calculateExternalColumn();
|
||||
|
||||
// update the piece row and column arrays
|
||||
_rows[0] = _row;
|
||||
_rows[1] = _erow;
|
||||
_cols[0] = _col;
|
||||
_cols[1] = _ecol;
|
||||
|
||||
// calculate the drop block board bounds
|
||||
int maxrow = Math.max(_row, _erow);
|
||||
int mincol = Math.min(_col, _ecol);
|
||||
|
||||
int bpwid, bphei;
|
||||
if (_orient == NORTH || _orient == SOUTH) {
|
||||
bpwid = 1;
|
||||
bphei = 2;
|
||||
} else {
|
||||
bpwid = 2;
|
||||
bphei = 1;
|
||||
}
|
||||
|
||||
// create the bounds rectangle if necessary
|
||||
_dbounds.setBounds(mincol, maxrow, bpwid, bphei);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row the external piece is located in based on the
|
||||
* current central piece location and sprite orientation.
|
||||
*/
|
||||
protected int calculateExternalRow ()
|
||||
{
|
||||
if (_orient == NORTH) {
|
||||
return (_row - 1);
|
||||
} else if (_orient == SOUTH) {
|
||||
return (_row + 1);
|
||||
} else {
|
||||
return _row;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column the external piece is located in based on the
|
||||
* current central piece location and sprite orientation.
|
||||
*/
|
||||
protected int calculateExternalColumn ()
|
||||
{
|
||||
if (_orient == WEST) {
|
||||
return (_col - 1);
|
||||
} else if (_orient == EAST) {
|
||||
return (_col + 1);
|
||||
} else {
|
||||
return _col;
|
||||
}
|
||||
}
|
||||
|
||||
/** How many times this sprite can be popped-up a row in a forgiving
|
||||
* rotation. */
|
||||
protected byte _popups = 2;
|
||||
|
||||
/** The drop block bounds in board coordinates. */
|
||||
protected Rectangle _dbounds = new Rectangle();
|
||||
|
||||
/** The drop block piece rows. */
|
||||
protected int[] _rows = new int[2];
|
||||
|
||||
/** The drop block piece columns. */
|
||||
protected int[] _cols = new int[2];
|
||||
|
||||
/** The external piece location in board coordinates. */
|
||||
protected int _ecol, _erow;
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
//
|
||||
// $Id: DropBoardView.java 3527 2005-04-28 23:17:29Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.sprite.ImageSprite;
|
||||
import com.threerings.media.sprite.PathAdapter;
|
||||
import com.threerings.media.sprite.Sprite;
|
||||
import com.threerings.media.util.LinePath;
|
||||
import com.threerings.media.util.Path;
|
||||
|
||||
import com.threerings.parlor.media.ScoreAnimation;
|
||||
|
||||
import com.threerings.puzzle.Log;
|
||||
import com.threerings.puzzle.client.PuzzleBoardView;
|
||||
import com.threerings.puzzle.data.Board;
|
||||
import com.threerings.puzzle.data.PuzzleConfig;
|
||||
import com.threerings.puzzle.util.PuzzleContext;
|
||||
|
||||
import com.threerings.puzzle.drop.data.DropBoard;
|
||||
import com.threerings.puzzle.drop.data.DropConfig;
|
||||
import com.threerings.puzzle.drop.data.DropPieceCodes;
|
||||
|
||||
/**
|
||||
* The drop board view displays a drop puzzle game in progress for a
|
||||
* single player.
|
||||
*/
|
||||
public abstract class DropBoardView extends PuzzleBoardView
|
||||
implements DropPieceCodes
|
||||
{
|
||||
/** The color used to render normal scoring text. */
|
||||
public static final Color SCORE_COLOR = Color.white;
|
||||
|
||||
/** The color used to render chain reward scoring text. */
|
||||
public static final Color CHAIN_COLOR = Color.yellow;
|
||||
|
||||
/**
|
||||
* Constructs a drop board view.
|
||||
*/
|
||||
public DropBoardView (PuzzleContext ctx, int pwid, int phei)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
// save off piece dimensions
|
||||
_pwid = pwid;
|
||||
_phei = phei;
|
||||
|
||||
// determine distance to float score animations
|
||||
_scoreDist = 2 * _phei;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the board with the board dimensions.
|
||||
*/
|
||||
public void init (PuzzleConfig config)
|
||||
{
|
||||
DropConfig dconfig = (DropConfig)config;
|
||||
|
||||
// save off the board dimensions in pieces
|
||||
_bwid = dconfig.getBoardWidth();
|
||||
_bhei = dconfig.getBoardHeight();
|
||||
|
||||
super.init(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width in pixels of a single board piece.
|
||||
*/
|
||||
public int getPieceWidth ()
|
||||
{
|
||||
return _pwid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height in pixels of a single board piece.
|
||||
*/
|
||||
public int getPieceHeight ()
|
||||
{
|
||||
return _phei;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link DropSprite} to populate <code>pos</code> with
|
||||
* the screen coordinates in pixels at which a piece at <code>(col,
|
||||
* row)</code> in the board should be drawn. Derived classes may wish
|
||||
* to override this method to allow specialised positioning of
|
||||
* sprites.
|
||||
*/
|
||||
public void getPiecePosition (int col, int row, Point pos)
|
||||
{
|
||||
pos.setLocation(col * _pwid, (row * _phei) - _roff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link DropSprite} to get the dimensions of the area
|
||||
* that will be occupied by rendering a piece segment of the given
|
||||
* orientation and length whose bottom-leftmost corner is at
|
||||
* <code>(col, row)</code>.
|
||||
*/
|
||||
public Dimension getPieceSegmentSize (int col, int row, int orient, int len)
|
||||
{
|
||||
if (orient == NORTH || orient == SOUTH) {
|
||||
return new Dimension(_pwid, len * _phei);
|
||||
} else {
|
||||
return new Dimension(len * _pwid, _phei);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new piece sprite and places it directly in it's correct
|
||||
* position.
|
||||
*/
|
||||
public void createPiece (int piece, int sx, int sy)
|
||||
{
|
||||
if (sx < 0 || sy < 0 || sx >= _bwid || sy >= _bhei) {
|
||||
Log.warning("Requested to create piece in invalid location " +
|
||||
"[sx=" + sx + ", sy=" + sy + "].");
|
||||
Thread.dumpStack();
|
||||
return;
|
||||
}
|
||||
createPiece(piece, sx, sy, sx, sy, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the piece sprite at the specified location, if no sprite
|
||||
* exists at the location, one will be created. <em>Note:</em> this
|
||||
* method assumes the default {@link ImageSprite} is being used to
|
||||
* display pieces. If {@link #createPieceSprite} is overridden to
|
||||
* return a non-ImageSprite, this method must also be customized.
|
||||
*/
|
||||
public void updatePiece (int sx, int sy)
|
||||
{
|
||||
updatePiece(_dboard.getPiece(sx, sy), sx, sy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the piece sprite at the specified location, if no sprite
|
||||
* exists at the location, one will be created. <em>Note:</em> this
|
||||
* method assumes the default {@link ImageSprite} is being used to
|
||||
* display pieces. If {@link #createPieceSprite} is overridden to
|
||||
* return a non-ImageSprite, this method must also be customized.
|
||||
*/
|
||||
public void updatePiece (int piece, int sx, int sy)
|
||||
{
|
||||
if (sx < 0 || sy < 0 || sx >= _bwid || sy >= _bhei) {
|
||||
Log.warning("Requested to update piece in invalid location " +
|
||||
"[sx=" + sx + ", sy=" + sy + "].");
|
||||
Thread.dumpStack();
|
||||
return;
|
||||
}
|
||||
int spos = sy * _bwid + sx;
|
||||
if (_pieces[spos] != null) {
|
||||
((ImageSprite)_pieces[spos]).setMirage(
|
||||
getPieceImage(piece, sx, sy, NORTH));
|
||||
} else {
|
||||
createPiece(piece, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new piece sprite and moves it into position on the board.
|
||||
*/
|
||||
public void createPiece (int piece, int sx, int sy, int tx, int ty,
|
||||
long duration)
|
||||
{
|
||||
if (tx < 0 || ty < 0 || tx >= _bwid || ty >= _bhei) {
|
||||
Log.warning("Requested to create and move piece to invalid " +
|
||||
"location [tx=" + tx + ", ty=" + ty + "].");
|
||||
Thread.dumpStack();
|
||||
return;
|
||||
}
|
||||
Sprite sprite = createPieceSprite(piece, sx, sy);
|
||||
if (sprite != null) {
|
||||
// position the piece properly to start
|
||||
Point start = new Point();
|
||||
getPiecePosition(sx, sy, start);
|
||||
sprite.setLocation(start.x, start.y);
|
||||
// now add it to the view
|
||||
addSprite(sprite);
|
||||
// and potentially move it into place
|
||||
movePiece(sprite, sx, sy, tx, ty, duration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the view to move the piece at the specified starting
|
||||
* position to the specified destination position. There must be a
|
||||
* sprite at the starting position, if there is a sprite at the
|
||||
* destination position, it must also be moved immediately following
|
||||
* this call (as in the case of a swap) to avoid badness.
|
||||
*
|
||||
* @return the piece sprite that is being moved.
|
||||
*/
|
||||
public Sprite movePiece (int sx, int sy, int tx, int ty, long duration)
|
||||
{
|
||||
int spos = sy * _bwid + sx;
|
||||
Sprite piece = _pieces[spos];
|
||||
if (piece == null) {
|
||||
Log.warning("Missing source sprite for drop [sx=" + sx +
|
||||
", sy=" + sy + ", tx=" + tx + ", ty=" + ty + "].");
|
||||
return null;
|
||||
}
|
||||
_pieces[spos] = null;
|
||||
movePiece(piece, sx, sy, tx, ty, duration);
|
||||
return piece;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for moving pieces into place.
|
||||
*/
|
||||
protected void movePiece (Sprite piece, final int sx, final int sy,
|
||||
final int tx, final int ty, long duration)
|
||||
{
|
||||
final Exception where = new Exception();
|
||||
|
||||
// if the sprite needn't move, then just position it and be done
|
||||
Point start = new Point();
|
||||
getPiecePosition(sx, sy, start);
|
||||
if (sx == tx && sy == ty) {
|
||||
int tpos = ty * _bwid + tx;
|
||||
if (_pieces[tpos] != null) {
|
||||
Log.warning("Zoiks! Asked to add a piece where we already " +
|
||||
"have one [sx=" + sx + ", sy=" + sy +
|
||||
", tx=" + tx + ", ty=" + ty + "].");
|
||||
Log.logStackTrace(where);
|
||||
return;
|
||||
}
|
||||
_pieces[tpos] = piece;
|
||||
piece.setLocation(start.x, start.y);
|
||||
return;
|
||||
}
|
||||
|
||||
// note that this piece is moving toward its destination
|
||||
final int tpos = ty * _bwid + tx;
|
||||
_moving[tpos] = true;
|
||||
|
||||
// then create a path and do some bits
|
||||
Point end = new Point();
|
||||
getPiecePosition(tx, ty, end);
|
||||
piece.addSpriteObserver(new PathAdapter() {
|
||||
public void pathCompleted (Sprite sprite, Path path, long when) {
|
||||
sprite.removeSpriteObserver(this);
|
||||
if (_pieces[tpos] != null) {
|
||||
Log.warning("Oh god, we're dropping onto another piece " +
|
||||
"[sx=" + sx + ", sy=" + sy +
|
||||
", tx=" + tx + ", ty=" + ty + "].");
|
||||
Log.logStackTrace(where);
|
||||
return;
|
||||
}
|
||||
_pieces[tpos] = sprite;
|
||||
if (_actionSprites.remove(sprite)) {
|
||||
maybeFireCleared();
|
||||
}
|
||||
pieceArrived(when, sprite, tx, ty);
|
||||
}
|
||||
});
|
||||
_actionSprites.add(piece);
|
||||
piece.move(new LinePath(start, end, duration));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a piece is finished moving into its requested position.
|
||||
* Derived classes may wish to take this opportunity to play a sound
|
||||
* or whatnot.
|
||||
*/
|
||||
protected void pieceArrived (long tickStamp, Sprite sprite, int px, int py)
|
||||
{
|
||||
_moving[py * _bwid + px] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the piece that is supposed to be at the specified
|
||||
* coordinates is not yet there but is actually en route to that
|
||||
* location (due to a call to {@link #movePiece}).
|
||||
*/
|
||||
protected boolean isMoving (int px, int py)
|
||||
{
|
||||
return _moving[py * _bwid + px];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image used to display the given piece at coordinates
|
||||
* <code>(0, 0)</code> with an orientation of {@link #NORTH}. This
|
||||
* serves as a convenience routine for those puzzles that don't bother
|
||||
* rendering their pieces differently when placed at different board
|
||||
* coordinates or in different orientations.
|
||||
*/
|
||||
public Mirage getPieceImage (int piece)
|
||||
{
|
||||
return getPieceImage(piece, 0, 0, NORTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image used to display the given piece at the specified
|
||||
* column and row with the given orientation.
|
||||
*/
|
||||
public abstract Mirage getPieceImage (
|
||||
int piece, int col, int row, int orient);
|
||||
|
||||
// documentation inherited
|
||||
public void setBoard (Board board)
|
||||
{
|
||||
// when a new board arrives, we want to remove all drop sprites
|
||||
// so that they don't modify the new board with their old ideas
|
||||
for (Iterator iter = _actionSprites.iterator(); iter.hasNext(); ) {
|
||||
Sprite s = (Sprite) iter.next();
|
||||
if (s instanceof DropSprite) {
|
||||
// remove it from _sprites safely
|
||||
iter.remove();
|
||||
// but then use the standard removal method
|
||||
removeSprite(s);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all of this board's piece sprites
|
||||
int pcount = (_pieces == null) ? 0 : _pieces.length;
|
||||
for (int ii = 0; ii < pcount; ii++) {
|
||||
if (_pieces[ii] != null) {
|
||||
removeSprite(_pieces[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
super.setBoard(board);
|
||||
|
||||
_dboard = (DropBoard)board;
|
||||
|
||||
// create the pieces for the new board
|
||||
Point spos = new Point();
|
||||
int width = _dboard.getWidth(), height = _dboard.getHeight();
|
||||
_pieces = new Sprite[width * height];
|
||||
for (int yy = 0; yy < height; yy++) {
|
||||
for (int xx = 0; xx < width; xx++) {
|
||||
Sprite piece = createPieceSprite(
|
||||
_dboard.getPiece(xx, yy), xx, yy);
|
||||
if (piece != null) {
|
||||
int ppos = yy * width + xx;
|
||||
getPiecePosition(xx, yy, spos);
|
||||
piece.setLocation(spos.x, spos.y);
|
||||
addSprite(piece);
|
||||
_pieces[ppos] = piece;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we use this to track when pieces are animating toward their new
|
||||
// position and are not yet in place
|
||||
_moving = new boolean[width * height];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the piece sprite at the specified location.
|
||||
*/
|
||||
public Sprite getPieceSprite (int xx, int yy)
|
||||
{
|
||||
return _pieces[yy * _dboard.getWidth() + xx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the specified piece from the board.
|
||||
*/
|
||||
public void clearPieceSprite (int xx, int yy)
|
||||
{
|
||||
int ppos = yy * _dboard.getWidth() + xx;
|
||||
if (_pieces[ppos] != null) {
|
||||
removeSprite(_pieces[ppos]);
|
||||
_pieces[ppos] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out a piece from the board along with its piece sprite.
|
||||
*/
|
||||
public void clearPiece (int xx, int yy)
|
||||
{
|
||||
_dboard.setPiece(xx, yy, PIECE_NONE);
|
||||
clearPieceSprite(xx, yy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new drop sprite used to animate the given pieces falling
|
||||
* in the specified column.
|
||||
*/
|
||||
public DropSprite createPieces (int col, int row, int[] pieces, int dist)
|
||||
{
|
||||
return new DropSprite(this, col, row, pieces, dist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dirties the rectangle encompassing the segment with the given
|
||||
* direction and length whose bottom-leftmost corner is at <code>(col,
|
||||
* row)</code>.
|
||||
*/
|
||||
public void dirtySegment (int dir, int col, int row, int len)
|
||||
{
|
||||
int x = _pwid * col, y = (_phei * row) - _roff;
|
||||
int wid = (dir == VERTICAL) ? _pwid : len * _pwid;
|
||||
int hei = (dir == VERTICAL) ? _phei * len : _phei;
|
||||
_remgr.invalidateRegion(x, y, wid, hei);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an animation showing the specified score
|
||||
* floating up the view, with the label initially centered within the
|
||||
* view.
|
||||
*
|
||||
* @param score the score text to display.
|
||||
* @param color the color of the text.
|
||||
* @param font the font.
|
||||
*/
|
||||
public ScoreAnimation createScoreAnimation (
|
||||
String score, Color color, Font font)
|
||||
{
|
||||
return createScoreAnimation(
|
||||
score, color, font, 0, _bhei - 1, _bwid, _bhei);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an animation showing the specified score
|
||||
* floating up the view.
|
||||
*
|
||||
* @param score the score text to display.
|
||||
* @param color the color of the text.
|
||||
* @param font the font to use.
|
||||
* @param x the left coordinate in board coordinates of the rectangle
|
||||
* within which the score is to be centered.
|
||||
* @param y the bottom coordinate in board coordinates of the
|
||||
* rectangle within which the score is to be centered.
|
||||
* @param width the width in board coordinates of the rectangle within
|
||||
* which the score is to be centered.
|
||||
* @param height the height in board coordinates of the rectangle
|
||||
* within which the score is to be centered.
|
||||
*/
|
||||
public ScoreAnimation createScoreAnimation (String score, Color color,
|
||||
Font font, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
// create the score animation
|
||||
ScoreAnimation anim =
|
||||
createScoreAnimation(score, color, font, x, y);
|
||||
|
||||
// position the label within the specified rectangle
|
||||
Dimension lsize = anim.getLabel().getSize();
|
||||
Point pos = new Point();
|
||||
centerRectInBoardRect(
|
||||
x, y, width, height, lsize.width, lsize.height, pos);
|
||||
anim.setLocation(pos.x, pos.y);
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the sprite that is used to display the specified piece. If
|
||||
* the piece represents no piece, this method should return null.
|
||||
*/
|
||||
protected Sprite createPieceSprite (int piece, int px, int py)
|
||||
{
|
||||
if (piece == PIECE_NONE) {
|
||||
return null;
|
||||
}
|
||||
ImageSprite sprite = new ImageSprite(
|
||||
getPieceImage(piece, px, py, NORTH));
|
||||
sprite.setRenderOrder(-1);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates <code>pos</code> with the most appropriate screen
|
||||
* coordinates to center a rectangle of the given width and height (in
|
||||
* pixels) within the specified rectangle (in board coordinates).
|
||||
*
|
||||
* @param bx the bounding rectangle's left board coordinate.
|
||||
* @param by the bounding rectangle's bottom board coordinate.
|
||||
* @param bwid the bounding rectangle's width in board coordinates.
|
||||
* @param bhei the bounding rectangle's height in board coordinates.
|
||||
* @param rwid the width of the rectangle to position in pixels.
|
||||
* @param rhei the height of the rectangle to position in pixels.
|
||||
* @param pos the point to populate with the rectangle's final
|
||||
* position.
|
||||
*/
|
||||
protected void centerRectInBoardRect (
|
||||
int bx, int by, int bwid, int bhei, int rwid, int rhei, Point pos)
|
||||
{
|
||||
getPiecePosition(bx, by + 1, pos);
|
||||
pos.x += (((bwid * _pwid) - rwid) / 2);
|
||||
pos.y -= ((((bhei * _phei) - rhei) / 2) + rhei);
|
||||
|
||||
// constrain to fit wholly within the board bounds
|
||||
pos.x = Math.max(Math.min(pos.x, _bounds.width - rwid), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the given drop block sprite to the specified orientation,
|
||||
* updating the image as necessary. Derived classes that make use of
|
||||
* block dropping functionality should override this method to do the
|
||||
* right thing.
|
||||
*/
|
||||
public void rotateDropBlock (DropBlockSprite sprite, int orient)
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void paintBetween (Graphics2D gfx, Rectangle dirtyRect)
|
||||
{
|
||||
gfx.translate(0, -_roff);
|
||||
renderBoard(gfx, dirtyRect);
|
||||
renderRisingPieces(gfx, dirtyRect);
|
||||
gfx.translate(0, _roff);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Dimension getPreferredSize ()
|
||||
{
|
||||
int wid = _bwid * _pwid;
|
||||
int hei = _bhei * _phei;
|
||||
return new Dimension(wid, hei);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the row of rising pieces to the given graphics context.
|
||||
* Sub-classes that make use of board rising functionality should
|
||||
* override this method to draw the rising piece row.
|
||||
*/
|
||||
protected void renderRisingPieces (Graphics2D gfx, Rectangle dirtyRect)
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the board rising offset to the given y-position.
|
||||
*/
|
||||
protected void setRiseOffset (int y)
|
||||
{
|
||||
if (y != _roff) {
|
||||
_roff = y;
|
||||
_remgr.invalidateRegion(_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/** The drop board. */
|
||||
protected DropBoard _dboard;
|
||||
|
||||
/** A sprite for every piece displayed in the drop board. */
|
||||
protected Sprite[] _pieces;
|
||||
|
||||
/** Indicates whether a piece is en route to its destination. */
|
||||
protected boolean[] _moving;
|
||||
|
||||
/** The piece dimensions in pixels. */
|
||||
protected int _pwid, _phei;
|
||||
|
||||
/** The board rising offset. */
|
||||
protected int _roff;
|
||||
|
||||
/** The board dimensions in pieces. */
|
||||
protected int _bwid, _bhei;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// $Id: DropPanel.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
import com.threerings.puzzle.data.BoardSummary;
|
||||
|
||||
/**
|
||||
* Puzzles using the drop services need implement this interface to
|
||||
* display drop puzzle related information.
|
||||
*/
|
||||
public interface DropPanel
|
||||
{
|
||||
/**
|
||||
* Sets the next block to be displayed.
|
||||
*/
|
||||
public void setNextBlock (int[] pieces);
|
||||
|
||||
/**
|
||||
* Updates the board summary display for the given player.
|
||||
*/
|
||||
public void setSummary (int pidx, BoardSummary summary);
|
||||
}
|
||||
@@ -0,0 +1,584 @@
|
||||
//
|
||||
// $Id: DropSprite.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Shape;
|
||||
|
||||
import com.samskivert.util.ObserverList;
|
||||
import com.threerings.util.DirectionUtil;
|
||||
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.sprite.Sprite;
|
||||
|
||||
import com.threerings.puzzle.Log;
|
||||
|
||||
/**
|
||||
* The drop sprite is a sprite that displays one or more pieces falling
|
||||
* toward the bottom of the board.
|
||||
*/
|
||||
public class DropSprite extends Sprite
|
||||
{
|
||||
/**
|
||||
* Constructs a drop sprite and starts it dropping.
|
||||
*
|
||||
* @param view the board view upon which this sprite will be displayed.
|
||||
* @param col the column of the sprite.
|
||||
* @param row the row of the bottom-most piece.
|
||||
* @param pieces the pieces displayed by the sprite.
|
||||
* @param dist the distance the sprite is to drop in rows.
|
||||
*/
|
||||
public DropSprite (
|
||||
DropBoardView view, int col, int row, int[] pieces, int dist)
|
||||
{
|
||||
this(view, col, row, pieces, dist, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a drop sprite and starts it dropping.
|
||||
*
|
||||
* @param view the board view upon which this sprite will be displayed.
|
||||
* @param col the column of the sprite.
|
||||
* @param row the row of the bottom-most piece.
|
||||
* @param pieces the pieces displayed by the sprite.
|
||||
* @param dist the distance the sprite is to drop in rows.
|
||||
* @param renderOrder the render order.
|
||||
*/
|
||||
public DropSprite (
|
||||
DropBoardView view, int col, int row, int[] pieces, int dist,
|
||||
int renderOrder)
|
||||
{
|
||||
_view = view;
|
||||
_col = col;
|
||||
_row = row;
|
||||
_pieces = pieces;
|
||||
_dist = (dist == 0) ? 1 : dist;
|
||||
_orient = NORTH;
|
||||
_unit = _view.getPieceHeight();
|
||||
setRenderOrder(renderOrder);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void init ()
|
||||
{
|
||||
super.init();
|
||||
|
||||
// size the bounds to fit our pieces
|
||||
updateBounds();
|
||||
// set up the piece location
|
||||
setBoardLocation(_row, _col);
|
||||
// calculate vertical render offset based on the number of pieces
|
||||
setRowOffset(-(_pieces.length - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remaining number of columns to drop.
|
||||
*/
|
||||
public int getDistance ()
|
||||
{
|
||||
return _dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column the piece is located in.
|
||||
*/
|
||||
public int getColumn ()
|
||||
{
|
||||
return _col;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row the piece is located in.
|
||||
*/
|
||||
public int getRow ()
|
||||
{
|
||||
return _row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pieces the sprite is displaying.
|
||||
*/
|
||||
public int[] getPieces ()
|
||||
{
|
||||
return _pieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the velocity of this sprite.
|
||||
*/
|
||||
public float getVelocity ()
|
||||
{
|
||||
return _vel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the row and column the piece is located in.
|
||||
*/
|
||||
public void setBoardLocation (int row, int col)
|
||||
{
|
||||
_row = row;
|
||||
_col = col;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the column the piece is located in.
|
||||
*/
|
||||
public void setColumn (int col)
|
||||
{
|
||||
_col = col;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the row the piece is located in.
|
||||
*/
|
||||
public void setRow (int row)
|
||||
{
|
||||
_row = row;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the column offset of the sprite image.
|
||||
*/
|
||||
public void setColumnOffset (int count)
|
||||
{
|
||||
_offx = count;
|
||||
updateRenderOffset();
|
||||
updateRenderOrigin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the row offset of the sprite image.
|
||||
*/
|
||||
public void setRowOffset (int count)
|
||||
{
|
||||
_offy = count;
|
||||
updateRenderOffset();
|
||||
updateRenderOrigin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pieces the sprite is displaying.
|
||||
*/
|
||||
public void setPieces (int[] pieces)
|
||||
{
|
||||
_pieces = pieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the velocity of this sprite. The time at which the current
|
||||
* row was entered is modified so that the sprite position will remain
|
||||
* the same when calculated using the new velocity since the piece
|
||||
* sprite may have its velocity modified in the middle of a row
|
||||
* traversal.
|
||||
*/
|
||||
public void setVelocity (float velocity)
|
||||
{
|
||||
// bail if we've already got the requested velocity
|
||||
if (_vel == velocity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_rowstamp > 0) {
|
||||
// get our current distance along the row
|
||||
long now = _view.getTimeStamp();
|
||||
float pctdone = getPercentDone(now);
|
||||
|
||||
// revise the current row entry time to account for the new velocity
|
||||
float travpix = pctdone * _unit;
|
||||
long msecs = (long)(travpix / velocity);
|
||||
_rowstamp = now - msecs;
|
||||
}
|
||||
|
||||
// update the velocity
|
||||
_vel = velocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the piece dropping toward the next row.
|
||||
*/
|
||||
public void drop ()
|
||||
{
|
||||
// Log.info("Dropping piece [piece=" + this + "].");
|
||||
|
||||
// drop one row by default
|
||||
if (_dist <= 0) {
|
||||
_dist = 1;
|
||||
}
|
||||
|
||||
if (_stopstamp > 0) {
|
||||
// we're dropping from a stand-still
|
||||
long delta = _view.getTimeStamp() - _stopstamp;
|
||||
_rowstamp += delta;
|
||||
_stopstamp = 0;
|
||||
|
||||
} else {
|
||||
// we're continuing a previous drop, so make use of any
|
||||
// previously existing time
|
||||
_rowstamp = _endstamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this drop sprite is dropping, false if it has been
|
||||
* {@link #stop}ped or has not yet been {@link #drop}ped.
|
||||
*/
|
||||
public boolean isDropping ()
|
||||
{
|
||||
return (_stopstamp == 0) && (_rowstamp != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the piece from dropping.
|
||||
*/
|
||||
public void stop ()
|
||||
{
|
||||
if (_stopstamp == 0) {
|
||||
_stopstamp = _view.getTimeStamp();
|
||||
// Log.info("Stopped piece [piece=" + this + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the drop sprite into (or takes it out of) bouncing
|
||||
* mode. Bouncing mode is used to put the sprite into limbo after it
|
||||
* lands but before we commit the landing, giving the user a last
|
||||
* moment change move or rotate the piece. While the sprite is
|
||||
* "bouncing" it will be rendered one pixel below it's at rest state.
|
||||
*/
|
||||
public void setBouncing (boolean bouncing)
|
||||
{
|
||||
if (_bouncing = bouncing) {
|
||||
// if we've activated bouncing, shift the sprite slightly to
|
||||
// illustrate its new state
|
||||
shiftForBounce();
|
||||
|
||||
// to prevent funny business in the event that we were a long
|
||||
// ways past the end of the row when we landed, we warp the
|
||||
// sprite back to the exact point of landing for the purposes
|
||||
// of the bounce and any subsequent antics
|
||||
_endstamp = _rowstamp = _view.getTimeStamp();
|
||||
|
||||
// Log.info("Adjusted rowstap due to bounce " +
|
||||
// "[time=" + _endstamp + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this sprite is bouncing.
|
||||
*/
|
||||
public boolean isBouncing ()
|
||||
{
|
||||
return _bouncing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sprite's location to illustrate that it is currently in
|
||||
* the "bouncing" state.
|
||||
*/
|
||||
protected void shiftForBounce ()
|
||||
{
|
||||
setLocation(_ox, _srcPos.y+1);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean inside (Shape shape)
|
||||
{
|
||||
return shape.contains(_bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value between <code>0.0</code> and <code>1.0</code>
|
||||
* representing how far the piece has moved toward the next row
|
||||
* as of the given time stamp.
|
||||
*/
|
||||
public float getPercentDone (long timestamp)
|
||||
{
|
||||
// if we've never been ticked and so haven't yet initialized our
|
||||
// row start timestamp, just let the caller know that we've not
|
||||
// traversed our row at all
|
||||
if (_rowstamp == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
long msecs = Math.max(0, timestamp - _rowstamp);
|
||||
float travpix = msecs * _vel;
|
||||
float pctdone = (travpix / _unit);
|
||||
|
||||
// Log.info("getPercentDone [timestamp=" + timestamp +
|
||||
// ", rowstamp=" + _rowstamp + ", msecs=" + msecs +
|
||||
// ", travpix=" + travpix + ", pctdone=" + pctdone +
|
||||
// ", vel=" + _vel + "].");
|
||||
|
||||
return pctdone;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void paint (Graphics2D gfx)
|
||||
{
|
||||
// get the column and row increment based on the sprite's orientation
|
||||
int oidx = _orient/2;
|
||||
int incx = ORIENT_DX[oidx];
|
||||
int incy = ORIENT_DY[oidx];
|
||||
|
||||
// determine offset from the start of each actual row and column
|
||||
int dx = _ox - _srcPos.x, dy = _oy - _srcPos.y;
|
||||
|
||||
int pcol = _col, prow = _row;
|
||||
for (int ii = 0; ii < _pieces.length; ii++) {
|
||||
// ask the board for the render position of this piece
|
||||
_view.getPiecePosition(pcol, prow, _renderPos);
|
||||
// draw the piece image
|
||||
paintPieceImage(gfx, ii, pcol, prow, _orient,
|
||||
_renderPos.x + dx, _renderPos.y + dy);
|
||||
// increment the target column and row
|
||||
pcol += incx;
|
||||
prow += incy;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints the specified piece with the supplied parameters.
|
||||
*/
|
||||
protected void paintPieceImage (Graphics2D gfx, int pieceidx,
|
||||
int col, int row, int orient, int x, int y)
|
||||
{
|
||||
Mirage image = _view.getPieceImage(_pieces[pieceidx], col, row, orient);
|
||||
image.paint(gfx, x, y);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void tick (long timestamp)
|
||||
{
|
||||
super.tick(timestamp);
|
||||
|
||||
// initialize our rowstamp if we haven't done so already
|
||||
if (_rowstamp == 0) {
|
||||
_rowstamp = timestamp;
|
||||
}
|
||||
|
||||
// if we're bouncing or paused, do nothing here
|
||||
if (_bouncing || _stopstamp > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
PieceMovedOp pmop = null;
|
||||
|
||||
// figure out how far along the current board coordinate we should be
|
||||
float pctdone = getPercentDone(timestamp);
|
||||
if (pctdone >= 1.0f) {
|
||||
// note that we've reached the next row
|
||||
advancePosition();
|
||||
|
||||
// update remaining drop distance
|
||||
_dist--;
|
||||
|
||||
// calculate any remaining time to be used
|
||||
long used = (long)(_unit / _vel);
|
||||
_endstamp = _rowstamp + used;
|
||||
_rowstamp = _endstamp;
|
||||
|
||||
// update our percent done because we've moved down a row
|
||||
pctdone -= 1.0;
|
||||
|
||||
// inform observers that we've reached our destination
|
||||
pmop = new PieceMovedOp(this, timestamp, _col, _row);
|
||||
}
|
||||
|
||||
// constrain the sprite's position to the destination row
|
||||
pctdone = Math.min(pctdone, 1.0f);
|
||||
|
||||
// calculate the latest sprite position
|
||||
int nx = _srcPos.x + (int)((_destPos.x - _srcPos.x) * pctdone);
|
||||
int ny = _srcPos.y + (int)((_destPos.y - _srcPos.y) * pctdone);
|
||||
|
||||
// Log.info("Drop sprite tick [dist=" + _dist + ", pctdone=" + pctdone +
|
||||
// ", row=" + _row + ", col=" + _col +
|
||||
// ", nx=" + nx + ", ny=" + ny + "].");
|
||||
|
||||
// only update the sprite's location if it actually moved
|
||||
if (_ox != nx || _oy != ny) {
|
||||
setLocation(nx, ny);
|
||||
}
|
||||
|
||||
// lastly notify our observers if we made it to the next row
|
||||
if (pmop != null) {
|
||||
_observers.apply(pmop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the sprite has finished traversing its current row to
|
||||
* advance its board coordinates to the next row.
|
||||
*/
|
||||
protected void advancePosition ()
|
||||
{
|
||||
setRow(_row + 1);
|
||||
// Log.info("Moved to row " + _row);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void fastForward (long timeDelta)
|
||||
{
|
||||
if (_rowstamp > 0) {
|
||||
_rowstamp += timeDelta;
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void toString (StringBuilder buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", orient=").append(DirectionUtil.toShortString(_orient));
|
||||
buf.append(", row=").append(_row);
|
||||
buf.append(", col=").append(_col);
|
||||
buf.append(", offx=").append(_offx);
|
||||
buf.append(", offy=").append(_offy);
|
||||
buf.append(", dist=").append(_dist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates internal pixel coordinates used when the piece is moving.
|
||||
*/
|
||||
protected void updatePosition ()
|
||||
{
|
||||
_view.getPiecePosition(_col, _row, _srcPos);
|
||||
_view.getPiecePosition(_col, _row+1, _destPos);
|
||||
setLocation(_srcPos.x, _srcPos.y);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setOrientation (int orient)
|
||||
{
|
||||
invalidate();
|
||||
super.setOrientation(orient);
|
||||
updateBounds();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bounds for this sprite based on the sprite display
|
||||
* dimensions in the view.
|
||||
*/
|
||||
protected void updateBounds ()
|
||||
{
|
||||
Dimension size = _view.getPieceSegmentSize(
|
||||
_col, _row, _orient, _pieces.length);
|
||||
_bounds.width = size.width;
|
||||
_bounds.height = size.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts our render origin such that our location is not in the
|
||||
* upper left of the sprite's rendered image but is in fact offset by
|
||||
* some number of rows and columns.
|
||||
*/
|
||||
protected void updateRenderOffset ()
|
||||
{
|
||||
_oxoff = -(_view.getPieceWidth() * _offx);
|
||||
_oyoff = -(_view.getPieceHeight() * _offy);
|
||||
}
|
||||
|
||||
/** Used to dispatch {@link DropSpriteObserver#pieceMoved}. */
|
||||
protected static class PieceMovedOp implements ObserverList.ObserverOp
|
||||
{
|
||||
public PieceMovedOp (DropSprite sprite, long when, int col, int row)
|
||||
{
|
||||
_sprite = sprite;
|
||||
_when = when;
|
||||
_col = col;
|
||||
_row = row;
|
||||
}
|
||||
|
||||
public boolean apply (Object observer)
|
||||
{
|
||||
if (observer instanceof DropSpriteObserver) {
|
||||
((DropSpriteObserver)observer).pieceMoved(
|
||||
_sprite, _when, _col, _row);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected DropSprite _sprite;
|
||||
protected long _when;
|
||||
protected int _col, _row;
|
||||
}
|
||||
|
||||
/** The default piece velocity. */
|
||||
protected static final float DEFAULT_VELOCITY = 30f/1000f;
|
||||
|
||||
/** The time at which we started the current row. */
|
||||
protected long _rowstamp;
|
||||
|
||||
/** The time at which we reached the end of the previous row. */
|
||||
protected long _endstamp;
|
||||
|
||||
/** The time at which we were stopped en route to our next row. */
|
||||
protected long _stopstamp;
|
||||
|
||||
/** The board view upon which this sprite is displayed. */
|
||||
protected DropBoardView _view;
|
||||
|
||||
/** The unit distance the sprite moves to reach the next row. */
|
||||
protected int _unit;
|
||||
|
||||
/** The screen coordinates of the top-left of the row currently
|
||||
* occupied by the sprite. */
|
||||
protected Point _srcPos = new Point();
|
||||
|
||||
/** The screen coordinates of the top-left of the row toward which the
|
||||
* sprite is falling. */
|
||||
protected Point _destPos = new Point();
|
||||
|
||||
/** The piece render position; used as working data when determining
|
||||
* where to render each piece in the sprite. */
|
||||
protected Point _renderPos = new Point();
|
||||
|
||||
/** The number of rows remaining to drop. */
|
||||
protected int _dist;
|
||||
|
||||
/** The piece velocity. */
|
||||
protected float _vel = DEFAULT_VELOCITY;
|
||||
|
||||
/** The offsets in columns or rows at which the piece is rendered. */
|
||||
protected int _offx, _offy;
|
||||
|
||||
/** The current piece location in the board. */
|
||||
protected int _row, _col;
|
||||
|
||||
/** The pieces this sprite is displaying. */
|
||||
protected int[] _pieces;
|
||||
|
||||
/** Indicates that the drop sprite is bouncing; see {@link
|
||||
* #setBouncing}. */
|
||||
protected boolean _bouncing;
|
||||
|
||||
// used to compute the column and row increment while rendering the
|
||||
// sprite's pieces based on its orientation
|
||||
// W N E S
|
||||
protected static final int[] ORIENT_DX = { -1, 0, 1, 0 };
|
||||
protected static final int[] ORIENT_DY = { 0, -1, 0, 1 };
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $Id: DropSpriteObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
/**
|
||||
* Provides notifications for drop puzzle specific stuff.
|
||||
*/
|
||||
public interface DropSpriteObserver
|
||||
{
|
||||
/**
|
||||
* Called when the drop sprite has moved completely to the specified
|
||||
* board coordinates.
|
||||
*/
|
||||
public void pieceMoved (DropSprite sprite, long when, int col, int row);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// $Id: NextBlockView.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.util.DirectionCodes;
|
||||
|
||||
/**
|
||||
* The next block view displays an image representing the next drop block
|
||||
* to appear in the game.
|
||||
*/
|
||||
public class NextBlockView extends JComponent
|
||||
implements DirectionCodes
|
||||
{
|
||||
/**
|
||||
* Constructs a next block view.
|
||||
*/
|
||||
public NextBlockView (DropBoardView view, int pwid, int phei, int orient)
|
||||
{
|
||||
// save things off
|
||||
_view = view;
|
||||
_pwid = pwid;
|
||||
_phei = phei;
|
||||
_orient = orient;
|
||||
|
||||
// configure the component
|
||||
setOpaque(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pieces displayed by the view.
|
||||
*/
|
||||
public void setPieces (int[] pieces)
|
||||
{
|
||||
_pieces = pieces;
|
||||
repaint();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void paintComponent (Graphics g)
|
||||
{
|
||||
super.paintComponent(g);
|
||||
|
||||
// draw the pieces
|
||||
Graphics2D gfx = (Graphics2D)g;
|
||||
if (_pieces != null) {
|
||||
Dimension size = getSize();
|
||||
int xpos = (_orient == VERTICAL) ? 0 : (size.width - _pwid);
|
||||
int ypos = (_orient == VERTICAL) ? (size.height - _phei) : 0;
|
||||
|
||||
for (int ii = 0; ii < _pieces.length; ii++) {
|
||||
Mirage image = _view.getPieceImage(_pieces[ii]);
|
||||
image.paint(gfx, xpos, ypos);
|
||||
if (_orient == VERTICAL) {
|
||||
ypos -= _phei;
|
||||
} else {
|
||||
xpos -= _pwid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Dimension getPreferredSize ()
|
||||
{
|
||||
int wid = (_orient == VERTICAL) ? _pwid : (2 * _pwid);
|
||||
int hei = (_orient == VERTICAL) ? (2 * _phei) : _phei;
|
||||
return new Dimension(wid, hei);
|
||||
}
|
||||
|
||||
/** The drop board view from which we obtain piece images. */
|
||||
protected DropBoardView _view;
|
||||
|
||||
/** The pieces displayed by this view. */
|
||||
protected int[] _pieces;
|
||||
|
||||
/** The piece dimensions in pixels. */
|
||||
protected int _pwid, _phei;
|
||||
|
||||
/** The view orientation; one of {@link #HORIZONTAL} or {@link
|
||||
* #VERTICAL}. */
|
||||
protected int _orient;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// $Id: PieceGroupAnimation.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.puzzle.drop.client;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import com.threerings.media.animation.Animation;
|
||||
import com.threerings.media.sprite.ImageSprite;
|
||||
import com.threerings.media.sprite.PathObserver;
|
||||
import com.threerings.media.sprite.Sprite;
|
||||
import com.threerings.media.util.Path;
|
||||
|
||||
import com.threerings.puzzle.drop.data.DropBoard;
|
||||
import com.threerings.puzzle.drop.data.DropPieceCodes;
|
||||
|
||||
/**
|
||||
* Animates all the pieces on a puzzle board doing some sort of global
|
||||
* effect like all flying into place or out into the ether.
|
||||
*/
|
||||
public abstract class PieceGroupAnimation extends Animation
|
||||
implements PathObserver
|
||||
{
|
||||
/**
|
||||
* Creates a piece group animation which must be initialized with a
|
||||
* subsequent call to {@link #init}.
|
||||
*/
|
||||
public PieceGroupAnimation (DropBoardView view, DropBoard board)
|
||||
{
|
||||
super(new Rectangle(0, 0, 0, 0)); // we don't render ourselves
|
||||
_view = view;
|
||||
_board = board;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void tick (long tickStamp)
|
||||
{
|
||||
// nothing doing
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void paint (Graphics2D gfx)
|
||||
{
|
||||
// nothing doing
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void pathCancelled (Sprite sprite, Path path)
|
||||
{
|
||||
_finished = (--_penders == 0);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void pathCompleted (Sprite sprite, Path path, long when)
|
||||
{
|
||||
_finished = (--_penders == 0);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void willStart (long tickStamp)
|
||||
{
|
||||
super.willStart(tickStamp);
|
||||
|
||||
// create an image sprite for every piece on the board and set
|
||||
// them on their paths
|
||||
int width = _board.getWidth(), height = _board.getHeight();
|
||||
_sprites = new Sprite[width * height];
|
||||
for (int yy = 0; yy < height; yy++) {
|
||||
for (int xx = 0; xx < width; xx++) {
|
||||
int spos = yy*width+xx;
|
||||
_sprites[spos] = _view.getPieceSprite(xx, yy);
|
||||
if (_sprites[spos] != null) {
|
||||
configureSprite(_sprites[spos], xx, yy);
|
||||
_sprites[spos].addSpriteObserver(this);
|
||||
_penders++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An animation must override this method to configure each sprite
|
||||
* with a path, potentially a render order, and whatever other
|
||||
* configurations are needed.
|
||||
*/
|
||||
protected abstract void configureSprite (Sprite sprite, int xx, int yy);
|
||||
|
||||
protected DropBoardView _view;
|
||||
protected DropBoard _board;
|
||||
protected Sprite[] _sprites;
|
||||
protected int _penders;
|
||||
}
|
||||
Reference in New Issue
Block a user