Hacker News new | past | comments | ask | show | jobs | submit login
24 Hours of Rust Game Development (iolivia.me)
204 points by oliviff on Mar 4, 2019 | hide | past | web | favorite | 70 comments

It is fine that people are experimenting with putting graphics on the screen and playing with new languages.

But I just wanted to comment that you don't need an "Entity Component System" in a game, and especially not for a very simple not-yet-a-game like shown here. (You also don't need inheritance or composition).

It bothers me that so many people are buying into this hive-mind marketing on ECS, when in reality it is just overengineering + procrastination in almost all cases.

(None of my games have ever had anything as complicated as a component system).

If you want to make a simple game like this, just sit down and program it in the obvious way. It will work. You don't need to be fancy.


Like you, I've seen both sides. Unreal lineage evolved from inheritance-based into ECS-like. Frostbyte is heavily ECS.

Googling... the author is ex-amazon, ex-microsoft - with xbone and 360 title experience. Perhaps the author was exposed to that pattern at one of those institutions, or perhaps the author saw the 2018 Rust Conf Closing Keynote[0] and was inspired to continue down that path.

I think people tend to either go with what they've seen work in the past, or heard works well. Maybe it's cargo culting, or maybe in the case of rust (which I have no current experience with), it helps? Either way, the most important point is to focus on the fun and not let technologies get in the way of making a good game.

[0] - https://www.youtube.com/watch?v=aKLntZcp27M

For some people (myself included) the technology is part of the fun. The cargo cult popularity can definitely influence the decision to play with the technology, and by no means does it indicate that it is entirely appropriate for the task at hand. I personally use it as an exercise to familiarize myself with the patterns in a toy environment, which leaves me better equipped to apply them for a problem that lends itself to the technology. It also helps in preparing me to find those applications with a better understanding of the costs and semantics. While the knowledge may not be used for a practical purpose, at the end of the day, I learn something new, and I have a new way of looking at problems and understanding how to solve them with fresh perspective.

I agree.

It's definitely fun to play with new programming languages and technologies. Using games as a medium to explore a new language is a great way to learn and have fun at the same time. That said, when a game development luminary like jblow takes the time to make a comment, it's good to think about why.

It seems to bother jblow that people are buying into the use of this system without thinking about the costs as well.

Its the same as the debate about when it is the right time to move to a distributed microservice architecture from a monolith. In this case, the use of an Entity Component Systems in a small game could be compared to the choice to use a Distributed Microservice Architecture for a small application.

Monolithic applications are easy to build and maintain by a small solo developer/shop, but they don't scale as well as you increase the number of engineers and expand the scope of the product. So a monolith is split into domain specific distributed microservices to allow for an increased number of developers working in parallel. When you pick to employ this tactic is up for debate.

Building a distributed system is hard. Debugging a distributed system without solid tooling/tracing is even harder. In the microservice world we have a lot of tooling to help us. Games, usually much less so. Where you might use GRPC in microservices and have stuff like OpenTracing to lean on, in games with Entity Component Systems you'll usually have some form of a message bus/event system without the same level of tooling and tracing.

Entity Component Systems/Distributed Systems are a useful pattern to implement when your desire is to build a reusable generic game engine/application to be implemented by large or scaling engineering teams. That's why you see these patterns employed and used by large game companies/startups and game engine/SaaS developers.

In summary, perhaps jblow's point is that small/solo developers can build a good game/application without employing the ECS/distributed microservice architecture pattern. And like you said, it's also useful to try building/using these patterns in toy applications to gain experience.

I'd say the gulf between monolithic and microservice architectures is much wider than between ECS and non-ECS in games. The cost of microservices is much higher than that of ECS.

While building a game using some inheritance based approach, one will quickly hit limits even with a single engineer, whereas a monolithic web app can scale to a team of a couple dozen engineers easily.

The idea that you would “quickly hit limits” on a 1-programmer project is completely baseless. In fact a 1-programmer project is easier without an ECS as it’s one less system whose constraints you would have to comply with at all times.

Please stop saying this stuff as it just contributes to the general confusion.

You don't have to use an inheritance based approach if you don't make it an ECS. The point is that using any "something-based" approach is not necessary for most small and even medium sized games. Just make what seems obvious until it doesn't work and then change it. If you start thinking about architecture from the start you will have an issue when you find out it won't work for your project no matter the architecture you are using.

Especially ironic given that Rust's default package/project management tool is named 'cargo.'

>If you want to make a simple game like this, just sit down and program it in the obvious way. It will work.

I have heard that the restrictions imposed by the Rust compiler make it surprisingly hard to get it working the normal way. The first time I heard of ECS was in a Rust talk about how it helped them stop fighting the borrow checker.

For a simple game it seems like you could get away with vectors of mutable structs. This looks like ECS where one entity has a single component and there are only a few systems that update them (update, draw). For simple games you can do the old-school arcade style model with memory allocated upfront for everything (giant mutable gamestate struct) which was called out as not scalable in the talk but it worked for countless classic console and arcade games and scales all the way to Call of Duty. Another option is to avoid mutation and go for a functional style where you return a new game state struct after update (drawing probably shouldn't need to mutate), which might not scale for large games but is completely reasonable for small games without much state.

I suppose you can have a giant game state and return a new immutable copy on every frame if the amount of change is small, and you reuse most of the unchanged state.

> hard to get it working the normal way

This is mostly for complex games, otherwise for simple stuff there are ways to get it working.

I'm sure there are plenty of people out there who have a knee-jerk "ECS can solve that" reaction, but also be careful that you're not yourself just having a knee-jerk reaction here.

A full-fledged ECS can in fact be very helpful when writing game jam style code and you need to quickly iterate on ideas. Separating each unique idea into components (health, movement, ammo) and systems (physics, damage, AI) lets you turn things on and off, add new things (powerups that work on anything with health!), remove old things, all while everything keeps working in general. Closer to the end of a game jam you can also start playing with novel ideas (what if I make all bad guys suddenly start considering each other as enemies?)

If you can quickly iterate with a component system, you can iterate even faster just with regular procedures. Component systems aren’t magic (in fact they introduce friction).

They're definitely not magic, but they're also not just friction on top of regular procedures. They have use cases and used correctly they make a game mechanics into composable and configurable puzzle pieces that are easy to move around. Things that are much more difficult when you write all your game code into a classic run loop.

I think the debate here came down to whether a person who is inexperienced with either strategy for making a game is much more efficient with one thing or another, and I can't say that for sure. But I can say that in my experience the ECS pattern has had benefits for quick prototyping and experimentation, and shouldn't be dismissed out of hand in such a scenario.

This specific article starts with them doing a non-ECS design, and then running into problems, looking for the right solution, and having ECS solve them. I agree with your point that an ECS is not a one-size-fits-all solution (because nothing ever is), but this article is evidence that it can help even in some simple cases.

If I made a game though, it would likely be because I wanted to learn how an ECS works, or how to make an ECS, or how to make a game engine in general. Also I'd probably quit once the ECS was done but before anything was actually playable, because all the fun stuff (in my opinion) would be the technical plumbing and engine details, and not actually making anything creative with it.

As another example of this: I just bought a big DAW and a midi keyboard, and now obviously I'm stuck coding audio filters in Rust rather than making music.

hi, I'm interested in audio programming. Any tips/advice on a good starting point, etc.

If you are also interested in learning rust (as I am) you'll find an enthusiastic and new "RustDSP" community.

I'll mention that rust is young for this (e.g. VST dev), so if you don't want to learn rust but just want to get something finished - then Rust is probably not what you want. It's great for audio programming but the GUI buits are still immature.


thanks! I'll look into it

I'm kind of fascinated by the source code of this developer i found a couple years ago when exploring ECS: https://github.com/DaanVanYperen

Lots of interesting game-jam entries cranked out quickly using "pure" ECS : many small components, many small systems. Playable versions of some are here - http://www.mostlyoriginal.net/

I have been using specs ECS in rust for about a year and a half now and I think rust + ECSs work really nicely together.

However, I started with a simple stupid solution you describe. Despite that, I quickly realized I was going to end up coding an ad-hoc version of an ECS if I keep trying to do my own thing.

For reference, I am making a sim game like dwarf fortress so it has been kind of nice, though I think in the fullness of time I will probably end up writing my own ECS to replace specs or start contributing stuff to it.

I have used unity and UE4's "ECS" and I could see how they get a bad wrap. They aren't very good ECS systems and because the engine uses this model it forces people to use it.

One of the big advantages of writing a game from "scratch" is you are not burdened by weird architectures that don't make sense so experimenting first before makes sense. I don't know if I agree that ECS never have a place in game programming.

That is definitly true for your first game. My first game was written in processing, which is a wonderfully visual way of learning to program. Obviously I had a huge loop with a myriad of nested if statements.

Next thing I did was in Pyglet, this time I used Scene objectes that represented a statemachine that could switch arbitraily between other scene objects. Was much more comfortable to work with but slightly more complex. But where the real difference showed up was when I tried to extend: in the first thing I basically had to have all the code in my head, in the second I could just inherit from the Scene Class and make a new one with completely new rules.

If I were to do something now I would give a ECS a go, especially in Rust which really lends itself to ECS. I don’t think a ECS is any more complicated than relying on Object orientation. The problems you will have to solve with OOP will get incredibly hairy incredibly fast and I say that as someone who came to Rust from a OOP background.

Of course you can just use my first approach and write a huge loop with a lot of if else clauses and deal with every new thing in a new way.

This is the way I’d recommend it to a real beginner, who cares about pixels on the screen and doesn’t mind if they have to rewrite half of the code if they want to change or add a tiny detail.

You can have a non-ECS system without a giant inlined loop. If you look at an ECS for a typical 2D game what do you need? Components for: Sprites, Animation, Sound, Physics, Scripts, Pathfinding. All of which can be accomplished by function calls split up into separate source files. You can even begin with having everything inlined and pull the code out later once you've figured out what you want to do. ECS is overengineered abstraction to fit the set of all possible use cases instead of your specific use case. And if you write an engine that way you end up with an undebuggable mess of indirection for everything.

FWIW I don't think Jon is suggesting an OOP approach either. ECS advocates definitely promote that as the dichotomy though. There are lots of ways to structure game state without having to go the fine grained route.

Specially since many just learned it by doing, instead of reading the OOP literature regarding ECS systems.


ECS as meant here though is definitely imperative/functionally structured. Although there is a lot of familial resemblance with other component approaches.

SoA and AoS are othorgonal to components implementation.

Sometimes when you prototype something, half the reason is to try out these new fancy architectural styles :p

Usually it's for this kind of project: http://www.commitstrip.com/en/2014/11/25/west-side-project-s...

This is why discipline is the one thing that differentiates developers that release something and those that don't.

It's easy to try something new all the time, but it is tough as nails to stay with something even in the many cases where it sucks and gets difficult. Finishing something is it's own reward though, so even though it's tough it's always worth it.

By the obvious way, I'm guessing you would just have a single type 'entity' and put all entities in an array?

While that may be obvious to you, it's not obvious to a lot of programmers (myself included) who grew up learning about object orientation, abstractions and modelling behaviour on the real world. ECS's for all their added complexity come with the breath of fresh air that is classical imperative programming where all the data is just available.

There are scant few sources for learning this, Handmade Hero being a notable exception.

ECS builds up on protocol/interface oriented programming, where COM is the poster child how to organized such components.

There is CS literature about component oriented programming.

Component oriented programming seems to about about inherting only interfaces, but still abstracting the data behind function interfaces?

That's not at all what ECS's are about.

Component architecture doesn't specify how the data is stored, you are free to do SoA or AoS, depending on the case.

But but but... I thought game programming was 99% procrastinating?!

100% of my game programming is mulling over a framework to use

You’re doing it wrong then. It should be 100% spent on building your own framework. What game??

The python network library Twisted was originally written for a game they wanted to program. They never ended up writing the game.

Thank you guys you gave me a genuine big laugh. That said game programming is extremely hard. Probably the hardest IT field imho, so send my regards to all my fellow procrastinators.

Correct me if I'm wrong, but isn't ECS a really fitting architecture for a simulation/tycoon game? There are lots of entities and components that have to be updated and whose updates could be parallelized. Granted, the game in the post is far from a full-scale tycoon, but wouldn't it make sense to just start with an ECS if you're going to use it in the end anyways?

Reminds me of this article that was posted on HN a few months ago: https://www.gamedev.net/blogs/entry/2265481-oop-is-dead-long...

You don't need it to implement it a small-scope if the goal of your game project is to implement the game at hand. If the goal of your game project is to learn about tech and then use it on your main job, that's another matter.

On my job, I work on a Unity3d-based match3 mobile game. I am constantly running into game logic as a performance bottleneck – modern match3 games with "live" boards that you can play on while they flow is a combinatorial nightmare sometimes. Obviously, I can't rewrite already released project to take advantage of ECS, but I constantly toy with it in my free time so we don't run into the same problems in the future - without any desire to make a complete game with these toy projects.

I think you're talking about the new Unity ECS, which is a very specific implementation, while the OP talks about the general idea of composition via components, which is indeed overkill for many games.

If you're having an area of code which has a performance problem and can be isolated into a tight loop, the new Unity ECS is probably a good choice, but only in the specific context of Unity. And not because of the idea of "entities, components, and systems", but because the Unity ECS comes with a "toolbox" that makes it simple to run parallel code over flat arrays of structs, and with a limited C# subset created for writing high-performance code.

But it's important to note that outside of Unity, or other "behemoth engines" you can get close to that performance with a lot less effort, just by using a sane data layout and running your code in a simple loop (instead of running the same code in lots of tiny pieces interleaved with unrelated code, as is often the case with "traditional" entity-component systems.

I think a lot of game programmers that think this way and talk about tools and systems often don’t have a lot of artistic output themselves. That’s ultimately fine, but I think in order to be a somewhat accomplished game developer you have to somewhat give up an enthusiasm for novel programming.

EDIT: I should note that I am not accomplished as a game developer at all, so take my advice with a grain of salt.

Holy crap, you're the Braid and The Witness guy! Just wanted to say thanks for making some awesome games, and amazing experiences. Also, congratulations for The Witness selection for March PS Plus ^^

I look forward to supporting more of your work in the future, and introducing my SO to your puzzles.

Ah you are my hero for saying this, given that it comes from you.

Only partially related to the post topic, but this rust game project is worth checking out - https://github.com/citybound/citybound

Title seems to have been changed to meet the following rule:

> If the original title begins with a number or number + gratuitous adjective, we'd appreciate it if you'd crop it. E.g. translate "10 Ways To Do X" to "How To Do X," and "14 Amazing Ys" to "Ys." Exception: when the number is meaningful, e.g. "The 5 Platonic Solids."

However, I believe the "24" in "24 Hours of Rust Game Development" is pretty crucial.

Yup, we've added 24 back.

> ggez

Off-topic but that’s a darn nice name for a game engine.

Certainly ggez means “good game easy”. At least that’s how I read it.

Clever because “gg” and “ez” is gamer terminology used by people that play video games, with “gg” meaning a match was good (equivalent of “thanks for the match”) and putting them together you get a new meaning which is that it will be easy to create a good game.

"gg ez" is a taunt some players use when they win. Overwatch chat infamously auto-replaces that phrase with messages like, "I'm wrestling with some insecurity issues in my life but thank you for playing with me."

That being said, it is a clever name for an engine for the reasons you stated. And it's short, which is always nice.

I have been playing OW on and off for ages and didn't know that. Thanks!

I picked the name because the parts themselves are indeed what you said but when provided in combination it's a bit of a mean thing to say to say to the other team as you proclaim your easy victory in the context of online games. Sometimes it's also used ironically after the end of a long drawn out game that quite obviously wasn't easy for either side.

However, I was aware of that and decided to instead embrace it as a tongue in cheek kind of thing as I wanted to make a love2d clone and love is all about nice things so I wanted to make a game framework with all of the mean things. Hence why the logo is a salt shaker.

I never thought icefox would grow ggez into what it is otherwise I might have picked a less mean theme but maybe not. :)

Interesting and makes sense I think. Thanks for giving this background info on the name :)

The trouble is, `gg` means `good game` and `ez` means `easy`. But `ggez` means `you suck and I'm better than you`.

I'd have to look up the error code to be sure but I think the borrow checker emits that one occasionally.

Well deserved upvote.

Still works because your adversary in this case is the game you want to play not existing. So you can make a good game easily and taunt your defeated adversary. It works on a bunch of levels.

Hm, I only knew about the individual meanings of gg and ez, didn’t know they were already used in conjunction and with such negative meaning. That’s unfortunate :(

This brings some memories. When I was at HuffPost, we had a tool (to provision AWS resources) named AWSHeet, which we read as "aw shiiiit".

ggez means your team sucks.

The challenge is gathering consensus on how to pronounce it :p

Gee gee easy.

"Oh Jeez", Morty-style.

"ggez" is what someone says to piss you off, kind of like "haha, loser, you suck, beating you wasn't even hard". People who say this are trash, and it's a big part of the reason why I disconnect from games seconds before I lose.

It is not a good name for anything.

You seem disproportionately angry about this because of your personal experiences.

It means you can create a "Good Game Easily"

I've not been on the receiving end of `ggez` in online games, and it wouldn't really get to me if I were. (I should note, I also have not been on the sending end. Just preempting that question...)

That said, I don't think it's reasonable to pretend it's not a common, rude saying in the online gaming community. It absolutely is. And the online gaming community and game development communities are inextricably linked, like it or not.

I avoided even starting to look into `ggez` for a long time because I assumed a frat bro culture around it, entirely because of the name.

I don't get that feeling from using it, from reading the documentation or reading issues on Github. (though it's been awhile since I did any of those things)

But because it's named that, potential contributors and users are going to skip over it for Amethyst or Piston because they don't start off alienating people just from their names.

It means that as much as "Sieg heil" means "hail to victory" and is an appropriate thing to say before a football match.

You can't just take an existing phrase and pretend it doesn't mean what it means and feedback of the current meaning as "personal experiences".

Dismiss* feedback, missed a word there.

While working through your experience with Rust, would you mind writing down (doesn't have to be more than a couple of words and maybe a code snippet) diagnostic errors that were hard to understand or that were misleading? That feedback is invaluable in making rustc friendlier.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact