javascript - 使用 Canvas 在 Javascript 中做一个圆圈旅行

标签 javascript canvas html5-canvas

我是第一次用canvass,也是第一次用javascript做一个游戏类的东西,初学者的困惑还请见谅!

我正在尝试制作一种圆形的 Flappy Bird 类型的东西,你绕着一个圆圈移动,以一种类似重力的方式被吸引到圆圈中,点击让你升起。太高会死,太低也会死。然而,我在第一个障碍上就倒下了……

我现在遇到的两个主要问题是 .clearRect 函数,从最小的开始。我目前让它在球移动时模糊地在球后方清理,但这有点不完美,如果它离得太近就会切入中间的圆圈。如果我将整个窗口设置为清除每一帧,一切都会可怕地闪烁;有更好的方法吗?

第二个问题就是让球转一圈……我已经尝试了很多解决方案,我知道这很可能是我数学技能的一个巨大失败,但我做不到它完全围绕主圆运行。我可以让它移动,我已经让它从墙上弹开,这样我至少可以看到它在做什么,但它只是没有盘旋。我想如果我遇到同样的困难,我会在未来的某个时候询问这款游戏的其他方面,但是,正如我所说,我正在努力学习!

在 dx 和 dy 变量中,“太阳”代表我试图让行星围绕其运行的圆的中点。变量的其余部分基于我在其他地方找到的一个答案,但我也没有设法让它发挥作用。

var canvas = document.createElement("canvas"),
      context = canvas.getContext("2d"),
      sun = 300,
      sunRadius = sun / 2,    
      x = sun +110,
      y = sun -110,
        
      angle = 0,
      distance = 10,
      dx = sun + sunRadius * Math.cos(angle*Math.PI/180),
      dy = sun + sunRadius * Math.sin(angle*Math.PI/180),  
    
      planetRadius = 10;
    
    
    
    document.body.appendChild(canvas);
    canvas.width = canvas.height = sun * 2;
    
    function makeSun() {
      context.beginPath();
      context.strokeStyle = "yellow";
      context.arc(sun, sun, 60, 0, 2 * Math.PI);
      context.fillStyle = "yellow";
      context.fill();
      context.closePath();
    }
    
    function makePlanet() {
      context.beginPath();
      context.arc(x, y, planetRadius, 0, Math.PI * 2);
      context.fillStyle = "green";
      context.fill();
      context.strokeStyle = "green";
      context.stroke();
    }
    
    function draw() {
      context.clearRect(x + -20, y - 15, 40, 40);
      makePlanet();
      
       
       if (x + dx > canvas.width - planetRadius || x + dx < planetRadius) {
        dx = -dx;
      }
      if (y + dy > canvas.height - planetRadius || y + dy < planetRadius) {
        dy = -dy;
      }
      
    x += dx;
    y += dy;
    }
    
    
    setInterval(makeSun, 10);
    setInterval(draw, 10);

最佳答案

好吧

首先:

屏幕闪烁是因为您正在为 makesun 和 draw 设置两个不同的间隔。 javascript 零 promise 它不会在调用 makesun 和绘制之间更新屏幕。我认为最好的解决方案是有效地清除整个矩形然后重新绘制你的太阳(图形足够简单所以你不会有性能问题)。

第二个:

要为球制作动画,您需要获取当前时间并确定您希望它移动多快(以旋转/秒为单位)。正如其他人所建议的那样,requestAnimationFrame 比 setInterval 更好,因为它传递给您一个时间戳。

例子

我已经调整了您的代码,使地球旋转。我还为太阳添加了运动,所以你会看到行星实际上是相对于它的。看看吧,有不懂的地方请教。

const canvas = document.createElement("canvas"),
      context = canvas.getContext("2d"),
      checkbox = document.getElementById("moveSunBx"),
      sun = 300,
      sunRadius = sun / 2,
      controllables = {
        movesun : false,
        rotationspeed : 1/2 // half a turn every second (timestamps are in milliseconds)
      },

      distancePtoS = 110,//distance from planet to sun
      planetRadius = 10;

var   planetAngle = 0.0,// Starting angles
      sunAngle = 0.0,
      lastTimestamp;


var gui = new dat.GUI();
gui.add(controllables, 'movesun').name("move sun");
gui.add(controllables, 'rotationspeed', -6, 6).name("planet speed");// in turns per second

function makeSun(x, y) {
  context.beginPath();
  context.strokeStyle = "yellow";
  context.arc(x, y, 60, 0, 2 * Math.PI);
  context.fillStyle = "yellow";
  context.fill();
  context.closePath();
}

function makePlanet(x, y) {
  context.beginPath();
  context.arc(x, y, planetRadius, 0, Math.PI * 2);
  context.fillStyle = "green";
  context.fill();
  context.strokeStyle = "green";
  context.stroke();
}
    
function draw(timestamp) {
  requestAnimationFrame(draw);//immediately ask for next frame
  
  if(!lastTimestamp){
    lastTimestamp = timestamp;
    return;
  }
  

  var speed = Math.PI * 2.0 * controllables.rotationspeed / 1000, // convert speed from turns per second to radian per millisec 
      timestep = timestamp - lastTimestamp;
      
  lastTimestamp = timestamp;//we save the stamp

  planetAngle += timestep * speed;//we update the angle depending on the currentspeed and the timestep

  //angle = angle % Math.PI / 2;// this is for better comprehension, Math.cos and sin do the clamping for us
debugger;
  //let's make the sun move!!!
  if(controllables.movesun){
    sunAngle += timestep * speed;
  }
  var sunx = sunRadius + Math.cos(sunAngle /2) * distancePtoS;// <- sin of 2 angle gives a beautiful infinity
  var suny = sunRadius + Math.sin(sunAngle) * distancePtoS / 2;


  //x and y don't need to be kept, I made them local to draw()
  var planetx = sunx + Math.cos(planetAngle) * distancePtoS;
  var planety = suny + Math.sin(planetAngle) * distancePtoS;

  context.clearRect(0, 0, canvas.width, canvas.height);
  makeSun(sunx, suny);
  makePlanet(planetx, planety);
}
    
document.body.appendChild(canvas);
canvas.width = canvas.height = sun * 2;
    
draw();//we start the cycle
<script src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>

关于javascript - 使用 Canvas 在 Javascript 中做一个圆圈旅行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45838912/

相关文章:

javascript - Webgl 未捕获引用错误 : createShaderFromScriptElement is not defined

javascript - HTML5 Canvas toDataURL 返回空白

javascript - 删除数组中的特定元素

javascript - Croppie 有时会得到 No 'Acces-Control-Allow-Origin',有时不会

javascript - 遍历 Canvas 中的颜色

jquery - 如何使用CSS3、HTML5、SVG、Jquery制作不规则曲线?

php - 为 Javascript 对象动态添加值和排序

javascript - Algolia Search api 最多返回 1000 条记录,而我的总记录约为 50000 条

javascript - 在 Canvas 上绘制视频 HTML5

javascript - Canvas - 元素在 ThresholdFilter 后消失