Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Security game, and Flash.

April 29th update: part 2 released
July 27th update: part 3 released

Some days ago a reader told me about Security 2 game. It’s a simple game: navigate through a level by using the arrow keys avoiding security traps and guards.

Security 2

I found the game so easy do develop but so interesting about artificial intelligence that I decided to start a tutorial about it.

In this part we’ll see how to create and manage the player and the guard/cop.

The player

Creating the player is very easy, especially if you read the first part of Flash game creation tutorial – part 1.

All you have to do is to create an movieclip where you draw a ball, drag the movieclip on the stage and assign it this actionscript

onClipEvent (load) {
	power = 3;
}

onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		_x -= power;
	}
	if (Key.isDown(Key.RIGHT)) {
		_x += power;
	}
	if (Key.isDown(Key.UP)) {
		_y -=power;
	}
	if (Key.isDown(Key.DOWN)) {
		_y +=power;
	}
}

I won’t comment this actionscript because you can find all explainations in Flash game creation tutorial – part 1.

The walls

To create the walls, I created another movieclip and filled it with some squares, the “walls”. Then I moved to the stage and instanced it as “wall”.

The player actionscript changed this way:

onClipEvent (load) {
	power = 3;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		if (!_root.wall.hitTest(_x-power, _y, true)) {
			_x -= power;
		}
	}
	if (Key.isDown(Key.RIGHT)) {
		if (!_root.wall.hitTest(_x+power, _y, true)) {
			_x += power;
		}
	}
	if (Key.isDown(Key.UP)) {
		if (!_root.wall.hitTest(_x, _y-power, true)) {
			_y -= power;
		}
	}
	if (Key.isDown(Key.DOWN)) {
		if (!_root.wall.hitTest(_x, _y+power, true)) {
			_y += power;
		}
	}
}

As you can see in lines 6, 11, 16 and 21, I check the hit test between the center of the player and the wall before moving him. If I “foresee” the player’s center will hit the wall, I don’t move him.

Now the player can move through the scene, but I don’t like the player can partially disappear behind a wall. That’s due to the way I made the hit test. Testing with the center of the player, that’s what I got.

Time to change a bit the actionscript

The walls – part 2

In this second attempt, I introduced the concept of radius.
Knowing the radius of the player allowed me to determine the hit test not relatively to the player’s center but on the player’s edges.

onClipEvent (load) {
	power = 3;
	radius = 6;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		if (!_root.wall.hitTest(_x-power-radius, _y, true)) {
			_x -= power;
		}
	}
	if (Key.isDown(Key.RIGHT)) {
		if (!_root.wall.hitTest(_x+power+radius, _y, true)) {
			_x += power;
		}
	}
	if (Key.isDown(Key.UP)) {
		if (!_root.wall.hitTest(_x, _y-power-radius, true)) {
			_y -= power;
		}
	}
	if (Key.isDown(Key.DOWN)) {
		if (!_root.wall.hitTest(_x, _y+power+radius, true)) {
			_y += power;
		}
	}
}

Line 3: Determining the radius of the player

Then on lines 7, 12, 17 and 22 I performed the same hit test as before but not relatively to the center.
If, for example, the player is going left, the hit is performed on the player _x position (the center) minus the power minus the radius.

This allowed me to get a more accurate movement, but with some glitches (the same affecting the original Security 2 game).
In some cases you may notice the player stops some pixel before touching a wall, and in some other cases the player can walk through a wall if the wall it’s not in the direction the player is walking (this one don’t affect Security 2).

The first glitch appens because I move the player of 3 pixels/frame.

Imagine that the player has a radius of 6 pixels and is 8 pixels far from the wall. The test is performed on the pixel that is 9 pixels from the center (6+3) and it is a successful test, so I do not move the player. The player just stops 2 pixels away from the wall. How bad!

The second glitch happens because every time I go in a direction, I perform the hit test only in that direction, so if the player is very close to a wall corner, he can walk through a wall. Look at the picture to understand both glitches:

Glitches

So I needed to try another way

The walls – part 3

This is the new idea: I do not care about hit test when I move the player, but when I am about to display the frame

Look:

onClipEvent (load) {
	power = 3;
	radius = 6;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		_x -= power;
	}
	if (Key.isDown(Key.RIGHT)) {
		_x += power;
	}
	if (Key.isDown(Key.UP)) {
		_y -= power;
	}
	if (Key.isDown(Key.DOWN)) {
		_y += power;
	}
	while (_root.wall.hitTest(_x, _y+radius, true)) {
		_y--;
	}
	while (_root.wall.hitTest(_x, _y-radius, true)) {
		_y++;
	}
	while (_root.wall.hitTest(_x-radius, _y, true)) {
		_x++;
	}
	while (_root.wall.hitTest(_x+radius, _y, true)) {
		_x--;
	}
}

As you can see, in lines 6-17 I move the player without caring about hit tests, then at lines 18-29 I perform the test and move back the player of one pixel in a direction every time the hit test is detected in that direction. Since player’s speed is 3, the while loop won’t be executed more than 3 times, that is not CPU expensive.

The only thing I can say about this script is that the player can walk a bit through a corner, but it is not affecting the gameplay if the player has small size.

Now it’s time to design better levels

Designing a level

To design a level, I suggest you not to draw some boxes around the screen. Draw instead a big square covering all the stage then remove the parts you want to be walkable. Refer about designing levels for the game Tunnelball in this tutorial for more information about this way of drawing levels (or become a regular reader of this blog…)

Here it is a level designed in the new way

Now it’s time to add the guard/cop

The cop

The “line of sight” of Security 2 cops may seem awesome, but there is not artificial intelligence in it: I can do the same in a single movieclip.

As you may see, I simply designed the cop with his line of sight and managed it as a simple movieclip

onClipEvent (load) {
	power = 3;
	radius = 6;
	_x = 35;
	_y = 40;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		_x -= power;
	}
	if (Key.isDown(Key.RIGHT)) {
		_x += power;
	}
	if (Key.isDown(Key.UP)) {
		_y -= power;
	}
	if (Key.isDown(Key.DOWN)) {
		_y += power;
	}
	while (_root.wall.hitTest(_x, _y+radius, true)) {
		_y--;
	}
	while (_root.wall.hitTest(_x, _y-radius, true)) {
		_y++;
	}
	while (_root.wall.hitTest(_x-radius, _y, true)) {
		_x++;
	}
	while (_root.wall.hitTest(_x+radius, _y, true)) {
		_x--;
	}
	if ((_root.cop.hitTest(_x, _y+radius, true)) or (_root.cop.hitTest(_x, _y-radius, true)) or (_root.cop.hitTest(_x+radius, _y, true)) or (_root.cop.hitTest(_x-radius, _y, true))) {
		_x = 35;
		_y = 40;
	}
}

Line 32 performs the test in the four sensible spots of the player and, if checked, moves the player to his initial position (defined at lines 4 – 5 and 33 – 34)

Try to go through the “line of sight” and you’ll see by yourself.

Now all you have to do is move the cop along a defined path and you’re done.

During next tutorials I will explain how to make a real line of sight, how to add more stuff (patrolling cameras, traps, terminals etc).

Download all examples (I included a in-progress example too, not mentioned in this tutorial), give me feedback and enjoy, then proceed to part 2.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.