Menu

BASeTris: Suspend/Resume and replays

September 7, 2024 - .NET, C#, Programming

I’m still poking away at BASeTris, my Tetris Clone. I started it because I was annoyed at the lack of really good Tetris games which also allowed a wealth of customization to their visuals to look like various older versions. Specifically, I was driven to finally start it, way back in 2016, when “Tetris Ultimate” on my 3DS simply corrupted itself and required reinstallation and would wipe all data, making it somewhat useless.

I’m not sure why I needed that sort of introductory paragraph. Anyways, most recently I dealt with the problems of being able to suspend and resume a game, and currently am trying to tackle the problem of replays.

Suspend/Resume of course seems fairly simple. Just save which blocks are “filled in” in the field. That seemed too easy, so for some reason I insisted on making it more difficult. First, I wanted the visuals to be preserved. As it is, if the bottom piece of a I piece gets cut off in some of the themes, the other three keep their existing visuals, because the theme application “knows” what the owner of each block used to be.

Basically the way I had it work is that it would also record and save the actual Owners of each block, if they had it; and those would be saved in a separate list. Then the blocks could reference the appropriate owner in that list by index. This allowed the board state to visually be preserved when resuming. I’ve not actually experimented with any of the non-Tetris game modes, come to think of it, so I don’t know how well this works there.

Replays are another thing I’ve been slowing working on. It already records all input and I’ve got a special way of having those inputs get played back and the actual controls ignored (except pause). My main issues now are related to the actual Piece randomization being consistent. What I’ve been leaning towards lately is just having the game record every single piece that gets generated by the chooser. Then when replaying it just has to generate all the same pieces on the same order for the playback to be synchronized. This seems overkill  but it’s a lot less work than trying to synchronize everything via randomizer seeds. Another wrinkle was the suspend/resume itself as it would be nice to be able to have a replay effectively build over several sessions and then be replayable as one. If the suspend/resume was changed to also record the list of all pieces generated thus far, it would be able to add to that list going forward so the replay would end up being synchronized without having to figure out any annoyances with random number generation.

In many ways BASeTris is “done”. Well, excepting the CI builds and uploads, as the jenkins CI hasn’t been building properly since I upgraded to .NET 8 – But in many others it feels woefully incomplete. Though I can’t think of any project beyond the trivially-sized where I haven’t felt that way so that’s nothing new. It’s certainly better than BASeBlock…

Which is a bit of a tangent, I’ve been thinking about that project lately. That’s the Arkanoid Clone I wrote as a very first C# project starting in 2008 or so. It was a “clone” of a somehow even worse VB6 project, “Poing”- (which, it turns out, was not actually a unique name at all, oh well). Lots of stuff is done well in it, but a lot of stuff is done really poorly. In particular it’s coupled to System.Drawing quite tightly, and has weird reliances on specific sizes for things like the playfield. Now, BASeTris actually was coupled to GDI+ as well for a while, but I refactored it and created BCRendering, a library of sorts which is aimed to allow the creation and registration of “Render Providers” which effectively know how to draw item X onto canvas Y. BASeTris, in particular, got it’s start using it by me refactoring all the GDI+ coupled code out into separate providers. From there I was able to add new ones for SkiaSharp. Originally Skia was secondary but now the GDI+ providers are largely outdated and I’ve stopped writing them for a lot of new code as well, with BASeTrisTK, the OpenTK+SkiaSharp core, being the only one that is expected to fully work.

I have toyed with the idea, in my head, of trying to do a similar refactor to BASeBlock. It’s not like ‘backwards compatibility’ would necessarily be a big concern either, but it is a big task to try on a codebase that I’m no longer that familiar with.

Have something to say about this post? Comment!

Leave a Reply

Your email address will not be published. Required fields are marked *