--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/game/TiledLayer.java Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,289 @@
+/*
+* 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;
+ }
+}