【问题标题】:Gravity / Jumping ball in canvas, javascript重力/画布中的跳球,javascript
【发布时间】:2015-04-05 14:42:24
【问题描述】:

我的项目是创建一个游戏,球应该在按键上跳跃,左右移动。我的问题是,我在该游戏中实施的重力给我带来了问题。球卡在地上,这是我画布底部的图片。我猜是因为错误的碰撞代码而卡住了。

问题是,如果您能帮助我解决这个问题,或许可以提示如何继续,因为我试图找出导致该问题的碰撞,但我一无所获。

该游戏的链接在这里:Game JSFiddle:Fiddle

玩家碰撞所在的代码/其他代码正在正常工作,所以我不会把它们放在这里,只有当你真的需要它们时/

       function Player(x, y) {
     var size = 70;
      GameObject.call(this, x, y, size);
      this.img = document.getElementById("lopta");
      this.rotation = 0;
      this.dx = Math.random() * 50 - 25;
      this.dy = Math.random() * 50 - 25;

}

// Dedi vlastnosti z GameObject
Player.prototype = Object.create(GameObject.prototype);

Player.prototype.move = function(dt) {

    var x = this.x;
    var y = this.y;

    var sirka = canvas.width;
    var vyska = canvas.height;
    var bounce = 0.6;
 // Gravitacia
    this.dy += 9.8 * dt;

    // Posun
    if ( keys[37] ) {
        this.rotation -= dt;
        x-=5;
    }
    if ( keys[39] ) {
        this.rotation += dt;
        x+=5;
    }
    if ( keys[38] ) y-=5;
    if ( keys[40] ) y+=5;


        // Test novej pozicie
    var collision = false;
    for (i in scene) {
      var obj = scene[i];
      var test = 

                x -35>= obj.x + obj.size || 
                x + this.size -35<= obj.x || 
                y -35>= obj.y + obj.size ||
                this.dy - 35 >= obj.dy + obj.size || 
                y + this.size -35 <= obj.y ||
                this.dy + this.size -35<= obj.dy; 
      if (!test) {
        collision = true;
        break;
      }
    }
    // Posun bez kolizie
    if (!collision) {
      this.x = x;
      this.y = y;
    }
    // Posun
      //this.x += this.dx * dt;
    this.y += this.dy * dt;


    // podmienky aby lopta nevysla z hracieho pola cize z canvasu
    if (this.x + this.size - 35> canvas.width) {
        this.x  = canvas.width - this.size +35;

      }
      if (this.x -35 < 0) {
        this.x = 35;
      }

      if (this.y+this.size - 35 > canvas.height) {
        this.y = canvas.height - this.size + 35;

        this.dy *= -bounce;
        if(this.dy * (-bounce)  <   4)
            this.dy = 0;
      }
      if (this.y - 35< 0) {
        this.y = 35;    
      };


};

Player.prototype.draw = function() {
    ctx.save();
    ctx.translate(this.x, this.y);
    ctx.rotate(this.rotation);
    ctx.translate(-35, -35);
    //ctx.scale(this.size,this.size);
    ctx.drawImage(this.img, 0, 0, this.size, this.size);
    ctx.restore();

    };

【问题讨论】:

  • 如果你创建一个有效的jsfiddle.net,它会有所帮助。
  • 我试过了,但是有更多文件,我不知道如何将它们全部添加到一起,所以它会起作用。
  • 左边有外部资源选项,也可以hack the CSS pane
  • 用外部资源更新,见上文:)

标签: javascript html canvas gravity


【解决方案1】:

首先,请原谅我没有完全理解您的要求。

如果您在检测球与砖块或球与墙之间的碰撞时遇到问题,以下是一些有用的实用功能:

// Given circle & rect definitions
var circle={x:50,y:50,r:25};
var rect={x:125,y:125,w:50,h:50};


// detect if circle & rect are colliding
function RectCircleColliding(circle,rect){
    var distX = Math.abs(circle.x - rect.x-rect.w/2);
    var distY = Math.abs(circle.y - rect.y-rect.h/2);
    if (distX > (rect.w/2 + circle.r)) { return false; }
    if (distY > (rect.h/2 + circle.r)) { return false; }
    if (distX <= (rect.w/2)) { return true; } 
    if (distY <= (rect.h/2)) { return true; }
    var dx=distX-rect.w/2;
    var dy=distY-rect.h/2;
    return (dx*dx+dy*dy<=(circle.r*circle.r));
}

// detect if circle is colliding with canvas sides
function CircleWallColliding(circle){
    var cx=circle.x;
    var cy=circle.y;
    var r=circle.r;
    if(cx-r<0 || cx+r>canvas.width || cy-r<0 || cy+r>canvas.height){return(true);}
    return(false);
}

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

ctx.lineWidth=3;

var isDown=false;
var startX,startY;

var circle={x:50,y:50,r:25};
var rect={x:125,y:125,w:50,h:50};

$("#canvas").mousemove(function(e){handleMouseMove(e);});

draw('green');

function draw(circleFill){
  ctx.clearRect(0,0,cw,ch);

  ctx.fillStyle='blue';
  ctx.fillRect(rect.x,rect.y,rect.w,rect.h);

  ctx.beginPath();
  ctx.arc(circle.x,circle.y,circle.r,0,Math.PI*2);
  ctx.closePath();
  ctx.fillStyle=circleFill;
  ctx.fill();
  ctx.stroke();
}


function handleMouseMove(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  circle.x=mouseX;
  circle.y=mouseY;

  var isColliding=RectCircleColliding(circle,rect)||CircleWallColliding(circle);
  draw(isColliding?'red':'green');

}

// detect if circle & rect are colliding
function RectCircleColliding(circle,rect){
  var distX = Math.abs(circle.x - rect.x-rect.w/2);
  var distY = Math.abs(circle.y - rect.y-rect.h/2);
  if (distX > (rect.w/2 + circle.r)) { return false; }
  if (distY > (rect.h/2 + circle.r)) { return false; }
  if (distX <= (rect.w/2)) { return true; } 
  if (distY <= (rect.h/2)) { return true; }
  var dx=distX-rect.w/2;
  var dy=distY-rect.h/2;
  return (dx*dx+dy*dy<=(circle.r*circle.r));
}

// detect if circle is colliding with canvas sides
function CircleWallColliding(circle){
  var cx=circle.x;
  var cy=circle.y;
  var r=circle.r;
  if(cx-r<0 || cx+r>canvas.width || cy-r<0 || cy+r>canvas.height){return(true);}
  return(false);
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move ball with mouse.<br>Ball turns red if colling with rect or wall.</h4>
<canvas id="canvas" width=300 height=300></canvas>

【讨论】:

    【解决方案2】:

    我注意到了一些事情。首先,您将碰撞运动逻辑与弹跳逻辑分开,因此球基本上可以直接穿过物体。据我所知,物体只会阻止手动移动。另外,上述手动移动忽略了dt,所以它的速度会随着帧率的变化而变化。

    无论如何,在collision = true; 行上设置的断点揭示了问题:场景的一个对象没有设置大小,这导致obj.x + obj.sizeobj.y + obj.size 返回NaN,这就像无穷大。实际上,您有几个这样的:它是草对象。

    所以这是你的选择:要么不让草成为场景的一部分(它不应该参与碰撞),而是更改渲染逻辑以使用与碰撞逻辑分开的对象数组(如会有意义),或者为草设置size = 0;

    【讨论】:

    • 谢谢,我正在考虑将碰撞运动与弹跳逻辑分开,但我不确定如何解决它,我只是 Javascript 的初学者。你介意我问你一些提示(在需要的地方用 cmets 编辑我的代码吗?)再次感谢。
    • 你需要的不是分离,而是融合。运动逻辑和碰撞应该结合起来。第一步是根据设置dxdy 的键更改您更改xy 的部分,因此键决定球的速度。
    • 下一步将是改变碰撞,因此如果球试图移动到一个物体中,它不会简单地停在原地,而是尝试做一些更智能的事情。例如,您可以在没有dx 因素的情况下重试移动。如果这仍然不起作用,请尝试反转 dy 并重试,以模拟任何对象的反弹。您应该按以下顺序尝试运动:Same dy, dx=0; dy=-dy, 相同的 dx; dy=-dy,dx=0。如果不起作用,让球保持静止。
    • 我确实将 x y 更改为 dx dy 但我不知道下一步该怎么做。我对使用 dx 和 dy 感到困惑。
    • 您发布的代码已经完成了一半。 this.y += this.dy*dt; 是正确的公式,但不包括碰撞。你需要的是x = this.x+this.dx*dt; y = this.y+this.dy*dt; if (!check_collision(x, y)) { this.x = x; this.y = y; }。然后,要检查可能的反弹,您可以添加else { y = this.y-this.dy*dt; if (!check_colllision(x, y)) { this.x = x; this.y = y; this.dy = - this.dy; }。然后,您可以添加一些额外的案例来检查x 方向的碰撞。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多