Software Developer
APCoverImage.png

Audio-Pong

Design Brief

Design Brief

‘Audio Pong’ was to be a game playable by both blind and sighted people. More specifically then Pong, it was to be a single player variant of Pong; with an intelligent AI that had tune-able difficulty. Pong was chose as the base game due to it’s relative simplicity, but also it’s importance in gaming history.

The main crux of this project lay in its adaptations for the blind. The concept was for various audio cues to tell the player what was happening and where both the paddle and the ball where on the field. Specifically audio cues were needed for:

- The Ball’s Position

- The Player’s Paddle’s Possition

- A bounce off of the wall

- A bounce off of a paddle

Version 1 Design

Version 1 Design

The game was made in the unity engine, due to my previous familiarity with the engine and my preference for the Unity API over the Unreal API. As such I opted to utilize Unity’s 3D physic engine in order to handle the bounces, as well as to cue the playing of the sound effects.


The game is thus made using primitive 3D assets, shown from the side using an orthographic camera projection. This gives the same simple visuals as in pong, while still utilizing the 3D physics engine. The gameplay was classic pong, for the most part, however I did explicitly make it so the speed of the ball was increased every time the ball hit the players’ paddle, regardless of the direction of the ball or the bounce.


For the audio cues I went with background drones for both the ball and the player’s paddle. A continuous drone for the paddle and a continuous beeping for the ball. Both sounds would be pitched up or down in relation to their y-axis. The bounces were all given a similar bounce sound effect, with the wall bounces having their sound being pitched up or down depending on which wall it was.


For the AI, rather than using the original pong’s y-axis chasing algorithm, I decided to make the AI a bit more ‘clever’, so as to give the feeling of playing an actual person. The AI calculated where the ball is going to intersect with its own (the AI paddle’s) y-axis. It would take into account up to one bounce off of a wall. In order to make the difficulty scalable the AI only evaluates the balls ‘destination’ once every n seconds; n being a floating point value that can be publicly accessed. Thus a harder AI would effectively ‘think’ quicker than an easier one. Additionally the AI had a settable movement speed, thus allowing for more fine tuning of difficulty.

Version 1 Response

Version 1 Response

I had a group of friends test the game for me. As none of my testers were blind, I added a toggled function that would black out the game-play from the screen, thus preventing them from cheating accidentally.


The game-play was well received overall. That was expected however; it was only pong. I was told that the AI was a bit buggy, and would occasionally rush to opposite side of the court than the ball for no determinable reason. I was also informed that the AI, when not bugged, could be impossible to beat.


The more important issue was the audio cues. Unfortunately I was informed that while tracking the ball and paddle was possible with the in-place system, it was very unintuitive and hard to do. Specifically keeping track of both the paddle’s pitch and the ball’s pitch was too mentally taking for most players to do.

Version 2 Design

Version 2 Design

With the negative response to the current audio cue system, a new one had to be implemented. Initially I tried changing the drones of both the ball and the player, in order to make the two more distinct, but my playtesters still considered this to be too difficult. Additional testing within the editor revealed that the ‘pitch‘ function of the Unity audio source component actually worked by speeding up and slowing down the audio, rather than just changing the pitch. As such, I scraped the dynamic pitch concept.


To replace the dynamic pitch I decided to instead use the stereo pan in order to differentiate which side of the court the ball and player paddle were on. This was chosen for two reasons. The first was that it made a lot of sense if you thought about pong being a Tennis Match. I also made the pan be relative the player paddle’s position for this very same reason. It places the player on the court with the ball being to one side of the player, rather than the ball being to one side of the court. To coincide with this change, I also switched the controls to be left/right rather than up down. The other reason for this was due to the Unity audio source component already having a pan function for me to use. This allowed me to keep most of the pre-existing code the same, only requiring a change to the method called on the audio source.


The other major issue was the AI. The bug that resulted in the AI rushing to the opposite side of the court was found to be caused by an error in my logic for handling the change in the bounce calculation off of the top edge of the court. After some paper simulations and some trial-and-error, I managed to get the AI responding to the top bounce correctly. I also increased the time delay between destination calculations, in order to make it easier to for the player to beat the AI. I considered reducing the speed of the AI’s movement, but I wanted the mechanics to be as even for both sides as possible.

Version 2 Response

Version 2 Response

The response to this version was a lot more positive. The players were able to beat the AI in a non-bugged match, provided they worked for it. We were getting long, continuous rallies that were very tense to watch. However this was where we started to run into physic issues.


Due to the increase in the speed caused by the bounces, the ball started to reach speeds that the unity physics engine was incapable of handling consistently. The ball would occasionally ‘tunnel’ through one of the side barriers and thus be lost to the players. This mostly happened when the ball hit the barrier at a near-perpendicular angle.


Another issue we had was with the ball’s angle of motion. On many occasions the ball would end up bouncing between the top and bottom barriers at near perpendicular angles. While the ball would eventually reach the other end of the court, the situation was almost always flow breaking for the player.


The final physics issue was a bug with the code used to impact a new direction onto the ball. Specifically, It was possible for the player to impart an impulse onto the ball that was the direct counter of the balls prior velocity, thus freezing the ball in place.

Version 3 Design

Version 3 Design

At this point I decided to add a proper menu and set of win/loss conditions to the game. The win/loss system was that of regular tennis, first to 5, must win by 2. The trick was that every score had to be voiced. That was done with an array and a mapping function that retrieved the correct audio clip depending on the score. The menu similarly required voice work for every menu function, that would play when a menu button was focused on. I also added a paddle playing against an off screen component to the menu, just to give it some visuals for sighted players to look at.


Additionally I added two new sound effects. The first was a ‘movement blocked sound effect, that triggers when the player attempts to move off of the court. A simple but fundamental piece of auditory feedback. The other new audio cue was a drone indicating the player’s paddle is aligned along the x-axis with the ball. The intensity(volume) of the drone scales with how inline with the center of the paddle the ball is.


As for the bug fixes, the escaped ball was fixed by increasing the size of the barrier so as to minimise the chance of tunnelling. I also decreased the rate at which momentum was added to the ball. As a failsafe, I added a check to the game logic that calculates if the ball has escaped the count and if it has it teleports the ball back to its correct location court and halves the ball’s velocity.


The issue with the continuous bounces between the top and bottom barriers was solved by adding a minimum value that x component of the balls squared velocity could be. Making it the squared velocity allows the limit to apply regardless of components sign.

Version 3 Response

Version 3 Response

This final version of the game was the best received of the versions, with the game being an enjoyable challenge. However the game was still reported to be very difficult to play if actually blind. One error noticed by one of my testers was that the ‘Alignment Drone’ sounded off to him. This tester (James) has a very good ear for audio quality, and so I took his observation seriously enough to make some in engine tests to try and isolate the issue.


I discovered that the fadeout for the alignment drone was happening in reverse. When the ball would enter the faded area, the volume would start at max and become quieter as the ball approached the ‘Aligned’ area. Once in the aligned area, the volume would once again reach max volume. Due to the relatively small size of the ‘fade’ area and my own over use of my eye when testing I had missed the error. A quick patch to fix the error and, in the words of tester James, the blind version became ‘playable’.


The testers also liked the ball and paddle visual on the menu but did notice that the balls speed seemed to be inconsistent. Unfortunately I have not been able to discover what is causing the issue as to my knowledge the balls are all the same prefab and have the same magnitude of velocity, but admittedly I haven’t put much effort into fixing it. The testers also enjoyed the score announcements, although I feel they enjoy ripping into my voice acting even more.

Conclusion

Conclusion

Overall, I feel this project is a partial success. The game is playable for the visually impaired but would be a stretch for those with complete blindness. It is however still possible for them to play, which is better than not being able to play at all.


The biggest flaws in seem to come from laziness in my physics handling. In hindsight, I should have written my own physics engine into the game loop, and coded hard borders into the game, rather than relying on Unity’s engine. While the Unity physics engine is perfectly fine for most physics calculations, it isn’t suitable for high-speed calculations, and thus is prone to tunnelling.


Additionally, I probably would have been better to just write a custom engine for the project. This would have made the game much more light-weight and faster to run. Admittedly this would have forced me to completely rewrite the required physics functions, but that wouldn’t have been that much extra work.