?? sprite.java
字號:
this.y = oldY - getTransformedPtY(dRefX, dRefY, this.t_currentTransformation); // Calculate transformed sprites collision rectangle // and transformed width and height computeTransformedBounds(this.t_currentTransformation); } else { // just reinitialize the animation frames. initializeFrames(img, frameWidth, frameHeight, maintainCurFrame); } } /** * Defines the Sprite's bounding rectangle that is used for collision * detection purposes. This rectangle is specified relative to the * un-transformed Sprite's upper-left corner and defines the area that is * checked for collision detection. For pixel-level detection, only those * pixels within the collision rectangle are checked. * * By default, a Sprite's collision rectangle is located at 0,0 as has the * same dimensions as the Sprite. The collision rectangle may be * specified to be larger or smaller than the default rectangle; if made * larger, the pixels outside the bounds of the Sprite are considered to be * transparent for pixel-level collision detection. * * @param x the horizontal location of the collision rectangle relative to * the untransformed Sprite's left edge * @param y the vertical location of the collision rectangle relative to * the untransformed Sprite's top edge * @param width the width of the collision rectangle * @param height the height of the collision rectangle * @throws IllegalArgumentException if the specified * <code>width</code> or <code>height</code> is * less than <code>0</code> */ public void defineCollisionRectangle(int x, int y, int width, int height) { if (width < 0 || height < 0) { throw new IllegalArgumentException(); } collisionRectX = x; collisionRectY = y; collisionRectWidth = width; collisionRectHeight = height; // call set transform with current transformation to // update transformed sprites collision rectangle setTransformImpl(t_currentTransformation); } /** * Sets the transform for this Sprite. Transforms can be * applied to a Sprite to change its rendered appearance. Transforms * are applied to the original Sprite image; they are not cumulative, * nor can they be combined. By default, a Sprite's transform is * {@link #TRANS_NONE}. * <P> * Since some transforms involve rotations of 90 or 270 degrees, their * use may result in the overall width and height of the Sprite * being swapped. As a result, the values returned by * {@link Layer#getWidth} and {@link Layer#getHeight} may change. * <p> * The collision rectangle is also modified by the transform so that * it remains static relative to the pixel data of the Sprite. * Similarly, the defined reference pixel is unchanged by this method, * but its visual location within the Sprite may change as a result. * <P> * This method repositions the Sprite so that the location of * the reference pixel in the painter's coordinate system does not change * as a result of changing the transform. Thus, the reference pixel * effectively becomes the centerpoint for the transform. Consequently, * the values returned by {@link #getRefPixelX} and {@link #getRefPixelY} * will be the same both before and after the transform is applied, but * the values returned by {@link #getX getX()} and {@link #getY getY()} * may change. * <p> * @param transform the desired transform for this <code>Sprite</code> * @throws IllegalArgumentException if the requested * <code>transform</code> is invalid * @see #TRANS_NONE * @see #TRANS_ROT90 * @see #TRANS_ROT180 * @see #TRANS_ROT270 * @see #TRANS_MIRROR * @see #TRANS_MIRROR_ROT90 * @see #TRANS_MIRROR_ROT180 * @see #TRANS_MIRROR_ROT270 * */ public void setTransform(int transform) { setTransformImpl(transform); } /** * Checks for a collision between this Sprite and the specified Sprite. * <P> * If pixel-level detection is used, a collision is detected only if * opaque pixels collide. That is, an opaque pixel in the first * Sprite would have to collide with an opaque pixel in the second * Sprite for a collision to be detected. Only those pixels within * the Sprites' respective collision rectangles are checked. * <P> * If pixel-level detection is not used, this method simply * checks if the Sprites' collision rectangles intersect. * <P> * Any transforms applied to the Sprites are automatically accounted for. * <P> * Both Sprites must be visible in order for a collision to be * detected. * <P> * @param s the <code>Sprite</code> to test for collision with * @param pixelLevel <code>true</code> to test for collision on a * pixel-by-pixel basis, <code>false</code> to test using simple * bounds checking. * @return <code>true</code> if the two Sprites have collided, otherwise * <code>false</code> * @throws NullPointerException if Sprite <code>s</code> is * <code>null</code> */ public final boolean collidesWith(Sprite s, boolean pixelLevel) { // check if either of the Sprite's are not visible if (!(s.visible && this.visible)) { return false; } // these are package private // and can be accessed directly 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; // check if the collision rectangles of the two sprites intersect if (intersectRect(otherLeft, otherTop, otherRight, otherBottom, left, top, right, bottom)) { // collision rectangles intersect if (pixelLevel) { // we need to check pixel level collision detection. // use only the coordinates within the Sprite frame if // the collision rectangle is larger than the Sprite // frame 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; } // similarly for the other Sprite 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; } // recheck if the updated collision area rectangles intersect if (!intersectRect(otherLeft, otherTop, otherRight, otherBottom, left, top, right, bottom)) { // if they don't intersect, return false; return false; } // the updated collision rectangles intersect, // go ahead with collision detection // find intersecting region, // within the collision rectangles int intersectLeft = (left < otherLeft) ? otherLeft : left; int intersectTop = (top < otherTop) ? otherTop : top; // used once, optimize. int intersectRight = (right < otherRight) ? right : otherRight; int intersectBottom = (bottom < otherBottom) ? bottom : otherBottom; int intersectWidth = Math.abs(intersectRight - intersectLeft); int intersectHeight = Math.abs(intersectBottom - intersectTop); // have the coordinates in painter space, // need coordinates of top left and width, height // in source image of Sprite. int thisImageXOffset = getImageTopLeftX(intersectLeft, intersectTop, intersectRight, intersectBottom); int thisImageYOffset = getImageTopLeftY(intersectLeft, intersectTop, intersectRight, intersectBottom); int otherImageXOffset = s.getImageTopLeftX(intersectLeft, intersectTop, intersectRight, intersectBottom); int otherImageYOffset = s.getImageTopLeftY(intersectLeft, intersectTop, intersectRight, intersectBottom); // check if opaque pixels intersect. return doPixelCollision(thisImageXOffset, thisImageYOffset, otherImageXOffset, otherImageYOffset, this.sourceImage, this.t_currentTransformation, s.sourceImage, s.t_currentTransformation, intersectWidth, intersectHeight); } else { // collides! return true; } } return false; } /** * Checks for a collision between this Sprite and the specified * TiledLayer. If pixel-level detection is used, a collision is * detected only if opaque pixels collide. That is, an opaque pixel in * the Sprite would have to collide with an opaque pixel in TiledLayer * for a collision to be detected. Only those pixels within the Sprite's * collision rectangle are checked. * <P> * If pixel-level detection is not used, this method simply checks if the * Sprite's collision rectangle intersects with a non-empty cell in the * TiledLayer. * <P> * Any transform applied to the Sprite is automatically accounted for. * <P> * The Sprite and the TiledLayer must both be visible in order for * a collision to be detected. * <P> * @param t the <code>TiledLayer</code> to test for collision with * @param pixelLevel <code>true</code> to test for collision on a * pixel-by-pixel basis, <code>false</code> to test using simple bounds * checking against non-empty cells. * @return <code>true</code> if this <code>Sprite</code> has * collided with the <code>TiledLayer</code>, otherwise * <code>false</code> * @throws NullPointerException if <code>t</code> is <code>null</code> */ public final boolean collidesWith(TiledLayer t, boolean pixelLevel) { // check if either this Sprite or the TiledLayer is not visible if (!(t.visible && this.visible)) { return false; } // dimensions of tiledLayer, cell, and // this Sprite's collision rectangle // these are package private // and can be accessed directly int tLx1 = t.x; int tLy1 = t.y; int tLx2 = tLx1 + t.width; int tLy2 = tLy1 + t.height; int tW = t.getCellWidth(); int tH = t.getCellHeight(); int sx1 = this.x + this.t_collisionRectX; int sy1 = this.y + this.t_collisionRectY; int sx2 = sx1 + this.t_collisionRectWidth; int sy2 = sy1 + this.t_collisionRectHeight; // number of cells int tNumCols = t.getColumns(); int tNumRows = t.getRows(); // temporary loop variables. int startCol; // = 0; int endCol; // = 0; int startRow; // = 0; int endRow; // = 0; if (!intersectRect(tLx1, tLy1, tLx2, tLy2, sx1, sy1, sx2, sy2)) { // if the collision rectangle of the sprite // does not intersect with the dimensions of the entire // tiled layer return false; } // so there is an intersection // note sx1 < sx2, tLx1 < tLx2, sx2 > tLx1 from intersectRect() // use <= for comparison as this saves us some // computation - the result will be 0 startCol = (sx1 <= tLx1) ? 0 : (sx1 - tLx1)/tW; startRow = (sy1 <= tLy1) ? 0 : (sy1 - tLy1)/tH; // since tLx1 < sx2 < tLx2, the computation will yield // a result between 0 and tNumCols - 1 // subtract by 1 because sx2,sy2 represent // the enclosing bounds of the sprite, not the // locations in the coordinate system. endCol = (sx2 < tLx2) ? ((sx2 - 1 - tLx1)/tW) : tNumCols - 1; endRow = (sy2 < tLy2) ? ((sy2 - 1 - tLy1)/tH) : tNumRows - 1; if (!pixelLevel) { // check for intersection with a non-empty cell, for (int row = startRow; row <= endRow; row++) { for (int col = startCol; col <= endCol; col++) { if (t.getCell(col, row) != 0) { return true; } } } // worst case! we scanned through entire // overlapping region and // all the cells are empty! return false; } else { // do pixel level // we need to check pixel level collision detection. // use only the coordinates within the Sprite frame if // the collision rectangle is larger than the Sprite // frame if (this.t_collisionRectX < 0) { sx1 = this.x; } if (this.t_collisionRectY < 0) { sy1 = this.y; } if ((this.t_collisionRectX + this.t_collisionRectWidth) > this.width) { sx2 = this.x + this.width; } if ((this.t_collisionRectY + this.t_collisionRectHeight) > this.height) { sy2 = this.y + this.height; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -