Revengate development log

Weekly progress reports about the Revengate development.

Website | sources | Google Play | F-Droid | Itch

2020-04-27

Not a ton of progress this week: I started revisiting my level generator. I changed the passage carving on my BSP levels to use A* with constraints rather than dumb elbows. In most cases, that makes beautiful slightly twisty passages. There are edge cases where the passage will make a big detour around a room, this will go away once I move away from BSP.

Resurrecting the Dungeon Exhibit was really helpful. It's a minimalist version of the game without monsters. It has quick transition from one level to the other with arrow keys and it can regen a level with a single key, which makes it easy to test how well I am handling various constraints.

I wrote an importer for the Zorbus prefab templates (big image). I plan on using those instead of rectangles and grow the level with a modified Primm algo, just like I do with the maze levels. What is left is figuring out something sensible for door placements.

Next: finish the new level generator, close the plot hole with the code loom cards.

NO BLOCKERS!

2024-04-19

Lots of eye candy this week!

Instead of showing a message with the number of turns to arrival while traveling, I now highlight the path to be taken. It's oddly satisfying to see the path auto-update when your character notices a new obstruction. It's a bit distracting to see a diagonal step pop out of nowhere – A* artifacts that would be expensive to completely get rid of. I also added a debug flag to highlight the paths of all the other actors. I think this will become quite handy if I want to fine tune strategies like Swarming and Guarding.

We now have dynamic lighting.

The experiments I did with glow a few weeks back were a dead end. The glow intensity changes too much from one Godot renderer to the next and since the game aims to support Desktop, Web, and Android, that was a no-go. Dynamic lights on the other hand behave beautifully similar on all renderers. There is still room for adjustments and this will only achieve its full potential once we can pickup light sources. Thankfully, Godot lights ignore the visible property and use enabled instead. That will make it very easy to make items that keep emitting light even after their glyph become invisible as they become part of your inventory.

Tuning the lights forced me to invest the time to finally understand blending modes. I get it now! It's easier if you remember that the name implies that each channel is a float in 0..1. "Add" and "Subtract" are fairly intuitive. "Multiply" darkens the scene because the channel of what you are drawing and whatever was there are 1.0 max, most likely 0<=x<1, so the result will be smaller than what you started with. Similarly, "Divide" blending brightens the scene because you divide by something smaller than 1.

There is also a new wait-and-heal command. You rest, but to balance that being too easy and tempting to do all the time, you do it with your eyes closed so there is a risk that you'll be surrounded when you resume your exploration.

The above is on Itch and Google Play, F-Droid will take a few more days to catch up with the update.

Next: portable light sources that don't behave like they say on the package (rogue lights), draft the main lines of the next quest.

NO BLOCKERS!

2024-04-12

My game stopped building on F-Droid. Thankfully, the team was kind enough to open a ticket in my gitlab to let me know. They also have some fancy tagging system that will watch the issue in my project and restart the build when I close it. It turned out to be minor bug in the Godot Dialogue Manager plugin. Updating it solved the issue.

The harder problem, the game crashing during visual effects on some older Android devices was not as easy to solve. I still can't get my head around it. There can be fairly fancy shaders, but they can't take scalar uniforms. I reworked the spells so they would look good with only particle systems and Tween animations. I added a config to let players turn off shaders if they happen to be on a device where those crash the game.

When shaders are enabled, I now pre-load the spells and special effect sub-scenes during the wall of text game intro. This completely removes the stutter the first time you see a spell.

Based on an excellent bug report, I reworked the dialogue pane to make it more obvious to the player how they can interact with it. Tap in the text area advances (finish typing or start the next line), tap outside of the text area closes the conversation, and possible responses are now buttons rather than text line of a different colour. The old Close button that was easy to miss since it was hidden under your thumb has been moved to the top of the dialogue pane.

Next: highlight the path while traveling, start fleshing up a 4th quest.

NO BLOCKERS!

2024-04-05

I'm in Europe again: Toulouse, Carcassonne, Marseille (now), Lyon (Revengate is set in Lyon), and Brussels (beer!). I left myself get distracted by touristy things and the on-the-go lifestyle of fast city hopping made it hard to develop a good coding routine. It's way easier when you have a desk with the whole setup and you can just sit and get going.

I also have a really hard time with jet lag. I know the theory, but in practice, I'm just up at 4am for days. I think I'm good now, waking up around 8:00 this week.

I tidied up the story in chapter 3 of Revengate. There is a whole cast of NPCs who will hint at the background and what they have to say evolves as you become more aware of the big boss.

To make it easier on myself, I improved the summary of what actors know in the debug inspector. I really like the metaphor of learning facts, which you automatically forget after a while depending on how crucial that information is. It feels natural to write branching dialogues with that building block.

I thought that conditions (poisoned, on-fire, ...) were saved, but it turns out they are not. I tried getting to the bottom of this, but I couldn't find the problem. It's probably some subtleties with how Godot manages Node.owner that I don't fully grasp. I think I will convert those from Node to custom resources. The latter is harder to add on an actor in the Godot editor since you can't just drag and drop them, but they always save and restore how I expect them to.

I changed my shell to fish and added atuin for history management. Atuin converts the shell history from a flat file to a database with lots of metadata. This means I can how have a super charged CTRL-r with multiple facets to search for. It's great when looking for a command I vaguely recall typing a while back, but it get even better. I can also see the history of a given command: how often I type it, how long does it usually take, what the return code was the last few times I used it. A like how interactive fish is and how clean my setup file is. I don't know if it makes me more productive, but it makes me happier for sure.

Next up: find out why the explosions crash the game on some Android devices (thankfully I own one of those) and rework the dialogue UI to make response selection more obvious (probably something closer to what interactive Japanese novels do).

NO BLOCKERS!

2024-03-01

There is a new zapping spell. The effect takes too long and I would rather have a long bolt that goes from the caster to the victim, but since I can't figure out the proper way to do that right now, the shower of lightning particles will have to do for a little while.

It turns out that the missing noise texture for the animated water on F-Droid is indeed a Godot bug. Not converting resources to binary is a perfectly fine workaround and it barely increases the size of the APK. Maybe it slows down loading, but I can't tell. In any case, it should be fixed in Godot 4.3.

The accountant has new things to say after the confrontation. He also becomes neutral after you apply enough "convincing" with your favourite blunt object.

Next: give aggressive monsters a bit more smarts on how to corner the hero.

NO BLOCKERS!

2024-02-22

I wrote a new heap queue, fully typed and optimized for working with 2d coordinates. Compared with the old one, it does about 3x as many operations per second. This comes at the cost of losing some generality and doing some voodoo with bit shifting rather than divisions, which I borrowed from the Python heapq module. Using this new queue, I can do about 40% more A* path findings per second.

This is probably as good as it's going to get. The best thing to do now would probably be to either recycle paths with D*-lite or do sub-optimal paths with Best First Search when there are many actors in play. I could also simplify perception rules and that would shave a whole lot, but I kind of like that monsters can hear/feel you when you are just out sight around a corner.

The pinching gesture now uses the centroid of all fingers as the zoom focal point. This feels so much better! It used to have the top-left corner as the focal point and I was looking for a matrix transform that would do everything in one go, then I figured that I only had to zoom then see how far that moved the centroid, then translate the camera by the opposite of that offset.

The hero can learn spells. That UI is going to suck passed six or seven spells, but since there are only a handful of spells and even fewer spellbooks, it will do for now. The attack button should stay on the far right, but that we need Godot 4.3 for that. Stay tuned!

All of this and the tossing of items has been released in Revengate v0.12.0, now live on Google Play and Itch. It should be up on F-Droid in the next few days.

Next: hide spell books in dangerous places.

NO BLOCKERS!

2024-02-16

I was working on perf this week. Based on the good leads we received from players the week before, JT Wright and I used the Godot profiler on the game's Monte Carlo simulator to add caching on the stats modifier and also make sure that it does not change the general outcomes of encounters. This brings about 50% more combat turn/second for about 12 lines of code. Not bad!

I added a big room for stressing movement, something that was hard to stress test with the combat simulator. Indeed, entering that room was producing a noticeable pause on mobile. In order to find a suitable waypoint for Exploring actors, I used to run a pass of Dijkstra on the whole board. This had the benefit of guaranteeing that the waypoint is reachable, but it proved to be too expensive for what we needed. I now limit this first Dijkstra pass to a roughly 10-tiles radius and that really helps. Going towards the waypoint is using A* and that is considerably faster, especially when there are no obstacles.

This week, I learned that unlike Python, GDScript is faster when you provide types and indeed, turns are about 30% faster in the large open room after fully typing my distance functions. The Godot profiler is suggesting that I really should add some types the priority queue that my path finding is using. I sadly noticed that the git repo for that plugin has been taken down and now I'm really glad for open source and my ability to take over the maintenance. I'll see next week if specializing and typing the queue improves things, then I will consider if the API is still general enough to be worth publishing in the assets store.

I wanted to work on spells but I ended up doing very little. I added a spellbook that teaches you casting skills and factored out the health meter so I can be restyle it and use it for mana. There is still no UI for the player to cast.

Next up: stop optimizing once the refactor of the priority queue is done and then make the UI for casting.

NO BLOCKERS!

2024-02-09

You can now throw things. Potions auto activate upon shattering, weapons not designed for throwing do less damage, some weapons like the hammer have a two ranges: full damage nearby, half damage far away. A lot of this was done in collaboration with JT Wright.

I moved to the kitty terminal two weeks ago and I really was not sure if that was worth the effort. It has really nice shell integration, but very little discoverability so you have to read the doc to know what you can do. This week, with hyperlinks and mimetypes properly configured, it became clear that my terminal was now the a great place to do sound design.

I moved my durable task tracking to todo.txt. At first I thought that the requirement for a task to completely fit on one line would be limiting, but then it soon became clear that I was using my old TODO app for unactionable notes. Now I have two clear systems that do what they are meant to do and do it well. I like that I can do everything in my text editor and that I don't need 7 clicks to add 3 items to my grocery list. I still track short term items on paper.

A player used the new cheats to nail down the cause of a perf regression introduced a few releases ago. I'm amazed and energized seeing their dedication to this cause!

Next: the hero should cast spells.

NO BLOCKERS!

2024-02-02

Added a setting to change the size of text controls. The most logical size is still auto-detected based on screen size and pixel density, but who am I to tell you if you should enjoy squinting or not.

Added a cheat to conclude a chapter.

Finished the refactor of the inventory screen to make it stylable. Scrolling is better, but it's still hard on a small screen. This will need more work. My reference right now is Spotify: it just knows the difference really well between scrolling a playlist and selecting a song.

Added a long description on all the items. Added a "secret" stash area where you can explore the previous point.

Released the cheats and the settings screen in v0.11.6 to Google Play and Itch. It should be picked up by F-Droid in the next few days.

I started working on a targeting system so you can finally toss those dynamites rather than carefully placing them on the ground before (hopefully) retreating. Be warned, folks, the fuses are about to get a whole lot shorter. If I get this slick enough, that's pretty much how I know we're ready to teach the hero some magic.

Does it seem obvious that the blue highlighted tiles are within tossing range?

NO BLOCKERS!

2024-01-19

The water bug on F-Droid is almost certainly a Godot bug, but I have not made a minimal repro yet to report it upstream. I did however start detecting if the noise textures are missing in order to gracefully fall back to static water tiles.

This and last week's work has been released in v0.11.5.

I started the redesign of the inventory screen with JT Wright. One awesome side-benefit of no longer relying on static images for buttons is that we don't have to make one button do many different things. You "activate" a dynamite and "consume" a potion. Much better! Besides that, we are just shooting for feature parity and skinnability. Cool features like filtering and sorting will come later.

We tried MacOS exports. They work just fine, so I will probably start publishing those as well.

All items now have a "simple" and a "detailed" description. You need very high perception to see the detailed one – lots of excellent hints hiding in there.

I added a settings screen. The only settings so far is to enable cheats. I don't mind players cheating if the game is too hard and they are completely stuck. I mention that they cheated on the victory screen – I don't judge, but you should not exaggerate your bragging rights.

Next up, polish up the cheats that I have been using for testing so that they are not too confusing in the hands of players. Add a few other settings.

NO BLOCKERS!

2024-01-12

I played with UI and UX this week.

The text controls are now much bigger on small screens. The advertised screen DPI is not accurate, but I can still use it do divide screens in three classes: tiny, small, big. I make buttons and labels bigger as screens get smaller, text margins follow an inverse rule. I will have to redo the inventory screen since the buttons in a Godot Tree control are not stylable.

Godot has a cool feature: theme.merge_with(other_theme). That way I just need mini alt themes for the screens sizes that need bigger text controls. The UI to set those properties is far from intuitive, but the way the controls just stay where I want them to be makes it very tempting to say that I like that system better than CSS. I will probably be certain by this time next week.

Following a player recommendation, you can now hold the arrow keys down and you'll seamlessly keep moving or attacking in that direction. It's quite satisfying! I was already doing all the state management to only pass commands to the hero when it's its turn, so it was only a matter of looking for key-down rather that key-released.

I'm trying to see why water is not animated in my F-Droid builds. It's weird! I think I will soon have narrowed it down enough to declare it a Godot bug.

2024-01-05

New year, new platform: you can now play Revengate in the browser! Godot web exports do not work yet on M1 Macs, might only work with Firefox on non-M1 Macs.

This was easier than I was expecting – I added the web export recipe and then almost everything just worked, including saved games across multiple browser sessions. Thanks Godot! I just had to tune a little bit my auto-resizing setting and do a dirty hack to make sure stale saved games are not exposed to the player (deleting entries from the Local Storage seems less reliable that creating them).

The controls still very much have a mobile flavour to them. Adding ways to do things with mouse and keyboard is going to be the theme of the next few releases. For now, I made sure you can cancel multi-turn action and close most dialogues with ESC.

I added two new potions: potion of absinthe and potion of analysis paralysis. Both serve some of the purpose of the scroll of identify that is common in roguelikes. Since they come with some drawbacks, they introduce some fun dilemmas.

I wrote a brief recap of my progress during 2023 for the RoguelikeDev subreddit.

Next: figure out why water in not animated on the F-Droid builds.

NO BLOCKERS!

Older Updates