1. 21

  2. 1

    Should’ve chosen Lua, and gone with MOAI or Corona or something .. these frameworks are designed to solve the problems he had. Otherwise, its like they are re-inventing the wheel .. not necessary, but not a rare compulsion.

    1. 10

      Depending upon your goals, that could of course be a perfectly reasonable approach. I had a couple of goals that led me to make other choices (keep in mind this is purely a hobby project, so even if it turns out I’ve made a terrible choice, it’s not a huge problem):

      • I want to be able to experiment with more complex, expensive algorithms. I realize I can embed native code and call it from Lua, but I’d prefer to be able to write most of the code in one language, and not have to worry about whether I’m on the right side of the performance issue. My alternative option was just to use C++ (which I’m quite comfortable with), but wanted to experiment with different options that offer same order-of-magnitude performance out of the box.
      • I’m ok “reinventing the wheel”, again because it’s a hobby project. The last time I worked on a game professionally in the 90s, we were still writing software renderers by hand in x86 code, so I’m also using this as an opportunity to internalize all the changes in the graphics/simulation state-of-the-art that have happened since.
      • I do think it’s a worthwhile pursuit to look into alternatives to C++ for the “base language” for game development, as a forward-looking exercise. If I were starting a professional project, I would of course just stick with C++ to stay safe, but hobby projects offer a good opportunity to explore alternatives with less risk.
      1. 4

        Lua seems like a poor choice given that his first requirement was “Fast output: It doesn’t need to be precisely C speed, but it needs to be close.” Lua’s pretty fast for a scripting language but it ain’t no C. Go benchmarks an order of magnitude faster than Lua:


        1. 2

          There’s no benchmark there for LuaJIT, which can approach - and in some cases even beat - C/C++ speed.

          1. 4

            No doubt, LuaJIT’s a great achievement, and if I’m looking for a fast embedded scripting language, that’s exactly where I’d look first. I can’t find any good non-trivial benchmarks comparing LuaJIT to C, but I keep hearing that it can be comparable, especially in cases where the tracing JIT compiler can re-optimize hot paths based on runtime knowledge. Notably, this is often true of Java as well, even though non-trivial Java programs often perform 2-3x slower than the equivalent C++ (c.f. http://www.j15r.com/blog/2014/05/23/Box2d_2014_Update).

            At the same time, I have no interest in writing an entire game engine in Lua. Dynamic types are fine for small scripts, but I find that it’s hard to maintain a big dynamically-typed codebase. That’s just my experience, of course, but my experience is what matters for my own decisions.

            Also, as I understand it Lua would give me little to no control over memory allocation and layout. I presume this is one of many reasons you don’t see large professional games written entirely in Lua, even as it’s obviously quite popular as a scripting language.

            This isn’t to say, of course, that you shouldn’t use it this way if it works well for your purposes. Just that my goals and constraints have led me to try something different.

            1. 1

              As someone struggling to understand why anyone likes go, that’s an interesting combination of requirements to see, and one that I hadn’t known would exist; at the very least, thanks for sharing.

              I’m surprised you’d care that much about memory layout but be happy with GC (you link to a thing about pooling but that exists in many languages with mature implementations, it’s not a go-specific thing at all). I would’ve thought the two would go together, which would suggest the likes of Rust or D if we want precise control. If we’re allowing GC my go-to language thoughts are Haskell or Scala, both of which seem to outperform Go on those benchmarks, which seems to suggest that this memory layout control doesn’t translate to a practical performance advantage (at least for these benchmarks).

              I’m also surprised that you’d dislike the idea of maintaining a large dynamically-typed codebase, but be happy with Go’s limited type system; my (admittedly very limited) experience is that interface{} ends up being pretty common, because it’s the only way to write any kind of generic code. In Rust or Haskell you do have a certain amount of “type parameter hell”, but the tradeoff seems to be the same as the one you’re making by using types at all.

              1. 3

                I don’t want to turn this into a debate on the merits of Go as a language. I’ve seen how that plays out on HN and elsewhere, and afaict it serves no purpose other than to raise the cortisol levels of all involved, quite unnecessarily. My company (fullstory.com) is using Go very successfully for high-scale server infrastructure, in a way that I know from experience would be difficult on the JVM. That’s just one data point – take it for what it’s worth, and feel free to ignore it if you have different needs or feel you have a more effective way to meet them.

                As for the question of being “happy with GC”, that’s not really the point. I want two things – control over memory layout to minimize the overhead of memory management (GC, ref-counting, whatever); and to lower the cognitive and debugging overhead of getting it right. I feel like we can do better than C++ without sacrificing much of the performance we expect from it. Go’s approach – GC, but with much more control over memory than you get in a typical VM language – is one that might prove fruitful. Rust’s is another, and while I’m not exploring it in depth right now, I fully intend to continue playing with it in my spare time.

                I also don’t believe it’s a question of whether Scala, or whatever, outperforms Go on microbenchmarks. First, I’m not writing a microbenchmark, I’m writing a game, and what matters is the performance of the whole thing, in all its complex glory, not just at the leaves. I also have every reason to believe that Go’s generated code will continue to approach that of raw C (only time will tell, but there’s no obvious theoretical reason to expect otherwise). Now of course if raw performance were the only concern, I’d hunker down and spend ages building, in C, a thing of perfect crystalline beauty. But of course we all know that’s not the only concern, so things like memory safety, good concurrency primitives, fast iteration, and all that matter as well. It’s always a tradeoff, and a different balance of goals will lead you to different conclusions.

                On type systems, I find (again YMMV) that there’s such a thing as both too little and too much. Too little, and you can’t tell what the hell’s going on anywhere in your code, and all your errors become hard-to-track runtime failures. Too much, and you can spend ages fiddling with type parameters just to satisfy the type checker. My experience with Go has been that interface{} creeps in here and there, but in normal concrete code (at least mine) it’s fairly infrequent. And even when it does crop up, it rarely turns into a runtime failure, or if it does it’s pretty fast and easy to track down, because most of your code is cleanly typed, so there are only a few places it can go wrong. This isn’t all that different than the number of times you’re forced to use Object in old versions Java/C#, or void* in C. Except that it’s a lot less because you have pseudo-generic slices, arrays, and maps. These may seem like kind of a hack from a theoretical perspective, but I find that they’re pragmatically useful.

                All my experience, but hopefully that will help you understand where I’m coming from.

              2. 1

                Lua doesn’t let you manage memory at the language/interpreter level, but rather at the level of the VM. You can do all the management you want in C/C++, and then interface that to the Lua scripting engine .. and thats sort of a good way to isolate responsibilities/duties throughout your engine or framework, anyway. Managing everything manually is a sure-fire way to get yourself in a pickle if you’re also mixing game logic with your engine - isolating the logic from the engine means a lot less hassle in the mid-/long- term. Of course, you have to get used to mixing languages in your project, which in the case of the OP may be enough of a reason to warrant ignoring this advice. But I’ve found (as an active user of/contributor to the MOAI game framework - http://getmoai.com) that this separation of duties always pays off in the lifetime of a project.

                YMMV, of course, and it sounds like you’ve selected your tool of choice with no looking back; for those also interested in this topic of game engines, though, doing everything from scratch in Go versus using the existing, extremely productive technologies in the Lua/LuaJIT world could make all the difference ..

                1. 3

                  Yes, that’s all quite reasonable. As I stated in the original post, my goals are different, because part of the goal is to explore alternatives to C++. I’ve done my time writing giant piles of C++ in a past life, and much like Jonathan Blow and others, I think it’s a worthwhile exercise to consider alternatives. So to the extent I’ve “made my decision without looking back”, it’s simply a question of assuming using Go at the base will work well, then trying to confirm or refute that hypothesis.

                  But as I’ve said elsewhere, if I were still building games for a living, and under the attendant pressure to ship a game that works efficiently, in a fixed time-frame, I’d of course still be using C++ with something like Lua bolted in for scripting. Of course, I’d also most likely use an existing engine as well, because ain’t nobody got time to build yet another engine, at least not without a damned good reason!

                  But for a hobby project, I get to do inefficient things in order to explore and learn :)

        2. 1

          I’ve been developing games in Go since I started to learn the language over 3 years ago. I think it can be a pretty good choice for the client and a fantastic choice for a multi player server. Having both in a single binary, cross compiled to a single binary for each major OS is a nice benefit. It’s worth watching https://godoc.org/golang.org/x/mobile since I’m pretty sure OpenGL in Go will converge to that API

          1. 1

            Do you know if the GLES implementation in that API (or an equivalent) can be used on the desktop? For my purposes, ES would be sufficient, and simpler than trying to deal with desktop and mobile GL separately.

            1. 1

              Yep, works fine on desktops. Personally I have only tried it on Linux but I believe it’ll work anywhere.