📄 sprite.java
字号:
public final boolean collidesWith(Image image, int x, int y,
boolean pixelLevel) {
// check if this Sprite is not visible
if (!(this.visible)) {
return false;
}
// if image is null
// image.getWidth() will throw NullPointerException
int otherLeft = x;
int otherTop = y;
int otherRight = x + image.getWidth();
int otherBottom = y + image.getHeight();
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;
// first 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) {
// find intersecting region,
// 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;
}
// 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;
}
// 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 = intersectLeft - x;
int otherImageYOffset = intersectTop - y;
// check if opaque pixels intersect.
return doPixelCollision(thisImageXOffset, thisImageYOffset,
otherImageXOffset, otherImageYOffset, this.sourceImage,
this.t_currentTransformation, image, Sprite.TRANS_NONE,
intersectWidth, intersectHeight);
} else {
// collides!
return true;
}
}
return false;
}
// -----
// ----- private -----
/**
* create the Image Array.
*
* @param image
* Image to use for Sprite
* @param fWidth
* width, in pixels, of the individual raw frames
* @param fHeight
* height, in pixels, of the individual raw frames
* @param maintainCurFrame
* true if Current Frame is maintained
*/
private void initializeFrames(Image image, int fWidth, int fHeight,
boolean maintainCurFrame) {
int imageW = image.getWidth();
int imageH = image.getHeight();
int numHorizontalFrames = imageW / fWidth;
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) {
frameSequence = new int[numberFrames];
}
int currentFrame = 0;
for (int yy = 0; yy < imageH; yy += fHeight) {
for (int xx = 0; xx < imageW; xx += fWidth) {
frameCoordsX[currentFrame] = xx;
frameCoordsY[currentFrame] = yy;
if (!customSequenceDefined) {
frameSequence[currentFrame] = currentFrame;
}
++currentFrame;
}
}
}
private void initCollisionRectBounds() {
// reset x and y of collision rectangle
collisionRectX = 0;
collisionRectY = 0;
// intialize the collision rectangle bounds to that of the sprite
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 (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) {
// starting point of comparison
int startY1;
// x and y increments
int xIncr1, yIncr1;
// .. for image 2
int startY2;
int xIncr2, yIncr2;
int numPixels = height * width;
int[] argbData1 = new int[numPixels];
int[] argbData2 = new int[numPixels];
if (0x0 != (transform1 & INVERTED_AXES)) {
// inverted axes
// scanlength = height
if (0x0 != (transform1 & Y_FLIP)) {
xIncr1 = -(height); // - scanlength
startY1 = numPixels - height; // numPixels - scanlength
} else {
xIncr1 = height; // + scanlength
startY1 = 0;
}
if (0x0 != (transform1 & X_FLIP)) {
yIncr1 = -1;
startY1 += (height - 1);
} else {
yIncr1 = +1;
}
getRGBNokia(image1,argbData1,0,height,
image1XOffset, image1YOffset, height, width);
/*
image1.getRGB(argbData1, 0, height, // scanlength = height
image1XOffset, image1YOffset, height, width);
*/
} else {
// scanlength = width
if (0x0 != (transform1 & Y_FLIP)) {
startY1 = numPixels - width; // numPixels - scanlength
yIncr1 = -(width); // - scanlength
} else {
startY1 = 0;
yIncr1 = width; // + scanlength
}
if (0x0 != (transform1 & X_FLIP)) {
xIncr1 = -1;
startY1 += (width - 1);
} else {
xIncr1 = +1;
}
getRGBNokia(image1,argbData1,0,width,
image1XOffset, image1YOffset, width, height);
/*
image1.getRGB(argbData1, 0, width, // scanlength = width
image1XOffset, image1YOffset, width, height);
*/
}
if (0x0 != (transform2 & INVERTED_AXES)) {
// inverted axes
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;
}
getRGBNokia(image2,argbData2,0,height,
image2XOffset, image2YOffset, height, width);
/*
image2.getRGB(argbData2, 0, height, image2XOffset, image2YOffset,
height, width);*/
} else {
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;
}
getRGBNokia(image2,argbData1,0,width,
image2XOffset, image2YOffset, width, height);
/*
image2.getRGB(argbData2, 0, width, image2XOffset, image2YOffset,
width, height);*/
}
int x1, x2;
int xLocalBegin1, xLocalBegin2;
// the loop counters
int numIterRows;
int numIterColumns;
for (numIterRows = 0, xLocalBegin1 = startY1, xLocalBegin2 = startY2; numIterRows < height; xLocalBegin1 += yIncr1, xLocalBegin2 += yIncr2, ++numIterRows) {
for (numIterColumns = 0, x1 = xLocalBegin1, x2 = xLocalBegin2; numIterColumns < width; x1 += xIncr1, x2 += xIncr2, ++numIterColumns) {
if (((argbData1[x1] & ALPHA_BITMASK) != 0)
&& ((argbData2[x2] & ALPHA_BITMASK) != 0)) {
return true;
}
} // end for x
} // end for y
// worst case! couldn't find a single colliding pixel!
return false;
}
private int getImageTopLeftX(int x1, int y1, int x2, int y2) {
int retX = 0;
// left = this.x
// right = this.x + this.width
// top = this.y
// bottom = this.y + this.height
switch (this.t_currentTransformation) {
case TRANS_NONE:
case TRANS_MIRROR_ROT180:
retX = x1 - this.x;
break;
case TRANS_MIRROR:
case TRANS_ROT180:
retX = (this.x + this.width) - x2;
break;
case TRANS_ROT90:
case TRANS_MIRROR_ROT270:
retX = y1 - this.y;
break;
case TRANS_ROT270:
case TRANS_MIRROR_ROT90:
retX = (this.y + this.height) - y2;
break;
}
retX += frameCoordsX[frameSequence[sequenceIndex]];
return retX;
}
private int getImageTopLeftY(int x1, int y1, int x2, int y2) {
int retY = 0;
switch (this.t_currentTransformation) {
case TRANS_NONE:
case TRANS_MIRROR:
retY = y1 - this.y;
break;
case TRANS_ROT180:
case TRANS_MIRROR_ROT180:
retY = (this.y + this.height) - y2;
break;
case TRANS_ROT270:
case TRANS_MIRROR_ROT270:
retY = x1 - this.x;
break;
case TRANS_ROT90:
case TRANS_MIRROR_ROT90:
retY = (this.x + this.width) - x2;
break;
}
retY += frameCoordsY[frameSequence[sequenceIndex]];
return retY;
}
private void setTransformImpl(int transform) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -