如何随机化旋转圆的速度?

时间:2018-10-01 07:02:38

标签: javascript html random settimeout

我有两个圆圈旋转,我希望圆圈在旋转一圈后随机改变速度,两个圆圈的速度或速度可能相同(否则会发生碰撞)。例如,在第一次运行时,两个圆都以10m / s的速度运动,到达旋转结束后它们将发生碰撞。假设旋转后,它将圆1更改为15m / s,将圆2更改为30m / s,这样他们就不会发生冲突。我想知道如何实现这一目标。这只是我要实现的目标的一个想法。如果每转一圈后随机分配速度,那会更好。

任何帮助将不胜感激。

代码:

(function() {
  var ctx = document.getElementById("canvas").getContext("2d"),
    x1 = 160,
    y1 = 120,
    x2 = 330,
    y2 = 280,
    radius = 20;
  angle = 0,
    velX = 0,
    velY = 0,
    thrust = 3,
    rotation = 0;

  function draw() {
    velX = Math.cos(angle * Math.PI / 180) * thrust;
    velY = Math.sin(angle * Math.PI / 180) * thrust;
    x1 += velX;
    y1 += velY;
    angle += 1;
    ctx.fillStyle = "#000";
    ctx.clearRect(0, 0, 550, 400);
    ctx.beginPath();
    ctx.arc(x1, y1, radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    draw2();
    setTimeout(function() {
      draw()
    }, 30);
  }

  function draw2() {
    velX = Math.cos(angle * Math.PI / 180) * thrust;
    velY = Math.sin(angle * Math.PI / 180) * thrust;
    x2 += -velX;
    y2 += -velY;
    angle += 1;
    ctx.fillStyle = "#80ced6";
    ctx.beginPath();
    ctx.arc(x2, y2, radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    collisiondetection();
  }

  var distance = 0;
  var totalcounter = 0;
  var collide = false;

  function collisiondetection() {
    distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

    if (distance < radius * 2) {
      if (collide == false) {
        totalcounter = totalcounter + 1;
        document.getElementById("cTotal").innerHTML = "Total collisions:" + totalcounter;
        collide = true;
      }

    } else {
      collide = false;
    }

  }
  draw();
})();
<canvas id="canvas" width="550" height="400" style="background:#eee;"></canvas>
<span id="cTotal">Total collisions: </span>

4 个答案:

答案 0 :(得分:1)

您可以做的是为speed函数声明一个本地draw()变量,然后将其传递给setTimeout()回调,如下所示:

var speed = Math.floor(Math.random() * 11);
draw2();
setTimeout(function() {
    draw()
}, speed);

代码Math.floor(Math.random() * 11)将为您提供一个介于010之间的随机数,因此每次setTimeout都会以不同的速度被调用。

演示:

window.onload = function() {
  (function() {
    var ctx = document.getElementById("canvas").getContext("2d"),
      x1 = 160,
      y1 = 120,
      x2 = 330,
      y2 = 280,
      radius = 20;
    angle = 0,
      velX = 0,
      velY = 0,
      thrust = 3,
      rotation = 0;

    function draw() {
      velX = Math.cos(angle * Math.PI / 180) * thrust;
      velY = Math.sin(angle * Math.PI / 180) * thrust;
      x1 += velX;
      y1 += velY;
      angle += 1;
      ctx.fillStyle = "#000";
      ctx.clearRect(0, 0, 550, 400);
      ctx.beginPath();
      ctx.arc(x1, y1, radius, 0, Math.PI * 2);
      ctx.closePath();
      ctx.fill();

      var speed = Math.floor(Math.random() * 11);
      draw2();
      setTimeout(function() {
        draw()
      }, speed);
    }

    function draw2() {
      velX = Math.cos(angle * Math.PI / 180) * thrust;
      velY = Math.sin(angle * Math.PI / 180) * thrust;
      x2 += -velX;
      y2 += -velY;
      angle += 1;
      ctx.fillStyle = "#80ced6";
      ctx.beginPath();
      ctx.arc(x2, y2, radius, 0, Math.PI * 2);
      ctx.closePath();
      ctx.fill();

      collisiondetection();
    }

    var distance = 0;
    var totalcounter = 0;
    var collide = false;

    function collisiondetection() {
      distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

      if (distance < radius * 2) {
        if (collide == false) {
          totalcounter = totalcounter + 1;
          document.getElementById("cTotal").innerHTML = "Total collisions:" + totalcounter;
          collide = true;
        }

      } else {
        collide = false;
      }

    }
    draw();
  })();
}
<canvas id="canvas" width="550" height="400" style="background:#eee;"></canvas>
<span id="cTotal">Total collisions: </span>

答案 1 :(得分:0)

您可以在timeGap变为360,即旋转完成时更改angle。因此,它将随着速度的改变而出现。

draw()函数内部:

if(angle % 360 == 0) {
    timeGap = Math.random() * 20 + 5;
}

(function() {
  var ctx = document.getElementById("canvas").getContext("2d"),
    x1 = 160,
    y1 = 120,
    x2 = 330,
    y2 = 280,
    radius = 20,
    angle1 = 0,
    angle2 = 0,
    velX = 0,
    velY = 0,
    thrust = 3,
    rotation = 0,
    timeGap1 = 10,
    timeGap2 = 10,
    diff = 20,
    minTimeGap = 20;

  function draw() {
    velX = Math.cos(angle1 * Math.PI / 180) * thrust;
    velY = Math.sin(angle1 * Math.PI / 180) * thrust;
    x1 += velX;
    y1 += velY;
    angle1 += 2;
    ctx.fillStyle = "#000";
    ctx.beginPath();
    ctx.arc(x1, y1, radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();
    
    if(angle1 % 360 == 0) {
        timeGap1 = Math.random() * diff + minTimeGap;
    }
    
    setTimeout(function() {
      draw();
    }, timeGap1);
  }

  function draw2() {
    velX = Math.cos(angle2 * Math.PI / 180) * thrust;
    velY = Math.sin(angle2 * Math.PI / 180) * thrust;
    x2 += -velX;
    y2 += -velY;
    angle2 += 2;
    ctx.fillStyle = "#007700";
    ctx.beginPath();
    ctx.arc(x2, y2, radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    if(angle2 % 360 == 0) {
        timeGap2 = Math.random() * diff + minTimeGap;
    }    
    
    setTimeout(function() {
      draw2();
    }, timeGap2);
  }
  
  function clearCanvas() {
  	ctx.fillStyle = 'rgba(220,220,220,0.5)';
    ctx.fillRect(0, 0, 550, 400);
    collisiondetection();
    
    setTimeout(function() {
      clearCanvas();
    }, timeGap2 + timeGap1);
  }

  var distance = 0;
  var totalcounter = 0;
  var collide = false;

  function collisiondetection() {
    distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

    if (distance < radius * 2) {
      if (collide == false) {
        totalcounter = totalcounter + 1;
        document.getElementById("cTotal").innerHTML = "Total collisions:" + totalcounter + "<br/>Speed1: " + timeGap1 + "<br/>Speed2: " + timeGap2;
        collide = true;        
      }

    } else {
      collide = false;
    }
  }
  draw();
  draw2();
  clearCanvas();
})();
<canvas id="canvas" width="550" height="400" style="background:#eee;"></canvas>
<span id="cTotal">Total collisions: </span>

答案 2 :(得分:-1)

(function() {
  var ctx = document.getElementById("canvas").getContext("2d"),
    x1 = 160,
    y1 = 120,
    x2 = 330,
    y2 = 280,
    radius = 20;
  angle = 0,
    velX = 0,
    velY = 0,
    thrust = 3,
    rotation = 0,  
    maxSpeed = 100,      
    speed = Math.floor(Math.random() * 100) + 1;

  function draw() {
    velX = Math.cos(angle * Math.PI / 180) * thrust;
    velY = Math.sin(angle * Math.PI / 180) * thrust;
    x1 += velX;
    y1 += velY;
    angle += 1;
    ctx.fillStyle = "#000";
    ctx.clearRect(0, 0, 550, 400);
    ctx.beginPath();
    ctx.arc(x1, y1, radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    draw2();
    SpeedCount();
  }

  function draw2() {
    velX = Math.cos(angle * Math.PI / 180) * thrust;
    velY = Math.sin(angle * Math.PI / 180) * thrust;
    x2 += -velX;
    y2 += -velY;
    angle += 1;
    ctx.fillStyle = "#80ced6";
    ctx.beginPath();
    ctx.arc(x2, y2, radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    collisiondetection();
  }
  
  function SpeedCount(){
  (function(speed) {
  setTimeout(function() {
      draw()
    }, speed);
  })(speed);
}


  var distance = 0;
  var totalcounter = 0;
  var collide = false;

  function collisiondetection() {
    distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

    if (distance < radius * 2) {
      if (collide == false) {
        totalcounter = totalcounter + 1;
        document.getElementById("cTotal").innerHTML = "Total collisions:" + totalcounter;
        collide = true;
      }

    } else {
      collide = false;
    }
    
    if((angle + 90) % 360 == 0){   
         speed = Math.floor(Math.random() * maxSpeed) + 1;
    }

  }
  draw();
})();
<canvas id="canvas" width="550" height="400" style="background:#eee;"></canvas>
<span id="cTotal">Total collisions: </span>

尝试这个。

答案 3 :(得分:-1)

让我们稍作修改:

首先,在对图形动画进行编程时,应将对象逻辑和绘图操作分开。

绘制操作应该根据屏幕刷新率有规律地进行(以避免有时绘制两次,有时根本不绘制)。

对于这种确切情况,Web API中提供的一种便捷方法是requestAnimationFrame(callback)。它将使我们的回调在下一个屏幕刷新率之前触发。
因此,我们可以将其用作动画循环的核心,始终以与屏幕显示相同的速率(通常为60FPS)触发。

当场景中有动画对象时,js中最简单的数据结构就是对象。您不必将变量放在各处,而是将它们打包在自己的对象中。
当您有多个此类对象时,可以将它们全部放在一起(例如在数组中)。

现在,在动画循环中,我们将首先更新对象的位置,然后绘制它们。
在更新部分中,我们将控制对象的速度,只有在更新完所有对象之后,我们才会检查它们是否发生碰撞。

(function() {
  var ctx = document.getElementById("canvas").getContext("2d"),

    max_speed = Math.PI / 12,
    objects = [{
        center_x: 160,
        center_y: 120,
        speed: Math.random() % max_speed,
        angle: 0,
        color: '#000'
      },
      {
        center_x: 330,
        center_y: 280,
        speed: -(Math.random() % max_speed),
        angle: 0,
        color: "#80ced6"
      }
    ],
    radius = 20,
    outerRad = 120,
    totalcounter = 0,
    collide = true;

  anim(); // begin our main anim loop

  function anim() {
    update(); // our objects update logic
    draw(); // now we draw
    collisiondetection(); // DOM update
    requestAnimationFrame(anim); // start again @next-frame
  }


  function update() {
    // here we only change the object's properties
    // nothing graphical should come here
    objects.forEach(function(object) {
      var angle = object.angle;
      object.x = Math.cos(angle) * outerRad + object.center_x;
      object.y = Math.sin(angle) * outerRad + object.center_y;
      object.angle += object.speed;
    });
  }

  function draw() {
    // here is only the graphical part
    // no logic should come here
    ctx.clearRect(0, 0, 550, 400);
    objects.forEach(function(object) {
      ctx.fillStyle = object.color;
      ctx.beginPath();
      ctx.arc(object.x, object.y, radius, 0, Math.PI * 2);
      ctx.fill();
    });
  }

  function collisiondetection() {
    var o1 = objects[0],
      o2 = objects[1];
    var distance = Math.sqrt((o1.x - o2.x) * (o1.x - o2.x) + (o1.y - o2.y) * (o1.y - o2.y));

    if (distance < radius * 2) {
      if (collide == false) {
        totalcounter = totalcounter + 1;
        document.getElementById("cTotal").innerHTML = "Total collisions:" + totalcounter;
        collide = true;
      }

    } else {
      collide = false;
    }

  }

  // and now if you want to update randomly these object's speed, you can do from anywhere
  document.onclick = function() {
    objects[0].speed = Math.random() % max_speed;
    objects[1].speed = -(Math.random() % max_speed);
  };

})();
<canvas id="canvas" width="550" height="400" style="background:#eee;"></canvas>
<p id="cTotal">Total collisions: </p>