
Show HN: Crown – A flexible game engine written from scratch in C++ - dbartolini
https://github.com/dbartolini/crown
======
lazyjones
While I find the "sane C++" approach pragmatic and practical all things
considered, I'm firmly in the "time to use a better language if possible"
camp.

The problem with approaches requiring extra discipline is: it's an extra
mental burden to bear while programming. Also, you'll always be limited by the
fact that you're working in a less pure ecosystem and will likely end up using
libraries written in "not very sane C++" anyway.

We seem to have flexible compiler SDKs these days (LLVM etc.), why isn't there
a strict "sane C++" or "orthodox C++" subset available as a custom language or
compiler option yet?

~~~
simias
The first step would be to actually define such a subset. And what happens
when this subset calls into "full" C++? If you don't want to lose
interoperability you have to be pretty conservative with the things you
disallow.

In particular since C++ kept the C-style preprocessor "just copy and paste
that file in there" includes it would be tricky to handle "sane C++" including
"full C++", especially since templated C++ tends to put a massive amount of
code in the headers (think boost for instance, which is mostly .hpp
"headers"). You'd have to tell the compiler to switch the "sane" flag on and
off within the same translation unit depending on the original source of the
code. Nothing impossible, but not exactly elegant. Alternatively you could use
a new `extern "sane-C++" { ... }`-type block around all your code to tell the
compiler what to do.

At any rate you'll have to make sure that your sane subset can always inter-
operate with the "wild" C++ without any cross-contamination.

But really I think the main problem is that you'd have trouble getting a
consensus on what would be your sane subset. Some devs will tell you to get
rid of exceptions altogether, others will tell you that multiple inheritance
is the work of the devil. Some will want to ban raw pointers (or at least
severely gimp them). And some will want none of that but something else
instead.

~~~
lazyjones
> _But really I think the main problem is that you 'd have trouble getting a
> consensus on what would be your sane subset._

This can probably be solved by adding flexible configuration options (C++
compilers already have plenty). In practice, project leaders would then decide
on a set of such options, similar to what happens with code style guidelines.

Perhaps some day a majority of people will agree on a "good" subset of C++ /
option set and it will become standardized as a new language or dialect.

------
krapp
I'm not trying to be too critical, but the first thing I look for whenever I
come across a new game engine is an actual game implemented in it.
Unfortunately, almost none of these engines ever seem to get around to
providing a MVP.

~~~
andrewmcwatters
Bingo. Designing a game engine that has no dogfood project(s) just portrays it
has no applied use, and hasn't ran into issues with its own design before.

------
OssetianOdin
I partially agree with "Orthodox C++". Templates should be used only when
needed and for turn the code simpler(not like the abomination used in most of
Boost libraries).

But also, i don,t see any sane reason to reinvent the wheel and reimplement
basic stuff like thread/mutex classes when the C++ version works well. Or
using "NULL" instead "nullptr", or using that pre-processor macro garbage
instead templates/constexpr, etc

I think some modern C++ features, that if well used, turn the code much clear
and expressive.

~~~
dbartolini
When I started the project C++11 was not supported well on most compilers. I'm
fine with new features when they don't limit my freedom.

I'm fine with nullptr, it is going to replace NULL very soon.

~~~
sqeaky
You should just replace it and define a nullptr macro for older compiles.

------
zakirenish
If you come to finance, most of the developers love premature templatization,
it makes them feel like they know something. Not sure it that can be
attributed to their insecurity about C++ coding skills, but it gets really
ridiculous at times.

~~~
jcranberry
I have a friend who runs a hedge fund, not really insecure at all but uses
templates vigorously. More stuff in compile time rather than runtime. In
critical sections inheritance can be prohibitively expensive because of the
use of lookup tables.

~~~
monocasa
Thrashing your I$ because you have too many template instantiations can be
prohibitively expensive too, it's just harder to metric.

~~~
mhh__
Just how many nested templates are we talking about here? You can have that
problem (obviously) with or without templates. Most sane template designs
don't exist when the program is actually run (Debugging them when they don't
work is another matter)

------
aaron-lebo
New hobbyist engines pop up from time to time and then they fade into memory.
Why is this going to be different?

Not to be too grumpy but game engines are a weird thing cause they are such
complex beasts and usually the people using them have invested a lot of time
in learning them. It's fun to make a new engine, but it probably doesn't have
the community nor interest to cover the hard 10 to 20% that inevitably come
up. Seems like the time is better invested in one of the super big AAA engines
or in writing your own.

What's the plan for 2 to 3 years from now?

[https://news.ycombinator.com/item?id=5442366](https://news.ycombinator.com/item?id=5442366)

Polycode had some interest around here 4 years ago, with lots of the same
goals, but haven't really heard from it since. Similarly, how does this
compare to Godot or even something like Torque?

~~~
AHTERIX5000
Yeah, writing game engines can be a great framework for learning all kinds of
useful and interesting concepts (and trying out experimental things!) but an
actual, usable engine needs a ton of "boring" stuff regarding tooling and
asset pipeline that hobby engines usually miss. When artist creates shiny
visuals in <some editor> it is expected to look somewhat like that in engine
and then you find yourself deep in some FBX/whatever SDK/your own loader +
shaders wondering how the pipeline is supposed to work and how all the usual
formats seem to suck in some way. Add animations, IK etc. and suddenly there
is a lot of work to do that production quality engines solve.

That is not to say it is always needed though if the game is really
simplistic. But there are a lot of engines capable of rendering instanced
bouncing OBJs out there.

~~~
badsectoracula
While in general you are right about the boring stuff (although some people
find writing tools far from boring - e.g. me, i should actually write _less_
tools if ever want to finish some of my own stuff:-P) the shiny visual bits
aren't usually "just" imported. In the (commercial, not personal) engines i
worked at, the artists used their 3D mesh editor of choice (max and maya) to
make the meshes but only bothered with the basic texturing in that 3D mesh
editor. The materials were created inside the engine's own editor since
3dsmax/maya's materials both do not make much sense to fully replicate _and_
they lack functionality that the engine's own renderer (and material system)
can provide.

In the last (commercial) engine i worked at, the pipeline was to export the
mesh from the 3D mesh editor (3dsmax or maya) to a custom easy to parse format
and then import it from the editor to a more compact faster and easier to work
with format. Then the artists would create the materials and other resources
that the engine needed to work with from inside the engine's own tools. The
imported resource remembered the original file so that artists could simply
export again and ask the editor to reimport stuff (at a later point we made
the editor to automatically monitor the directories for changes - both Windows
and Linux provide functionality for this - so the artists would simply export
from their 3D mesh editor and the engine's editor would reimport the meshes
automatically).

In the previous (commercial) engine i worked at, things were simpler in that
we only supported 3ds max (although the 3dsmax SDK was _far_ from simple, if
it wasn't for SymbianOS it would be one of the worst SDKs i've worked with...
but that is another story) and we exported animations and meshes directly to a
custom format the engine expected. The exporter also had a "preview" feature
to allow the artists preview the exported files in a standalone viewer that
used the engine's renderer to make sure that things looked fine (in that case
we actually did try to use 3ds max's materials, although in hindsight that was
a mistake since even with the viewer the artists often assigned textures
incorrectly - we should have relied only as little as necessary on 3ds max
instead of making it the primary content editor).

------
comstock
Interesting! I'd be interested in better understanding the motivation behind
Orthodox C++. In particular, you seem to dump most of the C++ standard
library:

"Don't use anything from STL that allocates memory, unless you don't care
about memory management."

I now mostly avoid templatization in my own code unless there's a really good
reason. But the standard library often lets me avoid explicit memory
allocation. Would love to hear more about the motivation for this (and other
aspects of your C++ usage).

Also, if you have a demo of the engine in use that would be fun to see!

~~~
badsectoracula
Generally speaking many C++ game engines avoid the STL stuff and reimplement
their own more predictable containers, often with custom allocation schemes.
The engine at the last game company i worked at, for example, had its own
containers and memory allocator and allowed you to define the allocation
category and pool per allocator and per object class (so, e.g., dynamic
strings would be isolated to their own pool to avoid fragmenting the heap).

Related, Andrei Alexandrescu had a great talk about allocators in C++ a couple
of years ago:
[https://www.youtube.com/watch?v=LIb3L4vKZ7U](https://www.youtube.com/watch?v=LIb3L4vKZ7U)

Also related to the Orthodox C++, the same engine also ousted exceptions and
RTTI. I'm not sure about the reason for exceptions, but C++'s RTTI was simply
inadequate and instead it was replaced with a custom one made using macros
(similarly to wxWidgets and MFC) that allowed automatic object serialization
and reflection which was used for all saving and loading, exposing objects to
the editor automatically with a common UI and exposing classes and objects to
the (custom) scripting language with very little setup.

Interestingly most of the stuff the engine had to reinvent seem to be first
class citizens in the D language. Also Andrei's allocators also seem to be
available (experimentally) there too.

Personally i prefer plain old C (C89 even, although with a few commonly
available or easily reproducible extras like stdint) because i see C++ as too
complex for what it is worth. However D seems to provide more power with less
complexity and more and more makes me want to try it, especially the new
"better C" mode that DMD has got (which i think is somewhat the D equivalent
to Orthodox C++ that is linked from the page).

~~~
ryandrake
> Generally speaking many C++ game engines avoid the STL stuff and reimplement
> their own more predictable containers

This seems a little like cargo cultism. I wonder if any of these shops
regularly measure the performance of their custom containers and compare with
the standard library on a modern optimizing compiler and make a reasoned
judgment that it's still currently worth the trade-offs to stick with their
own stuff.

~~~
stevenwoo
Older implementations of STL had a lot of issues, EA wrote their own version
way back when to address them with a list of whys here: [http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2007/n227...](http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html)

~~~
ryandrake
Right, but that was a long long time ago, 64 bits long. Even calling it "STL"
nowadays kind of dates someone. I wonder how regularly EA currently does bake-
offs between their stuff and the standard library. Not that it would matter at
this point--they probably have so much legacy code depending on it that it
would be painful to switch.

~~~
pixel_fcker
You can clone the repo and run the benchmarks yourself. When I last did it it
was quite mixed (compared to libc++ on a MBP) - a lot of things were the same
or slightly faster in EASTL, occasionally some things were an order of
magnitude faster, some things an order of magnitude slower. Those were in what
I would consider "edge cases" rather than general usage, for which the two
were fairly similar.

As other comments have said though, the main reason it's used (and the reason
I was interested even though I don't do games) is because the allocation story
in the stdlib sucks.

~~~
stevenwoo
My recollection (which could be wrong, it's been a long time) is that the
white papers Microsoft freely distributed for XBox 360 development said
specifically to not use any STL containers except contiguous memory ones and
probably not those either without custom allocators. The penalties for cache
misses/pipeline flushes were very high and naive STL usage made both those
things happen a lot in real games (Microsoft would step in and help developers
and would do post mortems on things they did to improve performance).

------
alkonaut
Wow it seems to contain a full level editor written in vala, a language I
hadn't heard of. It seems to be a high level language similar to C# but with a
native compiler and some different semantics (RC instead of a tracing GC for
example). Is vala widely used?

~~~
rhodysurf
Its really only used for gtk3 apps. I think it was created with that in mind
by the gnome team

~~~
dbartolini
Toolchain was initially written in C#. Vala simplified a lot the switch to
GTK+3. Today I think an IMGUI-like approach is the way to go for game tools.
Rewriting the editors should be rather painless due to their engine-decoupled
TCP/IP architecture.

------
partycoder
The code seems clear enough, though I think the preprocessor macros for
wrapping OS specific logic could be at the function level or class level
rather than at the statement level.

~~~
dbartolini
Why when code amount is small enough?

------
B1narySunset
How long have you been working on this engine for?

~~~
dbartolini
I started with game engines well before I put this project on github in 2012.

~~~
mendeza
Can you recommend any resources/books to learn game engine development? I
would love to implement a mini one where I can rapidly prototype AR
applications :).

~~~
slavik81
You may just want to start by building your AR applications first. After a few
of them, you'll have a better understanding of what common functionality is
needed.

See also: [https://geometrian.com/programming/tutorials/write-games-
not...](https://geometrian.com/programming/tutorials/write-games-not-engines/)

~~~
mendeza
I love the article! It makes sense that after developing AR application on a
game engine, I will identify the common functionality that would fit better
for an "engine" that would fit the ideas I want to develop.

I am interested in developing AR applications that are not as much of a game,
so I was worried that a game engine would not fit.

With both learning more about graphics and making my own games, it would make
future engine development more clear.

------
tempodox
Props for the coding discipline. I couldn't even tell how long it has been
since I saw C++ as readable as this.

~~~
dbartolini
Thanks, I'm glad you like it. :)

------
Jumziey
Really cool work! I would love to have some time over to try it out.

~~~
dbartolini
Hey, thanks. :)

------
andrewmcwatters
Your use of `require` is incorrect.

~~~
dbartolini
Can you elaborate on this?

~~~
andrewmcwatters
[http://lua-users.org/lists/lua-l/2012-08/msg00302.html](http://lua-
users.org/lists/lua-l/2012-08/msg00302.html)

~~~
dbartolini
All resource paths (.lua files are resources like any other) in Crown are
unix-style and do not include the extension.

I have a custom loader that deals with it:
[https://github.com/dbartolini/crown/blob/master/src/lua/lua_...](https://github.com/dbartolini/crown/blob/master/src/lua/lua_environment.cpp#L52)

~~~
andrewmcwatters
I would recommend that you extend `package.loaders` instead. You risk breaking
expected `require` functionality. Then you get the benefits of both!!

[https://www.lua.org/manual/5.1/manual.html#pdf-
package.loade...](https://www.lua.org/manual/5.1/manual.html#pdf-
package.loaders)

~~~
dbartolini
I already do so:
[https://github.com/dbartolini/crown/blob/master/src/lua/lua_...](https://github.com/dbartolini/crown/blob/master/src/lua/lua_environment.cpp#L85)

------
ericfrederich
Great title. C++ is so terrible you have to prefix it with "modern" or "sane"
to get people excited about it.

------
teknico
It's a lost cause: there's no such thing as "sane" or "orthodox" C++. Instead,
use something actually sane like Go. Or Rust, if you really must (first bad
pun is free, then it's 50 cents each).

~~~
zielmicha
Go is a bad choice for game with its unavoidable GC. And Rust is simply too
complicated for a person wanting sane C++.

D or Nim (or even C!) would make more sense.

~~~
dmit
Is there not a point where GC overhead becomes negligible? There have been
production examples of Go maintaining sub-millisecond GC pauses with a multi-
GB heap under a server workload.
[https://twitter.com/brianhatfield/status/804355831080751104](https://twitter.com/brianhatfield/status/804355831080751104)

Surely there are better reasons to disregard Go for gamedev by now.

~~~
aaron-lebo
I've dipped my toes into using OpenGL and Go a few times and it seems pretty
nice. But I'm entry level graphics programming and so it scares me off to go
further (surely someone would have used Go by now in a 3d game, if you can do
Minecraft on the JVM, why not Go)?

I keep wondering if it's not possible or if there's just not a lot of overlap
between Go programmers and gamedevs? Wish someone knew.

~~~
Jach
I wouldn't predict a lot of overlap. On the game dev side, Go offers nothing
new, and the forced untuneable gc will be an instant turnoff for the usual
reasons. On the Go side, my outside perspective is most of its users seem to
be focused on web server backends, trying to justify async everywhere, and/or
rewriting slow Python or Perl or Bash scripts and assuming that makes it a
systems language.

Go users interested in diving in to SDL or OpenGL bindings to make a game
shouldn't be discouraged. Lots of games are made in all sorts of high level
languages, the heavy lifting is put onto a few native libraries. But if the
goal is to make a general engine, I'd question its utility apart from
fun/learning. Again there are game engines in high level languages (with dark
native-level secrets in any that try to be performant) but they don't seem to
get traction. Even an engine in e.g. C++ doesn't necessarily help your
performance goals ([http://www.yosoygames.com.ar/wp/2013/11/on-mike-actons-
revie...](http://www.yosoygames.com.ar/wp/2013/11/on-mike-actons-review-of-
ogrenode-cpp/)) if your plan is to make it general instead of make it just
support whatever sorts of games you're making and planning to make.

------
mikepurvis
A cross platform project in modern C++ that doesn't use CMake? Unsure if want.

~~~
dbartolini
It is not "modern" C++. It uses GENie, a fork of premake.

~~~
mikepurvis
Huh. Okay, that was not immediately apparent from viewing the project— it
looked like a hand-written Makefile. Link for the curious:

[https://github.com/bkaradzic/GENie](https://github.com/bkaradzic/GENie)

Appreciating that CMake has its warts, it also has a ton of mindshare and has
lots of convenient modules for handling common dependencies. What are the
motivations to use a Lua-based scheme instead?

~~~
dbartolini
I find GENie/premake way simpler to read and write. Also, you have more
flexibility since your build scripts have full-fledged Lua capabilities.

~~~
mikepurvis
Yeah, similar sentiments in the PPT presentation here:
[https://onedrive.live.com/view.aspx?cid=171ee76e679935c8&pag...](https://onedrive.live.com/view.aspx?cid=171ee76e679935c8&page=view&resid=171EE76E679935C8!139573&parId=171EE76E679935C8!18835&authkey=!AKv_SGrgJwxDGDg&app=PowerPoint)

CMake is "too complicated" and "you need to be an expert". Understandable, I
suppose. There are certainly specific things in CMake which are pretty
terrible, like the add_custom_command/add_custom_target dance, but from the
perspective of someone who has had to become an expert in it (via ROS/catkin),
I would be unlikely to give it up. There's just way too much stuff it gives
you for free, especially when it comes to things like packaging, testing, etc.

------
JabavuAdams
Great learning project, but for production just use Unity unless you
absolutely, positively (triple-check) cannot. You will be massively more
productive.

~~~
thehardsphere
Umm, no. Unity has lots of problems that make it not ideal for games that have
fast action or are developed by a larger team.

Like, the fact that it uses an old version of Mono on not-Windows, which uses
a mark and sweep garbage collector. You end up with frequent stop-the-world
garbage collection pauses that freeze the screen for seconds at a time. Play
any Unity game on the PS4 and you'll see it frequently.

I've also heard that Unity's project asset management doesn't really work for
teams that have more than 10 people working together, but that's something I
don't have direct knowledge of.

~~~
aphextron
> You end up with frequent stop-the-world garbage collection pauses that
> freeze the screen for seconds at a time. Play any Unity game on the PS4 and
> you'll see it frequently.

This is a coding problem, not an engine problem. A game should have almost no
dynamic resource allocation.

~~~
thehardsphere
Then what about Unity leads everyone who uses it to allocate dynamically,
somehow, on every platform but Windows?

If everybody makes the same coding problem, and the common denominator is one
of their dependencies, it makes you wonder what's wrong with the dependency.

~~~
meheleventyone
If you're genuinely interest the developers of Inside have a great
presentation on how they hit a stutter free 60fps on all platforms, PS4
included.

[https://www.youtube.com/watch?v=mQ2KTRn4BMI](https://www.youtube.com/watch?v=mQ2KTRn4BMI)

I don't know what projects you're referring to specifically on the PS4 but I'd
suspect the difference comes down to hardware spec on the PC masking the
issue, it probably being the primary platform and/or lack of time to work on
optimisation for the port.

It's the use of C#, which generally written in a manner that creates garbage
and lack of experience with programming games that causes many people who use
it to go wild with allocations. Both intentionally and by accident. These days
you can actually get pretty far before it's ever a problem on a gaming PC.
Unity is also incredibly accessible so more people with less technical chops
are programming games without even opening the profiler.

------
Jeaye
Yet another game engine written in an imperative language, seemingly with the
focus on writing something in Orthodox C++ and not necessarily writing
something to solve a problem. Just as the discussion on this post shows, the
more interesting thing here is Orthodox C++, not yet another game engine which
doesn't offer any featues that modern game engines offer.

If you're expecting people to see this as a useful product, please explain why
it should be used instead of the existing game engines. Consider listing its
features and comparing them, maybe in a table, to popular game engines.
Deferred rendering? Multi-threaded rendering? Entity-component system? etc.

Right now, I can see it has a (nice looking) editor, "physics" (nothing's
moving, so it's hard to tell), and "animation" (again, nothing's animating in
the image). Alas, one needs to learn to use its entirely fresh standard
library reimplementation, and likely its strict C++ subset, if one actually
wants to be productive with it. Given apparently no active community, no
sample (or actual) games written in it, and no paid support, I don't see how
that would be feasible.

If you have no interest in actually making a competitive, novel, or useful (to
others, compared to existing solutions) game engine, please just say that. In
that case, I'd just say this is a neat side project: well done, but try to
focus on building something with it to help sell/prove its features.

~~~
dbartolini
It is just a simple general-purpose, data-oriented, data-driven, entity-
component based, lua scripted game engine written in sane C++ for my own game
development needs.

Nobody's trying to sell anything here.

