Beginner: fast dragging collisions

Official forum for the Chipmunk2D Physics Library.
Post Reply
theLastNightTrain
Posts: 4
Joined: Wed Aug 25, 2010 9:23 am
Contact:

Beginner: fast dragging collisions

Post by theLastNightTrain »

I have started making a very simple wargame, using Cocos2d and now Chipmunk.

The game consists of a grid (a Tiled map), and "units" which occupy grid cell locations (one per cell). Units are moved by touching and dragging them and dropping them in a new empty location.

Units cannot move through some terrain and cannot move through other units, so if they are dragged through another unit, they should stop in the empty cell location closest to where they bumped into the other unit.

I have written a simple mechanism for detecting collisions and backing off to the previous cell location. This works fine for slow movement, because the ccTouchMoved event is frequent enough that the previous location is always a good place to drop the unit.

However, if the user drags rapidly over the screen, the TouchMoved events don't arrive fast enough, such that between two events there can be 200 pixels or more, which for me is many cells. A solution to that then is for me to measure a line between the two points, and then determine the path of that line and check for collisions with every cell on that path. It was at this point that I decided to look at Chipmunk and use that for collision detection, in the hope that it will be much better (and faster) than my code at handling all of this, and give me increased ability for future features too.

(Sorry for the long boring intro story btw! But it might help provide a solution faster than without it :)).

So I have added Chipmunk, removed my "manual" collision detection (which was really crude - basically went through the whole array of all units on the screen at the time to compare their locations, on every single movement event) and I now have Chipmunk detecting collisions instead, and that all appears to be working fine, and has got me back to the same place I was at above in that I now need to do the path detection, and find out where to drop the moving collided unit if it is dragged at high speed through grid locations that should stop it.

My question is that it seems to me this is likely to be an extremely common problem and one that has a well-known and ready solution that perhaps already exists in Chipmunk.

Is that the case? If so, can someone point me in the right direction for it please? Sorry if it is easy to find, I have been looking :)

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

Re: Beginner: fast dragging collisions

Post by slembcke »

I think the closest thing somebody asked was this: http://www.slembcke.net/forums/viewtopi ... lit=#p4312

You could do something similar. You can create a temporary copy of the body and shape on the stack and move the body in constant sized increments.

You could also use segment queries (raycasting) to test if the path hits anything along the way and back up to the collision point.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
theLastNightTrain
Posts: 4
Joined: Wed Aug 25, 2010 9:23 am
Contact:

Re: Beginner: fast dragging collisions

Post by theLastNightTrain »

Hi,
Thanks for the quick reply.

So it sounds like there are some options:

1. In my TouchMoved, measure a line between the last move point and the current, and step along it creating a fake shape and check for collisions, on detecting a collision set the location to the step point before the collision, and abort the moving of the unit (player unit).

2. At the moment I update the moving Unit position directly in the TouchMoved method, and that updates the shape position at the same time. There is a "step" (or "tick") method called on a schedule every 1/30s, and that at present simply calls cpSpaceStep() (actually it calls it for every 1/30th that has passed since the last call). It seems to me that by changing the position directly in the TouchMoved method I might be causing problems, and perhaps a nicer approach will be to append a target point to a path of points for the moving unit, and then every tick make it move at a max speed of my grid cell size per tick call. That would slow the display of movement down (compared to fast finger moves) but have the benefit of letting a collision check occur along every significant point along the path.

3. Use a queryFunc as you mention with a ray path centred along the route described in (1) above.

Perhaps 2 is the best option?

A related question (sorry!), is that at the moment my game units easily manage to overlap each other. My Units get set up with defaults, and my collision handler looks like this:

cpSpaceAddCollisionHandler(battleSpace, CollisionTypeUnit, CollisionTypeUnit, bumpedUnit, NULL, NULL, NULL, self);

bumpedUnit() {
// drop selected unit (mark it as no longer moving)
[self dropSelectedUnit];
return 1;
}

(I am working on the basis of one unit moving at a time for the moment)

Perhaps I am forcing the units to overlap by not changing the position of the moving unit in my handler, but from reading other posts in this forum I got the impression there was a way to let Chipmunk handle that and stop bodies from overlapping - should I be changing the position of the moving unit back myself in the bumpedUnit function (or perhaps in a presolve function) ? Or should I be asking the shape/body something and using that? In future I want to make them bounce off a little, but for now just preventing them from overlapping will be great.

Thanks again for any help, sorry about the beginner questions, maybe I will have more interesting ones in the future :)
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Beginner: fast dragging collisions

Post by slembcke »

I would actually go with #1. I think you'll run into the fewest issues that way.

That said, if you are setting the positions of all your objects each step, then you wont be getting anything like real physics. What you are asking is pretty advanced usage. It sounds like you want collision detection without the collision response. You can use Chipmunk to do this by creating a preSolve() callback that returns false every time. Then you can implement your own collision response.

By setting the position every frame without updating the velocity, you make Chipmunk's collision response almost useless. If you want to use Chipmunk's collision response, you have to smooth out your input (which makes it less responsive) and set the velocity to match the change in position. Even that isn't good enough sometimes. If you are setting the velocity and position of two objects that collide, you are still undoing all the work to try to resolve their collision. If this ends up being a problem, you'll need to control the objects using constraints. (see the Tank demo for an example of this)

Without doing one of the two options above you can't really fix the overlapping objects problem. I've found that using constraints to control objects works very smoothly, but can use a lot of CPU.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
theLastNightTrain
Posts: 4
Joined: Wed Aug 25, 2010 9:23 am
Contact:

Re: Beginner: fast dragging collisions

Post by theLastNightTrain »

Just a quick note that I have taken a naive approach so far and so am very open to ideas about how to make it better :)

The situation is that all of my objects are stationary (running sprite animations but not changing position) EXCEPT when being dragged by a user. So at any one time, there are typically only two objects moving, and during my testing, only one. However I think it is important that they move rapidly, ideally remaining with the finger of the user(s).

I have not set the velocity on any object (yet). So I think I understand - by not ever setting the velocity I am not giving chipmunk the info it needs - that sounds like the missing element I wasn't aware of, but yes is obvious in hindsight - I have only been setting position. (Although... couldn't the body derive velocity itself from position changes and time? Perhaps that is often undesirable... or I am misunderstanding :)).

I am returning true from all the collision handlers (just the one so far).

Earlier I implemented (2), by having each unit also hold a path to follow, and then making the position change happen in the tick method. The path contains a sequence of points that are separated by at most one grid size (but without being snapped to the grid, which at the moment I only do at the end). That means the movement of the sprite lags behind a fast finger, but it does get the chance to test for collisions all the way around the route.

However I can still cause overlaps - I was about to put in code after a collision that steps back through the previous positions until it is in empty grid location, then sets the position there.

In terms of real physics, it would be nice to have the moving unit that collides hit the wall/other unit and bounce off a bit and settle in the adjacent space. I also want to make it so that moving units can slide along other units and terrain - so only a full on collision with a finger moving into the stationary object should actually cause the moving unit to stop.

You say I am undoing the work of Chipmunk by setting the position (and velocity say if I were to), but if I am not setting the position, how are the objects to move in the first place? (I apologise for how beginner that question sounds actually, and I admit I am embarrassed to ask it!)
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Beginner: fast dragging collisions

Post by slembcke »

Well, the idea is that a physics engine simulates physics. You tell it the forces that are acting on objects, their shape, and how they are jointed together. Then you let the physics simulate their velocity and positions. You read the position back from the physics engine when drawing, and sometimes write changes back based on input.

If all you are doing is setting positions, then the physics engine would have to make tons of assumptions of what you meant by simply telling it a new position.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
theLastNightTrain
Posts: 4
Joined: Wed Aug 25, 2010 9:23 am
Contact:

Re: Beginner: fast dragging collisions

Post by theLastNightTrain »

Ok I understand better now.

On reflection, I have been guilty of intellectual laziness - I was kind of hoping that a framework would solve everything, but actually it isn't a physics engine I need.

I believe I have an algorithm now that will achieve everything I want and will be very fast.

Thanks for your time - I have a better understanding of how (and more importantly, when) to use Chipmunk now - many thanks!
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Beginner: fast dragging collisions

Post by slembcke »

Well, as I said, you can use just Chipmunk's collision detection but it may be easier not to.

If you aren't using all the collision shapes and queries that Chipmunk supports and all you need is bounding box collisions against other bounding boxes and a tilemap, it's probably easier to roll your own.
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 26 guests