24 Hours, No AI, Zero to Rust: Building a Game from Scratch — A Full Account

One creator built a Rust game in 15 hours with zero prior knowledge and no AI assistance.
A YouTube creator challenged himself to learn Rust from scratch and ship a playable game within 24 hours — no AI tools allowed. He covered Rust syntax, ownership and borrowing, and a 2D game engine before building a complete Brick Breaker game in just 15 hours and 23 minutes. The account details every technical hurdle, from memory management concepts to the real cost of poor ecosystem choices.
A Programming Challenge Without AI Assistance
In an era when AI coding assistants are everywhere, one YouTube creator set himself a countercultural challenge: starting with zero knowledge of Rust, using no AI tools whatsoever, typing every character by hand, and shipping a playable game — all within 24 hours. If he failed, he'd let the top-pinned comment on the video decide his next language to learn.
The challenge had two compelling angles. On one hand, Rust has topped the "most loved programming language" polls for years running. On the other, Rust is notoriously hard to learn. It tolerates no sloppy code — the compiler scrutinizes every detail and flatly refuses to compile anything that doesn't pass muster. As the creator put it, "It's very stubborn, just like me."
The challenge unfolded in three stages: learning Rust syntax from scratch, mastering a Rust-based game engine from scratch, and building a complete game with that engine — all compressed into 24 hours.
Cramming Rust Syntax: Familiar Yet Foreign Building Blocks
To move fast, he picked a three-hour introductory Rust course on YouTube and watched it at 2× speed. His background was primarily Python with about six months of programming experience, but he acknowledged that every language has its own syntax universe — "like learning to write sentences again, but every word is spelled differently and the grammar rules have all changed."
The course started with the classic Hello World. Unlike Python, where you write code and run it directly, Rust requires compilation first — transforming source code into a standalone executable the computer can run directly. This step reflects an important language classification: Python is an interpreted language, where an interpreter translates and executes code line by line, offering a flexible development experience but relatively lower runtime performance. Rust is a compiled language, where the entire source is converted to machine code before execution, achieving speeds close to C/C++ — one of the core reasons Rust is favored in systems programming and game development.
This performance gap can be staggering in practice. In benchmarks like the Computer Language Benchmarks Game, Rust typically executes 50 to 100 times faster than Python while using a fraction of the memory. The gap stems from multiple layers: every Python line requires the interpreter to perform type checks and bytecode interpretation before execution, while Rust code has all types determined at compile time and generates native machine code optimized for the target CPU's instruction set. Python integers are heap-allocated objects (to support arbitrary-precision big integers), while Rust's i32 is simply 4 bytes on the stack. Python's GIL (Global Interpreter Lock) limits true multi-thread parallelism, while Rust's ownership system inherently guarantees thread safety and can fully leverage modern multi-core CPUs. For game development specifically, maintaining a stable 60 FPS means only 16 milliseconds per frame — any GC pause or interpreter overhead directly destroys the experience.
He then worked through variables and data types, structs, loops, functions, and other building blocks common to most languages.

One key difference: Rust has no object-oriented programming. As a lower-level language, Rust organizes code with simpler primitives. The upside is faster, lower-overhead programs; the downside is that many things high-level languages handle automatically must be done manually. Notably, Rust doesn't entirely abandon object-oriented thinking — its Trait system achieves capabilities similar to interfaces and polymorphism, a more flexible, zero-cost abstraction design philosophy known as "composition over inheritance."
Getting Stuck on Ownership and Borrowing
What really gave the creator headaches were two concepts unique to Rust: heap vs. stack memory management, and the ownership and borrowing system.
Understanding the engineering implications of heap vs. stack: Stack memory follows last-in, first-out principles, with sizes determined at compile time and extremely fast access. Heap memory is dynamically allocated at runtime, variable in size, but accessed via pointer indirection — slower and prone to fragmentation. High-level languages typically hide this distinction from developers, while Rust requires explicit awareness of where data lives — String goes on the heap, primitives like i32 go on the stack — which directly affects the semantics of ownership transfers and is the root of the creator's "falling down a rabbit hole" feeling.
The underlying logic of the ownership system: Understanding Rust's ownership system requires understanding the historical dilemma it was designed to solve. Before Rust (around 2010), systems programming faced a persistent dilemma: C/C++ gave programmers complete memory control, but use-after-free, buffer overflows, and similar memory safety vulnerabilities were the industry's top security threat — roughly 70% of high-severity vulnerabilities in Chrome's history trace back to these issues. Meanwhile, GC-based languages were safe but couldn't be used in operating system kernels, game engines, or other latency-sensitive domains due to runtime overhead and unpredictable Stop-The-World GC pauses that could last hundreds of milliseconds.
Rust chose a third path: statically analyzing memory usage through ownership rules at compile time, with no runtime GC and no manual memory management — achieving "zero-runtime-overhead memory safety." This was a genuine paradigm breakthrough in programming language history. Simply put, every piece of data in Rust has exactly one "owner." When data is transferred from one variable to another, the original variable gives up ownership. The way around this is "borrowing" — temporarily lending out access rights without transferring ownership. This mechanism forces programs to run efficiently and makes memory leaks nearly impossible. As the creator marveled, "I feel like in Rust you can't even create a memory leak on purpose."
Without fully mastering these concepts, he learned enough to press on. Four hours in, the Rust syntax phase was complete.
The Cost of Choosing the Wrong Engine: Going It Alone with Rusty Engine
Rendering a game window, drawing sprites, and detecting collisions all require a game engine. The creator found a 2D engine called Rusty Engine, designed specifically for Rust beginners — it looked like a perfect fit.
He used it as an opportunity to practice reading official documentation directly, diving in without much research. Many hours later, he discovered a fatal problem: there was almost no third-party material about this engine anywhere online — no forum discussions, no Stack Overflow posts, no YouTube videos. Only documentation pages written by the author himself.
The reality of the Rust game development ecosystem: This predicament reflects the broader state of the Rust game ecosystem. The most actively developed pure-Rust engine is Bevy, which uses an ECS (Entity-Component-System) architecture. Unlike traditional object-oriented game development where "a player is a class inheriting from GameObject," ECS decomposes game objects into three orthogonal concepts: Entities are just numeric IDs, Components are pure data structures (like Position, Velocity, Health), and Systems are functions that process specific component combinations. This architecture has excellent data locality, high CPU cache hit rates, and dramatically outperforms traditional OOP when handling tens of thousands of game objects. However, Bevy's steep learning curve and frequent breaking API changes (each major version may require large-scale refactoring) make it unfriendly for beginners. Macroquad is known for simplicity and is better suited for rapid prototyping. Compared to mature engines like Unity and Godot with millions of developers and vast tutorial libraries, Rust-based engines generally suffer from incomplete documentation and scarce third-party resources — meaning that when you hit a problem, you're completely on your own, and even Google can't help. This decision caused him considerable trouble.
From Sprites to Physics: Building a Complete Brick Breaker Game
The creator decided to build the classic Brick Breaker game — knock out all the bricks with a bouncing ball to win. This gave him exposure to physics simulation, real-time state updates, and multiple game events — a solid practice project.
He designed all the sprites in Photoshop: a small crab (the Rust community mascot) holding a paddle as the player character, five different brick styles, and a ball. With the images done, he used Rusty Engine's built-in tool to draw custom polygons over the sprites to define collision areas.

Movement Logic and Ball Physics
Player movement was straightforward: check keyboard state each frame, add 10 to the player's X coordinate on right arrow, subtract 10 on left arrow, and let the render function place the paddle accordingly. The ball worked the same way — each frame, add X and Y velocity to the current position for movement; when hitting the top or sides of the screen, multiply the corresponding direction's velocity by -1 to bounce.
This "velocity vector flip" bounce logic has rigorous physical grounding: in an ideal perfectly elastic collision, the component of velocity along the collision normal reverses sign while the tangential component remains unchanged. For axis-aligned boundaries (horizontal or vertical walls), the normal direction is exactly parallel to the coordinate axis, so only the corresponding axis's velocity component needs to flip — vx *= -1 or vy *= -1 — which is mathematically exact for a collision between an infinite-mass plane and a point mass, not merely an approximation. What's actually being ignored is friction, energy loss, and ball radius (the point-mass approximation), but this performs admirably in light physics games like Brick Breaker.
A clever design touch: the ball's horizontal velocity was linked to the paddle's movement direction — the ball accelerates when moving the same direction as the paddle, and decelerates when moving against it. This is actually a clever approximation of the real physical effect of "a moving paddle imparting momentum to the ball," a mechanic traceable back to the hardware circuit implementation of the 1976 Atari original Breakout and now a near-standard convention for the genre. It both prevents the ball from falling into a perfect looping path that makes levels unsolvable and gives players meaningful control over the rebound angle.
Building Levels with a 2D Array
The brick layout was defined via a 2D array (a 5×8 grid of numbers), where non-zero values represent bricks and zero represents empty space — modifying the numbers makes it easy to design different level layouts. The program iterates through each row and column, calculates screen coordinates for non-zero cells, and creates and places the corresponding sprites.
A classic example of data-driven design: Using a 2D array to define game levels is a time-tested data-driven design pattern used widely since the 8-bit console era — Super Mario Bros. levels are essentially tile index matrices. This approach completely decouples game logic from level data: developers only need to change the number matrix to generate entirely new levels without touching any rendering or collision code. The "Tilemap" editor in modern game engines is essentially a visual extension of this concept, transforming numeric matrices into graphical interfaces for level designers, while the underlying storage format often remains structured numeric data.

Each brick was programmatically assigned a unique ID based on its grid position and a randomly selected visual style. All data was stored in a vector of brick structs, each containing the brick's ID, hit points, and sprite copy. On collision, the engine returned the ID of the hit brick, and the program removed that brick from both the engine and the vector.
Design Compromises Forced by Engine Limitations
This is where the consequences of the engine choice became apparent. The creator had originally planned to give each brick hit points, switching textures after a hit to show a damaged state. But Rusty Engine doesn't support modifying a sprite's texture after it's been created — the texture is fixed when the sprite is added, with no built-in update method. He searched through the documentation and across the web and found no solution; attempts to manually implement texture changes by replacing the entire sprite consumed hours without success. He ultimately simplified the design: one hit, one kill.
This predicament vividly illustrates the importance of "ecosystem maturity" in technology selection. A single Stack Overflow answer or a GitHub issue discussion can sometimes save hours of debugging. In rapid prototyping scenarios, choosing a tool with an active community — even if not technically optimal — is often wiser than choosing a functionally superior but isolated one.
With the core gameplay running, he added a start screen (press S to begin), a corner scoreboard, and a victory screen triggered when all bricks were cleared.
Challenge Completed in 15 Hours and 23 Minutes
The creator finished the game in 15 hours and 23 minutes — nearly 9 hours ahead of the 24-hour deadline. He said he thoroughly enjoyed learning Rust, and even though he'd only covered the most basic parts, he strongly recommended that anyone interested give it a try.
The value of this challenge wasn't just proving "you can learn without AI" — it was the authentic recreation of the full emotional journey of self-teaching an unfamiliar language: repeatedly chewing through syntax details, painstakingly digesting low-level concepts like ownership and borrowing, and the grind of debugging alone after a poor technology choice. For developers accustomed to AI autocomplete, this "fully manual" process is actually better at exposing knowledge gaps and genuinely building the skills of reading documentation and solving problems independently. Understanding low-level mechanisms like the ownership system, in particular, requires repeated failure and hands-on debugging — precisely the steps that AI autocomplete makes it easiest to skip.
Worth reflecting on: choosing an engine like Rusty Engine with scarce community resources did build the skill of grinding through documentation, but it forced a sacrifice of design goals on the texture-switching problem. This is a reminder that in rapid prototyping, ecosystem maturity is often just as important as the technology itself.
Key Takeaways
Related articles

Pinery Prose: Redefining the AI Book-Writing Experience with Diff Review
Pinery Prose is a Mac AI book-writing assistant using code diff review mechanics, letting authors accept or reject each AI edit. Supports Markdown, ePub/PDF export, and covers the full self-publishing workflow.

How Developer Productivity Startups Boost Their Own Efficiency: Practicing What You Preach
How developer productivity startups practice what they preach—from automated toolchains and DORA metrics to engineering culture that shortens feedback loops and reduces cognitive load.

Laxis Review: Bot-Free Meeting Notes & Real-Time Translation AI Tool
In-depth review of Laxis AI meeting tool: bot-free recording, 100+ language real-time translation, voice dictation 4x faster than typing. Features, competitors & value analysis.