Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: How to "blend" two states?  (Read 3103 times)

0 Members and 1 Guest are viewing this topic.

buymespam

  • Newbie
  • *
  • Posts: 6
    • View Profile
How to "blend" two states?
« on: July 11, 2014, 08:46:15 am »
So I was learning how to use SFML on my own for fun, but I've realized when things are moving at a medium speed, my screen gets a little choppy. Poking around the forums (which I should've done a long time ago...) I found countless links to http://gafferongames.com/game-physics/fix-your-timestep/ .

I just don't know how to implement this! My home-made loop is almost identical, except I don't have the last step of "combining" two different states into one in order to draw an "in-between" representative. (I also don't have a fancy state-updating function a la integrate-- but everything moves linearly in what I've made so that's okay.)

I currently just have a sf::RenderWindow that I draw everything on, and then display that window, and repeat. How would I do the following in SFML?

State state = currentState * alpha + previousState * ( 1.0 - alpha );

I'm sorry if this is a common question, as it probably is. I tried to search, but I don't think I know the proper terminology, so searching was fruitless.

Thank you!

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: How to "blend" two states?
« Reply #1 on: July 11, 2014, 08:55:15 am »
The simplest way is
Entity.move(horizontal speed * deltatime,vertical speed * deltatime);
 
Movement speed equals something like 200 pixels per second so that when multiplied by a number usually around 15 to 30-60 milliseconds you'll have a directly proportional movement. You must use a sf::Clock and call clock.restart().asSeconds() each frame for your deltatime.

buymespam

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: How to "blend" two states?
« Reply #2 on: July 11, 2014, 09:00:26 am »
The simplest way is
Entity.move(horizontal speed * deltatime,vertical speed * deltatime);
 
Movement speed equals something like 200 pixels per second so that when multiplied by a number usually around 15 to 30-60 milliseconds you'll have a directly proportional movement. You must use a sf::Clock and call clock.restart().asSeconds() each frame for your deltatime.

Thanks, but that's unrelated to my issue.

If I know what the screen looks like at time T1 = 1.00 seconds, and I know what the screen looks like at time T2 = 1.05 seconds, I want to be able to draw the game at a time T3 = 1.01 seconds as if it were a blend of 80% T1 and 20% T2. I want to know how to do do that.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to "blend" two states?
« Reply #3 on: July 11, 2014, 09:04:19 am »
Simply put, it means that you should apply that calculation to all variables.

The "state" in this case is just what all the values are at that point. This "alpha blending" requires the previous state as well as the current one which means that you need access to all of the values that were "current" in the previous cycle. You then calculate them against the new current ones to blend them into an inbetween value.

p.s. It's not blending (visually) from one screen display to another, it's blending from one value to its successor as to get a more accurate value based on the time past (more specifically, it's going backwards in time by the amount of currently unprocessed time).
« Last Edit: July 11, 2014, 09:07:29 am by Golden Eagle »
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

buymespam

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: How to "blend" two states?
« Reply #4 on: July 11, 2014, 09:12:28 am »
Simply put, it means that you should apply that calculation to all variables.

The "state" in this case is just what all the values are at that point. This "alpha blending" requires the previous state as well as the current one which means that you need access to all of the values that were "current" in the previous cycle. You then calculate them against the new current ones to blend them into an inbetween value.

Yeah, I understand that, I was just wondering if there was an easy, built in way to manage these.

For instance (and I don't know how everything works on the inside, so I can't speak to how feasible this is):

Instead of drawing everything on window.draw(...), I would instead have an intermediary: newframe and oldframe.

Where I would normally call window.draw(...), I would instead call newframe.draw(...). When a new frame is done drawing, the old frame is assigned to the new frame, and newframe.draw(...) is called again.

Now when it's time to do window.display() in my example, I just do window.display(0.8 * oldframe + 0.2 * newframe) ,or something with similar results and different syntax. Then I would call window.display(), and it would properly merge the two images such that they are now the combination of the two frames.

Is this easily done, or would I have to manually keep track of the "old" and "new" for each object I deal with?

Thank you for your help.

EDIT:

Are you certain that in the link provided, he is not implying that it's not a "visual blending" from one value to its successor? That's the impression I got from the article. I'm a little more confused then, if it's going backwards in time by the as-of-yet unprocessed time, because it seems like that would take rendering an entire frame all over again!
« Last Edit: July 11, 2014, 09:14:12 am by buymespam »

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to "blend" two states?
« Reply #5 on: July 11, 2014, 09:43:58 am »
It's not re-rendering a frame. It's deciding on where the positions etc. are in time before rendering them. As he describes, this means that each frame is always up to a frame behind. It's a bit like always rendering the previous frame instead of the current one by using previous values. Then, using the current values as if they were in the future, you can "predict" where the values will be. The left-over time decides where in time between the two frames you are, and then you calculate the values that lie between them.

If you wanted to insist on wanting to visually blend one screen into another, you can render to a couple of renderTextures instead and display them both as sprites, changing the opacity of the one above. This can be slow, especially at high resolutions.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

buymespam

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: How to "blend" two states?
« Reply #6 on: July 11, 2014, 09:50:43 am »
Oh, I see. I had incorrectly connected state and frame in my head.

So in this example, while the velocity of an object may be changing in a non-linear fashion, we can use a linear approximation to get the position at time 1.01 in my case? Since it's the best we can (efficiently) do?

How do you (or what is a good manner to) keep a copy of "old" and "new" state for each time step?

Is there a more convenient way of doing this than having two containers, one designated "old" and one designated "new," and then having a "todraw" container that does the aforementioned linear approximation for position?

I'm having trouble thinking of how I would deal with the "new" container having more or fewer elements than the "old" one. For instance in the case of object creation or destruction, how would I properly estimate the position of an object that ceases to exist in the next state?

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to "blend" two states?
« Reply #7 on: July 11, 2014, 04:52:46 pm »
Yes, the simplest way would be just to copy the object that stores the values. These objects should not contain resources (images, sounds etc.) - use the normal objects as "current" and the copy/ies as "previous".

The linear blending is a step up from not blending at all and can help to display smoother animation. However, it is possible to blend non-linearly. To blend accurately, this would require more integration (running the integration/physics from the previous state up until the blended time. This is overkill. There are other blending techniques too;you can take derivation into account when calculating the blend e.g. use the current velocity to interpret an intermediate position. This would require more complicated blending calcuations. I'm not sure but I think it's mentioned in that article. It could be on the integration section, or maybe in the comments.

A third object would probably not be necessary as the calculations can be done as required, using the two objects.

Remember that you aren't technically predicting the "next" state; you're 'tweening the previous state so no prediction is actually necessary. If an object no longer exists (i.e. doesn't exist in the current state", it's fine to just not display it. If it now does exist but didn't previously, you can either use the current state as its blended state (ignoring the previous state and no need to blend), or also just not displaying it until the next frame so it has a previous state to calculate from. The former is probably better. Frames are very short so there is no need to "blend" between non-existing and existing. The blending is to create visually smoother movement; it's not really noticeable whether an image is exists on one frame or the one before it.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: How to "blend" two states?
« Reply #8 on: July 12, 2014, 08:30:54 am »
This is popular technique used for multiplayer games. I would try to separate state from the entity and have something like entity.draw(state1, state2, dT).
SFML.Utils - useful extensions for SFML.Net

 

anything