Update 04/04/16: I've become aware of some other projects which may be very similar to the criteria described below. I'm going to look into them and make a part 2

I've been researching game engines for a few months now, and I think I've finally settled on a combination of design patterns which will work well for a JavaScript game engine.

There are already JavaScript game engines. Why make one?

Part of the reason is because it seems like something fun to do. However, I'm not a huge fan of reinventing the wheel. As such, I'm not going to be following the same practices as other engines like Phaser and Impact. My approach is born from the usage of npm modules.

A modular approach

Phaser and Impact both use a classical inheritance structure with some things being modular, like plugins. While there's nothing wrong with this, I prefer an extremely modular approach using a tool like rollup to
bundle only the exact pieces of code you need.

Having a smaller footprint is useful in a world becoming dominated by mobile devices. It may not seem like much at first, however what if you have included some large libraries like jQuery, TweenJS, React, etc. If you are only using a handful of functions from these libraries, it'd be great to discard the rest.

Disclaimer: I'm not sure if these libraries would be 'tree-shakable' by rollup

In any case, having a modular engine means you can include only the parts you need. Let's say you're making an infinite space shooter. An example of the modules you could include might look something like this:

  • Timer
  • Loop
  • Collision detection
  • Levels
  • Renderer
  • State
  • UI
  • Movement
  • Input
  • Particles (If we want to get really fancy)

That may seem like a lot. However, we could have many more modules in a more complex game. Here are some hypothetical modules:

  • Animations
  • Complex Physics (Box2D for example)
  • Camera
  • Filters
  • Tile maps
  • Particles
  • Shadows

Some of these modules could be really useful for lots of games. However, if they are not needed, we have no reason to pack them in with the engine.

Entity-Component-System makes it easy to recycle entities

I suggest reading this article about ECS and why it's useful for game development. I will skip a lot of the stuff explained in that article as it is well written and easy to comprehend.

So, if you read the above or already know what ECS is, then it's easy to see why this design pattern makes it trivial to recycle entities.

The reason that you want to recycle entities is to keep memory usage low. If you have a player shooting a few bullets every second and you do not recycle them, you end up in a situation of all these bullets sitting in memory until the garbage collector decides to clear it out. During this time, it's possible to rack up a huge memory footprint - depending on your game.

If, instead of creating a new bullet we just used an old one and repositioned it at the player's weapon again, we would not need to use more memory and therefore lessen the chance of frame-rate dips.

Assemblages instead of inheritance

In a classical inheritance engine, if you want to create a Dog entity, you might do something like this:

// entities/dog.js
import Animal from './animal';

class Dog extends Animal {  
  constructor() {
    super();
    this.health = 20;
    this.position.set(32, 32);
    this.sprite = 'media/dog.png';
    this.sound = 'media/woof.mp3';
  }
}

export default Dog;  

However, if you want to recycle this object, you can only recycle it into another dog. With an assemblage, you can do something like this:

// assemblages/dog.js
import Health from '../components/health';  
import Position from '../components/position';  
import Appearance from '../components/appearance';  
import Collision from '../components/collision';  
import Sound from '../components/sound';

export default function(health, x, y, sprite, sound) {  
  return [
    new Health(health),
    new Position(x, y),
    new Appearance(sprite),
    new Collision(),
    new Sound(sound)
  ];
}

So, you may have noticed that in the assemblage we are calling new for each component we have attached to this entity. I am aware that unless those components are also pooled like the entities then the ECS structure is actually
much less memory efficient.

I do not currently have pooling set up for components. However, it is on my list of todos and I would like to see how it effects performance.

Putting performance aside, I find it much easier to think of game entities as groups of collections (data) rather than as inheriting from each other. Many times I get caught up in whether the Enemy class should inherit from Entity or something else and then which classes should inherit from that.

With this approach, you just need to think: 'Okay, I need to create a dog. Dogs should have health, a position, a sprite, collision detection and they can make sounds'.

Conclusion

I think that the Entity-Component-System design pattern afford a lot more flexibility and is more useful for creating games. In the coming weeks I will attempt to get Flask fleshed out enough to create the classic game Pong. Upon this, I'll be sure to post my findings, trials and tribulations.