更新6:

Fenomenas建议我重新创建的一切都尽可能简单。我有我的怀疑,这将使任何差异,作为算法保持相同,并表现似乎并不是这一问题。无论如何,这是唯一的建议,我就在这里:

  1. 30FPS: http://www.feedpostal.com/test/simple/30/SimpleMovement.html
  2. 40FPS: http://www.feedpostal.com/test/simple/40/SimpleMovement.html
  3. 60FPS: http://www.feedpostal.com/test/simple/60/SimpleMovement.html
  4. 100FPS: http://www.feedpostal.com/test/simple/100/SimpleMovement.html

代码:

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.utils.getTimer;

    [SWF(width="800", height="600", frameRate="40", backgroundColor="#000000")]

    public class SimpleMovement extends Sprite
    {
        private static const TURNING_SPEED:uint = 180;
        private static const MOVEMENT_SPEED:uint = 400;
        private static const RADIAN_DIVIDE:Number = Math.PI/180;
        private var playerObject:Sprite;
        private var shipContainer:Sprite;
        private var moving:Boolean = false;
        private var turningMode:uint = 0;
        private var movementTimestamp:Number = getTimer();
        private var turningTimestamp:Number = movementTimestamp;

        public function SimpleMovement()
        {
            //step 1: create player object
            playerObject = new Sprite();
            playerObject.graphics.lineStyle(1, 0x000000);
            playerObject.graphics.beginFill(0x6D7B8D);
            playerObject.graphics.drawRect(0, 0, 25, 50);
            //make it rotate around the center
            playerObject.x = 0 - playerObject.width / 2;
            playerObject.y = 0 - playerObject.height / 2;
            shipContainer = new Sprite();
            shipContainer.addChild(playerObject);
            shipContainer.x = 100;
            shipContainer.y = 100;
            shipContainer.rotation = 180;
            addChild(shipContainer);

            //step 2: install keyboard hook when stage is ready
            addEventListener(Event.ADDED_TO_STAGE, stageReady, false, 0, true);

            //step 3: install rendering update poll
            addEventListener(Event.ENTER_FRAME, updatePoller, false, 0, true);
        }

        private function updatePoller(event:Event):void
        {
            var newTime:Number = getTimer();

            //turning
            if (turningMode != 0)
            {

                var turningDeltaTime:Number = newTime - turningTimestamp;
                turningTimestamp = newTime;
                var rotation:Number = TURNING_SPEED * turningDeltaTime / 1000;
                if (turningMode == 1) shipContainer.rotation -= rotation;
                else shipContainer.rotation += rotation;
            }

            //movement
            if (moving)
            {
                var movementDeltaTime:Number = newTime - movementTimestamp;
                movementTimestamp = newTime;
                var distance:Number = MOVEMENT_SPEED * movementDeltaTime / 1000;
                var rAngle:Number = shipContainer.rotation * RADIAN_DIVIDE; //convert degrees to radian
                shipContainer.x += distance * Math.sin(rAngle);
                shipContainer.y -= distance * Math.cos(rAngle);
            }
        }

        private function stageReady(event:Event):void
        {
            //install keyboard hook
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown, false, 0, true);
            stage.addEventListener(KeyboardEvent.KEY_UP, keyUp, false, 0, true);
        }

        private final function keyDown(event:KeyboardEvent):void
        {
            if ((event.keyCode == 87) && (!moving))  //87 = W
            {
                movementTimestamp = getTimer();
                moving = true;
            }
            if ((event.keyCode == 65) && (turningMode != 1)) //65 = A
            {
                turningTimestamp = getTimer();
                turningMode = 1;
            }
            else if ((event.keyCode == 68) && (turningMode != 2)) //68 = D
            {
                turningTimestamp = getTimer();
                turningMode = 2;
            }
        }

        private final function keyUp(event:KeyboardEvent):void
        {
            if ((event.keyCode == 87) && (moving)) moving = false; //87 = W
            if (((event.keyCode == 65) || (event.keyCode == 68)) && (turningMode != 0)) turningMode = 0; //65 = A, 68 = D
        }
    }
}

结果正如我的预期。绝对没有改善。我真的希望有人有另一项建议,因为这东西需要修复。此外,我怀疑这是我的系统,因为我有一个很好的一个(8GB RAM、Q9550四核英特尔、外汇管理局4870 512MB).此外,其他人我问迄今有同样的问题与我的客户。

更新5: 另一个例子的一个光滑的闪游戏只是为了证明我的运动肯定是不同的!看看 http://www.spel.nl/game/bumpercraft.html

更新4:我追溯的时间之前呈现(事件。渲染)和右后呈现(事件。ENTER_FRAME),结果:

rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 24 ms
rendering took: 18 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 232 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 16 ms
rendering took: 12 ms
rendering took: 14 ms
rendering took: 12 ms

范围是12至16毫秒。在这些差异,令人震惊/翘曲/闪烁的运动已经在进行。还有1顶峰232ms,在这个时候,有一个相当大的扭曲。这是但是不是最大的problme,最大的问题是连续的小扭曲正常的运动。这不会给任何线索吗?

更新3: 经检测,我知道,下列因素 导致我的问题:

  • 位的质量>改变用photoshop于一个丑陋8色的优化了图形,没有改善。
  • 不断转动的图像,同时打开->残疾,没有任何改善,在所有
  • 浏览器渲染->试图使用flash player独立的,没有改善,在所有

我是100%确信,问题在于,在我的代码或在我的算法。请帮助我。它已经几乎两个星期(1周,我问这个问题上所)现在我仍然必须得到我的黄金回答。

更新1: 看到底为全flex项目的来源和现场演示了展示我的问题。

我工作的一个2d闪光的游戏。播放船只是作为创建一个对象:

ships[id] = new GameShip();

当运动和旋转的信息是可用的,这是针对相应的船舶:

ships[id].setMovementMode(1); //move forward

现在,在这GameShip对象的运动的作用"的事件。ENTER_FRAME"事件:

addEventListener(Event.ENTER_FRAME, movementHandler);

下列功能后正在运行:

private final function movementHandler(event:Event):void
        {
            var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
            var distance:Number = (newTimeStamp - movementTimeStamp) / 1000 * movementSpeed; //speed = x pixels forward every 1 second
            movementTimeStamp = newTimeStamp; //update old timeStamp
            var diagonalChange:Array = getDiagonalChange(movementAngle, distance); //the diagonal position update based on angle and distance
            charX += diagonalChange[0];
            charY += diagonalChange[1];
            if (shipContainer)
            { //when the container is ready to be worked with
                shipContainer.x = charX;
                shipContainer.y = charY;
            }
        }

private final function getDiagonalChange(angle:Number, distance:Number):Array
        {
            var rAngle:Number = angle * Math.PI/180; //convert degrees to radian
            return [Math.sin(rAngle) * distance, (Math.cos(rAngle) * distance) * -1];
        }

当对象不再移动,事件的听众将被删除。同样的方法正被用于旋转。一切正常,几乎是完美的。

我已经设置该项目的目标》100和创建一个》计数器。根据该》反,平均》在火狐约为100,而顶部是1000和底是22。我认为,底部和顶部平价店是仅仅发生的初始化过程中的客户(启动时)。

问题是,船舶似乎是几乎完全顺利,而应当只是没有"几乎"的一部分。它几乎是因为如果该船舶是"闪烁的"非常非常的快,你不能实际上看到它但它很难把重点放在对象时它的移动你的眼睛。此外,每一个现在和以后,似乎有点framerate穗,因为如果客户是跳过一两个框架,然后你看到迅速扭曲。

这是非常难以解释什么是真正的问题是,但是一般的运动不是完全顺利。所以,您有任何建议,就如何使该运动或过渡的对象完美的顺利?

更新1:

我重新创造了客户证明我的问题。请检查出来。

对客户: http://feedpostal.com/test/MovementTest.html

Actionscript项目(全部资源): http://feedpostal.com/test/MovementTest.rar

一个例子的一个闪光滑的游戏 (不由我创建): http://www.gamesforwork.com/games/swf/Mission%20Racing_august_10th_2009.swf

我花了一个相当长的时间来重建这个客户面的版本,我希望这将有助于解决问题。

请注意:是的,它实际上是相当顺利。但它肯定不是光滑够的。

有帮助吗?

解决方案

我不知道如果有任何金的答案在这里,但是我有几个建议。

首先,我要免除任何调查到的东西喜欢优化数学。PI/180,等等。通常高framerate应明确说明,简单的计算不是减缓任何东西了。

第二,为解决偶然的峰值显示的滞后:这些看起来对我很喜欢垃圾收集器的运行非常频繁。在一个非常简短看过你的代码,我没有看到任何明显的原因导致的频繁的全球合作协会,但我有两项建议。第一,如果你访问到闪IDE,我想尝试重建项目而不使用Flex框架。一闪光的项目不包括任何代码,除非你放,但Flex采用了很多其自己的僵尸,这可能并不总是显而易见的,和一些相互作用之间代码和框架可能会导致全球合作协会.

如果没有帮助,其他东西尝试将是使一个大大简化版本的你的代码(在闪如果可能的话),它希望能够简单,不要触发器一样的尖峰。我的意思是,例如,一个单一的类附的图形,其中只有一个监听器于关键事件和第二听众对于框架(或计时器)的事件,其内没有变量。如果一个最小的版本没有显示这些峰值,然后,它应该是可能的三分之间,和你的客户,弄清楚什么是造成尖峰。

最后,关于一般光滑,我的唯一评论是,闪光的屏幕,更新本质上都是微不平衡的,而实际上你只有两个办法可用。要么你移动你的行为者根据框架的更新,这使得他们的运动稍有不均衡的帧率变化,或移动他们根据过去的时间,这使得他们的整体运动顺利(素在每第二个),但它们显示略有不均匀(在移动像素每框架)。差异被放大至更高FPS。

此外,重要的是要记住,经过快速做出了更新,他们如何出现在你的屏幕是严重影响,通过你的视频卡。尤其是你会找到那剪切和垂直的问题可以是高度引人注目的一环境并没有在另一个。有没有真正的方式开发人员可以解决这个问题,除了一般避免非常高FPS动和保持整体处理的负担,尽可能低的水平。

编辑: 欲了解更多关于什么我的意思是有关框架更新时间是"固有的不平衡",请见 这篇文章.延迟之间的屏幕,更新变化之间的12-16毫秒以上的时间是不是有些东西你可以做任何事情;这是一个事实的结果的操作系统和浏览器影响的方式闪光的时工作。(这也有些东西你会看到甚至在一个空的电影,这就是为什么许多意见在此线有关优化数学等不要帮助你。) 你不能避免这种变化,但正如我前面所说,你可以定你的视觉效果,以唤起你想要的效果。无论哪种方式,我认为尖峰更值得担心。变化你看到的是微妙的,将很难通知在一个游戏有很多的东西,但是尖峰是令人震惊的。

编辑2 你问:"你真的认为那些流畅游戏使用同样的运动算法,因为我做什么?"

答案是,我认为他们正在做的事情简单得多。他们几乎肯定会这样做下列之一:

function onEnterFrame() { // move at a constant speed per frame
    ship.angle += dtheta;
    ship.x += speed * Math.cos( ship.angle );
    ship.y += speed * Math.sin( ship.angle );
}

function onEnterFrame2() { // move at a constant speed per second
    var dt:Number = getTimeSinceLastFrame();
    ship.angle += anglePerSecond * dt/1000;
    var dist:Number = speedPerSecond * dt/1000;
    ship.x += dist * Math.cos( ship.angle );
    ship.y += dist * Math.sin( ship.angle );
}

换句话说,无论是移动一定的距离,每框架,或者一定的距离。这些都是两个最简单的方法可以处理这个,而是两个选项会导致流畅的外观。他们看起来相同的恒定framerate,后一种方法将看起来平滑至轻微变化的帧率的原因类似于"时间混淆"在文章中提到你的联系。但是选择这些方法之间真下来,如果一个CPU穗发生的,之后它的过去做你想要的船舶必须保持移动或不行?这真的是一个游戏设计问题。有一件事我已经做了在过去是使用第二种方法,同时夹紧 dt 以至多2或3次持续时间的一个理想的框架(1/fps)。

正如你可能已经注意到,两个方法我只是建议到底是什么"修复你的时间步长!"的文章说不做。这是因为那篇文章是关于数字上的综合物理学的发动机,这就是不你在做什么。如果你开始实施泉和严重性,那么是的,只要的步长得到大会引入一个很大的错误,因为这种模拟,过于简单化的事情,错误取决于规模的时间步长.你在做什么,没,因此偶尔大步长不会影响正确的模拟。

答复更新6

第一,我没有告诉你你的问题是表现,我说的正相反。我建议一个最小的再现,因为我认为你的问题是不是在别的地方项目中,或者不可避免的,并且我仍然做。第二,我现在感觉很舒服的说法,你正在做的事相同的任何其他闪光的游戏,什么问题你看不可能解决其他的看法。在新的联系你的动画看起来完全可以顺利如果我认为它在独立SWF播放器,并具有细微的闪烁在前面和后面的边缘在浏览器(用户在火狐于在IE)。从技术上讲,我不认为它可以改进(特别是当它基本上是完美的独立的播放,这意味着任何乱套在浏览器是受到容器中。)

当然, 感知 业绩仍然可以改进。如果船上没有对比如此急剧的背景,例如,闪烁将远远不那么明显。此外,只需使船更为缓慢地移动将使运动似乎更加顺畅,并能够结合一个运动的背景以得到一种幻想的更快的速度(作为你的一个例子没有).

作为一个完整性检查,这里是最小的一个类似的版本,我在IDE。http://www.fenomas.com/random/ship/ 性能是可比你在我的机器,如我所说,我真的看不到任何问题。(除了偶尔的尖峰,我现在通知只发生时我在火狐。) 再次,尤其是事实,这两个版本出现基本上是完美的我在独立的玩家进一步使我相信,有没有黄金的算法在这里。我知道这不是答案你想要的,但这是一个我有了.

其他提示

你的代码运行顺利我的。没有尖峰任何责任。测试了它与下列代码在末尾添加的updatePoller功能。

var shadow:Sprite = new Sprite();
shadow.graphics.beginFill(0xFFFFFF, 0.01);
shadow.graphics.lineStyle(1, 0xFFFFFF, 0.8);
shadow.graphics.drawRect(0, 0, 25, 50);
this.addChildAt(shadow, 0);
shadow.x = shipContainer.x;
shadow.y = shipContainer.y;
shadow.rotation = shipContainer.rotation;

100》版本往往获得非统一模式,但这是正常的,因为根据你的计算,它不可能是可能呈现100框架在第二,如果计算一个框架需要超过10毫秒。因此,至少对我来说,最后一个编码的顺利运行,在30帧/秒.

至于模糊的一部分,一个主要数字户外,并希望你不会生气我问:是否有任何机会,模糊/模糊的效果是因为你的监视器?即使在10ms响应时间的液晶显示器,一个白色的快速移动的东西强加在一个静态的黑色的背景,往往看起来模糊。

我认为根本的问题是,"垂直同步"是不相同的屏幕。这是同时发生的问题寻找一个以24电影上说,60hz屏幕上。更新将不会完全匹配起来(在你的情况100/60)和当他们打一个更大的跳跃,它看起来像一个小小的抖动的运动。

这可以在某种程度上纠正通过降低你的框架速度,任何上述的画面只是废物的处理能力无论如何。它真的不能完全避免,虽然 新wmodes闪嵌入 可能是一个可能的解决方案。

可以我建议你在令人担忧过早?

如果你仔细看的"完全平滑"游戏,你挂,你会注意到,它在欺骗你的"幻想"的顺利运动。

汽车是不是移动速度非常快,在所有--可能是一个象素每隔几框架。它的背景,并最大的运动。仔细看:有一点点的抖动和相同的"硬集中"的效果你试图修复,但由于它的背景,它似乎正常的。甚至当这车确实显示了这些影响,背景和游戏的分散你注意到他们。

我想你没有注意到的抖动,因为所有你现在所拥有的是一艘船上的移动完全黑色的背景。一旦剩余的游戏,是在地方,一个球员大概不会有备用的关注,注意到一个小小的抖动。至于"难集中"的效果,它就会消失,因为您减少船舶的移动速度。

为什么你不工作的其余的游戏中的第一个?你可以随时回来和调整的运动以后,如果它仍然是一个问题。你花了很多时间在一个动画项目。不是游戏更加重要?

这是一个非常好的问题。我已经扫描的代码和我有几个建议,虽然我的建议可能不是那么好。

我想你可以做很多优化的代码。显然,并不是在这个早期阶段。但你可以有一个测试,代码看看快速运行的优化的代码,然后你就会知道如果这是值得继续。

这里是我的'反对':

  • 你用了很多的分歧。司 是昂贵的多 乘法运算。

    var距离:数量=(newTimeStamp-movementTimeStamp)/1000*movementSpeed;

可以很容易地写作

var distance:Number = (newTimeStamp - movementTimeStamp) * .001 * movementSpeed;
  • 你有很多参考文献了很多 的功能。

    这样的东西fixAngle()等可在同一个功能,而不具有电话来回运行,往往。这适用于提到外部类和数学。PI或数学。罪等,以fenomas和艾伦*指出的那样。

我已经测试了 方法中的正弦和余弦和它的血腥快。确保它使代码脏,但是这就是为什么你不要优化这一不久直到你得到了它的大部分工作的方式,它需要的工作,优化只会让你发疯为该守则将变得更难于阅读。从我的经验罪,因为是非常昂贵的行动。

正如其他人已经提到的,你可能是杞人忧天太多的在这一步骤。记住有很多事情可以获得的速度,直到你得到了你所有的逻辑工作正常、甚至不认为关于优化。

我认为这是几乎可以肯定因为你是在80fps.闪只是不能给出一个一致的框架速度快。下降下降到30帧/秒和保测试。此外,试飞船在前面的一个实际的背景,我认为你会注意到这一少。

要下载的文件是不存在(http://feedpostal.com/test/MovementTest.rar).

我已经回答另一个问题涉及到这个问题上,宣读如下:

我觉得你的疼痛,因为我目前正在战壕开发我自己的游戏。在默认设置,闪渲染产生的可怕画面撕裂/v-同步问题,无论什么代码产品。

这就是为什么我感到高兴的是已经找到了最简单优雅的答案,那不是重新分解代码(它并不能帮助一个单位,问题是Flash player,不码)。

刚刚启用的硬件加速在你的布置.有两个不同的选择:

第1级:直接的;和 2级:GPU.

了解更多关于它在官方文件: 指定公布的设置SWF文件, ,并决定什么最适合你的游戏。

目标市场的确发挥的因素在这里,如果它是一个严重的游戏玩家,你不需要担心的可能性问题,因为大多数游戏玩家有GPU。

这篇文章 没有提供我解决具体的,但是导致我在正确的方向。但是,如果你的游戏会在浏览器窗口,则可能必须使用相同的技术设wmode直接或gpu。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top