Hello! Welcome back to our chess project.
In our last lesson, you successfully added the macroquad graphics library to our project using Cargo. This was a crucial first step into the world of graphical applications in Rust. Our project now has access to a powerful toolkit for drawing and user interaction.
Today, we'll put that library to use. We're moving from the command line to a graphical window. The goal of this lesson is to create a game window and set up a main rendering loop. This loop is the beating heart of any game; it's a continuous cycle that draws everything you see on the screen, frame by frame.
By the end of this lesson, you will have replaced our console-based "Hello, world!" with a graphical window and understand the basic structure of a macroquad application.
1. The Anatomy of a Macroquad App
Before we write any code, let's get a high-level overview. A macroquad application has a few key ingredients:
- A special attribute to mark our
mainfunction as the entry point for the game. - An
asyncmain function. This is a requirement formacroquadto handle different platforms (like desktop and web) smoothly. - An infinite
loopthat runs for every frame of the game. - A function call inside the loop that tells
macroquadto update the screen.
Let's watch a short video that puts these pieces together.
This video by Tantan is a great, concise demonstration of setting up a basic macroquad application. It will show you exactly the code we need to get a window on the screen.
Watch from the timestamp 00:29 to 01:16. Pay attention to how the main function is structured, the use of the loop, and the next_frame() call.
As you saw, it only takes a few lines of code to get a window up and running. Now, let's do it ourselves and then break down what each line means.
2. Hands-On: Creating Your Game Window
It's time to replace the code in your src/main.rs file. For now, we will set aside all our existing chess logic. Don't worry, we'll bring it back in later lessons once we have the graphical foundation in place.
-
Open
src/main.rs: Open your project's main source file. It probably just contains aprintln!("Hello, world!");line. -
Replace the code: Delete everything in
src/main.rsand replace it with the following code.use macroquad::prelude::*; #[macroquad::main("Chess")] async fn main() { loop { clear_background(LIGHTGRAY); // All of our game's drawing and logic will go here in the future next_frame().await; } } -
Run the project: Go to your terminal and run the command:
cargo run
After a moment of compiling, you should see a new window appear with the title "Chess" and a light gray background. It's empty, but it's a window that you created! You can close it to stop the program.
3. Understanding the Code
You've successfully created a window. Now, let's understand how it works. The code is simple, but each part plays a vital role.
The official Macroquad documentation provides an excellent explanation for the starter code we just used. This will clarify the purpose of each line.
Read the section titled 'Description of the application'. It breaks down the use statement, the #[macroquad::main] attribute, the game loop, and the next_frame() function.
Let's summarize the key points from that reading:
use macroquad::prelude::*;: This line imports the most common functions and types from themacroquadlibrary, so we can use things likeclear_backgroundandLIGHTGRAYdirectly.#[macroquad::main("Chess")]: This is a Rust macro. It's a special piece of code that writes more code for you at compile time. This specific macro frommacroquadsets up the window with the title "Chess" and prepares the platform-specific code needed to run yourmainfunction.async fn main(): Theasynckeyword is part of Rust's concurrency system.macroquaduses it to manage the game loop in a non-blocking way, which is especially important for web-based games (a cool feature ofmacroquad!) and ensures your game runs smoothly without freezing the operating system.loop { ... }: This is our main rendering loop. Everything inside this loop will be executed repeatedly, once for each frame. If your game runs at 60 frames per second (FPS), this loop runs 60 times every second.clear_background(LIGHTGRAY);: This is our first drawing command. It tellsmacroquadto fill the entire window with a specific color. Even if you don't call this,macroquadclears the screen with black by default at the start of each frame.next_frame().await;: This is arguably the most important line. It tellsmacroquadthat you are done with all your drawing commands for the current frame. The.awaitpauses yourmainfunction until it's time to draw the next frame, effectively syncing your loop to the screen's refresh rate and preventing your CPU from running at 100% unnecessarily.
Quick Challenge
The resource you just read mentioned a challenge. Let's try it!
Go back to your code and change LIGHTGRAY to a different color. You can try RED, BLUE, GREEN, or even DARKPURPLE. Run the program again to see your change. This simple exercise reinforces the idea that the code inside the loop directly controls what you see on the screen.
Conclusion
Fantastic! You've made the leap from a text-only console program to a graphical application. You now have a window and a running render loop, which is the fundamental structure for your entire chess game.
Key Takeaways:
- The
#[macroquad::main("Window Title")]macro is used to create a window and start the game. - The game's logic and drawing commands are placed inside an infinite
loop {}, which represents the main rendering loop. - The
async fn main()andnext_frame().awaitcombination is howmacroquadmanages the frame-by-frame execution in a platform-independent way. - Functions like
clear_background()are used inside the loop to draw to the screen.
Preview of the Next Lesson
Our window is currently just an empty gray box. In the next lesson, we'll start making it look like a chess game. We will learn how to draw shapes, specifically rectangles, to draw the 8x8 chessboard with its alternating colored squares. This will be our first major step in visualizing the game state.