如何让汽车在路上行驶

时间:2017-06-24 03:24:41

标签: javascript jquery html5 canvas

我正在开发一个javascript中的动画,其中一辆车向一个人移动并且选择但是当前而不是一条路径,我只是对着以下代码的人对角驾驶。

django_cron

但是我想要遵循一条道路。我也创建了一些网格,当你点击它记录控制台的图像时它是一个网格。但我无法在一条路径中移动汽车。为了完全理解动画是在 animation

感谢任何帮助

1 个答案:

答案 0 :(得分: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       

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

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

一个简单的例子。

东西以恒定速度移动。点击页面可添加更多航点。

&#13;
&#13;
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));
&#13;
canvas {
position: absolute;
top : 0px;
left : 0px;
}
&#13;
<canvas id="canvas"></canvas>
click drag to add waypoints.
&#13;
&#13;
&#13;