Reputation: 407
Example: A cannon fired with the speed of ball 60 kpH/
Given: (60 kpH) Distance = 60 kilometers, Time = 1 hour
Libgdx: GameWorld
// Given that I am using 1/45.0f step time, the rest iteration velocity 6 and position 2
// Given that 60.00012 kilometres per hour = 16.6667 metres per second
float speed = 16.6667f; // 16.6667 metres per second
Vector2 bulletPosition = body.getPosition();
Vector2 targetPosition = new Vector2(touchpoint.x touchpoint.y);
Vector2 targetDirection = targetPosition.cpy().sub(bulletPosition).scl(speed);
Problem: but my problem is the cannon ball is not moving in my desired speed, also how do I log the body speed so I could check if the speed is correct. I just noticed it was wrong because the cannon ball is moving so slow, imagine 60 kpH
PS: assume that the above picture width is 5 meters and height is 3 meters
body.setLinearVelocity(targetDirection.scl(deltaTime));
Problem 2: I have no idea how do I compute force by the given speed and step time
// Given that F = ma
Vector2 acceleration = ???
float mass = body.getMass();
Vector2 force = ???
body.applyForces(force);
Upvotes: 1
Views: 2368
Reputation: 946
In Box2d, rather than directly applying a force instead you apply an impulse which is a force applied for a time, which effectively results in a near instantaneous acceleration. To calculate your impulse is just a bit of physics.
First we define some variables, F
is the force in newtons, a
is acceleration, I
is the impulse (which we want to calculate to apply in Box2d), u
is the initial velocity (metres per second), v
is the final velocity and t
is time in seconds.
Using Newtons laws and the definition for acceleration we start with:
Now we can calculate the impulse:
In your case, u
is 0 because the cannon ball is initially at rest so it boils down to:
And that's it! So, in your code you would apply an impulse on the cannon ball equal to it's mass times the required velocity. The following code also contains how you would compute the direction to your touchPoint.
E.g:
float mass = body.getMass();
float targetVelocity = 16.6667f; //For 60kmph simulated
Vector2 targetPosition = new Vector2(touchpoint.x, touchpoint.y);
// Now calculate the impulse magnitude and use it to scale
// a direction (because its 2D movement)
float impulseMag = mass * targetVelocity;
// Point the cannon towards the touch point
Vector2 impulse = new Vector2();
// Point the impulse from the cannon ball to the target
impulse.set(targetPosition).sub(body.getPosition());
// Normalize the direction (to get a constant speed)
impulse.nor();
// Scale by the calculated magnitude
impulse.scl(impulseMag);
// Apply the impulse to the centre so there is no rotation and wake
// the body if it is sleeping
body.applyLinearImpulse(impulse, body.getWorldCentre(), true);
Edit: in response to the comment:
A normalized vector is a unit length vector meaning it has a size of 1 (irrespective of which angle it is at). A visual explanation (from Wikipedia):
Both vectorsd1
andd2
are unit vectors and so are called normalized. In Vector2
, the nor
function makes the vector normalized by keeping it at the same angle but giving it a magnitude of one. As the below diagram shows (blue are original vectors and green are after normalization):
For your game, the point of this is so that the cannon ball travels at the same speed whether the player touched the screen very close or very far from the cannon ball, all that matters is the angle to the cannon.
Upvotes: 4