LD41 Post-mortem: InvadTris
Play and Rate InvadTris
I wasn't sure I'd be able to participate in the jam this weekend. I had some other committments that I couldn't move, so wasn't sure how much time I'd have to put into a project. Accordingly, I paid attention to the theme announcement, but didn't immediately have in mind a game idea, so put it out of my mind and went to bed early on Friday.
Saturday, I woke with an idea to mash up Tetris with Space Invaders. There's a verticality to both games that I wanted to explore. Falling Tetronimoes and Invaders marching downward. I thought about it and came up with some ideas that I thought were interesting for how the games could be combined. I still didn't think I'd have time to actually make it, but the idea interested me enough to make a design document, which I posted.
Saturday came and went.
Sunday, I felt like having a go at it, so I worked for about 8 hours, and implemented most of the Space Invaders half. I took a 4 hour break in the evening, but then picked it up again around midnight and put another 3 hours into it, and got Invaders 99%, and some foundational work for the Tetris half by 3am.
If it wasn't for the fact that I had to work on Monday, I could have spent all day on the project and finished it up completely before the Jam deadline. But most of the day I worked. I got home at 6pm and put the next 3 hours into a valiant effort to get the Tetris half finished. I ran into a frustrating bug in the last two hours, and couldn't fix it in time. I knew a workaround was possible, but implementing that would take even more time. I kept working at it until around 2 AM.
So I missed deadline, but I only really put in about 17 hrs of development time over the 72-hr Jam period.
Tuesday, I came up with a workaround to the bug I ran into on Monday, and deemed the project fit for release. It took 27.5 hours of labor to get the game playable enough for a release.
I have a lot more planned for the project, and I'm looking forward to putting more time into it in the next week to add polish.
Design
My very first step was to run to Google Image Search and steal some screen captures to use as a conceptual mockup.

Mashing up Space Invaders and Tetris was fun. Although from two very different genres (shooter and falling block puzzle), there's some similarity between them. Both have strong vertical elements: the Invaders march downward from the top of the screen; the Tetris blocks fall from the top and stack up on the bottom. When the Invaders reach the ground, the game ends; when the Tetris stack reaches the top of the screen, the game ends. Both games start off very slowly, but pick up speed and become overwhelming. I recognized that these similarities in the design elements of the two games complimented each other well, and as I thought about it I began to see the "Tetris in the Invaders" and the "Invaders in the Tetris." To combine the games started feeling natural, and I realized I'd hit upon something brilliant. Why had no one done this before?
To make the games work together as one, I needed to come up with an approach that would allow the player to focus on one game at a time, so I took a "turn based" approach, where you play Invaders until you destroy an enemy, then you take a turn at Tetris. To connect the games, I made the action in Invaders determine the next Tetronimo in Tetris. At first, that was it, but later toward the end I came up with the idea to have Tetris feed back into Invaders by turning completed lines into a super-weapon for Invaders. To create additional time pressure, I allowed the Invaders to continue marching while you play Tetris (albeit, more slowly) rather than pause completely. But to make it fair, since I freeze the player object in Invaders while focus is on Tetris, I made the Invaders ship invulnerable while Tetris has focus, and later I decided also to make the Invaders stop shooting while Tetris has focus. I'm not sure if Invaders is challenging enough, at this point, but I wanted to err on the side of fairness to the player, and immobilizing the player while shots rain down that could kill him while he's completely helpless didn't feel fun. Since the Invaders continue marching, and the game will end if they hit the ground, there's still plenty of time pressure to complete the Tetris move quickly.
Development
I worked in GameMaker Studio 1.4, which I'm still more comfortable with than GMS2.
I opted to focus solely on mechanics and programming, so the graphics are very rudimentary. Since I had so little time, I wanted to work as quickly as possible, so I just used simple squares to represent the Invaders and Mothership, rather than try to make sprites for them. I can always do that later.
I mostly tried to make both games feel like authentic implementations of the originals they're inspired by, but I did take a certain amount of license. I experimented with the number of rows and columns of Invaders, and their spacing.
Programming Invaders was very easy and straightforward. I once live-coded a talk on how to make games with GameMaker, in which I implemented Space Invaders, and I got about 80% feature complete in 90 minutes that time.
I had never successfully completed a Tetris clone in GameMaker (or any other tool) before, so that was a challenge. I had tried once, a few years ago, but gave up on it in frustration. But I know GML better now than I did then, and I didn't have nearly as much trouble this time.
The interesting parts of the program were:
Controller-centric design
I'm not sure why I decided to do it, but I started out with a controller object, one for each game, and rather than have the individual objects for each game have their own code in them, I had the controller object manipulate them as much as possible. There might be a little code in some of the objects, to handle Collision Events, but that's just about it. I put 95%+ of the code in the Step Event for the Controller objects, and eschewed the use of Alarm events entirely, instead implementing my own timer systems in the Step. This gave me two big, very long scripts for the Step event, where everything was handled to run the game except for Drawing and Collision Events. Keeping the code all in one place like this is different from my usual approach, and at first I was doing it more for the challenge of writing a GameMaker program in this way, but toward the end I recognized that it was a really effective approach to take, and that I was effective that my instinct took me in that direction for this project. Looking through dozens of events in several objects for the line of code that is causing some problem or other with some other line of code in some other object is hard, confusing, and frustrating, but with this project there wasn't any of that, since almost the entire game was in two Step Events.
Invaders switchback
Invaders are supposed to all reverse course and drop down a row when any of them reaches the side of the screen. This isn't actually that hard to do, but for some reason I got my logic a little tangled, and it felt like it took forever to figure it out. It took me almost 8 hours to get my Invaders half of the project 99% working, where in my live-coding demo I'd somehow made progress much faster.
Tetris early placement
In my early attemtps, I used place_meeting() to check for whether the Tetronimo could move into the next adjacent cell. This worked very well, until I started rotating Tetronimoes, and found that certain shapes would not drop, seemingly detecting that they were blocked a cell before they should have been. I spent probably 4 hours trying to figure out what was going wrong and what I could do about it.
Ultimately, I worked around it by using a grid-based collision check, instead. This actually made the rest of the Tetris development easier for me, though, since I used the same grid-based approach to detect completed lines, clear them, and drop the stack above.
Getting the nested for loops to iterate over the cells was tricky. I thought about using an array to store the state of cells, but in the end I didn't need to do that; I simply use the objects themselves, and check for them with GML's instance_point() function, rather than storing presence/absence states in an array. This works great and is actually much easier.
To make sure I was thinking properly about the grid, I had to write a loop to draw it out so I could visually confirm that my logic was working right. This took a few tries to get right, but making my mistakes visual really made it possible to fix them.
Tetris line completion
I had a working algorithm to detect completed lines, and it nearly worked on the first try. But because of a dumb array indexing bug, it wasn't working. It took me almost a half hour of puzzlement before I saw the problem. That wasn't actually too bad.

What worked:
Theme:
I loved loved loved the theme! It sucked me back in when I didn't think I was going to make a game this weekend, and I really enjoyed the time I spent working on it. I am seeing a tremendous amount of awesome game ideas this Jam, too. I can't wait to play them all!
Slacking:
By taking it easy and not trying to cram every spare minute of the weekend, I felt that the time I did spend working was a lot more enjoyable. Not taking the jam "seriously" is the way to go.
Working fast:
Despite "slacking", when I was at work on the project, I felt very focused, and got a lot done very quickly.
What didn't:
Slacking:
In previous Jams, I feel like I have put pressure on myself to do as much as I possibly can, and often end up getting stuck on some problem, which blocks me from completing everything I wanted, and turning in a compromised, but playable, game by deadline. This time when I hit bugs, up until the last one, I felt calm and relaxed about fixing them, and they never gave me any real trouble, until that last one. If I would have put in a little bit of time Saturday, or Friday, maybe I would have finished everything before deadline. But I can't let it worry me too much. I don't know that I would have come up with the idea that I did if I had tried to come up with an idea immediately when the theme announcement happened. Letting it just come to me worked better this time. And if I'd tried to work on Saturday, I might have made some progress, but I might just have been too disorganized with my thinking because of the other things I had going on, and ended up with a messy project that was harder to work in. Working with a clear head and no pressure, I was able to make very effective use of what time I did spend on the project. Still, it's a lot better to get more than just 15 hours of productivity out of a 72 hour jam weekend!