I recently jumped on the "Build Games with Amazon Q CLI and score a T shirt 🏆👕" challenge. As a developer who loves a good retro arcade game and is curious about AI-driven development, this was the perfect excuse to dive in. The mission was simple: build a game using Amazon Q's command-line interface, document the journey, and share the results.
The result? A fully-functional, nostalgic side-scrolling shooter called Space Conquer, and a ton of insights into pairing AI with a classic coding project. Here’s how it went down.
My Game: "Space Conquer" - A Modern-Classic Shooter
For my project, I chose to build Space Conquer, a side-scrolling space shooter inspired by the classic Space Impact from old Nokia phones.
Why a Retro Shooter?
- Nostalgia Factor: Like many, I have fond memories of playing Space Impact. I wanted to capture that simple, addictive fun but with a modern coat of paint—better graphics, dynamic sound, and smoother controls.
- A Great Test for AI: A 2D shooter involves a fantastic mix of programming challenges that are perfect for an AI assistant: managing game states, handling real-time user input, collision detection, and creating varied enemy behaviors.
- Extensibility: I didn't just want to build a game; I wanted to build a framework. My vision was a modular design where new enemies, power-ups, or levels could be added easily. This is where an AI's ability to generate structured, boilerplate code would really shine.
Space Conquer features diverse enemies, collectible power-ups, dynamic audio that changes with the game state, and even a hidden developer panel for testing.
Unlocking AI's Potential: Effective Prompting Techniques
Working with Amazon Q CLI is a conversation. The better your questions, the better the answers. I quickly learned that vague prompts like "make a game" were less effective than breaking down the problem into specific, well-defined tasks.
Here are a few prompting techniques I discovered.
Technique 1: Requesting a Modular Architecture
Instead of asking for a single, monolithic script, I prompted for a clean, organized structure from the start.
My Prompt: "Create a project structure for a PyGame-based space shooter. I need separate modules for asset management, sprites (player, enemies, bullets), UI components, and the main game loop. The asset manager should load images and sounds from manifest files."
The Result: Amazon Q generated a directory structure (src/
, assets/
, tools/
) and starter Python files for each module (asset_loader.py
, sprites.py
, ui.py
, main.py
). The generated asset_loader.py
included a function to read a JSON manifest, which was a huge head start.
Technique 2: Defining Behavior with Roles and Rules
When creating enemies, I defined their characteristics and constraints clearly.
My Prompt: "Generate a Python class
Enemy
that inherits frompygame.sprite.Sprite
. It needs attributes for health, speed, and score value. Then, create a subclassEliteEnemy
that moves in a sine wave pattern down the screen and fires a bullet every 2 seconds."
The Result: Q provided a base Enemy
class and a well-defined EliteEnemy
subclass with its update()
method already implementing the sine wave movement using math.sin()
. This saved me from figuring out the trigonometry and timing loops myself.
How AI Handled Classic Programming Challenges
Game development is full of recurring problems. Here's how Amazon Q helped tackle some of the classics:
State Management: A game needs distinct states like 'main_menu', 'gameplay', 'settings', and 'game_over'. I prompted the AI to implement a simple state machine. It generated a
GameManager
class that held the current state and handled transitions, ensuring that the main menu logic didn't run during gameplay and vice-versa.Collision Detection: A core mechanic of any shooter. I asked Q for an efficient way to check for collisions between player bullets and enemies, and between the player and enemy ships or bullets. It suggested using PyGame's built-in
pygame.sprite.groupcollide()
function, providing a concise and performant solution that I could drop right into my main game loop.Power-Up Spawning: I wanted power-ups to drop randomly from destroyed asteroids. I prompted: "When an asteroid is destroyed, there should be a 15% chance of it dropping a power-up. The power-up type (health, speed, rapid-fire) should be chosen randomly." The AI generated a clean
if random.random() < 0.15:
check and arandom.choice()
call to select from a list of power-up types.
Time-Saving Automation: More Than Just Code
One of the biggest wins was using AI for automation around the code. The project summary mentions developer tools, and Q was instrumental here.
The Asset Manifest Generator
My game uses JSON files to manage all assets (images, sounds, maps). Manually keeping these in sync is tedious.
My Prompt: "Write a Python script for the
tools/
directory that scans theassets/images/enemies
andassets/sounds/sfx
directories and automatically generates amanifest.json
file with all the file paths."
This single prompt created a utility script that saved me countless minutes of error-prone manual editing every time I added a new enemy sprite or sound effect.
The Cross-Platform Launcher
I wanted a simple way for anyone to run the game, regardless of their OS.
My Prompt: "Create a Python script named
run_game.py
that checks the user's operating system. It should ensure all dependencies fromrequirements.txt
are installed using pip and then launch themain.py
script."
Q generated a script using the subprocess
and sys
modules that provided a one-click experience—a small but professional touch that I might have skipped otherwise.
AI-Generated Code That Impressed Me
It's one thing to generate boilerplate, but another to produce elegant solutions. Here are a couple of snippets that stood out.
1. Manifest-Driven Asset Loader
This function, generated early on, set the foundation for the game's modularity. It loads all assets listed in a JSON file into a dictionary, making them easily accessible throughout the game.
# Part of src/asset_loader.py
import pygame
import json
def load_assets_from_manifest(manifest_path):
"""Loads images and sounds based on a JSON manifest file."""
assets = {'images': {}, 'sounds': {}}
with open(manifest_path, 'r') as f:
manifest = json.load(f)
for category, files in manifest.items():
if category == 'images':
for key, path in files.items():
try:
assets['images'][key] = pygame.image.load(path).convert_alpha()
except pygame.error as e:
print(f"Error loading image {key} at {path}: {e}")
elif category == 'sounds':
for key, path in files.items():
try:
assets['sounds'][key] = pygame.mixer.Sound(path)
except pygame.error as e:
print(f"Error loading sound {key} at {path}: {e}")
return assets
# Example Usage in main.py
# ASSETS = load_assets_from_manifest('assets/manifest.json')
# player_img = ASSETS['images']['player_ship']
This design is clean, error-handled, and makes adding 50 new assets as easy as adding one.
- A Base Class for Animated UI Panels I wanted the UI to have a modern, "glowing" feel. I asked Q to create a reusable class for this.
# Part of src/ui.py
import pygame
class GlowingPanel(pygame.sprite.Sprite):
"""
A UI panel that has a subtle pulsing glow effect by alpha blending.
"""
def __init__(self, rect, color, glow_color):
super().__init__()
self.rect = rect
self.color = color
self.glow_color = glow_color
self.image = pygame.Surface(self.rect.size, pygame.SRCALPHA)
self.glow_alpha = 100
self.glow_direction = 2 # Rate of change for alpha
def update(self):
"""Update the pulsing glow effect."""
self.glow_alpha += self.glow_direction
if self.glow_alpha >= 180 or self.glow_alpha <= 80:
self.glow_direction *= -1
self.image.fill((0, 0, 0, 0)) # Clear with transparency
# Draw base panel
pygame.draw.rect(self.image, self.color, (0, 0, self.rect.width, self.rect.height), border_radius=8)
# Draw glow effect (a slightly larger rect with changing alpha)
glow_surface = pygame.Surface(self.rect.size, pygame.SRCALPHA)
glow_rect = pygame.Rect(0, 0, self.rect.width, self.rect.height)
glow_color_with_alpha = (*self.glow_color, self.glow_alpha)
pygame.draw.rect(glow_surface, glow_color_with_alpha, glow_rect, border_radius=10)
# Blit the glow onto the main surface
self.image.blit(glow_surface, (0,0), special_flags=pygame.BLEND_RGBA_ADD)
This self-contained class for a UI element with its own animation logic is a great example of the object-oriented code Q can produce. It's reusable for scoreboards, health bars, or any other panel in the game.
Final Thoughts
Using Amazon Q CLI for the "Build Games" challenge was a fantastic experience. It didn't just write code for me; it acted as a partner that handled the tedious, boilerplate, and sometimes complex parts of development, freeing me up to focus on the creative vision for "Space Conquer."
If you're a developer who hasn't tried integrating an AI assistant into your workflow, I highly recommend it. Pick a fun project, break it down into small pieces, and start prompting. You'll be surprised at how much you can build.
And hey, I might even get a t-shirt out of it.
Happy coding!
Top comments (0)