[HN Gopher] Hands-On Rust: Effective Learning Through 2D Game De...
       ___________________________________________________________________
        
       Hands-On Rust: Effective Learning Through 2D Game Development and
       Play
        
       Author : nallerooth
       Score  : 262 points
       Date   : 2021-10-14 07:59 UTC (15 hours ago)
        
 (HTM) web link (pragprog.com)
 (TXT) w3m dump (pragprog.com)
        
       | igh4st wrote:
       | The book sounds awesome to get your hands dirty with Rust :)
       | 
       | is there a promo code for Latin-american countries?
        
         | thebracket wrote:
         | I'm not sure what promos are active right now (I just got back
         | from vacation). It will be included in the November
         | Thanksgiving sales. You could also email support@pragprog.com -
         | they would be able to help.
        
           | igh4st wrote:
           | I'll reach out to them, thanks!
        
         | cultofmetatron wrote:
         | by any chance, can you reccomend a good book for learning
         | programming thats written for a spanish speaking audience?
        
       | myth_drannon wrote:
       | It's a great book but I struggled with an additional overhead of
       | ECS library usage. Don't know if it would have been better just
       | roll out it's own simple logic for ECS , but then it would
       | probably double the length of the book.
        
         | thebracket wrote:
         | Page count was a real concern. I wanted to introduce Rust
         | newcomers to easy concurrency, and keep the data-storage side
         | of things manageable (storing a big list of dynamic objects
         | with traits gets messy _fast_ and leads to a lot more borrow-
         | checker fighting). Using an ECS let me dodge the latter bullet,
         | at the expense of a bit of complexity. (I made sure Flappy didn
         | 't need an ECS)
         | 
         | Bevy didn't exist when I started writing, or I'd have probably
         | used it. Legion is a great ECS, but it's heavier than I'd like
         | - and Bevy makes a lot of things really easy.
        
           | TylerE wrote:
           | This concerns me a bit.. when I've made (failed) attempts to
           | learn Rust in the past the borrow checker was always the
           | sticking point.
        
             | baq wrote:
             | It needs a mindset change. The thing is trying to _help_
             | you. It points out issues that you didn't think about. It's
             | naturally difficult to think about things you've never had
             | to think about before. It also turns out that architecting
             | software in certain ways (like ECS) makes it easier to
             | think less about borrowing.
        
       | uDontKnowMe wrote:
       | Consistently interesting content coming out of Pragmatic
       | Bookshelf publishers these days. Recently, I have particularly
       | enjoyed the Ray Tracer Challenge
       | (https://pragprog.com/titles/jbtracer/the-ray-tracer-challeng...)
       | and Web Development in Clojure
       | (https://pragprog.com/titles/dswdcloj3/web-development-with-c...)
        
       | halvnykterist wrote:
       | I can't help but be heavily skeptical of approaches to a
       | (traditional) roguelike that use ECS. The idea is very entrenched
       | in the rust gamedev community, but for a turn based tile based
       | game there's extremely little benefit and a lot of added
       | complexity. Bob Nystrom has an excellent talk on roguelike
       | architecture [0] and rust as a language itself doesn't prevent
       | any of these approaches. If anything, the existence of sum types
       | as enums make many of them all the more powerful.
       | 
       | [0]: https://www.youtube.com/watch?v=JxI3Eu5DPwE
        
         | pizza234 wrote:
         | > The idea is very entrenched in the rust gamedev community
         | 
         | I don't think it's very entrenched, although it's certainly
         | present. The reason for this perception, I guess, is that Bevy
         | (which is based on ECS) is all the rage.
         | 
         | Amethyst was ECS as well, but it's dead now (and Bevy is
         | essentially its successor). Veloren is ECS though, and active.
         | 
         | The remaining major engine (AFAIK) is RG3D, but it's not ECS.
         | Macroquad provides a node graph (but it's a smaller engine).
         | 
         | All the other game engines are comparatively small, and they
         | don't provide storages/ECS engines.
         | 
         | (edit: added Veloren)
        
           | halvnykterist wrote:
           | I think Kyren's 2018 CustConf talk [0] caused it to become
           | popular earlier. Arewegameyet has an entire section for ECS
           | crates, with 10 different entries. I'm aware of multiple
           | smaller homegrown solutions, too.
           | 
           | https://kyren.github.io/2018/09/14/rustconf-talk.html
        
         | bcrosby95 wrote:
         | I've coded MUDs for about 25 years now, and I use a lot of
         | these patterns in my code. Nice to see someone else thinks its
         | useful.
         | 
         | I think a key strategy that is not touched on too much in the
         | talk is flexibility in your effect system, whatever your effect
         | system may be. It should be trivial to take an effect (heal,
         | damage, stat boost, etc) and let anything in your game apply it
         | to actors with just a few lines of code: items, spells, tiles,
         | regions, the whole game, etc.
         | 
         | As an example, lots of games will specifically give certain
         | classes hps/mana/better chance to hit/new skills as they gain
         | levels.
         | 
         | I just use my effect system for this. Now I can have items that
         | give skills too, because items use the same effect system.
        
           | dkersten wrote:
           | Do you know of any articles or resource that go into your
           | style a bit deeper? I'd love to hear more on how your effects
           | system works and how that compares to a component-based or
           | ECS architecture.
        
             | bcrosby95 wrote:
             | I wouldn't call it an architecture, more a goal. When I say
             | effect system, I just mean how you apply various effects to
             | your players/npcs. I wouldn't prescribe how to get there -
             | it could just be your component system.
             | 
             | For myself, I go at it from a baseline approach: effects
             | are one of the fundamental building blocks of the game. As
             | much as possible, if something in the game does something,
             | I try to do it through effects. This includes skills,
             | spells, weapons, armor, commands, AI, systems, etc.
             | 
             | If everything does everything through these effects, you
             | can make anything do anything in response to anything
             | without having to special code it.
             | 
             | I don't make it _that_ flexible for various reasons. But I
             | think it 's a good place to be philosophy-wise for
             | something like a MUD.
             | 
             | As an example from the video, there is an Attack, Use, and
             | Defense class that Items use, with specific attributes
             | assigned to them (armor, dodge bonus, min damage, max
             | damage, etc). With effects, you might have a list of
             | effects that trigger on wear, on attack, on activate, etc.
             | 
             | A common effect is a damage effect. You could make an item
             | that damages someone you hit with it (typical weapon),
             | damages you when you wear it, or damages a target when you
             | activate it. But you could do this with literally any
             | effect you programmed for any spell or command. You can
             | make an item heal you when you wear it. Or provides a heal
             | over time when you wear it. Or heals your target when you
             | hit them with it.
             | 
             | You can even combine them. I could make an item that, when
             | worn, transfers everyone in the game to the wearer's
             | location and kills them. I could do the very same thing for
             | a spell. Or when someone enters a tile. Or a command. Etc.
             | 
             | I can do this because there is an admin command that can
             | transfer everyone in the game to a location. It does this
             | by effects. I have an admin command that can insta-kill
             | anyone. It does this by effects. I can assign these effects
             | to any place that uses effects.
             | 
             | I arrived at this solution because, when working long term
             | on MUDs, I found myself coding the same thing over and over
             | for different subsystems for different content creators.
             | Ultimately my mantra turned into "non coders shouldn't need
             | coders to build new, cool things" and this is how I went
             | about doing that.
        
         | jyriand wrote:
         | Sorry, what is ESC?
        
         | modernerd wrote:
         | I think Jonathan Blow's take is right:
         | 
         | > ECS _only_ starts to make sense when you are big enough to
         | have multiple teams, with one team building the engine and the
         | other using the engine to make the game; or you are an engine
         | company and your customer makes the game. If that is not your
         | situation, do not rathole.
         | https://twitter.com/Jonathan_Blow/status/1427358365357789199
         | 
         | Most of the arguments I've seen for ECS in Rust suggest it
         | helps to work with memory management/borrowing. For example,
         | here's Patrick Walton's take:
         | 
         | > There's a reason why Rust game engines all use ECS and it's
         | not just because the traditional Unity OO style is out of
         | fashion. It's because mutable everywhere just doesn't work in
         | Rust. Mutex and RefCell explosion.
         | https://twitter.com/pcwalton/status/1440519425845723139.
         | 
         | And here's Cora Sherratt's discussion of ECS options in Rust:
         | 
         | > So why do you need one? Well all ECS developers will claim
         | it's largely about performance, and show you a mountain of
         | numbers to back it up. The more honest answer probably comes
         | down to the difficulty of making ownership work in Rust without
         | some type of framework to manage the transfer of ownership for
         | you. Rust punishes poor architecture, so ECS' are here to help.
         | https://csherratt.github.io/blog/posts/specs-and-legion/ (This
         | post also has the best visualisation and explanation of an ECS
         | I've read.)
         | 
         | I've read Hands-On Rust and you could definitely implement the
         | game without an ECS. But at the same time it was useful to play
         | with that pattern because it's in common usage in the Rust
         | community. (Bevy also makes heavy use of it, for example, where
         | it feels pretty lightweight because they made some good design
         | decisions: https://bevyengine.org/news/bevys-first-
         | birthday/#bevy-ecs.)
        
           | moth-fuzz wrote:
           | This is an interesting happenstance in the Rust community
           | that I think is largely cultural rather than technical.
           | Backlash against some figurative idea of OOP is popular. ECS
           | is popular as the messianic retort to that OOP figure. But
           | when you look at it from an architectural standpoint, ECS is
           | quite possibly one of the hardest things to do in Rust
           | compared to other designs. Let me get this straight - you
           | want to avoid shared mutability but you have _all_ your
           | gamestate in centralized stores? That systems will
           | necessarily have to have _shared, mutable_ access to?
           | Possibly concurrently? I think it 's a good idea
           | architecturally, but also I think it's a tough problem to
           | solve, and I think the claims that Rust lends itself to that
           | architecture are false. It's even tougher in Rust than in
           | other languages, I'd say. And though I've read the source
           | code to many Rust ECS libraries, they all do it in different
           | ways, and _all_ of them feel like hacks.
           | 
           | I definitely feel like the most "rustic" way to do game
           | design, just based on what's easy to do in the language
           | itself without resorting to workarounds, is to have
           | individual actors maintain their individual state, and then
           | have a common interface via a trait that would call update()
           | or render() virtually in a loop or whatever. Then have them
           | message each other via mpsc channels. That's pretty much rust
           | straight from the book, and, it's also a bog standard
           | GameObject architecture straight outta the 2000s.
        
             | [deleted]
        
             | platz wrote:
             | are these message channels deterministic? Or would order of
             | delivery and processing be resolved by chance?
        
               | nyanpasu64 wrote:
               | Message channels are deterministic if they're only used
               | on a single thread.
        
           | dgb23 wrote:
           | I really like Jonathan Blow, but I sometimes wish he would
           | substantiate these kind of claims more so an outsider could
           | learn what he is actually saying and why. I've watched a
           | lengthy video of his on that topic but I didn't get out
           | anything other than "you don't need it". No concrete
           | implementation cases where it gets in the way or how a
           | category of problems is better modeled in a different way.
        
             | cardanome wrote:
             | I am beginning to suspect people like him because he speaks
             | slowly with lots of repetition and in a relatively
             | accessible way.
             | 
             | Sure he might have lot's of valuable experience but every
             | video I have watched of him was like a 1 hour rambling
             | opinion piece which could be 3 minutes of actual content.
             | 
             | His video reaction to the rustconf ECS video had some good
             | points but they were very nitpicky and not really
             | justifying the length of the video at all.
        
             | modernerd wrote:
             | On why ECS gets in the way for him:
             | 
             | > Because it is far more complicated, thus takes far more
             | work, than what you actually need to do. That work has a
             | large opportunity cost. https://twitter.com/Jonathan_Blow/s
             | tatus/1427378984145154048
             | 
             | To me this has more nuance than, "you ain't gonna need it".
             | I don't think "concrete implementations" would do all that
             | much to strengthen his argument that unnecessary complexity
             | gets in the way of shipping for indie devs:
             | 
             | > Even 10% friction more than I ever had would have killed
             | me. I wouldn't have been able to make the things I had.
             | Even 5% more friction would have been really bad.
             | https://youtu.be/4t1K66dMhWk?t=3635
             | 
             | And...
             | 
             | > I have, several times, built games where I barely managed
             | to finish. ... I've just experienced that too many times to
             | increase friction. I need to decrease friction.
             | https://youtu.be/4t1K66dMhWk?t=3072
             | 
             | And again, in relation to entities rather than Rust's
             | borrow checker:
             | 
             | > If you are trying to focus on the way your entities are
             | set up, you are mis-directing your effort and that's going
             | to make it harder. Try to solve the problem that makes your
             | game interesting. What is it about the gameplay that makes
             | it interesting ... that users can see? Focus on that, solve
             | those problems. https://www.youtube.com/watch?v=w7W3xM2tzRA
             | 
             | On what he uses instead of ECS/components in his engines:
             | 
             | > One struct per entity type, with a base struct that is
             | common to all of them. https://twitter.com/Jonathan_Blow/st
             | atus/1427376307453665280
        
               | meheleventyone wrote:
               | Frictions a funny thing in this sense and what hurts one
               | person helps another.
               | 
               | One example is that a concrete entity is much harder to
               | change than one that is composed of concrete components.
               | So for example an artist I work with took some components
               | from an FPS game we made, some other random components we
               | had and a couple of components made in people's spare
               | time, made a bunch of art and ended up with a pretty
               | convincing prototype of a multiplayer shooter. He
               | couldn't have done that at all following a concrete
               | entity approach.
               | 
               | Composition and in particular making composition data-
               | driven and runtime malleable is very flexible even if you
               | don't care for the ECS approach.
               | 
               | But a large part of the problem is that we end up
               | promulgating opinion divorced from context and often a
               | lot of that context is not really more complex than the
               | approach someone is used to. Like if you have no problems
               | with the concrete entity approach which has been a
               | successful pattern since forever then there isn't that
               | much compelling you to change. That doesn't make it the
               | one true way or that because someone famous and
               | opinionated likes it that there isn't an alternative that
               | will better serve someone else's needs.
               | 
               | Horses for courses.
        
           | halvnykterist wrote:
           | I think the idea that you need something like ECS to deal
           | with mutability everywhere is a misconception. Traditional
           | architectures you'd use in C or C++ are all going to more or
           | less have a tree-based ownership graph, and these translate
           | very well to Rust. Long-lived pointers to things that you
           | don't own are a great way to get UAF errors or similar, and
           | having a collection of entities you can look up by ID is a
           | common pattern to use outside of ECS. > But at the same time
           | it was useful to play with that pattern because it's in
           | common usage in the Rust community. And in doing so it
           | perpetuates it. ECS is a good solution for lots of problems
           | (in particular I don't agree with jblow's take) but parading
           | it as _the_ way to make games in Rust feels a lot like how
           | OOP has been championed in the past. If you're going to teach
           | someone how to make games in Rust, doing with extra patterns
           | that don't add much other than complexity (in this case)
           | doesn't seem like a good strategy for teaching or introducing
           | people to the language.
        
           | kvark wrote:
           | Rust has ways to deal with mutability. Three-rs [1] uses a
           | classic scene graph tree, like ThreeJS. It's based on Froggy
           | [2], which is a general low level primitive for building a
           | "traditional" topology of the classes.
           | 
           | [1] https://github.com/three-rs/three [2]
           | https://github.com/kvark/froggy
        
         | rtoway wrote:
         | Bevy, while an ECS based library, can easily be used to program
         | a game in a more traditional way (excuse my formatting):
         | 
         | struct Player { health: Health, }                 // ECS style
         | fn update_player(query: Query<&mut Player>) {                }
         | // Traditional "OOP" style       impl Component for Player {
         | fn update() {                          }        }
        
         | verdagon wrote:
         | Indeed, ECS might not be a good fit for turn-based games.
         | 
         | We explored the topic quite thoroughly in [0] and came to the
         | conclusion that Roguelikes are more suited for something in-
         | between ECS and OO, named just "EC".
         | 
         | ECS is better suited to real-time games, or games which have a
         | lot of iteration over large arrays and parallel (not as in
         | multi-threading, but as in, batchable) computations, where ECS
         | can really shine due to its data layout. Most turn-based games
         | like roguelikes don't iterate over large arrays in the same
         | way.
         | 
         | With EC on the other hand, you're a little more free to group
         | components into their parent entity, and use interfaces
         | (traits), which can make things more understandable.
         | 
         | Whether idiomatic Rust likes EC is an open question though.
         | Idiomatic Rust tends to dislike heap allocation and virtual
         | dispatch, both which can make life a lot easier for Roguelike
         | games, which tend to prioritize flexibility and features, and
         | don't need the data-oriented optimization.
         | 
         | Additionally, a lot of people suggest using ECS in Rust because
         | that's the only architecture that the borrow checker doesn't
         | fight you in, for various reasons.
         | 
         | [0]:
         | https://www.reddit.com/r/roguelikedev/comments/i3xekn/ec_vs_...
        
           | brundolf wrote:
           | > Idiomatic Rust tends to dislike heap allocation and virtual
           | dispatch
           | 
           | Maybe Rust the way most people end up writing it, but Rust
           | the language has no issue with these things. I think the
           | idioms come more from the fact that Rust _empowers_ you to
           | avoid these things, not that it 's poorly-suited to them.
        
             | verdagon wrote:
             | I think both are true. Rust is poorly-suited to certain
             | architectures, and empowers us to use other architectures.
             | Rust's idioms take both its strengths and weaknesses into
             | account.
             | 
             | It can make up for it in other ways, but in my experience,
             | Rust is poorly-suited for Roguelike architecture
             | specifically.
        
         | cardanome wrote:
         | ECS is for me the natural way to design games. I wouldn't even
         | know to design them any other way.
         | 
         | I started game dev with love2d which is a pretty minimalist
         | framework. When I participated in a game jam, I needed a very
         | flexible system that would allow for quick prototyping and
         | would handle many different entities. I ended up writing
         | something which I later realized would be an ECS system. It
         | worked great and I would copy it over for other games.
         | 
         | I know there is that ECS-faction that is talking about
         | performance benefit and stuff but honestly I don't care. I
         | don't even know most of the terminology these people use. I
         | just use ECS to structure my code while being very flexible. I
         | use OO in other domains but it would never occur to me to
         | structure games that way. OO just feels way to brittle for a
         | domain where you do lot's of experimentation and can't really
         | know what you will need and how your entities might end up
         | looking.
        
           | pjmlp wrote:
           | ECS and OOP are sides of the same coin, although apparently
           | it is only visible to those that read SIGPLAN papers.
           | 
           | "Component Software: Beyond Object-Oriented Programming"
           | 
           | https://www.amazon.com/-/en/Clemens-Szyperski/dp/0201745720
           | 
           | One of the first publications on the matter.
        
             | dgb23 wrote:
             | Not sure I get what you mean. As I see it, ECS has more of
             | a relational character. Feels more like data pipeline than
             | operations/messages on objects. I think the mental model
             | matters the most here and that depends on how you think of
             | objects. But then any attempt of defining OO objectively
             | seems to be futile, there are conflicting historical and
             | contemporary notions plus a whole bunch of jargon on top,
             | depending on who you're asking.
             | 
             | As an example you could say that Scheme is more object
             | oriented than Java or vice versa and there would be valid,
             | typically cultural reasons for each.
             | 
             | In terms of ECS what kind of happens is that, yes, you have
             | a model of an entity and can think of that as an object,
             | but that is a projection of a set of components or a
             | relation. You're not really talking to the entity as a
             | whole all that much anymore. And it's not just "it
             | satisfies this set of interfaces" either. Your systems
             | literally define data transformations, each on a focused
             | set of related components that matter to a system, which
             | seems kind of the inverse of hiding data behind object
             | interfaces.
        
               | pjmlp wrote:
               | That is when data oriented programming gets into the
               | equation.
               | 
               | Classical ECS as it originally appeared on the literature
               | is coding against interfaces, COM or Objective-C
               | protocols style.
               | 
               | So yeah, one composes those interfaces together, there is
               | no class inheritance, only composition, delegation, and a
               | system is composed from a jungle of such components.
               | 
               | It is also a reason why DirectX is COM based, instead of
               | basic Win32 calls.
        
               | ngrilly wrote:
               | What do you mean by classical ECS? I've always read that
               | the Entity-Component-System approach originated in the
               | gaming industry, completely unrelated to what you wrote
               | about COM, etc.
        
               | pjmlp wrote:
               | Yes, the famous GDC talk.
               | 
               | Usually most stuff in game development tends to be
               | rediscovered, as most people don't come from CS
               | backgrounds.
        
             | glowcoil wrote:
             | > There has been an explosive growth in component software
             | technologies since the first edition of this classic book
             | was published. The advent of EJB, J2EE, CORBA 3, COM+ and
             | the .NET framework are evidence of a maturing market in
             | component software that goes 'beyond OOP'.
             | 
             | This book seems to be discussing distributed object
             | systems, which is a sense of the word "component" that has
             | little or nothing to do with the sense used by game
             | developers in reference to the ECS architecture.
             | Distributed object systems are designed to enable an
             | object-oriented design philosophy to be used for a system
             | which spans multiple address spaces or machines. The
             | entity-component-system architecture is a methodology for
             | organizing data layout and program functionality, usually
             | within a single address space on a single machine, where
             | the data associated with a given entity is spread across
             | multiple components or subsystems and associated by index
             | relations (much like a relational database), rather than
             | being all grouped together in one place (as encouraged in
             | OOP).
             | 
             | These two concepts (distributed object systems and ECS) are
             | designed to solve different problems, they are generally
             | used in different scenarios, and they apply at different
             | levels of system organization. There is so little
             | resemblance between the two that I have to conclude someone
             | calling them "sides of the same coin" is either completely
             | unfamiliar with one of them or is being deliberately
             | misleading.
        
               | pjmlp wrote:
               | I also did not state that book was the canonical ECS
               | model, rather that it was one of the first sources to
               | move into discussing components instead of classes.
               | 
               | COM and DirectX aren't distributed object systems, nor
               | Objective-C protocols, for example.
               | 
               | Don't confuse COM with DCOM and COM+.
               | 
               | Then there are the component models based on traits,
               | mixins, patterns, message passing, type classes,...
               | plenty of variants scattered around SIGPLAN and ECOOP
               | papers.
        
               | Rusky wrote:
               | You are still conflating two totally unrelated things.
               | 
               | The book is one of the first sources to move into
               | discussing "components," as in coding against
               | interfaces/protocols/traits/etc.
               | 
               | ECS deals with "components," as in pieces of data
               | composed using a relational model. This has nothing to do
               | with interfaces or protocols whatsoever! It is
               | practically the _opposite_ thing- working directly with
               | raw data, with no abstraction boundary.
               | 
               | You can't just pattern match on the word "component" and
               | expect it to mean the same thing to everyone.
        
               | pjmlp wrote:
               | That is the next step, data oriented programming, which
               | many confuse with ECS, as they tend to be used together.
        
               | Rusky wrote:
               | I am not talking about data oriented programming. With or
               | without that sort of memory layout optimization, ECS
               | "component" still refers to un-abstracted chunks of
               | concrete data rather than interfaces/protocols/etc.
               | 
               | Let's step back even further and consider Unity's pre-
               | DOTS "entities" and "components." These do not take the
               | data oriented approach, are not typically even classified
               | as ECS (e.g. because they lack the System aspect of that
               | design). However, the components are _clearly_ chunks of
               | concrete data (transforms, meshes, rendering parameters,
               | rigid bodies, etc.) rather than interfaces /protocols.
               | 
               | This is the sense in which ECS means "component." That
               | book is not relevant to this sense.
        
             | [deleted]
        
         | nulldata wrote:
         | ECS might have a higher initial complexity overhead, but once
         | you scale up, ECS can really help you keep complexity at bay.
         | 
         | There's a great talk [0] from the Overwatch developers where
         | they talk about how they built Overwatch using the ECS
         | architecture. They barely mention performance at all, but
         | instead talk about how it helped deal with complexity.
         | 
         | [0] https://www.gdcvault.com/play/1024001/-Overwatch-Gameplay-
         | Ar...
        
           | wlamartin wrote:
           | At https://story.ai we're using Shipyard ECS to model the
           | data behind the structured editing experience. Although at
           | first I was suspicious, I've come to realise it's an
           | extremely elegant way to handle our complexity.
           | 
           | Consider for example, a snippet that reads along the lines
           | of:                   when there is a new stripe charge
           | send a slack message
           | 
           | It's very nice to attach something like a "ScopeContext"
           | component to each Entity that has a "TokenLine" component,
           | that is a Vec of EntityIds that are sharing values into
           | scope. Very easy to model and add without interfering with
           | other data structures.
        
         | dkersten wrote:
         | ECS is entrenched in rogue development in general, at least
         | going by r/roguelikedev. It (or at least a component
         | architecture, if not fully blown ECS) seems to be a good fit
         | since these style of games tend to have a lot of composition
         | (in items, effects, behaviour).
         | 
         | Personally, while my experience is a bit limited, I quite like
         | the ECS style. It just makes logical sense to me as a way of
         | composing entities from different parts. The implementation
         | details (cache friendliness or whatever) are not important to
         | me since I've never made anything of a scale where it matters,
         | but that style of developing/designing how things act and
         | interact is logical to me personally. I haven't watched Bob
         | Nystrom's talk yet though (or, actually, I may have, it seems
         | familiar, but I don't remember any details. I plan to watch it
         | tonight).
         | 
         | With that said, many people find the Godot style more natural
         | and it certainly is nice too.
        
           | codetrotter wrote:
           | I've not yet used Godot. What is the Godot style like? And
           | are there some documents about it and example code of it?
        
             | meheleventyone wrote:
             | Godot uses a hierarchy of nodes, you can think of it as one
             | step further than entities being composed of components.
             | The hierarchy and how nodes operate on it define the game.
             | In practice though you end up with things that look very
             | entity like IMO so it's not _that_ different.
        
         | ffhhj wrote:
         | ECS is nothing compared to the eclipsing aspects of games that
         | a gamedev has to solve:
         | 
         | * Structures persistency (save/load/stream)
         | 
         | * Optmized seamless world expansion
         | 
         | * Where to get assets and content from (licenses, generated,
         | etc.)
         | 
         | * Affordable and responsive multiplayer
        
         | [deleted]
        
         | thebracket wrote:
         | (Author here) Bob makes some good points, so I'd like to share
         | my $0.02 on the ECS debate. The posters below who point out
         | that a lot of Rust setups use ECS to avoid mutability issues
         | are correct (although internally Bevy is an ECS that maps its
         | own node graph) - and that certainly helps - but it's not the
         | whole picture.
         | 
         | I think it's important to separate the EC from the S in ECS.
         | Entity-Component storage is basically a fast, in-memory
         | database. It's a great way to store global state, and provides
         | for really efficient querying. Using it as a database gives you
         | some advantages:
         | 
         | * Composition over inheritance (especially in Rust, which
         | doesn't really have inheritance - although you can fake it with
         | traits). It becomes easier to glue on new functionality without
         | realizing that you need to rearrange your object tree, and
         | there's real performance boosts to not doing virtual function
         | calls or dynamic casting to see what an object is.
         | 
         | * Replication; if you want to replicate state across multiple
         | nodes, a good ECS can really help you.
         | 
         | * Mutability; as mentioned above, you don't need mutable access
         | to everything at all times, and your code is definitely safer
         | if you have explicit mutability control.
         | 
         | * Surprising flexibility; Rust EC setups typically let you put
         | anything into a component. I have one slightly crazy setup that
         | stores an Option<Enum> as a component with the enum featuring a
         | number of different union setups.
         | 
         | So what about systems? Sometimes systems have some real
         | advantages:
         | 
         | * For simulation type games, it's great to be able to add a
         | simulation feature and have it apply everywhere. For example,
         | when I added gravity to Nox Futura it instantly worked for
         | player characters, NPCs, and objects. (It also worked on flying
         | creatures, killing them instantly - but I fixed that).
         | 
         | * It really helps with parallelism. Your systems declare the
         | data to which they will write, allowing the ECS to order your
         | systems in such a way that you get parallelism without having
         | to think about it too much (especially in Rust).
         | 
         | * If you're in a team, it's a great way to break out work
         | between team-members.
         | 
         | * It's often helpful for finding bugs, because functionality of
         | one type is localized to that system. You can get the same
         | result by being careful in a non-system setup.
         | 
         | Sometimes, systems aren't so great. It can be really tricky to
         | ensure that linked events occur in the correct order. You can
         | make a bit of a mess when you want something to work one way
         | for one type of entity and another for a different type.
         | 
         | But here's the thing: the systems part is optional. You can
         | easily have your main loop query the EC data-storage directly
         | and work like a traditional game loop - without losing the
         | benefits of the storage mechanism. If you prefer, you can
         | attach methods to components and call those. Or you can build a
         | message-passing system and go that way. There's no real _right_
         | way to do it. Once you 've got the hang of your ECS's
         | query/update model, you can tailor the game logic however you
         | want. (I happen to like systems, but that's a personal choice
         | more than a "you must do this" belief).
         | 
         | (Edit: My formatting was awful, sorry.)
        
           | halvnykterist wrote:
           | > Composition over inheritance (especially in Rust, which
           | doesn't really have inheritance - although you can fake it
           | with traits)
           | 
           | This does not require ECS, you can happily have something
           | like                 struct Entity {           components:
           | Vec<Box<dyn Component>>,       }
           | 
           | (Nor do I think this is a good way of setting up a
           | traditional roguelike)
           | 
           | > Replication; if you want to replicate state across multiple
           | nodes, a good ECS can really help you
           | 
           | I'm not sure what you exactly mean by nodes here, but making
           | something serializable in Rust for easy replication is hardly
           | an issue when we have access to tools like serde.
           | 
           | > Mutability; as mentioned above, you don't need mutable
           | access to everything at all times, and your code is
           | definitely safer if you have explicit mutability control
           | 
           | Addressed above, but while ECS solves the mutability issue
           | it's not a unique way of solving it and bringing it in to
           | deal with that is overkill at the very least.
           | 
           | > Surprising flexibility; Rust EC setups typically let you
           | put anything into a component.
           | 
           | Again, you can do this with regular old components too. This
           | is also an oversold feature of components / mixins / anything
           | like this in general, I think. You can never "just add a
           | component", you need to fix all the issues that come with
           | that, like making sure that gravity doesn't kill your birds.
           | 
           | > For simulation type games, it's great to be able to add a
           | simulation feature and have it apply everywhere.
           | 
           | Yes, but that's not what a turn based tile based game is.
           | Generally you want to iterate over things in order - gravity
           | (if a roguelike has such a thing) gets applied on the
           | player's turn, and only for the player. If you step over a
           | ledge you don't wait for the "gravity" system to kick in and
           | apply gravity to all entities, it is resolved in the same
           | instant for only the entity that has just moved
           | 
           | > It really helps with parallelism.
           | 
           | Sure, although gameplay logic is not what's going to have to
           | be parallel in a roguelike. Building up pathfinding maps and
           | similar is useful to do in parallel, but ECS doesn't really
           | help you with that.
           | 
           | > If you're in a team, it's a great way to break out work
           | between team-members.
           | 
           | Not a particular strength of ECS, and if anything I could see
           | issues arising from the fact that you basically have dynamic
           | typing when it comes to what behaviors an entity has.
           | 
           | > But here's the thing: the systems part is optional.
           | 
           | If you're not doing query-based ECS with systems there's also
           | no particular reason to not use vecs of components within
           | entity structs.
           | 
           | I believe what you're doing here is adding a bunch of
           | complexity to something that could be much simpler, and it
           | really does the language a disservice.
           | 
           | As a final note, in the excerpt about items you have this
           | justification for not using an enum instead of components:
           | Each item you're adding provides only one effect. It's
           | tempting to       create a generic UseEffect component
           | containing an enumeration.       Enums can only have one
           | value--if you want to make an item with       multiple
           | effects, you'd be out of luck. It's a good idea to separate
           | effects into their own components in case you decide to
           | create an       item that does more than one thing.
           | 
           | Not only does this violate YAGNI, it's trivial to work
           | around:                 enum ItemEffect {
           | Heal(i32),           Poison(i32),           Explode,
           | MultiEffect<Vec<Box<dyn ItemEffect>>>,       }
           | 
           | It just feels like you're looking for problems to solve.
        
             | [deleted]
        
             | MaulingMonkey wrote:
             | struct Entity {             components: Vec<Box<dyn
             | Component>>,         }
             | 
             | At this point you're effectively just hand-rolling your own
             | ECS - and perhaps being in denial about it by touting the
             | fact that the ECS is half implemented at best - rather than
             | eschewing an ECS outright, IMO. If you want to skip the
             | ECS, embrace the natural typing of the language - then you
             | don't need to build something to query and filter
             | components, and can instead just use the language's built-
             | in constructs:                   struct Entity {
             | pub position: Option<XY>,             pub sprite:
             | Option<SpriteId>,             pub scripts:  Vec<ScriptRef>,
             | //...         }                  fn render_world(entities:
             | &[Entity]) {             for entity in entities {
             | if let Entity { position: Some(xy), sprite: Some(sprite),
             | .. } = entity {                     // ...
             | }             }         }
             | 
             | Entity may eventually become a merge hazard on larger
             | teams, and Entity enumeration without archetype filtering
             | may eventually become a performance hazard if done too
             | frequently and naively, but this kind of approach can work
             | fine for many smaller projects.
        
               | halvnykterist wrote:
               | The crucial difference between having a vector of
               | components is in access patterns - in ECS you iterate
               | over entities that have a given set of component, using
               | queries, with entities that have vectors of components
               | you're still iterating over entities. For something like
               | a roguelike you're generally just dealing with one entity
               | at a time, so this is a very important distinction.
               | 
               | That said, I don't think just having a vector of
               | components is good design, you can do a lot better than
               | that. I think the most natural thing to do in most
               | roguelikes is to have an "Entity" type that's shared
               | between players and monsters and has things that you'd
               | expect those things to have, along with an inventory and
               | potentially some kinds of tags governing behavior. Type
               | Objects etc fit nicely into that kind of scheme.
               | 
               | >and Entity enumeration without archetype filtering may
               | eventually become a performance hazard if done too
               | frequently and naively, I'm specifically talking about
               | turn based tile based games, here, so iterating over all
               | entities matching a given set of components is rarely
               | going to be a performance concern. It's far more
               | important to make sure you're efficient when it comes to
               | things like AI routines and pathfinding.
        
             | [deleted]
        
             | thebracket wrote:
             | We should probably agree to disagree; your approach is just
             | as valid as mine. My first attempt at a roguelike in Rust (
             | https://github.com/thebracket/rustyroguelike ) was a
             | straight-from C++ approach, using dynamic traits and a lot
             | of casting. It was my first try at using Rust, and is
             | pretty bad - but at least it completed the "r/roguelikedev
             | does the tutorial" event. Going from OOP to a non-
             | inheritance language was quite the leap.
             | 
             | You absolutely can have an entity structure containing a
             | vector of dynamic component types. It can get quite messy
             | when you start having a lot of component types. When your
             | entity runs, it has to look at the data in its components.
             | That either means that component is a big enum (no need for
             | dyn and Box there), or component is a trait and you're
             | going to be doing a bunch of dynamic casting to find out
             | what components an entity has when it ticks. Either can
             | work (as can having an Option for each component type,
             | which replaces the dynamic cast with an `if let`).
             | Ultimately, there's not a lot of difference between an
             | entity iterating its components and calling methods on
             | components (or branching based on the components it has)
             | and running a query to retrieve the components you want and
             | acting on them. It's not that different from a NoSQL
             | database (everything in a node graph) vs. a relational
             | database (tables keyed to an identifier) - both work, each
             | has their strengths and weaknesses. (I also really didn't
             | want to try and teach dynamic casting early in the book!)
             | 
             | Some specific points from your reply:
             | 
             | By "replication", I meant network replication. You can get
             | the same benefits by tracking changes within an
             | entity/component, but it's really handy when a single
             | storage system does that for you. Not that useful to a
             | traditional single-player roguelike, but a nice tool to
             | have.
             | 
             | > Yes, but that's not what a turn based tile based game is.
             | Generally you want to iterate over things in order -
             | gravity (if a roguelike has such a thing) gets applied on
             | the player's turn, and only for the player. If you step
             | over a ledge you don't wait for the "gravity" system to
             | kick in and apply gravity to all entities, it is resolved
             | in the same instant for only the entity that has just moved
             | 
             | That very much depends upon what you're creating. (Nox
             | Futura is a Dwarf Fortress like). In the gravity example,
             | it was solved by remembering to exclude the Flying
             | component from the gravity query. The roguelike example in
             | Hands-on Rust actually runs the player and monsters in
             | different phases, but re-uses a lot of systems in the
             | process. Matching on the turn state and executing systems
             | isn't all that different to matching on the turn state and
             | running tick functions on the entities included in that
             | turn - especially if you have an energy cost/initiative
             | type system breaking out the moves (the tutorial I created
             | does this). Both Hands-on Rust and the tutorial effectively
             | use message-passing for chaining events together.
             | 
             | > if anything I could see issues arising from the fact that
             | you basically have dynamic typing when it comes to what
             | behaviors an entity has
             | 
             | You have the exact same problem with a dynamic vector of
             | components.
             | 
             | > If you're not doing query-based ECS with systems there's
             | also no particular reason to not use vecs of components
             | within entity structs.
             | 
             | It mostly boils down to preference. I find
             | Query<(MonsterAI, Position, LikesToEatPlayers)> easier to
             | work with than having each entity iterate a component list,
             | query the type of each component and then act accordingly.
             | 
             | > As a final note, in the excerpt about items you have this
             | justification for not using an enum instead of components:
             | 
             | Again, we're solving the same problem in similar ways.
             | There's really not a whole lot of difference between
             | matching the enum and iterating MultiEffect and querying if
             | an entity has components. Either way, you have code that
             | says "oh, it explodes" and makes a boom.
             | 
             | In other words, we both prefer different ways to accomplish
             | exactly the same thing. Neither of us is right or wrong,
             | there's plenty of ways to skin a cat. Hands-on Rust is as
             | much about teaching Rust and gamedev in general as it is
             | roguelikes in particular; if you want a big, working
             | roguelike - the tutorial (
             | https://bfnightly.bracketproductions.com/ ) does that.
        
         | anothernewdude wrote:
         | The reason ECS is so common for roguelikes, is because they
         | provide a simulationist experience. The main draw of several
         | roguelikes is having enemies on the same footing as the player,
         | and a good way to do that is to have them use the exact same
         | systems. It's also a good way to make interesting interactions
         | between environment and objects happen.
         | 
         | Also, having collections of entities works well for Rust's
         | borrow checker.
        
       | vjust wrote:
       | His explanations seem very clear and simple, I'd dig into it,
       | just to get a better understanding of rust, and the game dev part
       | also seems do-able, unlike other authors where they dive into
       | some complex pieces causing frustration to the learner.
        
       | [deleted]
        
       | cius wrote:
       | I recently finished this book and highly recommend it. Very fun
       | stuff, a decent introduction to rust, and does a great job of
       | setting the reader up for exploring further. Kudos to Mr.
       | Wolverson.
        
       | ttymck wrote:
       | It is a very good learning guide. Keep in mind I am someone who
       | negotiates the borrow checker by adding-and-removing
       | */&/to_owned() rather haphazardly.
       | 
       | I found it especially satisfying to port the game from
       | racketlib/rltk to bevy afterwards.
        
         | rtoway wrote:
         | I was thinking of following the book but with Bevy. How do you
         | replace bracket-lib?
        
       | dopu wrote:
       | Looks pretty good! I will say, as someone who programs in their
       | day job and has been trying for ages to get into game dev as a
       | hobby, love2d [0] has been excellent for getting started. My
       | github has a few repos of previous attempts at making simple
       | games (in .cpp, .rs, etc) which I abandoned from the amount of
       | work it took.
       | 
       | If you're in a similar boat, I would recommend checking the
       | framework out. Lua's a pleasure to program in and you can focus
       | on the game development itself instead of getting bogged down in
       | the details of rust / cpp. In fact I've been thinking lately
       | about how easy it would be to use it for things other than games
       | -- quick prototyping of graphical simulations, psychophysics
       | experiments, etc.
       | 
       | [0]: https://love2d.org/
        
       | greenail wrote:
       | I don't think most non-rust programmers know what ECS is.
       | 
       | ECS is a pattern to manage composable logic and shared behavior.
       | very very loosely like splitting logic in to class level and
       | object level.
        
         | runevault wrote:
         | Lots of game developers know what ECS is. It existed before
         | rust gamedev became a major thing. Unity even has an
         | (experimental to be clear) ECS engine you can use to replace
         | traditional monobehavior style objects.
        
           | greenail wrote:
           | fair, but I had to lookup what ECS was so I though I'd save
           | others a bit of googling.
        
             | runevault wrote:
             | Yeah explaining it is great. Just don't want people
             | thinking it is only a Rust thing.
        
       | dudul wrote:
       | I started reading this book a few months ago. It is pretty good,
       | I really like learning while working on a "sort of real world"
       | project.
       | 
       | However, being completely new to Rust I find that the author
       | doesn't spend enough time discussing the language, it's syntax
       | and nuances. It is hard to talk both about rust alongside video
       | game design techniques.
       | 
       | I put it down after reading 1/4th of it. I'm planning to spend
       | some time on a book that focuses on the language first and then
       | get back to it ;)
        
         | timClicks wrote:
         | That's a very difficult balance as an author writing a project-
         | based book for a language. It's really difficult to know how
         | much time to spend where: the language (Rust), the projects
         | background (gamedev patterns) or the project code.
        
       | Zolomon wrote:
       | I worked through this book a couple of weeks ago and I had a
       | blast. I heartily recommend it to roguelike fans that haven't
       | tried out participating in the 7DRL game jam yet.
        
       | Camas wrote:
       | Book is also online: https://bfnightly.bracketproductions.com/
       | 
       | and on Github: https://github.com/amethyst/rustrogueliketutorial
        
         | thebracket wrote:
         | (Author here) That's the Roguelike tutorial I created, not the
         | Hands-on Rust book. The two are quite different beasts, with a
         | bit of overlap.
         | 
         | Hands-on Rust is designed for the newcomer to Rust, and
         | carefully maps tutorial sections through teaching beginner-to-
         | intermediate Rust concepts. It starts with some basic Rust
         | exercises, works through a Flappy Bird clone, and then uses
         | Roguelike development to teach a lot of underlying Rust
         | concepts. It also teaches gamedev, and tries to do so in a way
         | you can reuse in other games.
         | 
         | The tutorial is all Roguelike, all the time - focused on
         | building a working roguelike.
        
           | rudedogg wrote:
           | Congratulations on releasing your book. I watched one of your
           | talks about procedural generation[0] and really enjoyed it,
           | thanks!
           | 
           |  _Mentioning this here since the tutorial linked above has a
           | lot of procedural generation content_
           | 
           | [0] https://www.youtube.com/watch?v=TlLIOgWYVpI
        
       ___________________________________________________________________
       (page generated 2021-10-14 23:00 UTC)