Ticket #36 (closed defect: fixed)

Opened 3 years ago

Last modified 3 years ago

Velocities do not 'tick' correctly

Reported by: knowknowledge Owned by: knowknowledge
Priority: critical Milestone: 0.4.0
Component: Video Version:
Keywords: Cc:

Description

All velocities should move sprites based on the time since the last 'tick' in a way that creates the same illusion of speed regardless of the framerate.

Currently, slower framerates cause movement to be much slower than normal. This means that ships turn jerkily and weapons do not fire as far on slower systems.

While we should try to avoid low framerates caused by slow algorithms, many systems will run at below maximum framerates. It is important to have the same gameplay regardless.

Change History

comment:1 Changed 3 years ago by chris

  • Milestone set to 0.2.0

Please see the 'Fixed Frame Pig' demo at http://olofson.net/mixed.html for a great example of how to do this.

Basically, the work should be done in the Timer class. The Timer class then has a function like GetDelta?() which is a multiplier to be used against all position updates. That way, if Timer::Pause() is called, GetDelta?() will return 0s to ensure that if the logic loop is run, we don't end up moving anything.

comment:2 Changed 3 years ago by chris

Arke has indicated he's interested in working on this (and he'd do a good job) but he won't be able to meet the January deadline. We might want to do just a little work on this and push it to 0.3.0 for him.

comment:3 Changed 3 years ago by knowknowledge

  • Owner changed from somebody to chris
  • Status changed from new to assigned
  • Milestone changed from 0.2.0 to 0.3.0

Chris started to implement a virtual framerate timer.

comment:4 Changed 3 years ago by knowknowledge

Multiple draw steps per update step causes the Engine Animation to flicker.

The current engine draw logic 'turns itself off' after every draw, but turns on only when it is updated.

comment:5 Changed 3 years ago by knowknowledge

The current implementation of the virtual timer does not work great with the new "Update Wave" code introduced by gsweeney (Changeset 44cb2dbd170aebf070120bf2b9c1f6542517e303).

Ships that are outside of the inner most update ring (2 QUADRANTS) will move slowly compared to the ships that are nearer the camera.

We should consider adding a 'last update time' attribute to sprites, and do any interpolation calculations based on that rather than the Timer::GetDelta?() value.

Of course, moving half speed is better than the previous implementation. Ships and Projectiles would come to dead stop outside of the 2 QUADRANTS, creating a ring of frozen sprites at the Quadrant boundaries. So this may be a non-issue.

comment:6 Changed 3 years ago by gsweeney

To be honest, that's something I should have done in the first place - I saw the issue with them slowing down outside the inner box but didn't think of modifying the size of the updates to compensate. Little bit outside the scope of the original ticket but still.

Is there anything else to do with this ticket, apart from that?

comment:7 Changed 3 years ago by knowknowledge

I need to study the Virtual Timer more, but I've seen the game slow to a dead stop and I think that it's because the virtual timer implementation doesn't have a short-circuiting mechanism. If the framerate drops, (most likely due to the Update loop being too costly), the current virtual timer will issue more update loops!

I may be misreading this though, so the Timer::Update could definitely use more comments.

The current solution to this problem was to add a hard abort when the framerate dropped below 0.1 fps. (Changeset 647f9f51) I don't particularly like this solution, but it seems better than a deadlocked game.

comment:8 Changed 3 years ago by chris

I think I'm responsible for this and I can look over it though I've not personally seen the game completely stand still. The virtual timer basically enforces a certain 'logical framerate' (a framerate which will always occur, if possible, regardless of the speed of the computer), by varying the number of update loops run and skipping some draw cycles. It's possible we need to add a forced draw cycle.

What we should even do, is force say, a 16fps draw cycle minimum, and if the game cannot run at least 16 draw cycles and perhaps 10 logic loops per second, give a warning that their computer is too slow to play Epiar (because it is - we would no longer have enough time to run the logic _and_ draw).

comment:9 Changed 3 years ago by gsweeney

Chris, if it's ok with you I can take ownership of this? Ties into the wave update changes I made and I can look over the rest of the area as well.

comment:10 Changed 3 years ago by chris

Go for it!

comment:11 Changed 3 years ago by gsweeney

  • Owner changed from chris to gsweeney
  • Status changed from assigned to accepted

comment:12 Changed 3 years ago by knowknowledge

gsweeney, I'm sure that you already have something in mind, but it would be cool if the update-wave and update-all settings were dependent on the current game performance. For example, if everything is running great, Epiar should always run Update-all, but as the fps drops, the update-wave should pull in and limit the number of ships that get updated in any given update loop.

comment:13 Changed 3 years ago by chris

I believe if you put the update-wave in the regular logic loop update, you won't need to touch the timer at all.

The timer already times each loop and calculates whether it needs to run more or less loops. To re-program it or augment it would be to under-utilize the existing code imo.

comment:14 Changed 3 years ago by gsweeney

Matt - yep, and that's in a ticket that I opened when I finished the original update-wave stuff (http://epiar.net/trac/ticket/73). Once fps drops below a certain threshold then switch from update-all to update-wave.

Chris - may not have to touch the timer, but I have to change it so that some sprites can be updated 'more' than others depending on where they are. I need to have a good look at the code before knowing exactly where I'm looking at here, but basically - right now, when in update-wave mode, the sprites outside the closest quadrants move at 1/4 the speed of those inside as they are updated 1/4 of the time. I'll need them to move 4* the amount per update to compensate.

comment:15 Changed 3 years ago by knowknowledge

  • Owner changed from gsweeney to knowknowledge

This seems to be working well. Closing this for now.

comment:16 Changed 3 years ago by knowknowledge

  • Status changed from accepted to closed
  • Resolution set to fixed
Note: See TracTickets for help on using tickets.