In this post I share my experiences using AI coding assistant Amazon Q Developer to take the heavy lifting out of developing a simple online arcade scroller
Building my first arcade game using Amazon Q Developer
I can still remember the day that someone in the class brought in their ZX80 to show us what a computer was. We had all brought our own curiosities (mine was this large spider called Boris that you could make run away with a careful aim of the infra red laser blaster), but none caught my attention like this. This was the beginning of my relationship with tech and computers, and very soon I had my own machine and I began like many, trying to learn how programming it. I wanted to join the 80s bedroom gaming boom that little to me then, had gripped the nation. I never did quite make it in the gaming hall of fame, but I never forgot how it kick started my career in tech.
Over thirty years later, thanks to generative AI coding assistants like Amazon Q Developer, I wanted to return to my early days and see how easy it would be to build a game from scratch. This blog post shares my journey, and I hope that maybe this might inspire the inner gamer in some of you to follow along. Whilst this blog post doesn't share all the code generated, you will find all the code that Amazon Q Developer generated over at this repo here.
Overview of the approach
I am a big fan of retro games, and decided to build myself a simple arcade scrolling game where you need to navigate a space ship avoiding space debris. You would get points for successfully dodging these objects, and as time progressed, the game would get harder. Simple, but it should be a fun way to see how tools like Amazon Q Developer can help you achieve this.
If I want to create a game, I need some graphics. So my first port of call was to use generative AI image generators to create me some graphics and audio. Once I have these assets, I will build up the game iteratively, adding new features as we go along. Finally, I want to run this game online and host this in a way that anyone can play along.
Let's get started then.
Generating sprite sheets
As I wanted to get started quickly, I decided to use the Amazon Titan Image Generator G1 image playground to create my game graphics and sprites. These are the prompts I used, and you can see some of the outputs they generated.
Generate a sprite sheet that has retro looking space asteroids of different designs on a white background. Use pixel art style when generating.
Generate a sprite sheet that has retro looking space rocket of different designs on a white background. Use pixel art style when generating.
Generate a lunar landscape background image for a scrolling game. Use pixel art style when generating.
Generate a sprite sheet that has fuel cells, cute alien creatures, and jewels. Use pixel art style when generating.
The output of these are a bunch of files that contain my working sprites. Using an image editor, I trim these and make sure that I set the transparency of the background so that I can use these as sprites.
Generating audio files
I wanted to create some audio files for my game. I was not sure how I could use generative AI to generate sound effects, so I went into Amazon Bedrock's text playground, and selecting a number of different foundational models, I asked it this question:
Amazon Q Chat I want to create some mp3 sound effects for a video game. What is the easiest way of doing this?
The different models provided very different output. The best output for this particular use case and prompt was provided by Anthropic's Claude Sonnet 3.5 v1, giving me a number of different options including some online tools to try out (such as jsfxr which was perfect for what I needed). I was able to quickly get some nice sound effects, and I was specifically looking for one to play when registering a point.
I also wanted to have some human voices as part of the audio design. When crashing, I wanted the game to say "ouch!" rather than have an explosion. I decided that I would use Amazon Polly to achieve this. It has been a while since I used Amazon Polly, so I entered the following prompt into the Amazon Q Developer chat interface.
Amazon Q Chat How can I generate sound effects using Polly that covert the words "ouch" and "nice" into mp3 files. Can you make the voice sounds fast.
Following the instructions I soon had a set of audio files that I could use. I now had some graphics and some audio files, it was time to start writing the game code itself.
First attempt - building the game in Python
I am most familiar with Python, so this was my first port of call. I spent around twenty minutes using Amazon Q Developer to take the images and audio files I had created, and developer a working game. It used a well known Python library called PyGame, and I was very pleased with this.
However, I quickly found issues with my approach, specifically because I wanted to host this game online for anyone to play. PyGame runs great locally, but does not do well online. There are additional Python libraries that you can use as wrappers around PyGame (Pygbag for example).
Tip!! At this early stage of the design, tools like Amazon Q Developer are great for generating divergent ideas - things that you might not have thought about, tools or frameworks for example. You can then introduce convergent prompts to narrow down the information you have learned, and get a more specific and opinionated direction. This is the kind of prompt you might use:
I did consider perhaps exploring some new frameworks that might help me stick with Python, but in the end I decided to see if I could get some additional input from Amazon Q Developer to help guide my approach.
Amazon Q Chat I want to build an online arcade game that will be played in the browser. I want this to store high scores in a leaderboard that is hosted in the cloud. Can you suggest a good architecture and frameworks that might be a good starting point
Reading through the output, I get confirmation of the kind of architecture I might need. A front end to run the game, which would speak to a backend for services that I want to use within the game (for example, the leaderboard). It also suggested using Javascript and Node for the front end and backend. Yikes, I am no Javascript or Node expert, so this is going to be very much a learning exercise for me. I am not too worried though, these days, I am much happier to experiment with new tools, libraries, and even languages, because I feel supported by Amazon Q Developer.
Now that I have a better idea of what to do, I can move to generating some code.
Creating the core gameplay mechanics
Setting up my project workspace
I created a new directory, and then copied the game assets I had already created into the following structure.
├── audio
<audio files>
└── images
└── sprites
<game sprites in PNG format>
Once I had this setup, I started VSCode. I made sure that I had enabled Amazon Q Developer workspace indexing. In my experience of using Amazon Q Developer, @workspace provides additional context for prompts within Amazon Q Developer that can be super helpful.
I was now ready to begin.
Creating the initial game code
I decided to use Amazon Q Developer Agent for software development to generate the initial code. I wanted to see if this is something I could work with, and given that I have limited knowledge of coding in Javascript/NodeJS, I was hoping it would give me that head start I was looking for.
I typed in /dev and then entered this prompt:
Amazon Q Chat /dev can you build a simple sideways scrolling game in NodeJS using the images in the images/sprites directory as sprites. The background scrolling graphic to be used is titan-lunar-background.png. The player should control the rocket ship which is the file titan-sprite-rockets.png. Hazards should randomly appear and be a selection of the sprites in the other image files.
And after around 4-5 minutes, the process finished. During that time, I was provided with a running commentary of what Amazon Q was doing, how it was thinking, and then finally a set of files to review. It looked good, so I accepted it.
I was not actually sure how to run the game, so I asked Amazon Q to help me - like I said, I am not great at NodeJS! I soon had the game up and running, and I was surprised how good it looked and how well it played. In fact, if anything, it was a little too challenging. Time for some gameplay tweaks.
I tried the following prompts to change and adjust how the game played:
Can we update the code so that the longer the play is playing, the harder it gets. Start off easy and then slowly but gradually get harder - does not produce great guidance
Which worked great, but I got even better output when I used @workspace
@workspace Can we update the code so that the longer the play is playing, the harder it gets. Start off easy and then slowly but gradually get harder -is much better
Which provided me with updates to my code, including comments, such as
gameTime += 1/60; // Assuming 60 FPS
if (gameTime - lastDifficultyIncrease >= 5) { // Increase difficulty every 30 seconds
difficultyMultiplier += 0.1;
lastDifficultyIncrease = gameTime;
}
and
// Generate hazards
if (Math.random() < 0.02 * difficultyMultiplier) {
let hazardType = Math.floor(Math.random() * 3);
let hazard = {
x: canvas.width,
y: Math.random() * (canvas.height - 50),
width: 50,
height: 50,
speed: (Math.random() * 3 + 1) * difficultyMultiplier,
type: hazardType
};
hazards.push(hazard);
}
and it also ensure that the difficulty level is reset
function resetGame() {
player.x = 50;
player.y = 300;
player.vx = 0;
player.vy = 0;
hazards = [];
backgroundX = 0;
gameOver = false;
score = 0;
gameTime = 0;
difficultyMultiplier = 1;
lastDifficultyIncrease = 0;
keys = {};
hasPromptedForName = false;
}
I tested as I made these code changes. I soon noticed a few issues with the game. Collision detection was not great, and there was a feature where I could disappear at the bottom of the screen and effectively cheat my way to getting a high score. I wanted to fix these, so again, I asked Amazon Q Developer to address every issue that I found. This is the prompt I used to help me fix the second issue:
@workspace the current game logic in game.js allows the space ship to disappear at the bottom of the screen. update the code so that it if touches the bottom it counts as a collision
As you can see from the code, it understood the assignment.
// Check for bottom collision
if (player.y + player.height > canvas.height) {
player.y = canvas.height - player.height;
if (!player.invulnerable) {
gameOver = true;
collisionSound.play();
}
}
The next thing I wanted to do is to add a leaderboard so that players could see how well they did (and eventually compete for bragging rights when I host it online)
Creating a leaderboard
I ask Amazon Q Developer via the chat interface the following:
@workspace Can i update the code so that it keeps track of high scores. It should list the top 15 scores and list them on the screen before and after a game
After incorporating the code, it looks like it works.
Mmm, just as well I tested it properly, it looks like this code has introduced some bugs. Every time a new high score is recorded there are two issues: 1/ You lose control of the rocket ship on the subsequent game, and 2/ It keeps asking you for your name until all the high score slots are filled. Not great, but I can use Q to help me trouble shoot these problems.
The first issue which is an easy fix
And I repeat the same for the second, using the following prompt after highlighting the code blog and sending it to the prompt
this code does not work properly. the second time you play the game, you are prompted many times to enter your name. can you fix
As is the way, sometimes you have to follow up with additional prompts as the updated code might not always do what you want. I use the follow up prompt:
This code never triggers the player to enter their name for their high score
and after a few iterations it is now working. I now have a working leaderboard, hurrah!
Making some improvements
The first improvement I want to make is ensuring that only alpha numeric characters can be used for the high score. I enter the following prompt:
@workspace can you update the code so that you can only enter alpha numeric characters if you get on the leaderboard
And it walks me through creating a new help function (a regex function) and then updating the game over routine. When I test this, I try and enter some incorrectly formatted names and it all works great.
Persisting the leaderboard
Whilst I now have a functioning leaderboard, every time I restart the application, those scores are reset. What I really need is a way of persisting that data, and so I ask
I want to build an online arcade game that will be played in the browser. I want to store high scores in a leaderboard that is hosted in the cloud. Can you suggest a good architecture and frameworks that might be a good starting point.
It provides me with some options and shows me how to incorporate the code. The steps it walks me through are:
- creating a new backend service called app.js that will be used to manage the leaderboard
- updating the game code to use this service
- provide sample code to persist the leaderboard data (to Redis)
This aligns with the architecture that I set out at the beginning to use. I setup a new directory structure for this, so my layout now looked like:
index.html
game.js
server.js
├── leaderboard (my backend app.js code that gets and sets scores against a Valkey cache)
└── valkey (configuration file to run Valkey locally)
├── audio (audio files)
└── images
└── sprites (game sprites in PNG format)
The code provided by the previous prompt suggesting using Redis. This is no longer open source, so I ask how I would use Valkey instead (if you did not know, Valkey is an open source fork of Redis). I follow up the previous prompt with this to help refine my ask.
@workspace I want to use Valkey to store the leaderboard for this game (game.py) that runs in the browser. I do not want to run the code to store and read the leaderboard in the browser as I want to keep the credentials safe. How can i use Valkey ?
This updated the code example from the previous steps, and I was guided in creating a backend that spoke to Valkey, whilst modifying the game code to access that backend code to store and retrieve scores.
Running Valkey locally I am running a local Valkey instance locally using a docker file that Amazon Q generated for me and that I blogged about previously here. Once I have the code running locally it should be simple enough to move it to the Cloud.
When I re-start the game (starting the backend app.js first, confirming it connects to Valkey without any errors) I check to make sure that the game still functions, and that now high scores persist. I restart the game several times, and each time I still have the high scores. Looking good so far.
I wanted to make sure that only the game could interact with this. I already knew that I would be hosting the game on game.sueiras.dev, and so I thought I would add CORS to restrict access to that backend API. I noticed that whilst the backend had loaded the CORS module, it was not being used, so I followed up with the following prompt:
@workspace how do i configure CORS in app.js so that it only accepts requests from the domain game.sueiras.dev
It provides
// CORS configuration
const corsOptions = {
origin: 'https://game.sueiras.dev',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
After restarting the backend and then trying to access this locally (via http://127.0.0.1) I could see that the requests were being rejected. For the time being whilst working locally, I updated the code so that it looked like;
// CORS configuration
const corsOptions = {
origin: '*',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
This allowed me to test locally that everything was working.
Adding profanity checks for my application
I want to make sure that people are not allowed any rude names when they enter a name into the leaderboard. I am not sure quite how to do this, so I ask Amazon Q Developer in the chat interface the following:
If I want to also check for obscene or rude words entered for the leaderboard, what are my options?
Amazon Q provides me with some good options. I can code something myself, or perhaps use a number of already existing libraries. By now you can probably see the flow of how you can use AI coding assistants to help first guide, and then provide some code to try out.
After reviewing the options I decide to add a third party library, and after using Amazon Q to help me review these, settle on one called profanity. I ask it to help me update the code:
@workspace can you update app.js to add a new route that takes in an input of a name and then either passess or fails it agains profanity. Please use the @2toad/profanity library
I use Amazon Q to guide me on how to update the code in the backend (app.js) and then make the supporting changes in the game code (game.js) that will call this API to check for profanities. I select the new profanity function created in app.js, and then using the integrated Amazon Q menu option, I send it to the prompt and ask it
how would I use this function to catch inappropriate names in the following function
I then paste the function from game.js that I need to update. You can see from the screenshot that it provides me with the right code to update the function in game.js to use this new API
After restarting the backend and front end, I play the game to register a new high score, and confirm that I can now no longer enter inappropriate names.
Removing hard coded references in the game.js
As I want to eventually host the front end and backend on potentially different hosts, I need to make sure that I do not hard code any URI's. I enter the following into Amazon Q Developer:
can you update the game.js to remove the hard coded reference to the remote api and change it for an environment variable for the uri. I need this to work for a browser based javascript file
After reviewing the output, I make a few changes and now have a new file (config.js) that defines the backend URL for the various services (leaderboard) this game will use.
const CONFIG = {
API_URL: 'http://127.0.0.1:3001'
};
and my modified game.js loads this up
const API_URL = CONFIG.API_URL;
With the game now up and running and functioning locally, the next step was to get Amazon Q Developer to help guide me as to how to host this on AWS.
Hosting this game - backend
At the beginning of this post, I had already asked Amazon Q to help me try and figure out what likely architectures and potential AWS services I might need to use when creating an online game. So I had a rough idea of where I wanted to take this.
I use the following prompt to give me a rough overview of my options. How did I come up with this prompt? I wanted to make sure that I reflect the previous thinking in the prompt design. This is to ensure that I get the best output for my given context.
@workspace is the best way of hosting this application on aws. I want to host the front end game on AWS Amplify, but want to know the best option for deploying the backend. The backend needs to connect to a Valkey cache, so I need options that work well with VPC connectivity.
and what would be the best option for hosting the front end?
The output I get is kind of what I expected. AWS Amplify for the front end, Amazon ECS for the backend, with Valkey for the leaderboard.
Before proceeding I have a defined VPC in my AWS account that I am going to use to host all the components. The VPC has two public subnets where I will deploy resources to host this game.
Setting up Valkey
As the backend will depend upon Valkey, this is the first thing I am going to setup. I am going to deploy Valkey and the backend application (hosted on Amazon ECS) into the same VPC.
I ask q how to create a new Valkey instance on AWS via the cli using the following prompt:
Can you tell me how to provision a Valkey cache cluster using the aws cli. Provide me with the simplest setup as this is only a demo, using serverless if available
And it quickly provides me with a handy set of commands to get me going.
I am going to deploy this in my local region in an existing VPC, so the only thing I need to find out is two public subnet's IDs. When I try and run this command:
aws elasticache create-serverless-cache \
--serverless-cache-name demo-leaderboard \
--engine valkey \
--region eu-west-1 \
--subnet-ids "subnet-1, subnet-2"
This generates an error. I turn to my trusty companion Amazon Q, to help me with the error. It tells me that the likely issue is that the create-serverless-cache command is not available in your version of the AWS CLI or in the region you're using. This is probably right, it has been a while since I have updated the AWS cli, and Amazon ElastiCache for Valkey was only launched recently.
I check what version I am currently using (aws-cli/2.13.38 Python/3.11.6 Darwin/23.6.0 exe/x86_64 prompt/off) before I ask Amazon Q how to update the AWS cli, and it provides me with exactly what I need. After updating my AWS cli (it's now version aws-cli/2.18.14 Python/3.12.7 Darwin/23.6.0 source/arm64) and trying again this time works.
{
"ServerlessCache": {
"ServerlessCacheName": "demo-leaderboard",
"Description": " ",
"CreateTime": "2024-10-25T20:57:19.622000+00:00",
"Status": "creating",
"Engine": "valkey",
"MajorEngineVersion": "7",
"SecurityGroupIds": [
"sg-0cdd21561dee418a7"
],
"ARN": "arn:aws:elasticache:eu-west-1:xxxxxxx:serverlesscache:my-valkey-serverless",
"SubnetIds": [
"subnet-1",
"subnet-2"
],
"SnapshotRetentionLimit": 0,
"DailySnapshotTime": "23:30"
}
}
I need to give it some time to get up and running, so great time to pause for a cup of tea.
Updating the backend to work with Amazon ElastiCache for Valkey and Amazon ECS
Before I deploy the application to the cloud, I want to make sure that the backend code does not need to be updated. I use the following prompt:
@workspace if I wanted to use app.js to connect to an ElastiCache Redis instance on AWS, how would I need to update the code
It returns some changes that I do not have in my current code, specifically this:
const client = new Valkey({
port: 6379,
host: 127.0.0.1,
username: 'default',
tls: true
});
I am glad I asked this question before proceeding, as there is nothing worse than having to go back. As you plan your projects, I find it useful to use Amazon Q to help me anticipate what I might need to do. It is all too easy to fall into the "it works on my laptop" situation.
In fact, as I was thinking about this I realised that I had forgotten another detail. As I look ahead to hosting this on Amazon ECS, I need to make sure that I have a route that the load balancer can use to provide health check of everything work. So I ask Amazon Q to help me out.
@workspace in the app.js can you add a health check route that always returns OK
Which returns exactly what I need.
// Add this new route for the health check
app.get('/health', (req, res) => {
res.status(200).send('OK');
});
Thinking harder, I realise there are few other things that I might need to change as I host this on Amazon ECS. First, the host details for the Valkey cache are currently hardcoded. I ask Amazon Q to help me fix this using the following prompt:
@workspace update app.js so that instead of using a hardcoded IP address to connect to a Valkey cache it uses an env variable
which provides me with updated code which looks good, as well as examples of how to run the backend. It also provide me with some additional ideas around using .env configuration to make this easier to manage.
// Get Valkey server address from environment variable
const VALKEY_SERVER = process.env.VALKEY_SERVER || 'localhost:6379';
const [host, port] = VALKEY_SERVER.split(':');
const client = new Valkey(parseInt(port), host);
Second, I also have the CORS configuration hardcoded, so after asking Amazon Q with the following prompt:
@workspace can you update app.js so that it grabs the CORS origin from an environment variable
It suggests the following update to my code. I would probably change the default of * to something more restrictive, but as this is just a simple example, this looks good to go.
// Get CORS origin from environment variable, default to '*' if not set
const CORS_ORIGIN = process.env.CORS_ORIGIN || '*';
const corsOptions = {
origin: CORS_ORIGIN,
methods: ['GET', 'POST'],
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
Next, I follow up and ask Amazon Q Developer to help me configure the "username" and "tls" as more environment variables.
can you update the code so that both the username and tls are set via environment variables
and it provides me with an updated app.js, the interesting part being:
// Get username and TLS setting from environment variables
const VALKEY_USERNAME = process.env.VALKEY_USERNAME || 'default';
const VALKEY_TLS = process.env.VALKEY_TLS === 'true';
const client = new Valkey({
port: parseInt(port),
host: host,
username: VALKEY_USERNAME,
tls: VALKEY_TLS
});
I update the code and I feel as confident as one can be that I have thought of everything. If you know that your code is going to be running somewhere else, try some prompts to see what you might be missing.
Deploying the backend via Amazon ECS - building the container image
I am now ready to start building my container image for the backend app.js. I start with the following prompt.
@workspace I want to deploy the leaderboard directory (app.js and supporting files) to Amazon ECS. Can you guide me through the steps. I am using Node version v20.10.0
Which is great, although I realise that I am actually using Finch not Docker, so I follow up by asking "Can you update the instructions to use Finch instead of Docker" which fixes that issue. It comes up a decent enough set of instructions.
I am provided with the steps needed, and I only need to make a minor change in the Dockerfile (changing the port number). After building my container image, I can now run the backend up with the following:
finch run -e VALKEY_SERVER=192.168.5.2:6379 -e CORS_ORIGIN="*" -e VALKEY_TLS=false -p 3001:3001 leaderboard-app
(the IP address 192.168.5.2 is how processes running inside Finch access your hosts local network, in my case, the Valkey cache I have running).
When I try and access this via a browser, I get the following output:
{"name":"ric","score":165},{"name":"hello","score":51},{"name":"qwer","score":23},{"name":"help","score":23},{"name":"pot","score":18},{"name":"qqqqqq","score":17},{"name":"zaqwsx","score":13},{"name":"qqq","score":13},{"name":"fff","score":10},{"name":"eee","score":10},{"name":"qwe","score":8},{"name":"Anonymous","score":5},{"name":"xxx","score":2}]
Which is what I expect, given that these are the current high scores in my local Valkey container.
Deploying the backend via Amazon ECS - pushing to a container registry
I use the following prompt within the Amazon Q Developer chat interface to guide me through the steps of first taking the local container image I have just built, and then hosting it on Amazon ECR.
I want to push this container image to Amazon ECR. Can you guide me through the steps.
(I do have to change the commands slightly as I am using Finch instead of Docker) - this is what I used
aws ecr get-login-password --region eu-west-1 | finch login --username AWS --password-stdin 704533066374.dkr.ecr.eu-west-1.amazonaws.com
finch tag leaderboard-app:latest 704533066374.dkr.ecr.eu-west-1.amazonaws.com/leaderboard-app:1.0.0
finch push 704533066374.dkr.ecr.eu-west-1.amazonaws.com/leaderboard-app:1.0.0
I now have my container image in Amazon ECR (704533066374.dkr.ecr.eu-west-1.amazonaws.com/leaderboard-app:1.0.0) which we will need for the next step, setting up our Amazon ECS cluster.
Deploying the backend via Amazon ECS - configuring and deploying to Amazon ECS
It has been a while since I setup and deployed a container application on Amazon ECS, so I try with the following prompt:
@workspace I want to deploy the leaderboard directory (app.js and supporting files) to Amazon ECS. Can you guide me through the steps.
It walks me through step by step (I will not repeat those here) and helps me to create my task-definition.json file (you can see the example in the repo here). I use a number of prompts including asking for aws cli commands - it is not perfect, as some of the commands generate errors. These are minor issues though, which I get past quickly using Amazon Q to help me troubleshoot.
Before very long I have my backend app running as a task on Amazon ECS.
I now had my backend hosted, let's check to see if it works
Running into issues - Amazon Q to the rescue
From the ECS Task, I open up the Networking tab and find the IP address. I open a browser and access http://{IP}:3001/health - I am rewarded with an OK. Looking good. I try again, this time from the /api/scores and this time it just hangs.
From the ECS Task, I can check the Logs. Opening these I see the following error that keeps repeating:
2024-10-25T22:27:57.800Z [ioredis] Unhandled error event: Error: connect ETIMEDOUT
2024-10-25T22:27:57.800Z at Socket.<anonymous> (/usr/src/app/node_modules/iovalkey/built/Redis.js:170:41)
2024-10-25T22:27:57.800Z at Object.onceWrapper (node:events:628:28)
2024-10-25T22:27:57.800Z at Socket.emit (node:events:514:28)
2024-10-25T22:27:57.800Z at Socket._onTimeout (node:net:589:8)
2024-10-25T22:27:57.800Z at listOnTimeout (node:internal/timers:573:17)
2024-10-25T22:27:57.800Z at process.processTimers (node:internal/timers:514:7)
I try the following prompt
when I try and access Elasticache Valkey from my ECS app.js I get timeouts - what might be the problem
and I am provided with a set of things to check. I realise that when I setup the Amazon ElastiCache for Valkey, I did not update the security group to allow for ingress access from the ECS tasks. I quickly update that, and then try access the API again, and this time success - we are in business!
For one final test, I update the game.js file to point to the Amazon ECS hosted backend by changing these files:
async function addHighScore(name, score) {
try {
//const response = await fetch('http://127.0.0.1:3001/api/scores', {
const response = await fetch('http://54.170.151.17:3001/api/scores', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, score }),
});
if (!response.ok) {
throw new Error('Failed to add score');
}
console.log('Score added successfully');
} catch (error) {
console.error('Error adding high score:', error);
}
}
async function getTopScores() {
try {
//const response = await fetch('http://127.0.0.1:3001/api/scores');
const response = await fetch('http://54.170.151.17:3001/api/scores');
if (!response.ok) {
throw new Error('Failed to get scores');
}
const scores = await response.json();
//console.log('Top scores:', scores);
return scores;
} catch (error) {
console.error('Error getting top scores:', error);
return [];
}
}
I restart the game and test it out. The high scores have all disappeared, which is what I expected as these are now running on Amazon ElastiCache for Valkey.
We now have our backend sorted out, the next step is to deploy the front end via AWS Amplify.
Hosting this game - frontend
So far we have deployed the backend app.js on Amazon ECS, and configured supporting resources (the Amazon ElastiCache for Valkey cache). I have tested this and it all looks good. In preparation for the next step I have already setup and configured a custom domain in Amazon Route 53 (ricsue.dev) and I have used Amazon Certificate Manager to vend me a certificate (demo-game.ricsue.dev) which will be where I host the online game.
Setting up Amazon Route 53 is something I have done many times so I did not need any help from Amazon Q this time. If you are new to setting up a hosted domain, and want to use this to make vending certificates easy, then Amazon Q can help walk you through the steps.
With everything ready, the final piece is deploying the front end AWS Amplify. I have not used AWS Amplify for some time, so I kick off the following prompt in the Amazon Q chat interface:
I want to deploy the front end of this application via AWS Amplify - can you provide a step by step guide on how to do this
And it provides a nice step by step guide. As my local directory structure is not quite right, I spend some time sorting this out. I end up with the following layout:
$tree -d -L 2
├── ecs-deployment
├── game
│ ├── audio
│ ├── images
│ └── node_modules
├── leaderboard
│ └── node_modules
└── valkey
└── conf
@workspace I want to deploy the game directory to AWS Amplify. The game file is game.js and there are supporting resources (audio, images, and config.js)
I follow these instructions, and in a few minutes I now have the game up and running on AWS. It really was super easy, all I had to do was:
- create a new GitHub repo for the front end code (so everything under game)
- follow the guide that Amazon Q provided
- update the AWS Amplify configuration file which it tries to automatically create, but was not right. I ended up using a very simple one
version: 1
frontend:
phases:
build:
commands:
- echo "No build required"
artifacts:
baseDirectory: /
files:
- '**/*'
After following the prompts, the game deployed and I could access it via the provided Amplify URL.
I am not quite done yet though. From the AWS Amplify menu, I complete the step by step guide to enable a custom domain, using the demo-game.ricsue.dev domain I had configured beforehand. It takes a few minutes whilst AWS Amplify takes care of everything (it was certainly much simpler than when I did it manually for the backend). I retry in the browser with the game URL, and voila!
Taking advantage of AWS Amplify's auto deployment mechanism
I let a few colleagues play this game, and they provided some feedback that it was good practice to minify and obfuscate the Javascript. As I have no clue how to do this, I ask Amazon Q:
@workspace how do i minify and obfuscate the game.js and config.js in the demo-game-amplify directory
It walks me through the process of installing some additional Node libraries and then creating a build file. After running this, I have two new files. After updating the index.html to use these rather than the plan Javascript versions, I make an update to the repo and AWS Amplify automatically updates and rolls out the new code. It is just too easy, I am quickly loving AWS Amplify.
Not bad for a few hours effort. I have actually hosted a version of the game you can try for yourself, check out the links below.
Wrapping up and next Steps
That's all folks, in this blog post I walked you through how you can develop a simple, fun game with the aid of Amazon Q, and then deploy this to the cloud. As a Python coder, I was able to leave the comfort of pip and put together a fun game in a completely different language, in less than a day. There are probably better ways I could have approached this if I had more Javascript/Node knowledge, but this was a great way to kick start my learning.
Did you know... One of the things I learned in putting this game together is how hard the leaderboard problem is to solve. A untrusted client (the game running in Javascript, which can be easily manipulated and changed using client side tools) needs to push scores to the backend APIs. Those API's do not know whether that game client has been tampered with, or whether the game has been played at all! It is a rabbit hole that I spent more time looking into than actually coding the game, and a good subject for a future post perhaps!
You can give the game a go at this following link - https://demo-game.ricsue.dev. See if you can beat the highest score.
You can try Amazon Q Developer for free today, by signing up for a Builder ID, and then using that to login in after installing the plugin in VSCode or Intelij. I hope some of you will try this and maybe create your own games. If you do, please let me know how you get on - I would love to share your stories. I am an Amazon Q Challenge Coin going for my favorite game that you put together.
Check out my other posts on community.aws, as I have been sharing a lot of tips and use cases of how I am using Amazon Q Developer. You can also keep up to date with all the new features and improvements of Amazon Q Developer by checking out the changelog.
Top comments (0)