zoukankan      html  css  js  c++  java
  • OBB碰撞

    OBB碰撞检测,坐标点逆时针

    class OBBTest extends egret.DisplayObjectContainer {
        private obb1:OBB;
        private obb2:OBB;
    
        private points1:Array<egret.Point>;
        private points2:Array<egret.Point>;
        private sprite1:egret.Sprite;
        private sprite2:egret.Sprite;
        private resPoint:egret.Point = new egret.Point();
        constructor() {
            super();
    
            this.touchEnabled = true;
            var stage = egret.MainContext.instance.stage;
            stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin, this);
            stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this);
            stage.addEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEnd, this);
    
            this.points1 = [new egret.Point(0,0),new egret.Point(100,200),new egret.Point(300,300),new egret.Point(300,100),new egret.Point(0,0)];
            this.sprite1 = this.drawSprite(this.points1);
            this.addChild(this.sprite1);
            this.sprite1.x = 100;
            this.sprite1.y = 100;
    
            this.points2 = [new egret.Point(0,0),new egret.Point(100,200),new egret.Point(300,300),new egret.Point(300,100),new egret.Point(0,0)];
            this.sprite2 = this.drawSprite(this.points2);
            this.addChild(this.sprite2);
            this.sprite2.x = 100;
            this.sprite2.y = 400;
    
            //创建两obb盒子
            this.obb1 = new OBB();
            this.obb2 = new OBB();
            
            egret.startTick(this.onEnterFrame, this);
        }
    
        private pt:egret.Point = new egret.Point(0,0);
        private onEnterFrame():boolean {
            
            for (var i = 0; i < this.points1.length; i++) {
                var point1:egret.Point = this.points1[i];
                this.sprite1.localToGlobal(point1.x, point1.y, this.pt);
                this.obb1.setVertex(i, this.pt.x, this.pt.y);
            }
    
            for (var j = 0; j < this.points2.length; j++) {
                var point2:egret.Point = this.points2[j];
                this.sprite2.localToGlobal(point2.x, point2.y, this.pt);
                this.obb2.setVertex(j, this.pt.x, this.pt.y);
            }
    
            this.sprite1.visible = !this.obb1.isCollidWithOBB(this.obb2);
    
            return false;
        }
    
        private drawSprite(points:Array<egret.Point>):egret.Sprite {
            var startPoint:egret.Point = points[0];
            var sprite = new egret.Sprite();
            sprite.graphics.clear();
            sprite.graphics.beginFill( 0xffffff, 0.5 );
            sprite.graphics.moveTo( startPoint.x, startPoint.y );
            for (var i = 1; i < points.length ; i++) {
                var point = points[i];
                sprite.graphics.lineTo( point.x, point.y );
            }
            sprite.graphics.endFill();
    
            return sprite;
        }
    
        private onTouchBegin(evt:egret.TouchEvent):void {
            var posX = evt.stageX;
            var posY = evt.stageY;
    
            this.sprite2.x = posX;
            this.sprite2.y = posY;
        }
    
        private onTouchMove(evt:egret.TouchEvent):void {
            var posX = evt.stageX;
            var posY = evt.stageY;
    
            this.sprite2.x = posX;
            this.sprite2.y = posY;
        }
    
        private onTouchEnd(evt:egret.TouchEvent):void {
            var posX = evt.stageX;
            var posY = evt.stageY;
    
            this.sprite2.x = posX;
            this.sprite2.y = posY;
        }
    }
    /**
     * 投影判断
     */
    class Projection {
        private min:number = 0;
        private max:number = 0;
        constructor(min, max) {
            this.min = min;
            this.max = max;
        }
    
        public getMin(){
            return this.min;
        }
    
        public getMax(){
            return this.max;
        }
    
        /**
         * 判断是否叠加
         */
        public overlap(proj:Projection):boolean {
            if(this.min > proj.getMax())    return false;
            if(this.max < proj.getMin())    return false;
    
            return true;
        }
    };
    class OBB {
        private pList:Array<any> = []                   //保存盒子顶点数
        constructor() {
            this.pList = [];
        }
    
        public getVertex(idx):egret.Point {
            if (idx >= this.pList.length) {
                return null;
            }
    
            return this.pList[idx];
        };
    
        public setVertex(idx:number, x:number, y:number):void {
            if (!this.pList[idx]) {
                this.pList[idx] = new egret.Point(0, 0);
            }
    
            this.pList[idx].x = x;
            this.pList[idx].y = y;
        }
    
        /**
         * 计算分离轴
         * 如果边向量为(x,y),那么法向量为(-y,x),你也可以设置为(y,-x)。结果没有什么变化。 
         */
        public getAxies():Array<egret.Point> {
            var axies = [];
            var len = this.pList.length;
            var pOut = new egret.Point(0,0);
            for(var i = 0; i < len; i++) {    
                var startPoint:egret.Point = this.pList[i];
                var endPoint:egret.Point = this.pList[(i + 1) % len];
                var point = startPoint.subtract(endPoint);
    
                var length = Math.sqrt(point.x * point.x + point.y * point.y);
                pOut.x = point.x / length;
                pOut.y = point.y / length;
    
                axies[i] = new egret.Point();
                axies[i].x = -pOut.y ;
                axies[i].y = pOut.x ;
            }
            return axies;
        }
    
        /**
         * 计算投影
         * 计算出一个投影线条
         * 只是保存了两个float形的数据,分别表示OBB盒在分离轴上投影的最小值和最大值
         */
        public getProjection(axies:egret.Point):Projection {
            var min = this.pList[0].x * axies.x + this.pList[0].y * axies.y;
            var max = min ;
    
            var len = this.pList.length;
            for (var i = 1; i < len; i++) {
                var temp = this.pList[i].x * axies.x + this.pList[i].y * axies.y;
                if (temp > max) {
                    max = temp;
                } else if (temp < min) {
                    min = temp;
                }
            }// end for
    
            return new Projection(min, max);
        }
    
        //对传递进来的OBB判断是否与调用这个方法的OBB发生了交叉
        public isCollidWithOBB(obb:OBB):boolean {
            //获取分离轴
            var axies1 = this.getAxies();
            var axies2 = obb.getAxies();
    
            var p1:Projection = null;
            var p2:Projection = null;
            
            //Check for overlap for all of the axies
            for(var i = 0; i < axies1.length; i++)
            {
                p1 = this.getProjection(axies1[i]);
                p2 = obb.getProjection(axies1[i]);
                if(!p1.overlap(p2))
                {
                    return false ;
                }
            }
    
            for(var j = 0; j < axies2.length; j ++)
            {
                p1 = this.getProjection(axies2[j]);
                p2 = obb.getProjection(axies2[j]);
                if(!p1.overlap(p2))
                {
                    return false ;
                }
            }
    
            return true ;
        }
    }

     测试,在Main中添加

    var obb = new OBBTest();
    this.addChild(obb);
  • 相关阅读:
    想要学习设计模式,你得先会看类图,一张图读懂UML
    UML类图中箭头的含义
    DDD学习
    Customize your build
    WaitAll vs WhenAll
    When does a C# Task actually start?
    UE4中多种颜色轮廓线的后期处理
    [UE4]武器碰撞
    动态材质实例(Dynamic Material Instance)
    卷积运算
  • 原文地址:https://www.cnblogs.com/maxwell-xu/p/7767313.html
Copyright © 2011-2022 走看看