diff --git a/MODDING.md b/MODDING.md index 1d36a7b..0dec4ba 100644 --- a/MODDING.md +++ b/MODDING.md @@ -150,7 +150,7 @@ The areas which will expand based on how full the character is and their progres | `null` | The null that will expand. | | `scaleMax` | The scale (in percent) that will be added at maximum. Know that a scale of 100 is the normal scale of an animation. | -The first expand area is treated as the belly: it breathes, jiggles when smacked, rubbed or fed, and is where digestion and stage-up effects come from. +The first expand area is treated as the belly: it breathes, jiggles when smacked, rubbed or fed, and is where stage-up effects and gained weight come from. ### interactTypes, interactAreas `interactTypes` is an object of interaction types by name, giving each type's defaults. Rub, Smack, Kiss and Turn Around come from common. A type gets a button on the taskbar only if one of the character's areas uses it. `interactAreas` is a list of the concrete areas on a character which can be interacted with; usually for belly rubs, kisses, etc. Each area names its `type` and takes all of that type's settings, changing whichever it gives itself. @@ -201,7 +201,7 @@ The UI's sounds. | `sounds` | `open` and `close` (the taskbar or one of its windows), `hover` and `select` (a widget), and `cheats` (after entering a special code to activate cheats). | ### particles -An object of particles by name, each with the `anm2` and `animation` it plays once where spawned. The `Puff` particle is also used for the dust when an item lands hard. +An object of particles by name, each with the `anm2` and `animation` it plays once where spawned. The `Circle` particle is also spawned where an item lands hard. # items.json diff --git a/src/audio.cpp b/src/audio.cpp index 60a8faf..1edea9e 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -2,7 +2,7 @@ #include #include -constexpr float PITCH_VARIATION = 0.06f; +constexpr float PITCH_VARIATION = 0.025f; void Audio::init() { diff --git a/src/body.cpp b/src/body.cpp index f9a145f..4b77441 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -246,7 +246,6 @@ void Body::update(std::vector& events) stats.isDigesting = true; stats.digestionTimer = traits.digestionTime; audio->play(character->sounds[SOUND_DIGEST]); - events.push_back(EVENT_DIGEST_START); } } values_clamp(); diff --git a/src/effects.h b/src/effects.h index 741adf7..a9d4208 100644 --- a/src/effects.h +++ b/src/effects.h @@ -14,6 +14,7 @@ enum FloaterType enum SparkShape { SPARK_CIRCLE, + SPARK_LINE, SPARK_STAR }; @@ -26,10 +27,12 @@ struct Floater FloaterType type = FLOATER_CALORIES; }; -// A glint or puff that drifts, falls (or rises) by its gravity, and fades over its life. +// A glint, puff or line (from its position to its end) that drifts, falls (or rises) by its gravity, and fades over its +// life. struct Spark { Color color; + Vec2 end; Vec2 position; Vec2 velocity; float gravity = 0; diff --git a/src/items.cpp b/src/items.cpp index 78cd00d..345ed65 100644 --- a/src/items.cpp +++ b/src/items.cpp @@ -10,9 +10,9 @@ constexpr float CRUMB_SPEED_Y_MIN = 2; constexpr float CRUMB_SPIN = 15; constexpr Color GOLD = {1, 0.85f, 0.3f, 1}; constexpr Color TRAIL_COLOR = {1, 1, 1, 0.35f}; -constexpr const char* DUST_PARTICLE = "Puff"; +constexpr const char* IMPACT_PARTICLE = "Circle"; constexpr float BITE_JIGGLE = 4; -constexpr float DUST_IMPACT = 12; +constexpr float IMPACT_SPEED = 12; constexpr float FANFARE_MIN = 0.75f; constexpr float FANFARE_SHAKE = 0.015f; constexpr float FANFARE_SPEED = 5; @@ -23,9 +23,9 @@ constexpr float SQUASH_DECAY = 0.82f; constexpr float SQUASH_MAX = 0.35f; constexpr float SQUASH_PER_SPEED = 0.025f; constexpr float TRAIL_SPEED = 12; -constexpr Spark FANFARE_SPARK = {GOLD, {}, {}, 0.05f, 16, 50, 0, SPARK_STAR}; -constexpr Spark RARE_SPARK = {GOLD, {}, {}, 0, 10, 40, 0, SPARK_STAR}; -constexpr Spark TRAIL_SPARK = {TRAIL_COLOR, {}, {}, 0, 7, 14, 0, SPARK_CIRCLE}; +constexpr Spark FANFARE_SPARK = {GOLD, {}, {}, {}, 0.05f, 16, 50, 0, SPARK_STAR}; +constexpr Spark RARE_SPARK = {GOLD, {}, {}, {}, 0, 10, 40, 0, SPARK_STAR}; +constexpr Spark TRAIL_SPARK = {TRAIL_COLOR, {}, {}, {}, 0, 6, 18, 0, SPARK_LINE}; constexpr int FANFARE_COUNT = 20; constexpr int FANFARE_SHAKE_TIME = 12; constexpr int CRUMB_COUNT = 6; @@ -389,16 +389,18 @@ void Items::update(Play& play, Pointer pointer) } else { + Vec2 previous = position; float impact = motion_update(play, entity); if (impact > 0) audio.play(character.sounds[SOUND_BOUNCE]); - if (impact >= DUST_IMPACT) - play.particles_spawn({DUST_PARTICLE}, position); + if (impact >= IMPACT_SPEED) + play.particles_spawn({IMPACT_PARTICLE}, position); entity.isThrown &= vec2_length(entity.velocity) >= TRAIL_SPEED; if (entity.isThrown) { Spark spark = TRAIL_SPARK; - spark.position = position; + spark.position = previous; + spark.end = position; play.effects.spark_add(spark); } } diff --git a/src/play.cpp b/src/play.cpp index 5134a95..e21ae0d 100644 --- a/src/play.cpp +++ b/src/play.cpp @@ -11,12 +11,8 @@ constexpr ImGuiKey CHEAT_KEYS[] = {ImGuiKey_UpArrow, ImGuiKey_DownArrow, ImGu ImGuiKey_RightArrow, ImGuiKey_B, ImGuiKey_A}; constexpr const char* KEY_DISCOVERED = "discovered"; constexpr const char* KEY_ITEM = "item"; -constexpr Spark DIGEST_SPARK = {{1, 1, 1, 0.5f}, {}, {}, -0.06f, 10, 50, 0, SPARK_CIRCLE}; -constexpr Spark STAGE_SPARK = {{1, 0.85f, 0.3f, 1}, {}, {}, 0.06f, 18, 70, 0, SPARK_STAR}; +constexpr Spark STAGE_SPARK = {{1, 0.85f, 0.3f, 1}, {}, {}, {}, 0.06f, 18, 70, 0, SPARK_STAR}; constexpr float AUTOSAVE_TIME = 30; -constexpr float DIGEST_JIGGLE = 3; -constexpr float DIGEST_SHAKE = 0.006f; -constexpr float DIGEST_SPEED = 2; constexpr float PUNCH_DECAY = 0.93f; constexpr float PUNCH_EPSILON = 0.001f; constexpr float STAGE_FLASH = 0.7f; @@ -24,8 +20,6 @@ constexpr float STAGE_JIGGLE = 15; constexpr float STAGE_PUNCH = 0.08f; constexpr float STAGE_SHAKE = 0.04f; constexpr float STAGE_SPEED = 8; -constexpr int DIGEST_COUNT = 10; -constexpr int DIGEST_SHAKE_TIME = 40; constexpr int STAGE_COUNT = 28; constexpr int STAGE_FREEZE = 5; constexpr int STAGE_SHAKE_TIME = 30; @@ -193,16 +187,10 @@ void Play::events_handle(Vec2 screenSize) Dialogue& dialogue = character->dialogue; for (Event event : events) { - Spark spark = event == EVENT_STAGE_START ? STAGE_SPARK : DIGEST_SPARK; + Spark spark = STAGE_SPARK; spark.position = body.belly_get(); if (event == EVENT_GAINED && body.gained > 0) effects.floater_add(spark.position, body.gained, FLOATER_WEIGHT); - if (event == EVENT_DIGEST_START) - { - effects.burst_add(spark, DIGEST_COUNT, DIGEST_SPEED); - camera.shake_add(DIGEST_SHAKE, DIGEST_SHAKE_TIME); - body.jiggle_add(DIGEST_JIGGLE); - } if (event == EVENT_STAGE_START) { effects.burst_add(spark, STAGE_COUNT, STAGE_SPEED); diff --git a/src/play.h b/src/play.h index 6cab9b6..7f2dcdf 100644 --- a/src/play.h +++ b/src/play.h @@ -32,7 +32,6 @@ enum Hold // What happened to the body in a tick, answered once it's done. enum Event { - EVENT_DIGEST_START, EVENT_DIGESTED, EVENT_GAINED, EVENT_STAGE_START, diff --git a/src/ui.cpp b/src/ui.cpp index 20fa9fb..ad54ff3 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -25,11 +25,11 @@ constexpr float INDICATOR_SIZE = 0.35f; constexpr float INDICATOR_SPEED = 2; constexpr float ITEM_SIZE = 96; constexpr float ROUNDING = 10; -constexpr ImVec4 CALORIES_COLOR = {1, 0.85f, 0.3f, 1}; constexpr float BAR_EASE = 6; constexpr float BAR_SHAKE = 2; constexpr float BAR_SHAKE_SPEED = 40; -constexpr float FLOATER_OUTLINE = 2; +constexpr float FLOATER_SHADOW = 3; +constexpr float FLOATER_SHADOW_ALPHA = 0.6f; constexpr float OVERSTUFFED_PULSE = 0.35f; constexpr float OVERSTUFFED_SPEED = 6; constexpr float STAR_WAIST = 0.3f; @@ -724,7 +724,8 @@ void Ui::text_draw(Play& play, ImVec2 screen) ImGui::PopFont(); } -// The flourishes over the world: sparks, rising numbers (outlined so they read on anything), and the screen's flash. +// The flourishes over the world: sparks, rising numbers (in the character's color, shadowed so they read on anything), +// and the screen's flash. void Ui::effects_draw(Play& play, ImVec2 screen) { Effects& effects = play.effects; @@ -741,6 +742,12 @@ void Ui::effects_draw(Play& play, ImVec2 screen) drawList->AddCircleFilled({at.x, at.y}, size, color); continue; } + if (spark.shape == SPARK_LINE) + { + Vec2 end = view * spark.end; + drawList->AddLine({at.x, at.y}, {end.x, end.y}, color, size); + continue; + } float waist = size * STAR_WAIST; drawList->AddQuadFilled({at.x, at.y - size}, {at.x + waist, at.y}, {at.x, at.y + size}, {at.x - waist, at.y}, color); @@ -754,18 +761,13 @@ void Ui::effects_draw(Play& play, ImVec2 screen) std::string text = floater.type == FLOATER_CALORIES ? text_format("+%.0f kcal", floater.value) : "+" + weight_format(floater.value, *measurement); float alpha = std::min(1.0f, (float)floater.life / (FLOATER_LIFE / 2)); - ImVec4 color = floater.type == FLOATER_CALORIES ? CALORIES_COLOR : ImGui::GetStyleColorVec4(ImGuiCol_PlotHistogram); - color.w = alpha; + Color tint = play.character->color; + ImVec4 color = {tint.r, tint.g, tint.b, alpha}; ImVec2 size = font->CalcTextSizeA(FONT_HEADER_2, FLT_MAX, 0, text.c_str()); Vec2 at = view * floater.position; ImVec2 position = {at.x - size.x / 2, at.y - size.y / 2}; - ImU32 outline = ImGui::GetColorU32(ImVec4(0, 0, 0, alpha)); - for (int x = -1; x <= 1; x++) - for (int y = -1; y <= 1; y++) - if (x != 0 || y != 0) - drawList->AddText(font, FONT_HEADER_2, - {position.x + x * FLOATER_OUTLINE, position.y + y * FLOATER_OUTLINE}, outline, - text.c_str()); + drawList->AddText(font, FONT_HEADER_2, {position.x + FLOATER_SHADOW, position.y + FLOATER_SHADOW}, + ImGui::GetColorU32(ImVec4(0, 0, 0, alpha * FLOATER_SHADOW_ALPHA)), text.c_str()); drawList->AddText(font, FONT_HEADER_2, position, ImGui::GetColorU32(color), text.c_str()); } if (effects.flash > 0)