Really interested in hearing more about the architecture. Especially (1) why you chose Elixir, Phoenix over TS (2) how you dealt with real-time multiplayer.
Aside: The links to the web game in the post don't lead to being able to play.
Not OP, but TS (as in TypeScript, right?) is not even in the same universe as Elixir with Phoenix when it comes to building backend services.
It's a very productive and readable programming language with excellent documentation and conventions, and the most ergonomic way of handling concurrent operations (thanks BEAM) I've encountered.
The VM it runs on was originally designed for telephone switches, which, it turns out, cleanly translates to the internet/http era.
It makes it trivial to do soft-realtime because it's just actors (GenServers) passing messages.
I invite you (and others) to try it out and do a small weekend project. It'll make you reconsider reaching for TS on the backend :)
not op either but I built my entire startup using elixir. We have a realtime sync component across a range of devices that sync data between them.
It (phoenix channels) worked out of the box. in the last 6 years of development and growth, not once have we ever had to even discuss scaling issues related to it.
It just works and when you're in a startup, the more you can focus on growing your product instead of scaling issues, the more you're winning.
I’d guess that 2 is a huge part of the answer to 1 here - Elixir makes real-time multiplayer easy.
Phoenix is delightfully fast and not having to deal with two entirely different application stacks where your application is split down the middle (or the javascript ecosystem) is a breath of fresh air.
Hi! I'm sorry I took down the web client shortly after I write this in order to narrow my focus on the client codebase. I realize I ruined my point about being able to compare the client performance. I'm editing the post shortly.
I've been curious about elixir for years. Since maybe 2016. I tried in the days before AI, but I couldn't really get over the hump of syntax and BEAM and all of that.
I'd read it was the kind of thing that would be good for games, but I didn't really understand why until AI helped me build this.
A room is a GenServer. Which means its a process. Which means the unit of gameplay matches the unit of compute, kinda. That's really great. You can't really do that with node. Well, I guess with Durable Objects / PartyKit you have a closer match there.
There is a matchmaker process that runs. It assigns your socket to a room. But yeah, after that, your socket is exchanging messages with that room.
Because arrow physics are simple, the client predicts how it thinks the server will say things will be, and reconciles if / when wrong when it hears from the server about the room state.