Live data from Hacker News

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

github.com

111–120 of 179 posts

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

#111

Earlier quoted context omitted.

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.

We're slowly getting there though. I hope to release a blog post soon about how it might look like in Nim.

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

#112
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…

D has templates, yet their error messages seem fine for debugging what's going on.

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

#113
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…

[deleted]

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

#114

Earlier quoted context omitted.

I felt the same way dipping my toes in C++ for a few years. C99 is definitely my preferred language. But when in Rome...

I'm kind of curious about doing this more often, but it's the lack of clean collections that puts me off. What do you do regarding collections? (Dynamic arrays, hashmaps)?

> What do you do regarding collections? (Dynamic arrays, hash maps)?

I don't do anything!

I use the most appropriate data-structure and minimal transformation necessary to get the work done. I use maths and higher-level tools to verify my designs but the implementation, when required to be soft-realtime needs to exploit as much mechanical sympathy from my target platform as possible.

You might be interested in https://dataorientedprogramming.wordpress.com

Cheers!

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

#116
post #99

Earlier quoted context omitted.

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…

I agree that 2PI leads to all kinds of pain, but what I meant is not 2PI. Here's a more complete example:

  class Foo
  {
  public:
    static Foo* create()
    {
      Foo* result = new Foo();  //exceptions disabled so new can return nullptr
      if ( result )
      {
        //configure result here
      }
      return result;
    }
  private:
    Foo() {}
  };

  ...
  Foo* badFoo = new Foo(); // compiler error because Foo() is private

  Foo* foo = Foo::create();  //all good, no 2PI and can't forget to call initialize code
  
  if ( foo ) //check for non-null, note, if using an optional you'd also need a similar check
  {
    ...
  }
Now the only way to create a Foo object is through the create() function and there is no separated initialize - it all happens in the same place.

This pattern of using a static create method is explicitly designed to avoid 2PI and is very common, especially in codebases that disable exceptions.

Also note that I'm not personally advocating using it, just that it is commonly used to avoid 2PI.

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

#117
post #33

Earlier quoted context omitted.

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?

Most likely having an explicit copy method instead of a copy constructor.

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

#119
post #68

Earlier quoted context omitted.

You don't have constructors that 'fail'.

So, allocating memory for objects is not part of construction? Again, why not just stick with C?

> Again, why not just stick with C?

The thing that is hard to replicate in C is destructors. Automatic deinitialization when leaving scope in very convenient. It allows you to have multiple exists from the scope without preceding each of them with prologue of dinit_*() calls or creating single exit point and jumping to it.

Coupling allocation with initialization is trivial to do without C++ constructors (which I find to be very poorly designed).

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

#120
post #68

Earlier quoted context omitted.

You don't have constructors that 'fail'.

So, allocating memory for objects is not part of construction? Again, why not just stick with C?

Memory for objects is allocated structurally as part of the object, not dynamically, wherever possible. And it's usually very possible. If you can't do that, provide an initialization method. (In almost all cases, I would personally prefer hiding that two-phase initialization within a factory function.)

As for "why not stick with C"--all of the other reasons still hold true, from templates on down. The simple existence of dtors with viable scope guards that are guaranteed to fire when exiting scope is reason enough for me to never write C and to look with a default skepticism on any codebase that thinks its developers are perfect enough not to need them.

Post reply on HN