直线移动检测可否抵达的例子

最近的项目由于团队中初级ASer比较多,本来是做自动寻路的,硬是被砍到直线碰撞,可惜悲剧的是,直线碰撞都跟我说有问题。

昨天一个哥们一直是让角色没走一步与像素点碰撞判断是否可走。我再多废话一遍:这样既有误差,效率也不高。

今天放此例,表明直线碰撞的推荐做法是,先画一条直线与通断模型进行碰撞测试,证实可抵达之后再直接让角色移过去(速度控制之后再做,与此例无关)。

实例效果: 黑色区域表示不可抵达,红色小方块表示需要移动的物体。

Document Class :

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:

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;
}
}
}

源文件点此下载


技术内容转载请注明来源,个人日记不允许转载,欢迎指出任何有错误或不够清晰的表达。可以邮件至 mousebomb@gmail.com