db91329aff
rendering the tiles from an isometric perspective. Added comments and minor clean-up. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@88 542714f4-19e9-0310-aa3c-eee0fc999fb1
281 lines
7.6 KiB
Java
281 lines
7.6 KiB
Java
//
|
|
// $Id: IsoSceneView.java,v 1.13 2001/07/20 08:17:10 shaper Exp $
|
|
|
|
package com.threerings.miso.scene;
|
|
|
|
import com.threerings.miso.Log;
|
|
import com.threerings.miso.tile.Tile;
|
|
import com.threerings.miso.tile.TileManager;
|
|
import com.threerings.miso.util.MathUtil;
|
|
|
|
import java.awt.*;
|
|
import java.awt.image.*;
|
|
|
|
/**
|
|
* The IsoSceneView provides an isometric graphics view of a
|
|
* particular scene.
|
|
*/
|
|
public class IsoSceneView implements SceneView
|
|
{
|
|
public IsoSceneView (TileManager tmgr)
|
|
{
|
|
_tmgr = tmgr;
|
|
|
|
_bounds = new Rectangle(0, 0, DEF_BOUNDS_WIDTH, DEF_BOUNDS_HEIGHT);
|
|
|
|
_htile = new Point();
|
|
_htile.x = _htile.y = -1;
|
|
|
|
_hcolor = Color.green;
|
|
_hstroke = new BasicStroke(3);
|
|
|
|
_font = new Font("Arial", Font.PLAIN, 7);
|
|
|
|
_lineX = new Point[2];
|
|
_lineY = new Point[2];
|
|
for (int ii = 0; ii < 2; ii++) {
|
|
_lineX[ii] = new Point();
|
|
_lineY[ii] = new Point();
|
|
}
|
|
|
|
_showCoords = false;
|
|
}
|
|
|
|
public void paint (Graphics g)
|
|
{
|
|
Graphics2D gfx = (Graphics2D)g;
|
|
|
|
// clip the drawing region to our desired bounds since we
|
|
// currently draw tiles willy-nilly in undesirable areas.
|
|
Shape oldclip = gfx.getClip();
|
|
gfx.setClip(0, 0, _bounds.width, _bounds.height);
|
|
|
|
// draw the full scene into the offscreen image buffer
|
|
renderScene(gfx);
|
|
|
|
// restore the original clipping region
|
|
gfx.setClip(oldclip);
|
|
}
|
|
|
|
protected void renderScene (Graphics2D gfx)
|
|
{
|
|
int mx = 1;
|
|
int my = 0;
|
|
|
|
int screenY = DEF_CENTER_Y;
|
|
|
|
for (int ii = 0; ii < TILE_RENDER_ROWS; ii++) {
|
|
// determine starting tile coordinates
|
|
int tx = (ii < Scene.TILE_HEIGHT) ? 0 : mx++;
|
|
int ty = my;
|
|
|
|
// determine number of tiles in this row
|
|
int length = (ty - tx) + 1;
|
|
|
|
// determine starting screen x-position
|
|
int screenX = DEF_CENTER_X - ((length) * Tile.HALF_WIDTH);
|
|
|
|
for (int jj = 0; jj < length; jj++) {
|
|
|
|
for (int kk = 0; kk < Scene.NUM_LAYERS; kk++) {
|
|
// grab the tile we're rendering
|
|
Tile tile = _scene.tiles[tx][ty][kk];
|
|
if (tile == null) continue;
|
|
|
|
// determine screen y-position, accounting for
|
|
// tile image height
|
|
int ypos = screenY - (tile.height - Tile.HEIGHT);
|
|
|
|
// draw the tile image at the appropriate screen position
|
|
gfx.drawImage(tile.img, screenX, ypos, null);
|
|
}
|
|
|
|
// draw tile coordinates in each tile
|
|
if (_showCoords) paintCoords(gfx, tx, ty, screenX, screenY);
|
|
|
|
// draw an outline around the highlighted tile
|
|
if (tx == _htile.x && ty == _htile.y) {
|
|
paintHighlightedTile(gfx, screenX, screenY);
|
|
}
|
|
|
|
// each tile is one tile-width to the right of the previous
|
|
screenX += Tile.WIDTH;
|
|
|
|
// advance tile x and decrement tile y as we move to
|
|
// the right drawing the row
|
|
tx++;
|
|
ty--;
|
|
}
|
|
|
|
// each row is a half-tile-height away from the previous row
|
|
screenY += Tile.HALF_HEIGHT;
|
|
|
|
// advance starting y-axis coordinate unless we've hit bottom
|
|
if ((++my) > Scene.TILE_HEIGHT - 1) my = Scene.TILE_HEIGHT - 1;
|
|
}
|
|
|
|
// paintMouseLines(gfx);
|
|
}
|
|
|
|
protected void paintMouseLines (Graphics2D gfx)
|
|
{
|
|
// draw the baseline x-axis line
|
|
gfx.setColor(Color.red);
|
|
gfx.drawLine(_lineX[0].x, _lineX[0].y, _lineX[1].x, _lineX[1].y);
|
|
|
|
// draw line from last mouse pos to baseline
|
|
gfx.setColor(Color.yellow);
|
|
gfx.drawLine(_lineY[0].x, _lineY[0].y, _lineY[1].x, _lineY[1].y);
|
|
|
|
// draw the most recent mouse cursor position
|
|
gfx.setColor(Color.green);
|
|
gfx.fillRect(_lineY[0].x, _lineY[0].y, 2, 2);
|
|
gfx.setColor(Color.red);
|
|
gfx.drawRect(_lineY[0].x - 1, _lineY[0].y - 1, 3, 3);
|
|
}
|
|
|
|
/**
|
|
* Paint the tile coordinates in tile (x, y) whose top-left corner
|
|
* is at screen coordinates (sx, sy).
|
|
*/
|
|
protected void paintCoords (Graphics2D gfx, int x, int y, int sx, int sy)
|
|
{
|
|
gfx.setFont(_font);
|
|
gfx.setColor(Color.white);
|
|
gfx.drawString(""+x, sx+Tile.HALF_WIDTH-2, sy+Tile.HALF_HEIGHT-2);
|
|
gfx.drawString(""+y, sx+Tile.HALF_WIDTH-2, sy+Tile.HEIGHT-2);
|
|
}
|
|
|
|
/**
|
|
* Paint a highlight around the tile at screen coordinates (sx, sy).
|
|
*/
|
|
protected void paintHighlightedTile (Graphics2D gfx, int sx, int sy)
|
|
{
|
|
int x = sx;
|
|
int y = sy;
|
|
|
|
Stroke ostroke = gfx.getStroke();
|
|
gfx.setStroke(_hstroke);
|
|
gfx.setColor(_hcolor);
|
|
|
|
gfx.drawLine(x, y + Tile.HALF_HEIGHT,
|
|
x + Tile.HALF_WIDTH, y);
|
|
gfx.drawLine(x + Tile.HALF_WIDTH, y,
|
|
x + Tile.WIDTH, y + Tile.HALF_HEIGHT);
|
|
gfx.drawLine(x + Tile.WIDTH, y + Tile.HALF_HEIGHT,
|
|
x + Tile.HALF_WIDTH, y + Tile.HEIGHT);
|
|
gfx.drawLine(x + Tile.HALF_WIDTH, y + Tile.HEIGHT,
|
|
x, y + Tile.HALF_HEIGHT);
|
|
|
|
gfx.setStroke(ostroke);
|
|
}
|
|
|
|
/**
|
|
* Highlight the tile at the specified pixel coordinates the next
|
|
* time the scene is re-rendered.
|
|
*/
|
|
public void setHighlightedTile (int x, int y)
|
|
{
|
|
Point tpos = screenToTile(x, y);
|
|
if (tpos != null) _htile = tpos;
|
|
// Log.info("Highlighting tile [x="+_htile.x+", y="+_htile.y+"].");
|
|
}
|
|
|
|
/**
|
|
* Returns a new Point object containing the tile coordinates
|
|
* corresponding to the specified screen-based mouse-position
|
|
* coordinates.
|
|
*/
|
|
protected Point screenToTile (int x, int y)
|
|
{
|
|
Point tpos = new Point();
|
|
|
|
float mX, mY;
|
|
int bX, bY;
|
|
|
|
// calculate the x-axis line (from tile origin to right end of x-axis)
|
|
mX = 0.5f;
|
|
_lineX[0].x = DEF_CENTER_X;
|
|
bX = (int)-(mX * _lineX[0].x);
|
|
_lineX[0].y = DEF_CENTER_Y;
|
|
_lineX[1].x = _lineX[0].x + (Tile.HALF_WIDTH * Scene.TILE_WIDTH);
|
|
_lineX[1].y = _lineX[0].y + (int)((mX * _lineX[1].x) + bX);
|
|
|
|
// calculate line parallel to the y-axis (from mouse pos to x-axis)
|
|
_lineY[0].x = x;
|
|
_lineY[0].y = y;
|
|
mY = -0.5f;
|
|
bY = (int)(_lineY[0].y - (mY * _lineY[0].x));
|
|
|
|
// determine intersection of x- and y-axis lines
|
|
_lineY[1].x = (int)((bY - (bX + DEF_CENTER_Y)) / (mX - mY));
|
|
_lineY[1].y = (int)((mY * _lineY[1].x) + bY);
|
|
|
|
// determine distance of mouse pos along the x axis
|
|
int xdist = (int)
|
|
MathUtil.distance(_lineX[0].x, _lineX[0].y,
|
|
_lineY[1].x, _lineY[1].y);
|
|
tpos.x = (int)(xdist / TILE_EDGE_LENGTH);
|
|
|
|
// determine distance of mouse pos along the y-axis
|
|
int ydist = (int)
|
|
MathUtil.distance(_lineY[0].x, _lineY[0].y,
|
|
_lineY[1].x, _lineY[1].y);
|
|
tpos.y = (int)(ydist / TILE_EDGE_LENGTH);
|
|
|
|
// Log.info("[mX="+mX+", bX="+bX+", mY="+mY+", bY="+bY+"]");
|
|
// Log.info("x-axis=" + MathUtil.lineToString(_lineX[0], _lineX[1]));
|
|
// Log.info("y-axis=" + MathUtil.lineToString(_lineY[0], _lineY[1]));
|
|
|
|
return tpos;
|
|
}
|
|
|
|
public void setScene (Scene scene)
|
|
{
|
|
_scene = scene;
|
|
}
|
|
|
|
public void setShowCoordinates (boolean show)
|
|
{
|
|
_showCoords = show;
|
|
}
|
|
|
|
public void setTile (int x, int y, int lnum, Tile tile)
|
|
{
|
|
Point tpos = screenToTile(x, y);
|
|
_scene.tiles[tpos.x][tpos.y][lnum] = tile;
|
|
}
|
|
|
|
// default dimensions of the scene view
|
|
protected static final int DEF_BOUNDS_WIDTH = 18 * Tile.WIDTH;
|
|
protected static final int DEF_BOUNDS_HEIGHT = 37 * Tile.HEIGHT;
|
|
|
|
// total number of tile rows to render the full view
|
|
protected static final int TILE_RENDER_ROWS =
|
|
(Scene.TILE_WIDTH * Scene.TILE_HEIGHT) - 1;
|
|
|
|
// starting x/y-positions to render the view
|
|
protected static final int DEF_CENTER_X = DEF_BOUNDS_WIDTH / 2;
|
|
protected static final int DEF_CENTER_Y = -(9 * Tile.HEIGHT);
|
|
|
|
// length of a tile edge as rendered from an isometric perspective
|
|
public static final float TILE_EDGE_LENGTH = (float)
|
|
Math.sqrt((Tile.HALF_WIDTH * Tile.HALF_WIDTH) +
|
|
(Tile.HALF_HEIGHT * Tile.HALF_HEIGHT));
|
|
|
|
protected Point _lineX[], _lineY[];
|
|
|
|
protected Rectangle _bounds;
|
|
|
|
protected Point _htile;
|
|
protected Color _hcolor;
|
|
protected Stroke _hstroke;
|
|
|
|
protected Font _font;
|
|
|
|
protected boolean _showCoords;
|
|
|
|
protected Scene _scene;
|
|
protected TileManager _tmgr;
|
|
}
|