Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gamestate.switch should halt current state cycle #46

Closed
karai17 opened this issue Apr 18, 2015 · 14 comments
Closed

Gamestate.switch should halt current state cycle #46

karai17 opened this issue Apr 18, 2015 · 14 comments

Comments

@karai17
Copy link
Contributor

karai17 commented Apr 18, 2015

Currently when you switch Gamestates, Gamestate.leave is called immediately but the previous state still runs through its update/draw cycle one last time instead of canceling and switching to the new state. This causes lots of frustrating bugs when trying to deconstruct a state using Gamestate.leave to nil out some data.

It would be nice if Gamestate.switch would stop all actions, call leave, and go to the next state without finishing the current update/draw cycle.

@shakesoda
Copy link

Yeah, this was really biting us during LD. We had to just have a first_update flag on all of our gamestates that would make every function return early if update hadn't been run at least once yet. It'd be nice if GS took care of that by itself.

@karai17
Copy link
Contributor Author

karai17 commented Apr 24, 2015

Here is a very simple code example of this issue occuring.

@shakesoda
Copy link

I think that's not the issue we were having, that's unrelated (and I don't think there's anything gamestate can do automatically here, just being sure to return if needed). I think our issue was that when switching to a new state, it's possible for the first update to be skipped. enter() -> draw() -> update() would happen, so draw() could happen when things are in a bad state. the workarounds for this are either calling update yourself at the end of enter or putting guards on all the functions so they can't happen before the first update. I'm not sure any automatic way of doing this is good, now that I think about it, because what needs to happen depends on when, exactly, you're switching state.

The only thing I can think of that would really make that go away is if the GS switch got queued to happen post-draw.

@kd7tck
Copy link

kd7tck commented May 10, 2015

This is not a bug on gamestate side. Rather a bug on the lua side. Function calls are not processes that can be killed half way through, at least in LUA 5.2.

@karai17
Copy link
Contributor Author

karai17 commented May 10, 2015

The issue isn't necessarily that we need Lua to halt a function, but after that function, but the game state itself should be halted. Gamestate should set a flag when switch is called that tells the next callback and all of them thereafter to return, then execute that state's leave, and start the new state's cycle after draw is returned.

@vrld vrld closed this as completed in 3c666c5 May 30, 2015
@vrld
Copy link
Owner

vrld commented May 30, 2015

Fixed using a dirty flag as karai17 suggested. The dirty flag prevents callbacks to be processed until update() is called. return GS.switch(to, ...) should be used to cancel the function calling switch() (or pop()/push()). However, this only works if the switch occurs in a callback, not when it done in deeper stack levels. I don't think there is a (clean) way for hump to handle this.

@giann
Copy link

giann commented Dec 20, 2016

I don't think this was an issue.
I would like to be able to have a "stacking" effect of my states.
For example I would like to use a state that draw a dialog, but I still want the previous state (the game itself) to be drawn and updated.
To me it make only sense for the input (keypressed, etc.) functions to be only called for the current state.

Like so

@karai17
Copy link
Contributor Author

karai17 commented Dec 21, 2016

That is out of scope for this issue. The issue was that switching to a new state caused issues because it would switch immediately and not properly initialize the new state.

What you are looking for is something entirely different.

@eevee
Copy link

eevee commented Dec 29, 2016

It seems that this fix causes a single black frame to be drawn on the tic the gamestate is changed from update, since draw is never called.

The fix I've seen used before is to defer a change of gamestates until between frames.

@karai17
Copy link
Contributor Author

karai17 commented Dec 29, 2016

that does not happen for me.

@eevee
Copy link

eevee commented Dec 29, 2016

I don't understand how not? It skips the rest of the callbacks, that includes draw, and love.run() clears the screen before drawing.

@shakesoda
Copy link

shakesoda commented Dec 29, 2016 via email

@karai17
Copy link
Contributor Author

karai17 commented Dec 29, 2016

i was about to suggest that. we use a custom love.run

@KayleMaster
Copy link

That dirty flag cost me a couple days of work to track down the reason why a black screen appears with the default love run. I can't believe 3c666c5 never got reverted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants