Skip to main content
MaulingMonkey u/MaulingMonkey avatar

MaulingMonkey

u/MaulingMonkey

Feed options
Hot
New
Top
View
Card
Compact

There is non-axiom FTL, it's just slower (≈700c?) and experimental.

“Our main ship, The Dauntless, was able to work properly in Cruel Space, including crossing a distance of about a quarter of a percent of the galaxy wide in just four months. Now that’s a very long time compared to Axiom assisted travel but...”

https://www.reddit.com/r/HFY/comments/10svg9j/out_of_cruel_space_part_584/

...and a little spicy:

First problem was that trying to get anything with the engines needed for crude FTL through the Ozone Layer made a really, really big bang.

We’d been warned about this from the program so that first flight had been unmanned just to see how big a bang it would be. Most of the people that looked at it directly needed experimental optical surgery to see again. People like me that saw it through a recording were blinking spots out of their eyes for hours to come. Still it was really neat to see a double-sided mushroom cloud.

https://www.reddit.com/r/HFY/comments/nfsakq/out_of_cruel_space_part_1/


JOD 148 makes a passing mention of plans to build a ringworld as "a healthy nudge toward Type II efficiencies"... but it's unclear how concrete or speculative said plan is, and on what kind of timeline, and even a single ringworld is a far cry from a full dyson sphere made out of 100% efficient unobtainium solar panels.

Now, if we're hoping to make up for that by bulk of worlds, each power only controls a thousand or so (previous discussion)... and that number presumably includes agricultural and primitive worlds that haven't been given the full Type I treatment... hell, have any SSB worlds been given the full Type I treatment? And you'd need millions of full Type I worlds to reach Type II, considering the tiny fraction of Sol's output is captured by Earth? (EDIT: or tens of billions if going by Sagan's extended model where Type II is ten orders of magnitude - 10,000,000,000 times - more watts?)

...I'd buy "above 1.0", but I'd also buy "approaching 1.0".


> The real solution is to allocate everything up-front, and have no memory allocations once your game has begun.

Hot take: there's no such thing as "allocating everything up-front".

You can pre-create an array of 10,000 entities, but then you still need to keep track of which ones are alive or dead and reusable. This is custom allocation in everything but name, and so I prefer to fix the name and explicitly call it allocation. It's just a pre-sized, contiguous, type-specific pool allocator, with allocated objects possibly accessed by id, handle, index, or generational index instead of by raw pointer.

By virtue of all the strict limitations imposed by this allocator, it's extremely simple to write. If you're feeling particularly crazy you can write a macro that overloads new/delete for a type and forwards them to such an allocator - this won't give you the full cache-friendly performance advantages of iterating over the contiguous array in it's natural order - you'll instead probably still iterate over arrays of pointers into said contiguous array - but it can still nail some of the allocation performance and fragmentation issues pretty quickly. The default C++ new/delete interface isn't very friendly for falliable allocation (catching std::bad_alloc or null-checking after using std::nothrow) but can also be done.


I've had my share of bugs where manager.instance.a was used in the middle of deconstructing the audio manager, resulting in crashes and worse when exiting the game. When a bunch of code all reference it directly, it can turn into a tangled mess.

Dependency injection is one possible "fix" that usually ensures sane construction/deconstruction order - in a more complicated engine, you might use this, and have some kind of entity factory responsible for constructing fish and dogs from data, including delaying their creation until textures/models/sounds are all loaded, and the factory would be the one holding a reference/pointer to Audio.

Going the other way, another "fix" would be to hide the fact that you have an Audio manager at all:

void dog::animate(...) {
    ...
    event("dog-footstep", position, velocity, intensity);
    ...
}

This could trigger 3D audio events (footstep sounds), spawn particle effects (dust particles from walking in the dirt), contribute to "Mush! Mush!" achievement progress in your sled dog race simulator, etc. which can all be driven by system specific data files.

In this example, dog doesn't need to be fixed to handle the case where Audio isn't initialized yet. Or has been unloaded during game exit. It's possible that "event" could have bugs, but they tend to be simple and easily fixed:

  • If using a list of event listeners, adding Audio to the list before it's fully initialized - or not removing Audio from the list before it starts to be cleaned up - could lead to crashes.

  • If hardcoding which systems you use under the hood inside the event function, not checking if audio is initialized / cleaned up before using it.

Having a list of event listeners is extremely flexible:

  • If I haven't implemented the audio system for a new platform yet, I can simply not register it and the code will run without crashing.

  • If I have a crash bug in the audio system and want to provide a workaround for our designers until I can fix it, I can provide them a config option or flag to simply skip registering the audio system.

  • If I have multiple audio systems (because I'm replacing DirectSound with XAudio2 in preparation for a console port) I can easily swap around which audio systems are registered at runtime without a mess of conditional logic all over the place. I can just have AudioSystem_DirectSound and AudioSysten_XAudio2 and register/unregister them in one place.

  • If I'm doing fancy 3D audio where multiple console players each have their own headset connected to their gamepads, I can register multiple listeners that calculate the left/right balance and volume separately for each headset depending on which way they're facing, and how far from the event they are.


To avoid double-frees, those move ctors/assignment operators need to null out other.managedData (turning ~abc into a noop for the 'moved from' object)

    abc(abc&& other) { //move constructor
        managedData = other.managedData;
        other.managedData = nullptr;
    }
    abc& operator=(abc&& other) { //move assignment operator
        managedData = other.managedData;
        other.managedData = nullptr;
        return *this;
    }

Depending on what your own destructors do, you may need to add null checks - I'm (ab)using the fact that free(nullptr) is a noop.


I'd call 2% "mostly idle", and I'm using even less typing this reddit comment. It's not like it's running at a continuous 2%, it's short bursts of activity (maybe every 1/60th of a second or so, to pick a typical monitor refresh rate) divided by (relatively) long spans of doing nothing (aka being idle). It's probable that the GPU is running in a reduced power state for the both of us as well, where large swaths of the GPU are actually turned off - not merely "idle" - in an effort to save battery power, extend component life, reduce fan noise, etc. - it's not like you need your entire GPU powered just to update a few frame buffers.


So for me, the source of a 'Game Engine' is naturally agnostic of any actual game per se. It's the code that makes building a game possible.

Game engines are not inherently game type agnostic - in general it's a vaguely defined term referring to a pile of reusable stuff between titles. Typical engines like UE4, Crytek, Source Engine, etc. are all going to have FPS-specific stuff in them, for example. You might reuse the logic to blend multiple animations together to animate a character rig, and reuse the logic for detecting when hitscan weapons intersect a hitbox of that animated character rig, and reuse the logic for doing so server-side to reduce how badly one can cheat, etc. You might also find stuff like physics systems, pathfinding algorithms, systems for binding UI to gameplay logic... plenty of stuff that's not just about interacting with the OS.

Are they building an engine from scratch? That's a whole lot of work! Why is that necessary?

Sometimes they are. It is a lot of work. It's not necessary. They often don't ship an actual game as a result. It is a lot of work.

But I don't know whether I should be researching Game Engine Architecture or not.

It can be useful to know how similar games to whatever you're building are often built (which will also help narrow down the extremely broad/complex topic.)

That said, the best way to build engines is often to simply build games first, and then extract the parts that are worth reusing into a common library for your next game. This helps prove out the things you're building as actually useful (both in concept and in actual implementation). For a roguelike this might be things like tile atlases for rendering maps and sprites, pathfinding algorithms, or reusable dungeon generation logic (e.g. both spelunky and DCSS operate by stitching together smaller hand-authored chunks based on different rules - different enough in that case that it might not be worth trying to share, but if it's all sufficiently data driven, maybe.)

Some systems are typically similar across different game types. And FPS and an RPG both rig and animate 3d characters in similar ways. Entity Component Systems are in-vogue as one of the ways to do composition instead of problematic deep trees of class inheritance. So it won't hurt to learn about how other game types are designed too, but don't feel the need to rush out and learn it all at once. You can research it as specific topics come up.


Direct3DShaderValidatorCreate9

That sounds like an implementation detail of the d3d9 debug runtimes at first glance. Or possibly used by d3dcompiler_##.lib ?