views:

1386

answers:

8

Update 6:

Fenomenas suggested me to re-create everything as simple as possible. I had my doubts that this would make any difference as the algorithm remains the same, and performance did not seem to be the issue. Anyway, it was the only suggestion I got so here it is:

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

The code:

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
     }
    }
}

The results were as I expected. Absolutely no improvement. I really hope that someone has another suggestion as this thing needs fixing. Also, I doubt it's my system as I have a pretty good one (8GB RAM, Q9550 QuadCore intel, ATI Radeon 4870 512MB). Also, everyone else I asked so far had the same issue with my client.

Update 5: another example of a smooth flash game just to demonstrate that my movement definitely is different! See http://www.spel.nl/game/bumpercraft.html

Update 4: I traced the time before rendering (EVENT.RENDER) and right after rendering (EVENT.ENTER_FRAME), the results:

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

The range is 12-16 ms. During these differences, the shocking/warping/flickering movement was already going on. There is also 1 peak of 232ms, at this time there was a relatively big warp. This is however not the biggest problme, the biggest problem are the continuous small warps during normal movement. Does this give anyone a clue?

Update 3: After testing, I know that the following factors are not causing my problem:

  • Bitmap's quality -> changed with photoshop to an uglier 8 colours optimized graphic, no improvement at all.
  • Constant rotation of image while turning -> disabled it, no improvement at all
  • Browser rendering -> tried to use the flash player standalone, no improvement at all

I am 100% convinced that the problem lies in either my code or in my algorithm. Please, help me out. It has been almost two weeks (1 week that I asked this question on SO) now and I still have to get my golden answer.

Update 1: see bottom for full flex project source and a live demo demonstrating my problem.

I'm working on a 2d flash game. Player ships are created as an object:

ships[id] = new GameShip();

When movement and rotation information is available, this is being directed to the corresponding ship:

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

Now, within this GameShip object movement works using the "Event.ENTER_FRAME" event:

addEventListener(Event.ENTER_FRAME, movementHandler);

The following function is then being run:

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];
     }

When the object is no longer moving, the event listener will be removed. The same method is being used for rotation. Everything works almost perfect.

I've set the project's target FPS to 100 and created a FPS counter. According to the FPS counter, the average FPS in firefox is around 100, while the top is 1000 and the bottom is 22. I think that the bottom and top FPSs are only happening during the initialization of the client (startup).

The problem is that the ship appears to be almost perfectly smooth, while it should be just that without the "almost" part. It's almost as if the ship is "flickering" very very fast, you can't actually see it but it's hard to focus on the object while it's moving with your eyes. Also, every now and then, there seems to be a bit of a framerate spike, as if the client is skipping a couple of frames, you then see it quickly warp.

It is very difficult to explain what the real problem is, but in general it's that the movement is not perfectly smooth. So, do you have any suggestions on how to make the movement or transition of objects perfectly smooth?

Update 1:

I re-created the client to demonstrate my problem. Please check it out.

The client: http://feedpostal.com/test/MovementTest.html

The Actionscript Project (full source): http://feedpostal.com/test/MovementTest.rar

An example of a smooth flash game (not created by me): http://www.gamesforwork.com/games/swf/Mission%20Racing_august_10th_2009.swf

It took me a pretty long time to recreate this client side version, I hope this will help with solving the problem.

Please note: yes, it is actually pretty smooth. But it is definitely not smooth enough.

+1  A: 

I think the root of your problem is that the "vertical sync" isn't the same as that of the screen. This is the same problem that occurs when looking at a 24fps movie on a, say, 60hz screen. The updates won't perfectly match up (in your case 100/60) and when they hit a bigger jump it will look like a small jitter in movement.

This can be somewhat remedied by lowering your frame rate, anything above that of the screen is just waste of processing power anyway. It can't really be avoided entirely, although the newer wmodes for flash embedding might be a possible solution.

grapefrukt
I've tried lowering the framerate, but this only made things worse. So that can't be the biggest issue.
Tom
I added full flex source and a live demo to the OP.
Tom
A: 

May I suggest that you're worrying prematurely?

If you look carefully at the "perfectly smooth" flash game you linked to, you'll notice that it's tricking you with the ''illusion'' of smooth movement.

The car isn't moving very fast at all -- probably a pixel every few frames. It's the background that does most of the movement. Take a close look: there's a little bit of jitter and the same "hard to focus" effect you're trying to fix, but since it's the background, it seems normal. And even when the car does show those effects, the background and gameplay distract you from noticing them.

I think you're noticing the jitter because all you have right now is a ship moving on a perfectly black background. Once the rest of the game is in place, a player probably won't have the spare attention to notice a little jitter. As for the "hard to focus" effect, it goes away as you reduce the ship's movement speed.

Why don't you work on the rest of the game first? You can always come back and tweak the motion later, if it's still a problem. You're spending a lot of time on an animation artifact. Isn't the gameplay more important?

Selene
I really don't think that this is not a problem. If you read articles like http://gafferongames.com/game-physics/fix-your-timestep/, it really becomes clear that movement is not as simple as I thought it was. I just don't know how to do it the smooth way, that's why I'm asking here. This problem is too big to ignore, if I continue building other things, my problem will remain. About the black background causing it, judging on that article I linked, I don't think that's the only thing to blame.
Tom
The new game you linked to also exhibits the flickering/hard-to-focus effect you're worried about.When you're making a game, it's important to get to a playable prototype of your core game mechanic as quickly as possible. Don't try for perfection. Just make sure your mechanics are fun. You can always refine things later, when you *know* what needs refining from playing your prototype.I think your movement is at the "good enough" stage, and it's time to work on the rest of your game.
Selene
Well then we disagree. I have demonstrated the problem to many people and they all agreed that the flickering movement is gamebreaking, including myself.
Tom
+5  A: 

I don't know if there's any golden answer here, but I do have a couple of suggestions.

First, I'd dispense with any inquiries into things like optimizing Math.PI/180, and so on. The generally high framerate should make it clear that simple calculations are not slowing anything down.

Second, to address the occasional spikes of display lag: These look to me very much like the garbage collector is running very frequently. On a very brief look through your code I didn't see any obvious causes of frequent GCs, but I do have two suggestions. First, if you have access to the Flash IDE, I'd try recreating your project without using the Flex framework. A Flash project doesn't include any code except what you put in, but Flex employs a lot of its own arcanery, which may not always be obvious, and some interaction between your code and the framework might be causing GCs.

If that doesn't help, the other thing to try would be to make a greatly simplified version of your code (in Flash if possible), which would hopefully be simple enough not to trigger the same spikes. I mean, for example, a single class attached to the graphic, which merely has one listener for key events and a second listener for frame (or timer) events, within which no variables are created. If a minimal version doesn't display these spikes, then it ought to be possible to triangulate between that and your full client, to figure out what's causing the spikes.

Finally, regarding the general smoothness, my only comment would be that Flash's screen updates are inherently slightly uneven, and realistically you only have two approaches available. Either you move your actors according to frame updates, which makes their movement slightly uneven as framerates vary, or you move them according to elapsed time, which makes their overall movement smooth (in pixels per second) but their display slightly uneven (in pixels moved per frame). The difference is magnified at higher FPS.

Also, it's important to remember that after Flash has made its updates, how they appear on your screen is heavily influenced by your video card. Especially you'll find that shearing and vsync issues can be highly noticeable in one environment and absent in another. There's no real way the developer can address this, except to generally avoid very high-FPS animations and keep the overall processor burden as low as possible.

edit: For more on what I mean about frame update timing being "inherently uneven", please see this blog post. The delay between screen updates varying between 12-16ms is not something you can do anything about; it's a result of the fact that the OS and the browser influence the way Flash's timing works. (It's also something you'll see even in an empty movie, which is why the many comments in this thread about optimizing math and so on are not going to help you.) You can't avoid this kind of variation, but as I said above, you can tailor you visual effects to evoke the effect you want. Either way, I think the spikes are much more worth worrying about. The variation you're looking at is subtle, and will be hard to notice in a game with lots of stuff going on, but the spikes are egregious.

edit 2 You ask: "Do you really think that those smooth games use the same movement algorithm as I do?"

The answer is, I think they're doing something much simpler. They're almost certainly doing one of the following:

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 );
}

In other words, either move a constant distance per frame, or a constant distance per second. Those are the two simplest ways you can approach this, and are the two options that are going to result in the smoothest appearance in Flash. They'll look identical at a constant framerate, and the latter method will look smoother at slightly varying framerates for reasons similar to the "temporal aliasing" mentioned in the article you linked. But the choice between these methods really comes down to, if a CPU spike occurs, after it's over do you want the ship to have kept moving or not? Which is really a game design question. One thing I've done in the past is to use the second method, while clamping dt to at most 2 or 3 times the duration of an ideal frame (1/fps).

As you've probably noticed, the two methods I just recommended are exactly what the "Fix your timestep!" article says not to do. This is because that article is about numerically integrated physics engines, and that's not what you're doing. If you start implementing springs and gravity, then yes, whenever the timesteps get large it will introduce a lot of error, because for that kind of simulation, to oversimplify things, the error depends on the size of the timestep. In what you're doing, it doesn't, so occasional large timesteps don't affect the correctness of the simulation.

Reply to update 6

First, I didn't tell you your problem was performance, I specifically said the opposite. I suggested a minimal reproduction because I believed your problem was either somewhere else in your project, or unavoidable, and I still do. Second, I now feel pretty comfortable saying that you're doing things the same as any other Flash game, and whatever problems you see cannot be solved other than in perception. In the new links you posted, the animation looks perfectly smooth if I view it in the standalone SWF player, and has subtle flickering at the front and back edges in browsers (moreso in Firefox than in IE). Technically, I don't think it can improve (especially when it's basically perfect in the standalone player, implying that any choppiness in browsers is influenced by the container.)

Of course, the perceived performance can still improve. If the ship didn't contrast so sharply with the background, for example, the flicker would be much less noticeable. Also, simply making the ship move more slowly would make the movement appear much smoother, and could be combined with a moving background to give an illusion of greater speed (as one of your examples did).

As a sanity check, here's a similar minimal version I made in the IDE. http://www.fenomas.com/random/ship/ The performance is comparable to yours on my machine, and as I said, I really don't see any problem. (Except the occasional spike, which I now notice only occurs for me in Firefox.) Again, especially the fact that both versions appear basically perfect to me in the standalone player further convinces me that there's no golden algorithm here. I know that's not the answer you want, but it's the one I got.

fenomas
Note that I created an Actionscript project in Flex Builder, not a flex project. How would I download the Flash IDE, and how would I recreate my project without using the Flex framework?
Tom
Update: I traced the time before rendering (EVENT.RENDER) and right after rendering (EVENT.ENTER_FRAME), the results are now in the original post. Does this help you ?
Tom
The variation you're seeing between renders is not something that's avoidable - I added a paragraph of explanation. As for the other question, I'm not really a Flex guy; I don't know if any framework code is added to AS projects. There should be an option in FB somewhere not to delete any temporary AS files created for platform code.. that may let you see any extra code being added. As for using the Flash IDE, there's a 30 day free trial at Adobe's site. But you may be right, there may be no platform code in AS projects.
fenomas
I read your update. Still, the long duration before the spike is full of flickering movement (it's actually doing it all the time). The 4ms difference for each render is apparently not a problem (since it is like this in other games aswell and those are smooth). I believe that I already implemented one of your "solutions": [code]var distance:Number = (newTimeStamp - movementTimeStamp) / 1000 * movementSpeed;[/code]
Tom
You've given me the most useful comments so far, but I'm stil unable to solve the problem. Do you really think that those smooth games use the same movement algorithm as I do?
Tom
Thanks Fenomas. However, if you look at my code, it's doing the same exact thing as onEnterFrame2.
Tom
You may also want to look at http://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/ , an explanation of how the Flash Player slices up processing and rendering tasks to get the framerate you see.
Selene
Tom: as I said, try making a very minimal project with only the listener code described. The smoothness you see there is the smoothness the flash player is capable of giving you. If you see the same problems in a minimal re-creation, then the problems are either with your platform (video card, etc.) or inherent to the Flash player. If not, then as I said your task is triangulate how to change your real project to be more like the minimal one.
fenomas
Selene: that's an interesting link, but it's somewhat misleading in that it makes it look like the Flash player limits the rendering phase to the time available, which is not the case.
fenomas
Well, I guess I'm not going to get a better thing to try. However, what you're suggesting is purely a matter of optimization - the algorithm will be exactly the same. From my previous tests I already noticed that performance is not the issue. Since I have no better suggestions though, I will try it anyway as soon as I can. I am very pessimistic about it though.
Tom
It's not a matter of optimization, it's a matter of isolation. I'm not saying that a minimal reproduction of the best algorithm will definitely fix what you see as the problem, I'm just saying that if it doesn't, nothing else will. (As an aside, be sure to try various published framerates... something lower like 40fps often seems to look smoother than higher rates like 60 or 100.)
fenomas
Well, then I did what you suggested. Please see the original post for the update and another new client. PS. the results were not good.
Tom
Answer updated again.
fenomas
Well, I guess I need to start adding a background and hope that you're all right about it masking the choppyness. I really do hope so.
Tom
Update: your version looks very choppy to me, especially in Internet Explorer. Less in firefox but there it spikes every now and then... and I thought that Flash was the way to go for browser games. Pretty disappointed.
Tom
Did you compare the browser performance to what it looks like in the standalone player? Choppiness that only happens is browsers isn't really Flash's fault (as explained in the blog I posted earlier).
fenomas
It does seem to be the browser for the warping, although even in the player the front side is flickering. That kind of choppiness does not seem to appear in the many flash games I found on the web. There might be some way that is less "browser intensive".
Tom
You have helped me the most, and I don't expect any better answer. So I'll set your answer as the accepted one so you get the bounty. Thanks for the help, I'm pretty sure that what I want is not possible now.
Tom
A: 

Hi,

This is a pretty good question. I've scanned the code and I have a few suggestions, although my advice might not be that good.

I'm thinking you can do a lot to optimize the code. Obviously, not at this early stage. But you can have a test with that code and see fast it runs with the optimized code, then you'll know if it's worth continuing.

Here are my 'objections':

  • You use a lot of divisions. Division is more expensive than multiplication.

    var distance:Number = (newTimeStamp - movementTimeStamp) / 1000 * movementSpeed;

can be easily written as

var distance:Number = (newTimeStamp - movementTimeStamp) * .001 * movementSpeed;
  • You have a LOT of references to a lot of functions.

    Stuff like fixAngle() and so on can be inside the same function, without having calls running back and forth that often. This applies to references to external classes and Math.PI or Math.sin and so on, as fenomas and Allan pointed out.

I've tested this method for sine and cosine and it's bloody fast. Sure it makes the code dirty, but that's why you don't optimize this soon, until you got most of it working the way it needs to work, optimizing will only make you go nuts as the code will get harder to read. From my experience sin and cos are pretty expensive operations.

As the others already mentioned, you might be worring too much at this step. Keep in mind there are a lot of things you can gain speed on, until you got all your logic working properly, don't even think about optimizing.

George Profenza
I think it's very unlikely that the time required for divisions and so on is having any effect on the performance here.
fenomas
I agree with Fenomas. I tested the speed of these calculations and they are very fast. The minor difference between an optimized version is __definitely__ not visible by the human eye.I am confinced that I am not worrying more than I should. I have seen games that are very smooth, I linked another one in the newest update. Also, my problem is actually very noticeable. There is no way for me to release such game with this kind of movement. Because of that, it would be a huge risk to continue development while this mayor problem is still live. Instead, I am going to try to solve it right now.
Tom
Ok, I got the downvote for assuming rather than testing when all that data was available. I can't seem to find what is making it behave like this. I notice every second a slight delay in the ship rendering, like a very light hickup. I've run the profiler and saw that most memory was taken by the frameconter and enterFrame which made sense (http://www.lifesine.eu/so/profile1.gif), also most objects loitering were strings(http://www.lifesine.eu/so/profile2.gif) so I've changed the keys in Settings to ints(87,65,68) and all uints to ints. Sadly that didn't make any difference in movement...
George Profenza
The only difference was slightly less memory used (353K to 281K) http://www.lifesine.eu/so/profile3.gif. That might have been because of keys beeing converted to strings back and forth and maybe the uints, according to Grant Skinner's post: http://www.gskinner.com/blog/archives/2006/06/types_in_as3_in.htmlSorry, not much handy information here. I did learn new things though.
George Profenza
Thanks George. I'm not the one who downvoted you, as I was happy to atleast get a bit more help (even though it didn't get me any further in solving the problem). Anyway, I know that optimizations can be made in game code. I have said this before, however, assigning an only positive integer as int while uint is possible does not make a lot of sense from a design point of view. It only makes sense in an optimization view when the difference is actually going to improve the client, this is however not the case as you noticed from your tests. I still need someone to reply on my overal algorithm.
Tom
On a side note, I am convinced that when you use data types appropriately, the code will become a lot easier to manage. Being strict in your coding will lead to better code in the end, as you know what's going on. Anyway, that's another subject, I hope we can drop this subject and get more into the problem, which probably has everything to do with what kind of algorithm is used for movement calculations.
Tom
A: 

I think this is almost certainly because you're up at 80fps. Flash simply can't give a consistent frame rate that fast. Drop down to 30fps and keep testing. Also, try flying the ship in front of an actual background, and I think you'll notice this less.

Iain
Hi, I've tried lower FPSs (including 30). They increase the warping and non-smooth movement by a lot and make things worse. According to my FPS counter, flash is actually able to keep the framerate pretty consistent at 80 FPS.
Tom
+2  A: 

Your code runs smooth to me. No spikes whatsoever. Tested it with the following code added at the end of the updatePoller function.

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;

The 100 fps version tends to get non-uniform patterns, but it's normal because based on your calculation, it can't be possible to render 100 frames in a second, if calculating a frame takes more than 10 ms. So, for me at least, the last code runs smoothly, on 30fps.

As for the fuzzy part, a major dooh, and hopefully you won't get mad with me asking: Is there any chance that the fuzzy / blurry effect is because your Monitor? Even at 10 ms response time on an LCD Monitor, a white rapidly moving something imposed on a static black background, tends to look blurry.

Virusescu
I'm getting non-uniform patterns until framerate 70. At 70 and higher (including 100), the pattern is uniform. Anyway, it does seem to be flickering. I have a 2MS Samsung 22inch LCD monitor, it should be pretty good.
Tom
To sum up a little. Rendering problems in such a small applications are rarely caused by the actual frame code. The biggest processor hog is the actual rendering. The bigger a part of the screen changes (can be seen with the "Show Redraw Regions..." Option.Can you look up into your processes and check out how much processor power uses this flash app? Try to close everything. In order to lose frames like that, there should also be spikes in the CPU Usage. I experience a smooth running with your example on Intel Core 2 Duo 2.2Ghz E4500 2GB Ram. It seems a LOT slower than your machine.
Virusescu
A: 

The files to download is not exist (http://feedpostal.com/test/MovementTest.rar).

Sorry about that, but I considered this thread closed and thus deleted all the corresponding files from my server.
Tom
A: 

I've answered another question relating to this issue, read below:

I feel your pain as I'm currently in the trenches developing my own game. At default settings, the Flash renderer produces horrible screen tearing / v-sync issues, regardless of what code you produce.

This is why I was pleased to have found the most simple, elegant answer, that wasn't re-factoring code (which doesn't help a single bit, the problem is the Flash player, not code).

Just enable Hardware Acceleration in your Publish Settings. There's two different options:

Level 1: Direct; and Level 2: GPU.

Read more about it at the official documentation: Specify publish settings for SWF files, and decide what option is best for your game.

Target market does play a factor here, if it's a serious game for gamers, you don't need to worry about possible performance issues, as most gamers have GPU's.

This article did not provide me with the solution specifically, but lead me in the right direction. BUT, if your game is going to be in a browser window, you might have to use the same technique of setting wmode to direct or gpu as well.

Daniel Carvalho