On Wednesday, 10 May 2017 at 12:52:34 UTC, JN wrote:
I wonder, would it be possible for D in the current state to
achieve the same? I imagine iOS isn't possible yet and Android
is just getting there?
I've been developing a small 2D PC-only game in my free time over
the last year or so (10 kLOC so far). It's very much still in the
early stages, but I'll add some of my experiences here in case
it's useful.
For context, I'm a developer of 2.5 years at a medium-sized
studio that ships full-price games. At work we use C++ (msvc) for
the engine, Lua for scripting, and C# for tools.
TLDR: You can totally make a game in D right now. However, it's
definitely not ideal. Be ready to deal with untested
tools/libraries, wrangling with how you call out to C libraries,
and a couple hacks to the D source to make things work the way
you want.
PROS
I'll skim this section, because you all know the pros of D at
this point :) No header files, sane templates, way better
introspection, the list goes on. D is one of the nicest
programming languages I've had the pleasure of working in. It's
not without its faults, but my experience so far is that it's the
language I most want to be developing a game in right now. We'll
see if Jai might take that throne some day, but I reserve
judgement until I can actually get my hands on it, and even that
might still be years out.
The Rust article mentions build times as a downside. In contrast,
that has been one of the upsides of D for me. My build time is
~1.75s for a usual-case rebuild (all the game files), and ~4.5s
for a full rebuild (the game, plus all heavy templates (like
regexes), and all library glue code (like derelict)). Rapid build
times are one of the killer features of DMD, and it makes me
happy to know it will continue to be a focus as development
continues.
CONS
The debugger. Rainers is doing great work with Mago, I suspect it
simply needs more developers giving it some love. It's currently
a far cry from the MSVC debugger. Mago crashes/hangs regularly
for me, doesn't step in and out of functions consistently (and
you can't reposition the instruction pointer by dragging if you
miss a function call you want to re-run), is inconsistant about
which variables I can see and which I can't, and lacks features I
miss greatly (like data breakpoints). This is *by far* my biggest
pain point. I'd like to look at it at some point and try to
improve some of the low-hanging fruit, but debugging a debugger
is a daunting proposition.
DLL support. I've made a handful of hacks to druntime to allow me
to implement hot-reloading via a DLL (a la Handmade Hero). My
problems all stem from the fact that a D DLL has its own copy of
the runtime and GC. I use the GC proxy to redirect calls from the
DLL's GC to the EXE's GC, and have hacked together a similar
solution for redirecting the spawning of threads. On top of that
I had to completely disable finalizers, and pretty much avoid
using classes altogether (at least any that might need to outlive
a frame or survive a hot reload). I'll bet it's no easy task to
implement, but if D supported "light" DLLs (ie DLLs that just
work out of the executable's druntime), probably 2/3 my hacks to
D would evaporate. This all being said, the hot reloading works
marvellously with these changes, and it combined with a <2s build
time makes day-to-day development far more of a joy than at work.
The GC. This is an issue in games for reasons already tread many
times over. It's lower on my list because it's relatively
straightforward for me to intercept GC calls and do my own memory
management instead. I've hacked in a setup that lets me swap
allocators at runtime. For example, I can add a line at the top
of a scope that says "for the duration of this scope, allocate
into the scrapheap" (a bump-the-pointer stack that gets wiped at
the end of each frame). I currently use the GC by default, and
manually specify an allocator to use anywhere I'm generating
excessive garbage, but this strategy will likely change as
development continues and performance constraints start becoming
more strict.
Library support. Basically the same as mentioned in the Rust
article. I regularly try out libraries where I find a critical
bug within an hour of using the library. I've used libraries
(plural) that interface to C but use the wrong calling
convention, so before I discovered the problem, every function I
called was a crapshoot as to whether or not some subtle
misbehaviour or outright crash would occur.
For reference, the libraries I'm using are:
- SFML (graphics/windowing, misc utilities)
- FMOD (audio)
- dear imgui (debug UI)
- msgpack-d (save game/state serialization)
- OpenGL (just tiny bits here and there for stuff SFML and imgui
don't handle out of the box)
- speech4d (TTS for placeholder dialogue, I heavily modified this
library to fix some critical bugs and make it work better for my
purposes)
Any questions, ask away!