ctmatthews

Indie game developer

a trans woman in the UK making 2D action games about ducks:

Ducky's Delivery Service (Steam/itch/Switch)

Chessplosion (Steam/itch)


i mostly post on my Blog / Newsletter / Patreon


i play fighting games! i won Evo in 2021.


pfp/header by NomnomNami


✉️ Contact (email/DM)
ctmatthews.com/contact
🖼️ pfp/header by NomnomNami
nomnomnami.com/

ctmatthews
@ctmatthews

Hi! This is just a quick post to say that the ability to save and load your game's state is extremely useful for tracking down gameplay bugs. My engine has a lot of strange features, but the one that has proven to be the most useful by far is that it automatically records the last ~10 seconds of gameplay states in the background. So if I ever see anything strange happen while I'm playtesting my game I can pause, rewind to the point where it happened, and open the game in a debugger to see what caused the problem.

This post was inspired by a bug I just found with my game's bump attack system which only triggers if you attack one enemy, then try to attack a different enemy on the very first frame that you can act again, but that enemy decides to start stepping away from you on that exact same frame. All I had to do was see that my attack randomly didn't work, go "oh that's weird", then rewind to the frame where my attack was supposed to come out and step through it in a debugger. I don't know how I ever would have reproduced or fixed that issue without a feature like this.

I imagine it's difficult to add this feature to the game engines that most people use. So I don't talk about it much, in case I accidentally find myself getting dragged into a game engine argument. But if you have the ability to implement it, I really can't overstate how useful it is!


britown
@britown

Also, if you use Live++ sometimes you can

  1. rewind to where the state is bad
  2. break in the debugger, find the issue
  3. fix it, live-recompile
  4. hit play on still-running game to confirm the fix

You must log in to comment.

in reply to @ctmatthews's post:

Many years ago when I was building a gameboy emulator from scratch I decided to add rewind functionality just because it sounded like a fun thing to make. It was fun, but it was even more practical than I expected. Saved me countless hours of debugging time

I remember seeing the developers at Tomorrow Corporation showing off something similar with their engine! If I ever dip my toes into the horrifying world of engine dev I'm definitely gonna look into something like this.

in reply to @britown's post:

nice! for the record, my game state copy function is just memcpy(dst, src, sizeof(GameplayState)).

live-recompiling definitely saves a lot of time too! i probably should have mentioned that one in the original post, oops. i don't use Live++, but instead my debug builds just put all of the gameplay code in a DLL that gets hot-reloaded whenever it changes. it means that i can't live-recompile code that changes the memory layouts of any structs, but it's still useful 90% of the time.

oh fantastic! yeah lpp dies when changing memory layouts as well, it works under a similar premise.

I definitely cheat and rely on default copy constructors so it's a "deep" copy without having to write any constructors, having it all be a memcpy is impressive :eggbug-smile-hearts: