Tennis Street is an arcade game about tennis. During this series we'll explore a model we can use to simulate the sport so that we can have our two tennists throwing a ball at one another on the tennis court:
During the 4 posts we'll explore the following:
- Setting up the court and making the ball behave like a ball.
- Determine where we want the ball to go.
- Launching the ball where we want.
- Hitting a ball that was thrown at a player.
The Court
To start off, if you're not familiar with Tennis: it's a game where two persons throw a ball at one another until one of the players cannot hit the ball back. The ball must land inside a square on the opponent's side of the court. The sport is a little more complicated than this, but so far we have this:
In grey, you can see the court. P is the player currently throwing the ball. In red, you can see the current ball's path and T is the place where the ball initially lands.
As we said, the ball in Tennis must land in a squared region on the opponent's side of the court. Depending on the stage of the game, the ball may be required to land in different zones inside that square (this applies only to 1v1 matches, 2v2 matches are just slightly different):
Of course, the target squares you need to aim towards depend on the side of the court you're in. You don't normally want the ball bouncing on your side.
We can simulate this in an engine by defining the zones as polygons with 4 vertices, and storing this in a tree data structure, so that bigger zones contain the smallest zones. And you can solve the problem of determining where a ball landed by identifying the zones with binary flags, so that the ball can be in multiple zones at once:
public enum ZoneType { Half, Serve };
public enum ZoneId {
None = 0, //0000000
Half = 1 << 0, //0000001
ServeL = 1 << 1, //0000010
ServeR = 1 << 2, //0000100
}//Add more at the end!
Here we identify the regions of the court by flagging them as either half the court or one of the two serve regions. Notice that the ball can be both in a half and in the left serve region by doing this:
ZoneId ballLandZone = ZoneId.Half | ZoneId.ServeL; //0000011
Make sure to validate the different states.
So we have these zones in the game:
Unity has a class called Rect that can help us with the definition of these zones.
The Ball
Now, if we're using a physics engine we already got the physics calculations covered - we only need to configure the physics engine so the ball acts like a ball! In Unity we can achieve this by creating a GameObject with a Collider, a RigidBody, and assigning a Physics Material to the object. You can use the Engine's gravity if your game is not gonna have to rotate the court in space or some such weirdness. Also, make sure you use some kind of continuous collision detection. Failing to do it may result in your ball skipping collisions if it goes fast enough or against a thin-enough object.
This is an example of settings that achieve the desired effect:
In the next blog post, we'll explore why (even if we are using the physics engine) we want to have full control of what the ball does. And we'll explore how we can achieve that.