At certain times, extra rooms are added to Black Annex during game-play. I actually cut this from the design doc about six months ago, but I was finally able to add it back in by piggy-backing on the system I build for spawning in enemies. It works in a much more complex way than the enemy spawn-in. With enemy spawn, there’s just an AI entity that’s invisible until it hears someone call for help.
When creating a new room, the clipping plane needs to be dramatically modified, and the zBuffer needs to be rebuilt as the room is spawning-in as well (the zBuffer typically only considers walls and static objects once when the level loads, and then never again because they don’t change.). There’s also the issue of “joining” tiles needing to appear to connect old rooms to the new ones, so certain wall tiles need to “listen” for a spawning room, and switch to a different type to connect to the new room.
In the video below, see how the new room actually “connects” to the old room, and a new window appears in one of the offices which wasn’t there before.
I’m at a stage with Black Annex at the moment where most of the development time is spent creating content, rather than working on the technical side of things. The features are nailed down (although some still not implemented) and most of the technical hurdles are overcome (except optimisation, there’s always room for more optimisations) so I don’t really get to just play around with code all that much in Black Annex right at this time.
So, one week ago I opened a blank new project and started creating something. This blog is always about the more technical side of what I’m doing, so here’s some video of something totally new.
A lot of the jobs on my to-do list are variations of “Make [x] not run like shit”, so I’ve been spending a lot of time making things run a lot faster, and the overall system requirements for Black Annex a lot lower.
So one of the first things I managed to do was fix an issue paging the video buffer meaning that even when the game was running at 60fps, the screen would only update at 30fps. I didn’t even realize this was happening until I fixed it so now the game is literally running twice as smoothly as it was in the PAXAus AIS demo.
After this, I needed to seriously think about getting the game able to “Stretch to full screen”. I mean, I’ve had it working, but the “stretch” was slowing the game down massively so it would drop about 20fps when doing it. I had been just treating the screen like a rectangle and scaling it in a really basic way before blitting it to the computer screen. It was running horrible, so I started working on a way to actually map the screen to a couple of texture-mapped triangles and scale those up to the screen size instead. I ended up getting this working, so the screen is sliced into two triangles, then the two triangles are drawn back onto the screen at a new size to make the game full-screen. This turned out to be almost no slower than drawing the screen at the original size. Dealing in polygons seems to be pretty snappy, it turns out!
When I figured that out, I went back and changed almost every sprite-blitting routine to use texture-mapped triangles instead, and this sped up the game massively, especially if any form of scaling was being used on any sprite. The problem is, there’s no filtering, so I can’t smooth the screen or anything. Scaling square pixels to funny numbers can get some ugly results. I’m going to let the player run the game in any resolution they want, but they’ve got a few options on scaling. They can just go straight-up “Full screen” and just put up with any ugly pixels, or they can “Scale to nearest square pixels” which leaves some black borders at some resolutions (It will scale to 100%, 150%, 200%, 250%, etc. Keeping things fairly nice), and they can turn on “allow 25% extra scaling”, which allows 100%, 125%, 150%, 275%, etc. It’s a little uglier, but it’s up to the player to decide what they’re happy with.
So that’s done! Although I had at least tried to put some kind of screen filter in, it was just too slow to actually use. During that process, I did actually make a pixel shader for the game, which a lot of people though was pretty cool. It’s just a tilt-shift thing which gives everything a kind-of “Miniature” look. It will just be optional in the game as it runs like trash, but I like leaving things like that in for people to fiddle with.
But THAT lead to me deciding to work on some absolutely massive performance tweaking for the engine. I decided it was about time to actually go ahead and work on “Frame Skip”. “Frame Skip” is where you measure the time it’s taking to render the game’s graphics and, if it takes too long, turn off rendering until the game catches back up again. This results in “choppy” gameplay, instead of “slow motion” game play when things start getting too heavy for the CPU. The good thing about frame skip is that it lets people with computers just a little below requirements still play the game at the same “speed”, they just notice the game looks a tiny bit worse. It’s much less frustrating than having the game run at a snail’s pace.
I made it so Frame Skip comes on gradually, so if the game only slows down only for 1 second, it will give you a little mix of slow-motion and maybe just skip 2 frames or so. This means that if a GUI element takes a little bit too long to populate (Some of them have elements that stream from the hard drive), the GUI animation will still remain smooth instead of just jumping in. If the entire game runs slow, the frameskip will quickly go to full effect and the whole game will just be a bit jumpy.
So that’s great! The game runs way better on this Core Duo Mobility laptop I have for testing, which it was kinda unplayable on before. It still needs some tweaks but the technology is there and working so I’m super happy with that. The next item on my to-do list said “Make Pathfinding faster, a LOT faster” so I decided I really needed to finally wrestle with a* Pathfinding and make it work. Doing this in BASIC is extremely hard because you can not create arrays of arrays, and there’s no pointers either. I had to create a ton of different arrays with a bunch of arbitrary reference keeping arrays between them so they can point back and forth to each other. I also ran into a massive issue calculating the heuristic for my map because I use a horrible skewed coordinate system. A goon by the name of “testsubject” eventually figured out the math for it and I’ve had awesome success now implementing a*.
I uploaded a video showing the game running with the old pathfinding, and then I pull down a menu and change it to a* in real-time and the game instantly returns to 60fps with no frames dropping at all. Have a little read of the video description on youtube if you want a bit more detail on exactly what I’m doing in the video.
So that’s what’s new. Oh, I’m also going to E3! I won’t be exhibiting there or anything, just hanging out and hopefully meeting some cool people. I’ve never been to America before, tweet at me if you want to meet up or something.
I didn’t really make it clear what I was doing in March, I just just smashing out updates every day to try to create a cohesive, playable game out of the pre-alpha version of BA Project. The reason for this was that the deadline for submitting a playable demo to the judges at PAXAus was April 10th and I really wanted to try to get something into their hands that actually “worked”.
So I spent the entire month of March smashing through as many critical features that the game needed to actually work as a whole. With that done, I hit the Alpha milestone and announced Black Annex. Around April 7th I sent the most bleeding edge build into the PAX judges after about 30mins of playtesting and two last-second fixes. (The final playtesting is shown in the video below, recorded around 3am).
For a little fun, I built a gimmicky custom intro into the PAX build which makes it appear that you’ve launched a DOS command prompt when you run the game. It just dumps you into a DOS window reading: “C:\GAMES\BLACKA~1>”, slowly, the commend prompt types out “annex.exe /paxmode”, a fake DOS/4GW runtime starts, and then a warning saying “YOU ARE SEEING THIS SCREEN BECAUSE BLACK ANNEX WAS LAUNCHED IN ‘PAX MODE’”. The moment the player pressed a key on the keyboard, the entire computer screen instantly goes black and the demo starts.
The demo had an utterly broken Main Menu that liked to randomly drop in and out if you clicked “Begin Game” too quickly, the Options menu didn’t work, and sometimes the “BLACK ANNEX” logo itself would just disappear. The only instruction given to the player was a loading-screen hint reading “Left click to make your agents walk to a location, double-click to run.”. There were five “playable” levels, but all of them were either uncompletable due to being massively unbalanced, or completed within 10 seconds of the level starting because the mission objective was way too simple. The minigun was completely broken, if you stacked three weapon abilities none of them worked, nothing made sense. The mouse cursor was an uncontrollable wreck plagued by a bug that I’ve only now fixed two weeks later and the “Mission Deploy” screen would just randomly close sometimes as soon as it opened. Loading took up to twenty seconds per level and the game ran at about 40fps on a computer made one year ago.
I can not stress enough how little sense this game made in the demo. You were dumped into a game with way too many mechanics, none of which were explained to the player and most of which barely functioned correctly anyway and expected to find, as the PAXAus submission form said “fun factor and a great gameplay experience.”.
As the creator of Black Annex, all I see when I play it is a mess of systems interacting with a bunch of unintended things happening all over the place.
The judges at PAXAus didn’t see the same thing I see. They sent me an email to let me know.
One year ago today I sat down in front of a blank QBASIC document having gotten sick of working on a 2D adventure-game engine for DOS which had constantly run into memory limitations. I made an isometric tile editor, a sprite editor, a spritesheet builder, and a little game engine that put them all together and made them move around. Then I made a post on this website about it to show it off.
Lots of people found my work really interesting and paid lots of attention to what I wrote every few days about my adventures in a struggle to make a game in QBASIC. Many months later I visited a site called reddit.com for the first time, made a post there called “I’m making a game in QBASIC”, and showed people some screenshots of it. I thought everyone would think it was a really stupid idea, but lots of people really encouraged me to keep working hard and had lots of positive things to say about the work I had done so far.
Since then, people talk to me about my game and ask me for updates. Sometimes a person knows who I am even though I’ve never interacted with them. I even got mentioned on a real video game website! People who I care about actually follow me on twitter and they listen to what I have to say. Hundreds of people talk to me and online and actually sit down to read the often nonsensical things I write on this website just to keep up with what I’m struggling through at the time to keep working on making a game in such a limited environment.
It’s been a year of nights staying up until 3am with 9am starts the next morning. A year of missing time at the gym because a door keeps randomly opening the third time you visit a certain level. A year of missing time with my wife and daughters because half the chair legs on all the desks are the wrong shade of grey and tomorrow is screenshotsaturday.
But most of all, it’s been a year of amazing encouragement from a huge online community of people who really actually care about the effort I’m putting into making a game that they might get to play some day.
I’d like to show you a game I’ve been making; I’d like to show you Black Annex.
Sometimes days and days go by where I just try to fix these tiny bugs that have been in the game engine for months and I’ve just always thought “Oh yeah, I understand that bug, I’ll just fix it next time I’m in that part of the engine”. Then you get back to that part of the engine and you realize you have no idea how any of that code works anymore or why it’s bugging out the way it is.
Even with the amount of comments in my code, I sometimes spent a large chunk of time actually re-learning how I managed to make something work the first time so I can actually get down to making it work properly the second time.
For something slightly more entertaining, I went ahead and removed the old “Damage popup numbers” that were floating out of creatures when you damaged them. They were way too big and ugly, especially in hectic situations. I replaced them with blood particle effects with no real damage quantifier to let you know how much exact damage you’re doing. Weapon power is made clear elsewhere in the game when you are equipping abilities, so I think for the in-mission effects the blood is a much better result.
It also looks pretty cool when all hell breaks loose. In these videos, my creatures have a massive amount of health, probably more than you’ll ever actually achieve in the game. It’s just to test it all out.
I spent all of New Year’s Day making the drag and drop mechanics feature-complete for one of the in-game menus.
It’s been amazingly more complicated than expected to implement something that I use in my OS and other games every day without even thinking about it. When you pick up a sprite to drag it somewhere, you have to record such a huge amount of information about what you’re doing and what you might possibly plan to do with that sprite.
I use the mouse cursor as an entity which records what it’s carrying, where it started carrying it, where it’s considering throwing it to, what it’s doing with it at the moment, and about fifteen other things. When you release the mouse button, the game has to check so many things regarding “Is this a good place to drop this?” that it’s amazingly easy to leave loop-holes that can be exploited and result in duped items or creatures.
Another important thing is to only check certain “drag and drop” conditions if you actually need to – because you’re looking at doing a huge number of checks on a per-pixel basis, you can’t do that every frame all the time; you need to turn certain features on or off depending on whether they might possibly apply at any given time.
In the end, everything turns out very satisfyingly tactile and you can kinda “throw” objects around between windows in a smoothly rendered way. I like the result so I made a little video about it.
While play-testing your own game, it’s sometimes hard to imagine what a lot of your game’s features are going to feel like from the perspective of someone other than yourself. After a lot of play, I’ve decided to throw out a chunk of code regarding “Ability Cooldowns” simply because it’s no fun and doesn’t make immediate sense.
It can be kind of hard to accept that a ream of code you wrote might actually have no place in the game you’ve written it for, but it’s just part of “Making a game”, you put some code in, see if it works, and then change it if it doesn’t. The code I’m removing has been a core part of the gameplay for months now, but as the game’s changed slightly over time, I’ve created a much more relevant set of rules for how “Abilities” are used in a fairer and much more sensible way.
It’s become quite a challenge to communicate to the player exactly how “Abilities” work, especially when you have a full team of five creatures running about potentially all using different abilities at the same time in different locations. The player needs to be able to always see at a glance who is doing what and whether it’s working or not. I’m changing the way the “Solution” box at the top-right of the screen works so that it will show what abilities are currently being “Cast” and how long they’ve got left until they’re finished. Hopefully you’ll start to see this change in future videos. In the meantime, here’s some play-testing I recorded.
In other news, Man Fight Dragon has been accepted into the Indie Pavilion at PAXAus 2013 where I’ll have a little booth for people to come look at a game and maybe play it if they’d like to hunch over a monitor and keyboard.
So, last post I mentioned that I had finished off the particle emitter system in a prototype environment (literally a blank 2D canvas) but the next job was to take those particle emitters and drop them into the game environment. I had initially through that I would just overlay the particles over the top of the game scene and it wouldn’t be all that bad if you could see particles through walls; in-game walls aren’t taller than people anyway so it should be okay, surely.
But it wasn’t okay, it looked terrible.
In an “Isometric” scene, zSorting (the order things are rendered in so behind/in-front looks right) is done from the top of the screen to the bottom in linear order. In-engine at the moment, only 1 object (a wall tile, a person, a door) can be on 1 tile at a time, so the engine just renders whatever object is on whatever tile starting at the top of the screen down to the bottom. However, there can be 2000 particles on one tile, and incorporating them into the zSorting populator and renderer took some fairly heavy changes to the way it works.
Every particle has to remember what the y-axis of the tile was for the emitter that it came from and then gets inserted into a massive stack in order of y-axis, with up to 2000 other particles sharing the same y-axis. So there’s an array called ParticleSorter(200,2000), the first dimension is the y axis, and the second is the particular particle that’s on that axis. Once all the particles are added to that array stack, the stack is then read from during the zRenderer routine.
It’s not perfect yet; particles need to be given a concept of “floor” for them to land on, but the rendering is working and it seems to be fairly pretty so far. Here’s a video where you can see a fairly early implementation of breakable doors with particle effects.