The second devlog closed with the third and fourth maps, the look of the rocks, and the first pass over combat. This post covers making the save file safe, asking the player what should happen when they leave a map and come back, the counter that stops rewards from being paid out twice, combat becoming a two-way fight, and the Thorn Forest's mini-boss, the Goblin Captain.
The images for this post haven't been captured yet.
35 · The save file no longer gets corrupted
The save used to be written directly to a single file. If the game closed or the phone killed the app while it was writing, you were left with a half-written file. The next time the game opened, that file couldn't be read, so the progress was treated as lost.
Now no save is written in place. The new save is first written as save.tmp.json. If the existing save can still be read, it is renamed to save.bak.json, and only after that does the new file take over the real name. On startup, three files are tried in order: the real save, the finished temporary file, and the backup. If none of them can be read, the file is set aside as save.corrupt.json — it isn't overwritten and destroyed, because even a corrupted save is the only evidence there is, and something might still be recovered from it.
The game also saves when the app is paused, loses focus, or is closed. But it only does this if there is real progress in memory: quitting from the title screen doesn't write an empty save over a full one.
Development and test runs use save_dev.json. A test or a screenshot script has no way to touch the player's real progress.
36 · Pick up where you left off, or start over?
Leaving a map halfway through and going back to map selection was unclear: nobody could tell what would happen when you came back.
Now each map carries its own return point. When you touch a campfire, the game records where you left that map, how many seconds you'd played, and how many times you'd died. When you enter the map again, the game asks: "Pick up where you left off" or "Start over". Since each map keeps its own record, playing another map in between doesn't throw away the unfinished one.
The time and death count are stored in the return point too. Otherwise, finishing a map by continuing from the last fire would record a time as if the run had started from zero. In other words, a player who continued from where they left off would end up with a best time that was a lie.
The option in the pause menu also got a clearer name. What it does is take you back to the last checkpoint, so it now reads "Return to Last Fire", not "Restart".
37 · A reward isn't paid out twice
"Start over" puts that map's collectibles back. This is needed so that a player replaying the map can complete the x/y counter on the end card. It is not there so you can open the same chest a second time and put the same gems in your purse a second time.
That's why there are two separate lists. collected holds what has been collected on a map, and starting that map over clears it. credited, on the other hand, holds which rewards have already been paid out once, and it is never cleared for as long as the save exists. A chest opened a second time still throws out its gems so they count toward the map's counter. But it puts nothing in your purse, and it doesn't show a notification promising something it isn't giving.
The copper ore carried by goblins is on the same counter too, keyed to the tile the goblin stands on. So neither dying and walking the same path again nor replaying the map lets you milk the same goblin for a second ingot. An enemy spawned by an arena wave doesn't have a fixed spot, so it never drops ore in the first place.
"Play Again" on the end-of-chapter card is built on top of this too. It puts back the collectibles on all of the chapter's maps and starts from the first map, without erasing any progress and without touching the save at all.
38 · Hitting has a cost
The real problem with combat showed up once it was measured: a hit that landed moved straight on to the next one without waiting for its recovery frames. So as long as the sword kept connecting, it never stopped. You could keep up more than five hits per second, and swinging cost nothing at all. The enemy had no opening to strike back, because there was never a moment when the player wasn't swinging.
The fix wasn't to slow the player down, but to give the combo an ending. The sequence is now three hits: a swing, a thrust, and a finisher. The finisher can't be canceled, either into the next hit or into a jump. You're stuck in it for half a second, and that's exactly when the enemy gets its turn. In return, it deals one and a half times the damage.
Two things keep this rule from turning into a trap. The finisher only comes out if the hit before it landed, so swinging at thin air never pins anyone in place. And a dash can cut the finisher short. Getting pinned in the middle of a crowd isn't forced on you, but the way out isn't free either — it uses up the dash and puts it on cooldown.
On phones, the rhythm of tapping the button hasn't changed. Holding it down still keeps the combo going. The only thing that changed is that taking the combo all the way to the end now has a cost.
39 · Parrying with the shield
Holding up the shield cost nothing and gained you nothing, so nobody ever used it.
Now a blow blocked within 0.2 seconds of raising the shield counts as a parry. There's no knockback, the screen freezes for a moment, and the enemy that struck is left open for 0.8 seconds. This stagger ignores the poise counter, the stun cooldown, and armor. It's the only way to take a boss's turn on purpose.
40 · Enemies now react
Five behaviors were added to the base enemy, all of them off by default. Keeping them off matters: the hundreds of goblins, slimes, mushrooms, and bats across the five maps stayed bit-for-bit the same.
- Swing speed can be set per enemy. The gray goblin's attack strip is a one-second animation, and the hit lands at the 0.7-second mark. That's too late to ever catch a moving player.
- Recovery: after a swing, the enemy can't move, and the damage it takes in that window is multiplied. It's the honest answer to the question "When should I hit?"
- Retreat: when an enemy is taking a combo, it cuts the swing short and backs off. But it never runs away in the middle of its own swing. That rule is the only reason it can hit back at all.
- Spacing: when its swing isn't ready, the enemy steps out of the sword's range instead of standing inside it and waiting.
- Armor: an enemy that isn't staggered on every third hit. A boss needs this; a boss that gets interrupted by every sword strike doesn't give you much of a fight.
A real bug turned up too. The enemies' "are there thorns there?" check looked at the physics layer. But that layer holds not just hazards but every trigger: checkpoints, story beats, and boss rooms. So enemies were refusing perfectly safe jumps that passed over a trigger, thinking "there's a hazard there". Hazards now have their own group, so enemies can tell them apart.
41 · An exclamation mark before the attack
All enemies share the same wind-up animation, and on a character 20 pixels tall, that wind-up doesn't read as a threat. The player sees that they've been hit, but not that the hit was coming.
Now, before it swings, an enemy stands still for 0.4 seconds and shows an exclamation mark above its head. It's the same bubble the smith has, with the same white exclamation mark. Nothing hits during that moment, so that's your window to get away. The same exclamation mark also appears when the captain crouches before a leap.
This is off by default as well. None of the enemies on the five maps show the exclamation mark; only the captain and the goblins he summons use it.
42 · The Goblin Captain
He is the Thorn Forest's mini-boss, made for the seventh map. The packs don't include a captain sprite, so he's the gray goblin at 2.1 times the size, with a slightly warmer tint. He has 100 health and armor: an ordinary sword strike makes him flash white, and that's it. The only way to take his turn is a parry.
The fight's beats, each with a warning before it and a window after it:
- Combo. Two hits, 0.7 seconds apart; on the second one he lunges and deals two damage. Afterward he stays open for 0.65 seconds, and the damage he takes in that window is doubled.
- Back hop. If four hits pile onto him, he finishes his swing and opens up distance.
- Leap series. Every 25 health — that is, at 75, 50, and 25 — he crouches and jumps three times in a row. Each jump lands where the player is heading, the landing hits on both sides, and every landing drops a goblin. Like in the ambush waves, the goblins first announce themselves with a warning puff of smoke, and when they arrive they stay still for a moment. At most two of them are alive at once. After the last landing of the series, he stays open for 0.9 seconds: the reward for surviving.
- Second phase. When his health drops to half, he turns red, everything gets 1.2 times faster, and the series gets one jump longer.
One thing was also removed. At first the captain carried a shield and planted it between his swings. It was a beat that blocked everything coming from the front, wore down with every blocked hit, and left him open when it broke. The mechanic worked, but the shield looked like an item icon sitting on his arm, so it was taken out entirely. A well-designed mechanic isn't guaranteed to look good on screen.
The captain has his own test room: a bare arena that doesn't show up in map selection and doesn't belong to any chapter. The whole fight is tested there with 41 checks. They cover him waking up and the gates closing when you enter the room, the armor holding up against an ordinary combo, the parry stunning him, and damage being multiplied during his open window. They also cover him answering a combo by backing off, starting the series at each health mark, dropping a goblin on every landing, and the phase changing. Then there's everything resetting when the player dies: the captain comes back at full health and asleep, and the goblins he summoned go with him. Finally, when he's defeated, the gate opens and the flag is saved.
Behind the scenes: nobody says "it's better now" without measuring
The combat numbers in this post aren't guesses either. How many seconds pass between one hit and the next was counted from the animation frames and physics frames. How long an enemy can't move during a combo, how long its swing takes to arrive, and how long a fight lasts were all worked out the same way.
The reason is simple: a combat setting doesn't just affect the enemy you're looking at, it affects every map at once. That's why every new behavior was added switched off by default. After each change, the tests for all five maps, the save tests, the English test, the UI tests, and the reachability audit were all run again from the start.
Balance, though, was decided by playing, not by measuring. The captain's first version was too easy, and his second was too hard. The gaps between swings, the telegraph durations, and the goblin count were settled through hands-on play.
What's next?
- The Thorn Forest's remaining three maps: Root Cave, Goblin Camp, and the Slime King's Swamp.
- Moving the captain into his own map, the seventh one.
- The end-of-chapter flow and a start-to-finish check of the whole chapter.
- Sound. The game still has no sound at all; without hit and impact sounds, no amount of tuning makes combat feel quite right.
Credits
- Character, enemy, tile, and item art: Eduardo Scarpato (im-dagon), Dagon's Fantasy packs: eduardscarpato.itch.io
- UI and title lettering: Franuka, RPG UI Pack: franuka.itch.io/rpg-ui-pack
- Text font: Silver, Poppy Works (CC BY 4.0): poppyworks.itch.io/silver