Game Examples Guide¶
This guide analyzes the complete game examples included with PixelRoot32, explaining their architecture, patterns, and lessons learned.
Available Examples¶
PixelRoot32 includes several complete game examples:
- Space Invaders: Full-featured shooter with enemies, projectiles, and audio
- Pong: Classic arcade game with physics and collisions
- Snake: Grid-based game with entity pooling
- TicTacToe: Turn-based game with simple AI
- CameraDemo: Platformer with scrolling camera and parallax
- SpritesDemo: Demonstration of advanced sprite formats
Space Invaders¶
Location: src/examples/SpaceInvaders/
Architecture¶
Space Invaders demonstrates a complete game with multiple systems:
- Scene Management:
SpaceInvadersScenemanages game state - Actor Hierarchy:
PlayerActor,AlienActor,ProjectileActor,BunkerActor - Collision System: Uses collision layers for player, enemies, projectiles
- Audio Integration: Sound effects for shooting, explosions, music
- Tilemap Background: Starfield using tilemap system
Key Systems¶
Collision Layers¶
namespace Layers {
constexpr uint16_t PLAYER = 0x0001;
constexpr uint16_t ALIEN = 0x0002;
constexpr uint16_t PROJECTILE = 0x0004;
constexpr uint16_t BUNKER = 0x0008;
}
// Player can collide with aliens and bunkers
player->setCollisionLayer(Layers::PLAYER);
player->setCollisionMask(Layers::ALIEN | Layers::BUNKER);
// Projectiles can hit aliens and bunkers
projectile->setCollisionLayer(Layers::PROJECTILE);
projectile->setCollisionMask(Layers::ALIEN | Layers::BUNKER);
Entity Management¶
- Uses object pooling for projectiles
- Manages alien formation with grid layout
- Handles game state (playing, game over)
Audio Integration¶
- Background music using
MusicPlayer - Sound effects for various events
- Audio events triggered on collisions
Patterns Used¶
- Object Pooling: Projectiles are pooled and reused
- State Machine: Game states (playing, game over, victory)
- Grid Layout: Alien formation uses grid-based positioning
- Event-Driven Audio: Sounds triggered by game events
Lessons Learned¶
- Collision layers are essential for complex games
- Object pooling improves performance
- Tilemaps are efficient for backgrounds
- Audio enhances game feel significantly
Pong¶
Location: src/examples/Pong/
Architecture¶
Pong demonstrates physics and collision handling:
- PhysicsActor: Ball uses
PhysicsActorfor automatic physics - Collision Callbacks: Paddles and ball handle collisions
- Score System: Simple score tracking and display
- Game State: Reset and game over handling
Key Systems¶
Physics Setup¶
class BallActor : public pixelroot32::core::PhysicsActor {
public:
BallActor(float x, float y, float speed, int radius)
: PhysicsActor(x, y, radius * 2, radius * 2) {
setRestitution(0.8f); // Bouncy
setFriction(0.1f); // Low friction
setWorldSize(240, 240);
}
};
Collision Response¶
void BallActor::onCollision(pixelroot32::core::Actor* other) {
// Adjust ball position
// Modify velocity based on impact point
// Play bounce sound
}
Patterns Used¶
- Physics Integration: Uses
PhysicsActorfor automatic movement - Collision Response: Custom collision handling
- Score Management: Simple state tracking
- Audio Feedback: Sound on collision
Lessons Learned¶
PhysicsActorsimplifies physics-based games- Collision callbacks allow custom response logic
- Simple games can be very effective
Snake¶
Location: src/examples/Snake/
Architecture¶
Snake demonstrates entity pooling and grid-based movement:
- Entity Pooling: Snake segments are pooled
- Grid Movement: Movement constrained to grid
- Game Logic: Food spawning, collision detection
- State Management: Game over, reset functionality
Key Systems¶
Entity Pooling¶
class SnakeScene {
private:
std::vector<SnakeSegmentActor*> segmentPool;
std::vector<SnakeSegmentActor*> snakeSegments;
void resetGame() {
// Reuse pooled segments
for (int i = 0; i < initialLength; ++i) {
SnakeSegmentActor* segment = segmentPool[i];
segment->resetAlive();
snakeSegments.push_back(segment);
addEntity(segment);
}
}
};
Grid-Based Movement¶
class SnakeSegmentActor : public pixelroot32::core::Actor {
private:
int cellX, cellY; // Grid position
public:
void setCellPosition(int x, int y) {
cellX = x;
cellY = y;
// Convert to world position
this->x = cellX * CELL_SIZE;
this->y = cellY * CELL_SIZE;
}
};
Patterns Used¶
- Object Pooling: Segments are pre-allocated and reused
- Grid System: Discrete grid-based movement
- Linked List: Snake segments form a linked structure
- Food Spawning: Random food placement with collision checking
Lessons Learned¶
- Entity pooling is essential for dynamic entities
- Grid-based movement simplifies collision detection
- Pre-allocation avoids memory fragmentation
TicTacToe¶
Location: src/examples/TicTacToe/
Architecture¶
TicTacToe demonstrates turn-based logic and simple AI:
- Turn Management: Player vs AI turns
- Game Board: 3x3 grid representation
- Win Detection: Check for winning conditions
- Simple AI: Random move selection
Key Systems¶
Board Representation¶
class TicTacToeScene {
private:
int board[3][3]; // 0=empty, 1=X, 2=O
bool playerTurn = true;
bool makeMove(int row, int col, int player) {
if (board[row][col] == 0) {
board[row][col] = player;
return true;
}
return false;
}
};
Win Detection¶
int checkWinner() {
// Check rows
for (int i = 0; i < 3; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2]) {
return board[i][0];
}
}
// Check columns, diagonals...
return 0; // No winner
}
Patterns Used¶
- State Machine: Turn-based state management
- Grid Logic: 2D array for board representation
- Simple AI: Random valid move selection
- UI Integration: Buttons for player input
Lessons Learned¶
- Turn-based games are straightforward to implement
- Simple AI can be effective for basic games
- Grid-based logic is easy to reason about
CameraDemo¶
Location: src/examples/CameraDemo/
Architecture¶
CameraDemo demonstrates scrolling and parallax:
- Camera2D: Camera following player
- Tilemap: Level built with tilemap
- Parallax: Multiple background layers
- Platformer Physics: Player with jumping and gravity
Key Systems¶
Camera Setup¶
class CameraDemoScene {
private:
pixelroot32::graphics::Camera2D camera;
float levelWidth;
public:
void init() override {
camera = pixelroot32::graphics::Camera2D(240, 240);
camera.setBounds(0, levelWidth - 240);
}
void update(unsigned long deltaTime) override {
camera.followTarget(player->x, player->y);
}
void draw(pixelroot32::graphics::Renderer& renderer) override {
camera.apply(renderer);
renderer.drawTileMap(levelTileMap, 0, 0, Color::White);
Scene::draw(renderer);
}
};
Platformer Physics¶
class PlayerCube : public pixelroot32::core::PhysicsActor {
public:
void update(unsigned long deltaTime) override {
// Input handling
// Gravity application
// Jump logic
// Platform collision
PhysicsActor::update(deltaTime);
}
};
Patterns Used¶
- Camera Following: Dead-zone camera following
- Tilemap Rendering: Efficient level rendering
- Parallax Scrolling: Multiple background layers
- Platform Collision: Custom collision with platforms
Lessons Learned¶
- Camera system enables large levels
- Tilemaps are efficient for level data
- Parallax adds depth to 2D games
- Platform collision requires custom logic
SpritesDemo¶
Location: src/examples/SpritesDemo/
Architecture¶
SpritesDemo showcases advanced sprite formats:
- 2bpp Sprites: 4-color sprite format
- 4bpp Sprites: 16-color sprite format (if enabled)
- Animation: Sprite animation examples
- Format Comparison: Side-by-side format display
Key Systems¶
2bpp Sprite Usage¶
#ifdef PIXELROOT32_ENABLE_2BPP_SPRITES
static const pixelroot32::graphics::Sprite2bpp SPRITE_2BPP = {
SPRITE_DATA,
SPRITE_PALETTE,
16, 32, 4
};
renderer.drawSprite(SPRITE_2BPP, x, y, false);
#endif
Animation Display¶
class SpritesDemoActor : public pixelroot32::core::Entity {
private:
unsigned long timer = 0;
uint8_t currentFrame = 0;
public:
void update(unsigned long deltaTime) override {
timer += deltaTime;
if (timer >= 150) {
timer -= 150;
currentFrame = (currentFrame + 1) % 9;
}
}
};
Patterns Used¶
- Format Comparison: Shows different sprite formats
- Animation Loop: Frame-based animation
- Conditional Compilation: Uses build flags
Lessons Learned¶
- Advanced formats provide more color options
- Animation is straightforward with frame arrays
- Build flags enable/disable experimental features
Common Patterns Across Examples¶
Scene Initialization¶
All examples follow this pattern:
void init() override {
// 1. Set palette
pixelroot32::graphics::setPalette(PaletteType::NES);
// 2. Create background entity
addEntity(new BackgroundEntity());
// 3. Create game entities
player = new PlayerActor(...);
addEntity(player);
// 4. Initialize game state
resetGame();
}
Update Pattern¶
void update(unsigned long deltaTime) override {
// 1. Process input
handleInput();
// 2. Update game logic
updateGameLogic();
// 3. Call parent update (updates all entities)
Scene::update(deltaTime);
// 4. Post-update logic
checkGameState();
}
Draw Pattern¶
void draw(pixelroot32::graphics::Renderer& renderer) override {
// 1. Apply camera (if used)
camera.apply(renderer);
// 2. Draw background/tilemap
renderer.drawTileMap(background, 0, 0, Color::White);
// 3. Call parent draw (draws all entities)
Scene::draw(renderer);
// 4. Draw UI/HUD
drawHUD(renderer);
}
Learning Path¶
Beginner Examples¶
- Pong: Start here - simple physics and collisions
- TicTacToe: Learn turn-based logic
- Snake: Understand entity pooling
Intermediate Examples¶
- CameraDemo: Learn scrolling and parallax
- SpritesDemo: Explore sprite formats
Advanced Examples¶
- Space Invaders: Complete game with all systems
Code Study Recommendations¶
For Learning Physics¶
- Study
Pong/BallActor.cpp- PhysicsActor usage - Study
CameraDemo/PlayerCube.cpp- Platformer physics
For Learning Collisions¶
- Study
SpaceInvaders- Complex collision layers - Study
Pong- Simple collision response
For Learning Memory Management¶
- Study
Snake/SnakeScene.cpp- Entity pooling - Study
SpaceInvaders- Projectile pooling
For Learning Audio¶
- Study
SpaceInvaders- Music and sound effects - Study
Pong- Simple audio integration
For Learning UI¶
- Study
TicTacToe- Button-based UI - Study menu scenes - Layout usage
Extending Examples¶
Adding Features¶
- Pong: Add power-ups, multiple balls
- Snake: Add obstacles, multiple food types
- Space Invaders: Add boss battles, power-ups
Creating Variations¶
- Pong: Make it vertical, add walls
- Snake: Change to hexagonal grid
- TicTacToe: Make it 4x4 or 5x5
Best Practices from Examples¶
- Pre-allocate Resources: All examples pre-allocate entities
- Use Object Pooling: For frequently created/destroyed entities
- Organize by Layers: Clear collision layer organization
- Separate Concerns: Game logic separate from rendering
- State Management: Clear game state handling
See Also¶
- Code Examples - Reusable code snippets
- API Reference Overview - Complete API documentation
- Manual - Game Development - Detailed guides
Note: All example code is available in the src/examples/ directory of the PixelRoot32 Game Samples project.