Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 43

Drawing a Chessboard

Recommended resources

Hello! Welcome back to our journey of building a chess game in Rust.

In the last lesson, you did something very important: you moved our project from the console to a graphical window. You set up the macroquad library and created a main rendering loop, which is the foundational structure for any game. We now have an empty window, a blank canvas waiting for us to paint our game on.

Today, we'll take the first major step in turning that blank canvas into a recognizable game. Our goal is to draw the 8x8 chessboard with alternating colored squares. We will learn how to draw basic shapes and use loops to create a grid, which are fundamental skills in 2D graphics programming.

1. The Building Block: draw_rectangle

To draw our chessboard, we need to draw 64 squares. macroquad provides a simple function for this: draw_rectangle. Let's look at its official documentation to see how it works.

draw_rectangle in macroquad::shapes

This is the official documentation for the draw_rectangle function. It's a great habit to refer to the documentation as it gives you the precise signature and parameters for the tools you're using.

Read the main description of the function. Take note of its five parameters: x, y, w, h, and color. Pay close attention to the fact that x and y define the position of the top-left corner of the rectangle.

As you saw, the function is straightforward: draw_rectangle(x, y, width, height, color). The coordinate system in macroquad starts with (0.0, 0.0) at the top-left corner of the window.


2. Hands-On: Drawing Your First Square

Let's apply this immediately. In your src/main.rs file, add a call to draw_rectangle inside your main loop, right after clear_background.

// In src/main.rs

use macroquad::prelude::*;




#[macroquad::main("Chess")]
async fn main() {
    loop {
        clear_background(LIGHTGRAY);

        // Draw a single blue square
        draw_rectangle(0.0, 0.0, 100.0, 100.0, BLUE);

        next_frame().await;
    }
}

Run your project with cargo run. You should now see a blue square with a size of 100x100 pixels at the very top-left corner of your window.

Quick Challenge:
Before moving on, try changing the parameters of draw_rectangle to move the square. For example, can you make it appear roughly in the center of the window? This will help you get a feel for the coordinate system.


3. From One Square to a Grid

Drawing one square is easy. Now, how do we draw 64 of them in an 8x8 grid? We can use your existing programming knowledge here. A nested loop is perfect for this task—one loop for the rows (ranks) and another for the columns (files).

For each square in the grid, we need to calculate its x and y position. If we decide on a size for our squares (let's say SQUARE_SIZE), we can calculate the position like this:

  • x_position = column_index * SQUARE_SIZE
  • y_position = row_index * SQUARE_SIZE

The video below demonstrates a similar principle in the context of a different game. The developer is creating a grid of blocks and calculates their positions within a loop.

Rust breakout game tutorial

This clip from Tantan's tutorial on a Breakout game shows how to generate and draw a grid of blocks. The core idea of looping and calculating positions to draw multiple rectangles is exactly what we need for our chessboard.

Watch from 04:45 to 06:10. Notice how a loop is used to create multiple blocks and then another loop is used to draw them. The key takeaway is how the x and y position for each block is calculated based on its index in the grid.


4. Implementing the Chessboard

Now, let's combine these ideas to draw our board. We will:

  1. Define constants for the board dimensions and square size.
  2. Use nested for loops to iterate over each of the 8 ranks and 8 files.
  3. Inside the loops, determine if a square should be light or dark. A simple way to do this for a checkerboard pattern is to check if the sum of the rank and file indices is even or odd.
  4. Calculate the x and y position for the current square.
  5. Call draw_rectangle with the calculated position and the appropriate color.

Replace the code in your src/main.rs file with the following complete example.

use macroquad::prelude::*;

// Define colors for the board squares
const DARK_COLOR: Color = color_u8!(118, 150, 86, 255);
const LIGHT_COLOR: Color = color_u8!(238, 238, 210, 255);

// Define the dimensions of the board
const RANKS: i32 = 8;
const FILES: i32 = 8;
const SQUARE_SIZE: f32 = 80.0;




#[macroquad::main("Chess")]
async fn main() {
    loop {
        clear_background(BLACK);

        // Loop through each rank (row)
        for rank in 0..RANKS {
            // Loop through each file (column)
            for file in 0..FILES {
                // Determine the color of the square
                let is_light_square = (rank + file) % 2 != 0;
                let color = if is_light_square {
                    LIGHT_COLOR
                } else {
                    DARK_COLOR
                };

                // Calculate the position of the square
                let x = file as f32 * SQUARE_SIZE;
                let y = rank as f32 * SQUARE_SIZE;

                // Draw the square
                draw_rectangle(x, y, SQUARE_SIZE, SQUARE_SIZE, color);
            }
        }

        next_frame().await;
    }
}

Run the program now. You should see a complete 8x8 chessboard!

A digital rendering of an 8x8 chessboard with alternating light green and dark green squares.

An 8x8 grid of alternating colored squares, drawn using macroquad.

Let's briefly break down the color logic: (rank + file) % 2 != 0.

  • For the top-left square (rank 0, file 0), (0 + 0) % 2 is 0, so it's dark.
  • For the square next to it (rank 0, file 1), (0 + 1) % 2 is 1, so it's light.
  • For the square below the first (rank 1, file 0), (1 + 0) % 2 is 1, so it's light.
    This simple mathematical trick creates the classic alternating pattern.

Conclusion

Excellent work! You've transformed an empty window into a proper chessboard. This is a significant step forward and forms the visual foundation upon which we will build the rest of our game.

Key Takeaways:

  • The draw_rectangle(x, y, w, h, color) function is used to draw solid rectangles.
  • Nested loops are an effective way to create 2D grids.
  • You can calculate the position of elements in a grid by multiplying their indices by a fixed size.
  • Simple arithmetic ((row + col) % 2) can be used to create alternating patterns like a checkerboard.

Preview of the Next Lesson

Our board is ready, but it's empty. In the next lesson, we will begin to populate it. We will learn how to load chess piece images (sprites) from files. This will prepare us to eventually render the pieces on the board according to the game state.