使用canvas

时间:2017-08-23 11:48:56

标签: javascript canvas html5-canvas

这是我第一次使用canvas,并且我第一次使用Javascript来制作完整的游戏类型的东西,所以请原谅初学者的混乱!

我正试图制作一种圆形Flappy Bird类型的东西,你围绕一个圆圈旅行,以某种引力方式画入圆圈,点击让你起来。太高了,你死了,太低,你死了。但是,我在第一个障碍中摔倒......

我现在遇到的两个主要问题,从最小的问题开始,是.clearRect函数。我现在在球移动时模糊地清理球,但这有点不完美,如果距离太近则切入中间圈。如果我将整个窗口设置为每个框架都清晰,那么一切都会闪烁;有更好的方法吗?

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

在dx和dy变量中,' sun'代表我试图让行星绕轨道运行的圆圈的中点。变量的其余部分基于我在其他地方找到的一个答案,但我还没有设法让它工作。



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);
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

好的,所以

首先:

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

第二名:

要为球设置动画,你想获得当前时间并决定你想要它的速度(以转/秒为单位)。正如其他人所建议的那样,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>

答案 1 :(得分:0)

使用requestAnimationFrame()而不是设置的间隔,之后你不应该闪烁,半圆的等式是y =±√(r ^ 2-x ^ 2) 使用变量来确定它应该是正数还是负数,并更改每个绘制的轨道运行对象的x变量以将其移动到圆圈中