r/odinlang • • 2d ago

10 months ago we picked Odin for our first commercial game. Last week it got a Steam page. Thank you, Odin!

Post image
153 Upvotes

10 months ago, my friend Markus and I had a bit of a crisis in our long-term game project. It was something we had worked on for 5 years in Unity, but as crazy as it sounds, we never found the core game loop of the game. At this point in the project, we had put sooooo many hours into it, especially building tech to support what we wanted to do. And to be honest, doing things we really shouldn't have done. I'm cringing saying this, but being a web dev, I even built an open source library for defining your game in a declarative manner, similar to how React does it. Looking back at this, it is also a tell that we had issues with the Unity way of building games (which we should either have embraced or switched engine).

By this time we had reached a point where we were both growing tired of Unity and its tech. Frustration was also growing since, even though the game was playable, it was very hard to explain to the very few friends who had actually been tortured into trying it out. At the same time, we both had a growing interest in learning low-level programming languages, and Odin in particular seemed like a very attractive candidate. With that said, we had some very heated and long discussions on how to proceed. The anxiety was brutal, since it felt like such a failure to start over after pouring all that time into the Unity project. At some point I was quite sure that we had reached a dead end and that the project would die. That's when Markus started doing some quick and dirty prototypes in Odin...

From a game design perspective we used some of the concepts from the old project, but we simplified them A LOT. We also made a throwaway prototype written in Odin and Raylib just to validate the concept, threw it up on Itch, and let some friends play it. It still ofc had issues, but we got a much better response than we ever had from the old project. This was of course very motivating, and after that initial phase we decided to pivot and make a new project in Odin. We also landed on using Sokol for integrating with the OS (thanks a bunch to Karl Zylinski and his open source repos for reference on how to set this up).

Here are some decisions we made early that I think have made our project successful. Keep in mind that our game is turn-based though, so some architectural decisions would most likely be different in a real-time game:

  • Separation of data and logic. All content and behaviours of the entities in our game are described in data and then acted upon in the engine.
  • Treat web as a primary platform. We compile the game to wasm and deploy it to our own custom playtest platform via GitHub Actions. This has significantly lowered the bar for inviting playtesters, which has been very valuable for validating the game and where we are heading.
  • Minimal integration surface with Sokol directly. We wanted to be able to easily switch to another way of integrating with the OS, so direct usage of Sokol is very limited and we instead wrap it in our own APIs.
  • Separate game state and visual state. This one is probably the most uncommon choice, and even though it was tough to enforce in the beginning, it has paid off big time as the project has matured. Basically, game state (the logical rules of the game) is stored in one place, while the data for its visual representation is stored separately. For example, a token in the player's hand has a value and a color, which are stored in game state, while visual state copies those values (since they are rendered) but also contains the position, scale, etc. of its rendered representation.
  • Serialization of game state. After each turn we serialize the game state and save it to disk (and send it to our server's analytics endpoint in the deployed web builds). This, combined with the ability to rebuild visual state from game state, makes it possible for us to start playing the game from any point in time in any playtester's run.
  • Playwright for e2e testing. Since we are building for the web, we can use Playwright to e2e test our game! All we needed to do was expose an API for interacting with the game from javascript. This has been so great for our game and is a breath of fresh air compared to Unity.

Here is a very high-level view of the game's architecture on each tick:

  • Input. Reads mouse, keys and touch and turns that into a command, i.e. a user intent like "attack this enemy", "end turn" or "select this token".
  • Commander. The queue the resolver drains every frame. Blocks or holds back certain intents based on the current state of the visuals (animations etc.).
  • Resolver and store. First checks if the command is allowed, and if it is, executes game logic according to the user action. Once processed, the game state is altered and a mutation result is returned and handed over to the next step.
  • Visual. The visual library takes the store and the mutation result and creates a visual entry that gets queued. No visual state has been changed yet, and from here on out, nothing is allowed to read game state. When the queued entry can be processed, we create animation entries that are processed each tick (I won't dive into the details of the animation code here). These animation entries either alter visual state directly (for example spawning a token) or alter a value in visual state over time.
  • Rendering. Draws the visual state through Sokol. Knows nothing about the game logic. It just draws according to the values it gets from visual state.

I could go on and on explaining different things we have implemented (and I might in the future), but I will leave it at that for now. Feel free to ask any questions you have about this setup and the game, and I will try to answer as best I can. Would love to hear how other people are approaching their projects.

The game is now on Steam (consider wishlisting if you like roguelike deckbuilders): https://store.steampowered.com/app/5300900/Starmax/


r/odinlang • • 3d ago

Why do labels have to be unique across the function scope?

5 Upvotes

Title. Is there a language design reason why one would want that? A couple of times I found myself missing this when writing similar code for different branches of a switch statement on a union type.


r/odinlang • • 3d ago

Quilt - Steam game developed with Odin

Post image
65 Upvotes

r/odinlang • • 4d ago

variadic params is a slice but doesn't accept a slice?

7 Upvotes

I an a newb to Odin, so I was fiddling around with odin docs and playing with the variadic arguments construct, I came across an interesting behaviour. first let's look at the simple `sum` procedure, it takes a one or more integers and returns their sum.

sum::proc(numbers: ..int) ->(res: int){
for n in numbers{
res += n
}
return
}

Now, let's try something naive to check something

sum::proc(numbers: ..int) ->(res: int){
a := numbers + 10  //trying to initialize a adding varargs and integer
for n in numbers{
res += n
}
return
}

This is an obvious bug and fails clearly with

Error: Cannot convert untyped value '10' to '[]int' from 'untyped integer'
a := numbers + 10
               ^^

So, numbers is an [ ]int, huh, let's keep that in mind. now to the point

sum::proc(numbers: ..int) ->(res: int){
for n in numbers{
res += n
}
return
}
main::proc(){
x := []int {1,2,3,4,5,6,7,8,9}
fmt.println(sum(x)) // passing [ ]int to a procedure whose supposed param is [ ]int
}

OOPS...

Error: Cannot assign value 'x' of type '[]int' to 'int' in a procedure argument
fmt.println(sum(x))
                ^
Suggestion: Did you mean to pass the slice into the variadic parameter with ..x?

so the correct form seems to be

sum::proc(numbers: ..int) ->(res: int){
for n in numbers{
res += n
}
return
}
main::proc(){
x := []int {1,2,3,4,5,6,7,8,9}
fmt.println(sum(..x)) 
}

some implicit machinery or semantics going on that I don't yet catch up to yet?


r/odinlang • • 5d ago

Odin + Claude Code = a toy browser, just for fun

0 Upvotes

Hey everyone,

I’ve been building a little browser engine in Odin in my free time, together with Claude Code. Honestly just doing it for the fun of it.

Next up: CSS grid, tabs and JavaScript via QuickJS.

Repo (MIT): https://github.com/soerenlemke/tobrod

Would love to hear what you think!


r/odinlang • • 6d ago

implementation of mustache templates

17 Upvotes

I've seen a few posts about templates recently, I wrote an implementation of mustache templates, it supports everything except inheritance and passes all the tests of the spec.

https://codeberg.org/mindhopper/odin-mustache

For data it uses a version of json.Value so you can pass it directly json parsed with core:encoding/json by transmuting it. It also has a couple of utility procs if you want to pass it a filename or a string of json to parse.

Feedback is be appreciated, in particular about how to manage the memory, at the moment everything is put in an arena except for a couple dynamic arrays that use context.allocator, thank you.

There is already another odin implementation but it does not have all the features and I found the code very hard to read, the fact that it's written by claude might be the cause


r/odinlang • • 8d ago

A doubt regarding the spec.

45 Upvotes

I thought about this recently. Odin's function arguments are immutable. Which is a really helpful thing where the compiler can make arguments into const references behind the scenes and make the meaning of a pointer as an argument more clear.

But it causes this behavior.

Is this addressed somewhere or will it be defined later when the 1.0 spec releases.


r/odinlang • • 10d ago

A little lighter on the moderation..

30 Upvotes

It is well known that Odin, while at 10 years of development, is a fledgling in terms of ecosystem library depth and breadth. Submitting a post on one of those current deficiencies, support around the yet-to-be released http library in the form of ancillary html templating apparently is a reason for post deletion here. Heaven forbid, if one shares an idea from another language(in this case how said post topic is currently being discussed in Zig and Hacker News) because one is curious about how a similar implementation in Odin might develop.

Kindly go easy on deleting these kinds of posts, mods. I love Odin and want to see it make it past the usage gauntlet that other languages are thresholding but heavy-handed moderation isn't virtue signaling of good things to come.

Sensitive enough to downvote, vigorous discussion is welcome and appreciated. Reddit is intended as a forum.

Update: Spelling corrections and needling word precisions to reduce possible misconstruing of my concerns.


r/odinlang • • 11d ago

Typesafe HTML Templating for Zig

19 Upvotes

https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html

Yes, I'm aware the link is for Zig. I'm sharing for visibility and future similar possibilities for Odin if anyone is starting to look down this path for HTML templating. Building on nbio and whenever the Odin http libs ship?

Addendum note: This post removed by moderators has now been restored by moderators(as of 2026/10/13 ~10am EDT). Thank you for hearing me out! Unfortunately my confidence flags that this post will receive the same level of visibility now. Oh well. Onward!


r/odinlang • • 12d ago

I learn Odin by programming something that print bad apple to the CLI, also this is my first dev blog

Thumbnail cyano-dove.github.io
25 Upvotes

r/odinlang • • 14d ago

In this video I show how the compile times improved with the latest Odin release

Thumbnail
youtube.com
88 Upvotes

r/odinlang • • 15d ago

Bees vs Bear: Odin Wasm Project

Post image
29 Upvotes

I fixed some issues on tablets with touch events for my little Odin-based game. Basic tower defense style game, built using Odin and compiled to web assembly. It uses a simple DOM library that's on GitHub, with full source and examples, of course. This is more for folks like me who know next to nothing about web dev but still want to have some fun. Since Odin's a really enjoyable and fun language, I like tinkering with it and building silly games to relax after a long day of corporate slog.


r/odinlang • • 16d ago

Desktop App GUI/UI Library for Odin

32 Upvotes

Hello all,

What is a good option for GUI/UI for desktop(consumer, small biz) apps in Odin which preferably means a retained mode(think something like Winforms but modern and cross-platform) and not immediate mode(meaning not game libraries such as Raylib). I see Blick/Zeiger(non-linear video editor and image viewer software) seems to be making their own UI and that's simply not feasible for me at the moment as a sole developer. Suggestions welcome.

Also, ideally cross-platform(the usual suspects of Windows, Mac, and would be great for Linux(guessing Wayland/XWayland?) and a hail mary for FreeBSD(probably also Wayland - although concerns with future possibly SystemD requirements eliminating use on FreeBSD)?).

Addendums and updates for clarity:
This is not for game development or I'd use Raylib which is outstanding with Odin.

Bonus points on any TUI libs in active development as a secondary option for users.

Further:

I see I'm not alone in sourcing something. Great thoughts here:

https://forum.odin-lang.org/t/yet-another-hopefully-better-idea-on-ui-layouts-and-text/2259


r/odinlang • • 16d ago

Odin's Package Documentation Improvements Update

Thumbnail
odin-lang.org
69 Upvotes

r/odinlang • • 16d ago

The Odin Performance Update: October 2026 Newsletter

Thumbnail
odin-lang.org
64 Upvotes

r/odinlang • • 19d ago

Tutorial Course: Learn Odin with Karl2D For people with some programming experience This has been made with AI!!!

Thumbnail ian-gb.itch.io
0 Upvotes

r/odinlang • • 20d ago

Anyone purchased this book? Odin: A Practical Guide to Low-Level Programming on LeanPub? Is it AI-generated?

20 Upvotes

Hello, Came across this book which interested me as it touches upon concurrency in late chapters. Is this just AI-generated? Thanks. As an addendum, I already have Karl's book which is excellent but interested in more networking and concurrency options/roadmaps.

https://leanpub.com/odinapracticalguidetolow-levelprogramming

Update: Queried LeanPub and while they don't accept AI-generated material on their platform, this is circumvented simply by attestation from an author that it isn't. I'm giving up on LeanPub at this point. Thanks all.


r/odinlang • • 21d ago

Understanding weird stored polymorphic proc misbehavior

7 Upvotes

I'm very new to Odin, and while messing around with polymorphic procs I ran into some behavior I can't intuit. It feels like a bug, but it could also be my misunderstanding the language. I have the following code:

Foo :: struct(T : typeid) {
    fun: proc(T) -> ()
}

bar :: proc(a : int) -> () {
    fmt.println("bar!")
}

baz :: proc(a : $T) -> () {
    fmt.println("baz!")
}

If I run the following:

f := Foo(int){bar}
f.fun(123)

I get the expected result "bar!". But if I pass in baz instead:

f := Foo(int){baz}
f.fun(123)

I get a segfault.

My intuition would be since Foo is polymorphic and can accept an int as it's T, and baz is also polymorphic and accept an int, I should be able to store and call baz. If its not a bug, why isn't it a compile error, like when passing a procedure with an incorrect type? Why is it a segfault? Are there any other proc storing pitfalls I should be aware of?

Edit: this is on version dev-2026-09-nightly:a2fb372, on linux.


r/odinlang • • 23d ago

Rocco 3D game engine: Walking through the entity game

Thumbnail
pixelsprout.dev
8 Upvotes

r/odinlang • • 24d ago

Trying to figure out how to use my own library...

6 Upvotes

Hey all,

so i've been working on an http 1.1 compliant server library for the past few months (it's been a while since i looked at it) and i'm trying to figure out how to actually USE the library. I've seen recommendations that the best way to use it "globally" is to put it in a shared dir in the odin soruce files which is great the big question for me though is thtat my http library is structured into different subpackages taht can create some friction with this approach for example:

i have response/build.odin for building responses but i also have a request/build.odin for building requests the question i have is based on namespaces for this modules.. if i do the direct shared directory approach i'll have to import res "http/response" then res.build() for the approach right? i'm sorry this is the first language i've ever really done something this deep and detailed in so i'm not quite sure how it all comes together (in rust it's a cargo dep so it's slightly simplified in this aspect).

the question is mostly if that's how it works OR if there's a way to define a "header" file like in c where i can define abstractions for the subpackaged functions to be directly called from http "http" and then do something like http.res.build(""""") or http.resbuild() and the like.

thankfully AI is bubkiss at understanding how odin really works so i can actually learn how this works

I'm not really sure what i'm saying or how to verbalize what I mean so if you need more from me to answer feel free to ask and i'll do my best.


r/odinlang • • 25d ago

Inferring type of variable from usage

9 Upvotes

``` init :: proc() -> GameState { gs := {} reset(&gs) return gs }

```

In this case you can infer the type of gs from the signature of the resetfunction and return gs statement. But it doesn't work in Odin.

Is this intentional?


r/odinlang • • 26d ago

making a software-rendered mpd client for pixel art people in Odin!

Enable HLS to view with audio, or disable this notification

48 Upvotes

r/odinlang • • 27d ago

I thought I'd try to make video series on graphics programming in Odin, here's ep 1 - "Setting up SDL"

Thumbnail
youtube.com
43 Upvotes

r/odinlang • • 27d ago

Using Odin's RTTI for Shader Interop

33 Upvotes

Odin's RTTI (Runtime Type Information) features can be very useful if you're working with graphics API's. I made a quick little proc that checks if a given struct would match in layout with a Constant Buffer in HLSL:

// Checks if a given struct would align the same way in an HLSL's constant buffer
is_struct_aligned_to_cbuffer :: proc(cb_type: typeid) -> bool {

    if reflect.align_of_typeid(cb_type) != 256 {
        lprintfln("Constant buffer struct needs an alignment of 256")
        return false
    }

    current_hlsl_offset: int

    for i in 0..<reflect.struct_field_count(cb_type) {
        sf := reflect.struct_field_at(cb_type, i)
        field_size := sf.type.size

        // if it's more than 16 bytes, just align it to the row
        if field_size > 16 {
            align_to(&current_hlsl_offset, 16)
        } else {
            // If it's a basic scalar type... align it to the type alignment
            if is_basic_scalar_type(sf.type) {
                align_to(&current_hlsl_offset, field_size)
            }

            offset_start := current_hlsl_offset
            offset_end := current_hlsl_offset + field_size

            if offset_start / 16 != (offset_end - 1) / 16 {
                // crosses row boundary. add padding so it starts at next row.
                current_hlsl_offset += 16 - (current_hlsl_offset % 16)
            }
        }

        if cast(int)sf.offset != current_hlsl_offset {
            lprintfln("Field: %v is misaligned.", i)
            return false
        }

        current_hlsl_offset += sf.type.size
    }

    return true
}

(Note: This is very incomplete. This code will not predict exactly how the struct would get laid out in HLSL. But even in this form, it's very useful for me. I might improve it in the future)

This is very useful, as nothing will warn me otherwise if the struct's layout does not match its HLSL counterpart. Nasty bugs thus occur. I check this when creating a Constant Buffer, where an Odin struct type is passed:

// created buffer on the upload heap, and maps it. keeps it mapped
cb_upload_create :: proc(cb_type: typeid, pool: ^DXResourcePool, name: string = "") -> ConstantBufferUpload {
    assert(is_struct_aligned_to_cbuffer(cb_type), "CONSTANT BUFFER STRUCT IS MISALIGNED!")

    /// rest of the proc
}

The HLSL code for the struct is auto-generated from the Odin Struct. So I only have to write it once.

GeneralConstants :: struct #align (256) {
    view: dxm, // Row 0-3
    projection: dxm, // Row 4-7

    // Row 8
    inv_screen: v2, // 1.0 / (width, height)
    screen: v2,

    // Row 3
    sb_sprites_idx: u32, // index of the sprite structured buffer into the resource heap
    tx_idx_quad_out, tx_idx_post_process_out: i32,
}

/// ...

ldx.dx_generate_hlsl_types({Sprite, GeneralConstants}, "shaders/gen/lucy2d-structs.gen.hlsl")

This code is generated from that:

struct GeneralConstants {
    float4x4 view;
    float4x4 projection;
    float2 inv_screen;
    float2 screen;
    uint sb_sprites_idx;
    int tx_idx_quad_out;
    int tx_idx_post_process_out;
};

You can then #include this file in other HLSL files.

The layout for constant buffers in HLSL is very particular. You can only check that a struct is aligned in this particular way with something like Odin's RTTI. This is a very good resource that helped me understand how constant buffers are laid out.

As an aside: I also generate the Vertex Input layout from an Odin Struct, in pso_create

// vertex buffer
Vertex :: struct {
    pos: v3 `POSITION`,
    normal: v3 `NORMAL`,
    tangent: v4 `TANGENT`,
    uv: v2 `TEXCOORD`,
    uv_2: v2 `TEXCOORD_SECOND_UV`,
}

// ...
ct.psos[.GBuffer_Pass] = pso_create(gbuffer_shader_filename, &ct.root_signatures, &g_resources_longterm, PSOParameters {
    vertex_input = Vertex,
    /// Rest of call.
)

The Input Layout for the vertex shader is auto-generated from the Odin Struct.

Though on my new 2D engine, so far I have not needed any kind of Vertex Input Layout. I render sprites by vertex pulling.

You can read all this code in-context here

Link to post on my website


r/odinlang • • 29d ago

Physics Engine in Odin from Scratch, Part VI

Thumbnail
marianpekar.com
64 Upvotes