Tennis Tutorial: The Game

Atari’s original tennis game was a lot simpler than later versions. There are no foul balls, for instance, and boundaries are simplified in this game. This requires the code to have complete control over where the ball goes, and how high it goes, since there are no foul balls or net balls. The game is divided into six sets, with the players alternating their position in each set. Scoring is a bit complicated, in order to win a set a player requires a minimum of two point advantage over its opponent.

The game consists of 4 moving sprites, plus the elements that comprise the background and interface: court, net, and score display. The four moving sprites are: The Player, the Ai, the Ball, and the Ball Shadow. They will each contain the logic for their specific types of movement as well as keep the information of where they are currently and where they want to be next.

The court sprite is the only static display object that contains something useful for the code. It has invisible movie clips inside of it that are used in the logic to pick a target position for the either the ball or the Ai sprite. These movie clips are: one for each corner and two lines within each side of the court. The roles these movie clips play will become clearer when the BallTarget and AiWrapper classes are explained.

The game is built within a simple framework that I use a lot, especially with games, with the sprites’ actions being managed by a GameController class that applies the logic of the game to the individual elements, controlling general interaction between the movable pieces, the points, deaths, game over logic and all that nice stuff. All visual elements are inserted into a GameStage class, and all data pertaining to the game is stored and managed by a GameData class.

The document class then only needs to initiate this framework and its 3 classes and the game is off and running. The document class then looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
 
_gameData = GameData.instance;
 
_gameController = GameController.instance;
 
var game_stage:GameStage = new GameStage();
 
addChild(game_stage);
 
_gameController.initGame();
 
_gameController.startGame();

The game’s classes are all inside a separate folder called tennisGame and so the package for those classes will reflect that location.

Tennis offers a good practical opportunity for building fuzzy logic for a simple AI, as well as making you work extra hard to maintain all the illusions 2D isometric games require. But the main challenge with this game is the main challenge with almost every arcade game: consistency.

When you play a game there is a certain amount of predictability that must exist in order for you to enjoy the game. It sounds wrong, doesn’t it? But trust me a good game must have it. What do I mean by predictability or consistency? When you do something in a game you must know you will always get the same result every time you do it. This gets more and more complicated as you begin to string actions together: Run the sprite up to a wall, hit it just right, jump, flip, turn left, and the sprite must do the same thing every time you do all that. If it doesn’t, if it varies anything even a little bit, your brain will notice it, and it will leave you with a bad impression, as if the computer is cheating or not doing its job properly, a feeling of unpredictability, which means you can’t actually plan your actions beforehand, since they might respond erratically anyway. Your brain stops trying to anticipate moves and instead will only be interested in the variations one particular move may cause. Games based on physics engines are like that, games that are more reactive and not based on fixed scenarios.

And here is the complete document class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
 
package  {
 
 
 
	import flash.display.MovieClip;
 
	import flash.events.Event;
 
	import flash.events.MouseEvent;
 
	import flash.text.TextField;
 
	import tennisGame.*;
 
 
 
	public class Main extends MovieClip {
 
 
 
		private var _gameController:GameController;
 
		private var _gameData:GameData;
 
 
 
		public function Main ():void {
 
			addEventListener(Event.ADDED_TO_STAGE, initMe);
 
		}
 
 
 
		/**
 
		 * Init game, and set up listener to wait for USER's click on stage
 
		 */
 
		private function initMe (event:Event):void {
 
			removeEventListener(Event.ADDED_TO_STAGE, initMe);
 
			stage.addEventListener(MouseEvent.MOUSE_UP, onClick);
 
		}
 
 
 
		/**
 
		 * Hide the Intro Movie Clip and start game 
 
		 */
 
		private function onClick (event:MouseEvent):void {
 
			ini.visible = false;
 
			stage.removeEventListener(MouseEvent.MOUSE_UP, onClick);
 
			run();
 
		}
 
 
 
		/**
 
		 * Create the Singletons: GameData, GameController 
 
		 * Create GameStage which will contain all visual elements of the Game 
 
		 */
 
		 private function run():void {
 
			_gameData = GameData.instance;
 
			_gameController = GameController.instance;
 
			var game_stage:GameStage = new GameStage();
 
			addChild(game_stage);
 
 
 
			//init the game elements and start the game main loop inside GameController
 
			_gameController.initGame();
 
			_gameController.startGame();
 
		}	
 
	}
 
}