如何实现这种画路径的效果?

视频前面是我的demo,后面是目标效果
【Demo-哔哩哔哩】https://b23.tv/zGUAx6

核心代码:

this.event.on(`INPUT:swipeStart[${this.id}]`, info => {
            this.event.on(`INPUT:swipe[${this.id}]`, swipe);
            this.event.once(`INPUT:swipeEnd[${this.id}]`, () => {
                this.event.off(`INPUT:swipe[${this.id}]`, swipe);
            });
            
            const entities   = this.entities,
                  result     = this.result,
                  path       = this.path,
                  simplified = this.simplifiedPath,
                  body       = new Collisions.Circle(0, 0, config.Assaulter.body.radius),
                  radius2     = body.radius * body.radius,
                  filter     = new Filter().setMatch(Wall.FILTER);
            let x       = 0, 
                y       = 0,
                offsetX = 0,
                offsetY = 0,
                next    = true;// if add another path point
            
            this.pathBody = body;
            function swipe() {
                x = info.currentX + offsetX;
                y = info.currentY + offsetY;
                body.x = x;
                body.y = y;
                    
                for(let e of entities) {
                    if(e.body && filter.test(e.body.filter) && body.collides(e.body, result)) {
                        next = false;
                        
                        body.x -= result.overlap * result.overlap_x;
                        body.y -= result.overlap * result.overlap_y;
                        
                        offsetX = body.x - info.currentX;
                        offsetY = body.y - info.currentY;
                        
                        break;
                    }
                }
                
                path.push([body.x, body.y]);
            }
        });

用自然语言描述思路也可以

PS:
我不是很明白为什么我的问题被踩了一下,作为一个刚提出第一个问题的新手,这让我很在意。在审视代码后,我觉得主要在冗余代码过多,与问题无关,这因为我还要实现其他功能,但另外我希望大家能注意到可以告诉我思路。已纠正。谢谢。

另:for里面那个break注释掉后与原先效果差不多。

阅读 1.2k
1 个回答

今天早上突然想起这个问题,然后就找到了答案。
问题主要在于

body.x -= result.overlap * result.overlap_x;
body.y -= result.overlap * result.overlap_y;

无法让body时刻不相交,所以需要缓冲,完整代码如下

this.event.on(`INPUT:swipeStart[${this.id}]`, info => {
            const entities = this.entities;
            const result = this.result;
            const path = this.path;
            const body = new Collisions.Circle(info.startX, info.startY, config.Assaulter.body.radius);
            const radius2 = body.radius * body.radius;
            const filter = new Filter().setMatch(Wall.FILTER);
            const temp = new Vector();
            const vel = new Vector();
            const acc = new Vector();
            const pos = new Vector().bind(body);
            let maxAcc = 2;
            let maxVel = 6;
            this.pathBody = body;
                
            this.simplifiedPath.length = 0;    
            this.event.on(`INPUT:swipe[${this.id}]`, swipe);
            this.event.once(`INPUT:swipeEnd[${this.id}]`, () => {
                this.event.off(`INPUT:swipe[${this.id}]`, swipe);
            });
            
            function swipe() {
                for(let e of entities) {
                    if(e.body && filter.test(e.body.filter) && body.collides(e.body, result)) {
                        body.x -= result.overlap * result.overlap_x;
                        body.y -= result.overlap * result.overlap_y;
                    }
                }
                
                temp.copy(pos).to(info.currentX, info.currentY);
                const len = temp.length();
                const ang = temp.angle();
                acc.copy(temp.setLenAng(Math.min(temp.copy(info.dx, info.dy).length(), len), ang));
                if(len > 70) {
                    maxVel = 10;
                    maxAcc = 4;
                } else if(len > 30) {
                    maxVel = 6;
                    maxAcc = 2;
                } else {
                    maxVel = 4;
                }

                acc.limitLen(0, maxAcc);
                vel.add(acc).limitLen(0, maxVel);
                pos.add(vel);
                
                path.push([body.x, body.y]);
            }
        });

注:vector.bind(obj)的效果是让vector与obj的xy属性值同步变化

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题