DEV Community

Shivam Gupta
Shivam Gupta

Posted on

🚀 Building “Space Ball” – My First AI-Generated Game with Amazon Q CLI

Space Ball

🚀 Building “Space Ball” – My First AI-Generated Game with Amazon Q CLI


🎥 Here's a short clip showing the game in action:

Youtube Video

🎮 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
Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

3. 🧪 Testing and Running

I used:

q run
Enter fullscreen mode Exit fullscreen mode

...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:

📸
Screenshot 1
📸
Screenshot 2


🧵 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)