Unobtrusive Game Engines
We’ve suddenly seen an uprising up HTML5 game engines over the last year. To me not many of them stand out and that’s a personal opinion. Maybe because the things I look for in an engine is not actually an engine but a library. The best engine is the one I can replace.
I don’t like the idea of being tightly coupled to a game engine. Too much of the code base becomes unknown and at risk of deprecation or API changes. I also don’t want to be forced to use a methodology (MVC, entity component). This is probably why we have so many engines. Every developer has their own style and if they can’t reflect that in an engine they get frustrated and make one that can.
Take the UNIX philosphy: Rule of Separation: Separate policy from mechanism; separate interfaces from engines. http://www.faqs.org/docs/artu/ch01s06.html ‘Basics of the Unix Philosophy’
Here’s my wishlist of the perfect game engine which from now on I shall call library.
1. Hook for tick and render
This is the most basic requirement for creating a game. An unobtrusive API might be:
Game.tick(function(dt, frameNumber) {
//register a callback on tick
});
The render hook would be similar:
Game.render(function(ctx) {
});
The important thing here is that I still have control and I can easily replace the library with something else that implements the same basic API. Heck, I could write a basic wrapper should another engine not implement it.
2. Input
An abstract layer for inputs that can generalise touch and mouse events and even keyboard events.
Game.input(function(type, e) {
//type = Click, Down, Up, Key
//e = Event object includes position in form of Point
// or key code for keyboard events
});
Generally you want to know if an entity lies within the position from the event. Which leads us to our next feature.
3. Maths
Some basic algorithms commonly used in 2D games such as SAT collision, polygons, points, rects, spatial data structures but again no dependence on how the entities are stored.
//Point = {x: Number, y: Number}
Game.math.pointInRect(Point, Rect);
//Rect = {x: Number, y: Number, w: Number, h: Number}
Game.math.collision(Rect, Rect[]);
However you organise game objects it should be simple enough to export it to the Rect interface if it isn’t stored like that already.
For determining if the user clicked/touched our entity:
Game.input(function(type, e) {
if(Game.math.pointInRect(e.point, entity.rect)) {
//clicked/touched
}
});
Even if this is too verbose it is simple enough for the developer to write another abstraction that suits them.
4. Mobile Support
Most mobile browsers are capable of rendering the Canvas element. The issues arrive with resolution, aspect ratio and sizing the stage.
We don’t want an implementation that will be obtrusive so this can’t be an automatic fix.
if(Game.isMobile) {
Game.maintainRatio(DOMElement);
}
This would detect if the user is on a mobile device, make the specified element “fullscreen” by scaling it as big as possible while maintaining the aspect ratio and using a black background for a letterbox effect.
Again, the problem here is this doesn’t match all solutions and is the reason this can’t happen automatically. What if the game was meant to stretch?
Game.stretch(DOMElement);
This will make the specified element as big as the window (so it doesn’t matter if it’s on mobile or not).
To find out the size of the stage:
Game.width; //Number
Game.height; //Number
5. Modular
I see mobile support as more of a module or extension than part of the core. Therefore the game library should allow extensions.
Game.extend({
maintainRation: function(el) {},
stretch: function(el) {}
});
I haven’t actually written this library, it’s just my ideas for a game library that would be flexible enough so developers can add their own touch to it without being forced into a style or methodology they dislike. Would love to hear feedback about this concept.
Some initial code for proof of concept is up here: https://github.com/louisstow/Game