Hello Everybody,
I've just started messing about with Cocos and Chipmunk and I'm really amazed with both of them. I'm working on an iPhone App and am considering using Chipmunk for collision. The collision in my game would be very simple, essentially circle and vector. Being able to add some physics for object movement would also come in handy. I looked at the cpMouse files posted by supertommy, and got them working in my project. I soon after encountered a couple of problems that I thought the community might be able to help me with...
1. How would the problem of excessive velocities applied to the cpMouse object during its first update after a "touches began" event be solved? In a mouse based environment, mouse move messages are sent every time the mouse moves, so the delta between the current (mouse down) position and the previous mouse move position is usually a few pixels. On a stylus/touch based environment, this delta is usually quite large, and results in a large velocity being applied to the object when it is first grabbed by the cpMouse. After the object is grabbed, everything settles down.
2. A similar problem appears when you need to update the mouse before collision detection to see if it actually hits anything. I've solved this part of the problem by stepping the whole simulation after moving the mouse to the current touched location. I'm working on a solution without having to step the entire simulation.
Thanks,
Wildstar
cpMouse and iPhone/iPod Touch
-
- Posts: 4
- Joined: Sun Feb 15, 2009 7:09 pm
- Contact:
-
- Posts: 56
- Joined: Tue Jul 15, 2008 4:13 am
- Contact:
Re: cpMouse and iPhone/iPod Touch
the solution for 1. is simple: call the mouse-move function twice before the grab function (only if not grabbed already) that'll set the initial velocity to zero.
I don't really understand your problem in 2. It seems you do it the way you're supposed to (update mouse position, then update space).
What do you mean with "stepping the simulation"? You step the simulation every frame anyway. So just call the update func beforehand.
I don't really understand your problem in 2. It seems you do it the way you're supposed to (update mouse position, then update space).
What do you mean with "stepping the simulation"? You step the simulation every frame anyway. So just call the update func beforehand.
-
- Posts: 4
- Joined: Sun Feb 15, 2009 7:09 pm
- Contact:
Re: cpMouse and iPhone/iPod Touch
Hey Ker,
Thanks for the reply. By "stepping the simulation" I refer to calling spSpaceStep with the normal time slice. What is peculilar to me at least is that I am making an extra call just so the system can correctly resolve collisions for the mouse. I think I can set this up so I don't have to waste the step. So for now, let's assume that we have #2 solved, and focus on #1.
The code that gets called in cpMouseMove is the following:
As you can see it updates the body's position, and accumulates the total distance moved. The value of 'mouse->moved' gets cleared during the mouse's custom update velocity function.
This is why I found it necessary to step the simulation between the initial mouse move call and the mouse grab call. The collision testing was failing when trying to pick up an item during the initial mouse down, because without stepping the simulation (via cpSpaceStep) the mouse was still at the previous position.
Unless the object to be grabbed is at 0,0 ( or near the last place the mouse button was released ) in simulation space, the object will shudder for the next few frames after the mouse down. The farther the mouse is from 0,0 ( or the last place the mouse button was released ), the greater the shutter. Does that make sense? When the mouse down event is first fired. The previous position isn't where the last mouse-move event was ( as it would be for a standard mouse based computer,) it's where the last "mouse-up" event occurred. Basically a very strong force is being applied to the joints that bind the mouse and the object it is grabbing, forcing the grabbed objects away from the two pin joints that the mouse uses to pick it up. The simulation then tries to correct and bring the objects back at a 'penalty-velocity'. If the penalty velocity is too, great, the simulation must again compensate with a smaller penalty velocity. After a few frames of this, the grabbed object settles down, and everything seems normal.
I hope I've made my question clearer,
Thanks,
wildstar
Thanks for the reply. By "stepping the simulation" I refer to calling spSpaceStep with the normal time slice. What is peculilar to me at least is that I am making an extra call just so the system can correctly resolve collisions for the mouse. I think I can set this up so I don't have to waste the step. So for now, let's assume that we have #2 solved, and focus on #1.
The code that gets called in cpMouseMove is the following:
Code: Select all
void
cpMouseMove(cpMouse *mouse, cpVect position)
{
mouse->moved = cpvadd(mouse->moved,
cpvsub(position, mouse->body->p));
mouse->body->p = position;
}
Code: Select all
mouseUpdateVelocity(cpBody *body,
cpVect gravity,
cpFloat damping,
cpFloat dt)
{
cpMouse *mouse = (cpMouse *)body->data;
/*
* Calculate the velocity based on the distance moved since the
* last time we calculated velocity. We use a weighted average
* of the new velocity and the old velocity to make everything
* a bit smoother.
*/
cpVect newVelocity = cpvmult(mouse->moved, 1.0f / dt);
body->v = cpvadd(cpvmult(body->v, 0.7f),
cpvmult(newVelocity, 0.3f));
mouse->moved = cpvzero;
}
This is why I found it necessary to step the simulation between the initial mouse move call and the mouse grab call. The collision testing was failing when trying to pick up an item during the initial mouse down, because without stepping the simulation (via cpSpaceStep) the mouse was still at the previous position.
Unless the object to be grabbed is at 0,0 ( or near the last place the mouse button was released ) in simulation space, the object will shudder for the next few frames after the mouse down. The farther the mouse is from 0,0 ( or the last place the mouse button was released ), the greater the shutter. Does that make sense? When the mouse down event is first fired. The previous position isn't where the last mouse-move event was ( as it would be for a standard mouse based computer,) it's where the last "mouse-up" event occurred. Basically a very strong force is being applied to the joints that bind the mouse and the object it is grabbing, forcing the grabbed objects away from the two pin joints that the mouse uses to pick it up. The simulation then tries to correct and bring the objects back at a 'penalty-velocity'. If the penalty velocity is too, great, the simulation must again compensate with a smaller penalty velocity. After a few frames of this, the grabbed object settles down, and everything seems normal.
I hope I've made my question clearer,
Thanks,
wildstar
-
- Posts: 56
- Joined: Tue Jul 15, 2008 4:13 am
- Contact:
Re: cpMouse and iPhone/iPod Touch
Oh, ok, that is annoying. Let me explain what I wrote above somewhat more clearly:
calling cpMouseMove will cause the mouse position to be immediately set to the correct position (mouse->body->p = position). After that calling cpMouseGrab will cause the object below the current mouse position to get grabbed. Now you have a body (your mouse) with an extreme velocity. Also you got yourself some joints between your mouse-body and your grabbed body. During the next space updatestep that velocity will move your mouse extremely far, causing the object attached to it to get pulled along.
now, the next turn around, your mouse gets returned to the actual mouse-position by calling cpMouseMove again. The grabbed object gets pulled along. So your velocity is now extreme again. Since the mouse-code interpolates a little, all this will settle down.
Solution is to call cpMouseMove twice if you have no object grabbed. (or simply call it, and reset mouse->moved to cpvzero). (IMPORTANT: really only do this if grabbedBody is NULL, otherwise regular mouse-behavior gets messed up).
calling cpMouseMove will cause the mouse position to be immediately set to the correct position (mouse->body->p = position). After that calling cpMouseGrab will cause the object below the current mouse position to get grabbed. Now you have a body (your mouse) with an extreme velocity. Also you got yourself some joints between your mouse-body and your grabbed body. During the next space updatestep that velocity will move your mouse extremely far, causing the object attached to it to get pulled along.
now, the next turn around, your mouse gets returned to the actual mouse-position by calling cpMouseMove again. The grabbed object gets pulled along. So your velocity is now extreme again. Since the mouse-code interpolates a little, all this will settle down.
Solution is to call cpMouseMove twice if you have no object grabbed. (or simply call it, and reset mouse->moved to cpvzero). (IMPORTANT: really only do this if grabbedBody is NULL, otherwise regular mouse-behavior gets messed up).
-
- Posts: 4
- Joined: Sun Feb 15, 2009 7:09 pm
- Contact:
Re: cpMouse and iPhone/iPod Touch
Hey Ker,
Thanks for the clarification. I got it working by adding a new function (cpMouseSet) that acts in a similar fashion to cpMouseMove, except it doesn't the change in position to the "mouse->moved" accumulator. With cpMouseSet being called when the touch begins, and cpMouseMove called when the touch moves.
Thanks for your help!
wildstar
Thanks for the clarification. I got it working by adding a new function (cpMouseSet) that acts in a similar fashion to cpMouseMove, except it doesn't the change in position to the "mouse->moved" accumulator. With cpMouseSet being called when the touch begins, and cpMouseMove called when the touch moves.
Thanks for your help!
wildstar
- deansx
- Posts: 2
- Joined: Tue May 26, 2009 11:33 pm
- Location: Mountain View, CA
- Contact:
Re: cpMouse and iPhone/iPod Touch
I ran into a problem problem on the iPhone where I had to touch twice, quickly, to actually grab a moving object. It looked like the code in cpMouse wasn't getting the new bb for the mouse shape properly updated on the first touch. On the second touch, it would be updated, so I could grab the object. I had noticed a previous comment that suggested adding a cpMouseSet() function to be called in touchesBegan. I wrote the following function in cpMouse.c and called it from my touchesBegan method:
...and everything is working fine. I can reliably grab even fast moving objects with the first touch. Thanks for the pointers!
Code: Select all
void
cpMouseSetLoc(cpMouse *mouse, cpVect position)
{
mouse->moved = cpvzero;;
mouse->body->p = position;
cpShapeCacheBB(mouse->shape);
}
[color=#0000BF][b][url=http://www.BluMtnWerx.com]BluMtnWerx[/url][/b][/color]
[url=http://www.blumtnwerx.com/iPuck.html]iPuck v1.1[/url] - a fun casual arcade game
[url=http://www.blumtnwerx.com/RingDance.html]RingDance[/url] - a soothing audiovisual relaxation tool
[url=http://www.blumtnwerx.com/iPunt.html]iPunt[/url] - an immersive 3-D experience
[url=http://www.blumtnwerx.com/blog]Mobile Perspectives Blog[/url]
[url=http://www.blumtnwerx.com/iPuck.html]iPuck v1.1[/url] - a fun casual arcade game
[url=http://www.blumtnwerx.com/RingDance.html]RingDance[/url] - a soothing audiovisual relaxation tool
[url=http://www.blumtnwerx.com/iPunt.html]iPunt[/url] - an immersive 3-D experience
[url=http://www.blumtnwerx.com/blog]Mobile Perspectives Blog[/url]
Who is online
Users browsing this forum: No registered users and 26 guests