Page 1 of 3

World wrap around

Posted: Wed Jun 11, 2008 5:18 am
by hungrybutterfly
I want to implement a world that wraps around old school style (think Thrust). When an object is fully off the left I can just pop it onto the right side of the world no problem but the issues start when it's only part way off the left. The object somehow needs to interact with things way over on the right at the same time. I thought one solution would be to create 2 bodys, one for each side of the world, and somehow combine their velocity/rotation after each cpSpaceStep.... but I have no idea how to do that.

Any suggestions welcome.

Re: World wrap around

Posted: Fri Jun 20, 2008 6:32 am
by hungrybutterfly
I'm guessing from the lack of replies that this is a dumb thing to do.

FYI Using a collision pair callback I've tried storing references to the collision information when the second 'mirror' body touches anything. Then I apply those impulses to the original body and then force the mirror body's position and rotation to match that of the original (except offset by the width of the world). This sort of works for collision with only one other object in the world but goes a bit mad when it collides with more than one (the impulses just accumulate sending it off at high speed).

I have no idea how Chipmunk does things internally or indeed how physics engines work in general, I'm just trying to use the functions that have been exposed.

Is this a lost cause?

Who would have thought Asteroids would be so tricky with physics?

Re: World wrap around

Posted: Sat Jun 21, 2008 1:56 pm
by Michael Buckley
I haven't fully thought this out, but it occurs to me that you could try something like this:

For just left-right wrapping, create 2 cpSpaces. One for the left of the screen, and one for the right. Whenever an object is crossing the middle line or in the process of wrapping around the screen, add it to both spaces. If you need to to top-bottom wrapping too, then you'll need to create 4 spaces that all meet in the middle of the screen.

There are a few tricky problems with this. First, I don't know how Chipmunk will handle it if an object is in multiple spaces, so it might not work. Second, If an object in two or more spaces collides with another object in two or more spaces, you'll have to make sure that they don't generate more than one collision. This will require some extra overhead in the collision pair function. But (and this is the part I haven't fully thought out) I think that the collisions generated will be the same in each space, so all you have to do is take the first collision between two specific objects and throw out any subsequent collisions between those two objects during the same frame.

Re: World wrap around

Posted: Sun Jun 22, 2008 12:46 am
by hungrybutterfly
Great, thanks for the ideas. I'll give it a shot and stick with just left/right wrap around for now. I hope I understand your suggestions correctly but one thing I'm not sure of is if a body is crossing over the left world edge and I'm adding it to the right hand space I need to offset it's position to be on the right hand side of the world (to collide with things over there). How do I do this without screwing it up in the left hand space?

Re: World wrap around

Posted: Sun Jun 22, 2008 11:32 pm
by Michael Buckley
You know what, I was a little sick when I wrote that last post. Still am. I got the idea halfway there. Yeah, normally you'd need to reset the position of the body in the second space. That would screw things up. But, if you can't move the body to the location you need, move the location you need to the body. Aha, so, this is tricky. But, let's say that, for example, your window is 200 wide. Each space would then be 100 wide. Well, the space doesn't have an intrinsic width, but when an object in a space goes past 100, it's added to the other space. So, what you do, is the right side will range from 0-100, and the left side will range from 100 to 200. Then, let's say you have an object 10 wide in the right space. If it's at location 95 in the right space, it will be 5 wide in each space. What you do is you put it at location 95 in each space, but you draw the left space starting at 100, so only the right half of the object shows coming on the screen on the left. Then you'd have to adjust properly so that images move off the left side when x < 100 or x > 200, as opposed to the x < 0 or x > 100 for the right side.

I think that makes sense.

Re: World wrap around

Posted: Mon Jun 23, 2008 2:48 am
by hungrybutterfly
Yeah there's a lot of that going around.

I think I understand what your suggesting and it looks like it should work for that instance. However I might be overlooking something but I think you may have just shifted the problem along by 100 units. How will bodys collide in the middle of the screen now?

Re: World wrap around

Posted: Mon Jun 23, 2008 11:28 am
by Michael Buckley
Yeah, you're totally right. I was pretty fevered when I wrote that. I'm sorry.

Anyway, I think that, while there may be some sort of trick that I'm missing, you're trying to flatten a torus into a plane and keep the properties of the torus. You might be able to achieve it by adding two bodies (you'd only then need one space) if it's crossing the line. You would then have to filter out multiple collisions between the same objects, keeping in mind that an object can have two separate bodies, and save the impulses for each object (both bodies) from the collision function, sum them at the start of the next cpSpaceStep, calculate the resulting force, and apply it to the object. Unfortunately, this means your collision function will have to return 0 for any collision involving at least one object with two bodies, which means that you will have to position the objects after the collision yourself. I'd look at the current Chipmunk code to see how that's done.

Sorry to lead you down that other path. I was just really sick and it seemed like it would work at the time. I'm not even sure if this way will work.

Re: World wrap around

Posted: Mon Jun 23, 2008 3:49 pm
by Michael Buckley
You know, it also occurs to me, though it may be that I'm still getting over my fever, that you could have both spaces range from 0 to 100, but draw the right space backwards. When an object is entirely in the right space, reverse its x velocity and x acceleration and draw the body in the right space. When it's entirely in the left space or in both spaces, reverse them back, and only draw the body in the left space.

Re: World wrap around

Posted: Tue Jun 24, 2008 12:36 am
by hungrybutterfly
No problems, I get that confused when I'm perfectly well.

I don't think the idea of a reversed space would work either. The vertices that make up a shape in the right hand side would also have to be flipped. I'm sure there would be other problems as well.

So yeah the idea of 2 bodies is what I've been exploring so I set up a little test to try it out. In this simple test I did what you suggested about collecting the impulse data and applying it to the other body. However I wasn't sure how to apply it properly (because I don't know how physics works basically). Presumably you just use cpContactsSumImpulses and apply the result using cpBodyApplyImpulse. When you call cpBodyApplyImpulse it requires a position as well as a direction so doesn't that mean applying it to the center of the body would only translate it, it would never rotate?

I suspect the only solution to this would be to get down and dirty and do some modification to the library... but that's hard... and I'm weak.

Re: World wrap around

Posted: Tue Jun 24, 2008 1:20 am
by slembcke
Thought about this some, I'm not sure if the idea of using multiple spaces is going to work very well.

I think your best bet is to add extra copies of the objects to the space (bodies and shapes). If the object is in the lower left quadrant of your space, add copies to the top, to the left, and to the top left offset by the world dimensions. If it's in the upper right, add copies below, to the left, and to the bottom left. (you get the idea for the other two quadrants) After every step, average the position (after subtracting the offset), velocity, etc of the bodies. The collisions won't always be quite right though, as you may only be getting 1/2 or 1/4 of the collision impulse. It should smooth out somewhat well over time though as long as you don't have complex contact happening. It also will use more CPU.

The most correct option is to create a joint to bind the motion of the bodies together, but this would require understanding how joints are written. Not impossible, but not easy.