AWS Logo
Menu
Tez: A 2D Car Racing Game

Tez: A 2D Car Racing Game

Amazon Q Developer helped create Tez, an exciting 2D car racing game built with HTML, CSS, and JavaScript, using advanced tools to boost gameplay and dynamics

Published Jan 14, 2025

Tez: The EV Racing Game

Hey everyone! I’m thrilled to share my game, developed with immense help from Amazon Q.
logo
tezlogo
Check it out: Tez:TheGame.link
(optional: before you start the game, please read below to learn more about the details and inspiration behind its creation)

🥇 Background

In late November 2024, I learned about the AWS Game Builder Hackathon. As soon as I read the hackathon's criteria, I knew I had to jump at the opportunity because of my passion for gaming. I’ve always been fascinated by the work it takes to build a game. Growing up as a huge fan of car games like Need for Speed: Most Wanted, Burnout, and many others, I was inspired to incorporate bits and pieces of nostalgia from those classics into my project.
As an electric vehicle (EV) owner—because apparently, I decided charging anxiety wasn’t stressful enough—I felt inspired to create an EV-themed game. It shows off the cool features of EVs while bringing some much-needed excitement to the mix.
gameplay1
gampeplay

🎮 Controls

Use the arrow keys or the letter keys mentioned below to control the car.
↑/W: Accelerate
↓/S: Deaccelerate
←/A: Turn Left
→/D: Turn Right

📜 Rules

To maximize your chance of earning a higher score follow the rules of the game and beat the clock!
Check out the rules page for details; alternatively, they are also mentioned in the post below:
Rule 0: Points
Points will increase continuously as long as the game isn't over, there are no collisions, the player doesn't go out of bounds, and the speed limit is maintained when the police arrive.
Rule 1: Collect Batteries
As you progress through the game, make sure to collect batteries that are found on the road, failure to collect will decrease the battery on the right and the game will end early.
Rule 2: Dodge Cars
Dodge the blue cars as they appear on the road. They are one of the obstacles in the game. If you collide with a blue car, the screen on the left will turn red, indicating that you have collided. You will lose 5 points from the scoreboard if you collide.
Rule 3: Stay on Track
Stay on the road and avoid going onto the grass area. If you do, the screen on the left will turn yellow, indicating you're out of bounds. You will lose 2 points from the scoreboard if you try to leave the road area.
Rule 4: Cops Arrival
During gameplay, cops will randomly arrive, indicated by the rearview mirror at the top. When the cop's head appears, move left and right to show that the cop is nearby, and you must keep your speed under 90 km/h. Failing to do so will result in losing 3 points each time you exceed the speed limit, until the speed limit is met.

🧱The Making of TEZ: The Game🧱

Foundation
It took me a few days into the hackathon to decide on the gaming genre for my project. Here was my thought process:
  • RPG/Fighting Game: Might be a little too violent in nature.
  • Tic-Tac-Toe/Hangman: Might be too simple.
  • Are you Smarter than 5th Grader type game: GenAI version: I was also contemplating on creating a trivia game like Are You Smarter than 5th grader using tools like AWS Bedrock(GenAI) to integrate and generate new question per each user session on a more chat based bot, that acts as a host of the show, I had to scrape that idea, because I wanted to keep things simple and fun.
Final Decision:
I chose a Racing Car Game—a bit of a stretch, but adding unique obstacles could make the game more fun, exciting, and thrilling.
Once I decided to build a Racing Car Game, I knew there were some trade-offs I had to make to meet the hackathon deadline. With that in mind, I began researching previously built racing games on the internet for inspiration. I came across a wide range of sandbox games created by developers from around the world—some appeared complicated, while others didn’t feel user-friendly. The trade-off I ultimately made was to opt for a 2D game instead of a 3D game, due to the fast-approaching hackathon deadline.
I was able to narrow down my search for 2D racing games and came across a very useful blog and project that formed the foundation for building this game.
The blog mentions that 3D projection onto a 2D screen relies on basic trigonometry using the law of similar triangles (learned this in Grade 12 😊). To project a 3D onto a 2D surface, key variables like camera height, distance from the camera to the screen and the distance from the car are used. The equation **(y = h*d/z)**​ helps calculate the screen's y-coordinate for a given point, which is how objects are projected onto the 2D plane.
To calculate the x-coordinate for a 3D point in a top-down view, a similar equation is used: x=w*d/z​, where 'w' is half the width of the road. Both the x and y coordinates are scaled by a factor of d/z​, which accounts for the distance from the camera to the object, creating the illusion of depth on a 2D screen.
similar triangle
similar triangle diagram
To calculate the distance 'd' from the camera to the projection plane, it’s derived from the desired vertical field of view (fov) rather than being hard-coded. Using the formula d=1/tan(fov/2), we can adjust the camera’s zoom by tweaking the fov variable. This allows for dynamic adjustments to the rendering algorithm for better control.
Once the research phase was over, it was time to start the development. I came across a free-to-use Code Pen Project that provided a base car game with a landscape, mountains, road, grass, and a car that moved using the arrow keys.
base
base game
Implementation/Development Duration
Github Link
After understanding the complete codebase, I started making the necessary changes, and this is when Amazon Q Developer came to the rescue!
1.1 Game Design
Sprite Files: Using AWS Amazon BedRock, I was able to use generated sprite file that was used to build the game, which was just png image files
I removed the the car that was drawn using Javascript DOM properties, by following the code and recognizing the unwanted functions
remove_help
Amazon Q Developer assisting removing unwanted game components
Once the sprite files were generated, Amazon Q helped making the necessary code changes, to include the sprite file appropriately in the game. Along with that Amazon Q also helped me modify the keystroke to activate, for example when user pressed arrow left, (car_left.png) is activated.
Removed the Sun from the game canvas, as I didnt feel the need for it at that moment.
Amazon Q helped me modify the speedometer to give it a more futuristic car look.
Additional game design elements were also assisted by Amazon Q:
  • Added a steering wheel that moves left and right based on user input.
  • Integrated a scoreboard on the right to help users track their score.
  • Introduced a screen element to detect and identify collisions and out-of-bounds events.
  • Added a rearview mirror for a more realistic touch
day1
Day 1 Progress
Process Duration: ~ 2 Days
1.2 Game Development
Once the game design reached a satisfactory stage, it was time to tackle the most challenging part of the project: game development. This phase was crucial, as it would determine the entertainment value and overall trajectory of the game
Functionality
Car Movement:
As mentioned previously, Amazon Q helped me create the functionality for the user car movement and incorporate the sprite files for the game.
Sample prompt: carup.png, carleft.png, and carright.png are the main game sprites. Can you help me implement this so that when the user clicks the arrow keys or W, A, S, D keys, the corresponding sprite activates based on user input?
With this prompt, Amazon Q helped me build the car and car movement functionality.
Reference: Functions drawCar(), update(), calcMovement(), downKey(), upKey() in script.js
Sample Prompt: @workspace When user press the arrow keys or the WASD keys, instead of the car object moving, the road should move, that reflects more of like a driving experience. Just like how current code is currently functioning.
With this prompt, Amazon Q helped me build the functionality that mimics a driving experience. Instead of moving the car object on the page, I worked on animating the road based on user input.
Reference: Functions draw(), drawRoad(), update(), drawGround()
Process Duration: ~ 2 Days
Obstacle:
Next, I worked on the obstacle component of the game, which involves spawning cars that the player must avoid. This part required a significant amount of work and careful thought to handle the obstacles effectively and to craft better prompts for Amazon Q Developer.
Sample Prompt: @workspace Add the car obstacle(car_01.png) within the border of the road, this is the obstacle part of the game, where the car comes in the way of the user
Sample Prompt: @workspace Make sure the car obstacle, is being spawned from the center of the road, and must seem like as it is coming towards the user, like a driving experience
Reference: classObstacle(), spawnObstacle(), updateObstacle()
Process Duration: ~ 3 Days
Scoreboard:
The scoreboard was designed to track user scores, aligning with the EV-inspired theme of the game. While I initially planned to track only the scores, I decided to incorporate battery degradation as a factor influencing the score, adding an extra layer of strategy to the gameplay. Additionally, I included a time limit feature as part of the scoreboard to enhance the challenge.
Sample Prompt: @workspace I want to create a scoreboard on the right, that would keep track of the score, and that scoreboard would also have the time limit(2 minutes). This will countdown separately.
Sample Prompt: @workspace I also want to add a functionality in the scoreboard, to keep track of the battery, over time as user is progressing through the game, there needs to be a functionality, shows battery degradation. Once battery reach 0%, the user car should stop, so once the battery reaches end, user should not be able to press W,A,S,D or arrow keys to proceed further(more on the battery functionality later)
Reference: Functions startCountdown() and startIndependentTimer()
Process Duration: ~ 2 Days
Battery Collection:
I used another sprite file, generated by AWS BedRock, for the battery. Throughout the game, the player can collect batteries to charge the battery in the scoreboard, keeping the game going for a duration of two minutes.
Sample Prompt: @workspace Use the battery_powerup.png, as sprite file, this sprite file must be spawned like how obstacle are being spawned, and when user collects the battery this should increase the battery by certain percentage, in the scoreboard
Reference: Functions spawnBattery(), updateBatteries(), drawBatteries()
Process Duration: ~ 1 Days
Collision and Out of bound Detection:
  • Car Obstacle Collision:
    I created a system to reduce points on the scoreboard whenever the user’s car collides with an obstacle car. Each collision deducts 5 points from the score.
  • Sample Prompt: @workspace using the user car object and obstacle car object, every time both the object overlaps half way, this would indicate that there is a collision. Deduct -5 pts from the scoreboard component.
  • Battery Collision:
    Once the Car Obstacle Collision functionality was implemented, I applied a similar approach to increase the battery count when the user’s car collides with a battery object. The idea was to reward the player with additional battery points for every successful collection.
  • Sample Prompt: @workspace similar to obstacle, collision and detection. I need to implement similar functionality. The battery must spawn on the road area, within the width of the road. Once the user object collides with battery object, some percent(reasonable amount), should be increased as the user drive car
  • Out of Bounds Detection:
    During testing, I noticed that when the user’s car was positioned near the corner between the grass and the road, it became easier to dodge cars and earn points due to the orientation of the screen and game canvas. To make the game more challenging and fun, I added an out-of-bounds detection system. If the user goes off-road, they lose points from their total score.
  • Sample Prompt: @workspace I noticed, that it is easy to dodge car and increase points on scoreboard, when the user car is between grass area and the road area. Every time, the user object overlaps the border of the road(white area), this should be a penalty and decrease 3 points from user scoreboard
Reference: class Obstacle(), class Battery()
Process Duration: ~ 1 Days
Cop Detection/Randomization:
This is my favorite part of the game, which I really enjoyed building with Amazon Q Developer. I wanted to add a feature that resembles the experience of GTA and Need For Speed: Most Wanted, so I thought, why not make it unique? I decided to randomize the appearance of the cop in the rearview mirror, making it move left to right and right to left. This functions as an obstacle in the game—if the user exceeds the speed limit, 3 points are deducted from their score.
Sample Prompt: @workspace I want to add a cop type functionality as part of another obstacle, separate but part of the game. First, lets start with, cop01.png, I want it appear between the width of rear-view mirror, animating moving from left to right and right to left.
Sample Prompt: @workspace Now that this is animating, I want to randomize the occurrence of this, currently it is always animating, staying on the screen. So it should only be shown on rear-view on a randomize occurrence, this will represent the first part of building the second obstacle
Sample Prompt: @workspace now that this is setup, every time the cop01.png appears on the rear-view mirror on the random basis, the game canvas, should flash red and blue, resembling a siren
Sample Prompt: @workspace now that this is setup, flash red and blue, resembling of a siren, should only happen if user speed is above a certain limit for exe: 90km/h (34 in frame rate)
Reference: functions initCopCar(), animateCar(), animateCar() checkSpeedAndApplyEffects()
Process Duration: ~ 2 Days
Game Over:
There are two indications that the game is coming to an end. The first is when the user fails to collect batteries, and the battery runs out, causing the game to end while providing the user with their updated score. The second indication is when the 2-minute timer completes, signaling the game is over and also updating the user's score.
Sample prompt: @workspace There are two ways the game ends, if the user cannot collect battery, and battery reaches 0, edit the gameCanvas, to a dark background, with score and with message "Game Over", "Battery ran-out". The other way is when the timer, in the score board, reaches 00:00, then the game canvas should have a dark background with message "Game Complete", with updated score.
Reference: functions showGameOver()
Process Duration: ~1 Day
Bugs and Defects:
Dealing with bugs and defects was one of the most challenging and time-consuming parts of the development process. Since I was building a game, I had to continuously test the end-to-end functionality to ensure the behavior met my expectations, which sometimes became a lengthy process. There were days when tackling bugs and defects felt demotivating and threatened the timely submission of my hackathon project. That's when Amazon Q Developer came to the rescue. The bugs and defects stemmed from my lack of detailed prompts, which Amazon Q interpreted in unintended ways, leading to issues. Eventually, I decided to reverse-engineer a few steps and began prompting Amazon Q to ask me questions to better assist me. Amazon Q did an excellent job, asking smart questions like, "What was observed? Provide pieces of code that affect the overall application. Explain the current behavior of the application and the expected behavior." After I provided those follow-up answers, Amazon Q was able to effectively help me fix the functionality of my code.
Process Duration: ~ 4 Days
1.3 Web App Development
With my background in development, I was able to handle the basic web development tasks needed for this project, such as setting up the basic structure, web page flow, stylesheet, and JavaScript file. Amazon Q provided exceptional support by optimizing my code, offering excellent web development practices, and giving valuable advice on code organization. It also helped me adopt best practices for writing clean and efficient code
1.4 Deployment
As a DevOps Engineer, this part was right in my wheelhouse, requiring less assistance from Amazon Q. However, it helped clear up any doubts I had, allowing me to deploy the app more quickly. There was a suggestion on the DevPost Hackathon page to use AWS Amplify and AWS S3. Instead of using the AWS Console to provision these resources, I decided to write CDK scripts to provision them, allowing for quicker configuration, easier modifications, and reducing the potential for errors. I also wanted to use more AWS resources, such as DynamoDB (for storing game data, user data, and the leaderboard) and Step Functions (for automating updates between the deployed AWS Amplify app and AWS S3 Bucket). Unfortunately, I was running out of time, but this is on my to-do list for the next iteration of the game.
Amazon Q helped clear my doubts, especially since I had never used AWS Amplify before. It provided me with a foundational introduction to the service and addressed my concerns about whether it was safe to use AWS Amplify in terms of safeguarding my AWS accounts, S3 Buckets, and deploying a secure, scalable application.
Process Duration: ~ 1 Day
Technical Stack
Basic Architecture
Quick Architecture
Web Development:
For the development of this project, I chose to use HTML, CSS, and Vanilla JavaScript. I knew the game needed engaging functionality but also required a framework with a minimal learning curve. While frameworks like React or Angular could have provided a better user experience, they would have been time-consuming, especially since I was working solo on this hackathon. The learning curve would have likely led to incorrect prompts on my end, which could have caused me to get stuck in a troubleshooting loop, preventing me from achieving the results I had initially planned for.
AWS Ecosystem:
As mentioned earlier, there was a suggestion on the DevPost Hackathon page to use AWS Amplify and AWS S3, so I focused on implementing these services. I decided to write two small CDK stacks for AWS S3 and AWS Amplify, although they may not follow the best practices in terms of code. In my daily work, I emphasize the importance of Infrastructure as Code (IaC) and the benefits it brings to organizations. This approach proved to be beneficial in this project as well. Due to my limited experience with AWS Amplify, I had to make several modifications to my source code, folder structure, and unprovision a few AWS resources multiple times. This process would have been time-consuming if done manually through the AWS console, but with AWS CDK, I was able to quickly deploy and destroy AWS resources, which helped me efficiently configure AWS Amplify.
Check out Infrastructure code
Summary of AWS Resources Used:
Amazon Q Developer
Example of Amazon Q Developer Usage
Amazon Q Developer
AWS S3 (with AWS S3 bucket Policy)
AWS S3 Usage
AWS S3
AWS BedRock
AWS Bedrock Usage
AWS Bedrock
AWS Amplify
AWS Amplify Usage
AWS Amplify
AWS CDK
See Github Repo
→→Maintenance of this project→→→→
I plan to maintain this project as a learning opportunity to explore new techniques and tools necessary for its ongoing development. Currently, the project doesn't fully adhere to the best software engineering practices, but I intend to gradually implement these improvements with the help of Amazon Q (e.g., restructuring folders, enhancing code readability). Additionally, I aim to incorporate DevOps best practices, such as Infrastructure as Code (IaC), CI/CD pipelines, observability, and automation, to streamline deployment, eliminate manual processes, ensure long-term sustainability, and deliver the project to end users with minimal downtime.
Part of this project can also be enhanced, as I had the chance to research building a solution with AWS Step Functions that would update the necessary AWS Amplify app (Build and Deploy) if S3 detects a change in the bucket. This would also require Lambda functions to operate the Step Functions and access the S3 buckets.
I also plan to redesign the architecture to enable more efficient use of multiple AWS services, which will enhance the overall functionality of the game. My goal is to transform it into a Three-Tier Web Game that allows users to sign up, sign in, earn higher scores, save scores, and participate in a global leaderboard where they can compete for a spot in the top 10. Initially, I plan to use resources like RDS, DynamoDB, and AWS Lambda to implement these additional features. I also aim to incorporate AWS SNS for a notification system, enabling users to report bugs. Furthermore, I plan to use AWS security tools to protect the app, ensuring it’s accessible via a NAT gateway through a public subnet, while securing the database by placing it in a private subnet.
Additionally, I’m excited to explore Kubernetes and learn more about EKS to evaluate whether this app can be deployed on an EKS cluster and how well it can manage traffic, maintenance, and application load.

Final Notes:

I hope everyone who has stuck with this post until the end has enjoyed it as much as I enjoyed writing it. The game development journey has been challenging, but fun, and most importantly, I've learned a lot along the way. I also hope the game I've developed is enjoyable, playable, and encourages you to play multiple times. Feel free to leave a comment with any suggestions you have regarding the scalability, resilience, or security of the project, as well as any additional game features you'd like to see. Good luck to everyone participating in this hackathon!
 

Comments