Cocos2D/Box2d Setting velocity in only one axis - c++

I'm trying to simulate some real jump physics with setVelocity using Box2d in Cocos2d x C++.
My commands are like:
switch (keyCode){
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
physicsBody->setVelocity(Vec2(75, 0));
mySprite1->setPhysicsBody(physicsBody3);
break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
physicsBody3->setVelocity(Vec2(-75,0));
mySprite1->setPhysicsBody(physicsBody3);
break;
case EventKeyboard::KeyCode::KEY_UP_ARROW:
physicsBody3->setVelocity(Vec2(0,200));
mySprite1->setPhysicsBody(physicsBody3);
break;
}
However, as it is clear to me, whenever i change the velocity in one axis, the other axis gets one.
The problem is: i'm unable to run and jump (the jump stops the running).
I need some way to change the velocity in only one axis at a time, so that my jump don't interfere with my run. That or another way to do tat exact same thing. I'm open to ideas regarding the physics since i'm a newbie in game programming.

You should use the ApplyLinearImpulse to get the effect that you are looking for.
// Apply linear impulse only in x-direction
physicsBody->ApplyLinearImpulse(b2Vec(75, 0), physicsBody->GetPosition(), true);
// Apply the jump impulse
physicsBody->ApplyLinearImpulse(b2Vec(0, 200), physicsBody->GetPosition(), true);
The above code will apply impulse and add to the current velocity. Which means that when you jump you will keep moving in the x-direction. This is code from one of my projects so I can confirm that it works.

Related

Cocos2D BezierBy with increasing speed over time

I'm pretty new to C++/Cocos2d, but I've been making pretty good progress. :)
What I want to do is animate a coin 'falling off' the screen after a player gets it. I've managed to successfully implement it 2 different ways, but each way has major downsides.
The goal: After a player gets a coin, the coin should 'jump', then 'fall' off of the screen. Ideally, the coin acts as if acted upon by gravity, so it jumps up with a fast speed, slows down to a stop, then proceeds to go downward at an increasing rate.
Attempts so far:
void Coin::tick(float dt) {
velocityY += gravity * dt;
float newX = coin->getPositionX() + velocityX;
float newY = coin->getPositionY() + velocityY;
coin->setPosition(newX, newY);
// using MoveBy(dt, Vec2(newX, newY)) has same result
}
// This is run on every 'update' of the main game loop.
This method does exactly what I would like it to do as far as movement, however, the frame rate gets extremely choppy and it starts to 'jump' between frames, sometimes quite significant distances.
ccBezierConfig bz;
bz.controlPoint_1 = Vec2(0, 0);
bz.controlPoint_2 = Vec2(20, 50); // These are just test values. Will normally be randomized to a degree.
bz.endPosition = Vec2(100, -2000);
auto coinDrop = BezierBy::create(2, bz);
coin->runAction(coinDrop);
This one has the benefit of 'perfect' framerate, where there is no choppiness whatsoever, however, it moves at a constant rate which ruins the experience of it falling and just makes it look like it's arbitrarily moving along some set path. (Which, well, it is.)
Has anybody run into a similar situation or know of a fix? Either to better handle the frame rate of the first one (MoveBy/To don't work- still has the choppy effect) or to programmatically set speeds of the second one (change speeds going to/from certain points in the curve)
Another idea I've had is to use a number of different MoveBy actions with different speeds, but that would have awkward 'pointy' curves and awkward changes in speed, so not really a solution.
Any ideas/help are/is greatly appreciated. :)
Yes, I have run into a similar situation. This is where 'easing' comes in handy. There are many built in easing functions that you can use such as Ease In or Ease Out. So your new code would look something like:
coin->runAction(cocos2d::EaseBounceOut::create(coinDrop));
This page shows the graphs for several common easing methods:
http://cocos2d-x.org/docs/programmers-guide/4/index.html
For your purposes (increasing speed over time) I would recommend trying the 'EaseIn' method.

Fire event when reach certain angle in revolute joint

I need to develop cannon game using box2d and cocos2dx. Cannon is divided into two parts
Base which is fixed in the ground and doesn't move.
b2WeldJointDef basePlatformWeldJointDef;
basePlatformWeldJointDef.Initialize(base->getBody(), weaponPlatform->getBody(),weaponPlatform->getBody()->GetWorldCenter());
basePlatformWeldJointDef.collideConnected = false;
basePlatformWeldJoint = m_world->CreateJoint(&basePlatformWeldJointDef);
Arm which is fixed in the base with a RevoluteJoint.
b2RevoluteJointDef armJointDef;
armJointDef.Initialize(base->getBody(), arm->getBody(), m_loader->pointsToMeters(ccp(armPosition.x-(arm->getContentSize().width*WeaponScale/4),armPosition.y)));
armJointDef.enableMotor = true;
armJointDef.enableLimit = true;
armJointDef.motorSpeed = 0;
armJointDef.lowerAngle = CC_DEGREES_TO_RADIANS(0);
armJointDef.upperAngle = CC_DEGREES_TO_RADIANS(0);
armJointDef.maxMotorTorque = 2;
armJointDef.collideConnected = false;
cannonRevoluteJoint = (b2RevoluteJoint*)m_world->CreateJoint(&armJointDef);
The cannon should calculate the angle that will fire to, and this is calculated correctly. Using the revolutJointObject->setLimits(lowerAngle, higherAngle) here i use the lowerAngle and the higherAngle both are the desired angle so the arm moves to desired angle directly without motion.
Then i needed to move the arm not just change its angle, so i set the lowerAngle and higherAngle with the old angle and desired angle depending which will be the lower and the which will the higher, and changed the motor speed of the RevoluteJoint
The problem is that i need a callback method which fires when the revolute joint reaches to a certain angle or when the motor speed reaches Zero assuming that when the arm reaches the limit angle will stop and the motor speed will be Zero.
I have searching in SO and i found This Solution which calculates the angle each step, this can be used but it needs more calculations that i feel lazy to do.
Does the callback method for notifying motor speed or certain angle has been reached exists ?
Schedule a function to check your conditions on each frame. When you don't need the checks any more - unschedule the selector, then reschedule when needed again.
As far as I know there are no callbacks for your exact task.
All a callback would do behind the scenes is check the angle each frame and then call the callback function when the joint angle is within a certain range.
There's no built in callbacks for this use case. You could make your own to hide what's going on, or you could just put the if statement in the update function. The performance of this will be fine.

Move 2d circle automatically with constant speed

I want to move a 2d circle in opengl automatically with constant speed on load and then control it with keyboard to move smoothly.
Right now i have the code to move the circle with keyboard, but it is moving only one unit for every keypress.
I want a smooth movement when keypress and automatic movement when on load.
Use glTranslatef to move your object, or alternatively you can just adjust its position x,y,z by a set amount in each update cycle when the keyboard keys are pressed.
E.g
const float MOVE_AMOUNT = 5.0;
public void Update()
{
if (Keyboard.IsKeyDown("a"))
circle.position.x -= MOVE_AMOUNT;
else if (Keyboard.IsKeyDown("d"))
circle.position.y += MOVE_AMOUNT;
}
NOTE: this is not valid C++ syntax, but it gives the overall logic of what you need to be doing, you should be able to figure it out from this. If you want a glTranslate example please let me know.

How can my sprite body will jump and come back to original place in box2d

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)

2D Movement Theory

I have recently been getting into OpenGL/SDL and playing around with objects in 2D/3D Space and as i'm sure most newbies to this area do, have a few queries, about the 'best' way to do something. I quote best, because i'm assuming there isn't a best way, it's personal preference.
So, I have an entity, a simple GL_QUAD, which I want to move around. I have keyboard events setup, i can get the keypress/release events, not a problem.
I have an entity class, which is my GL_QUAD, pseudo implementation....
class Entity
{
void SetVelocity(float x, float y);
}
I then have this event handler code...
if theEvent.Key = UPARROW AND theEvent.State = PRESSED
Entity.SetVelocity(0.0f, -1.0f);
else if theEvent.Key = UPARROW AND theEvent.State = RELEASED
Entity.SetVelocity(0.0f, 0.0f);
My question is, is this the best way to move my entity? This has led me to thinking that we could make it a little more complex, by having a method for adjusting the X/Y Velocity, seperately. As SetVelocity would forget me X velocity if i started moving left? So i could never travel diagonally.
For Example...
class Entity
{
void SetXVelocity(float x);
void SetYVelocity(float y);
}
if theEvent.Key = UPARROW AND theEvent.State = PRESSED
Entity.SetYVelocity(-1.0f);
else if theEvent.Key = UPARROW AND theEvent.State = RELEASED
Entity.SetYVelocity(0.0f);
if theEvent.Key = LEFTARROW AND theEvent.State = PRESSED
Entity.SetXVelocity(-1.0f);
else if theEvent.Key = LEFTARROW AND theEvent.State = RELEASED
Entity.SetXVelocity(0.0f);
This way, if I have an XVelocity and I then press the UPARROW, I will still have my XVelocity, as well as a new YVelocity, thus moving diagonally.
Is there a better way? Am I missing something very simple here?
I am using SDL 1.2, OpenGL, C++. Not sure if there is something in SDL/OpenGL which would help?
Thanks in advance for your answers.
The question is really general since it depends on how you want to model the movement of your objects in your world.
Usually every object has its velocity which is calculated basing on an acceleration and capped to a maximum. This means that a key press alters the acceleration of the object for the specified frame which is then calculated and applied to the current velocity of the object.
This is done through an update phase which goes through all the objects and calculates the velocity change according to the object acceleration. In this way you don't bother to modify the velocity itself but you let your engine to do its calculations depending on the state of every object..
acceleration is applied over a period of time, so in the example by #jack, you would apply an acceleration 10m/s^2 over a time period of one second.
you should also modify your application to make it time based, not frame based.
have a look at this basic game physics introduction, and I would also really have a look at the GameDev.net Physics Tutorials
I assume the way you want movement to work is that you want the player to move only when a key is held.
In short: your solution is fine.
Some potential gotchas to take consideration of: What happens if both left and right is pressed?
Well, what you describe here is a simple finite state machine. You have the different directions in which you can move (plus no movement at all) as the states, and the key-events as transitions. This can usually be implemented quite well using the state pattern, but this is often quite painful in C++ (lots of boilerplate code), and might be over the top for your scenario.
There are of course other ways to represent speed and direction of your entity, e.g. as a 2D-vector (where the length gives the speed). This would enable you to easily represent arbitrary directions and velocities.