Macroquad egui DevTools: Rust Game Debugging UI
Tags: rust, gamedev, debugging
Published: 2024-05-02 11:01:03

---
title: "Macroquad egui DevTools: Rust Game Debugging UI"
published: "true"
description: "Macroquad egui DevTools: adding a visual 🐞 debugging user interface for developers to Rust Macroquad game using ⚡️ egui."
tags: "rust, gamedev, debugging"
canonical_url: "https://rodneylab.com/macroquad-egui-devtools/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9dgflyq1m1rz0re5h7z5.png"
---
## 🎮 Macroquad egui DevTools

In this post on Macroquad egui DevTools, I talk about a demo project I put together to add a developer-focussed **debugging view** to a Macroquad game.  Macroquad is a Rust game development library built for **fast prototyping** and egui is a Rust **immediate mode** GUI.  Interestingly, both were inspired by libraries from the C/C++ world.  Macroquad was inspired by the C, **raylib** library, while **Dear ImGui** inspired the creation of egui.

We shall see the idea of the DevTools is to create a debugging interface, rather than something intended for end-user access.  The inspiration here is the DevTools found in web browsers like **Chrome** and **Firefox** to help **web developers** debug sites they are working on.  Using egui we shall see how you can both display data on the current Macroquad game state and also mutate the state.  The latter could be handy for **tweaking gameplay** or even just the **game aesthetic**, working on real-world project.

Macroquad does have its own UI, though I preferred to use egui here partly because it allows more flexibility.  It saves me having to learn another UI interface, and also make the UI more portable if I later want to port the game to **Bevy**, **Godot** or **Tauri** for example.  <a href="https://github.com/emilk/egui?tab=readme-ov-file#3rd-party-integrations">egui enjoys wide support in the Rust Game Dev</a> ecosystem.

Anyway, if this all sounds interesting to you, then let&rsquo;s press on, starting by taking a look at what I created.

## 🧱 What I Built

I built a minimal proof-of-concept &ldquo;game&rdquo; using Macroquad and egui.  The Macroquad base code renders a carrot coloured ball, which bounces off the window edges. Using egui widgets, I then added a dev panel which has readouts of the ball current position and velocity.  Taking things a step further, another widget lets the developer change the size of the ball in real-time, just by using an egui UI slider.

![Macroquad egui Dev Tools: a carrot-coloured ball floats in the middle of a window on a screen capture.  The window has a gunmetal coloured background.  In the top left corner of the window sits a panel title "Developer Tools"; it has two sections.  The Ball Physics section gives the current x and y values of the ball position and velocity.  The lower Ball Shape section has a slider for controlling the ball radius.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mclhrzekdxtqo4ls7vmc.png)

## 🤔 A Little more about egui

I mentioned egui is an **immediate mode** GUI.  Immediate mode is a design pattern where code for handling user interface side effects appears alongside the code for the UI itself.  For example, there is no callback function attached to our slider for adjusting the ball radius.  We just pass a mutable reference to the ball radius into the slider widget UI method, and let the UI widget update the radius directly.

That immediate mode pattern makes coding an interface far simpler.  It is not all milk and honey, though!  Re-rendering unchanged elements on every loop might be inefficient.  Another drawback is that precise layout can be tricky with immediate mode.  Because the library draws widgets as it encounters them, centring a widget horizontally, as an example, can be tricky. This is because we might not know how wide the widget or container are until we have drawn them.  That said, for a game debugging tool, immediate mode is a pretty good match.

If you want to see a more general introduction to egui or immediate mode in Rust, see a recent post where we looked at <a href="https://rodneylab.com/trying-egui/">creating a Cistercian clock using Rust with egui</a>.

## ⚙️ Project Setup

The `macroquad-egui` crate is probably the easiest way to get egui working with Macroquad.  At the time of writing, `macroquad-egui` was not working well with the latest version of Macroquad, though I found these versions do work well together:

```toml
[package]
name = "macroquad-egui"
version = "0.1.0"
edition = "2021"
 
[dependencies]
egui = "0.21.0"
egui-macroquad = "0.15"
macroquad = { version="0.3.26", default-features=false }
```

You can find <a href="https://github.com/optozorax/egui-macroquad">some skeleton code in the `egui-macroquad` repo</a> to test your setup:

```rust
// Source: https://github.com/optozorax/egui-macroquad#usage
use macroquad::prelude::*;
 
#[macroquad::main("egui with macroquad")]
async fn main() {
    loop {
        clear_background(WHITE);
 
        // Process keys, mouse etc.
 
        egui_macroquad::ui(|egui_ctx| {
            egui::Window::new("egui ❤ macroquad")
                .show(egui_ctx, |ui| {
                    ui.label("Test");
                });
        });
 
        // Draw things before egui
 
        egui_macroquad::draw();
         
        // Draw things after egui
 
        next_frame().await;
    }
}
```

## 🖱️ Adding egui to Macroquad

Probably the hardest part, if you are new to egui, is to work out how to display the widgets you want.  The <a aria-label="e gui demo site is quite handy" href="https://www.egui.rs/">egui demo site is quite handy</a> in this regard.  It features the egui widgets, and has GitHub links to the Rust code used to make each widget.  This will help you replicate them in your own project.

I include the egui code I wrote here, in case it is useful for you as a starting point:

```rust
egui_macroquad::ui(|egui_ctx| {
    egui_ctx.set_pixels_per_point(4.0);
    egui::Window::new("Developer Tools").show(egui_ctx, |ui| {
        CollapsingHeader::new("Ball Physics")
            .default_open(false)
            .show(ui, |ui| {
                ui.horizontal(|ui| {
                    ui.label("Position");
                    ui.label(format!(
                        "x: {:.2} y: {:.2}",
                        ball.position.x, ball.position.y
                    ));
                });
                ui.horizontal(|ui| {
                    ui.label("Velocity");
                    ui.label(format!("x: {} y: {}", ball.velocity.x, ball.velocity.y));
                });
            });
        CollapsingHeader::new("Ball Shape")
            .default_open(false)
            .show(ui, |ui| {
                ui.horizontal(|ui| {
                    ui.label("Radius");
                    ui.add(egui::Slider::new(&mut ball.radius, 1.0..=100.0));
                });
            });
    });
});
```

Some interesting points;

- `set_pixels_per_point` in line `128` scales the whole user interface.  I set `4.0` so the elements were large enough for capturing screenshots, and this might be a little high for general use.
- The `CollapsingHeader` element in lines `130`-`144` creates the folding tree structure you see in the demo.
- Notice in line `150`, we just pass in a mutable reference to `ball.radius` to the slider. No need for callbacks; it directly updates the same variable which Macroquad uses for rendering.

Hopefully the other parts of the code will make sense, probably more so if you have already used Dear ImGui.  That said, please let me know if some lines would benefit from further clarification.  I have added a link, further down, to the entire project code.

## 🏁 What Next for the Macroquad egui DevTools Interface?

I mentioned this is just a basic proof-of-concept.  I have tried <a href="https://rodneylab.com/using-jolt-with-flecs-dear-imgui/">a similar game debugging interface in C++ using raylib and Dear ImGui</a> and would like to bring some features across such as:

- adding game state and pausing play in the Dev Tools;
- having separate regular and debugging DevTools modes; and
- the ability to move the dev tool tab so it does not overlap the main window.

## 🙌🏽 Macroquad egui DevTools: Wrapping Up

In this Macroquad egui DevTools post, we got an introduction to working with Macroquad and egui.  In particular, we saw:

- which **versions of Macroquad and egui work with egui-macroquad**;
- how you might use **egui to update game state from a debugging panel**; and
- some **resources for getting started with egui**.

I hope you found this useful.  As promised, you can <a href="https://github.com/rodneylab/macroquad-egui">get the full project code on the Rodney Lab GitHub repo</a>.  I would love to hear from you, if you are also new to Rust game development.  Do you have alternative resources you found useful? How will you use this code in your own projects?

## 🙏🏽 Macroquad egui DevTools: Feedback

If you have found this post useful, see links below for further related content on this site.  Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on X, giving me a mention, so I can see what you did. Finally, be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please <a aria-label="Support Rodney Lab via Buy me a Coffee" href="https://rodneylab.com/giving/">consider supporting me through Buy me a Coffee</a>.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via <a href="https://twitter.com/messages/compose?recipient_id=1323579817258831875">@askRodney</a> on X (previously Twitter) and also, join the <a href="https://matrix.to/#/%23rodney:matrix.org">#rodney</a> Element Matrix room. Also, see <a aria-label="Get in touch with Rodney Lab" href="https://rodneylab.com/contact/">further ways to get in touch with Rodney Lab</a>. I post regularly on <a href="https://rodneylab.com/tags/gaming/">Game Dev</a> as well as <a href="https://rodneylab.com/tags/rust/">Rust</a> and <a href="https://rodneylab.com/tags/c++/">C++</a> (among other topics). Also, <a aria-label="Subscribe to the   Rodney Lab newsletter" href="https://newsletter.rodneylab.com/issue/latest-issue">subscribe to the newsletter to keep up-to-date</a> with our latest projects.