40  The Beginning of Your Game Development Quest

Today, we embark on an epic journey into the realm of game development using Pyxel, a retro-inspired Python game engine. Just as a knight needs training before battling dragons, we’ll start by understanding what Pyxel is, how to set it up, and the fundamental pattern that brings games to life.

40.1 What is Pyxel and Why Use It?

Pyxel is a Python library specifically designed for creating retro-style 2D games. Think of the classic 8-bit games from the 1980s - Pyxel helps you create games with that nostalgic pixelated look and feel, but using modern Python code.

Why choose Pyxel for your game development quest?

  1. Simplicity: Pyxel is designed to be simple and easy to understand, making it perfect for beginners.
  2. All-in-one: It includes everything you need - graphics, sound, and input handling - in one package.
  3. Retro Aesthetic: Pyxel embraces the charm of 8-bit games with a fixed 16-color palette and 4-channel sound.
  4. Focus on Creativity: By limiting technical options, Pyxel helps you focus on game design rather than complex graphics.

Here’s a glimpse of what Pyxel provides:

  • A 16-color palette inspired by retro systems
  • Simple sprite and tilemap handling
  • Keyboard, mouse, and gamepad input
  • Sound effects and music capabilities
  • A built-in resource editor for creating assets

40.2 Basic Setup and Initialization

Before we can create magical game worlds, we need to prepare our spellbook (code environment). Let’s walk through setting up Pyxel and creating your first window:

40.2.1 Installing Pyxel

To install Pyxel, you’ll need Python 3.7 or newer. Type the following inside your IDE’s terminal:

py -m pip install pyxel

40.2.2 Your First Pyxel Program

Let’s create the simplest Pyxel application - a window that displays “Hello, Pyxel!”:

import pyxel

# Initialize Pyxel with a 160x120 window and a title
pyxel.init(160, 120, title="My First Pyxel Game")

# Define what happens each frame
def update():
    # Quit the application when Q is pressed
    if pyxel.btnp(pyxel.KEY_Q):
        pyxel.quit()

# Define what to draw each frame
def draw():
    # Clear the screen with color 0 (black)
    pyxel.cls(0)
    # Draw text at position (55, 41) with color 7 (white)
    pyxel.text(55, 41, "Hello, Pyxel!", 7)

# Start the Pyxel application
pyxel.run(update, draw)

When you run this code, a window will appear with the text “Hello, Pyxel!” displayed on a black background. You can exit by pressing the Q key.

40.3 The Game Loop: The Heart of Your Game

Every game needs a beating heart to bring it to life. In Pyxel (and most game engines), this heart is called the game loop. The game loop continually updates the game state and redraws the screen, creating the illusion of movement and interaction.

Pyxel’s game loop consists of two main functions:

  1. update(): This function runs before each frame is drawn. It’s where you handle:
    • Player input (keyboard, mouse, gamepad)
    • Game logic (moving characters, checking collisions)
    • Game state changes (scoring points, changing levels)
  2. draw(): This function runs after each update. It’s where you:
    • Clear the screen
    • Draw backgrounds, sprites, characters, and UI
    • Display text and scores

Let’s examine a slightly more complex example that demonstrates the game loop:

import pyxel

class Game:
    def __init__(self):
        # Initialize Pyxel
        pyxel.init(160, 120, title="Game Loop Demo")
        
        # Set up game variables
        self.player_x = 80  # Player's x position
        self.player_y = 60  # Player's y position
        self.player_color = 11  # Light blue
        
        # Start the game
        pyxel.run(self.update, self.draw)
    
    def update(self):
        # Allow quitting with Q
        if pyxel.btnp(pyxel.KEY_Q):
            pyxel.quit()
        
        if pyxel.btn(pyxel.KEY_LEFT):
            self.player_x = max(self.player_x - 2, 0)  # Move left but don't go below x=0 (left edge)
        if pyxel.btn(pyxel.KEY_RIGHT):
            self.player_x = min(self.player_x + 2, 160)  # Move right but don't exceed x=160 (right edge)
        if pyxel.btn(pyxel.KEY_UP):
            self.player_y = max(self.player_y - 2, 0)  # Move up but don't go below y=0 (top edge)
        if pyxel.btn(pyxel.KEY_DOWN):
            self.player_y = min(self.player_y + 2, 120)  # Move down but don't exceed y=120 (bottom edge)
    
    def draw(self):
        # Clear screen with dark blue
        pyxel.cls(1)
        
        # Draw player as a circle
        pyxel.circ(self.player_x, self.player_y, 8, self.player_color)
        
        # Draw instructions
        pyxel.text(5, 5, "Use arrow keys to move", 7)
        pyxel.text(5, 15, "Press Q to quit", 7)

# Create and start the game
Game()

This code creates a more interactive application where you can control a blue circle using the arrow keys. Each frame:

  1. The update() method checks for input and adjusts the player’s position.
  2. The draw() method clears the screen and draws the player at their new position.

This continuous update-draw cycle creates the interactive experience that makes games feel alive.

40.4 Understanding Input Handling in Pyxel

One of the most important aspects of any game is handling player input. Pyxel provides two main functions for detecting button (keyboard/gamepad) presses:

40.4.1 The Difference Between btn and btnp

  1. pyxel.btn(key): Checks if a button is currently being held down
    • Returns True continuously as long as the button is pressed
    • Perfect for continuous actions like movement
    • Example: Moving a character while an arrow key is held down
  2. pyxel.btnp(key): Checks if a button was just pressed
    • Returns True only on the first frame when a button is pressed
    • Perfect for one-time actions like jumping, shooting, or menu selection
    • Example: Quitting the game when Q is pressed (you only want this to happen once)

Let’s see this difference in action:

# In your update() function:

# Continuous movement (good for walking)
if pyxel.btn(pyxel.KEY_RIGHT):
    self.player_x += 2  # Move right continuously while key is held

# One-time action (good for jumping or firing)
if pyxel.btnp(pyxel.KEY_SPACE):
    self.fire_weapon()  # Only fire once when space is pressed

40.4.2 Common Input Constants

Pyxel provides constants for various keys:

  • Direction keys: pyxel.KEY_UP, pyxel.KEY_DOWN, pyxel.KEY_LEFT, pyxel.KEY_RIGHT
  • Action keys: pyxel.KEY_SPACE, pyxel.KEY_Z, pyxel.KEY_X, pyxel.KEY_RETURN
  • Control keys: pyxel.KEY_Q, pyxel.KEY_ESCAPE
  • Mouse buttons: pyxel.MOUSE_BUTTON_LEFT, pyxel.MOUSE_BUTTON_RIGHT

Remember to choose the appropriate input function based on the action you want to perform!

40.5 Object-Oriented Approach in Pyxel

You might have noticed we used a class in the second example. While not required, organizing your game using classes (object-oriented programming) has several benefits:

  1. Organization: Keeps related variables and functions together
  2. State Management: Makes it easier to track game state
  3. Expandability: Makes it simpler to add new features
  4. Readability: Creates cleaner, more understandable code

Let’s look at a more structured example (ensure pyxel_logo.png is in current directory):

import pyxel

class App:
    def __init__(self):
        pyxel.init(200, 140, title="Hello Python Class")
        # Load an image (we'll learn more about this later)
        pyxel.images[0].load(0, 0, "pyxel_logo.png")
        pyxel.run(self.update, self.draw)

    def update(self):
        if pyxel.btnp(pyxel.KEY_Q):
            pyxel.quit()

    def draw(self):
        pyxel.cls(0)
        # Display text with changing colors
        pyxel.text(60, 21, "Hello, Python Class!", pyxel.frame_count % 16)
        # Draw the loaded image (we'll explain this more in later lessons)
        pyxel.blt(24, 46, 0, 0, 0, 160, 70)
        # pyxel.blt(61, 66, 0, 0, 0, 38, 16)

App()

This example uses a class called App to organize our game. It also introduces a few new concepts:

  • pyxel.frame_count: A variable that increases by 1 each frame
  • pyxel.images: Pyxel’s image banks for storing graphics
  • pyxel.blt(): The function to draw images on the screen

40.6 Practice Time: Your First Pyxel Challenge

Now it’s your turn to create a simple Pyxel application. Complete these quests to prove your newfound skills:

  1. Create a Pyxel window with a size of 200x150 and a title of your choice.

  2. Make a program that displays your name in the center of the screen with changing colors.

Here’s a starting point for your quest:

import pyxel

class MyFirstGame:
    def __init__(self):
        # Initialize Pyxel with your chosen size and title

        # Start the game
        pyxel.run(self.update, self.draw)

    def update(self):
        # Allow quitting with Q

        # Add your update logic here

    def draw(self):
        # Clear the screen
        pyxel.cls(0)

        # Add your drawing code here

# Create and start your game
MyFirstGame()

40.7 Common Bugs to Watch Out For

As you begin your Pyxel journey, beware of these common pitfalls:

  1. Forgetting to import pyxel: Always start your code with import pyxel.

  2. Not calling pyxel.init(): This must be called before using any other Pyxel functions.

  3. Undefined variables: Make sure all variables are defined before using them.

  4. Drawing outside the screen: Remember that coordinates start at (0,0) in the top-left corner. Drawing outside the window size will not cause an error, but you won’t see the results.

  5. Forgetting to call pyxel.run(): Without this, your game won’t start.

  6. Using colors outside the palette: Pyxel only supports 16 colors (0-15). Using a color number outside this range will cause errors.

  7. Infinite loops: Be careful not to create loops without exit conditions in the update function, as they can freeze your game.

40.8 Conclusion and Resources for Further Quests

You’ve taken your first steps into the realm of game development with Pyxel. You now understand what Pyxel is, how to set it up, and the fundamental game loop pattern that brings games to life.

To continue your game development journey, check out these resources:

  1. Pyxel’s Official GitHub Repository - Contains documentation, examples, and the latest updates.

  2. Pyxel Documentation - The official guide to all Pyxel’s features and functions.

  3. Pyxel Examples - A collection of example games and demos to inspire you.

  4. Introduction to Game Development with Pyxel - A beginner-friendly guide to game development concepts.

In our next lesson, we’ll explore Pyxel’s color system and coordinate system, giving us the foundation to create more visually engaging games. Keep practicing, keep experimenting, and remember - every master game developer started where you are now!