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.
So I talked about particles the other day when I pushed the prototype into the game engine and got them working, but I had to do some work to make them really “exist” in the game world. The first thing to do was make sure you couldn’t see them through walls, and I’ve now given them the ability to “collide” with the floor.
As an example, I’ve made “Bullet Casings” eject from guns fired and bounce on the floor before coming to a resting stop and fading away. To do this, I had to make the X axis inertia inherit the direction the creature was facing when he fired the gun to make sure the bullet fires out of the “back” of the gun. On top of this, the particles are told, when they spawn, how high above the floor are they. The floor is defined as the bottom-most pixel of the sprite that emits them.
Using this information, the particle can tell when it has hit the floor, however, because the game camera is skewed isometrically, the floor is angled. If the creature is facing North or East, the floor behind the creature is tilted “downwards”, otherwise it tilts “upwards”. The further the particle has traveled horizontally, the further the floor has skewed.
With much fiddling, bullet casings now bounce along the floor as per the rules of the isometric camera, and any particle can follow the same rules with a simple “CollidesWithFloor” flag.
That was certainly a whole lot of words that probably make no sense out of context, but I’m still pretty happy with the result; I’m wondering if I should make particles bounce off walls now.
I’ve added a new routine that calculates a creature’s cone of vision based on the distance they can see and how wide the cone should be. For debugging, at the moment it doesn’t do much of anything other than draw a graphical representation of a cone in front of their face, but it’s nice to see the way it collides with walls correctly and follows the creatures around as they change directions and move about.
At the moment, calculating the cone of vision for more than ten creatures at a time causes a few frames to drop, so I’m going to have to speed things up a bit, as well as be a bit more intelligent about what creatures actually need to have a cone of vision calculated at any given time.
Update: Okay, I actually spent some decent time optimising the cone of vision logic when I realized I really can’t be calculating it every frame, and it needs to be only recalculated when a creature moves, but rendered visibly every frame. I also needed to store the cone of vision in a manageable array so I can quickly check who can see who (Bool CanThisSeeThat(This, That)). I got this work done, and realized I was massively over-rendering the cone of vision graphics before. It’s now much faster and much more intelligent, meaning no more dropped frames and it’s all kept in a nice little loop called “ManageVision”. Creatures have a boolean called “HasEyes” to decide whether they need to have vision management, so the ornaments don’t get cones of vision rendered near them.
I like the attached screenshot here as you can see four creatures distracted by computers, as well as a cone of vision colliding with a wall, demonstrating how it can not penetrate the clipping plane.
I’ve improved a lot of little things regarding acuracy at this point. Previously, although the program was “working” on an isoletric scale, it was cutting heaps of corners to create the illusion of an isometric layout. I’ve slowly improved the calculations everywhere to make everything perform a lot more nicely on the grid.
I’ve also implemented a new type of path-finding, with the previous one now called “Beeline” where a creature will take the most direct path across the tiles to a given point, I have now programmed in Dijkstra’s Algorithm and named that ‘Pathfinding’ in the game code. The large red wall exists to demonstrate the pathfinding.
The long line demonstrates my implementation of Bresenham’s line algorithm. It traces a straight line from one the “player” creature to the mouse cursor at the moment, to demonstrate what tiles would inflict “damage” on creatures standing on them if the creature were to fire a bullet in that direction.