This will be a small post in which we would make a bullet or a projectile which can be added to a game. Most of the games have some sort of ranged weapon or an enemy having ranged weapons throwing bullets, arrows etc.
Making a Bullet:
We would consider bullet to be a circular fixture so we would attach a circular fixture to the body.
- Low Denisty
- IsBullet -> True (This is required if fixture attached is really small and speed of bullet is fast, because this flag enables Continuous Collision Detection which protects against tunneling through thin fixtures)
- IsSensor -> False(By Default it is false but if you want to make bullets which can kill and go through enemies (like super bullets) then you can sensor to true and in collision handling just kill the enemy when collision is detected)
- Shape :- Circle Shape
The above properties can be used to make a circular bullet.
Arrows are little tricky. We tried to make arrow a polygon of the kind of shape shown below and added custom drag at its tail to simulate a real arrow. But most of the time they never landed on the ground vertically and would fall horizontal. So we skipped to a circle shape fixture as it looked better.
It had similar properties as above. Just for the texture which was attached we made adjustments to its position. First was to make the texture start at the tip of the circle fixture. So we took half height (as width was negligible) and texture’s position was calculated as body position’s y coorindate – the half height. Now we have to rotate the texture to point in the same direction as the body. To calculate the direction of the body we just calculated the body’s angle as Math.atan2(velocity.y,velocity.x) i.e taking tan inverse of the direction of the velocity to get the angle. Now taking body center as pivot we rotated the texture center point as ->
Finally we set the rotation angle to the Texture in degrees to match the angle of the body’s velocity.
Note: When we say body position we actually mean the position which has been scaled to world coordinates.
Adding the body in the box2d physics world:
Suppose we have an enemy and it is shooting bullets. So either we can have a array in enemy class to handle the bullets or have a global body manager as mentioned in the previous to handle the bullets. It can be useful if we keep references of bullets in enemy class but creating them in a global manager. In other case if an enemy dies and you destroy the object then the bullets which were created in the enemy object would also be destroyed but if the enemy class just has a reference from a global object manager then the bullets will still remain active till they hit the obstacle.
For shooting/throwing a body the easiest way is to apply impulse. Its syntax is body.applyLinearImpulse(ImpulseX,ImpulseY,pX,pY) where ImpulseX and ImpulseY are impulses in x & y direction and px and py are the points where you would want to apply the impulse. Usually we put impulse at the center of the body so px would be body.getWorldCenter().x and py would be body.getWorldCenter().y as the arguments should be in world coordinates. getWorldCenter() gives the center of body in world coordinates. There is another function called applyLinearForce which can be used to apply a constant force to a body over a period of time. Impulse on the other hand is a fast acting force which causes instant change in velocity and does not depend on time. You can think of ApplyLinearForce in cases like applying gravity,wind drag etc and ApplyLinearImpulse in case like hitting a ball where force is short lived.
Smooth Rotation of Texture:
In the above case arrow’s body velocity can change really fast for e.g. an arrow shot vertically in air its y speed would change from positive to negative in a frame which can be a potentially a 180 degree change in a frame’s time. So that would give a really jerky look to the animation. In balloon shooter we added two variables, one to hold the current body angle and other to hold current texture angle. In updates we would slowly increment texture angle to reach the body angle value in fix steps rather than reaching the value in one frame.
Thanks for the patience. If you have any queries/suggestion please put them in comments and we would try to answer them.