From ba95e3e8343729938747610501006f97cbb2f80a Mon Sep 17 00:00:00 2001 From: AShiningRay Date: Tue, 17 Sep 2024 23:36:47 -0300 Subject: [PATCH] lcdui: color_game: Implement Tiled Layer and Sprite based on J2ME-Loader Implementation is heavily based on J2ME-Loader, just with some changes here and there to better fit FreeJ2ME's structure along with some patches by @zb3. Also, make those siemens color_game's classes simply mirror the current lcdui ones. If siemens requires any changes, we should add them, and only them, there. With this Jbenchmark 2's Tiled Layer test now works as intended, probably fixes games such as Arcadius as well. Co-authored-by: zb3 --- src/com/siemens/mp/color_game/Layer.java | 33 +- .../siemens/mp/color_game/LayerManager.java | 50 +- src/com/siemens/mp/color_game/Sprite.java | 229 +--- src/com/siemens/mp/color_game/TiledLayer.java | 10 +- src/javax/microedition/lcdui/game/Layer.java | 35 +- .../microedition/lcdui/game/LayerManager.java | 87 +- src/javax/microedition/lcdui/game/Sprite.java | 1047 ++++++++++++++--- .../microedition/lcdui/game/TiledLayer.java | 261 ++-- 8 files changed, 1190 insertions(+), 562 deletions(-) diff --git a/src/com/siemens/mp/color_game/Layer.java b/src/com/siemens/mp/color_game/Layer.java index 990611b2..23610522 100644 --- a/src/com/siemens/mp/color_game/Layer.java +++ b/src/com/siemens/mp/color_game/Layer.java @@ -19,34 +19,11 @@ import javax.microedition.lcdui.Image; -public abstract class Layer extends javax.microedition.lcdui.game.Layer -{ +public abstract class Layer extends javax.microedition.lcdui.game.Layer +{ + public Layer() { super(); } - public Layer() { x = 0; y = 0; } + public Layer(int width, int height) { super(width, height); } - public Layer(int w, int h) { x = 0; y = 0; width = w; height = h; } - - public Layer(Image i) { setLayerImage(i); } - - protected void setWidth(int w) { width = w; } - - protected void setHeight(int h) { height = h; } - - protected void setLayerImage(Image i) - { - image = i; - x = 0; - y = 0; - width = i.getWidth(); - height = i.getHeight(); - } - - protected void copyAllLayerVariables(Layer target) - { - target.setPosition(x, y); - target.setWidth(width); - target.setHeight(height); - target.setLayerImage(image); - target.setVisible(visible); - } + public Layer(Image i) { super(i); } } \ No newline at end of file diff --git a/src/com/siemens/mp/color_game/LayerManager.java b/src/com/siemens/mp/color_game/LayerManager.java index 6827384a..d7126634 100644 --- a/src/com/siemens/mp/color_game/LayerManager.java +++ b/src/com/siemens/mp/color_game/LayerManager.java @@ -26,51 +26,7 @@ import org.recompile.mobile.Mobile; import org.recompile.mobile.PlatformGraphics; -public class LayerManager extends javax.microedition.lcdui.game.LayerManager -{ - private Vector layers; - - public LayerManager() - { - layers = new Vector(); - - width = Mobile.getPlatform().lcdWidth; - height = Mobile.getPlatform().lcdHeight; - - canvas = Image.createImage(width, height); - gc = canvas.platformImage.getGraphics(); - } - - public void paint(Graphics g, int xdest, int ydest) - { - for(int i=0; i sequence = new Vector(); - - private int frame=0; - private int frameWidth; - private int frameHeight; - private int frameCount=1; - private int imgWidth; - private int imgHeight; - - public int rowCount=1; - public int colCount=1; - - public Sprite() - { - System.out.println("Sprite A"); - } - - public Sprite(Image img) - { - //System.out.println("Sprite B"); // used in wizardry.jar - setImage(img, img.getWidth(), img.getHeight()); - imgWidth = img.getWidth(); - imgHeight = img.getHeight(); - frameWidth = imgWidth; - frameHeight = imgHeight; - colCount = 1; - rowCount = 1; - frameCount = 1; - } - - public Sprite(Image img, int frameW, int frameH) - { - //System.out.println("Sprite C"); // used in wizardry.jar - //System.out.println("Sprite C: "+frameW+", "+frameH+" of "+img.getWidth()+", "+img.getHeight()); - setImage(img, frameW, frameH); - imgWidth = img.getWidth(); - imgHeight = img.getHeight(); - frameWidth = frameW; - frameHeight = frameH; - colCount = (int)(imgWidth/frameWidth); - rowCount = (int)(imgHeight/frameHeight); - frameCount = rowCount * colCount; - } - - public Sprite(Sprite s) - { - System.out.println("Sprite D"); - image = s.image; - } - - public boolean collidesWith(Image img, int x, int y, boolean pixelLevel) - { - return false; - } - - public boolean collidesWith(Sprite s, boolean pixelLevel) - { - int Ax = (x+refX) + hitX; - int Ay = (y+refY) + hitY; - int Aw = hitWidth; - int Ah = hitHeight; - - int Bx = (s.getX()+s.getRefPixelX()) + s.getHitX(); - int By = (s.getY()+s.getRefPixelY()) + s.getHitY(); - int Bw = s.getHitWidth(); - int Bh = s.getHitHeight(); - - if( (Ax+Aw)>Bx && Ax<(Bx+Bw) && (Ay+Ah)>By && Ay<(By+Bh) ) - { - return true; - } - - return false; - } - - public boolean collidesWith(TiledLayer t, boolean pixelLevel) - { - return false; - } - - public void defineCollisionRectangle(int x, int y, int width, int height) - { - hitX = x; - hitY = y; - hitWidth = width; - hitHeight = height; - } - - public void defineReferencePixel(int x, int y) - { - refX = x; - refY = y; - } - - public int getFrame() { return frame; } - - public int getFrameSequenceLength() { return sequence.size(); } - - public int getRawFrameCount() { return frameCount; } - - public int getRefPixelX() { return refX; } - - public int getRefPixelY() { return refY; } - - public void nextFrame() - { - if(frame0) - { - frame--; - } - else - { - frame=sequence.size()-1; - } - } - - public void setFrame(int sequenceIndex) { frame = sequenceIndex; } - - public void setFrameSequence(int[] fsequence) - { - //System.out.println("Set Frame Sequence"); - try - { - frame = 0; - sequence.clear(); - for(int i=0; i layers; + private int layers; - protected Image canvas; - protected PlatformGraphics gc; - protected Shape clip; + private Layer component[] = new Layer[4]; protected int x; protected int y; @@ -42,46 +40,89 @@ public class LayerManager protected int height; - public LayerManager() - { - layers = new ArrayList(); + public LayerManager() { setViewWindow(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE); } + + // This is just an insert() call, but with the last layer pos as the index. + public void append(Layer l) { insert(l, layers); } - width = Mobile.getPlatform().lcdWidth; - height = Mobile.getPlatform().lcdHeight; + public Layer getLayerAt(int index) + { + if ((index < 0) || (index >= layers)) { throw new IndexOutOfBoundsException(); } - canvas = Image.createImage(width, height); - gc = canvas.platformImage.getGraphics(); + return component[index]; } - public void append(Layer l) { layers.add(l); } + public int getSize() { return layers; } - public Layer getLayerAt(int index) { return layers.get(index); } + public void insert(Layer l, int index) + { + if ((index < 0) || (index > layers) || (exist(l) && (index >= layers))) { throw new IndexOutOfBoundsException(); } + + remove(l); - public int getSize() { return layers.size(); } + if (layers == component.length) + { + Layer newcomponents[] = new Layer[layers + 4]; + System.arraycopy(component, 0, newcomponents, 0, layers); + System.arraycopy(component, index, newcomponents, index + 1, layers - index); + component = newcomponents; + } + else { System.arraycopy(component, index, component, index + 1, layers - index); } - public void insert(Layer l, int index) { layers.add(index, l); } + component[index] = l; + layers++; + } public void paint(Graphics g, int xdest, int ydest) { - for(int i=0; i= 0; i--) + { + Layer comp = component[i]; + if (component[i].visible) { component[i].paint(g); } + } + + g.translate(-xdest + x, -ydest + y); + g.setClip(cx, cy, cw, ch); + } + + public void remove(Layer l) + { + if (l == null) { throw new NullPointerException(); } + + for (int i = layers-1; i >= 0; i--) { - drawLayer(g, xdest, ydest, layers.get(i)); + if (component[i] == l) + { + System.arraycopy(component, i + 1, component, i, layers - i - 1); + component[--layers] = null; + } } } - private void drawLayer(Graphics g, int dx, int dy, Layer l) + private boolean exist(Layer l) { - if(l.isVisible()) + if (l == null) { return false; } + + for (int i = layers; --i >= 0; ) { - l.render(); - g.drawRegion(l.getLayerImage(), 0, 0, l.getLayerImage().getWidth(), l.getLayerImage().getHeight(), 0, dx+x+l.getX(), dy+y+l.getY(), Graphics.TOP|Graphics.LEFT); + if (component[i] == l) { return true; } } + return false; } - public void remove(Layer l) { layers.remove(l); } - public void setViewWindow(int wx, int wy, int wwidth, int wheight) { + if (width < 0 || height < 0) { throw new IllegalArgumentException(); } + x = wx; y = wy; width = wwidth; diff --git a/src/javax/microedition/lcdui/game/Sprite.java b/src/javax/microedition/lcdui/game/Sprite.java index bb03ebc8..371cdc03 100644 --- a/src/javax/microedition/lcdui/game/Sprite.java +++ b/src/javax/microedition/lcdui/game/Sprite.java @@ -16,250 +16,1003 @@ */ package javax.microedition.lcdui.game; -import java.util.ArrayList; - import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; - -public class Sprite extends Layer +public class Sprite extends Layer { - public static final int TRANS_MIRROR = 2; - public static final int TRANS_MIRROR_ROT180 = 1; - public static final int TRANS_MIRROR_ROT270 = 4; - public static final int TRANS_MIRROR_ROT90 = 7; - public static final int TRANS_NONE = 0; - public static final int TRANS_ROT180 = 3; - public static final int TRANS_ROT270 = 6; - public static final int TRANS_ROT90 = 5; + public static final int TRANS_NONE = 0; + public static final int TRANS_ROT90 = 5; + public static final int TRANS_ROT180 = 3; + public static final int TRANS_ROT270 = 6; + public static final int TRANS_MIRROR = 2; + public static final int TRANS_MIRROR_ROT90 = 7; + public static final int TRANS_MIRROR_ROT180 = 1; + public static final int TRANS_MIRROR_ROT270 = 4; + + private static final int INVERTED_AXES = 0x4; + + private static final int X_FLIP = 0x2; + + private static final int Y_FLIP = 0x1; + + private static final int ALPHA_BITMASK = 0xff000000; + + private static final int FULLY_OPAQUE_ALPHA = 0xff000000; + + Image sourceImage; + + int numberFrames; + + int[] frameCoordsX; + + int[] frameCoordsY; + + int srcFrameWidth; + + int srcFrameHeight; + + int[] sequence; + + private int sequenceIndex; + + private boolean customSequenceDefined; + + int dRefX; + + int dRefY; + int collisionRectX; - private int refX = 0; - private int refY = 0; + int collisionRectY; - private int hitX; - private int hitY; - private int hitWidth; - private int hitHeight; + int collisionRectWidth; - private int transform; + int collisionRectHeight; - private ArrayList sequence = new ArrayList(); + int t_currentTransformation; - public Image sprite; + int t_collisionRectX; - private int frame=0; - private int frameWidth; - private int frameHeight; - private int frameCount=1; - private int imgWidth; - private int imgHeight; + int t_collisionRectY; - public int rowCount=1; - public int colCount=1; + int t_collisionRectWidth; - public Sprite() + int t_collisionRectHeight; + + + public Sprite(Image image) { - System.out.println("Sprite A"); + super(image.getWidth(), image.getHeight()); + + initializeFrames(image, image.getWidth(), image.getHeight(), false); + + initCollisionRectBounds(); + + setTransform(TRANS_NONE); } - public Sprite(Image img) + public Sprite(Image image, int frameWidth, int frameHeight) { - //System.out.println("Sprite B"); // Found in use, Pacman Championship Edition - imgWidth = img.getWidth(); - imgHeight = img.getHeight(); - frameWidth = imgWidth; - frameHeight = imgHeight; - colCount = 1; - rowCount = 1; - frameCount = 1; - setImage(img, imgWidth, imgHeight); + + super(frameWidth, frameHeight); + + if ((frameWidth < 1 || frameHeight < 1) || ((image.getWidth() % frameWidth) != 0) || ((image.getHeight() % frameHeight) != 0)) + { throw new IllegalArgumentException(); } + + initializeFrames(image, frameWidth, frameHeight, false); + + initCollisionRectBounds(); + + setTransform(TRANS_NONE); } - public Sprite(Image img, int frameW, int frameH) + public Sprite(Sprite s) { - //System.out.println("Sprite C"); // Found in use, Pacman Championship Edition - imgWidth = img.getWidth(); - imgHeight = img.getHeight(); - frameWidth = frameW; - frameHeight = frameH; - colCount = (int)(imgWidth/frameWidth); - rowCount = (int)(imgHeight/frameHeight); - frameCount = rowCount * colCount; - setImage(img, frameWidth, frameHeight); + + super(s != null ? s.getWidth() : 0, s != null ? s.getHeight() : 0); + + if (s == null) { throw new NullPointerException(); } + + this.sourceImage = Image.createImage(s.sourceImage); + + this.numberFrames = s.numberFrames; + + this.frameCoordsX = new int[this.numberFrames]; + this.frameCoordsY = new int[this.numberFrames]; + + System.arraycopy(s.frameCoordsX, 0, this.frameCoordsX, 0, s.getRawFrameCount()); + + System.arraycopy(s.frameCoordsY, 0, this.frameCoordsY, 0, s.getRawFrameCount()); + + this.x = s.getX(); + this.y = s.getY(); + + this.dRefX = s.dRefX; + this.dRefY = s.dRefY; + + this.collisionRectX = s.collisionRectX; + this.collisionRectY = s.collisionRectY; + this.collisionRectWidth = s.collisionRectWidth; + this.collisionRectHeight = s.collisionRectHeight; + + this.srcFrameWidth = s.srcFrameWidth; + this.srcFrameHeight = s.srcFrameHeight; + + setTransform(s.t_currentTransformation); + + this.setVisible(s.isVisible()); + + this.sequence = new int[s.getFrameSequenceLength()]; + this.setFrameSequence(s.sequence); + this.setFrame(s.getFrame()); + + x = s.getRefPixelX() - getTransformedPtX(dRefX, dRefY, t_currentTransformation); + y = s.getRefPixelY() - getTransformedPtY(dRefX, dRefY, t_currentTransformation); } - public Sprite(Sprite s) + public int getRefPixelX() { return (this.x + getTransformedPtX(dRefX, dRefY, this.t_currentTransformation)); } + + public int getRefPixelY() { return (this.y + getTransformedPtY(dRefX, dRefY, this.t_currentTransformation)); } + + public void setFrame(int sequenceIndex) { - System.out.println("Sprite D"); - imgWidth = s.sprite.getWidth(); - imgHeight = s.sprite.getHeight(); - frameWidth = imgWidth; - frameHeight = imgHeight; - colCount = 1; - rowCount = 1; - frameCount = 1; - setImage(s.sprite, imgWidth, imgHeight); + if (sequenceIndex < 0 || sequenceIndex >= sequence.length) { throw new IndexOutOfBoundsException(); } + this.sequenceIndex = sequenceIndex; } - public boolean collidesWith(Image image, int x, int y, boolean pixelLevel) + public final int getFrame() { return sequenceIndex; } + + public int getRawFrameCount() { return numberFrames; } + + public int getFrameSequenceLength() { return sequence.length; } + + public void nextFrame() { sequenceIndex = (sequenceIndex + 1) % sequence.length; } + + public void prevFrame() { - return false; + if (sequenceIndex == 0) { sequenceIndex = sequence.length - 1; } + else { sequenceIndex--; } } - public boolean collidesWith(Sprite s, boolean pixelLevel) + @Override + public final void paint(Graphics g) { - int Ax = (x-refX) + hitX; - int Ay = (y-refY) + hitY; - int Aw = hitWidth; - int Ah = hitHeight; - int Bx = (s.getX()-s.getRefPixelX()) + s.getHitX(); - int By = (s.getY()-s.getRefPixelY()) + s.getHitY(); - int Bw = s.getHitWidth(); - int Bh = s.getHitHeight(); + if (g == null) { throw new NullPointerException(); } - if( (Ax+Aw)>Bx && Ax<(Bx+Bw) && (Ay+Ah)>By && Ay<(By+Bh) ) + if (visible) { - return true; + g.drawRegion(sourceImage, + frameCoordsX[sequence[sequenceIndex]], + frameCoordsY[sequence[sequenceIndex]], + srcFrameWidth, + srcFrameHeight, + t_currentTransformation, + this.x, + this.y, + Graphics.TOP | Graphics.LEFT); } - return false; } - public boolean collidesWith(TiledLayer t, boolean pixelLevel) + public void setFrameSequence(int sequence[]) { - return false; + + if (sequence == null) + { + sequenceIndex = 0; + customSequenceDefined = false; + this.sequence = new int[numberFrames]; + for (int i = 0; i < numberFrames; i++) { this.sequence[i] = i; } + return; + } + + if (sequence.length < 1) { throw new IllegalArgumentException(); } + + for (int aSequence : sequence) { if (aSequence < 0 || aSequence >= numberFrames) { throw new ArrayIndexOutOfBoundsException(); } } + customSequenceDefined = true; + this.sequence = new int[sequence.length]; + System.arraycopy(sequence, 0, this.sequence, 0, sequence.length); + sequenceIndex = 0; + } + + public void setImage(Image img, int frameWidth, int frameHeight) + { + + // if image is null image.getWidth() will throw NullPointerException + if ((frameWidth < 1 || frameHeight < 1) || ((img.getWidth() % frameWidth) != 0) || ((img.getHeight() % frameHeight) != 0)) + { throw new IllegalArgumentException();} + + final int noOfFrames = (img.getWidth() / frameWidth) * (img.getHeight() / frameHeight); + + boolean maintainCurFrame = true; + + if (noOfFrames < numberFrames) + { + maintainCurFrame = false; + customSequenceDefined = false; + } + + if (!((srcFrameWidth == frameWidth) && (srcFrameHeight == frameHeight))) + { + + int oldX = this.x + getTransformedPtX(dRefX, dRefY, this.t_currentTransformation); + int oldY = this.y + getTransformedPtY(dRefX, dRefY, this.t_currentTransformation); + + setWidth(frameWidth); + setHeight(frameHeight); + + initializeFrames(img, frameWidth, frameHeight, maintainCurFrame); + + initCollisionRectBounds(); + + this.x = oldX - getTransformedPtX(dRefX, dRefY, this.t_currentTransformation); + + this.y = oldY - getTransformedPtY(dRefX, dRefY, this.t_currentTransformation); + + computeTransformedBounds(this.t_currentTransformation); + + } + else { initializeFrames(img, frameWidth, frameHeight, maintainCurFrame); } + } public void defineCollisionRectangle(int x, int y, int width, int height) { - hitX = x; - hitY = y; - hitWidth = width; - hitHeight = height; + + if (width < 0 || height < 0) { throw new IllegalArgumentException(); } + + collisionRectX = x; + collisionRectY = y; + collisionRectWidth = width; + collisionRectHeight = height; + + setTransform(t_currentTransformation); } - public void defineReferencePixel(int x, int y) + public void setTransform(int transform) { - refX = x; - refY = y; + + this.x = this.x + getTransformedPtX(dRefX, dRefY, this.t_currentTransformation) - getTransformedPtX(dRefX, dRefY, transform); + + this.y = this.y + getTransformedPtY(dRefX, dRefY, this.t_currentTransformation) - getTransformedPtY(dRefX, dRefY, transform); + + computeTransformedBounds(transform); + + t_currentTransformation = transform; } - public int getFrame() { return frame; } + public final boolean collidesWith(Sprite s, boolean pixelLevel) + { + + if (!(s.visible && this.visible)) { return false; } + + int otherLeft = s.x + s.t_collisionRectX; + int otherTop = s.y + s.t_collisionRectY; + int otherRight = otherLeft + s.t_collisionRectWidth; + int otherBottom = otherTop + s.t_collisionRectHeight; + + int left = this.x + this.t_collisionRectX; + int top = this.y + this.t_collisionRectY; + int right = left + this.t_collisionRectWidth; + int bottom = top + this.t_collisionRectHeight; + + if (intersectRect(otherLeft, otherTop, otherRight, otherBottom, left, top, right, bottom)) + { + + if (pixelLevel) + { + + if (this.t_collisionRectX < 0) { left = this.x; } + if (this.t_collisionRectY < 0) { top = this.y; } + if ((this.t_collisionRectX + this.t_collisionRectWidth) > this.width) { right = this.x + this.width; } + if ((this.t_collisionRectY + this.t_collisionRectHeight) > this.height) { bottom = this.y + this.height; } + + if (s.t_collisionRectX < 0) { otherLeft = s.x; } + if (s.t_collisionRectY < 0) { otherTop = s.y; } + if ((s.t_collisionRectX + s.t_collisionRectWidth) > s.width) { otherRight = s.x + s.width; } + if ((s.t_collisionRectY + s.t_collisionRectHeight) > s.height) { otherBottom = s.y + s.height; } - public int getFrameSequenceLength() { return sequence.size(); } + if (!intersectRect(otherLeft, otherTop, otherRight, otherBottom, left, top, right, bottom)) { return false; } - public int getRawFrameCount() { return frameCount; } + final int intersectLeft = (left < otherLeft) ? otherLeft : left; + final int intersectTop = (top < otherTop) ? otherTop : top; - public int getRefPixelX() { return refX; } + final int intersectRight = (right < otherRight) ? right : otherRight; + final int intersectBottom = (bottom < otherBottom) ? bottom : otherBottom; - public int getRefPixelY() { return refY; } + final int intersectWidth = Math.abs(intersectRight - intersectLeft); + final int intersectHeight = Math.abs(intersectBottom - intersectTop); + + final int thisImageXOffset = getImageTopLeftX(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + final int thisImageYOffset = getImageTopLeftY(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + final int otherImageXOffset = s.getImageTopLeftX(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + final int otherImageYOffset = s.getImageTopLeftY(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + return doPixelCollision(thisImageXOffset, thisImageYOffset, + otherImageXOffset, otherImageYOffset, + this.sourceImage, + this.t_currentTransformation, + s.sourceImage, + s.t_currentTransformation, + intersectWidth, intersectHeight); + + } + else { return true; } + } + return false; - public void nextFrame() + } + + public final boolean collidesWith(TiledLayer t, boolean pixelLevel) { - if(frame this.width) { sx2 = this.x + this.width; } + if ((this.t_collisionRectY + this.t_collisionRectHeight) > this.height) { sy2 = this.y + this.height; } + + if (!intersectRect(tLx1, tLy1, tLx2, tLy2, sx1, sy1, sx2, sy2)) { return (false); } + + startCol = (sx1 <= tLx1) ? 0 : (sx1 - tLx1) / tW; + startRow = (sy1 <= tLy1) ? 0 : (sy1 - tLy1) / tH; + + endCol = (sx2 < tLx2) ? ((sx2 - 1 - tLx1) / tW) : tNumCols - 1; + endRow = (sy2 < tLy2) ? ((sy2 - 1 - tLy1) / tH) : tNumRows - 1; + + int cellTop = startRow * tH + tLy1; + int cellBottom = cellTop + tH; + + int tileIndex;; + + for (int row = startRow; row <= endRow; row++, cellTop += tH, cellBottom += tH) + { + int cellLeft = startCol * tW + tLx1; + int cellRight = cellLeft + tW; + + for (int col = startCol; col <= endCol; col++, cellLeft += tW, cellRight += tW) + { + tileIndex = t.getCell(col, row); + + if (tileIndex != 0) + { + int intersectLeft = (sx1 < cellLeft) ? cellLeft : sx1; + int intersectTop = (sy1 < cellTop) ? cellTop : sy1; + + int intersectRight = (sx2 < cellRight) ? sx2 : cellRight; + int intersectBottom = (sy2 < cellBottom) ? sy2 : cellBottom; + + if (intersectLeft > intersectRight) + { + int temp = intersectRight; + intersectRight = intersectLeft; + intersectLeft = temp; + } + + if (intersectTop > intersectBottom) + { + int temp = intersectBottom; + intersectBottom = intersectTop; + intersectTop = temp; + } + + int intersectWidth = intersectRight - intersectLeft; + int intersectHeight = intersectBottom - intersectTop; + + int image1XOffset = getImageTopLeftX(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + int image1YOffset = getImageTopLeftY(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + int image2XOffset = t.tileSetX[tileIndex] + + (intersectLeft - cellLeft); + int image2YOffset = t.tileSetY[tileIndex] + + (intersectTop - cellTop); + + if (doPixelCollision(image1XOffset, + image1YOffset, + image2XOffset, + image2YOffset, + this.sourceImage, + this.t_currentTransformation, + t.image, + TRANS_NONE, + intersectWidth, intersectHeight)) + { return true; } + } + } + } + + return false; } + } - public void paint(Graphics g) + public final boolean collidesWith(Image image, int x, + int y, boolean pixelLevel) { - try + + if (!(visible)) { return false; } + + int otherLeft = x; + int otherTop = y; + int otherRight = x + image.getWidth(); + int otherBottom = y + image.getHeight(); + + int left = x + t_collisionRectX; + int top = y + t_collisionRectY; + int right = left + t_collisionRectWidth; + int bottom = top + t_collisionRectHeight; + + // first check if the collision rectangles of the two sprites intersect + if (intersectRect(otherLeft, otherTop, otherRight, otherBottom, left, top, right, bottom)) { - int f = sequence.get(frame); - int r = frameHeight * (int)(f / colCount); - int c = frameWidth * (int)(f % colCount); - g.drawRegion(sprite, c, r, frameWidth, frameHeight, transform, x-refX, y-refY, 0); + if (pixelLevel) + { + if (this.t_collisionRectX < 0) { left = this.x; } + if (this.t_collisionRectY < 0) { top = this.y; } + if ((this.t_collisionRectX + this.t_collisionRectWidth) > this.width) { right = this.x + this.width; } + if ((this.t_collisionRectY + this.t_collisionRectHeight) > this.height) { bottom = this.y + this.height; } + + if (!intersectRect(otherLeft, otherTop, otherRight, otherBottom, left, top, right, bottom)) + { return false; } + + final int intersectLeft = (left < otherLeft) ? otherLeft : left; + final int intersectTop = (top < otherTop) ? otherTop : top; + + final int intersectRight = (right < otherRight) + ? right : otherRight; + final int intersectBottom = (bottom < otherBottom) + ? bottom : otherBottom; + + final int intersectWidth = Math.abs(intersectRight - intersectLeft); + final int intersectHeight = Math.abs(intersectBottom - intersectTop); + + final int thisImageXOffset = getImageTopLeftX(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + final int thisImageYOffset = getImageTopLeftY(intersectLeft, + intersectTop, + intersectRight, + intersectBottom); + + final int otherImageXOffset = intersectLeft - x; + final int otherImageYOffset = intersectTop - y; + + return doPixelCollision(thisImageXOffset, thisImageYOffset, + otherImageXOffset, otherImageYOffset, + this.sourceImage, + this.t_currentTransformation, + image, + Sprite.TRANS_NONE, + intersectWidth, intersectHeight); + + } + else { return true; } } - catch (Exception e) + return false; + + } + + private void initializeFrames(Image image, int fWidth, int fHeight, boolean maintainCurFrame) + { + + final int imageW = image.getWidth(); + final int imageH = image.getHeight(); + + final int numHorizontalFrames = imageW / fWidth; + final int numVerticalFrames = imageH / fHeight; + + sourceImage = image; + + srcFrameWidth = fWidth; + srcFrameHeight = fHeight; + + numberFrames = numHorizontalFrames * numVerticalFrames; + + frameCoordsX = new int[numberFrames]; + frameCoordsY = new int[numberFrames]; + + if (!maintainCurFrame) { sequenceIndex = 0; } + + if (!customSequenceDefined) { sequence = new int[numberFrames]; } + + int currentFrame = 0; + + for (int yy = 0; yy < imageH; yy += fHeight) { - System.out.println("Problem drawing sprite"); + for (int xx = 0; xx < imageW; xx += fWidth) + { + + frameCoordsX[currentFrame] = xx; + frameCoordsY[currentFrame] = yy; + + if (!customSequenceDefined) + { + sequence[currentFrame] = currentFrame; + } + currentFrame++; + } } } - public void prevFrame() + private void initCollisionRectBounds() + { + + collisionRectX = 0; + collisionRectY = 0; + + collisionRectWidth = this.width; + collisionRectHeight = this.height; + + } + + private boolean intersectRect(int r1x1, int r1y1, int r1x2, int r1y2, int r2x1, int r2y1, int r2x2, int r2y2) { - if(frame>0) + if (r2x1 >= r1x2 || r2y1 >= r1y2 || r2x2 <= r1x1 || r2y2 <= r1y1) { return false; } + else { return true; } + } + + private static boolean doPixelCollision(int image1XOffset, + int image1YOffset, + int image2XOffset, + int image2YOffset, + Image image1, int transform1, + Image image2, int transform2, + int width, int height) + { + + int startY1; + int xIncr1, yIncr1; + + int startY2; + int xIncr2, yIncr2; + + int numPixels = height * width; + + final int[] argbData1 = new int[numPixels]; + final int[] argbData2 = new int[numPixels]; + + if (0x0 != (transform1 & INVERTED_AXES)) { - frame--; + + if (0x0 != (transform1 & Y_FLIP)) + { + xIncr1 = -(height); + startY1 = numPixels - height; + } + else + { + xIncr1 = height; + startY1 = 0; + } + + if (0x0 != (transform1 & X_FLIP)) + { + yIncr1 = -1; + startY1 += (height - 1); + } + else { yIncr1 = +1; } + + image1.getRGB(argbData1, 0, height, image1XOffset, image1YOffset, height, width); + } else { - frame=sequence.size()-1; + if (0x0 != (transform1 & Y_FLIP)) + { + startY1 = numPixels - width; + yIncr1 = -(width); + } + else + { + startY1 = 0; + yIncr1 = width; + } + + if (0x0 != (transform1 & X_FLIP)) + { + xIncr1 = -1; + startY1 += (width - 1); + } + else { xIncr1 = +1; } + + image1.getRGB(argbData1, 0, width, image1XOffset, image1YOffset, width, height); } - } - public void setFrame(int sequenceIndex) - { - if(sequenceIndex<0 || sequenceIndex >= sequence.size()) + if (0x0 != (transform2 & INVERTED_AXES)) { - throw new IndexOutOfBoundsException(); + if (0x0 != (transform2 & Y_FLIP)) + { + xIncr2 = -(height); + startY2 = numPixels - height; + } + else + { + xIncr2 = height; + startY2 = 0; + } + + if (0x0 != (transform2 & X_FLIP)) + { + yIncr2 = -1; + startY2 += height - 1; + } + else { yIncr2 = +1; } + + image2.getRGB(argbData2, 0, height,image2XOffset, image2YOffset, height, width); + } - frame = sequenceIndex; - } + else + { - public void setFrameSequence(int[] fsequence) - { - //System.out.println("Set Frame Sequence"); - try + if (0x0 != (transform2 & Y_FLIP)) + { + startY2 = numPixels - width; + yIncr2 = -(width); + } + else + { + startY2 = 0; + yIncr2 = +width; + } + + if (0x0 != (transform2 & X_FLIP)) + { + xIncr2 = -1; + startY2 += (width - 1); + } + else { xIncr2 = +1; } + + image2.getRGB(argbData2, 0, width, image2XOffset, image2YOffset, width, height); + } + + int x1, x2; + int xLocalBegin1, xLocalBegin2; + + int numIterRows; + int numIterColumns; + + for (numIterRows = 0, xLocalBegin1 = startY1, xLocalBegin2 = startY2; numIterRows < height; + xLocalBegin1 += yIncr1, xLocalBegin2 += yIncr2, numIterRows++) { - frame = 0; - sequence.clear(); - for(int i=0; i= numberOfTiles) { throw new IndexOutOfBoundsException(); } - public void fillCells(int col, int row, int numCols, int numRows, int tileIndex) - { - for (int c=0; c= numberOfTiles) { throw new IndexOutOfBoundsException(); } + + animatedTileIndex = -animatedTileIndex; + if (animatedTiles == null || animatedTileIndex <= 0 || animatedTileIndex >= animatedTileCount) { throw new IndexOutOfBoundsException(); } + + animatedTiles[animatedTileIndex] = staticTileIndex; } - public int getCell(int col, int row) { return tiles[col][row]; } + public int getAnimatedTile(int animatedTileIndex) + { + animatedTileIndex = -animatedTileIndex; + if (animatedTiles == null || animatedTileIndex <= 0 || animatedTileIndex >= animatedTileCount) { throw new IndexOutOfBoundsException(); } - public int getCellHeight() { return tileHeight; } + return animatedTiles[animatedTileIndex]; + } - public int getCellWidth() { return tileWidth; } + public void setCell(int col, int row, int tileIndex) + { + if (col < 0 || col >= this.cols || row < 0 || row >= this.rows) { throw new IndexOutOfBoundsException(); } - public int getColumns() { return cols; } + if (tileIndex > 0) { if (tileIndex >= numberOfTiles) { throw new IndexOutOfBoundsException(); } } + else if (tileIndex < 0) { if (animatedTiles == null || (-tileIndex) >= animatedTileCount) { throw new IndexOutOfBoundsException(); } } - public int getRows() { return rows; } + tiles[row][col] = tileIndex; + } - public void paint(Graphics g) + public int getCell(int col, int row) { - g.drawImage(canvas, x, y, 0); + if (col < 0 || col >= this.cols || row < 0 || row >= this.rows) { throw new IndexOutOfBoundsException(); } + return tiles[row][col]; } - private void drawTiles() + public void fillCells(int col, int row, int numCols, int numRows, int tileIndex) { - int tile; - for (int c=0; c= this.cols || row < 0 || row >= this.rows || col + numCols > this.cols || row + numRows > this.rows) { throw new IndexOutOfBoundsException(); } + + if (tileIndex > 0) { if (tileIndex >= numberOfTiles) { throw new IndexOutOfBoundsException(); } } + else if (tileIndex < 0) { if (animatedTiles == null || (-tileIndex) >= animatedTileCount) { throw new IndexOutOfBoundsException(); } } + + for (int rowCount = row; rowCount < row + numRows; rowCount++) { - for (int r=0; r0) { drawTile(tile, c*tileWidth, r*tileHeight); } - } + for (int columnCount = col; columnCount < col + numCols; columnCount++) { tiles[rowCount][columnCount] = tileIndex; } } } - private void drawTile(int tile, int xdest, int ydest) + 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 void setStaticTileSet(Image baseimage, int tileWidth, int tileHeight) { - //tile--; - int r = tileHeight * (tile / tilesWidth); - int c = tileWidth * (tile % tilesWidth); - gc.drawRegion(image, c, r, tileWidth, tileHeight, 0, xdest, ydest, 0); + if (tileWidth < 1 || tileHeight < 1 || ((baseimage.getWidth() % tileWidth) != 0) || ((baseimage.getHeight() % tileHeight) != 0)) + { + throw new IllegalArgumentException(); + } + setWidth(cols * tileWidth); + setHeight(rows * tileHeight); + + int noOfFrames = (baseimage.getWidth() / tileWidth) * (baseimage.getHeight() / tileHeight); + + // the zero index is left empty for transparent tiles + // so it is passed in createStaticSet as noOfFrames + 1 + if (noOfFrames >= (numberOfTiles - 1)) { createStaticSet(baseimage, noOfFrames + 1, tileWidth, tileHeight, true); } + else { createStaticSet(baseimage, noOfFrames + 1, tileWidth, tileHeight, false); } } - public void setAnimatedTile(int animatedTileIndex, int staticTileIndex) + @Override + public final void paint(Graphics g) { - int tile; - animatedTiles[0-animatedTileIndex] = staticTileIndex; - for (int c=0; c 0) { startColumn = number; } + + // calculate the number of columns right of the clip + int endX = this.x + (this.cols * tileWidth); + int endClipX = g.getClipX() + g.getClipWidth(); + number = (endX - endClipX) / tileWidth; + if (number > 0) { endColumn -= number; } + + // calculate the number of rows above the clip + number = (g.getClipY() - this.y) / tileHeight; + if (number > 0) { startRow = number; } + + // calculate the number of rows below the clip + int endY = this.y + (this.rows * tileHeight); + int endClipY = g.getClipY() + g.getClipHeight(); + number = (endY - endClipY) / tileHeight; + if (number > 0) { endRow -= number; } + + // paint all visible cells + int tileIndex = 0; + + // y-coordinate + int ty = this.y + (startRow * tileHeight); + for (int row = startRow; row < endRow; row++, ty += tileHeight) { - tile = tiles[c][r]; - if(tile==animatedTileIndex) + + // reset the x-coordinate at the beginning of every row + // x-coordinate to draw tile into + int tx = this.x + (startColumn * tileWidth); + for (int column = startColumn; column < endColumn; column++, tx += tileWidth) { - drawTile(animatedTiles[0-animatedTileIndex], c*tileWidth, r*tileHeight); + + tileIndex = tiles[row][column]; + // check the indices + // if animated get the corresponding + // static index from animatedTiles table + + // tileIndex = 0 is a transparent tile + if (tileIndex == 0) { continue; } + else if (tileIndex < 0) { tileIndex = getAnimatedTile(tileIndex); } + + g.drawRegion(image, tileSetX[tileIndex], tileSetY[tileIndex], tileWidth, tileHeight, Sprite.TRANS_NONE, tx, ty, Graphics.TOP | Graphics.LEFT); } } } } - public void setCell(int col, int row, int tileIndex) + private void createStaticSet(Image baseimage, int noOfFrames, int tileWidth, int tileHeight, boolean maintainIndices) { - tiles[col][row] = tileIndex; - drawTile(tileIndex, col*tileWidth, row*tileHeight); - } + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; - public void setStaticTileSet(Image baseimage, int tilewidth, int tileheight) - { - image = baseimage; - tileWidth = tilewidth; - tileHeight = tileheight; - tilesWidth = (int)Math.floor(image.getWidth()/tilewidth); - tilesHeight = (int)Math.floor(image.getHeight()/tileheight); + final int imageW = baseimage.getWidth(); + final int imageH = baseimage.getHeight(); + + this.image = baseimage; + + numberOfTiles = noOfFrames; + tileSetX = new int[numberOfTiles]; + tileSetY = new int[numberOfTiles]; + + if (!maintainIndices) + { + // populate tile matrix, all the indices are 0 to begin with + for (rows = 0; rows < tiles.length; rows++) + { + int totalCols = tiles[rows].length; + for (cols = 0; cols < totalCols; cols++) { tiles[rows][cols] = 0; } + } + // delete animated tiles + animatedTiles = null; + } + + int currentTile = 1; + + for (int locY = 0; locY < imageH; locY += tileHeight) + { + for (int locX = 0; locX < imageW; locX += tileWidth) + { + + tileSetX[currentTile] = locX; + tileSetY[currentTile] = locY; + + currentTile++; + } + } } }