如何将球扔进杯子?

时间:2014-10-22 07:49:46

标签: javascript html css physics game-physics

我有一个球,一个杯子,以及代表投掷力棒的内外div的图像 当用户点击球时,电源条开始递增然后递减。当用户第二次点击球时,投掷力杆停止并且投球。

当我开始编码时,我意识到某些事情会变得非常复杂,尽管这个想法本身很简单。

例如,我希望球能够“反弹”,这意味着我不仅需要跟踪球的x和y坐标,还需要跟踪表示深度的z坐标。

当球落到弹跳时,z坐标会减小,并且球的图像应缩小尺寸,当它开始反弹时,它应该按比例放大,再次基于z坐标。如果z坐标在到达杯子时低于某个值,如果它是某个最佳位置则进入杯子,或者如果z值超过杯子,我还希望球从杯子上反弹那个甜蜜点。

为了保持这个简短的地方,我会发布到目前为止的内容。这个例子缺乏我希望这里的人可以帮助我的某些事情。

http://jsfiddle.net/7Lsh78nw/

<html>
    <head>
    <style>
        #ball {
            position:absolute;
            width:75px;
            height:75px;
        }

        #cup1 {
            position:absolute;
            left:375px;
        }

        #outerPowerMeter {
            position:absolute;
            width:25px;
            height:100px;
            background-color:red;
        }

        #innerPowerMeter {
            position:absolute;
            width:25px;
            height:100px;
            background-color:black;
        }
    </style>

    <script>
        window.onload = function() {
            var ball = document.getElementById("ball");
            var yPos = 500;
            var xPos = 400;
            var zPos = 100;
            var ballWidth = 75;
            var ballHeight = 75;
            var throwBallInterval;
            var changeBallSizeInterval;

            ball.style.top = yPos + "px";
            ball.style.left = xPos + "px";

            var cup1 = document.getElementById("cup1");

            var powerMeter = document.getElementById("innerPowerMeter");
            var powerMeterValue = 0;
            var powerMeterHeight = 100;
            var powerMeterActive = false;
            var powerMeterInterval;

            powerMeter.style.height = powerMeterHeight + "px";

            ball.onclick = function() {
                if (powerMeterActive == false) {
                    powerMeterActive = true;
                    startPowerMeter();
                } else {
                    powerMeterActive = false;
                    stopPowerMeter();
                    throwBall();
                }
            }

            function throwBall() {
                throwBallInterval = setInterval(function() {
                    yPos = yPos - 1;
                    ball.style.top = yPos + "px";
                }, 1);

                changeBallSizeInterval = setInterval(function() {
                    zPos = zPos - 1;
                    ballWidth = ballWidth - 1;
                    ballHeight = ballHeight - 1;
                    ball.style.width = ballWidth;
                    ball.style.height = ballHeight;
                }, 100);
            }

            function startPowerMeter() {
                var increment = true;
                powerMeterInterval = setInterval(function() {
                    if (increment == true) {
                        powerMeterValue = powerMeterValue + 1;
                        powerMeter.style.height = (powerMeterHeight - powerMeterValue) + "px";
                        if (powerMeterValue == 100) {
                            increment = false;
                        }
                    } else {
                        powerMeterValue = powerMeterValue - 1;
                        powerMeter.style.height = (powerMeterHeight - powerMeterValue) + "px";
                        if (powerMeterValue == 0) {
                            increment = true;
                        }
                    }
                },1);
            }

            function stopPowerMeter() {
                clearInterval(powerMeterInterval);
            }

            function detectCollision() { }

            function detectGoal() { }
        }
    </script>

    </head>
    <body>
        <img id="cup1" src="http://beerwar.com/game/images/cup.png">
        <img id="ball" src="http://beerwar.com/game/images/ball.png">
        <div id="outerPowerMeter">
            <div id="innerPowerMeter"></div>
        </div>
    </body>
</html>

1 个答案:

答案 0 :(得分:2)

既然你发布了这么详细的案例,我想我会给你一些指示。请注意:这主要是矢量数学。我也不是物理学家,但矢量数学并不幸运!这里和那里有一些毕达哥拉斯,你就定了。

一个好的快速库是glMatrix

有几件事可以帮助你。 请注意:它是伪代码,但它确实解释了它的概念。

  • 保持球的位置矢量
  • 保持杯子位置的矢量(球应击中的位置)
  • 为相机的位置保留一个矢量&#39; (因为你想根据与相机的距离来缩放球。不必准确,只需要了解这个想法)
  • 为力量的方向保留一个向量&#39;你打算申请球。 (这可以乘以力表的力量)
  • 为球的速度保持一个矢量&#39;
  • 为&#39; gravity&#39;
  • 保留一个向量

你的投掷&#39;功能将成为:

ball.velocity = throw.direction * throw.power
setInterval(tick,50);

基本上,你的&#39;打勾&#39;功能(每x次应用的功能)

ball.velocity += gravity; // we apply gravity to the speed of the ball. Pulling it down
ball.position = ball.position + ball.velocity // we add the velocity to the position every tick

if (ball.position.y < ball.radius) // if the ball is below its radius, it is colliding with the ground
{
    ball.position.y = 0 - ball.position.y; // just invert its 'up' position, to make it not collide with the ground anymore
    // to make the ball go back up again, invert its 'up' velocity. Gravity will get it down eventually
    // dampening applied so it will bounce up less every time. For instance make that 0.9.
    ball.velocity.y = 0 - (ball.velocity.y * dampening);
}
// the scale of the ball is not determined by its height, but by its distance from the camera
distanceFromCamera = (camera.position - ball.position).length()
ball.scale = 100 - (distanceFromCamera / scaleFactor);

// to make a simply guess if we are hitting the target, just check the distance to it.
distanceFromTarget = (cup.target.position - ball.position).length()
if (distanceFromTarget <= cup.target.radius) // if we 'hit the target'
    handleHit()