Page 1 of 1

Dynamic Object Floating Through Static Object

Posted: Thu Jul 05, 2012 7:00 pm
by hmcgames12
Hello,

We are designing a platformer game in Cocos2D using Chipmunk physics, and we find that our main character (a dynamic object) does not collide with our platform (a static object) as expected. When the character is above the platform and falls onto it, the collision is fine - the character lands on the platform as expected. However, when the platform is low enough and the main character jumps from underneath it, the character slows down and moves to the top of the platform, almost as if it is sucked in.

We are using Xcode 4.3.3, Cocos2D 1.0.1, and the built in Chipmunk Physics version that comes with these.

Our main character is defined in a class that inherits from CPSprite_Dynamic (that creates dynamic Chipmunk objects). This is the code for that class:

CPSprite_Dynamic.m

Code: Select all

#import "CPSprite_Dynamic.h"

@implementation CPSprite_Dynamic
@synthesize body;


- (id)initWithSpace:(cpSpace *)theSpace location:(CGPoint)location spriteWithFile:(NSString *)spriteFrameName {
    
    if ((self = [super initWithFile:spriteFrameName])) {
        
        space = theSpace;
        [self createBodyAtLocation:location];
        canBeDestroyed = YES;
        
    }
    return self;
    
}

- (void)update {    
    self.position = body->p;
    self.rotation = CC_RADIANS_TO_DEGREES(-1 * body->a);
}

- (void)createBodyAtLocation:(CGPoint)location {
    
    float mass = 1.0f;
    body = cpBodyNew(mass, cpMomentForBox(mass, self.contentSize.width, self.contentSize.height));
    body->p = location;
    body->data = self;
    cpSpaceAddBody(space, body);
    
    shape = cpBoxShapeNew(body, self.contentSize.width, self.contentSize.height);
    shape->e = 0.3f; 
    shape->u = 1.0f;
    shape->data = self;
    cpSpaceAddShape(space, shape);
    
}

Our platform is defined in a class that inherits from CPSprite_Static (which creates static chipmunk objects). This is the code for that class:

CPSprite_Static.m

Code: Select all

#import "CPSprite_Static.h"

@implementation CPSprite_Static
@synthesize body;


- (void)update {    
    self.position = body->p;
    self.rotation = CC_RADIANS_TO_DEGREES(-1 * body->a);
}

- (void)createBodyAtLocation:(CGPoint)location {
    
    
    body = cpBodyNewStatic();
    body->p = location;
    body->data = self;
    //cpSpaceAddBody(space, body);   //this line made our object picture fall due to gravity, so it's out.
    
    shape = cpBoxShapeNew(body, self.contentSize.width, self.contentSize.height);
    shape->e = 0.0f; 
    shape->u = 1.0f;
    shape->data = self;
    shape->collision_type = 1;
    cpSpaceAddShape(space, shape);
     
    
    
}

- (id)initWithSpace:(cpSpace *)theSpace location:(CGPoint)location spriteWithFile:(NSString *)spriteFrameName {
    
    if ((self = [super initWithFile:spriteFrameName])) {
        
        space = theSpace;
        [self createBodyAtLocation:location];
        canBeDestroyed = YES;
        
    }
    return self;
    
}

We have tried downsizing our time step to increase the frequency of collision checks, but that did not work for us. Is this a bug that others have experienced? Please let us know if you have any solutions! Thanks :)

Re: Dynamic Object Floating Through Static Object

Posted: Thu Jul 05, 2012 11:43 pm
by slembcke
You cannot move a static body (it wouldn't be static if it moved). By telling Chipmunk that a body is static, you are saying that it's collision detection information should never need to be recalculated and that it's safe for objects to fall asleep when they touch it. It is possible to notify Chipmunk that a static shape has move using one of the following cpSpace functions though. http://chipmunk-physics.net/release/Chi ... alIndexing If you are moving the static shape every frame, you should be using a rogue body instead however.

Also, you are only setting the position of the body when you move it. That's going to make the physics of the platform work very poorly. Read here for an explanation of why: http://chipmunk-physics.net/forum/viewt ... f=4&t=2227

Re: Dynamic Object Floating Through Static Object

Posted: Fri Jul 06, 2012 1:53 pm
by hmcgames12
Hello Slembcke,

Thank you for your response! I believe that I described my problem poorly/my code reflects it poorly, however. We never try to move the platform - it indeed remains static - but for some reason if we do not include an update function, the sprite does not display properly on the screen. But that's another problem entirely.

Also, we have a main update loop that is called periodically, so the positions of the characters and platforms are actually updated often (not just when the objects are moved).

The only part of the collision we are concerned about is that the main character (a dragon) does not "hit its head" on the platform when it jumps from underneath it. The platform stays still in all frames, as it should, but the dragon goes up through the platform instead of hitting its head on the platform and falling down. Basically, the collision between the static and the dynamic object is detected, as it should be, but the dynamic object is not reacting properly. How can we fix this (so that the dragon falls down after hitting the bottom of the platform rather than "falling up"?)

Thanks again!

Re: Dynamic Object Floating Through Static Object

Posted: Fri Jul 06, 2012 2:02 pm
by slembcke
Oh. Derp. I read the update method too quickly and misread it. Never mind about that.

I'm not really sure what would be causing your issues then. What does your jump function look like?

Re: Dynamic Object Floating Through Static Object

Posted: Fri Jul 06, 2012 2:17 pm
by hmcgames12
Our jumping is done by means of a jump button. The code for the character's reaction is called in our main update loop. This is the entire update loop:

Code: Select all

- (void)update:(ccTime)dt {
    cpSpaceStep(space, dt);
    [block1 update];
    [dragon update];
    [grassPlatform update];
    
    CGPoint vel = ccpMult(dPad.joystick.velocity, 7000 * dt);
    // Moving the sprite with the Dpad.
	if (vel.x != 0 && vel.y != 0)
	{
        dragon.body->p = CGPointMake(dragon.position.x+ vel.x * dt , dragon.position.y + vel.y * dt);
	}
    
    
    //Moving the sprite with the jump button (+Dpad)
    if (jump.button.active == YES)
    {
        jumpingStartPosY = dragon.position.y;
        dragon.body->p = CGPointMake(dragon.position.x, dragon.position.y + dt*1000.0f);
        jumping = YES;
    }
    
    
    if (jumping && dragon.position.y < exJumpingPosY)
    {
        jumping = NO;
        exJumpingPosY = 0.0f;
    }
     
    
    if (jumping && dragon.position.y < jumpingStartPosY+300)
    {
        exJumpingPosY = dragon.position.y;
        dragon.body->p = CGPointMake(dragon.position.x, dragon.position.y + dt*1000.0f);
    }
    
    if (jumping && dragon.position.y >jumpingStartPosY+300)
    {
        jumping = NO;
        exJumpingPosY = 0.0f;
    }
    
    
    if (jump.button.active && dPad.joystick.isBeingMoved)
    {
        jumping = YES;
        jumpingDiagonally = YES;
        diagonalJumpXVel = vel.x;
        jumpingStartPosY = dragon.position.y;
        exJumpingPosY = dragon.position.y;
        dragon.body->p = CGPointMake(dragon.position.x+ diagonalJumpXVel * dt , dragon.position.y +dt*1000.0f);
    }
    
    if (jumpingDiagonally && dragon.position.y < jumpingStartPosY+300 && jumping)
    {
        exJumpingPosY = dragon.position.y;
        dragon.body->p = CGPointMake(dragon.position.x+ diagonalJumpXVel * dt , dragon.position.y +dt*1000.0f);
    }
    
    if (jumpingDiagonally && dragon.position.y > jumpingStartPosY+300 && jumping)
    {
        jumpingDiagonally = YES;
        jumping = NO;
         exJumpingPosY = 0.0f;
    }
    
    
    if (jumpingDiagonally && dragon.position.y <120)
    {
        jumpingDiagonally = NO;
    }
    
}

Basically, the dragon moves up 300 beyond its starting y position in a vertical jump when the jump button is pressed. We haven't had a chance to test the diagonal jumping on our simulator (since the jump button and the DPad are used simultaneously), but I included the code just in case it's causing the issue.

Re: Dynamic Object Floating Through Static Object

Posted: Mon Jul 09, 2012 8:58 am
by slembcke
Ah. I suspected something like that.

So by applying the velocity and setting the position yourself, you are basically undoing all the work that the physics engine is doing. When it collides with the platform and stops its upward movement, you are continuing to push it into the platform anyway. It's trying to keep it out of the platform, but you are overwriting it's position and using a velocity that doesn't match the one Chipmunk is using.

The simplest way to make a character jump is to just "toss" them into the air by changing the velocity over one frame. playerBody->v.y = 100 or something similar. This is very simplistic though and I'm guessing not what you are looking for. I made some very complete platformer controls for a contest game last year. You can find the source code here:
https://github.com/maximile/Your-Story/ ... haracter.m

Re: Dynamic Object Floating Through Static Object

Posted: Mon Jul 09, 2012 12:57 pm
by hmcgames12
Ah yes, that was the problem exactly! Thank you so much, Slembcke!