Strange chipmunk performance with 3.0 OS!!

Official forum for the Chipmunk2D Physics Library.
Johanovski
Posts: 24
Joined: Thu Apr 29, 2010 5:07 am
Contact:

Strange chipmunk performance with 3.0 OS!!

Post by Johanovski »

Hi there!

I'm working in a Cocos2D + Chipmunk project which is nearly finished. I've been testing it on my own iPhone 3GS with 3.1.3 OS and everything works wonderfully. However today I've tested the project with an iPhone 1G with 3.0 OS, and I got really surprised when I saw that physics doesn't always work as they used to.
For example, in the 3GS iPhone a cube ALWAYS collides with ALL level walls (as expected). However with the 1G sometimes a cube just passes through a wall of cubes (which is completely senseless for me)! I've never seen this on my 3GS and it's pretty usual on the 1G... Also the game usually runs at 60 FPS on the 3GS, but in the 1G it runs only at 40 FPS or less depending on how many elements are in the screen (from 40 to 20 FPS more or less)... I've tried forcing the game at 40 FPS or even 30 FPS but it still does the same, so I think it's not related to performance...

Can it be caused by the firmware? I mean may the 3.0 OS cause this? Or maybe it's related to the iPhone itself (so chipmunk doesn't work as expected in the 1G)?

Thanks in advance, I'm really stuck with this and I don't know how to solve it... :(
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by slembcke »

Are you using a variable sized timestep? Using fixed sized timesteps with Chipmunk is very very recommended.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
mobilebros
Posts: 90
Joined: Tue Aug 04, 2009 9:53 am
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by mobilebros »

I think you must be using a variable sized timestep, the 1G's hardware is quite a bit slower than the 3GS, hence your framerate; your scheduled timestep is getting called with a greater dt between calls, thus making chipmunk calculate object's positions "past" the walls.

This'll help optimize the speed a bit
http://www.cocos2d-iphone.org/wiki/doku ... _practices
Johanovski
Posts: 24
Joined: Thu Apr 29, 2010 5:07 am
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by Johanovski »

Hi there!

Thanks for your replies, they are really helpful! :)

I've checked the link about improve Cocos2D performance and I've done a couple of things that made me win about 10 FPS in the iPhone 1G (so now the game runs at about 50 FPS, which is quite more acceptable than 30-40 FPS)! I've also modified my own scene update methods to link them to the delta time (so now even if the game runs beyond 60 FPS game logic is processed correctly -I think this is how chipmunk works, isn't it?-).
There's only one thing that isn't clear for me (and I think this is one of the most important things): timesteps (both of you told me about them)!

Well, at the beginning I had steps as a static variable:

Code: Select all

-(void) step: (ccTime) delta
{
	int steps = 2;
	CGFloat dt = delta/(CGFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
	cpSpaceHashEach(space->activeShapes, &eachShape, nil);
	cpSpaceHashEach(space->staticShapes, &eachShape, nil);

	[self updateScene:delta];
}
This works great with the 3GS, but crashes with the 1G as I told you. Then' I've tried the following:

Code: Select all

-(void) step: (ccTime) delta
{
	int steps = 10;
	CGFloat dt = delta/(CGFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
	cpSpaceHashEach(space->activeShapes, &eachShape, nil);
	cpSpaceHashEach(space->staticShapes, &eachShape, nil);

	[self updateScene:delta];
}
Let's rock! 10 steps instead of 2! With this the game runs well in the iPhone 1G! However, I suppose this can waste a lot of resources because the game may need only 4 or 6 steps and every time chipmunk is doing 10 steps, so now I've done the following:

Code: Select all

-(void) step: (ccTime) delta
{
	// 60 FPS means a standard delta of 0.01666
        // so if FPS are less than 0.01666 steps will increase, 
        // and if not steps will be 2 as they were at the beginning
		
	int steps = (int)( delta / 0.01666 ) + 1;
	if (steps < 2) {
		steps = 2;
	}

	CGFloat dt = delta/(CGFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
	cpSpaceHashEach(space->activeShapes, &eachShape, nil);
	cpSpaceHashEach(space->staticShapes, &eachShape, nil);

	[self updateScene:delta];
}
Which method do you recommend, the second or the third one? I mean it's OK to calculate how many steps will be needed at every loop or it's better to have always more steps than normally needed to ensure it will work?

Thanks in advance for your time! :)


PS: Sorry for my english, it isn't as good as I want...
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by slembcke »

Your third one is closer, but still not quite right. You are still calculating dt based on delta. The best thing you can do is to pass the exact same value to cpSpaceStep() every time. Read this: Gaffer on Games: Fix Your Timestep
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Johanovski
Posts: 24
Joined: Thu Apr 29, 2010 5:07 am
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by Johanovski »

Hi there!

Thanks for your replies! :)
I've read the link you've posted and, after a couple hours of headache, I think I've understood how it should work, so I've modified my step method like this:

Code: Select all

// In the initialization function (of course these are global variables though I write like local ones in this post):
float currentTime = CFAbsoluteTimeGetCurrent();
float accumulator = 0.0f;
float dt = 1.0f/60.0f;   // 60 times per second will be enough...

// Inside the "step" method:
float newTime = CFAbsoluteTimeGetCurrent();
		float deltaTime = newTime - currentTime;
		currentTime = newTime;

		accumulator += deltaTime;
		
		while (accumulator >= dt) {
			cpSpaceStep(space, dt);
			cpSpaceHashEach(space->activeShapes, &eachShape, nil);
			cpSpaceHashEach(space->staticShapes, &eachShape, nil);
			
			accumulator -= dt;
		}	
		
		[self updateScene:delta];
Which are the problems here? Well, seems that time variables are REALLY huge here, so at every step deltaTime is equal to 32 (integer!) or something like that, so it doesn't work as expected because accumulator decrease each time only (1.0f/60.0f), and this makes the "while" loop really long...
Is this the right way to do this? What I'm doing wrong then? How can I solve this?

EDIT: Wow, and I've forgotten! My "updateScene" method processes all special collisions (such as switches, traps, etc), should I include the "[self updateScene]" method INSIDE the while loop? If not, though the physic get processed well, the game may not detect when the player touches a switch, for example, so I think I should put the method inside the loop, shouldn't I? And the same with the "cpSpaceHashEach" functions... should they be inside the loop as I've put?

Thanks for your posts, they are really helpful! :)
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by slembcke »

If the game can't always keep up with real time or worse, that it never can, you can end up with some really long running while loops to catch up to the current time as you've found. The best solution to that is use a frameskip counter. Simply break out of the while loop if it runs more than 3 or 4 times.

Basically, it forces the game to slow down to the same speed that the hardware can keep up with. While not a desirable effect, it's better than a completely unplayable game on low end hardware. Fancier algorithms can only get you so far.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
mobilebros
Posts: 90
Joined: Tue Aug 04, 2009 9:53 am
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by mobilebros »

These should go outside the while loop:

Code: Select all

   cpSpaceHashEach(space->activeShapes, &eachShape, nil);
   cpSpaceHashEach(space->staticShapes, &eachShape, nil);
Since they're (most likely) just updating your sprites pos and rot, you're just slowing down the while loop because nothing will be being drawn while you're in that loop.

p.s. Sometimes doing eachShape for all the staticShapes is an unnecessary step, may be worth it to ditch it if possible.
Johanovski
Posts: 24
Joined: Thu Apr 29, 2010 5:07 am
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by Johanovski »

Hi there!

Thanks both for your help, I've done some arrangements to my step method and now the game runs fine both in the 3GS and in the 1G! :)
I've kept my delta-based timestep with variable steps because the last method I've done (the one that uses the accumulator, etc) didn't seem to work better (even seem to work worst), so my step method now is:

Code: Select all

-(void) step: (ccTime) delta
{
	int steps = (int)( delta / (1.0f / 60.0f) ) + 1;
	if (steps < 2) {
		steps = 2;
	}

	CGFloat dt = delta/(CGFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);			
	}	
		
	cpSpaceHashEach(space->activeShapes, &eachShape, nil);
	cpSpaceHashEach(space->staticShapes, &eachShape, nil);
		
	[self updateScene:delta];   // DOUBT ABOUT THIS METHOD...
}
My only question is if I should put the [self updateScene] method inside the "for" loop... It's a self-made method where I check if the player passes through a switch or touches a body that have some special properties (which chipmunk couldn't process), so should I put it inside the loop? If not maybe a body can do some steps, pass through a switch but the game may not get advice of that (let's say a body is just 1 pixel far from a special object -which is not a chipmunk body, just a sprite and a self-made object with it's own properties-, the game drops it's frame-rate suddenly due to a performance issue and the loop does 10 steps, so after those 10 steps the body is 40 steps more far than it was, resulting the body passing through the special object, but when the updateScene function is called the body have just passes through the object before checking if it even touched it... I don't know if I'm explaining it right -poor english + strange problem = terrible explanation ^_^-)...

Thanks for your help! :)
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Strange chipmunk performance with 3.0 OS!!

Post by slembcke »

I guess I don't really understand what this update scene method does. It depends on how robust it is I guess.

I would still not recommend using variable sized timesteps and guessing when objects passed through each other, but if you are happy with how it works now I can't argue with that.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Post Reply

Who is online

Users browsing this forum: No registered users and 36 guests