Box2d - 2D physics

Previous topic - Next topic

jaywat

Replying to myself here :p

Ok, isSleeping is the same as any other flag interrogation. So the code to implement it is:

Code (glbasic) Select

FUNCTION b_IsSleeping%: body%
INLINE
b2Body* pB = bBody(body); return pB->IsSleeping() ? TRUE:FALSE;
ENDINLINE
ENDFUNCTION


And yes, I can now see how I can use that if one of my objects is static. I can explicitly put an object to sleep, then check for it waking up, and play a sound or add a score or whatever accordingly, then put the object back to sleep. So certainly for dynamic->static collisions, that helps, thanks. Unfortunately, that doesn't help at all if you're trying to detect dynamic->dynamic collisions. So even in the case of pool balls... once you've woken the pool ball up by colliding with it, if another ball collides with the now moving ball, you couldn't detect that collision and play a sound.


blackway

Quote from: jaywat on 2010-Dec-06
I'm just curious to know if anyone is actually using box2d with GLBasic for anything 'serious'? Somehow I assume not.

Thing is, this box2d wrapper is all very nice and all for just fooling around with, but unless I'm very much missing the point, it's really of no practical use at all without the implementation of box2d contact listeners.

Sure, it physically HANDLES your object-object collisions, but without contact listeners, you can't get any feedback on those collisions. So how, for example, can you play a sound effect or animation? or add to a game score? or know when to destroy an object that was collided with? You can't do any of the normal things you'd expect to have in a game related to collision if you can't detect that a collision happened!

I've tried implementing glbasic sprite collisions, first of all with exact size sprites, but unless the collision just happens to exactly fall on the exact millisecond that your next frame update and collision check happens, it of course never sees that collision. (To be clear, I'm talking about a collision where the two objects will react to each other, ie, bounce off. The kind where contact happens for a fraction of a second. Detecting collisions where one object passes through another sensor object is obviously less of an issue).

I've tried using sprite collisions with a slightly larger sprite as a collision boundary in the hope of having more chance of catching the actual collision. Still unsatisfactory. Still misses at least 25% of collisions because they still don't exactly happen on the frame update you're testing - you're either just about to collide, or just finished colliding. Obviously the accuracy gets less and less the faster your object is moving.

Which is exactly why you need to get realtime feedback from box2d itself... direct feedback from the physics simulation is the only sure fire way of being sure to catch every collision so that you can act on them.

So if you ARE successfully using box2d in a glbasic game or whatever, perhaps you'd share how you're getting round this major problem? I don't even need code, really, if you can clearly describe your method.

I'm assuming it's no trivial matter to implement the contact listeners, or someone would have done it by now, because it must surely be one of the most necessary features of any physics engine. In fact, I simply can't see the point at all of using a physics engine you can't get any useful feedback from.


Hi Jaywat....
I don't know if Roll'n'Fall is anything 'serious' but if you like you can test it (today is free):
http://itunes.apple.com/us/app/rollnfall/id397681449?mt=8


To check collisions I used the "Sprite bigger than the physics object tricky" and I compare the object's speed between last frame and actual frame. It works good, but I think that you are right, we need the contact listener working.

Cheers!




matchy

I tried to have a go at porting but I can't so I settled for temporary solution for now. I would like have more collision data but for now these are just short cuts. That is comparing objects to previous states. As far as pool ball collisions it possible to detect and compare shape velocities will reveal a moving collision.


jaywat

Quote from: matchy on 2010-Dec-06
I would like have more collision data but for now these are just short cuts. That is comparing objects to previous states. As far as pool ball collisions it possible to detect and compare shape velocities will reveal a moving collision.

I'm not sure I follow? Are you essentially saying, assuming our pool example, to check each ball each frame and decide that 'if I just significantly changed speed or direction, assume something else hit me'?


jaywat

Quote from: blackway on 2010-Dec-06
Hi Jaywat....
I don't know if Roll'n'Fall is anything 'serious' but if you like you can test it (today is free):
http://itunes.apple.com/us/app/rollnfall/id397681449?mt=8

Just downloaded. Very nice! Your accelerometer control feels just right. I tend to dislike accelerometer controlled games in general cuz they're always either way too sensitive and the tiniest unintentional movement screws up your control... or they're not sensitive enough and you have to turn the device nearly upside down to move! :)

blackway

Thanks Jaywat!  :good:
If you play it a bit you'll see how barrels and boxes does a sound when fall and hit a platform or how a barrel crush a enemy...
Bye!


matchy

Quote from: jaywat on 2010-Dec-06
Quote from: matchy on 2010-Dec-06
I would like have more collision data but for now these are just short cuts. That is comparing objects to previous states. As far as pool ball collisions it possible to detect and compare shape velocities will reveal a moving collision.

I'm not sure I follow? Are you essentially saying, assuming our pool example, to check each ball each frame and decide that 'if I just significantly changed speed or direction, assume something else hit me'?

It's my pool example and you're not meant to follow me. Post sample code and we can work on that!

jaywat

Quote from: matchy on 2010-Dec-06
It's my pool example and you're not meant to follow me. Post sample code and we can work on that!

Really? Seems a bit pointless. I'd have to write code especially, which would ultimately be of no particular value to me or anyone else, when we could surely just talk in terms of the basic principle of how you would handle collisions between ANY two dynamic and currently moving objects without contact listeners, which would surely be more useful for anyone else who is interested in the future.

As I said, isSleeping wouldn't work where a pool ball has already been struck, has woken and is now moving, if it should then collide with another moving ball. Or if a character collides with a moving platform, or one race car that collides with another, etc etc, if you want to be strangely protective of your pool ball analogy. So interpreting what you said subsequent to that, I was merely asking if you were stating that, as a general principle, you would monitor each object each frame, and assume that any rapid deviation of speed or angle must have been caused by a collision? Or did you mean something else entirely that I haven't understood?

If you're saying that it depends what I want to do as to how it should be handled, and that's why you requested I post code, then I'd counter that this is precisely why it's pretty much essential that contact listeners are implemented for box2d to be of any use!.. they are the default, one-size-fits-all solution. And then we wouldn't have to be talking around all these less than perfect workarounds!


jaywat

#113
Seems I'm the only one interested in box2d these days! Though hopefully this will catch the eye of someone who can answer my (hopefully very basic) C related question.

I've added motors and limit angles to joints in the GLBasic wrapper. Yay me. But being a complete non-programmer type, I can't get my head round returning references across classes. I was wondering if anyone here could give me a heads up (see below for specifics), cuz if I can solve this little issue I think I can add a heck of a lot more to the box2d wrapper functionality.

Ok. Here's the thing. I can reference a DIRECT definition of 'class b2Joint', such as the joint type, with a function such as the following:

Code (glbasic) Select

FUNCTION b_JointGetType: joint%

INLINE
b2Joint* pB = bJoints(joint); return pB->GetType();
ENDINLINE

ENDFUNCTION


but what I need to know is how to reference a definition specific to 'class b2RevoluteJoint : public b2Joint', such as IsMotorEnabled() ?

I can't just express:

Code (glbasic) Select
b2RevoluteJoint* pB = bJoints(joint);

because it tells me error: invalid conversion from `b2Joint*' to `b2RevoluteJoint*'.

I can't say:

Code (glbasic) Select
b2Joint* pB = bJoints(joint); return pB->IsMotorEnabled();

because it tells me error: 'class b2Joint' has no member named 'IsMotorEnabled', and since I don't know anything about C, now I'm out of guesses and am stuck! ;)

So if anyone could post the INLINE for the as yet non existent function b_JointIsMotorEnabled: joint% to show me how to correctly reference b2RevoluteJoint, I'm pretty sure that following this example there's a whole raft of extra functionality I could add to the box2d wrapper.

I realise there's potentially an issue with 'what if the joint isn't one with a motor?', but I'm not too worried about that right now, since I'm hoping to be able to write the function to use the above gettype(), then interrogate the correct class and return a value conditionally... all I'm really interested in right now is how to return b2RevoluteJoint->IsMotorEnabled in the first place!

Thanks!

matchy

I think, maybe IsMotorEnabled is in a later version of Box2D.

jaywat

#115
Quote from: matchy on 2011-Jan-06
I think, maybe IsMotorEnabled is in a later version of Box2D.

No, it is in the b2RevoluteJoint.h file that we're using with the current wrapper.

Code (glbasic) Select

class b2RevoluteJoint : public b2Joint
{
public:
/// Is the joint motor enabled?
bool IsMotorEnabled() const;
}


As I understand it, b2RevoluteJoint extends b2Joint, and I know how to reference b2Joint, but not the extended members

Kitty Hello

If you really, really, really know, your joint "IS" a b2RevoluteJoint, you can do:

Code (glbasic) Select

b2RevoluteJoint* pB = (b2RevoluteJoint*)bJoints(joint);


You could do an dynamic_cast<b2RevoluteJoint*>(bJoints(joint)) and check if it's NULL.
That would require RTTI enabled, though - don't do that.

AlienMenace

I have used box2d quite a bit with Darkbasic and am excited that there is at least a partial implementation for GLBasic. I have virtually no C skills whatsoever so trying to extend the wrapper myself has been a head-banging exercise in futility. So, I do have a couple of questions and hopefully somebody will be kind enough to  help me out...

This code was posted in this thread as a replacement for the original b_WorldDebug. It allows the debug drawing to be offset, I was wondering if it were possible to modify it to actually offset the position of the world bodies themselves. DB has a command for something similar to this in it's wrapper called Screen Transform.. I've used it to scroll the world and it has worked really well.

Code (glbasic) Select

FUNCTION b_WorldDebug: xorg, yorg, scale // added circle radius marker
INLINE

b2Vec2 offset(xorg, yorg);
for(int i=0; i<LEN(bBody); ++i)
{
b2Body* pB = bBody(i);
if(!pB) continue;
for(b2Shape* pShp = pB->GetShapeList(); pShp; pShp = pShp->GetNext())
{
switch(pShp->GetType())
{
case e_circleShape:
{
b2CircleShape* pCirc = (b2CircleShape*)pShp;
const b2Vec2& p1 = pB->GetWorldPoint( pCirc->GetLocalPosition() );
DGInt r = pCirc->GetRadius();
DGInt a = pB->GetAngle() * -180.0 / 3.14159265358979323846;
DGInt ox, oy;
for(DGInt phi=0; phi<=360; phi+=5)
{
DGInt x = scale*p1.x+xorg+SIN(phi)*r, y=scale*p1.y+yorg+COS(phi)*r;
if(phi>0)
DRAWLINE(ox, oy, x, y, RGB(0,255,0));
ox=x; oy=y;
}
DGInt x = scale*p1.x+xorg+SIN(a)*r, y = scale*p1.y+yorg+COS(a)*r; // circle radius marker
DRAWLINE(x, y, scale*p1.x+xorg, scale*p1.y+yorg, RGB(255,255,0));     //

}
break;
case e_polygonShape:
{
b2PolygonShape* pPoly = (b2PolygonShape*)pShp;
for(int j=0; j<pPoly->GetVertexCount(); ++j)
{
int k = (j+1)%pPoly->GetVertexCount();
const b2Vec2& p1 = pB->GetWorldPoint(pPoly->GetVertices()[j]);
const b2Vec2& p2 = pB->GetWorldPoint(pPoly->GetVertices()[k]);
// Bah! Local coordinates!
DRAWLINE(scale*p1.x+xorg, scale*p1.y+yorg, scale*p2.x+xorg, scale*p2.y+yorg, RGB(0,255,0));
}
}
break;
}
}
}
ENDINLINE
ENDFUNCTION


My second question concerns how to read a vector from GLBasic. This function returns vec.x and vec.y but I have no idea how to store and use the information it is returning..

Code (glbasic) Select

FUNCTION b_GetWorldVector AS Tb_Vec2: body%, localx, localy
INLINE
b2Body* pB = bBody(body);
b2Vec2 vec = pB->GetWorldVector(b2Vec2(localx, localy));
Tb_Vec2 out;
out.x = vec.x; out.y=vec.y; return out;
ENDINLINE
ENDFUNCTION


I have a few more headaches I'm trying to figure out but if somebody could help me out with these, I would very much appreciate it.
Thanks
Apps published: 3

matchy

Something like:

Code (glbasic) Select

TYPE _vec
x
y
ENDTYPE

LOCAL vec as _vec

LOCAL body_id = b_CreatePoly(...
LOCAL body_angle

vec.x = b_BodyGetPosX(body_id) // + offset_x
vec.y = b_BodyGetPosY(body_id) // + offset_y
// INC body_angle, 30
b_BodySetMove(body_id, vec.x, vec.y, body_angle)

// LOCAL vec_world AS _vec = b_GetWorldVector(body_id, vec.x, vec.y)
// LOCAL vector_x = vec_world.x
// LOCAL vector_y = vec_world.y

mentalthink

Hi friends, I´ve got a question about the polygon creator command.

Well I try to make shapes whit more of 7 index on the first dimension of the array, but the code crashes.

It´s limited this command to 7 index (1st Index), or perhaps I made some wrong.

Kinds Regards,
Iván J.