最近的项目由于团队中初级ASer比较多,本来是做自动寻路的,硬是被砍到直线碰撞,可惜悲剧的是,直线碰撞都跟我说有问题。
昨天一个哥们一直是让角色没走一步与像素点碰撞判断是否可走。我再多废话一遍:这样既有误差,效率也不高。
今天放此例,表明直线碰撞的推荐做法是,先画一条直线与通断模型进行碰撞测试,证实可抵达之后再直接让角色移过去(速度控制之后再做,与此例无关)。
实例效果:
黑色区域表示不可抵达,红色小方块表示需要移动的物体。
Document Class :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
package { import flash.display.SimpleButton; import com.gskinner.motion.GTween; import com.gskinner.motion.easing.Sine; import org.mousebomb.display.RealHitTest; import flash.display.Sprite; import flash.events.MouseEvent; /** * @author Mousebomb (mousebomb@gmail.com) * @date 2010-6-8 */ public class HitTestMain extends Sprite { public var pz : Sprite ; public var line : Sprite = new Sprite(); public var box : Sprite; public var showBtn : SimpleButton; private var boxTween : GTween; private var curX : int = 300; private var curY : int = 200; public function HitTestMain() { addChild(line); boxTween = new GTween(box,.3,null,{ease:Sine.easeOut}); curX=box.x; curY=box.y; line.graphics.lineStyle(3, 0xff0000); line.graphics.moveTo(curX, curY); stage.addEventListener(MouseEvent.CLICK, onClick); showBtn.addEventListener(MouseEvent.CLICK, onShowClick); } private function onShowClick(event : MouseEvent) : void { if(pz.parent) { removeChild(pz); removeChild(line); }else{ addChildAt(pz,0); addChildAt(line,1); } } private function onClick(event : MouseEvent) : void { line.graphics.lineTo(event.stageX, event.stageY); if(RealHitTest.hitTestObj(line, pz)) { line.graphics.clear(); line.graphics.lineStyle(3, 0xff0000); line.graphics.moveTo(curX, curY); } else { curX = event.stageX; curY = event.stageY; boxTween.setValues({x:curX,y:curY}); } } } } |
RealHitTest:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package org.mousebomb.display { import flash.display.BlendMode; import flash.display.DisplayObjectContainer; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Rectangle; /** * Flash自带的HitTestObject有问题,这个类是真正的HitTest * @author Mousebomb (mousebomb@gmail.com) * @date 2010-3-14 */ public class RealHitTest { private static var bmp : Bitmap = new Bitmap(); /** * 此方法的思路由ryan-liu提出 * @return 是否重叠 * @param src 要比较的对象 * @param target 与之比较的对象 * src和target的容器必须是同意对象,或者原点坐标对齐 */ public static function hitTestObj(src : DisplayObject,target : DisplayObject) : Boolean { //获取要比较的对象的区域以偏移位图 var srcBound : Rectangle = src.getBounds(src.parent); var bmd : BitmapData = new BitmapData(srcBound.width, srcBound.height, false, 0); //bmp.bitmapData = bmd; var mtx1 : Matrix = new Matrix(); var mtx2 : Matrix = new Matrix(); mtx1.rotate(src.rotation * Math.PI / 180); mtx1.tx = src.x-srcBound.x; mtx1.ty = src.y-srcBound.y; mtx2.rotate(target.rotation * Math.PI / 180); mtx2.tx = target.x - srcBound.x; mtx2.ty = target.y - srcBound.y; bmd.fillRect(bmd.rect, 0); bmd.draw(src, mtx1, new ColorTransform(1, 1, 1, 1, -255, 255, 255, 255)); bmd.draw(target, mtx2, new ColorTransform(1, 1, 1, 1, 255, -255, -255, 255), BlendMode.DIFFERENCE); var rect : Rectangle = bmd.getColorBoundsRect(0xffffff, 0xffffff); //碰撞检测结束 //Rectangle四个属性为0则没搜索到 return (rect.x != 0 || rect.y != 0 || rect.width != 0 || rect.height != 0); } public static function debug(s : DisplayObjectContainer):void { s.addChild(bmp); bmp.x = 500; bmp.y = 300; } } } |
源文件点此下载
挺深奥的问题哦,UP