Long pause on start-up

28 views
Skip to first unread message

Nitneroc

unread,
Jul 30, 2012, 4:01:23 PM7/30/12
to cocos-...@googlegroups.com
I'm sorry for this pretty vague question, but i'm a bit helpless here...

When my game starts, it creates various layers, scrolling_managers, it generates a random landscape and about a thousand sprites and loads a large background. I understand this can take time.

But what's troubling me is that the update() function of my character (which is scheduled), receives this elapsed time parameter :
1st time : 0
2nd time : 0.059187720199 which isn't that a big problem
3d time : 1.53404387161 which is really long
4th time : 0.00426641644389
and then it's always something like 0.00177292282634

The real problem with this 1.5sec is that much should happen during this time, and no collision is tested and the character teleports to strange places
I thought that scheduling the character's update function in on_enter() could solve the problem but it does not.
The character is created after the layers, background, landscape and every other sprite.

Profiling the code proved it was pyglet's clock.py unschedule function that took 1.52sec running, but I don't really know what this means...

I guess you won't be able to help much without my code, but maybe some of you know this problem... Is it something I have to deal with ? Do you think I should create everything that rely on steady fps after some time has passed ?

Thank you very much for reading.

Nitneroc

unread,
Jul 30, 2012, 4:39:29 PM7/30/12
to cocos-...@googlegroups.com
forgot to say I'm running cocos2d 0.5.0 and pyglet 1.2alpha1 on windows 7. This occured with pyglet 1.1.4 too.

claudio canepa

unread,
Jul 30, 2012, 4:55:54 PM7/30/12
to cocos-...@googlegroups.com
On Mon, Jul 30, 2012 at 5:01 PM, Nitneroc <corent...@gmail.com> wrote:
I'm sorry for this pretty vague question, but i'm a bit helpless here...

When my game starts, it creates various layers, scrolling_managers, it generates a random landscape and about a thousand sprites and loads a large background. I understand this can take time.

But what's troubling me is that the update() function of my character (which is scheduled), receives this elapsed time parameter :
1st time : 0
2nd time : 0.059187720199 which isn't that a big problem
3d time : 1.53404387161 which is really long
4th time : 0.00426641644389
and then it's always something like 0.00177292282634


The real problem with this 1.5sec is that much should happen during this time, and no collision is tested and the character teleports to strange places

Understandable.
 
I thought that scheduling the character's update function in on_enter() could solve the problem but it does not.
The character is created after the layers, background, landscape and every other sprite.


If really happens only on startup, an easy but not robust way can be to schedule the update of problematic actors only after a small amount of time after the on_onter.
You can use an action Delay(e) + CallFunc(schedule_the_update) to this end. 

Profiling the code proved it was pyglet's clock.py unschedule function that took 1.52sec running, but I don't really know what this means...


Suspicious, but needs investigation about why so much.
 
I guess you won't be able to help much without my code, but maybe some of you know this problem... Is it something I have to deal with ? Do you think I should create everything that rely on steady fps after some time has passed ?

Thank you very much for reading.

 A common workaround to deal with infrequent big dt's is to intercept the clock and :

if dt > dt_thershold:
    dt = dt_safe

where dt_safe depends on the app.

For consistency is better if the general app clock can be cheated; for pyglet in the general case that is not so straightforward.

But in some situations it suffices to do this dt cropping in the individual update(self, dt) for a handful of problematic entities.

Do you think it can work in your use case ?
   

Nitneroc

unread,
Jul 31, 2012, 8:56:58 AM7/31/12
to cocos-...@googlegroups.com
Thanks for this very interesting answer Claudio !

One again your help is precious ! 


If really happens only on startup, an easy but not robust way can be to schedule the update of problematic actors only after a small amount of time after the on_onter.
You can use an action Delay(e) + CallFunc(schedule_the_update) to this end. 

It only happens on startup, so I could probably do this, but a friend of mine tested the program, and the problem was even worse on his computer. I have no sure way to choose a delay time, and I don't like this kind of hack, but I'll use it if I don't find a better solution.

 
Profiling the code proved it was pyglet's clock.py unschedule function that took 1.52sec running, but I don't really know what this means...


Suspicious, but needs investigation about why so much.

Since I installed pyglet 1.2alpha1, I have the source for pyglet, I might try to investigate a bit more, but as you already realized, i'm not an advanced python user, and it might prove to hard for me.
I don't understand what cocos could unschedule, so it could be interesting to have a look anyway.
 
 A common workaround to deal with infrequent big dt's is to intercept the clock and :

if dt > dt_thershold:
    dt = dt_safe

where dt_safe depends on the app.

For consistency is better if the general app clock can be cheated; for pyglet in the general case that is not so straightforward.

But in some situations it suffices to do this dt cropping in the individual update(self, dt) for a handful of problematic entities.

Do you think it can work in your use case ?

I guess I'll use this solution for now, it should work ok. Or maybe I'll schedule character.update() only after 5 layer updates, since the dt values are always normal after 5 loops.
I don't understand why there is such a slowdown, though. This character sprite is created after everything else. I should have been more careful when it appeared, I don't remember which code commit introduced this lag. Maybe I should go back in modifications to see what caused it.

Nitneroc

unread,
Jul 31, 2012, 4:10:36 PM7/31/12
to cocos-...@googlegroups.com
I made pyglet print the parameters of clock.unschedule every time it was called. It seems a lot of my objects have _step functions, that have to be removed (inherited from CocosNode.
Most of those objects are the Water_Blocks you created for me Claudio (http://pastebin.com/7FYWrDA6), and I use a lot of them, so it seems pretty logical.

I guess this will be very hard to avoid, so I'll stick with one of the above solutions. Yet I read this in the documentation :
Subclassing a cocosnode usually means (one/all) of:
        - overriding __init__ to initialize resources and schedule calbacks
        - create callbacks to handle the advancement of time
        - overriding draw to render the node

So maybe it's possible to avoid those _step functions, especially since those Water_blocks will never have any scheduled action. But this will probably be much too hard for me.

claudio canepa

unread,
Jul 31, 2012, 9:17:02 PM7/31/12
to cocos-...@googlegroups.com
If those nodes will never use actions, you can avoid the schedule / unschedule cost by adding in your CocosNode subclass:

def resume(self):
   """ special version: this skips actions scheduling"""
   pass

def pause(self):
   """ special version: this skips actions scheduling"""
   pass

def do( self, action, target=None ):
   """ special version: this skips actions scheduling"""
   # lets explode if the 'no actions promise' is forgotten
   assert False



   

Nitneroc

unread,
Aug 1, 2012, 8:57:29 AM8/1/12
to cocos-...@googlegroups.com
I'll have to stop asking anything here, or you'll be the author of all my game's code, Claudio ! You're really amazing !
Once again thank you very much, I just had to add your lines of code, and the problem disappeared. dt went from 1.5sec to 0.30sec, what a big change ! that's really amazing, thank you

Le mercredi 1 août 2012 03:17:02 UTC+2, Claudio Canepa a écrit :
Reply all
Reply to author
Forward
0 new messages