Tennis Street - Simulating tennis (#1): The ball

Tennis Street - Simulating tennis (#1): The ball

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:

Two players in a rally.

During the 4 posts we'll explore the following:

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:

Player P launching the ball at a target zone. 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):

All the zones on the opponent's side of the court.

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:

Zones in the court. 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:

Unity settings.

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.


Related Posts

Published by

Juan Pablo Mendez

Juan Pablo Mendez

Game Developer and Designer.