Rotating a Rogue Body around a bouncing ball

Official forum for the Chipmunk2D Physics Library.
Post Reply
jsMilton
Posts: 3
Joined: Fri Mar 30, 2012 1:02 pm
Contact:

Rotating a Rogue Body around a bouncing ball

Post by jsMilton »

Hi,

I'm using Chipmunk 6.0.3 (plain C version) to make a simple game (iPad) in which the user can throw balls around inside a square frame. The space inside the frame has no gravity and the ball just bounces around indefinitely, without losing / gaining any speed. I'd like the user to be able to rotate the frame whist the ball is still bouncing, however this is causing some issues for me.

When the frame gets rotated, the path of the ball gets affected in that it starts to curve in the opposite direction that the frame is spinning. This is only a slight curvature, but it is noticeable. Also, the ball sometimes tends to pass through the bounds of the frame, sometimes getting stuck in the edges which causes it to just follow the spinning frame. It's like it's getting sucked in.

These effects only happen when the frame is spinning, and when it is spinning at a slow speed. If the angular velocity is set above 10, everything works well.

As everything is fine when the frame is not rotating, I was wondering if there are things I should be aware of when manually rotating the frame.

I tried adding the cpSpaceReindexShapesForBody method after every rotation, but that didn't help.

The code I'm using is an adapted version of the Tumble demo.

Code: Select all


//Make a space

        cpSpace *room = cpSpaceNew();
        cpSpaceSetGravity(room, cpvzero);
        cpSpaceSetDamping(room, 1.0f);
        cpSpaceSetCollisionSlop(room, 0.9);


//Add an infinite mass rogue body. Bounds is the size of the UIView that holds the frame


    cpBody *squareFrame = cpBodyNew(INFINITY,INFINITY);
    cpBodySetPos(squareFrame, cpv(bounds.size.width * 0.5,bounds.size.width * 0.5));


//Add four segement shapes to the rogue body. These create the frame for the ball bounce around in. The cushion variable is thickness of the segments.


    int size = bounds.size.width;
    cpFloat cushion = 100.0f;
    
    cpVect a = cpv(-(size * 0.5) - cushion, -(size * 0.5) - cushion);
    cpVect b = cpv((size * 0.5) + cushion, -(size * 0.5) - cushion);
    cpVect c = cpv((size * 0.5) + cushion, (size * 0.5) + cushion);
    cpVect d = cpv(-(size * 0.5) - cushion, (size * 0.5) + cushion);
    
    
    cpFloat friction = 0.0f;
    cpFloat elastic = 1.0f;
    cpDataPointer mySelf = (__bridge void*) self;
    
    cpShape *shape2;
    
    shape2 = cpSpaceAddShape(room, cpSegmentShapeNew(squareFrame, a, b, cushion));
    cpShapeSetElasticity(shape2, elastic);
    cpShapeSetFriction(shape2, friction);
    cpShapeSetCollisionType(shape2, 7);
    shape2->data = mySelf;
    
    shape2 = cpSpaceAddShape(room, cpSegmentShapeNew(squareFrame, b, c, cushion));
    cpShapeSetElasticity(shape2, elastic);
    cpShapeSetFriction(shape2, friction);
    cpShapeSetCollisionType(shape2, 8);
    shape2->data = mySelf;
    
    shape2 = cpSpaceAddShape(room, cpSegmentShapeNew(squareFrame, c, d, cushion));
    cpShapeSetElasticity(shape2, elastic);
    cpShapeSetFriction(shape2, friction);
    cpShapeSetCollisionType(shape2, 9);
    shape2->data = mySelf;
    
    shape2 = cpSpaceAddShape(room, cpSegmentShapeNew(squareFrame, d, a, cushion));
    cpShapeSetElasticity(shape2, elastic);
    cpShapeSetFriction(shape2, friction);
    cpShapeSetCollisionType(shape2, 10);
    shape2->data = mySelf;


//This is where the ball gets added to the space. It's triggered by a user touch event. The pt variable is a CGPoint for position, whilst v is a CGPoint for velocity.


    cpFloat mass = 10;
    cpFloat elastic = 1.0f;
    
    cpBody *body = cpBodyNew(mass, INFINITY);
    cpBodySetPos(body, cpv(pt.x, pt.y));
    cpSpaceAddBody(room, body);
    
    cpShape *shape = cpCircleShapeNew(body, 10.0f, cpvzero);
    cpShapeSetElasticity(shape,elastic);
    cpShapeSetFriction(shape, 0.0f);
    cpSpaceAddShape(room, shape);
    
    cpBodyApplyImpulse(shape->body, cpv(v.x * 2.5, v.y * 2.5), cpv(0, 0));


//The update method for the whole thing. Rotation is an external variable, again from a touch event.


    cpBodySetAngVel(room, rotation);
    cpBodyUpdatePosition(squareFrame, dt);
    cpSpaceStep(room, dt);

Apologies for the long post, but I didn't know how else to explain it. Really appreciate any help you could give me.

Thanks,

James
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by slembcke »

You need to update both the angular velocity and position of the frame's body or the collision response won't work correctly.

Think of this simple example: A wall is moving to the right as 5 units/second. You are changing the wall's position at that rate but leave it's velocity at 0. A ball moving left hits that wall and reacts as though the wall were not moving (after all, it's velocity is 0). So now the ball stopped and it's velocity is 0 (it wasn't bouncy at all). Next frame, you move the wall to the right more and it's overlapping the ball now. The collision response runs again but sees that the collision velocities are already resolved. Both have a velocity of 0. They ball and wall are overlapping now, so Chipmunk pushes them apart gently to resolve the overlap (but possibly less than at 5 units/second).

The same thing happens with the angular velocity, it's just a little more complicated. What I do in the Tumble demo is to set the angular velocity of the rotating box at init time and then each frame call cpBodyUpdatePosition() which updates the position (and angle) based on its velocities. So the velocity and positions never get out of sync. You can do the same, you just need to calculate the angular velocity you want.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
jsMilton
Posts: 3
Joined: Fri Mar 30, 2012 1:02 pm
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by jsMilton »

Hey Scott,

Thats fixed it! Thanks a bunch :D

One thing now is that the velocity of the ball keeps changing every time it hits a spinning side! The spinning frame is just meant to redirect the ball, leaving the velocity the same. Is this possible, or is it just natural for chipmunk to alter the velocity like this ?
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by slembcke »

Well, it wouldn't be conserving momentum and wouldn't be a realistic simulation if the speed stayed the same.

I've worked on breakout-like games before where you always want the ball to have a more or less constant velocity. What I did in that case was to always be accelerating the ball back to it's natural speed. So after a collision, the ball would speed up or slow down, then accelerate up or down to get back to it's regular speed over a short amount of time (like a quarter of a second or something). It worked pretty well.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
jsMilton
Posts: 3
Joined: Fri Mar 30, 2012 1:02 pm
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by jsMilton »

Yeah I get that it would be unrealistic, but it's necessary as the app is actually a generative music maker, where the collisions act as notes for a sampler. A constant speed is good for repeating rhythms :P

Thanks for the help and advice, I really appreciate it.

As for the Chipmunk library, I definitely plan on doing some more interesting stuff with it in the future. It looks like an awesome tool!

Cheers,

James
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by slembcke »

Thanks. :)
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
gnasen
Posts: 24
Joined: Wed Mar 16, 2011 12:17 pm
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by gnasen »

Hey guys, Im using a wrapper and unfortunatly it does not deliver the cpBodySetAngVel() / cpBodyGetAngVel() functions. If they only get/set the value, could you pls tell me which of this structure fields:

Code: Select all

Structure  cpBody
  *velocity_func.i
  *position_func.i
  m.cpFloat
  m_inv.cpFloat
  i.cpFloat
  i_inv.cpFloat
  p.cpVect
  v.cpVect
  f.cpVect
  a.cpFloat
  w.cpFloat
  t.cpFloat
  rot.cpVect
  *Data.i
  v_limit.cpFloat
  w_limit.cpFloat
  v_bias.cpVect
  w_bias.cpFloat
  *space.cpSpace
  *shapesList.cpShape
  node.cpComponentNode
EndStructure
it should be? I would guess its "w" or "t" but Im not sure :?
aisman
Posts: 145
Joined: Tue Mar 04, 2008 2:21 am
Contact:

Re: Rotating a Rogue Body around a bouncing ball

Post by aisman »

Hello gnasen,

Yes the Chipmunk4PB 5.3.5 has no getter/setter. The 6.03 version will have it.

Chipmunk provides getter/setter functions for a number of properties on rigid bodies. Setting most properties automatically wakes the rigid bodies up if they were sleeping. You can also set the fields directly on the cpBody struct if you wish. They are documented in the headers.


Short here:

Code: Select all

	/// Angular velocity of the body around it's center of gravity in radians/second.
	cpFloat w;
	/// Torque applied to the body around it's center of gravity.
	cpFloat t;
I think w is the right one for you.
Chipmunk4PB: The fastest way to write games together with PureBasic and the Chipmunk physics engine.
Post Reply

Who is online

Users browsing this forum: Heise IT-Markt [Crawler] and 13 guests