Если это сложная форма, используйте растровые данные, как показано ниже. Это будет работать для всех форм.
Если вам все еще нужно знать самое низкое значение Y, не забывайте, что оно может быть и на X. Там есть дополнительная функция (getHitPoint) для расчета этого, которую нужно запускать только при успешном тесте на попадание. Его можно оптимизировать, передав в него растровые данные из исходной функции, но я сохранил его отдельно, чтобы он оставался читабельным.
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;
/**
* ...
* @author KM
*/
public class TestCases extends Sprite
{
private var rect :Sprite;
private var circle :Sprite;
public function TestCases() { }
/**
* Start the test case
*/
public function start():void {
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 = 0;
rect.y = 100;
// Position
circle.y = 400;
circle.x = 0;
// Frame loop
addEventListener(Event.ENTER_FRAME, frameFunc);
}
/**
*
* @param e
*/
private function frameFunc(e:Event):void {
// move them around
rect.y += 1;
circle.y -= 1;
circle.x += 1;
rect.x += 1;
// 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)) {
trace(getHitPoint(rect, circle));
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;
}
/**
* This ONLY needs to be called once a collision has been confirmed. Don't run this on every frame!
* @return
*/
private function getHitPoint(_obj1:Sprite, _obj2:Sprite, _debug:Boolean = false):Point {
var rtnPoint:Point = new Point();
// 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);
// Create two bitmaps
var bmp1:Bitmap = new Bitmap(bmd1);
var bmp2:Bitmap = new Bitmap(bmd2);
// Position
bmp1.x = _obj1.x;
bmp2.x = _obj2.x;
bmp1.y = _obj1.y;
bmp2.y = _obj2.y;
// Get the origins
var bitmapOrigin:Point = new Point(_obj1.x, _obj1.y);
var bitmapTwoOriginLocal:Point = bmp2.globalToLocal(bitmapOrigin);
// Find all the overlapping pixels
var overlappingPixels:Vector.<uint> = bmp2.bitmapData.getVector(new Rectangle(bitmapTwoOriginLocal.x, bitmapTwoOriginLocal.y, _obj1.width, _obj1.height));
var i:uint = 0;
var len:uint = overlappingPixels.length;
// Run through them all until we find a non-zero value
for(i; i < len; i++) {
if(overlappingPixels[i] != 0) {
// Our X collision is i % _obj1.width plus whichever X value is highest
rtnPoint.x = (i % _obj1.width) + (bmp2.x > bmp1.x ? bmp2.x : bmp1.x);
// Our Y collision is i / _obj1.height plus whichever Y value is highest
rtnPoint.y = (uint((i + 1) / _obj1.width)) + (bmp2.y > bmp1.y ? bmp2.y : bmp1.y);
// If debug, draw the collision point
if (_debug) {
var test:Sprite = new Sprite();
test.graphics.beginFill(0x008c6f);
test.graphics.drawRect(rtnPoint.x , rtnPoint.y, 10, 10);
test.graphics.endFill();
addChild(test);
}
break;
}
}
// Send it back
return rtnPoint;
}
}
}
person
Kevin McGowan
schedule
13.07.2014