如何在 Javascript pong 游戏中正确地偏转球?

5
我用JavaScript写了一个简单的乒乓球游戏,但是有两个问题需要解决:
  1. 我不知道为什么球不会从电脑的球拍(代码中称为“playerB”)反弹。
  2. 当球从球拍上反弹时,如何增加一些随机性?目前游戏似乎非常重复。
请问如何解决这两个问题? Jsfiddle链接

HTML

<!DOCTYPE html>
<html>
<head>
  <title>Pong game</title>
  <script type="text/javascript" src="jquery-2.1.4.min.js"></script>
  <script type="text/javascript" src="js/pong.js"></script>
  <link rel="stylesheet" href="css/pong.css">
</head>
<body>
  <header>
    <p>
    Computer:<span id="scoreB"></span> Human:<span id="scoreA"></span>
    </p>
  </header>
  <div id="playground">
    <div id="ball"></div>
    <div id="playerA" class="paddle right"></div>
    <div id="playerB" class="paddle left"></div>
  </div>
</body>
</html>

CSS

html,body{
  margin: 0 atuo;
  height:100%;
}
#playground{
  position: relative;
  width:700px;
  height:400px;
  border: 1px solid grey;
  overflow:hidden;
}
#ball{
  position: absolute;
  background: #fbb;
  width:20px;
  height:20px;
  left:200px;
  top:100px;
  border-radius:10px;
}
.paddle{
  position: absolute;
  border:1px solid grey;
  width:10px;
  height:80px;
}
.left.paddle{
  left:0px;
  background-color: green;
}
.right.paddle{
  right:0px;
  background-color: blue;
}

Javascript

$(document).ready(function(){
  var values = {
    ball:{
      speed:5,
      x:50,
      y:50,
      directionX: 1,
      directionY: 1,
      radius: 10
    },
    playground:{
      width: parseInt($("#playground").width()),
      height: parseInt($("#playground").height())
    },
    playerA:{
      y:0,
      top: $("#playerA").offset().top,
      height: $("#playerA").height(),
      width: $("#playerA").width(),
      score:0
    },
    playerB:{
      y:0,
      top: $("#playerB").offset().top,
      height: $("#playerB").height(),
      width: $("#playerB").width(),
      score:0
    }
  };
  //collision detection
  function hitsTopBottom(){
    var y = values.ball.y;
    return y>values.playground.height-20 || y < 0;
  }
  function hitsRight(){
    return values.ball.x > values.playground.width-20;
  }
  function hitsLeft(){
    return values.ball.x < 0;
  }
  //ball hits playerA's paddle. Works properly but open to improvement
  function hitsPlayerA(){
    var ballX = values.ball.x;
    var ballY = values.ball.y;
    var playerAY = values.playerA.y;
    return ballY<=playerAY+values.playerA.height && ballY>playerAY && ballX>=700-values.playerA.width-values.ball.radius;
  }
  //ball hits playerB's paddle. Doesn't work at all
  function hitsPlayerB(){
    var ballX = values.ball.x;
    var ballY = values.ball.y;
    var playerBY = values.playerB.y;
    return ballY<=playerBY+values.playerB.height && ballY>=playerBY && ballX<=values.playerB.width-values.ball.radius;
  }
  //rendering the position of the ball
  function renderball(){
    $("#ball").css("left",values.ball.x);
    $("#ball").css("top",values.ball.y);
    $("#scoreB").text(values.playerB.score);
    $("#scoreA").text(values.playerA.score);
  }
  //moving ball
  function moveball(){
    if(hitsTopBottom()){
      values.ball.directionY *= -1;
    }
    if(hitsPlayerA()){
      values.ball.directionX *= -1;
    }
    if(hitsPlayerB()){
      values.ball.directionX = 1;
    }
    if(hitsRight()){
      values.ball.x = 200;
      values.ball.y = 200;
      values.playerB.score += 1;
    }
    if(hitsLeft()){
      values.ball.x = 200;
      values.ball.y = 200;
      values.playerA.score += 1;
    }
    values.ball.x += values.ball.speed*values.ball.directionX;
    values.ball.y += values.ball.speed*values.ball.directionY;
    renderball();
    var playerB_pos = values.ball.y - values.playerB.height/2;
    $("#playerB").css("top",playerB_pos);
  }
  //player movements
  $("#playground").mousemove(function(e){
    values.playerA.y = e.pageY-values.playerA.top-parseInt($("#playerA").height()/2);
    $("#playerA").css("top",values.playerA.y);
  });
  setInterval(moveball,1000/30);
});

1
关于“随机性”:我建议球拍的速度应该修改球的垂直速度。目前我认为你只是反转了水平速度,而垂直速度没有改变。 - Oriol
你可以考虑在http://codereview.stackexchange.com/上发布这个问题 :) - OddDev
1
@OddDev 这个问题在 Code Review 中被认为是离题的,因为这里的代码没有按预期工作,我们被要求修复它。 - Ethan Bierlein
@EthanBierlein 是的,我的意思是他应该额外在那里发布问题(当然要相应地进行调整)。 - OddDev
2个回答

2
球没有被电脑挡板弹开,因为它的位置没有被存储。在循环中设置values.playerB.y = playerB_pos将使其正确地弹开。然而,由于它与球的y位置相同,电脑永远不会输。为了纠正这个问题并增加一些随机性,我使用了jQuery的动画函数来在两点之间缓慢移动电脑挡板,并模拟动量:
 if(!isAnimating) {
    isAnimating = true;
    $("#playerB").animate({"top": playerB_pos}, {
      duration: (values.ball.speed*16),
      easing: "linear",
      step: function( now, fx ) {
        values.playerB.y = parseInt($("#playerB").offset().top - parseInt($("#playerA").height()));
      }, 
      complete: function() {
        isAnimating = false;
      }
    }); 
  }

你可以在这里看到它的实际应用:http://jsfiddle.net/yb290ow9/5/

1
你忘记编辑实际的playerB.y值(你只是改变了CSS):
var playerB_pos = values.ball.y - values.playerB.height/2;
values.playerB.y = playerB_pos; // Forgot this!
$("#playerB").css("top",playerB_pos);

工作的JSFiddle链接: http://jsfiddle.net/yb290ow9/6/

关于随机性: 你可以让球拍变得"有弹性": 不仅改变球的方向,还要改变球的速度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接