Larkenx / Rotten-Soup

A roguelike built with Vue, Vuetify, Tiled, rot.js, and PixiJS! Playable at https://rottensoup.herokuapp.com/
GNU General Public License v3.0
383 stars 55 forks source link

Entities as data / composition over inheritance #74

Closed Larkenx closed 5 years ago

Larkenx commented 5 years ago

Right now, Rotten Soup uses an older OOP paradigm of managing entities. Here's a visual example how the files are laid out from an inheritance perspective.

> tree /Rotten-Soup/src/assets/js/game/entities
│   Entity.js
│
├───actors
│   │   Actor.js
│   │   GoalBasedAI.js
│   │   NPC.js
│   │   Player.js
│   │
│   └───enemies
│       │   GoalBasedEnemy.js
│       │   SimpleEnemy.js
│       │   StatelessAI.js
│       │
│       ├───boss
│       │       Lich.js
│       │
│       └───legendary
│               OrcPriest.js
│
├───items
│   │   Equippable.js
│   │   Item.js
│   │
│   ├───armor
│   │       Armor.js
│   │       Boots.js
│   │       ChestArmor.js
│   │       Helmet.js
│   │       LegArmor.js
│   │       Ring.js
│   │
│   ├───misc
│   │       Beer.js
│   │       Corpse.js
│   │       Gold.js
│   │       Key.js
│   │       Spellbook.js
│   │
│   ├───potions
│   │       HealthPotion.js
│   │       ManaPotion.js
│   │       Potion.js
│   │       StrengthPotion.js
│   │
│   └───weapons
│       │   Battleaxe.js
│       │   Sword.js
│       │   Weapon.js
│       │
│       └───ranged
│           │   Bow.js
│           │   RangedWeapon.js
│           │
│           └───ammo
│                   Ammo.js
│                   Arrow.js
│
└───misc
        Chest.js
        Door.js
        Ladder.js
        LevelTransition.js
        LockedDoor.js
        Store.js

There are several good resources out there that break down why this pattern is bad - I highly suggest watching this presentation by Brian Buckley (creator of Caves of Qud) https://www.youtube.com/watch?v=U03XXzcThGU).

The tldr is that when we define entities via inheritance, we eventually find areas where the same functionality is duplicated over and over again. Consider in the example above if I wanted both a bow & a sword that caused fire damage and costed mana everytime I attacked with it. The sensible approach is designing a master Entity base class, then adding pieces of data or components to that entity class.

My vision for Rotten Soup is not to embrace an "ECS" framework - because I don't personally think this is the right solution. I think we should take ideas of making entities data, and making it so that their characteristics and functionality is defined by modular components!

I have written some experimental code in the items-overhaul branch that toys with some of these ideas. I would love for folks to contribute here and figure out ways that we can redesign the way Rotten Soup handles entities - and if we can solve this problem, then it opens up the game for a massive content push where folks can rapidly create new item types with wild effects to make this game more fun and interesting.