10 ms·
Reflecting on a Year of Gamedev in Zig
- Zambyte 1y agoNot sure why this was flagged. It was an interesting read, thanks for sharing. My biggest concern with using Zig has been the breaking changes that you mentioned, but I have been pushing forward with it for personal projects because it just seems like people are able to work around them easily, like you mentioned.
- bgthompson 1y agoYou're welcome! My experience with the breaking changes in Zig has not been bad at all. For brevity in the blog I didn't get into what I had to do to get things working again, but the process itself was straightforwards. Sometimes the names of some standard library functions had changed, sometimes it was some extra fields in the build system. Whatever the case, the changes were almost always documented in the release notes anyway, so after reading the release notes I basically knew the (small) amount of work I had ahead of me.
- thunkingdeep 1y agoAll posts not fellating Rust are eventually flagged here. It’s not really a neutral venue for more academic conversations about PLT.
- einpoklum 1y agoI would assume, that when developing a game alone, you would depend a lot on libraries other have written. Is the Zig ecosystem rich enough in this respect, at this point?
- dragonelite 1y agoYou can easily integrate any C library, so pretty much all the important stuff is available. You also have Zig-gamedev repo where you have community written zig wrappers for those c libraries.
- 59nadir 1y ago> I would assume, that when developing a game alone, you would depend a lot on libraries other have written. The guts of a game engine don't require any libraries at all. Using licensed offerings like havok for physics, etc., I don't think the language-specific part you might write (bindings, etc.) is a meaningful part of integrating the offering, and since they're licensed it's not as if you could just add them willy nilly in C++. You could argue that you'd want a language-specific library for some Steam SDK stuff, but AFAIK both Odin and Zig do have bindings for at least some important parts of these, and even if they didn't I don't think FFI is really that big of a problem in either language. If you use Odin everything you need in order to create a game engine is shipped with it via the standard library (`math:linalg`, etc.) and vendor libraries (`vendor:{OpenGL,directx/direct3d11,directx/direct3d12,wgpu}`, etc.). If you really do want to use libraries `raylib` is also included, as well as SDL.
- Keyframe 1y agoC interoperability is the name of the game with Zig, however there is a chance of reading article like "Moving away from Zig" in the future like we're seeing with Rust. At one point in time you have to decide whether you want to write a game or tinker with tech and engines. Both is absolutely fine, of course and most of us "get it", but it also depends on personal skills and pain and time threshold.
- flohofwoe 1y agoThe Zig compiler can compile C, C++ and ObjC, directly import C headers, directly call into C APIs and the Zig type system is very "C ABI friendly". So if something isn't available in pure Zig it's quite trivial to directly integrate dependencies that are written in C, C++ or ObjC (much easier than any other language I used so far). There's also a centralized effort to wrap C/C++ libraries into Zig packages so that they can be easily consumed in the Zig build system: https://github.com/allyourcodebase https://github.com/allyourcodebase
- bgthompson 1y agoUltimately, this will be determined by the scope of the project, and depends on whether you count using an existing C library as part of the Zig ecosystem. If you want Zig libraries that don't call any C/C++ code whatsoever, then you're going to have a hard time (as of 2025). There's not, e.g, something as mature and tested as glfw in pure Zig. There is work being done to make pure Zig libraries for gamedev however, see for example Mach: https://machengine.org/ https://machengine.org/ If you're happy to use C libraries though (as I am), then things are generally fine. Many of the most popular gamedev C/C++ libraries have already had their build systems converted into Zig (e.g. Raylib) and so can easily be added to a project without having to do any work in the build system. For C libraries that aren't already packaged, or if you want to maintain full control of the build yourself, packaging libraries with the Zig build system isn't too bad, but it's still a lot of work. (E.g. Ghostty maintains its own build files for its packages; as a result there is a lot of Ghostty build system code: https://github.com/ghostty-org/ghostty/tree/main/pkg https://github.com/ghostty-org/ghostty/tree/main/pkg )
- rob74 1y agoThe Zig Discord is a great resource for anyone learning Zig. At any given time, the zig-help forum is awash with questions from beginners like “How do you make for loop in reverse? or “What allocator to use in WASM?” Most get answered within minutes. Am I the only one who feels this is a step back from platforms such as Stack Overflow? Discord is basically just a chat platform, and while it's nice that there are always people there who are willing to answer the same questions over and over again, you can't rely on that staying the same in the future. Whereas SO crowdsourced a "canonical" answer to a question, and if someone came up with the same question later (and didn't find the existing answer via the search function or Google), they could be pointed to that answer.
- dragonelite 1y agoI agree i rather see all this discussion etc take place on dedicated forums or other text based options so search engines can index the stuff..
- interpol_p 1y agoTotally agree But once we opened a Discord for our product we had so many more questions and users coming in. I do not like that it is locked up on a proprietary platform organised as a chat interface, but damn is it popular and often-used. Having users communicate with us more regularly is very motivating, and we've had so much more quality feedback by having it available It is, unfortunately, where a lot of the people are and it makes your user base feel very "alive"
- jjani 1y agoWhy not use AnswerOverflow to make the chats indexed and searchable? It's definitely a lot better than nothing, multiple times it has already helped me find answers to questions I had.
- interpol_p 1y agoThanks for the suggestion! I had no idea this existed
- belst 1y agoDiscord (Chat in general) is really nice if you are the first to have a problem. If anyone else has the same problem, they can't find it by just googling tho. So they need to ask the same question again which gets annoying pretty fast unfortunately
- amoss 1y agoOn point 4, I don't use zig but a two second google leads to http://ratfactor.com/zig/stdlib-browseable2/math/atan.zig.html http://ratfactor.com/zig/stdlib-browseable2/math/atan.zig.ht... I wonder about the accuracy of the rest of the article.
- bsder 1y agoThe issue is that atan wasn't implemented for a comptime float. A "comptime f32" is different from an "f32"
- jamiejquinn 1y agoIf you don't use zig, you might have missed why that error indicates a stdlib bug. The error in the article is down to a quirk of the type system where literals (like the literal float) have their own unique type (comptime_float) that can coerce to related types (f32, f64) but in this particular case, when atan switches on the type, it doesn't explicitly include comptime_float and fails. Seems like an oversight in the stdlib to me.
- amoss 1y agoMissed all of that, thanks for the explanation. Why doesn't zig try and apply the coercion before the type switch - is this deliberate for safety?
- pcwalton 1y agoBecause "else" technically includes "comptime_float", so that case is handled, just not in the way that's expected. One of the downsides of comptime over generics is that, because it's low-level and procedural instead of high-level and declarative, things like automatically inserting coercions become harder.
- jamiejquinn 1y agoI'm not sure but I would guess it's in the spirit of Zig's "explicit over implicit" philosophy. They are technically different types.
- Ygg2 1y agoNot gonna lie, most of those things look like negatives. - Zig main source of QnA is a black box (Discord)? One that might be soon enshittified to hell because we have to satisfy the IPO. - Zig uses Gradle style approach to Maven. Having used Gradle, I honestly can't recommend it. Too much freedom in build pipeline leads to too many footguns. - Zig changes in big exciting ways, sounds like euphemism for breaking changes. Having those on framework level is tiring, having those on language level is hell.
- flohofwoe 1y ago> Zig main source of QnA is a black box (Discord)? The Discord is quite okay-ish for getting a quick answer for things you're blocked on. For proper discussions and deeper questions, Ziggit is a better choice (which is also a 'proper' forum): https://ziggit.dev/latest https://ziggit.dev/latest > Zig uses Gradle style approach to Maven. Zig's build system is conceptionally further away from both Gradle and Maven than Gradle is different from Maven (having to wrestle with both from time to time, my personal opinion is: both are a huge pile of excrement, unfit for real-world usage - even cmake is better than what the Java world accepts as build systems, and that's some achievement ;) At least the Zig build system looks promising in the way that simple things are simple and complex things are possible, even though the API still sometimes doesn't quite know if it wants to be imperative or declarative. But the basic idea is that the Zig build system and package manager are "just" part of the regular stdlib and that your build process is a regular Zig program that gets compiled and then executed to perform the build. > Zig changes in big exciting ways, sounds like euphemism for breaking changes ...which is completely expected of a pre-1.0 status. OTH, the last couple of versions were not worse than fixing new warnings after a minor C/C++ compiler update.
- Ygg2 1y ago> ...which is completely expected of a pre-1.0 status. I fully agree, but I assume you want to ship your game (i.e. its a game not a toy). At least to Windows. Building your game on pre 1.0 language is like building a house on sand that's being transported by a truck.
- dns_snek 1y ago
- jamiejquinn 1y agoSnap! I've been developing a roguelike in zig for nearly exactly a year and my experience is very similar. I especially appreciate your mentioning the positives that come with breaking changes. Seems like you're also a C/C++ developer so I'm curious: how have you found zig's comptime compares to templates? (Personally I've found it a refreshingly simple experience, if occasionally annoying due to pre-1.0 bugs)
- bgthompson 1y agoFor my (relatively simple) use cases, I've had a significantly better time using comptime than templates; the syntax and the quality of the error messages are a lot simpler in Zig. While I've never attempted to do anything super fancy with templates in C/C++, my gut feeling is that comptime can provide most, if not all, of functionality that templates provide. (But C/C++ template experts please chime in if this is not the case.)
- jvanderbot 1y agoFormer Cpp dev here. If I never have to debug a template barf it'll be too soon. By the end of my time in C/Cpp land I'd written more C than anything, with occasional "structs with con/de-structors". Happily the next gen of systems languages fit about in that niche already!
- andreldm 1y agoI think point 3 is completely off. That's not cherry-picking, that's comparing apples to oranges, those generated Makefiles are not meant to be readable, if you want to compare, look at configure.ac and Makefile.am. I also dislike CMake, but just saying it sucks is poor argumentation. Finally, in the title Ninja and Meson are mentioned, just to be completely ignored. I'm having a great experience with Meson, I would like to learn how the Zig build system is better than it, this piece unfortunately does not provide that.
- tuetuopay 1y agoI would go even further: showing the generated cmake file is like showing the disassembly from the zig snippet shown. I still think the point stands though: zig's build system is nicer. Still bad IMHO as I despise build systems where you describe the build in the same language. Most of the time, it's much better to have a declarative rather than imperative build system. All in all, Ninja/Meson/Cargo/etc are much better in this regard. (and yes, I think build.rs was a mistake, a necessary evil. Definitely not a feature)
- jvanderbot 1y agoI have never once had to make a build.rs file, except to make python bindings for some of my own rust libraries. Are people out here using build.rs for everyday driving?
- tuetuopay 1y agoBindings, and generally any form of code generation, is the most common form of build.rs I see in the wild. One such example of "daily driving" is for gRPC, where the canonical way to generate the protobuf and gRPC bindings using Tonic+Prost is through build.rs. Another is C-to-Rust bindings, for all of those -sys crates. Though I've also seen it used to circumvent limitations of Cargo, e.g. for invocations of dependent cargo build steps, etc. Overall, it's less common (or more robust?) than it used to be 5-ish years ago.
- 1y ago
- IshKebab 1y ago> After compiling the game with the flag -Dcpu=baseline, the binary contained only x86-64-v1 instructions, allowing my friend to play the game. Feels like the startup code should actually verify that it's running on a suitable CPU rather than just crashing. I don't think C/C++ or Rust do this either but they should!
- tuetuopay 1y agopretty much no language do this by default. however, most languages target the -v1 instruction set in 'release' or optimized mode. (e.g. Rust does this, and AFAIK GCC and clang both do this for C/C++)
- IshKebab 1y agoI tried Zig a bit and found it quite nice, but it is very low level. Like in Rust you concatenate strings like this: let result = format!("{a}{b}{c}"); In Zig it's something like this: const allocator = std.heap.page_allocator; const parts = [_][]const u8{"a", "b"}; const result = std.mem.concat(allocator, &parts[0], 2) catch @panic("allocation failure"); defer allocator.free(result); I dunno if I want to write any really significant programs like that. At least not any that use strings a lot!
- MawKKe 1y agoThere's also `std.fmt.allocPrint()` which functions similarly to `format!()`. Although I'd argue its rather poorly named, like many of the functions in the stdlib... For wanting to avoid fiddling with multiple repeated alloc/defer-free, it's often convenient to use the arena allocators that allow you to release everything with a single `defer arena.deinit()`
- unwind 1y agoI would (coming from a C background) guess that `allocPrint()` owes its name from the C standard library function(s) `as(n)printf()`[1]. At least that would make sense, the naming is modernized by being made longer, to gain clarity. [1]: https://man7.org/linux/man-pages/man3/asprintf.3.html https://man7.org/linux/man-pages/man3/asprintf.3.html
- bgthompson 1y agoMy game has a bunch of strings, and my string code currently looks very different to this! For example, copying two lines from source: var buffer : [64] u8 = undefined; const level_name_cstring : stringnt = std.fmt.bufPrintZ(&buffer, "{}. {s}", .{icon_index + 1, level_name}) catch unreachable; (Make the string "10. Fortress" from the int 10 and "Fortress") The reason is, most of the strings in my game are bounded, and actually, known ahead of time. None of the levels have names that approach anything as long as 64 bytes, so I can actually do a fair bit of string manipulation on the stack before needing to use / save it to an allocator. (At least for now before localization XD) So it depends on the use case. Sure, string manipulation in general can be tiresome in Zig, but in many cases it's also simple.
- sgt 1y agoZig is really HN's new love story, isn't it. Or quickly becoming... Rust is still popular but it turns out the developer joy is pretty low.
- ultimaweapon 1y ago> Rust is still popular but it turns out the developer joy is pretty low. Rust is one of the language I enjoy to use. The problem is you need to overcome its steep learning curve in order to enjoy it, which people tend to give up because it is too hard.
- jvanderbot 1y agoWhich to me is fine. It's not a great hobby language but it is a fantastic professional language, precisely because of the ease of refactors and speed of development that comes with the type system and borrow checker.
- pcwalton 1y ago> It's not a great hobby language but it is a fantastic professional language, I never thought I'd live to see the day when someone would say this. The first 5 years of Rust were all "this is interesting for hobby projects but nobody will ever adopt this in industry".
- christophilus 1y agoFor me, it wasn’t the learning curve that was the problem with Rust. It’s the compilation time. It’s just so slow. I’m used to OCaml, Go, and Typescript (via Bun or esbuild) with iteration times in the tens-to-low-hundreds of milliseconds. Zig still feels a wee bit slow, but it’s acceptable. Rust? It makes me want to toss my laptop into the fire. To be honest, I haven’t touched Rust in years, so it may have improved.
- steveklabnik 1y agoIt has improved continually over the years, but on the order of 3x-5x, and by the way you talk about it, you’re looking for 10x-100x, so I doubt it’s not still an issue for you.
- jvanderbot 1y agoFirst class SIMD vector support is awesome. The complaint about that not being first class matrix support kind of misses the mark: it's all vectors all the way down. This is one glaring omission from Rust. Their SIMD integration is library specific and patchwork but improving.
- lerno 1y agoOut of C3, Odin and Zig, Zig is actually the language with the worst SIMD support. Odin has SIMD vectors, array programming and built in matrix types while C3 has built in SIMD vector types and operator overloading for userland numerical types such as matrix and complex types. Odin and C3 has things like swizzling, assigning a scalar to all elements etc out of the box, whereas Zig is similar to C and just provides compiler builtins. Compare `vec * @splat(foo())` (Zig) to `vec * foo()` (Odin/C3).
- johnisgood 1y agoYeah I dislike Zig for all those "@()" stuff.
- CollinEMac 1y ago2. Zig has good builtin support for vectors, but not for matrices. Oh boy do I have the language for you. https://odin-lang.org/docs/overview/#matrix-type https://odin-lang.org/docs/overview/#matrix-type
- n_jd 1y agoIf you poke around you will find the author is already familiar with Odin. Might be interesting to hear why they moved to Zig.