我怎样才能上,底部,右边和最左边的一个像素完美的BitmapData碰撞点?这是我的碰撞检测code:
How can I get the upper, bottom, rightmost and leftmost point of a pixel-perfect BitmapData collision? This is my collision-detection code:
public static function checkCollision(object1:*, object2:*, debug:Boolean = false):Boolean{
var object1Rect:Rectangle = object1.getRect(stage);
var object2Rect:Rectangle = object2.getRect(stage);
var object1Point:Point = new Point(object1Rect.x, object1Rect.y);
var object2Point:Point = new Point(object2Rect.x, object2Rect.y);
var bitmapData1:BitmapData = new BitmapData(
object1Rect.width,
object1Rect.height,
true,
0
);
var bitmapData2:BitmapData = new BitmapData(
object2Rect.width,
object2Rect.height,
true,
0
);
var clr:ColorTransform = new ColorTransform();
if(debug)
clr.color = 0x00ff00;
bitmapData1.draw(object1, new Matrix(1, 0, 0, 1, -object1Rect.x, -object1Rect.y), clr);
bitmapData2.draw(object2, null, clr);
if(debug){
if(bmp1.stage)
stage.removeChild(bmp1);
bmp1 = new Bitmap(bitmapData1);
bmp1.x = object1Point.x;
bmp1.y = object1Point.y;
stage.addChild(bmp1);
if(bmp2.stage)
stage.removeChild(bmp2);
bmp2 = new Bitmap(bitmapData2);
bmp2.x = object2Point.x;
bmp2.y = object2Point.y;
stage.addChild(bmp2);
}
var bCollide:Boolean = bitmapData1.hitTest(
object1Point,
255,
bitmapData2,
object2Point,
255
);
if(!debug){
bitmapData1.dispose();
bitmapData2.dispose();
}
return bCollide;
}
和它的工作原理perfeclty罚款。然而,code我用它来探测生命值最高不能正常工作。这是code:
And it works perfeclty fine. However, the code I use to detect the top hitpoint doesn't work properly. This is the code:
public static function getHitPoint(object1:*, object2:*):Point{
var point:Point = new Point();
var object1Rect:Rectangle = object1.getRect(stage);
var object2Rect:Rectangle = object2.getRect(stage);
var object1Point:Point = new Point(object1Rect.x, object1Rect.y);
var object2Point:Point = new Point(object2Rect.x, object2Rect.y);
var bitmapData1:BitmapData = new BitmapData(
object1.width,
object1.height,
true,
0
);
var bitmapData2:BitmapData = new BitmapData(
object2.width,
object2.height,
true,
0
);
bitmapData1.draw(object1, new Matrix(1, 0, 0, 1, -object1Rect.x, -object1Rect.y));
bitmapData2.draw(object2);
var bitmap1:Bitmap = new Bitmap(bitmapData1);
var bitmap2:Bitmap = new Bitmap(bitmapData2);
bitmap1.x = object1Point.x;
bitmap1.y = object1Point.y;
bitmap2.x = object2Point.x;
bitmap2.y = object2Point.y;
var bitmapOrigin:Point = new Point(object1Point.x, object1Point.y);
var bitmap2OriginLocal:Point = bitmap2.globalToLocal(bitmapOrigin);
var overlappingPixels:Vector.<uint> = bitmap2.bitmapData.getVector(
new Rectangle(bitmap2OriginLocal.x, bitmap2OriginLocal.y, object1Rect.width, object1Rect.height)
);
for(var i:String in overlappingPixels){
var index:uint = uint(i);
if(overlappingPixels[i] != 0){
point.x = (index % object1.width) + (bitmap2.x > bitmap1.x ? bitmap2.x : bitmap1.x);
point.y = (uint(index / bitmap1.height)) + (bitmap2.y > bitmap1.y ? bitmap2.y : bitmap1.y);
break;
}
}
return point;
}
我有不知道为什么,但 getHitPoint()
函数有时会返回错误的坐标。任何人都可以请解释这是为什么?我怎样才能检测到最底部,最左边和最右边的生命值?
I've got no idea why, but the getHitPoint()
function sometimes returns the wrong coordinates. Can anyone please explain why that is? And how can I detect the bottommost, the leftmost and the rightmost hitpoint?
修改
我现在知道为什么 getHitPoint()
有时返回错误的值: point.y =(UINT(指数/ bitmap1.height))+(bitmap2。 Ÿ&GT; bitmap1.y bitmap2.y:?bitmap1.y);
应 point.y =(UINT(指数/ bitmap1
< STRONG> 宽度
))+(bitmap2.y&GT; bitmap1.y bitmap2.y:bitmap1.y);
Edit
I now know why getHitPoint()
sometimes returned a wrong value: point.y = (uint(index / bitmap1.height)) + (bitmap2.y > bitmap1.y ? bitmap2.y : bitmap1.y);
should be point.y = (uint(index/bitmap1.
width
)) + (bitmap2.y > bitmap1.y ? bitmap2.y : bitmap1.y);
编辑2 我发现了如何获得生命值底部:
Edit 2 I found out how to get the bottom hitpoint:
public static function getHitPoint(object1:*, object2:*, direction:int = 0):*{
var point:Point = new Point();
var object1Rect:Rectangle = object1.getRect(stage);
var object2Rect:Rectangle = object2.getRect(stage);
var object1Point:Point = new Point(object1Rect.x, object1Rect.y);
var object2Point:Point = new Point(object2Rect.x, object2Rect.y);
var bitmapData1:BitmapData = new BitmapData(
Math.round(object1Rect.width),
Math.round(object1Rect.height),
true,
0
);
var bitmapData2:BitmapData = new BitmapData(
Math.round(object2Rect.width),
Math.round(object2Rect.height),
true,
0
);
bitmapData1.draw(object1, new Matrix(1, 0, 0, 1, -object1Rect.x, -object1Rect.y));
bitmapData2.draw(object2);
var bitmap1:Bitmap = new Bitmap(bitmapData1);
var bitmap2:Bitmap = new Bitmap(bitmapData2);
bitmap1.x = object1Point.x;
bitmap1.y = object1Point.y;
bitmap2.x = object2Point.x;
bitmap2.y = object2Point.y;
var bitmapOrigin:Point = new Point(object1Point.x, object1Point.y);
var bitmap2OriginLocal:Point = bitmap2.globalToLocal(bitmapOrigin);
var overlappingPixels:Vector.<uint> = bitmap2.bitmapData.getVector(
new Rectangle(bitmap2OriginLocal.x, bitmap2OriginLocal.y, object1Rect.width, object1Rect.height)
);
switch(direction){
case 0: //top
for(var i:String in overlappingPixels){
var index:uint = uint(i);
if(overlappingPixels[i] != 0){
point.x = (index % bitmap1.width) + (bitmap2.x > bitmap1.x ? bitmap2.x : bitmap1.x);
point.y = (uint((index)/bitmap1.width)) + (bitmap2.y > bitmap1.y ? bitmap2.y : bitmap1.y);
return point;
}
}
case 1: //right
// I still need this
case 2: //bottom
overlappingPixels.reverse();
for(var i:String in overlappingPixels){
var index:uint = uint(i);
if(overlappingPixels[i] != 0){
point.x = bitmap1.width - (index % bitmap1.width) + (bitmap2.x > bitmap1.x ? bitmap2.x : bitmap1.x);
point.y = (bitmap2.y + bitmap2.height > bitmap1.y + bitmap1.height ? bitmap1.y + bitmap1.height : bitmap2.y + bitmap2.height) - (uint(index/bitmap1.width));
return point;
}
}
case 3: //left
// I still need this too
}
return false;
}
我还需要一种方式来获得左和最右生命值,虽然
I still need a way to get the left and rightmost hitpoints though
您不需要做像你做什么。您都可以在一个单一的功能,这回正确返回的一切去做。我已经添加注释到下面。请注意我已经改变了,因为当你试图做到这一点,你现在所做的,与code,你变了,这是不可能的。
You don't need to do it like you're doing there. You can do it all within a single function, which returns everything back correctly. I've added comments to the below. Please take note of what I've changed, as when you're trying to do it as you're doing now, with the code you changed, it is impossible.
这适用于任何形状,任何方向。它会给你确切的碰撞X和Y
This works for any shape, any direction. It'll give you the exact X and Y of the collision.
请的不的使之成为一个静态函数这一点。把它变成一个全球性的类,并使用单来管理它,而不是。事情开始走得很严重错误正在使用的静态函数时,你并引用了舞台。
Please do not make this into a static function. Put it into a global class and use a Singleton to manage it instead. Things start to go very badly wrong when you being using static functions and reference the stage.
另外,如果你将要小于1(即99.75)像素值的工作,下面将需要一点点调整,以满足该的。我一直以为你是用全像素,给你Math.round使用。
Also, if you're going to be working with pixel values of less than 1 (ie 99.75), the below will need a bit of adapting to cater for that. I've assumed you're using whole pixels, given your Math.round usage.
/**
*
* @param object1
* @param object2
* @return
*/
private function getHitPoint(object1:*, object2:*):*{
var point:Point;
// X and Y where we hit
// do NOT change this to a stage location or it does NOT work
var object1Point:Point = new Point(object1.x, object1.y);
var object2Point:Point = new Point(object2.x, object2.y);
var bitmapData1:BitmapData = new BitmapData(
Math.round(object1.width),
Math.round(object1.height),
true,
0
);
var bitmapData2:BitmapData = new BitmapData(
Math.round(object2.width),
Math.round(object2.height),
true,
0
);
// Draw
bitmapData1.draw(object1, new Matrix(1, 0, 0, 1, -object1.x, -object1.y));
bitmapData2.draw(object2);
// Create BMP's
var bitmap1:Bitmap = new Bitmap(bitmapData1);
var bitmap2:Bitmap = new Bitmap(bitmapData2);
// Set X and Y and BMP
bitmap1.x = object1Point.x;
bitmap1.y = object1Point.y;
bitmap2.x = object2Point.x;
bitmap2.y = object2Point.y;
// BMP origin is the object1 X and Y
var bitmapOrigin:Point = new Point(object1Point.x, object1Point.y);
// Create a local version of the bitmap2 so we can see what is overlapping
var bitmap2OriginLocal:Point = bitmap2.globalToLocal(bitmapOrigin);
// Create a rectangle from what we now know
var rect:Rectangle = new Rectangle(bitmap2OriginLocal.x, bitmap2OriginLocal.y, object1.width, object1.height);
// The overlapping pixels are within the rectangle, so get them all
var overlappingPixels:Vector.<uint> = bitmap2.bitmapData.getVector(rect);
// Run through all the overlapping pixels until we find a colourful one
for (var i:uint = 0; i < overlappingPixels.length; i++ ) {
var index:uint = overlappingPixels[i];
// If the colour is not 0, we have found it
if(index != 0){
point = new Point();
// Basically, instead of using width and getting 100, we're working out how
// many pixles across the overlap is. The Vector doesn't tell us this, so we need to work it out
var overlappingWidth:uint = object1.width - Math.abs(bitmap2OriginLocal.x);
// The Y is object1.y, minus the local y, plus object1's width minus the X from the local
point.y = object1.y - bitmap2OriginLocal.y + uint(i / overlappingWidth);
// The X is the same as above, but % of the width
point.x = object1.x - bitmap2OriginLocal.x + (i % overlappingWidth);
// Found it, we're done
break;
}
}
// Only fires when you've got a collision that is less than 1 pixel from the width or height
// Just a fail safe
if (!point) {
point = new Point(object1.width, object1.height);
}
return point;
}
有关背景下,我的整个班级低于这说明我是如何使用此功能。您可以复制/粘贴这个类,它会工作。这表明你如何移动精灵在屏幕上,一旦它找到一个碰撞,然后它工作在哪里碰撞发生。
For context, my entire class is below which shows how I was using this function. You can copy/paste this class and it will work. It shows how you move sprites around the screen, once it finds a collision, then it works out where the collision took place.
本类是绝对像素完美碰撞检测,其中一个例子。
This class is for absolute pixel perfect collision detection, including an example.
package kazo
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Matrix;
/**
* ...
* @author KM
*/
public class TestCases2 extends Sprite
{
private var rect :Sprite;
private var circle :Sprite;
/**
*
*/
public function TestCases2()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
trace('Starting test case');
// Rectangle
rect = new Sprite();
// Circle
circle = new Sprite();
// Draw the rectangle. Center point must be TOP LEFT
// If you're using Flash Professional, place everything at 0,0 inside the MC
rect.graphics.beginFill(0xff0000);
rect.graphics.drawRect(0, 0, 100, 100);
rect.graphics.endFill();
// Draw the circle. Center point is TOP LEFT, so the X and Y of the circle need to be equal to the radius
circle.graphics.beginFill(0xffff00);
circle.graphics.drawCircle(50, 50, 50);
circle.graphics.endFill();
// Add them
addChild(rect);
addChild(circle);
// Position
rect.x = 225;
rect.y = 75;
// Position
circle.x = 225;
circle.y = 225;
// Frame loop
addEventListener(Event.ENTER_FRAME, frameFunc);
}
/**
*
* @param e
*/
private function frameFunc(e:Event):void {
// move them around
circle.y -= 2;
circle.x += 0;
rect.y += 1;
rect.x += 0;
// Check for collisions. If found, stop. Pass 'true' as the final param if you want it to draw to the screen
if (checkCollision(rect, circle)) {
var ref:Point = getHitPoint(rect, circle);
// Draws where the collision hit
var loc:Sprite = new Sprite();
loc.graphics.beginFill(0x000000);
loc.graphics.drawRect(0, 0, 10, 10);
loc.graphics.endFill();
addChild(loc);
loc.x = ref.x;
loc.y = ref.y;
trace(ref);
removeEventListener(Event.ENTER_FRAME, frameFunc);
}
}
/**
*
* @param _obj1
* @param _obj2
* @param _debug
* @return
*/
private function checkCollision(_obj1:Sprite, _obj2:Sprite, _debug:Boolean = false):Boolean {
// Draw the first item to bitmapdata
var bmd1:BitmapData = new BitmapData(_obj1.width, _obj1.height, true, 0);
// ..and the second
var bmd2:BitmapData = new BitmapData(_obj2.width, _obj2.height, true, 0);
// Now draw them
bmd1.draw(_obj1);
bmd2.draw(_obj2);
// If we're in debug, also add the bitmap to the stage so we can see where we are
if (_debug) {
var bmp:Bitmap = new Bitmap(bmd1);
bmp.x = _obj1.x;
bmp.y = _obj1.y;
addChild(bmp);
var bmp2:Bitmap = new Bitmap(bmd2);
bmp2.x = _obj2.x;
bmp2.y = _obj2.y;
addChild(bmp2);
}
// Hit test including alpha channel. Obj1 X/Y, Obj2 X/Y, alpha channel
var rtn:Boolean = bmd1.hitTest(new Point(_obj1.x, _obj1.y), 255, bmd2, new Point(_obj2.x, _obj2.y), 255);
// Dispose the bitmap data, we dont need it anymore
if (!_debug) {
bmd1.dispose();
bmd2.dispose();
}
// Return the boolean
return rtn;
}
/**
*
* @param object1
* @param object2
* @return
*/
private function getHitPoint(object1:*, object2:*):*{
var point:Point;
// X and Y where we hit
// do NOT change this to a stage location or it does NOT work
var object1Point:Point = new Point(object1.x, object1.y);
var object2Point:Point = new Point(object2.x, object2.y);
var bitmapData1:BitmapData = new BitmapData(
Math.round(object1.width),
Math.round(object1.height),
true,
0
);
var bitmapData2:BitmapData = new BitmapData(
Math.round(object2.width),
Math.round(object2.height),
true,
0
);
// Draw
bitmapData1.draw(object1, new Matrix(1, 0, 0, 1, -object1.x, -object1.y));
bitmapData2.draw(object2);
// Create BMP's
var bitmap1:Bitmap = new Bitmap(bitmapData1);
var bitmap2:Bitmap = new Bitmap(bitmapData2);
// Set X and Y and BMP
bitmap1.x = object1Point.x;
bitmap1.y = object1Point.y;
bitmap2.x = object2Point.x;
bitmap2.y = object2Point.y;
// BMP origin is the object1 X and Y
var bitmapOrigin:Point = new Point(object1Point.x, object1Point.y);
// Create a local version of the bitmap2 so we can see what is overlapping
var bitmap2OriginLocal:Point = bitmap2.globalToLocal(bitmapOrigin);
// Create a rectangle from what we now know
var rect:Rectangle = new Rectangle(bitmap2OriginLocal.x, bitmap2OriginLocal.y, object1.width, object1.height);
// The overlapping pixels are within the rectangle, so get them all
var overlappingPixels:Vector.<uint> = bitmap2.bitmapData.getVector(rect);
// Run through all the overlapping pixels until we find a colourful one
for (var i:uint = 0; i < overlappingPixels.length; i++ ) {
var index:uint = overlappingPixels[i];
// If the colour is not 0, we have found it
if(index != 0){
point = new Point();
// Basically, instead of using width and getting 100, we're working out how
// many pixles across the overlap is. The Vector doesn't tell us this, so we need to work it out
var overlappingWidth:uint = object1.width - Math.abs(bitmap2OriginLocal.x);
// The Y is object1.y, minus the local y, plus object1's width minus the X from the local
point.y = object1.y - bitmap2OriginLocal.y + uint(i / overlappingWidth);
// The X is the same as above, but % of the width
point.x = object1.x - bitmap2OriginLocal.x + (i % overlappingWidth);
// Found it, we're done
break;
}
}
// Only fires when you've got a collision that is less than 1 pixel from the width or height
// Just a fail safe
if (!point) {
point = new Point(object1.width, object1.height);
}
return point;
}
}
}
上一篇:Direct2D的 - preserve现有内容和覆盖新价值价值、内容、Direct2D、preserve
下一篇:SOAP XML客户端 - 使用Visual Studio 2010的C# - 怎么样?客户端、XML、SOAP、Studio