Assets are bundled with the compiled binary of the game using scripts that recurse through the assets folder and generate code as a result. Generated code includes enums to refer to the assets in the rest of the codebase and it uses the experimental #embed preprocessor directive to bundle the assets. Since assets will be used all over the code base, this is a stupid stupid idea because new assets will destroy compile times.
Branching dialog is written in this custom language and transpiled to code. This is also a stupid idea that destroys compile times but I think it’s pretty neat.
# The air clears and the sun rises over the mountains
Table: I'm a table!
{ Kerry: You sure look like one.
# The Table shifts nervously
Table: I sure do!
Kerry: ...
Table: Would you like to come in and have a drink?
var: offer
{ Kerry: Come in where?
Table: Into my home of course!
goto: offer
}
{ Kerry: Uhhh... sure
Table: Come on in!
end
}
}
{ Kerry: I don't think so...
Table: That's quite a rude thing to say don't you think? I think that you should take a deep breath. Just to calm yourself down!
Kerry: I'm sorry
Table: You better be!
[start_table_fight]
}
{ [has_cat] Kerry: Here's a cat!
Table: Thank you!
}
{ Kerry: FIGHT ME!!
[start_table_fight]
}
enum class Speaker {
WIZARD,
LADYBUG,
NIELON,
KERRY,
TABLE,
};
void give_flower();
void start_table_fight();
bool has_flower();
bool has_cat();
constexpr Dialog TABLE_DIALOG[] {
/* 001 */ DialogLine { {"I'm a table!"}, Speaker::TABLE },
/* 002 */ DialogChoice { {"Kerry: You sure look like one."}, 14, nullptr },
/* 003 */ DialogLine { {"I sure do!"}, Speaker::TABLE },
/* 004 */ DialogLine { {"..."}, Speaker::KERRY },
/* 005 */ DialogLine { {"Would you like to come in and have a drink?"}, Speaker::TABLE },
/* 006 */ DialogChoice { {"Kerry: Come in where?"}, 10, nullptr },
/* 007 */ DialogLine { {"Into my home of course!"}, Speaker::TABLE },
/* 008 */ DialogJump { 6 },
/* 009 */ DialogJump { 13 },
/* 010 */ DialogChoice { {"Kerry: Uhhh... sure"}, 0, nullptr },
/* 011 */ DialogLine { {"Come on in!"}, Speaker::TABLE },
/* 012 */ DialogJump { 0 },
/* 013 */ DialogJump { 25 },
/* 014 */ DialogChoice { {"Kerry: I don't think so..."}, 20, nullptr },
/* 015 */ DialogLine { {"That's quite a rude thing to say don't you think? I think that you should take a deep breath. Just to calm yourself down!"}, Speaker::TABLE },
/* 016 */ DialogLine { {"I'm sorry"}, Speaker::KERRY },
/* 017 */ DialogLine { {"You better be!"}, Speaker::TABLE },
/* 018 */ DialogFunction { start_table_fight },
/* 019 */ DialogJump { 25 },
/* 020 */ DialogChoice { {"Kerry: Here's a cat!"}, 23, has_cat },
/* 021 */ DialogLine { {"Thank you!"}, Speaker::TABLE },
/* 022 */ DialogJump { 25 },
/* 023 */ DialogChoice { {"Kerry: FIGHT ME!!"}, 0, nullptr },
/* 024 */ DialogFunction { start_table_fight },
/* 025 */ DialogJump { 0 },
};
Using entt and templates I can animate anything through a duration, delay, curve (linear, smoothstep, exponential, etc.), curve parameters, and member pointer (the struct type is inferred).
play_animation(0.06, 0.0, &UITransformComp::width, entity, [](Animation& animation, u16 starting_value) {
return smooth_curve(CARD_SPRITE_WIDTH, animation, starting_value);
});
I initially used a library that created SDL textures from .ttf files at runtime, but I quickly realized that it’s too expensive to send a new texture in VRAM every time I need new text. So I wrote a text renderer with a tool that creates font mipmaps and extracts kerning data.