🚀 Building “Space Ball” – My First AI-Generated Game with Amazon Q CLI
🎥 Here's a short clip showing the game in action:
🎮 The Idea
As someone curious about game development but not a full-time game dev, I wanted to build something fun and interactive—quickly. When I saw the Amazon Q Game Jam Challenge, I thought: Why not try building a simple space-themed ball game using Amazon Q CLI?
The concept was straightforward:
“A bouncing space ball that avoids obstacles or collects stars, with arrow keys for control and a scoring mechanism.”
🧠 Tools Used
- Amazon Q CLI
- Amazon Q Chat (in VS Code)
- p5.js for graphics and game logic
- VS Code for development
- GitHub for version control and sharing
- Screen recording tools & screenshots to capture the process
⚙️ Step-by-Step: How I Built It
1. 🔧 Project Initialization
I started by creating a new project using the Q CLI:
q init space-ball-game
I chose:
- Language: JavaScript
- Framework: p5.js (great for quick 2D games)
This scaffolded a complete p5.js game project with basic structure in place.
2. 🧠 AI-Powered Development with Amazon Q Chat
I opened Amazon Q Chat in VS Code and gave it this prompt:
“Create a simple 2D space ball game using p5.js where a ball bounces and avoids obstacles in space. Add scoring when player survives longer. Use arrow keys for control.”
In seconds, it generated working code for a ball that:
- Bounces around the canvas
- Responds to arrow key movement
- Increments score over time
Then I asked follow-ups like:
- “Add space background with stars”
- “Show score on the top-left”
- “Add a game over screen if the ball touches the edge”
- “Make it gradually harder”
Each prompt improved the game significantly. It felt like collaborating with a game dev buddy who worked at lightning speed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Ball Game</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
<style>
body {
margin: 0;
padding: 20px;
background: #000;
color: white;
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
}
#gameContainer {
border: 2px solid #333;
}
.instructions {
margin-top: 10px;
text-align: center;
}
</style>
</head>
<body>
<div id="gameContainer"></div>
<div class="instructions">
<p>Use arrow keys to control the ball • Avoid red obstacles • Survive as long as possible!</p>
<p>Press SPACE to restart when game over</p>
</div>
<script>
let ball;
let obstacles = [];
let stars = [];
let score = 0;
let gameOver = false;
let gameStartTime;
function setup() {
let canvas = createCanvas(800, 600);
canvas.parent('gameContainer');
// Initialize ball
ball = {
x: width / 2,
y: height / 2,
vx: 0,
vy: 0,
radius: 15,
maxSpeed: 8,
acceleration: 0.3
};
// Create background stars
for (let i = 0; i < 100; i++) {
stars.push({
x: random(width),
y: random(height),
size: random(1, 3),
brightness: random(100, 255)
});
}
gameStartTime = millis();
}
function draw() {
// Space background
background(5, 5, 20);
// Draw stars
drawStars();
if (!gameOver) {
// Update game state
updateBall();
updateObstacles();
checkCollisions();
// Update score based on survival time
score = Math.floor((millis() - gameStartTime) / 100);
// Spawn obstacles periodically
if (frameCount % 60 === 0) {
spawnObstacle();
}
}
// Draw game objects
drawBall();
drawObstacles();
drawUI();
if (gameOver) {
drawGameOver();
}
}
function drawStars() {
noStroke();
for (let star of stars) {
fill(255, star.brightness);
ellipse(star.x, star.y, star.size);
// Twinkling effect
star.brightness += random(-10, 10);
star.brightness = constrain(star.brightness, 50, 255);
}
}
function updateBall() {
// Handle input
if (keyIsDown(LEFT_ARROW)) {
ball.vx -= ball.acceleration;
}
if (keyIsDown(RIGHT_ARROW)) {
ball.vx += ball.acceleration;
}
if (keyIsDown(UP_ARROW)) {
ball.vy -= ball.acceleration;
}
if (keyIsDown(DOWN_ARROW)) {
ball.vy += ball.acceleration;
}
// Limit speed
ball.vx = constrain(ball.vx, -ball.maxSpeed, ball.maxSpeed);
ball.vy = constrain(ball.vy, -ball.maxSpeed, ball.maxSpeed);
// Apply friction
ball.vx *= 0.98;
ball.vy *= 0.98;
// Update position
ball.x += ball.vx;
ball.y += ball.vy;
// Bounce off walls
if (ball.x - ball.radius <= 0 || ball.x + ball.radius >= width) {
ball.vx *= -0.8;
ball.x = constrain(ball.x, ball.radius, width - ball.radius);
}
if (ball.y - ball.radius <= 0 || ball.y + ball.radius >= height) {
ball.vy *= -0.8;
ball.y = constrain(ball.y, ball.radius, height - ball.radius);
}
}
function drawBall() {
push();
translate(ball.x, ball.y);
// Ball glow effect
for (let i = 3; i > 0; i--) {
fill(100, 150, 255, 50 / i);
noStroke();
ellipse(0, 0, ball.radius * 2 * i);
}
// Main ball
fill(150, 200, 255);
stroke(200, 230, 255);
strokeWeight(2);
ellipse(0, 0, ball.radius * 2);
// Ball highlight
fill(255, 255, 255, 150);
noStroke();
ellipse(-ball.radius * 0.3, -ball.radius * 0.3, ball.radius * 0.6);
pop();
}
function spawnObstacle() {
let obstacle = {
x: random(width),
y: -50,
vx: random(-2, 2),
vy: random(2, 5),
radius: random(20, 40),
rotation: 0,
rotationSpeed: random(-0.1, 0.1)
};
obstacles.push(obstacle);
}
function updateObstacles() {
for (let i = obstacles.length - 1; i >= 0; i--) {
let obs = obstacles[i];
obs.x += obs.vx;
obs.y += obs.vy;
obs.rotation += obs.rotationSpeed;
// Remove obstacles that are off screen
if (obs.y > height + 100) {
obstacles.splice(i, 1);
}
// Bounce off side walls
if (obs.x - obs.radius <= 0 || obs.x + obs.radius >= width) {
obs.vx *= -1;
obs.x = constrain(obs.x, obs.radius, width - obs.radius);
}
}
}
function drawObstacles() {
for (let obs of obstacles) {
push();
translate(obs.x, obs.y);
rotate(obs.rotation);
// Obstacle glow
for (let i = 3; i > 0; i--) {
fill(255, 50, 50, 30 / i);
noStroke();
ellipse(0, 0, obs.radius * 2 * i);
}
// Main obstacle
fill(255, 80, 80);
stroke(255, 120, 120);
strokeWeight(2);
// Draw as angular asteroid-like shape
beginShape();
for (let angle = 0; angle < TWO_PI; angle += PI / 6) {
let r = obs.radius + sin(angle * 3) * 5;
let x = cos(angle) * r;
let y = sin(angle) * r;
vertex(x, y);
}
endShape(CLOSE);
pop();
}
}
function checkCollisions() {
for (let obs of obstacles) {
let distance = dist(ball.x, ball.y, obs.x, obs.y);
if (distance < ball.radius + obs.radius) {
gameOver = true;
break;
}
}
}
function drawUI() {
// Score
fill(255);
textAlign(LEFT);
textSize(24);
text(`Score: ${score}`, 20, 40);
// Speed indicator
let speed = sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
fill(100, 255, 100);
textSize(16);
text(`Speed: ${speed.toFixed(1)}`, 20, 70);
// Obstacle count
fill(255, 100, 100);
text(`Obstacles: ${obstacles.length}`, 20, 95);
}
function drawGameOver() {
// Semi-transparent overlay
fill(0, 0, 0, 150);
rect(0, 0, width, height);
// Game over text
fill(255, 100, 100);
textAlign(CENTER);
textSize(48);
text("GAME OVER", width / 2, height / 2 - 50);
fill(255);
textSize(24);
text(`Final Score: ${score}`, width / 2, height / 2);
textSize(18);
text("Press SPACE to restart", width / 2, height / 2 + 40);
}
function keyPressed() {
if (key === ' ' && gameOver) {
// Restart game
gameOver = false;
obstacles = [];
score = 0;
gameStartTime = millis();
// Reset ball
ball.x = width / 2;
ball.y = height / 2;
ball.vx = 0;
ball.vy = 0;
}
}
</script>
</body>
</html>
3. 🧪 Testing and Running
I used:
q run
...and the game loaded perfectly in the browser. I recorded a short video and took screenshots to document the gameplay.
🎥 Experience Video & Screenshots
Here's a short clip showing the game in action:
Youtube Video
And some screenshots:
🧵 What I Learned
- Q CLI + Q Chat is a powerful combo. I didn’t write a single line of game logic manually.
- p5.js is fantastic for small 2D games and works well with Q.
- The iterative prompt-based flow lets you build, test, improve quickly.
- Building a game is no longer “hard” when you have the right tools and guidance.
💡 Tips If You Want to Try
- Start with a simple idea.
- Use clear and direct prompts in Q Chat.
- Ask for improvements iteratively.
- Take screenshots and short videos as you go (makes writing blogs easy 😉).
- Don’t be afraid to experiment. You can always undo or regenerate!
🙌 Final Words
This was my first time building a game with the help of AI. And it was surprisingly smooth and rewarding.
Whether you're a student, hobbyist, or even a non-coder—Amazon Q can help you bring your game idea to life in hours.
Give it a try, build your game, and maybe win that T-shirt too!
Thanks for reading! Feel free to connect or ask if you want help getting started with your own game.
Top comments (0)