【问题标题】:Problems with javascript object and animationjavascript对象和动画的问题
【发布时间】:2013-07-01 19:06:12
【问题描述】:

我一直在玩弄 JavaScript/JQuery,并决定创建一个小程序,让球在矩形边界区域周围弹跳。我相信我的代码逻辑应该是有意义的,但由于某种原因,我无法让它改变方向。更奇怪的是,我将球的 x 和 y 位置作为文本放在上面,但它似乎是静态卡住的(它不会改变),但是当我检查它留下的元素时,我看到顶部的 css 参数正在改变时间。

代码如下:

    <!DOCTYPE html>
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js">
        </script>
        <style>
            .ball {
                width: 50px;
                height: 50px;
                background: red;
                -moz-border-radius: 50px;
                -webkit-border-radius: 50px;
                border-radius: 50px;
                position: absolute;
            }
            .boundary {
                width: 700px;
                height: 500px;
                background: #AAAAAA;
                border-style:solid;
                border-width:5px;
                position: absolute;
            }
        </style>
        <script>
            $(document).ready(function(){
                var b = new ball(1, 1, 10, 10);
                for(i = 0; i < 1000; i++)
                    b.moveBall();
            });

            function ball(xPos, yPos, xVel, yVel)
            {
                this.xPos = xPos;
                this.yPos = yPos;
                this.xVel = xVel;
                this.yVel = yVel;
                this.rightBound = false
                this.leftBound = false;
                this.upBound = false;
                this.downBound = false;
                this.width = 50;
                this.height = 50;


                this.moveBall = moveBall;
                function moveBall()
                {
                    var h = 500;
                    var w = 700;

                    //detect if it is at x bounds
                    if(this.xPos + this.width + this.xVel > w)
                        {this.rightBound = true;}
                    else if(this.xPos + this.xVel < -1)
                        this.leftBound = true;
                    else
                    {
                        this.rightBound = false;
                        this.leftBound = false;
                    }

                    //detect if it is at y bounds
                    if(this.yPos + this.height + this.yVel > h)
                        {this.downBound = true;}
                    else if(this.yPos + this.yVel < -1)
                        this.upBound = true;
                    else
                    {
                        this.upBound = false;
                        this.downBound = false;
                    }

                    //handle velocity changes for bounds
                    //so you switch the x direction if x bound is met, same for y
                    if(this.rightBound || this.leftBound)
                        this.xVel *= -1;
                    if(this.upBound || this.downBound)
                        this.yVel *= -1;

                    //now give motion               
                    this.xPos += xVel;
                    this.yPos += yVel;

                    //now draw  
                    $(".ball").animate({
                        left:this.xPos + 'px',
                        top:this.yPos + 'px'
                        }, 150).text(this.xPos + "," + this.yPos);  
                }
            }
        </script>
    </head>

    <body>
        <div class="boundary">
            <div class="ball"></div>
        </div>
    </body>
</html>

奇怪的是,它似乎从一开始就自动将结束值 10,001、10,001(假设它从不改变方向)作为 (x,y) 坐标。任何可以为我指明正确方向的东西都将不胜感激!很抱歉,如果这是一些基本错误,我试图确保它不是但有时他们会漏掉!

【问题讨论】:

    标签: javascript jquery html object jquery-animate


    【解决方案1】:

    您在循环中执行ball.moveBall,而不是在计时器上。所以它会尽可能快地进行计算。是的,可计算不是一个词。继续前进。

    通过调用$.animate,您是说您希望jQuery 处理将对象从一个位置移动到另一个位置。 jQuery 的运行方式比计算机慢。等等,这变得越来越混乱。让我简单地说。

    你循环了ball.moveBall 1000 次。这需要多长时间?几乎没有时间。这就是为什么坐标一直停留在 1000 的原因。它实际上超级超级超级快。如此之快,它基本上在 jQuery 有时间开始移动球之前就到达了那里。然后......然后球开始移动。为什么?为什么它实际上没有立即移动到位置 1000,1000?好吧,坐标确实达到了 1000,1000。但是 jQuery 就像,“哦,好吧,将球移动到位置 1000,1000。我可以做到!真的很慢......”。您可能已经厌倦了听到解释,所以这里是解决方法:

    $(".ball").animate 更改为$(".ball").css。并将您的循环更改为window.setInterval(function(){b.moveBall()},1000) 或类似的东西。我在这里为你设置了一个小提琴:http://jsfiddle.net/uXbwR/

    您会注意到它移动得非常缓慢。那是因为我将间隔设置为 1000 毫秒,这意味着它每秒只移动一次。对于一场比赛,你会想要 1000/60(每 60 秒一次),但我试过了,它让球移动得非常快。你的球的速度真的很高。你可能想试着把它调低一点。

    这就是我所拥有的。

    编辑

    计算上。这就是我要找的词。

    【讨论】:

    • 谢谢,这看起来是最好的解决方案。实际上,我发现它没有弹跳的原因是因为我错过了对速度的对象引用。 //现在给出运动 this.xPos += xVel; this.yPos += yVel;应该有this.xVel,this.yVel。但是,正如您所说,这并不能解决它更新的基本问题。感谢您的详细回答!
    • 没问题。另外,我注意到您可以根据需要保留 .animate 功能,只需确保(如@Andrea 的回答中所述)您弄乱了时间,所以它不会太慢。
    【解决方案2】:

    只有在前面的动画完成后,您才应该调用动画的下一步。您告诉 animate 需要 150 毫秒,但 while 循环几乎立即完成,无需等待每一步。

    [编辑]

    @Samuel 的回答是完整的,并且已经向您建议了一个很好的解决方法。我想这将超出您的应用程序的目的,但如果您有兴趣设置一个适当的 Javascript 游戏主循环,这些是一些有用的资源,然后是我的实现:

    法比安·桑格拉德,Game timers: Issues and solutions

    保罗·爱尔兰,requestAnimationFrame for smart animating

    var RENDERING_FRAME_TIME = 1000/60; // ms
    var PHYSICS_FRAME_TIME = 5;         // ms
    
    var currentTime = new Date().getTime();
    var accumulator = 0;
    
    (function mainloop(){
        newTime = new Date().getTime();
        accumulator = newTime - currentTime;
        currentTime = newTime;
        while (accumulator > PHYSICS_FRAME_TIME) {
            integrate(PHYSICS_FRAME_TIME);
            accumulator -= PHYSICS_FRAME_TIME;
        }
        requestAnimationFrame(mainloop);
        render();
    })();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      相关资源
      最近更新 更多