So, apparently the new Blogger interface has been eating my images for the past 2 months ...
So expect to see a blank image leading to a 403 page soon™.
It's been the hottest day of the year here, so naturally I went out for a half marathon route march ... and now my feet hurt.
I finally finished off another playable character model, a shotgun wielding, propeller-powered catgirl, currently named "Southern Hospitality", complete with Daisy Duke hotpants. She has a short range playstyle with slow attack rate but high damage and medium manouverability. After each shot a new shell is loaded with a single handed pump-action for the obligatory "rule of cool".
And here's some video of gameplay.
Apart from finally completing a second playable character I have been porting over my project to the new and shininess which is Dx11 and OpenGl 3.2 (might be 4.0 I can't remember). This meant a final farewell to the much loved DirectX9.0c which I could just about write a shader with. No such luck on Dx11/OGL with such things as of yet.
This has required me to finally defeat the spaghetti code which I had previously wrote, slimming things down in C++ and removing bloat for the porting. I have only ported to the pre-PBR branch of the engine - so really 2019 code - as a stepping stone to entering the latest shiny stuff once I know what the hell is going on. So far so good. Everything seems to run fine - except for my broken Dx9 shaders but that was to be expected.
I've also stuck my hand in my pocket and made a new, capital purchase. Only had it out of the box once for a quick test. If Google hasn't yet fubared my images, here's a quick pic below.
It's been an awfully long time since I've done any drawing.
I also used a 14 year old camera to get some pics of Comet Neowise.
It was my parents Golden Wedding Anniversary. 50 years! Albert Speer only got 20 years in Spandau Prison!
Steamworks updated yet again, so it was back to the; "how do I update Airship Dragoon again?" Seemed less hassle than usualy so I must have remembered how to integrate the Steam Client C++ this time around. Whilst giving it a quick test drive to make sure that it actual did work, I started to look through some of the old spaghetti code I had written all those many moons ago.
Comment out the old code on my local distro - incase I suddenly needed to change it back - I changed how panic works, making it more aggressive so that the troopers will always panic shoot if available and only flee if not. I also tweaked some animations and got impact reactions to being wounded, so the troopers now flinch when hurt. People did ask for this when I first released it but messing around with animation code was all rather confusing at the time so I avoided it. Oh well, seven years too late et al but here it is. Luckily I still had a 14 year old version of Blender available - otherwise I would have had to re-export every character and animation into the new format and that wasn't about to be a thing that was going to happen.
I'd also like to change the box art, branding and main menu screen art some time ... but one thing at a time.
Back to the current world of coughs and chaos, I spent the sunny days lounging about with a bottle or two of plonk, getting a tan - or at least turning quite red at some point.
Eventually I did get back to devving on the current - or at least occaisonal - project. One main character does not make a game, except all those games with a single main character of course ... However I was rather planning on having multiple playable characters based on weapon playstyle, so inbetween freezing fog, scorching sun and heavy rain, I eventually got round too booting up Blender and making another character. Whilst the original "GunGirl" was a long range fighter, this character is more short to medium range, with heavy hitting but slow attacks. Still need to PBR the shotgun - not that the current gameplay build is PBR, it's still stuck in the land of Dx9.0c until I upgrade to DX11/12.
So, next up is to finish off LODs, create an atlas map of textures and materials to reduce the all important drawcall number, rig up some animations (based on the previous character animations) and then get the model working in-game. The code for the character is done and works fine, having been a placeholder box for some time already.
If you want to be pedantic, it's actually a rectangle.
And here's it's replacement going all John Woo/Chow Yung Fat/Revy with dual wielding pistols.
Ooooh looks gamey!
But first to Blender3D 2.8. It's the newest version of Blender3D with a whole host of changes - like inverting mouse buttons for selection ... which is gonna take some getting used to after 15 years of it being the other way ...
However it did have a new addon I wanted to test out, an addon for generating LODs (level of detail) for my high poly mesh by creating retopology of the mesh automatically. What I wasn't expecting was for the new Blender 2.8 to hunt down and retire my older version of 2.78c which was in a totally different directory location.
So it turned out to be time to learn the new Blender whether I really wanted to or not ...
This was going to happen anyway due to the new Blender being all PBR and stuff ... it's just that I wanted to worry about that later, but now I had to worry about that now. The first problem was ... well ... PBR, and the fact that no materials or textures would render without creating some sort of spaghetti of virtual nodes - and this was just to get textures to show up on the model. And of course PBR textures won't render without both roughness and metal values.
Spagbol junction in the left pane, just to make textures visible in the right ...
Catchick hanging with the TripleA Thicc Squad in PBR land
Which is when I found out that transparency was broken and filed an issue report on the code repository, github ... by which I mean I whined in the discord server to the power's that be, because github is my mortal enemy for reasons of never having been able to successfully create a working pull request that didn't get rejected ...
So, back to that auto-retopology LOD generator I wanted to test. It's called Game Asset Generator and is looks like a pretty nice piece of kit. I had a model with around 27K triangles and beefed it up to a completely ridiculous 440K using some catfish-bob subsurfing (or whatever the hell it's called).
From "USE ALL THE TRIANGLES!!!!" to "use a more reasonable number of triangles in one simple click ...
The real down side to it was that it completely mangles the original UV maps into one horrible mess, and these were something which I wanted to try and preserve.
Whisky Tango Foxtrot on the left, as opposed to the original on the right
Now this is why people go about the arduous and rather boring process of manually retopology on high resolution meshes. But I want some sort of quick fix and my cake and eating that cake and still having cake, so I set about a cunning plan and broke the model up into separate sections based on the UV island layout, before automagically creating a lower topology. I then checked that the seams were still intact and adding new ones if they were not and recreated an approximation of the UV map, stitched all the parts together again and finally baked the textures from the original high poly mesh. Whew ...
And that all worked quite nicely. It wasn't "quite" as automated as I would have liked, and wasn't "quite" as good at retaining mesh loops as I had hoped for, but it did work. Having said that perhaps taking the extra time to manually retopology the high poly mesh into a lower poly mesh may be worth it ...
Next up was to rig the whole model with an armature for animation, and export as we would normally via the COLLADA exporter. Except the new Blender3D 2.8's COLLADA exporter has a whole range of new and completely undocumented options. So, in usual fashion I just went and dived in testing what worked and what didn't.
Nope
Nah
Eventually I got a rigged armature exported. It turned out it didn't like being parented to the actual skeleton directly and could pick it all up via the armature modifier. Now for animations!
Dancing on ice? Close but no banana as far as a nice clean export goes ...
To successfully export an animated model required making disabling exporting of all actions and relying on keyframes only, whilst keeping bind info and sorting objects by name to prevent a duplicate armature from arriving for no particular reason ...
I wrote a more detailed thread up on the forums here.
And eventually I got a working, and fully animated character out of Blender3D 2.8 and into the game.
Those Taoist charms say no and they mean no
Whilst trying to get the more hardcoded movement-to-attack animations working I came across numerous issues (which is just kinda part of life as an indie dev to be honest, especially when you're a One Man Army). The first was an unexpected naming convention for attack/recoil animation which took a day and a half to solve. This would have been a lot quicker if I had just gone and looked through the source code instead of thinking that something else was wrong.
The second was that the weapon finite state machine (FSM) kept overriding my second fire state with the first. The character has two handguns and I wanted them to fire each in turn for the standard light attack, and then both together in a heavy attack, except only the first light attack would work and occasionally half the animation for the second would attempt to play. It turned out that because I was using a hardcoded "stateFire=true;" setting, on loading it would store the animation, audio and particles for the fire state into memory and reuse it in any other state that had stateFire. However, stateFire does not actually launch any attacks or projectiles as that is all done via each states script, so by disabling stateFire on the second light attack I could prevent it from overriding the state and have the left handgun shoot.
And here is the game in all of it's post-yellow cube glory. This is the old DirectX9 version and not the new PBR one, recorded at a slightly janky 30fps because my upstream internet is bad.
So, that was the month that was ... I learned the new Blender and PBR by accident, pummelled exporting and animation until it worked, and finally replaced placeholder cube with an actual working character. And tomorrow is the first day of meteorological autumn.
Environmental level creation continues in earnest.
Level 4 is a grassland, inspired by the Asian Steppe. Originally the grass was going to be green, but the previous level was predominately green, so for variation I changed it to a more prairie yellowish-brown.
The Steppe, home to deer-monster, Wendigo-type, thingies ...
Grasslands, by their very nature are somewhat ... well, bland. There's a lot of grass and low rolling hills with more grass and not very much else. The level is mostly wide and flat open spaces, with high, dark, rock walls to limit the playable environments outer reaches. I added a few extra rock outcrops to break up the vast expanse and created a central "hub" mountain which dominates the centre of the map to create a vaguely circular map with a lot of open space. To disrupt the near constant flow of grass I threw in a few autumn coloured bushes which help add variance to the monotony, and clumps of violet flowers for a colour deviation. The violet flowers are all clumped around the central mountain, whilst the red and yellow bushes tend to crowd towards the outer edges of the map. This helps the player orientate themselves a little to their position in the wide expanses.
Whilst planning level design I realised that as the game progressed, the levels were getting too big too quickly. I do a lot of heavy playtesting - because, well, no one else is, so it's the only way to spot issues with things. By level 3 I was getting lost quite easily in the various narrow alleyways of the canyon level.
Whilst developing the gameplay and enemies for each level, I had been using my test level with grid textures for each of the consecutive level maps. This meant that I had always been testing in the same space. When I started to create the actual individual levels I had multiplied the size.
I went back and redesigned the first three levels, first cropping them into a more square shape that would fit inside a 512 pixel heightmap rather than a long thin shape that spilled into a 1024 pixel one but didn't use up much of the available space. This saved on the amount of terrain that the engine had to render and precompile collision for, which in turn saved on the number of polygons that had to be drawn.
The original test level had later become the basis for the first level. This map has a traversable area of twelve percent. Originally I had started by doubling the size for progressive levels but this now obviously far too much. Going back, I redesigned the second and third levels with a formula to increase level size based on around 50%-70% of level 1 size. Thus level 2 now has a traversable area of >150% the size of level 1 at ~20% of the 512 pixel heightmap, and level 3 is >200% larger than level 1 with a traversable area of ~26%. By contrast level 3 has an area of ~33% that the player can traverse.
Smaller heightmap sizes obviously reduce the amount of renderable terrain triangles and collision calls. For the first time I also used the "remove terrain tool", creating holes in the terrain in areas which the player would certainly never be able to see on-screen. This helped reduce the renderable area further.
Thick foliage.
Thinned foliage -50% polygons. Textures with less leaves show more transparency.
In the spirit of creating complex but also lean environments to reduce overhead I had another look at all my foliage. Whilst grass clearly needs all of it's polygons, I thought that I might be able to save a few on the bushes as the leaves near the undersides are not all going to be visible, obscured by those on top. I selected all the polygons that could be seen from directly above and deleted the rest. Depending on how thick the textures are with leaves, this thinned the viewable foliage somewhat, but for a saving of a whopping 50% polygons. Bushes are there to add movement in the wind and prevent the levels from looking barren, they're not there to hide the terrain beneath them so being more see-through is not a problem.
I tried the same idea with trees but the saving were so small - around 10% - that it didn't seem worth bothering with, so I left them as is.
And that, has been the month of May, 2019. Also the local internet exchange blew up and I was reduced to living a stoneage existence, devoid of memes, waifus, and all the important work related sites and indie game and engine development discord channel I rely on for day-to-day information about work.
In the meantime I rewrote various bits of code related to spawning the player in more open areas, reworked some effects and did manage to have a little play around with the (PBR) Physical Based Rendering package due for release with the next update of the engine.
PBR coming soon ... ish ...
Not entirely sure which bit of the development cycle I will tackle next. I might continue with level building as I am now 40% complete, or I might go back into 3D character modelling and finally replace that yellow placeholder cube with an actual player character.
In the meantime, have a look at some gameplay testing for level 4, The Steppe.
Tune in for next month's exciting instalment of the game development that never ends!
Well, it's been long enough, and in fact seems like forever, that my blank, grid box test level has been on show - but no more! We now have actual game play in actual game play levels!
We also still have Placeholder Player Cube ... but, one thing at a time ...
Starting with level 1 the environment is a dark and rather neglected graveyard, where the dead sleep peacefully ... at least until the player turns up and annoys the hell out of them all (DEEPEST LORE).
And here is a rather long video of the whole thing in action, save for the obviously missing parts of an actual player character and level boss, both of which are currently still placeholder cubes.
But now that we are actually into level design, I am moving quite fast and this month have managed to produce a whole 3 finalised levels.
Behold level 2, The Primordial Forest at dawn, home to ancient plants and even more ancient and decidedly angry velociraptors ... so angry some of them shoot fricken laser beams out of their fricken heads.
And here's a slightly shorter 7 minute video of the level in action. I noticed afterwards that my dinosaurs where not exploding properly and should have been throwing more splatters about. However I had a wrongly named datablock and so the extra gore was not showing up. This has since been fixed.
And finally we have level 3; which I based loosely off pictures of Wulingyuan canyon in China, where the canyon has steep sides of light coloured rock with darker, green vegetation hanging on to every conceivable flat area.
And here is a slightly more reasonable 2 and a half minutes of game play.
In the more cramped confines of the canyon level, I noticed that the enemy spawning often grouped up together at one end of the screen. To create a more even distribution of enemy starting points, I wrote a little algorithm to target the player with the least nearby enemies and then find which cardinal direction (north, east, south, west) had the least enemies and spawn new ones there. This helps to prevent the enemy all starting to one side of the player and spreads the distribution of new enemies out more evenly.
So, their we go. Indie game development is painfully slow, especially for the One Man Army, but once ready to start on creating the actual environments, I have managed to complete 3 levels in one month. That's 30% of the levels done.
Next up, more environments to complete before seeing about replacing the placeholder cubes of the player and boss characters.
So, I managed about 3/4 of Dry January before falling off the wagon. Not a record by any stretch of the imagination but there was a solid few weeks without any booze in there.
Back to gamedev ...
In the last month of the last year I left on the nail-biting cliffhanger of ... modeling yet another enemy. So yeah, 3 years in, and the player is still a placeholder cube ... anyhow, back to that enemy character.
Tentacles, in gloriously awkward to animate 3D
Tentacles. The scourge of cartoon schoolgirls everywhere (okay, only in Japan - literally nowhere else in the world, it's just Japan).
Cthulhu moves to Japan ...
It turn out that one thing a big bundle of psuedopods has trouble with is avoiding clipping into and colliding with each other when you use the minimum amount of keyframes in an animation. Tentacles turned out to be not that difficult to animate, pose into a nice, organic tentacle shape one way, then n frames later and another keyframe the other way. Let Blender 3D do the "tweening" (which is an animation term apparently for automated process of animating between keyframes) and then tweak the middle frame if it looks funny. Unfortunately there was a lot more frames which ended up needing "tweaking" to stop the writhing mass of extremities becoming a jumble of clashing appendages.
Did I ever mention that everything in game dev takes way longer than it would first appear to? Oh, every blog post? Yep, right ...
Placeholder cube getting snug cuddles from tentacles
Anyhoo, eventually said tentacles where animated, calibrated, datablocked into actually enemy AI and unleashed into a game level for tweaking - and boy did they need some tweaking. Player ended up squished rather quickly, then it was a case of tweaking data from too easy to too hard until it met in the middle somewhere.
Big tentacle, little tentacle
During testing I noticed an issue. Every so often a tentacle would fall from the sky past the camera to where it was supposed to be in the XYZ of the game world. I've seen this happen with other models before and each time I fixed it and then forgotten what the cause was. The last time I fixed it I remember thinking that next time I will know the cause adn solution ... except for I have forgotten it again ...
I went back and checked through my written notes on exporting animations and then through all my "how to" forum posts ... and it looks like I didn't record the reasons anywhere. It's got something to do with animation or COLLADA format export - but that's as good as my memory is helping right now ... so a bit more testing and tweaking of the model and exporter is required,
Tentacle surprise!
I also made a whole load of really cool effects, like spawning and fleeing and attacking - but in actual playtesting there was so much going on that a lot of it is easily missed and the constant rattle of tentacles bursting through the ground gets rather annoying, so I plan on simplifying the audio and also some of the particle effects.
So, that's pretty much January covered. There was some other maths related stuff concerning getting player evasion to trigger the way the player is moving when it's different from the way they are facing - which ended up being more difficult than expected because I forgot to take randomized camera rotation into account on spawning and also forgot about normalizing vectors in 3D space - but it was mostly tentacle animating.
To be continued ... possibly indefinately at this rate ... naw I'm just kidding, I'll ship before Half Life 3.
We are so into the future, and it is only another 2 years until the Tokyo Olympics. I can't wait.
Soon ... (ish)
And so to the New Year, which began with great productivity (once the hangover wore off) and "Dry January" commenced. More on that later.
First up was going back over some old ground and changing things ... which to be honest, appears to be 90% of what consumes my development time. I had used a small number of open source/creative commons/CC0/CC-BY images. I ended up stripping these out and replacing them with custom imagery. The most used one was of a cat, which was changed to be a tiger.
I dropped the sole icon I was using from http://game-icons.net/ (a really useful resource) and replaced it with my own custom one. This had been for the "Tough Skin" powerup, which during playtesting I had thought was underpowered for a rare item and so doubled the amount of damage it stopped from 10 to 20 percent.
"Tough Skin" Rare Powerup, Now With Less Gauntlet And More Catgirl
The overall layout of the player's interface/HUD went through another iteration, and a skull was added to the kill/gore gauge which fills up and changes colour until it completes level 4 and a Momento Mori is triggered. Upon this the player becomes invincible for 60 seconds and scoring multiplies by 8 (that's the old 4/8, death/wealth for the Far East), and all attacks now deal critical damage to enemies.
Object which mounts to the player to signify that the Momento Mori has been activated, and they are now Shinigami, God of Death.
Kinda like this guy but you have to make your own atatatatatatatata sound
I also altered the textures for the Gradius style followers which can be picked up and upgraded via powerups, giving them each a little sheen which passes over them. They are little weapon platforms which follow the player around and increase firepower. I spent a while in the depths of C++ changing their start/stop movement to make them move much smoother than they had before.
I am most proud about getting this gif to loop seamlessly :P
One thing I noticed about collecting offensive and defensive powerups is that there could be a disconnect between the information displayed to the player and what the actual effect is. This is because special attack and defend abilities are triggered using an RNG. The more abilities the player has, the greater chance of an activation. However this doesn't mean that the last powerup will trigger next, so I changed that so that it always triggers on the next attack or defence - thus giving the player a clear idea of the ability of the object which they just picked up.
Collect "Magic Bullet" offensive powerup, immediately see it used on your next attack
And so onto FUNBALLS. If the esoteric words "RoR, /v/, Git Gud and Host When?" mean anything to you, then this should give an inclining as to what comes next.
This is a FunBall. You can tell it's a FunBall due to the word "FUN" written on it and it's murderous grin
FunBalls are fun - okay, they're not really, they're bombs which some enemies will drop. I also intend to create an unlockable challenge mode when everything will drop FunBalls upon death.
I am using a slightly basic collision and physics system (hello rigidBody) for speed and convenience. FunBalls didn't look very good as standard objects due to sudden rotation changes when they bounced. To combat this I made the object a billboard so that it always faces the camera and used a scrolling texture to give the illusion of smooth, spinning movement. I then created four variations, leaving one central and rotating the others (off-left, off-right and upside down) so that when a number of FunBalls burst from a deceased enemy, they have plenty of variation but the player can always see the grin at some angle.
FunBalls in action! Audio has since been changed.
And upon all of this, there have been numerous little tweaks and changes to how things work, as well as much planning on the data of enemy types as the levels progress (though everyone is still a placeholder cube right now).
Did I mention "Dry January"? My performance at darts really suffered so halfway through the month this kinda happened ...
Next up, more sorting out data and attack types for enemies, and some considerable reading up on this new fangled thing called PBR.