Antonis Katzourakis / βlog

How I made a simple Pong “AI” using Control Engineering theory

3 Sep 2017

Applying Control theory to make a simple computer adversary for Pong

A couple years back I developed Myo Pong, a simple game in which you can use your Myo Armband to control the paddle of your player. The game was a great success, because it was the simple arcade game we all know, with the ability to use up to 2 armbands to play with your friends.

However, since it is first development I knew I needed some sort of computer adversary, so that there is a single-player mode. What I did back then was a dirty hack that I was never proud of: the computer’s paddle only followed the ball according to its coordinates, with some randomness in slight movements so that it can be actually defeated.

At first this seemed to work better than expected. There were 3 main problems though:

  1. As soon as you realise there is some-sort of pattern on how the computer can lose, you can immediately score points
  2. It felt really unnatural to follow the ball immediately when the direction changed, even at high speeds.
  3. I wanted to implement 3 levels of difficulty. I did this at first by changing this “randomness” parameter I mentioned earlier: the less random - the harder. This failed horribly to the point that the game was unusable. Therefore, I fixed the parameters to the value that it works and as long as you don’t figure out the pattern, the game is a bit challenging.

That bugged me a lot. Especially when I started updating all of my apps to include better user experience, use the latest SDK for the armband and clean up the messy parts of the code. So, I asked myself: How will I make a better AI, without using CoreML so that iOS 8 devices are supported?

Before starting developing, I waited a week, asking myself the same question: Should I do it with PID?

After waiting for too long, I decided to just give it a try, I had nothing to lose.

PID is a technique which belongs to the classic Control Engineering theory nowadays. It is a very simple mechanism which is used in the industry though, and having done a couple of projects with it, I though it shouldn’t be hard to implement a simple controller for Pong.

A PID controller block diagram - Credits: Arturo Urquizo

So, I started by stripping off all the old, unreadable, unmaintainable “AI” code which I hated so much and started from scratch.

I started by writing down the PID controller on code in my game-update function. The game has been built on SpriteKit. Therefore, my objects have everything I need:

  1. Current position
  2. Current velocity
  3. Game update interval

The error e(t) is the difference of the position of the ball and the AI-player’s paddle.

Using the velocities it was possible to calculate the Differential (D) parameter, using the current positions I can do the Proportional (P) parameter, and the Integral (I) is calculated by the simple numerical integration of Euler using the update-interval.

Since this feedback loop is happening almost continuously, the resulting y(t) shouldn’t change too much, and therefore my gains should be quite low.

Basic code of my PID-implementation

After developing for 2-3 hours, I gave it a go. After some fiddling around with the gain values, I managed to get something working. And actually, it was working very well. The motion of the paddle was natural now. But the best part of it was that by slightly changing the P-gain, it was possible to have different difficulty levels.

I was very satisfied with the result. This very simple controller can be deployed to iOS 8 devices, and satisfies the rest of my goals for this AI - taking into account that game development is not something I am really into. I think this was an update that many users were waiting for.