diff --git a/MODDING.md b/MODDING.md index 0dec4ba..c0ab01f 100644 --- a/MODDING.md +++ b/MODDING.md @@ -174,7 +174,6 @@ The first expand area is treated as the belly: it breathes, jiggles when smacked | `scaleCycles` | float | How many oscillations the scale effect performs. Defaults to 1. | | `scaleTime` | float, seconds | How long the scale effect lasts. Defaults to a third of a second. | | `sounds` | paths | Sounds played when interacting. | -| `particles` | strings | Particles (see `particles`) spawned when interacting. | ### sounds | Key | Meaning | @@ -186,12 +185,11 @@ The first expand area is treated as the belly: it breathes, jiggles when smacked How items move in the background (`gfx/area.anm2`): `gravity` (applied to items' velocities per tick), `friction` (applied when items are grounded or hit walls) and `airResistance`. ### cursor -The cursor's sounds and particles. Its look is `gfx/cursor.anm2` (see "Fixed files and names"). +The cursor's sounds. Its look is `gfx/cursor.anm2` (see "Fixed files and names"). | Key | Meaning | |---|---| | `sounds` | `grab` (grabbing an item), `release` (letting go) and `throw` (letting go while dragging quickly). | -| `particles` | `grab`: particles spawned when grabbing an item. | ### menu The UI's sounds. @@ -201,7 +199,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 `Circle` particle is also spawned where an item lands hard. +An object of particles by name, each with the `anm2` and `animation` it plays once where spawned. (The ring where something is touched, grabbed or lands hard is drawn by the game, not a particle.) # items.json diff --git a/resources/common/character.json b/resources/common/character.json index 91906c5..8aa98aa 100644 --- a/resources/common/character.json +++ b/resources/common/character.json @@ -20,8 +20,7 @@ "isHold": true, "cursorHover": "Hover", "cursorActive": "Rub", - "sounds": ["sfx/rub.ogg"], - "particles": ["Circle"] + "sounds": ["sfx/rub.ogg"] }, "Smack": { "icon": "smack", @@ -30,21 +29,18 @@ "dialogueCooldown": 0.6667, "scaleAmplitude": 1, "scaleCycles": 3, - "sounds": "sfx/smack*.ogg", - "particles": ["Circle"] + "sounds": "sfx/smack*.ogg" }, "Kiss": { "icon": "kiss", "cursorHover": "KissHover", "cursorActive": "Kiss", - "sounds": "sfx/kiss*.ogg", - "particles": ["Circle"] + "sounds": "sfx/kiss*.ogg" }, - "Turn Around": {"icon": "turn", "sounds": ["sfx/turn.ogg"], "particles": ["Circle"]} + "Turn Around": {"icon": "turn", "sounds": ["sfx/turn.ogg"]} }, "cursor": { - "sounds": {"grab": ["sfx/grab.ogg"], "release": ["sfx/release.ogg"], "throw": "sfx/throw*.ogg"}, - "particles": {"grab": ["Circle"]} + "sounds": {"grab": ["sfx/grab.ogg"], "release": ["sfx/release.ogg"], "throw": "sfx/throw*.ogg"} }, "menu": { "sounds": { @@ -56,7 +52,6 @@ } }, "particles": { - "Circle": {"anm2": "gfx/circle.anm2", "animation": "Main"}, "Puff": {"anm2": "gfx/puff.anm2", "animation": "Main"} }, "area": {"gravity": 0.95, "friction": 0.75, "airResistance": 0.975} diff --git a/resources/common/gfx/circle.anm2 b/resources/common/gfx/circle.anm2 deleted file mode 100644 index 5191e85..0000000 --- a/resources/common/gfx/circle.anm2 +++ /dev/null @@ -1,48 +0,0 @@ -{ - "anm2ed": 1, - "info": {}, - "spritesheets": [ - { - "path": "circle.png", - "regions": [ - { - "name": "Main", - "size": [128, 128], - "pivot": [64, 64], - "origin": "center" - } - ] - } - ], - "layers": [ - {"name": "Main"} - ], - "defaultAnimation": "Spawn", - "animations": { - "Spawn": { - "length": 11, - "loop": false, - "root": [ - {"delay": 11} - ], - "layers": [ - { - "layer": 0, - "frames": [ - { - "region": 0, - "scale": [10, 10], - "delay": 10, - "interpolation": "linear" - }, - { - "region": 0, - "tint": [255, 255, 255, 0], - "interpolation": "linear" - } - ] - } - ] - } - } -} diff --git a/resources/common/gfx/circle.png b/resources/common/gfx/circle.png deleted file mode 100644 index 7cd3f72..0000000 Binary files a/resources/common/gfx/circle.png and /dev/null differ diff --git a/src/character.cpp b/src/character.cpp index a2ddae9..19ec67b 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -118,7 +118,7 @@ static void interact_parse(object source, InteractArea& area, Character& charact json_keys_check(source, {"type", "null", "layer", "icon", "isHold", "animation", "idleOnEnd", "cursorHover", "cursorActive", "dialoguePool", "dialogueCooldown", "digestionClick", "digestionHover", - "scaleAmplitude", "scaleCycles", "scaleTime", "sounds", "particles"}, + "scaleAmplitude", "scaleCycles", "scaleTime", "sounds"}, "an interact area"); area.animation = json_string(source, "animation", area.animation); area.cursorActive = json_string(source, "cursorActive", area.cursorActive); @@ -137,8 +137,6 @@ static void interact_parse(object source, InteractArea& area, Character& charact area.layer = character.anm2 ? character.anm2->layer_get(json_string(source, "layer")) : -1; if (!source["null"].error()) area.null = character.anm2 ? character.anm2->null_get(json_string(source, "null")) : -1; - if (!source["particles"].error()) - area.particles = json_strings(source, "particles"); if (!source["sounds"].error()) area.sounds = audio.sounds_get(character.roots, json_strings(source, "sounds")); } @@ -259,11 +257,7 @@ static void character_parse(object root, Character& character, Renderer& rendere float_read(area, "friction", character.area.friction); float_read(area, "airResistance", character.area.airResistance); - object cursor = json_object(root, "cursor"); - object cursorParticles = json_object(cursor, "particles"); - json_keys_check(cursor, {"sounds", "particles"}, "cursor"); - if (!cursorParticles["grab"].error()) - character.cursor.grabParticles = json_strings(cursorParticles, "grab"); + json_keys_check(json_object(root, "cursor"), {"sounds"}, "cursor"); json_keys_check(json_object(root, "menu"), {"sounds"}, "menu"); for (auto [name, value] : json_object(root, "particles")) diff --git a/src/character.h b/src/character.h index 5379caf..0c6f5a6 100644 --- a/src/character.h +++ b/src/character.h @@ -84,7 +84,6 @@ struct InteractArea std::string icon; std::string idleOnEnd; std::string name; - std::vector particles; Sounds sounds; float digestionClick = 0; float digestionHover = 0; @@ -283,7 +282,6 @@ struct Swap struct Cursor { - std::vector grabParticles; Anm2* anm2 = nullptr; }; diff --git a/src/effects.cpp b/src/effects.cpp index e7651d6..9f647e6 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -1,5 +1,6 @@ #include "effects.h" +constexpr Spark RING_SPARK = {WHITE, {}, {}, {}, 0, 64, 20, 0, SPARK_RING}; constexpr float FLASH_FADE = 0.04f; constexpr float FLOATER_RISE = 0.8f; constexpr float SPARK_DRAG = 0.95f; @@ -36,6 +37,14 @@ void Effects::spark_add(Spark spark) sparks.push_back(spark); } +// A white ring growing and fading where something was touched or hit. +void Effects::ring_add(Vec2 position) +{ + Spark spark = RING_SPARK; + spark.position = position; + spark_add(spark); +} + // Throws count copies of a spark out in every direction, at up to speed. void Effects::burst_add(Spark spark, int count, float speed) { diff --git a/src/effects.h b/src/effects.h index a9d4208..6ec484e 100644 --- a/src/effects.h +++ b/src/effects.h @@ -15,6 +15,7 @@ enum SparkShape { SPARK_CIRCLE, SPARK_LINE, + SPARK_RING, SPARK_STAR }; @@ -27,8 +28,8 @@ struct Floater FloaterType type = FLOATER_CALORIES; }; -// A glint, puff or line (from its position to its end) that drifts, falls (or rises) by its gravity, and fades over its -// life. +// A glint, puff, line (from its position to its end) or ring (growing to its size) that drifts, falls (or rises) by its +// gravity, and fades over its life. struct Spark { Color color; @@ -54,4 +55,5 @@ public: void floater_add(Vec2 position, float value, FloaterType type); void spark_add(Spark spark); void burst_add(Spark spark, int count, float speed); + void ring_add(Vec2 position); }; diff --git a/src/interact.cpp b/src/interact.cpp index b67209f..e884d91 100644 --- a/src/interact.cpp +++ b/src/interact.cpp @@ -62,7 +62,7 @@ void Interactions::update(Play& play, Pointer pointer) } play.audio->play(entry.sounds); body.idle_override_set(entry.idleOnEnd); - play.particles_spawn(entry.particles, pointer.position); + play.effects.ring_add(pointer.position); if (entry.digestionClick > 0 && body.stats.calories > 0 && !body.stats.isDigesting) body.stats.digestionProgress += entry.digestionClick; body.actor.pulse_add(entry.layer, entry.scaleAmplitude, entry.scaleCycles, entry.scaleTime); diff --git a/src/items.cpp b/src/items.cpp index 345ed65..3029523 100644 --- a/src/items.cpp +++ b/src/items.cpp @@ -10,7 +10,6 @@ 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* IMPACT_PARTICLE = "Circle"; constexpr float BITE_JIGGLE = 4; constexpr float IMPACT_SPEED = 12; constexpr float FANFARE_MIN = 0.75f; @@ -360,7 +359,7 @@ void Items::update(Play& play, Pointer pointer) if (pointer.isClicked) { audio.play(character.sounds[SOUND_GRAB]); - play.particles_spawn(character.cursor.grabParticles, pointer.position); + play.effects.ring_add(pointer.position); isJustHeld = true; } if (pointer.isDown) @@ -394,7 +393,7 @@ void Items::update(Play& play, Pointer pointer) if (impact > 0) audio.play(character.sounds[SOUND_BOUNCE]); if (impact >= IMPACT_SPEED) - play.particles_spawn({IMPACT_PARTICLE}, position); + play.effects.ring_add(position); entity.isThrown &= vec2_length(entity.velocity) >= TRAIL_SPEED; if (entity.isThrown) { diff --git a/src/ui.cpp b/src/ui.cpp index c931949..98126b2 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -31,6 +31,8 @@ constexpr float BAR_SHAKE_SPEED = 40; constexpr float FLOATER_SHADOW = 3; constexpr float OVERSTUFFED_PULSE = 0.35f; constexpr float OVERSTUFFED_SPEED = 6; +constexpr float RING_START = 0.1f; +constexpr float RING_THICKNESS = 3; constexpr float STAR_WAIST = 0.3f; constexpr float BAR_WIDTH_MIN = 120; constexpr float BUTTON_SIZE_MAX = 96; @@ -741,6 +743,12 @@ void Ui::effects_draw(Play& play, ImVec2 screen) drawList->AddCircleFilled({at.x, at.y}, size, color); continue; } + if (spark.shape == SPARK_RING) + { + float radius = spark.size * view.a * (RING_START + (1 - RING_START) * (1 - fade)); + drawList->AddCircle({at.x, at.y}, radius, color, 0, RING_THICKNESS * view.a); + continue; + } if (spark.shape == SPARK_LINE) { Vec2 end = view * spark.end;