Today is the 10th anniversary of VVVVVV’s release!Or possibly tomorrow is, depending on who you ask – technically, the game first went live at 3am GMT on the 11th January 2010, after a very, very long day of fixing every last bug I could, making last minute builds, and trying to slowly upload everything on an extremely unreliable internet connection that kept cutting out. But I’ve always gone by “it’s not tomorrow until you wake up” rules, so I still think of January the 10th as the real launch day <3
Gosh, ten years.
VVVVVV is such an important game to me, I barely even know where to start. I wanted to do something special to mark the occasion: so, as of today, I’m making the game open source!
[VVVVVV Source Code on github]
The repo contains two versions – the desktop version, ported to C++ by Simon Roth in 2011, and later updated and maintained by Ethan Lee – and the mobile version, written in Actionscript for Adobe AIR, based on the original v1.0 flash version of the game.
I wanna give a big big thank you to Ethan Lee, who helped a lot to prepare for this, including getting the repo ready for the public, and organising the reveal on AGDQ (hi speedrunners!)! Thanks Ethan!
A quick overview of the source codeSo, I think a fair question to ask here is: “What’s interesting about the VVVVVV source code?”.
I think even a peek of the source code will quickly reveal that VVVVVV is not a technically sophisticated game! Even by the standards of self taught indie devs, it’s kind of a mess.
Some possibly interesting notes/explanations of why things are they way they are:
- There’s a lot of weird stuff in the C++ version that only really makes sense when you remember that this was made in flash first, and directly ported, warts and all. For example, maybe my worst programming habit is declaring temporary variables like i, j and k as members of each class, so that I didn’t have to declare them inside functions (which is annoying to do in flash for boring reasons). This led to some nasty and difficult to track down bugs, to say the least. In entity collision in particular, several functions will share the same i variable. Infinite loops are possible.
- If you’re looking for the game’s text, that’s mainly (but not entirely) in the Scripts.cpp and TerminalScripts.cpp classes. These functions basically load data into a very simple script parser that controls cutscene logic. Fun fact: modders reverse engineered this “internal scripting” years later to do amazing things with custom levels that I didn’t even know were possible.
- Somewhere along the road, I picked up that it was a good habit to separate your code into input, logic and render, and boy did I take that to heart. Most of the critical game code is in three files – input.ccp, logic.cpp, and the incorrectly named titlerender.cpp. Every state in the game is packed into these three files, under functions called things like “teleporterrender” and “towerlogic“. There’s a lot of copy and pasting going on here.
- All the actual levels in the game are hardcoded in huge arrays that I generated with my own map editor, which exports the levels in source code that I could read in. This is just kind of how it worked when making a flash game in 2009 – accessing external data assets is hard to do, so it just made sense at the time to compile that into the game instead. All the really big files (like Spacestation2.cpp, Finalclass.cpp and so on) were made this way. I’ve uploaded the code for the editor here for completeness, but it’s not really useable anymore to be honest (it requires Allegro and Mingw to compile). I made a similar tool for rearranging the final level layouts!
- When I was making this, I didn’t really understand how static classes worked, or why they were a good idea. I think I read somewhere that static classes and global variables were BAD in flash, so I tried to avoid using them at all ever. The result? Virtually every function in the game is passing around the following arguments: “Graphics& dwgfx, Game& game, mapclass& map, entityclass& obj, UtilityClass& help”.
- VVVVVV basically has no temporary objects, and it fills all of its entity arrays (and most of its other data arrays) with hundreds of blank entries when the game is first initialised. It does this because I read somewhere that deleting objects in flash causes weird hiccups as the garbage collector takes over and slows things down, which is actually sort of true. I was still doing this weird thing in new projects until very recently – I finally broke the habit in Dicey Dungeons.
- One more: as well as the cutscene parser, I had another way to control game logic as you were playing – a monolithic state machine, which had gotten completely out of control by the end of the project! You can find it in Game::updatestate, and I kinda recommend checking this out even if you don’t read anything else! This controls things like triggering the start of more complicated cutscenes, where teleporters send you, the timing of the level completion animation, and other miscellaneous things that I just wanted to kludge in quickly. The states are numbered, and it counts all the way up to 4099, with gaps. When I was developing the game, I kept a notepad nearby with the important numbers written down – 1,000 triggers the collection of a shiny trinket, 3,040 triggers one particular level completion, 3,500 triggers the ending. This dumb system is the underlying cause of this amazing 50.2 second any% speedrun of the game.
I dunno, what can I say? I was young and more interested in getting something on the screen than implementing it properly. Maybe the best thing about VVVVVV’s source code is that is stands as proof of what you can hack together even if you’re not much of a programmer.
Looking back through it myself all these years later, I find it really funny how much of it is basically just the same parts copy and pasted over and over, with the values changed. This basically makes it impossible to read and maintain ten years later, but back when I was in the thick of it, it made it really fast to iterate and add new things. I’ve gained better habits over the past decade, and I’m definitely a better programmer now – but it does seem to take me longer to do things.
Surprise Birthday Party!Just as I was getting ready to post all this, Sergio Cornaga announced a 10th anniversary game jam for VVVVVV over on glorious trainwrecks!
VVVVVV’s 10th birthday eVVVVVVent!
I am so excited about this, haha – and I love glorious trainwrecks, which hosted the regular Klik of the Month jams that I did regularly around the time I was making VVVVVV. This feels like a perfect home for it!
I’m really, really excited to see what people come up with – once the jam ends, I’ll do a big round up post here on this blog, in the style of the old VVVVVV player level posts I used to write <3
Even before I open sourced the game, I made the tools to make and play VVVVVV levels available for free in the “Make and Play” edition back in 2014! You can download that from here! If you’re interested in making levels in the VVVVVV editor, this thread is a good place to start! Good luck!
Mushy stuffAhhhhh so I’ve talked about how I feel about VVVVVV a little before – just before the first anniversary, I posted about how things were going for me when the game first came out, and how its success changed my life. Then on its firth anniversary, I posted about how VVVVVV felt like a once in a lifetime project – that nothing before or after could come close to.
A decade on, I still feel the same way. I’m incredibly proud of VVVVVV, and grateful for everything. I want to thank everyone who helped me along the way – Magnus for his incredible soundtrack, Ethan and Simon for all their work to bring the game to more people, Bennett for naming the rooms, Stephen for helping me get that mac build out late in launch day. This game is special to me – thank you to everyone who played it and supported me over the past ten years. It’s meant so much. <3
As the pandemic wreaks havoc on TV and movie ‘love lives’, intimacy coordinators need to find ways to adapt