I have one issue regarding box2d and cocos2d. My world have zero gravity and i am working in tile base game. I am using sneak joystick for movement of sprite and its move perfect but when i release point to joystick my sprite body can not stop because of some force. I want to stop that movement of sprite when joystick release.
-(void)update:(ccTime)dt :(b2Body *)ballBody :(CCSprite *)player
{
CGPoint scaledVelocity=ccpMult(joysticks.velocity, 2);
NSLog(#"Joystick Velocity X: %f",joysticks.velocity.x);
NSLog(#"Joystick Velocity Y: %f",joysticks.velocity.y);
b2Vec2 force=b2Vec2(scaledVelocity.x/PTM_RATIO,scaledVelocity.y/PTM_RATIO);
ballBody->ApplyLinearImpulse(force, ballBody->GetWorldCenter());
}
Here scaledVelocity value is approximate 0 to 1. When i release joystick that time value of joystick is 0.0
Please help me i am stuck since last 5 days.
Please help me.
Thanks in advance
Do you want the b2Body to immediately stop or to slow down (and eventually stop)?
To make it stop immediately:
ballBody->SetLinearVelocity(b2Vec2(0,0));
To make it slow down:
ballBody->SetLinearDamping(10.0); // experiment with the damping factor value until you get the right deceleration
You should check out the answer to this question:
How to stop the forces acting on a body in box2d
On release of the joystick, you should reset the velocity of your box2d body.
Related
i'm losing myself in this...
Situation:
Working on a game in cocos2d with box2d and I have a ropejoint between one fixed body and one dynamic body.
When I drop the dynamic body is swings from left to right and then from right to left due to the gravity in the world.
The problem:
The swings are getting shorter and shorter till finally the dynamic body hangs still beneath the fixed body. This is normal behavior but I need it to keep swinging.
My thoughts:
I think I need to apply a tangential force to the ropejoint in the direction of the swinging but how to do this is a mystery for now :)
Try setting the damping factor of the rope joint to zero
ropeJointDef.dampingRatio = 0.0f;
Hope it helps!
Here is a little code that should help you with your little problem
bool YourClass::init(){
CCCallFunc *swingL = CCCallFunc::create(this,callfunc_selector(YourClass::swingLeft));
CCDelayTime *delay = CCDelayTime::create(5);
CCCallFunc *swingR = CCCallFunc::create(this, callfunc_selector(YourClass::swingRight));
this->runAction(CCRepeatForever::create(CCSequence::create(swingL,delay,swingR,NULL)));
}
void YourClass::swingLeft(){
b2Body *dynamicBody = get your body from b2world;
dynamicBody->SetLinearVelocity(b2Vec2(-10, 0));//set velocity of the swing
}
void YourClass::swingRight(){
b2Body *dynamicBody = get your body from b2world;
dynamicBody->SetLinearVelocity(b2Vec2(10, 0));//set velocity of the swing
}
For the past days, I've been trying to make a ping pong like game. I have 2 paddles and a ball. All dynamic sprites. Everything's been working well except for one issue I'm having. The ball tends to bounce on the same angle at some point. So there would be times when the player can simply move the paddle on a specific part and the game can go on for a while or might be forever, since the ball doesn't change its angular velocity regardless of which part of the paddle it hits. I'm using a combination of linear and angular velocity to keep the ball moving like so:
if(_isPaused == FALSE)
{
_world->Step(dt, 10, 10);
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *)b->GetUserData();
if(sprite.tag == 2)
{
b2Vec2 dir = b->GetLinearVelocity();
dir.Normalize();
float currentSpeed = dir.Length();
int maxSpeed = 60;
float accelerate = vel;
if(currentSpeed <= maxSpeed)
{
b->SetLinearVelocity(accelerate * dir);
}
sprite.position = ccp(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO);
sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
//Keep sprite from bouncing in a straight angle
b->SetAngularVelocity(_body->GetAngle());
}}}
So my question is, how can I manipulate the angular velocity to keep the ball bouncing on different angles everytime it collides with my paddle? I'm thinking something like getting the current angular velocity then multiplying it with some value but I'm not sure if that's the right way to approach the issue I'm having. Any suggestions or ideas would be greatly appreciated. Thanks in advanced.
The way I see it, you have two options:
Check the location of a collision. If it's close to the top/bottom edge of the paddle, deflect the outgoing velocity by an angular amount proportional to the surface "curvature" at that point. Of course, this is cheating, but if the artwork and code are in agreement, it looks correct. And graphics is "the art of cheating without getting caught".
You could take into account the current velocity of the paddle as well as that of the ball. Eg: if the ball is moving downwards and to the right, and the paddle is moving down, then you can compute the outgoing direction using conservation of linear momentum. Just make sure you restrict the paddle's change in momentum along the horizontal axis to be zero.
Finally, you could combine the above techniques, but now you'd have to use accurate collision detection (not the hack I described in (1) above).
Hope that helps!
A few pointers, you should use SetLinearVelocity() and SetAngularVelocity() rarely. Each alters a property of the body definition, which could make you run into problems later on when things get more complex. It would be better to use ApplyForceToCenter() or ApplyLinearImpulse() in the place of SetLinearVelocity() as these two are much more versatile functions and are a bit more coder-friendly. In my opinion, I don't think you should use b->SetAngularVelocity(_body->GetAngle()); If you wanted to change the angular velocity each time it collided, you could, in your beginContact method, write that every time the body collides with the paddle body, a random angular impulse is applied to the ball, using ApplyAngularImpulse().Hope that helps.
How can my sprite will jump and come back to original place??
I am using box2d physics engine in iphone apps.
I am using impulse but cant work properly.
Is any one know the logic or code than tell me.
-(void)jump
{
b2Vec2 pos=ballbody->GetPosition();
// float vel=ballbody->GetAngularVelocity();
double radian=atan2(pos.x+10, pos.y+10);
float angle=CC_RADIANS_TO_DEGREES(radian);
NSLog(#"Angle: %f",angle);
float impulseFactor = 1.0;
float force=ballbody->GetMass()*10;
//force/=6.0;
//b2Vec2 force=b2Vec2(0,50.0f);
// float apply=force*JUMP_IMPULSE*impulseFactor;
ballbody->ApplyLinearImpulse(b2Vec2(angle,force), ballbody->GetWorldCenter());
// [self applyLinearImpulse:b2Vec2(0,[self mass]*JUMP_IMPULSE*impulseFactor) point:[self worldCenter]];
}
Thanks
please check whether gravity has been set
if not set gravity upon the particular angle you have put the force.
third case is note down that position... get the current position... get angle.... set linear velocity to that angle.... keep on checking the position and as soon as it reaches that position set linear velocity zero..... (this sounds confusing but i didn't understood your problem fully so as much as i did understood i can help only this much)
I have a CCSprite object of which I need to update the on screen (x,y) position as quickly as possible. It is an augmented reality app so the on screen position needs to appear fixed to a real world location.
Currently, during each update I check the heading and attitude of the device then move the sprite accordingly by determining the new x and y positions
[spriteObject setPosition:ccp(newX, newY)];
Each degree change in heading corresponds to 10 pixels in on screen position, so by setting the position this way the sprite jumps around in intervals of 10 pixels which looks stupid. I'd like to animate it smoothly, maybe by using
[spriteObject runAction:[CCMoveTo actionWithDuration:0.2f position:ccp(newX, newY)]];
but the problem here is that a new position update comes in while the sprite is animating and it sort of screws the whole thing up. Anyone know of a nice solution to this problem? Any help is much appreciated as I've tried numerous failed solutions to this point.
You can try to just animate your sprite movement to the point. I mean, you can several times during one second run animated position correction with duration of 1/numberOfUpdates in one second. Something like
- (void) onEnter
{
[super onEnter];
[self schedule:#selector(updatePositionAnimated) interval:0.2f];
}
- (void) updatePositionAnimated
{
[spriteObject runAction:[CCMoveTo actionWithDuration:0.2f position:ccp(newX, newY)]];
}
I suppose, you will have smooth enough animation in this case
I have got a ball which bounces of walls. This bounce is simple, i just do this, ( code snippet )
if ( x - moveSpeed < 0 ) // Ball hit left wall
xVel *= -1;
However i also got a rectangle which the player moves. The bounce on this practically works as the bounce on walls.
But i figured out that when a ball got similar movement as the picture, its impossible for me to make it go straight up again. I therefore need some kind of calculation regarding the rectangles movement to influence the outcoming angle of the ball. The rectangle always got a constant movement speed when moving. This picture shows a rectangle moving to the left and the ball hitting it during its movement, which results in a 90 degree angle.
( Which shouldn't always be 90 ).
Sorry about my crappy pictures i hope they make sense. My math is rusty thats why i really could need a push in the right direction.
Here is a tutorial on some physics (which is what you need to know) and you need to learn about vectors. The tutorial doesn't go over exactly what you are looking for (the reflection of the bounce and angles) but this is a GREAT start for beginning, because you'll need to know all this to finish your project.Game Physics 101
If you want to do it the easy way, here is code in c++ that describes exactly how to do what your looking for.
Edit
You should actually check out the second link first, its a tutorial on exactly what you need to know. But if you are looking to do more than just make the ball bounce around, say include other moving objects or something like that, check out the first link.
No need for any fancy math here. My understanding of these types of games is that the angle the ball comes off of the paddle is determined by where on the paddle it bounces. If it bounces in the middle, then the current angle is preserved. As it bounces closer to the edge of the paddle, the angle is adjusted in the direction of that side of the paddle. Think of the paddle as a rounded surface.
Going the route of simulating actual physics (as opposed to #Treebranche's answer, which is how I think those sort of games really work) can get very complicated. You can consider friction, spin, duration of contact, etc. Here are a couple links that discuss this.
https://physics.stackexchange.com/questions/11686/finding-angular-velocity-and-regular-velocity-when-bouncing-off-a-surface-with-f
https://physics.stackexchange.com/questions/1142/is-there-a-2d-generalization-of-the-coefficient-of-restitution/
This code demonstrates how to bounce the ball back or in another direction by reversing the ball's X or Y heading with ball.headingX=-ball.headingX and ball.headingY=-ball.headingY .
Putting theory to practice :
/* update ball's x heading */
ball.x+=ball.headingX;
/* update ball's y heading */
ball.y+=ball.headingY;
/* if ball at most right of screen then reverse ball's x heading */
if( (ball.x>PONG_SCREEN_RIGHT) )
{
ball.headingX=-ball.headingX;
}
/* check if ball's location at top or bottom of screen,if true reverse ball's y heading */
if( (ball.y<PONG_SCREEN_TOP) || (ball.y>PONG_SCREEN_BOTTOM-2) )
{
ball.headingY=-ball.headingY;
}
/* check if ball lands on pad, if true bounce back */
if ( (ball.y>= PlayersPad.LEFT) && (ball.y<= PlayersPad.RIGHT) && (ball.x==PlayersPad.x))
{
ball.headingX=-ball.headingX;
playersScore+=10;
}
/* let computer track ball's movement */
if (ball.x>PONG_SCREEN_RIGHT-18) computersPad.y=ball.y;
/* check if ball misses pad, if true display you missed */
if (ball.x<PONG_SCREEN_LEFT)
{
displayYouMissed();
ball.x=ball_Default_X;
ball.y=ball_Default_Y;
}