Как рандомизировать скорость вращения круга? - PullRequest
0 голосов
/ 01 октября 2018

У меня есть два круга, вращающихся вокруг круга, и я хотел бы, чтобы круг менял скорость случайным образом после прохождения одного оборота. Обе круги должны быть с разной скоростью, или они могут иметь одинаковую скорость (тогда произойдет столкновение).Например, во время первого пробега оба круга движутся со скоростью 10 м / с, и после того, как он достигнет конца оборота, они столкнутся. Допустим, после оборота он меняет окружность от 1 до 15 м / с и окружность от 2 до 30 м / с,тогда они не столкнутся. Я хотел бы знать, как этого добиться.Это просто идея того, чего я пытаюсь достичь.Было бы еще лучше, если бы скорость менялась после каждого оборота.

Буду признателен за любую помощь.

Код:

(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 голосов
/ 01 октября 2018

Давайте немного переделаем:

Во-первых, при программировании графической анимации вы должны разделить логику объектов и операции рисования.

Операции рисования должны выполняться через равные промежутки времени на основена частоте обновления экрана (чтобы не рисовать иногда дважды кадр, а иногда вообще не рисовать).

Для этого точного случая в 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>
0 голосов
/ 01 октября 2018

Вы можете изменить timeGap, когда angle станет 360, т.е. когда революция завершится.Таким образом, оно будет отображаться при изменении скорости.

Внутри вашей функции 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>
0 голосов
/ 01 октября 2018

(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>

Попробуйте это.

0 голосов
/ 01 октября 2018

Что вы можете сделать, это объявить локальную переменную speed для функции draw(), а затем передать ее обратному вызову setTimeout(), например:

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

Код Math.floor(Math.random() * 11)даст вам случайное число от 0 до 10, поэтому 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>
...