I’m actually in the middle of talking to my Sound Designer and also developing my Menu System, so the game is nearly complete. I originally promised 1 month per game and we’re 3 days short of 1 month and 1 week, and the reason for that is partly due to my week holiday and 2nd weeks job search.
Anyway, cracking on with the AI issue. So the question was, how do I get the AI racket to follow the ball? Well, I only really care about the ‘y‘ value of the ball, if it’s high or low because that’s the only axis the racket can move along. It can be quite easy to jump from this point to simply saying “well make the rackets ‘y‘ value equal to that of the balls at all times”, this however would be wrong as the racket wouldn’t actually be moving by itself, just repositioned by the script.
This means that the balls ‘y‘ value can simply just be assigned, but it’s still the key to how the AI is controlled. Well if the ball is above/below the racket, we know it has to move, so the first thing we have to do is determine where the ball is in relation to the racket then. For this I created a function called ‘RacketDistance()‘, it simply assigns to a variable the balls ‘y‘ value minus that of the rackets ‘y‘ value. It’s important to note however that the ‘y‘ value is measured from the centre of both objects, it doesn’t take into account the boundaries of both objects. So if the centre of the ball is above the centre of the racket we’d get a positive variable value, if the ball is below however then we’d get a negative value.
From this we can determine if the AI should go up or down, it’s not the most sophisticated, however it works and it reuses some of the code created earlier for how the ball bounces off a racket to create sharp angles. After this function it can be quite easy to make a responsive AI, but there is the issue of how to get it to move in a smooth fashion so it looks controlled and not wild or poorly done. This is where the nub of my issue lay for some time.
I wrote my original solution and then spent some time refactoring it so it was legible and also the logic flow could be seen much clearer. I ended up having a boolean value called ‘velup‘ (short for velocity up), this allowed me to create an ‘if‘ statement checking to see if the racket should consider going up/down or if it was irrelevant – after all, there’s no point in checking half of the ‘if‘ statements when the racket only needs to consider those related to an upward trajectory.
When considering either the up or downward trajectories, I wanted to have the racket rush to further away return serves at full speed and then listlessly collide into serves that were within its immediate vicinity. I therefore checked to see if the ‘tempRacketDist‘ variable was larger than the AI’s half height (the edge of the paddle), if that was the case rush upward to the ball until told otherwise, if not however just move at half speed. In hindsight I realise that I should have done several things slightly differently using this method of dual speed, the first is that I should have checked for further than just the rackets edges for full speed, and the second is I never set the racket to not bother moving if the ball was already within reach.
For the reasons I just mentioned, this resulted in a slightly poor and jumpy AI, it played fine but in terms of how it behaved was poor. I took a few steps back and re-evaluated how this racket should behave. In the end I changed the code only very slightly, I felt the AI should move at full speed if the ball was out of range, however maybe it should only go at a fraction of the original speed when it’s within reach. My reasoning was as such: If the ball is going upward, and the racket is also going upward, the racket has no need to ever overtake the ball, instead it should move WITH the ball as best as it can.
The ‘if‘ statements were changed, the logic shifted and now the AI moves a lot more smoothly, it doesn’t overshoot the ball’s position 3 times before it finally arrives on the AI’s side of the court. Instead it catched up with the ball, checks to see if it’s going up or down and then follows at a quarter speed, sometimes depending on the angle of the return serve this can be too much and it’ll overtake the ball, but it’s never too little as the racket can speed up again toward the ball.
To give an example of how smooth the AI is now, it started like this:
and now, the AI looks like this:
Admittedly I’ve changed the court to be a little wider, it was very hard to win when the court was so thin, it’s still very hard however sadly, or maybe I’m just a little lacking in the pong department, slightly funny how I’ve made it and yet can’t beat it.
The game isn’t perfect by any stretch, the AI snaps to different speeds instead of accelerating up and down, the score UI needs to be repositioned, and again it’s a very hard. However the most important part of the game now, is actually the Menu System, once that’s done the game is effectively finished! There are very minor touches that’ll be left, however in order to keep on time with my project ideas on the 27th the next project will begin. Several days later though it will be posted on Itch.io so you can check there, head back to this article where and update will be put below, or wait for the new article announcing it’s arrival to Itch.
Until then however, thank you for reading, having an awesome day and keep designing.