Live data from Hacker News

Show HN: Crown – A flexible game engine written from scratch in C++

github.com

101–110 of 179 posts

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#101
post #8

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).

If you're gonna bother with orthodox C++, or Go (suited to 3d games? nobody seems to have tried or lived to tell the tale), or Rust (no libraries anyway, so you may as well use something which wraps C easily and is higher level), why not try Nim?

I think if you were writing C, then Nim might be a good alternative. If you're writing C++, then Nim offers a lot of similar metaprogramming features; but it lacks RAII, which IMO is a monumental drawback. People may dislike C++ for many reasons, but RAII is a killer feature -- there's no question why languages like D and Rust adopted it.

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#102

Earlier quoted context omitted.

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…

> 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 s…

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...

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#103
post #83

Earlier quoted context omitted.

What's wrong with using templates vigorously?

Some things that are not so nice about templates: - dozens to hundreds of compiler error lines for a single error, where it's hard to find out what the real problem is (IDEs often point to the wrong line) - Code is hard to follow. E.g. try to figure out from boost asio source code which code is actually used if if you do a async_read(socket). I personally gave up after the second level of template substitutions, and…

All three of these seem to be compiler/tool UI problems and not problems with templates themselves.

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#104
post #8

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).

sane like Go Yet Go uses the oh-so-error-prone return value error checking that has been so successful in C :/

Still better than

try:

  ...
except:

  pass

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#105

Earlier quoted context omitted.

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…

> 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 s…

IME most of it is due to how bad c++'s builtin allocator support is though. C++11 helps a little but a lot of stuff you might want to do seemed to be impossible last time I looked. This is awful since games will often use pools and arenas, often heavily.

Part of it is also for cross-platform consistency. No chance for bugs caused by using a different stdlib, etc. This is worth it when a lot of the toolchains for consoles are arcane have the chicken/egg-ish problem of often having poor stl implementations since they expect everybody to implement their own.

I've been out of game dev for a while though. These days I'd expect using the C++ stdlib to be more common, and mallocs are faster now (although even if you're bundling e.g. jemalloc, I imagine you still get a substantial benefit from using pools or arenas in many cases).

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#106

Earlier quoted context omitted.

> 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 s…

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...

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.

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#107
post #99

Earlier quoted context omitted.

I don't think this is the proposal. The proposal is that the object contains a genuine constructor that only does the bare-bones "safe" stuff, and then it has a separate non-static method that does the might-fail initialization. So: class Foo { public: Foo(); bool initialize(); // returns success ... }; ... Foo foo; if ( !foo->initialize() ) { // handle error } This also means you can break up your initialization so…

It was almost the exact proposal specified by my grandparent post except using a pointer rather than an optional. It's also a technique that is widely used. See for example the cocos2d-x game library. The benefit of such a technique is that you can then make the constructor private, making it impossible to create an object and not also call the initialize() method.

It is very different from having a static method returning an optional, which guarantees that you can access the optional (with at least an assert in debug mode) only if the object is actually successfully constructed.

Using a separate initialize member function means that you may have objects in a zombie state laying around after a failed construction which lead to all kind of initialization order issues (you might get a pointer to the object, but is it initialized?). Also you need to remember to check the return type, which also need to be meaningful (does it return false on failure? or it returns 0 on success?).

Two phase initialization is a known antipattern which is, unfortunately, widely used and lead to all kind of pains.

Friends do not let friends use 2PI.

edit: sorry, I misread your comment, you were referring to the static function returning a pointer, which as you note is almost the same as the optional version. It forces heap allocation though, which is bad.

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#108
post #92

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…

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++…

> 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.

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#109
post #98
post #88

Earlier quoted context omitted.

Not quite. Try this: import "os" func main() { os.Open("this file does not exist") } This will compile just fine, producing no compiler error or warnings whatsoever. The error is just silently ignored. Compare to Rust: use std::fs::File; fn main() { File::open("this file does not exist"); } This will produce the following warning: warning: unused result which must be used --> test.rs:14:5 | 14 | File::open("this file…

A slightly related note: you can get similar behavior in C (and C++) with compiler extensions. In GCC and clang marking function with '__attribute__((warn_unused_result))' will produce a warning if function is called without using the result. Equivalent for MSVC is '_Check_return_'. Obviously this is not nearly as convenient as your Rust example, but enables some of its the benefits.

C++17 has (will have?) [[nodiscard]] with the same semantics.

Re: Show HN: Crown – A flexible game engine written from scratch in C++

#110
post #33
post #17

Earlier quoted context omitted.

If you disable exceptions hoe do you handle failures in constructors?

Instead of using a constructor you can use a constructor method e.g.: class Foo { public: static std::optional create(); private: Foo(); };

How would you handle failure in copy constructors?
Post reply on HN