{"id":3093,"date":"2014-01-12T21:21:20","date_gmt":"2014-01-12T20:21:20","guid":{"rendered":"http:\/\/t-machine.org\/?p=3093"},"modified":"2014-01-12T21:31:59","modified_gmt":"2014-01-12T20:31:59","slug":"cross-platform-entity-system-design","status":"publish","type":"post","link":"http:\/\/new.t-machine.org\/index.php\/2014\/01\/12\/cross-platform-entity-system-design\/","title":{"rendered":"Cross-platform Entity System design"},"content":{"rendered":"<p>I&#8217;ve started a new open-source project to make an ES designed specifically to be ported to different platforms <em>and work the same way, with the same class\/method names, on every platform<\/em>:<\/p>\n<p><a href=\"http:\/\/aliqua.org\">Aliqua.org<\/a><\/p>\n<p>Here&#8217;s some thoughts on &#8220;why&#8221; I&#8217;m doing this, and &#8220;how&#8221; I&#8217;m making it work&#8230;<br \/>\n<!--more--><br \/>\nI&#8217;ve written Entity Systems in a few different languages:<\/p>\n<ul>\n<li><strong>C<\/strong> (2 times: both small)\n<li><strong>C++<\/strong> (twice: one BIG, one &#8220;proof of concept&#8221;)\n<li><strong>Objective-C<\/strong> (3 times: two small, one a port)\n<li><strong>Java<\/strong> (3 times: two small, one big)\n<\/ul>\n<p>&#8230;and I&#8217;ve noticed some recurring issues.<\/p>\n<h2>What is &#8220;Cross Platform&#8221;?<\/h2>\n<p>In 2014 game-development, there are a few monolithic platforms where you can thrive while only knowing\/mastering a single language:<\/p>\n<ul>\n<li>Unity: C# <em>(any other options are an illusion ;))<\/em>\n<li>Unreal: C++ <em>(with Unreal 4&#8230;)<\/em>\n<li>Mobile (Apple): ObjectiveC <em>(unless you work at a mainstream games-studio, in which case: C++)<\/em>\n<li>Mobile (&#8220;other&#8221;): Java <em>(only Android and iOS have big enough market share for most of us to do *single platform* games)<\/em>\n<li>Console (both TV and handheld): C++ <em>(of course!)<\/em>\n<\/ul>\n<p>Note: each of these represents tens of millions (usually: hundreds of millions) installed userbase. When you&#8217;re shipping a game, a hardware base of &#8220;200 million&#8221; is enough for you to not bother with multi-platform code!<\/p>\n<p>If you want to go cross platform, you have a couple of options:<\/p>\n<h3>OPTION1: Use the Lingua Franca<\/h3>\n<p>C++ works almost everywhere, and it has good compiler support on most platforms (not perfect &#8211; e.g. Google seems to hate it, with their ADK for Android sucking particularly hard &#8211; but close).<\/p>\n<p>Downside: requires you to use C++ for everything, even game projects that don&#8217;t &#8220;need&#8221; it. C++ code is somewhere between 20% and 50% more expensive to write and maintain on like-for-like problems than most other platforms (it&#8217;s super powerful, verbose, low-level, and prone to horrors of e.g. manual memory management, ..etc).<\/p>\n<h3>OPTION2: Use a cross-platform engine<\/h3>\n<p>Unity says Hai.<\/p>\n<p>Downside: You have to use C#, which is popular but not super popular outside of MS\/Windows &#8211; many devs don&#8217;t (yet) use it. Also, Unity is a relatively immature platform, with many outstanding bugs and missing features. I love Unity, but it&#8217;s the cheap equivalent of many of the other platforms.<\/p>\n<h3>OPTION3: Learn another language<\/h3>\n<p>This is often the easiest and cheapest approach &#8211; but the one that developers (especially Indies) find most terrifying. Learning a new spoken language is much harder than learning a new programming language; don&#8217;t be afraid!<\/p>\n<p>Also &#8230; Senior programmers today are usually expert level in at least 2 distinct languages, and highly experienced in 2-4 more. There&#8217;s a high chance they already know the extra language they&#8217;ll need.<\/p>\n<p>Downside: the API&#8217;s and libraries you&#8217;ve come to know and love: do they exist on the &#8220;other&#8221; platform?<\/p>\n<h2>A good cross-platform Entity System<\/h2>\n<p><a href=\"http:\/\/gamadu.com\/artemis\/\">Artemis<\/a> is an early, simple ES design that&#8217;s very popular among small Indie game developers. Indies who&#8217;ve been publishing games for a long time usually have their own codebases already, but new ones tend to start with Artemis. I recently re-ported it to ObjectiveC, for use on iOS, and to learn how it&#8217;s put together (<a href=\"https:\/\/github.com\/adamgit\/ArtemisObjC\">https:\/\/github.com\/adamgit\/ArtemisObjC<\/a>).<\/p>\n<p>I noticed a few things when porting it:<\/p>\n<ol>\n<li>Some features are &#8220;core&#8221; to the ES (e.g. Entity, Component), others are Artemis&#8217;s &#8220;special sauce&#8221; (e.g. Aspect, Bag), and the rest is &#8220;useful but optional extensions&#8221; (e.g. the different EntitySystem subclasses)\n<li>Some constructs are impossible to port (e.g. Java allows two method names with the same name but different argument-types)\n<li>Some constructs use standard libraries that need porting (e.g. Java&#8217;s BitSet class is easier to use than Apple&#8217;s CFBit \/ CFBitSet C-code (non OOP!))\n<li>Some performance-tricks work almost identically on any platform (e.g. Artemis&#8217;s Bag class is very easy to port)\n<\/ol>\n<p>A few years back <a href=\"http:\/\/entity-systems-wiki.t-machine.org\/rdbms-with-code-in-systems\">I wrote a couple of blog posts, and a couple of open-source GitHub projects, for an ultra simple ES that Just Works<\/a> and is easy to port across platforms. The aim was to set a lowest-common-denominator, and to help those who learn best by reading source-code (I&#8217;m not one of them, but I know people who are).<\/p>\n<p>They succeeded in that sense, but weren&#8217;t practical enough for use in production. Artemis came along and showed how you could make something much better, good enough for real games, with relatively little extra work.<\/p>\n<p>But Artemis (as above) was written specifically for Java, without considering how this could\/would work in other languages. And it&#8217;s so popular that we have ports to 6+ other languages now &#8211; each of which has customized Artemis in substantial ways, so that it&#8217;s hard to go straight from Artemis-Java to Artemis-Javascript etc.<\/p>\n<p>So &#8230; my practical benchmarks:<\/p>\n<ol>\n<li>ABOVE ALL: when you write game-source-code using this library &#8230; is it short, sweet, and auto-completed by the IDE, or does it require lengthy typing and manual copy\/paste?\n<li>Every time I use a language feature: first check that feature can &#8216;easily&#8217; be implemented on most\/all other imperative\/OOP languages\n<li>When writing public interfaces: check that every method name, class name, etc is legal in most\/all other languages\n<li>When choosing data-structures: check there&#8217;s a &#8220;natural&#8221; implementation of that in other languages (e.g. &#8220;resizeable\/dynamic List&#8221; exists everywhere; &#8220;ordered HashMap&#8221; does not. Sadly &#8220;struct&#8221; does not :( )\n<li>When using an unusual standard-library (e.g. Java&#8217;s BitSet isn&#8217;t used often in normal apps): check it has direct counterparts in all languages &#8211; or indirect it via a custom class that wraps the platform-specific one.\n<li>When making indirect pointers: think about the &#8220;efficient&#8221; implementation of this on a C-based language; is this compatible with zero-copy memory semantics? If not, it&#8217;ll destroy performance on some platforms\n<\/ol>\n<h2>The Lowest Common Denominator: Objective-C<\/h2>\n<p>It&#8217;s not Obj-C&#8217;s fault: most of the problems come from C. C++ was invented largely to enable OOP coding in C &#8230; so it&#8217;s obvious that C will make modern coding (especially &#8220;library\/API development&#8221;) difficult.<\/p>\n<p>But Obj-C does add some interesting constraints of its own. It&#8217;s a superset of C, but adds its own form of &#8220;classes&#8221; that&#8217;s easy to use but not quite as robust or flexible as the ones we see in C++, Java, C#, etc. It has poor support for structs (a pity: that&#8217;s one of C&#8217;s strengths) &#8230; etc.<\/p>\n<p>All in all: an excellent LCD for porting to other C-family languages.<\/p>\n<h3>THIS IS MAGIC: Generics in Objective-C<\/h3>\n<p>This is some serious voodoo. <a href=\"https:\/\/github.com\/adamgit\/Aliqua\/blob\/1e5c34e42e1ddb621681ea6b04efff9c492181a9\/Platforms\/Aliqua-ObjC\/Aliqua-ObjCTests\/Tests\/TCBasic.m\">My first commit to Aliqua&#8217;s repository has a Unit test<\/a> that does this:<\/p>\n<p>[objc]<br \/>\nPosition* p1 = [[[Position alloc] init] autorelease];<br \/>\np1.value = 42;<\/p>\n<p>ALIListComponentInstances&lt;Position&gt;* positions = [ALIListOfPositions listOfPositions];<br \/>\n[positions set:p1 forEntity:0];<\/p>\n<p>Position* fetchedPosition = [positions getPositionForEntity:0];<br \/>\n[\/objc]<\/p>\n<p>The first two lines are creating a new Component (the standard example: Position).<\/p>\n<p>But the next three lines &#8230; whoa! That looks like Generics! And it&#8217;s somehow magically typesafe without casting! WTF?<\/p>\n<p>Some <a href=\"https:\/\/github.com\/tomersh\/Objective-C-Generics\">smarter people than me<\/a> (and <a href=\"https:\/\/github.com\/samnung\/Objective-C-Generics\">an improved fork<\/a>) figured out a clever way to auto-generate Protocols that simulate <strong>one aspect<\/strong> of Generics: the return-type.<\/p>\n<p>I looked at this, went &#8220;WTF?&#8221; a few times. I thought about it, came back to it, tried it a few times. Then eventually figured out a way to make a Generic container for Component classes that&#8217;s automatically typesafe on iOS\/ObjectiveC &#8211; using the ideas from Artemis&#8217;s Bag class.<\/p>\n<p>The best bit of all?<\/p>\n<blockquote><p>\nXcode5 auto-completes class and method names that are being auto-generated by C-style macros\n<\/p><\/blockquote>\n<p>Oh yeah! So all that stuff like &#8220;listOfPositions&#8221;, despite existing nowhere and being created on the fly (the Position.h and Position.m files have a one-liner to say &#8220;this is a Component, please DO YOUR VOODOO MAGIC&#8221;) &#8230; still auto-completes in Xcode. Yum.<\/p>\n<h2>Next steps&#8230;<\/h2>\n<p>I&#8217;m massively massively over-committed right now (7 x client apps to launch before the end of this month, plus a whole bunch of awesome stuff I&#8217;m trying to get funded and launched) &#8230; but I&#8217;m sneaking this library into my own projects now, and I&#8217;ll gradually add to it as I go.<\/p>\n<p>I recommend Star&#8217;ing on GitHub: <a href=\"https:\/\/github.com\/adamgit\/Aliqua\">https:\/\/github.com\/adamgit\/Aliqua<\/a> and following along.<\/p>\n<p>As it stands, I probably won&#8217;t touch the other languages until Summer 2014, when I&#8217;m going to try and unify this with a Unity3D project (!) &#8211; giving me an excuse to try this design with C#. But anyone else who wants to port to other languages as we go along is welcome&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve started a new open-source project to make an ES designed specifically to be ported to different platforms and work the same way, with the same class\/method names, on every platform: Aliqua.org Here&#8217;s some thoughts on &#8220;why&#8221; I&#8217;m doing this, and &#8220;how&#8221; I&#8217;m making it work&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[60,51,20],"tags":[],"_links":{"self":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3093"}],"collection":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/comments?post=3093"}],"version-history":[{"count":11,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3093\/revisions"}],"predecessor-version":[{"id":3104,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3093\/revisions\/3104"}],"wp:attachment":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/media?parent=3093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/categories?post=3093"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/tags?post=3093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}