「引」 http://bbs.9ria.com/thread-61774-1-8.html
一个平面上有2个mc,分别代表玩家和敌人,暂时把这个平面地图用二维数组表示吧,黑色表示障碍,红色表示敌人,绿色表示玩家,如果红色和绿色的连线没有经过黑色障碍物,则说明敌人发现了玩家,问题是我该如何确定红色和绿色的连线中有没有经过障碍物呢?
像这样,他们连线经过了黑色障碍物,就表示没有被发现
这样就表示发现了
大家有什么好的办法?之前在AS板块问了下,说是求直线方程,还要遍历每个格子,还要求格子四个顶点是否经过直线,太麻烦了,有没有更好点的办法呢
这个应该是游戏中经常会遇到的问题,也算是游戏的AI吧,敌人如何发现玩家,只要他们的直线距离内没有障碍物
sliz 回答
射线方法
package sliz.math {
/**
* ...
* @author sliz http://space.flash8.net/space/?534614
*/
import flash.display.Graphics;
import flash.geom.Point;
public class RayShape {
public var vertices:Array;
public function RayShape(vertices:Array){
this.vertices = vertices;
}
public function move(velocity:Point):void {
var len:int = vertices.length
for (var i:int = 0; i < len; i++){
vertices[i] = vertices[i].add(velocity);
}
}
public function setPosition(position:Point):void {
var diff:Point = position.subtract(middle());
var len:int = vertices.length;
for (var i:int = 0; i < len; i++){
vertices[i] = vertices[i].add(diff);
}
}
public function middle():Point {
var mid:Point = new Point();
var len:int = vertices.length;
for (var i:int = 0; i < len; i++){
mid = mid.add(vertices[i]);
}
mid.x = mid.x / len;
mid.y = mid.y / len;
return mid;
}
public function debugDraw(graphics:Graphics):void {
graphics.lineStyle(0);
graphics.moveTo(vertices[0].x, vertices[0].y);
var len:int = vertices.length;
for (var i:int = 0; i < len; i++){
graphics.lineTo(vertices[i].x, vertices[i].y);
}
graphics.lineTo(vertices[0].x, vertices[0].y);
}
}
}
其它:
package
{
import flash.geom.Point;
/**
* ...
* @author sliz http://space.flash8.net/space/?534614
*/
public class GeomMath
{
private static const EP:Number = Math.LOG10E;
/**
* 判断2点是否相等
* @param p1
* @param p2
* @return
*/
public static function isEuqalPoint(p1:Point, p2:Point):Boolean {
return Math.abs(p1.x - p2.x) < EP && Math.abs(p1.y - p2.y) < EP;
}
/**
* 确定两条线段是否相交
* @param l1
* @param l2
* @return
*/
public static function isIntersect(p1:Point,p2:Point,p3:Point,p4:Point):Boolean {
return((Math.max(p1.x,p2.x)>=Math.min(p3.x,p4.x))&&
(Math.max(p3.x,p4.x)>=Math.min(p1.x,p2.x))&&
(Math.max(p1.y,p2.y)>=Math.min(p3.y,p4.y))&&
(Math.max(p3.y,p4.y)>=Math.min(p1.y,p2.y))&&
(multiply(p3,p2,p1)*multiply(p2,p4,p1)>=0)&&
(multiply(p1,p4,p3)*multiply(p4,p2,p3)>=0));
}
/**
* 一种线段相交判断函数,当且仅当l1,l2相交并且交点不是l1,l2的端点时函数为true;
* @param l1
* @param l2
* @return
*/
public static function isIntersect2(p1:Point,p2:Point,p3:Point,p4:Point):Boolean {
return((isIntersect(p1,p2,p3,p4))&&
(!isEuqalPoint(p1,p3))&&
(!isEuqalPoint(p1,p4))&&
(!isEuqalPoint(p2,p3))&&
(!isEuqalPoint(p2,p4)));
}
/**
* 跨立
* 伸出右手手心像上依次穿越sp,ep
* @param sp
* @param ep
* @param op
* @return
*/
public static function multiply(sp:Point,ep:Point,op:Point):int {
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
/**
* 穿越
* @param cn
* @param ln1
* @param ln2
* @param sn
* @param en
* @return
*/
public static function acrossAble(cn:Point, ln1:Point, ln2:Point, sn:Point, en:Point):Boolean {
return multiply(ln1,cn,sn) * multiply(cn,ln2,sn) <= 0 && multiply(ln1,cn,en) * multiply(cn,ln2,en) <= 0;
}
public static function getAcrossPoint(p1:Point, p2:Point, p3:Point, p4:Point,isMax:Boolean=false):Point {
if (!isMax&&!isIntersect(p1,p2,p3,p4)) {
return null;
}
var p:Point = new Point();
//y=ax+b
//y=cx+d
var type:int = 0;
if (p1.x==p2.x) {
//|x=p1.x
type = 1;
}else {
var a:Number = (p1.y - p2.y) / (p1.x - p2.x);
var b:Number = p1.y - a * p1.x;
}
if (p3.x==p4.x) {
//|x=p1.x
type = 2;
}else {
var c:Number = (p3.y - p4.y) / (p3.x - p4.x);
var d:Number = p3.y - c * p3.x;
}
if (type==0) {
p.x = (d - b) / (a - c);
p.y = a * p.x + b;
}else if (type==1) {
p.x = p1.x;
p.y = c * p.x + d;
}else if (type==2) {
p.x = p3.x;
p.y = a * p.x + b;
}
return p;
}
}
}