【问题标题】:How to make the car move in a path如何使汽车在路径中移动
【发布时间】:2017-06-24 03:24:41
【问题描述】:

我正在用 javascript 开发一个动画,其中汽车向一个人移动并选择,但目前我只是用下面的代码斜着向那个人行驶而不是一条路径。

Car.prototype.main = function() {
      var angle = angleBetweenTwoPoints(this.target.position, this.position);
      var cos = Math.cos(degreeToRadian(angle)) * -1;
      var sin = Math.sin(degreeToRadian(angle));
      var _this = _super.call(this) || this;
      this.angle = angle;
      this.position.x += cos * this.speed;
      this.position.y -= sin * this.speed;
      if (distance(this.position, this.target.position) < 10 && this.image == GameImage.getImage("hero") ) {
        this.target.position.x = Math.random() * mainCanvas.width;
        this.target.position.y = Math.random() * mainCanvas.height;
        this.hitCount++;
        console.log(hitCount);
        ctx.fillText("points : " + hitCount, 32, 32);
         this.changeImage = true;
          _this.speed = 3;
        this.changeImageTime = Date.now() + 600; //0.5 sec from now.

        this.image = (this.image == GameImage.getImage("hero"))? GameImage.getImage("hero_other") : GameImage.getImage("hero");

      }

      if(this.changeImage){
      if(Date.now() > this.changeImageTime){
        this.changeImage = false;
        _this.speed = 9;
        this.image = (this.image == GameImage.getImage("hero_other"))? GameImage.getImage("hero") : GameImage.getImage("hero_other");
      }
    }


    };
    return Car;
  }(Actor));

但是我想跟随一条路径。我还创建了一些网格,当你单击它记录控制台它是哪个网格的图像时。但我无法在路径中移动汽车。为了完全理解动画是在 animation.

感谢任何帮助

【问题讨论】:

  • 你拥有大部分你想要的东西。但与其从一个点移动到另一个点,不如创建一组沿您想要遵循的路径的航点。从第一个开始,然后移动到第二个,当你到达那里时,让它成为第一个点,然后移动到下一个点。以此类推,直到你到达终点。
  • 是的,你是完全正确的。正如你所说,我需要创建航点,这对我来说是一个非常棘手的部分。如果你不介意你能提供一个工作示例

标签: javascript jquery html canvas


【解决方案1】:

作为队列的航点。

对于航路点路径,您使用一种称为队列的数组。顾名思义,队列包含需要使用的项目,特别是它们需要按照它们到达的顺序使用。队列中的第一个对象是第一个出来的对象(除非你推入队列)

在 javascript 中,队列很容易使用数组来实现。

const path = {
    points : [],
    currentPos : null,
    dist : 0,
    totalDistMoved : 0,
    atEnd : false,
    addPoint(x,y) { 
        if(this.currentPos === null){ 
           this.currentPos = { x :0,y : 0};
           this.dist = 0; 
           this.totalDistMoved = 0;
        }
        this.points.push({x,y}) ;
    },
    moveAlong(dist){
        if(dist > 0){
           if(this.points.length > 1){ 
              var x = this.points[1].x - this.points[0].x;
              var y = this.points[1].y - this.points[0].y;
              var len = Math.sqrt(x*x+y*y) ;
              if(len - this.dist < dist){  
                 this.points.shift(); 
                 dist -= (len - this.dist);
                 this.totalDistMoved += (len - this.dist);
                 this.dist = 0; 
                 this.moveAlong(dist); 
                 return;
              }
              const frac =  this.dist + dist / len;
              this.currentPos.x = this.points[0].x + x * frac;
              this.currentPos.y = this.points[0].y + y * frac;
              this.dist += dist;
              this.totalDistMoved += dist;
          }else{
              this.currentPos.x = this.points[0].x;
              this.currentPos.y = this.points[0].y;
              this.dist = 0;
              this.atEnd = true;
          }
        }
     }
  }

使用

添加一些路点。

path.addPoint(1,1);
path.addPoint(100,20);
path.addPoint(110,120);
path.addPoint(210,120);
path.addPoint(250,420);

然后为动画的每一步获取一段距离

 path.moveAlong(10); // move ten pixels

并使用当前位置

 ctx.drawImage(car,path.currentPos.x,path.currentPos.y);

你知道你什么时候到达了路径的尽头。

  if(path.atEnd) {
        // you have arrived
  }

而且在任何时候你都知道你已经走了多远

  path.totalDistMoved       

这适用于仅向前播放的动画。它会忽略负距离,因为当您通过它们时会丢弃路径点

如果您希望重用路径对象,或者正在添加航路点,则需要进行一些修改

一个简单的例子。

事物以恒定的速度移动。点击页面添加更多航点。

const ctx = canvas.getContext("2d");
requestAnimationFrame(mainLoop);
function mainLoop(time){
    gTime = !gTime ? time : gTime;
    fTime = time - gTime;
    gTime = time;
    if(canvas.width !== innerWidth || canvas.height !== innerHeight){
        canvas.width = innerWidth;
        canvas.height = innerHeight;
    }else{
        ctx.setTransform(1,0,0,1,0,0);
        ctx.clearRect(0,0,canvas.width,canvas.height);
    }
    if(mouse.button){
        if(!point){
            point = {x:0,y:0};
            path.addPoint(point);
        }
        point.x = mouse.x;
        point.y = mouse.y;

    }else{ 
         if(point){ point = null }
    }
    
    ctx.beginPath();
    var i = 0;
    while(i < path.points.length){ ctx.lineTo(path.points[i].x,path.points[i++].y)}
    ctx.strokeStyle = "blue";
    ctx.lineWidth = 2;
    ctx.stroke();
    
    var i = 0;
    while(i < path.points.length){ ctx.strokeRect(path.points[i].x-4,path.points[i++].y-4,8,8)}
    
    path.moveAlong(4 * fTime / 100);
    var x = path.currentPos.x - thingPos.x;
    var y = path.currentPos.y - thingPos.y;
    thingPos.x = path.currentPos.x;
    thingPos.y = path.currentPos.y;
    drawThing(thingPos.x,thingPos.y,Math.atan2(y,x));


    requestAnimationFrame(mainLoop);
}
var point;
const thingPos = {x:0,y:0};
const path = {
  points : [],
  currentPos : null,
  distAlong : 0,
  totalDistMoved : 0,
  atEnd : false,
  addPoint(x,y) { 
      if(y === undefined){
         this.points.push(x); // add point as object
         return;
      }
      if(this.currentPos === null){ 
         this.currentPos = { x :0,y : 0};
         this.distAlong = 0; 
         this.totalDistMoved = 0;
      }
      
      this.points.push({x,y}) ;
  },
  moveAlong(dist){
      if(dist > 0){
         if(this.points.length > 1){ 
            var x = this.points[1].x - this.points[0].x;
            var y = this.points[1].y - this.points[0].y;
            var len = Math.sqrt(x*x+y*y) ;
            if(len - this.distAlong < dist){  
               this.points.shift(); 
               dist -= (len - this.distAlong);
               this.totalDistMoved += (len - this.distAlong);
               this.distAlong = 0; 
               this.moveAlong(dist); 
               return;
            }
            const frac =  (this.distAlong + dist) / len;
            this.currentPos.x = this.points[0].x + x * frac;
            this.currentPos.y = this.points[0].y + y * frac;
            this.distAlong += dist;
            this.totalDistMoved += dist;
        }else{
            this.currentPos.x = this.points[0].x;
            this.currentPos.y = this.points[0].y;
            this.distAlong = 0;
            this.atEnd = true;
        }
      }
   }
}

path.addPoint(20,20);
path.addPoint(120,20);
path.addPoint(220,120);
path.addPoint(320,120);
path.addPoint(420,20);

function mouseEvents(e) {
    const m = mouse;
    m.x = e.pageX;
    m.y = e.pageY;
    m.button = e.type === "mousemove" ? m.button : e.type === "mousedown";
}
function drawThing(x,y,dir) {
    ctx.setTransform(1,0,0,1,x,y);
    ctx.rotate(dir);
    ctx.fillStyle = "red";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 2;
    ctx.beginPath();
    var i = 0;
    while(i < thing.length){ ctx.lineTo(thing[i++],thing[i++]) };
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
  
}
const thing = [-20,-10,20,-10,22,-7,22,7,20,10,-20,10];
var gTime;  // global and frame time
var fTime;
const mouse = { x:0,y:0,button:false};
["mousemove","mousedown","mouseup"].forEach(t=>document.addEventListener(t,mouseEvents));
canvas {
position: absolute;
top : 0px;
left : 0px;
}
<canvas id="canvas"></canvas>
click drag to add waypoints.

【讨论】:

  • 非常感谢您的详细解释。我得到了航点的想法。所以在我的场景中,我应该动态生成汽车和目标之间的航点。但这不是由寻路处理的算法
  • @Ricky 路径查找算法是独立的,它会将路点添加到路径/路点对象。寻路功能可以很简单也可以很复杂,并且非常依赖于您使用的地图/环境类型。
  • 所以在我的情况下,我需要一个正确的寻路算法。因为否则我怎么能随机添加路径点到路径
  • 如果你不介意可以帮我做个动画吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
相关资源
最近更新 更多