更新 6:
Fenomenas 建议我尽可能简单地重新创造一切。我怀疑这会产生什么不同,因为算法保持不变,性能似乎不是问题。无论如何,这是我得到的唯一建议,所以这里是:
- 30 FPS:http ://www.feedpostal.com/test/simple/30/SimpleMovement.html
- 40 FPS:http ://www.feedpostal.com/test/simple/40/SimpleMovement.html
- 60 FPS:http ://www.feedpostal.com/test/simple/60/SimpleMovement.html
- 100 FPS: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 QuadCore intel,ATI Radeon 4870 512MB)。此外,到目前为止,我询问的其他所有人都与我的客户有同样的问题。
更新5:另一个流畅的Flash游戏示例,只是为了证明我的动作绝对不同!见http://www.spel.nl/game/bumpercraft.html
更新 4:我跟踪了渲染前的时间 (EVENT.RENDER) 和渲染后的时间 (EVENT.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的峰值,此时出现了比较大的warp。然而,这不是最大的问题,最大的问题是在正常运动过程中连续的小翘曲。这是否给任何人一个线索?
更新3:经过测试,我知道以下因素不是我的问题:
- 位图的质量 -> 用 Photoshop 更改为丑陋的 8 色优化图形,完全没有改进。
- 转动时图像不断旋转->禁用它,根本没有改善
- 浏览器渲染 -> 尝试单独使用 flash 播放器,完全没有改进
我 100% 确信问题出在我的代码或算法上。请帮帮我。现在已经快两周了(我在 SO 上问了这个问题 1 周),我仍然需要得到我的黄金答案。
更新 1:请参阅底部以获取完整的 flex 项目源代码和演示我的问题的现场演示。
我正在开发一款 2d Flash 游戏。玩家船被创建为一个对象:
ships[id] = new GameShip();
当移动和旋转信息可用时,这将被定向到相应的船舶:
ships[id].setMovementMode(1); //move forward
现在,在这个 GameShip 对象移动中使用“Event.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];
}
当对象不再移动时,事件监听器将被移除。同样的方法被用于旋转。一切工作几乎完美。
我已将项目的目标 FPS 设置为 100 并创建了一个 FPS 计数器。根据 FPS 计数器,firefox 中的平均 FPS 在 100 左右,而顶部是 1000,底部是 22。我认为底部和顶部 FPS 仅在客户端初始化(启动)期间发生。
问题是这艘船看起来几乎是完全光滑的,而没有“几乎”的部分应该就是这样。几乎就好像这艘船在非常非常快地“闪烁”,你实际上看不到它,但是当它用你的眼睛移动时很难将注意力集中在物体上。此外,每隔一段时间,似乎会有一点帧率峰值,就好像客户端跳过了几帧,然后你会看到它迅速扭曲。
很难解释真正的问题是什么,但总的来说,运动并不完美。那么,您对如何使物体的移动或过渡完美流畅有什么建议吗?
更新1:
我重新创建了客户端来演示我的问题。请检查一下。
客户端:http: //feedpostal.com/test/MovementTest.html
Actionscript 项目(完整源代码): http: //feedpostal.com/test/MovementTest.rar
流畅的 Flash 游戏示例(不是我创建的):http ://www.gamesforwork.com/games/swf/Mission%20Racing_august_10th_2009.swf
我花了很长时间重新创建这个客户端版本,我希望这将有助于解决问题。
请注意:是的,它实际上非常流畅。但绝对不够流畅。