--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/game/TiledLayer.java Tue Aug 31 15:09:22 2010 +0300
@@ -0,0 +1,329 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+package javax.microedition.lcdui.game;
+
+import javax.microedition.lcdui.Graphics;
+import javax.microedition.lcdui.Image;
+
+public class TiledLayer extends Layer
+{
+
+ // Animated tile array increment
+ private static final int ANIM_ARRAY_INCREMENT = 4;
+
+ private int rows;
+ private int cols;
+
+ private int[][] cells;
+ private int[] animArray;
+ private int animCount;
+
+ public TiledLayer(int cols, int rows, Image tileImage, int tileWidth, int tileHeight)
+ {
+ super(tileImage, tileWidth, tileHeight);
+
+ if(cols < 1 || rows < 1)
+ {
+ throw new IllegalArgumentException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_DIMENSIONS);
+ }
+
+ this.cols = cols;
+ this.rows = rows;
+ cells = new int[rows][cols];
+ animArray = new int[ANIM_ARRAY_INCREMENT];
+ animCount = 0;
+ }
+
+ public void setStaticTileSet(Image tileImage, int tileWidth, int tileHeight)
+ {
+ final int oldTileCount = tileCount;
+
+ setTileImage(tileImage, tileWidth, tileHeight);
+
+ // If the new static tile set has as many or more tiles, then the
+ // animated tiles and cell contents will be preserved.
+ // If not, the contents of the grid will be cleared (all cells will
+ // contain index 0) and all animated tiles will be deleted.
+ //
+ if(tileCount < oldTileCount)
+ {
+ fillCells(0, 0, cols, rows, 0);
+ animCount = 0;
+ }
+ }
+
+ public void setCell(int col, int row, int aTileIndex)
+ {
+ validateTileIndex(aTileIndex);
+ cells[row][col] = aTileIndex;
+ }
+
+ public int getCell(int col, int row)
+ {
+ return cells[row][col];
+ }
+
+ public void fillCells(int col, int row, int numCols, int numRows, int tileIndex)
+ {
+ if(numCols < 0)
+ {
+ throw new IllegalArgumentException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_NUMBER_OF_COLUMNS);
+ }
+ if(numRows < 0)
+ {
+ throw new IllegalArgumentException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_NUMBER_OF_ROWS);
+ }
+ validateTileIndex(tileIndex);
+
+ for(int i = col + numCols; --i >= col;)
+ {
+ cells[row][i] = tileIndex;
+ }
+ for(int i = row + numRows; --i > row;)
+ {
+ System.arraycopy(cells[row], col, cells[i], col, numCols);
+ }
+ }
+
+ public int createAnimatedTile(int tileIndex)
+ {
+ if(tileIndex < 0 || tileIndex > tileCount)
+ {
+ throw new IndexOutOfBoundsException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_TILE_INDEX);
+ }
+
+ final int index = animCount;
+ checkCapacity(index + 1);
+ animArray[index] = tileIndex;
+ animCount++;
+ return ~index;
+ }
+
+ /**
+ * Grows the animated tile array if required.
+ */
+ private void checkCapacity(int requiredLength)
+ {
+ int length = animArray.length;
+ if(requiredLength > length)
+ {
+ int[] array = new int[length + ANIM_ARRAY_INCREMENT];
+ System.arraycopy(animArray, 0, array, 0, length);
+ animArray = array;
+ }
+ }
+
+ public void setAnimatedTile(int animIndex, int tileIndex)
+ {
+ final int index = ~animIndex;
+ if(index >= animCount)
+ {
+ throw new IndexOutOfBoundsException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_ANIMTILE_INDEX);
+ }
+ if(tileIndex < 0 || tileIndex > tileCount)
+ {
+ throw new IndexOutOfBoundsException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_TILE_INDEX);
+ }
+ animArray[index] = tileIndex;
+ }
+
+ public int getAnimatedTile(int animIndex)
+ {
+ final int index = ~animIndex;
+ if(index >= animCount)
+ {
+ throw new IndexOutOfBoundsException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_ANIMTILE_INDEX);
+ }
+ return animArray[index];
+ }
+
+ public final int getCellWidth()
+ {
+ return tileWidth;
+ }
+
+ public final int getCellHeight()
+ {
+ return tileHeight;
+ }
+
+ public final int getColumns()
+ {
+ return cols;
+ }
+
+ public final int getRows()
+ {
+ return rows;
+ }
+
+ public final void paint(Graphics aGraphics)
+ {
+ if(visible)
+ {
+ aGraphics.translate(x, y);
+
+ int clipX1 = aGraphics.getClipX();
+ int clipY1 = aGraphics.getClipY();
+ int clipX2 = clipX1 + aGraphics.getClipWidth();
+ int clipY2 = clipY1 + aGraphics.getClipHeight();
+
+ final int tw = tileWidth;
+ final int th = tileHeight;
+ final int lw = getWidth(); // layer width
+ final int lh = getHeight(); // layer height
+
+ clipX1 = (clipX1 < 0 ? 0 : clipX1);
+ clipY1 = (clipY1 < 0 ? 0 : clipY1);
+ clipX2 = (clipX2 > lw ? lw : clipX2);
+ clipY2 = (clipY2 > lh ? lh : clipY2);
+
+ final int begRow = clipY1 / tileHeight;
+ final int begCol = clipX1 / tileWidth;
+ final int endRow = (clipY2 - 1) / tileHeight;
+ final int endCol = (clipX2 - 1) / tileWidth;
+
+ int sx = begRow * th;
+ int sy = begCol * tw;
+ int dx;
+ int dy;
+
+ for(int row = begRow; row <= endRow; row++)
+ {
+ for(int col = begCol; col <= endCol; col++)
+ {
+ final int index = validateTileIndex(cells[row][col]);
+ if(index >= 0)
+ {
+ // Future performace improvement suggestion: accumulate
+ // region
+ //
+ // We have a visible tile in the clip rect, if its
+ // bounding rect is disjoint from our accumulated rect,
+ // we draw what we have accumulated so far and reset our
+ // accumulation rect, else we just add this tile to the
+ // accumulation rect.
+ //
+ // This helps with the not totally uncommon case of
+ // cells in the tiled layer containing adjacent tiles
+ // from the tile image. Accumulating the tiles turns
+ // multiple bitblt's into a single bitblt, saving a bit
+ // on setup/teardown/data transfer.
+
+ dx = col * tw;
+ dy = row * th;
+
+ int tr = index / tileColumns;
+ int tc = index % tileColumns;
+
+ sx = tc * tw;
+ sy = tr * th;
+
+ aGraphics.drawRegion(tileImage,
+ sx, sy,
+ tw, th,
+ Sprite.TRANS_NONE,
+ dx, dy, 0);
+ }
+ }
+ }
+
+ aGraphics.translate(-x, -y);
+ }
+ }
+
+ private int validateTileIndex(int tileIndex)
+ {
+ if(tileIndex > tileCount)
+ {
+ throw new IndexOutOfBoundsException(
+ MsgRepository.TILEDLAYER_EXCEPTION_INVALID_TILE_INDEX);
+ }
+ // check createAnimatedTile has been called, getAnimatedTile will throw
+ // exception if hasn't.
+ if(tileIndex < 0)
+ {
+ tileIndex = getAnimatedTile(tileIndex);
+ }
+ return tileIndex - 1;
+ }
+
+ boolean collidesCell(int aX1, int aY1, int aX2, int aY2)
+ {
+ // tiled layer rect in painter's coordinates
+ int tlX1 = x;
+ int tlY1 = y;
+ int tlX2 = x + getWidth();
+ int tlY2 = y + getHeight();
+
+ // compute intersection of TiledLayer bounds and sprite collision
+ // rectangle.
+ tlX1 = Math.max(tlX1, aX1);
+ tlY1 = Math.max(tlY1, aY1);
+ tlX2 = Math.min(tlX2, aX2);
+ tlY2 = Math.min(tlY2, aY2);
+
+ // return false if empty intersection.
+ if(!((tlX1 < tlX2) && (tlY1 < tlY2)))
+ {
+ return false;
+ }
+
+ // transform to tiled layer coordinates
+ tlX1 -= x;
+ tlY1 -= y;
+ tlX2 -= x;
+ tlY2 -= y;
+
+ int startRow = (tlY1 / tileHeight);
+ int startCol = (tlX1 / tileWidth);
+ int endRow = (tlY2 - 1) / tileHeight;
+ int endCol = (tlX2 - 1) / tileWidth;
+
+ for(int row = startRow; row <= endRow; row++)
+ {
+ for(int col = startCol; col <= endCol; col++)
+ {
+ if(cells[row][col] != 0)
+ {
+ // at least one cell is not empty
+ return true;
+ }
+ }
+ }
+
+ // all cells in overlap are empty
+ return false;
+ }
+
+ int getLayerWidth()
+ {
+ return cols * tileWidth;
+ }
+
+ int getLayerHeight()
+ {
+ return rows * tileHeight;
+ }
+}