DEV Community

Divyanshi Jain
Divyanshi Jain

Posted on

# Building "Echoes of Code": A Time-Loop Puzzle Game with Python and PyGame with #AmazonQCLI

In this technical blog, I'll walk you through creating "Echoes of Code," a 2D top-down puzzle game where you solve puzzles by collaborating with echoes of your past actions. I'll focus on the key components and concepts to keep this a quick 5-minute read.

Setting Up the Development Environment

Installing WSL on Windows

  1. Enable WSL: Open PowerShell as Administrator and run:([DEV Community][1])
 wsl --install 
Enter fullscreen mode Exit fullscreen mode
  1. Restart your computer and complete the Linux distribution setup.

Setting Up Python and PyGame

# Install Python and dependencies sudo apt install python3 python3-pip python3-dev -y sudo apt install python3-pygame -y # Install PyGame pip3 install pygame 
Enter fullscreen mode Exit fullscreen mode

Installing Amazon Q CLI

# Install AWS CLI first curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install # Configure AWS aws configure # Install Amazon Q CLI curl -Lo "/tmp/q-cli.deb" "https://d3l58w4xvhud7h.cloudfront.net/linux/amd64/latest/q-cli.deb" sudo dpkg -i /tmp/q-cli.deb # Login q login 
Enter fullscreen mode Exit fullscreen mode

Game Design and Concept

"Echoes of Code" features a software engineer trapped in a glitched digital world. Every 10 seconds, time resets, and your past actions are replayed by ghost clones called "echoes." You must use these echoes strategically to solve puzzles.

Implementation Highlights

Time Loop System

The core of the game is the TimerManager class that handles the time loop mechanics:

class TimerManager: def __init__(self, loop_duration: float, max_loops: int): self.loop_duration = loop_duration self.max_loops = max_loops self.start_time = time.time() self.current_loop = 1 def get_loop_time(self) -> float: """Get time elapsed in the current loop""" return self.get_elapsed_time() % self.loop_duration def should_reset_loop(self) -> bool: return self.get_loop_time() >= self.loop_duration def reset_loop(self): self.current_loop += 1 
Enter fullscreen mode Exit fullscreen mode

Action Recording and Replay

The Player class records actions, while the Echo class replays them:

# In Player class def record_action(self, action_type: str, time_stamp: float): self.actions.append(Action(action_type, (self.x, self.y), time_stamp, self.current_direction)) # In Echo class def update(self, current_time: float, game_objects: List): if self.current_action_index < len(self.actions): next_action = self.actions[self.current_action_index] if current_time >= next_action.time_stamp: if next_action.action_type == "move": self.x, self.y = next_action.position self.current_direction = next_action.direction elif next_action.action_type == "interact": self.interact_with_objects(game_objects) self.current_action_index += 1 
Enter fullscreen mode Exit fullscreen mode

Interactive Game Objects

The game includes various interactive elements:

# Example of the PressurePlate class class PressurePlate: def update(self, players: List[Player]): self.is_active = False plate_rect = pygame.Rect(self.x, self.y, self.width, self.height) for player in players: player_rect = pygame.Rect(player.x, player.y, player.width, player.height) if plate_rect.colliderect(player_rect): self.is_active = True break 
Enter fullscreen mode Exit fullscreen mode

Loop Reset Logic

When a loop resets, we create a new echo and reset the player:

def reset_loop(self): # Create a new echo from the current player  echo_colors = [PURPLE, YELLOW, CYAN, RED, GREEN] echo_color = echo_colors[min(len(self.echoes), len(echo_colors) - 1)] self.echoes.append(Echo(self.player, echo_color, self.timer_manager.current_loop)) # Reset player position  current_level = self.level_manager.get_current_level() self.player.x, self.player.y = current_level.player_start # Clear player actions for the new loop  self.player.actions = [] # Increment loop counter  self.timer_manager.reset_loop() 
Enter fullscreen mode Exit fullscreen mode

Level Design

Levels are created using the Level class, which manages all game objects:

def create_levels(self): # Level 1: Simple pressure plate and gate  level1 = Level(1, (100, 300), 3) # Player starts at (100, 300), 3 loops max  # Add walls (border)  level1.add_wall(0, 0, SCREEN_WIDTH, 20) # Top  level1.add_wall(0, SCREEN_HEIGHT - 20, SCREEN_WIDTH, 20) # Bottom  # Add pressure plate  level1.add_pressure_plate(300, 200, 1) # Controls gate with ID 1  # Add gate  level1.add_gate(400, 400, 20, 100, 1) # Gate with ID 1  # Add exit  level1.set_exit(700, 300) 
Enter fullscreen mode Exit fullscreen mode

Main Game Loop

The Game class ties everything together:

def run(self): running = True while running: running = self.handle_events() self.update() self.draw() self.clock.tick(FPS) 
Enter fullscreen mode Exit fullscreen mode

Development Challenges

  1. Echo Replay Timing: Ensuring echoes replayed actions at the exact same time they were recorded.

  2. Collision Detection: Making sure players and echoes interacted correctly with game objects.

  3. Loop Reset Logic: Managing the state transition when a loop resets, especially ensuring all objects reset properly.

Future Enhancements

The game can be expanded with:

  1. Additional Levels: More complex puzzles requiring multiple echoes to solve.

  2. Mini Terminal: Implementing a system where players can write simple logic commands.

  3. Enemies: Adding entities that track and interact with echoes.

  4. Visual Timeline: Creating a replay system to show all actions at the end of each level.

Running the Game

To run the game:

cd ~/echoes_of_code python3 echoes_of_code.py 
Enter fullscreen mode Exit fullscreen mode

Conclusion

Building "Echoes of Code" demonstrates how a unique game mechanic like time loops can create engaging puzzle gameplay. The modular code structure makes it easy to expand with new levels and features. By leveraging WSL for development and Amazon Q CLI for assistance, I was able to streamline the development process and focus on implementing the core game mechanics.

If you're interested in time-based puzzle games or want to explore PyGame development, I encourage you to try out "Echoes of Code" and even extend it with your own ideas!

Top comments (0)