bberak / react-game-engine

A lightweight Game Engine for the web (React) 🕹⚡🎮
MIT License
413 stars 24 forks source link

comparison with phaser etc? #7

Closed dcsan closed 4 years ago

dcsan commented 4 years ago

This looks nice and thanks for including an example and writeup of IoC etc. You seem to have a good few other interesting projects for such a small team, very grateful for the open sourcing.

So I'm wondering how to compare with Phaser and other game engines out there?

I'm looking to do some simple HTML5 like word games, but with text sprites and other components, and was actually looking for an engine that used a DOM renderer. But this doesn't quite seem to be that?

Thanks!

bberak commented 4 years ago

Hi @dscan,

Thanks for the kind words - much appreciated. Great questions btw.

We first created the React Native version of this library, and then ported it over to the web so we can release our apps on iOS and Android, and potentially on the web without re-writing too much code.

As such, the React version pretty much reflects the philosophies of the React Native version. We don't make too many assumptions on the technical details regarding:

This is left up to the developer because:

1) There are a tonne of ways to render your game (DOM, Canvas, WebGL) 2) There are variety of physics engines out there - all with pros and cons. Or you might like to write your own 3) Aiming for a small footprint eases the maintentance costs for us

That said, probably the biggest differentiating factor of our library is the way we manage game entities (state) and game logic. We've implemented a sort of Component-Entity-System that favours composition over inheritance. A lot of engines out there use a more traditional hierarchical approach (not sure about Phaser) - and this isn't a bad thing at all.

The non-minified size of our engine is 22KB, but there is a lot of room for minification.

Regarding the integration with React - you are correct, it is very loose. Once the GameEngine component is mounted in the React dom, the frames and game objects can be rendered to whatever/wherever. It just happens that React is good at diffing state and running updates - which is handy for games (in my opinion) because I can just update the state of my entities via my systems, and React will figure out what needs to change. However, the DefaultRenderer can be switched out for anything - I often use ThreeJS personally, but you might as well drop in some sort of DOMRenderer there.

We're also planning on making a core version of the engine that really isn't tied to any framework (we need it for a NodeJS project). However, I can't give you an ETA yet :/

I think simple HTML5 word games would be suitable - but just keep in mind that the library is very lightweight, so if you need some bells and whistles, Phaser will probably have you covered out of the box.

If you have any more questions or need more info - please let me know :)

dcsan commented 4 years ago

thanks for the response, I really appreciate it. NEAP looks like a cool place to work..

your points do lead to some follow-up so if you don't mind:

also, CSS transitions get hardware speed up, as they're more declarative over the length of their animation. harder to use for games though as the math to modify "in-flight" seems messy. almost all game engines seem render-loop/tick based for this reason.

bberak commented 4 years ago

Hi @dcsan,

Great questions. In regards to batching, the library guides (but doesn't restrict) users to render all entities in a batch at the end of the frame. So out of the box it looks something like this:

  1. System 1 Logic
  2. System N Logic
  3. Render entities
  4. Repeat

React and the DefaultRenderer will update the DOM with all required visual changes. The DefaultRenderer will assign each DOM element with a key (entity id) which helps React diff and reconcile the changes between it's internal "shadow" DOM and the actual DOM. It then performs the minimum required DOM changes from frame to frame.

Indeed, managing CSS transitions for games wouldn't be easy, but let me know if you find a neat way to do this. I've opted to create a Timeline/tick-based system which can be used to drive all sorts of ad-hoc logic on the fly, including animations on sprites, DOM elements or ThreeJS objects.

As for creating an SVG renderer - this is entirely possible, however I'm not sure about the performance. I recommend you do a quick proof-of-concept first - my experience SVGs and browser performance is limited.

In any case, if you do want to override the DefaultRenderer, the process would go something like this:

<GameEngine renderer={MyNewRenderer} />

At the end of the frame, MyNewRenderer will receive all the entities of your game. At this point, it's up to you to filter out the entities that need to be renderered, and write the rendering code as required (taking into account depth / order if required). Here's a link to the DefaultRenderer. It's quite basic because it relies on all entities that need to be displayed to implement a renderer function that will be called in a loop.

Here is an example of a ThreeJS renderer that renders enitities to a WebGLContext (hardware accelerated). It's a bit more involved, but it's mostly boilerplate code. The exported function is fairly basic.

Really interested to see in which direction you end up going, and if you find any interesting insights regarding SVG. Please let me know if I can help further or give you more info.

Cheers!

bberak commented 4 years ago

Hi @dcsan - let me know if you need to discuss further :)