两个物体形状的命中测试
Hittest for two object shapes
假设我们有一个具有任意复杂形状的 Hitbox 的对象和一个具有 circle/polygon 作为 Hitbox 的对象。如何检测这两个对象(不是边界矩形,而是实际像素)的碰撞?两个对象都是不透明的 Sprites。
试试这个。纹理精灵来自 Flambe 引擎。本质上是碰撞的边界框,然后遍历碰撞框检查每个像素。
static public function pixelPerfect(sprite1:SpriteContainer, sprite2:SpriteContainer):Bool
{
var collisionRect:Rectangle;
for (texture1 in sprite1.textures)
{
for (texture2 in sprite2.textures)
{
collisionRect = CollisionUtil.collisionRect(texture1, texture2);
if (collisionRect == null) continue;
if (pixelCollision(texture1, collisionRect) && pixelCollision(texture2, collisionRect))
{
return true;
}
}
}
return false;
}
static public function pixelCollision(sprite:TextureSprite, collisionRect:Rectangle)
{
var localRectPt:Point = sprite.globalToLocal(collisionRect.x, collisionRect.y);
localRectPt.x /= Main.GLOBAL_SCALE;
localRectPt.y /= Main.GLOBAL_SCALE;
var scaledRect:Rectangle = collisionRect.clone();
scaledRect.width /= Main.GLOBAL_SCALE;
scaledRect.height /= Main.GLOBAL_SCALE;
var PIXEL_DATA_LENGTH:Int = 4;
var PIXELS_TO_SKIP:Int = 5;
var resolution:Int = PIXEL_DATA_LENGTH * PIXELS_TO_SKIP;
var alphaOffset:Int = 3;
var bytes:Bytes;
try{
bytes = sprite.symbol.atlas.readPixels(Math.round(localRectPt.x), Math.round(localRectPt.y), Math.round(scaledRect.width), Math.round(scaledRect.height));
var n:Int = bytes.length;
var i:Int = 0;
while(i+3<n)
{
if (bytes.get(i + alphaOffset) > 0)
{
return true;
}
i += resolution;
}
}
catch (e:Dynamic)
{
Log.trace(e);
}
bytes = null;
return false;
}
}
这是我在 ActionScript 3 (https://snipplr.com/view/90435/pixel-perfect-collision-detection-as3/) 中找到的一段代码,看起来应该可以在 OpenFL 中运行。
代码的 Haxe 版本可能如下所示:
public function objectsHit (mc1:DisplayObject, mc2:DisplayObject):Bool {
var mc1bounds = mc1.getBounds (this);
var mc2bounds = mc2.getBounds (this);
var allintersections = (mc2bounds.intersection(mc1bounds));
for (xval in allintersections.x...(allintersections.x + allintersections.width)) {
for (yval in allintersections.y...(allintersections.y + allintersections.height)) {
if (mc2.hitTestPoint (xval, yval, true) && mc1.hitTestPoint (xval, yval, true)) {
return true;
}
}
}
return false;
}
也可以先使用 hitTestObject
方法,然后再使用 hitTestPoint
方法。一般的想法是首先执行边界框命中检测,如果您需要更精确的东西,然后执行基于点的碰撞(这更昂贵)。
假设我们有一个具有任意复杂形状的 Hitbox 的对象和一个具有 circle/polygon 作为 Hitbox 的对象。如何检测这两个对象(不是边界矩形,而是实际像素)的碰撞?两个对象都是不透明的 Sprites。
试试这个。纹理精灵来自 Flambe 引擎。本质上是碰撞的边界框,然后遍历碰撞框检查每个像素。
static public function pixelPerfect(sprite1:SpriteContainer, sprite2:SpriteContainer):Bool
{
var collisionRect:Rectangle;
for (texture1 in sprite1.textures)
{
for (texture2 in sprite2.textures)
{
collisionRect = CollisionUtil.collisionRect(texture1, texture2);
if (collisionRect == null) continue;
if (pixelCollision(texture1, collisionRect) && pixelCollision(texture2, collisionRect))
{
return true;
}
}
}
return false;
}
static public function pixelCollision(sprite:TextureSprite, collisionRect:Rectangle)
{
var localRectPt:Point = sprite.globalToLocal(collisionRect.x, collisionRect.y);
localRectPt.x /= Main.GLOBAL_SCALE;
localRectPt.y /= Main.GLOBAL_SCALE;
var scaledRect:Rectangle = collisionRect.clone();
scaledRect.width /= Main.GLOBAL_SCALE;
scaledRect.height /= Main.GLOBAL_SCALE;
var PIXEL_DATA_LENGTH:Int = 4;
var PIXELS_TO_SKIP:Int = 5;
var resolution:Int = PIXEL_DATA_LENGTH * PIXELS_TO_SKIP;
var alphaOffset:Int = 3;
var bytes:Bytes;
try{
bytes = sprite.symbol.atlas.readPixels(Math.round(localRectPt.x), Math.round(localRectPt.y), Math.round(scaledRect.width), Math.round(scaledRect.height));
var n:Int = bytes.length;
var i:Int = 0;
while(i+3<n)
{
if (bytes.get(i + alphaOffset) > 0)
{
return true;
}
i += resolution;
}
}
catch (e:Dynamic)
{
Log.trace(e);
}
bytes = null;
return false;
}
}
这是我在 ActionScript 3 (https://snipplr.com/view/90435/pixel-perfect-collision-detection-as3/) 中找到的一段代码,看起来应该可以在 OpenFL 中运行。
代码的 Haxe 版本可能如下所示:
public function objectsHit (mc1:DisplayObject, mc2:DisplayObject):Bool {
var mc1bounds = mc1.getBounds (this);
var mc2bounds = mc2.getBounds (this);
var allintersections = (mc2bounds.intersection(mc1bounds));
for (xval in allintersections.x...(allintersections.x + allintersections.width)) {
for (yval in allintersections.y...(allintersections.y + allintersections.height)) {
if (mc2.hitTestPoint (xval, yval, true) && mc1.hitTestPoint (xval, yval, true)) {
return true;
}
}
}
return false;
}
也可以先使用 hitTestObject
方法,然后再使用 hitTestPoint
方法。一般的想法是首先执行边界框命中检测,如果您需要更精确的东西,然后执行基于点的碰撞(这更昂贵)。