Showing posts with label ai. Show all posts
Showing posts with label ai. Show all posts

Saturday, 28 February 2026

An Arrow To The Knee But Then I Raised The Aimpoint

 

 I used to be an adventurer like you, but then - whizzzzzz ack! Since this video there is a cool motion trail effect courtesy of a ribbon particle behind each arrow as it cuts through the air.

So archery has been somewhat missing as I have been concentrating on devising an animation led melee combat system. This now work rather nicely (except when it inexplicable doesn't play the prepAttack animation and I have to throw in a safety call to get it back on track) so it was time to get on to ranged weaponry.

Cue Clannad and the greatest decade in history, the 1980s.


 Now, because I've upended the whole stock animation system, it turns out that mouse aiming system no longer works, because who wants mouse aiming to override a melee based animation system? Well no one, so that will take a bit of looking into to fix. However the actual aiming and shooting works, even if the AI and client Player doesn't currently animate correctly to look like it, due to the removal of most of the blend animation code.

I have a variety of ranged weapons coded, both differing sizes of bows and crossbows, with bows requiring greater stats in both STRength and DEXterity for use which make them much more expensive in XP spend to use, but having hugely quicker reloading than crossbows. 

Projectile damage is based on a singular strike to the target's hitboxes, so whilst a heavy melee attack can cause damage to multiple hitboxes with a wide slashing motion, arrows cause damage based on range to target to simulate increased velocity from loosing up close and the archer's ability to pinpoint weak areas in the target's defences. Getting struck at maximum range whilst wearing a full harness is most likely to plink off, but getting shot up close with 300lb of draw weight is another matter.

The main level has had a bit of a revamp, with more trees and shrubs in the open side of the map, but there is still plenty of nice open space for longbows to wreak havoc. 

I also converted my AiPlayer routines to use the new stock engine AiController system, which can be attached to any playable class including those usually restricted to clients, to turn them into Ai controlled - hence the new classname. This class has a lot of dynamic avoidance and automatic repathing systems, but even without those I found it to be very heavy on processing. Whilst still useful for being able to control the usual client based objects, it's clearly something to be used sparingly, and to keep the standard Ai based classes to themselves.

Archery is pretty much the final part of the Ai warbands and battle system, and with it now functioning materially (if not animating aiming perfectly) I need to integrate it's use into the AiPlayer combat routines. The most obvious example is for a warband that outranges an opponent is for them to stop, hold fast, and pepper the enemy at distance whilst they themselves seek to move to attack.

Whilst this is all in the works, here's a video of meeting engagement between the Norse and the Magyars, the latter of whom will be one of the more heavy ranged weaponry factions in the future.


 Aside from fitting archery into the individual AiPlayers' combat routine, I need to come up with a method of allowing the player to use archery effectively, regardless of their third person rotatable camera system. The obvious cop-out here would be to follow Elden Ring's lead and switch to first person for aiming. Maybe I can come up with something else which retains the third person view ... ?

Speaking of the player, to be honest they haven't really got a lot to do at the moment, as all my efforts have centered around making the AiPlayer's work as cohesive raiding parties, so next up after I tackle the blended aiming animations, is to give the actual client player something to play.

It's February, and it's ending early, somebody stole 2 extra days that I could have been coding! 

Saturday, 31 January 2026

The Great Debugging

Initial attempts at Inverse Kinemetics proved imperfect

 So THE GREAT DEBUGGING of actually trying to get our warbands to operate in a terrain environment has begun. And the good news is that it has almost™ ended.

Mistakes were made, and the good news is that it wasn't all be me, but also the data libraries which I use >>> I AM LOOKING AT YOU RECAST PATHFINDING. And I'm not even using AI (lol!), imagine how much worse it could have been!


So just pathfind across the RIVER OF DEATH and into the CLIFF OF IMPASSABILITY
 

Recast Pathfinding is a great resource, so great that I wrote my own pathfinding plan function that actually bothers to check if the pathfinding plan gets anywhere near the pathfinding objective ... not that I want to completely write my own pathfinding system you understand because I am not batshit insane.

But I did come up with a system of fallbacks, now that my own function actually bothered to tell me that the pathfinding library had, what we would call in layman's terms; FAILED, but for some reason it thought was fine to deposit everyone wearing heavy armour into a deadly deep river with unclimbable cliffs was some sort of mathematical success.

I want to get into the middle of the castle

Thankfully my own functions used something called basic reasoning that when the path ends hundreds of yards away from the goal position that it might actually have failed and we should try other things. Other things however still relied on Recast's "meh close enough" being ANYWHERE in the map rather than at the literal destination, so I came up with a level specific functioning system where I could direct the pathfinding to actual traversable waypoint paths to overcome the RIVER OF EVERYONE IS SINKING.

I want to get into the middle of the castle and I will use the waypoint on the bridge because I am forcing it to

And then there was the whitespace ... admittedly this was all down to me in the script files but "whoa laddy!" hunting down all those "objID" != " objID" has been a right royal pain in the Prince Andrew. So my apologies for a lack of interest but low fps debug build video of my multitude of warband troopers running about undulating, river obstacled terrains, knocking seven shades of the brown stuff out of each other. You will just have to "trust me bro™" that it really does work.

I also attempted some IK shenanigans to get the player's feet to actual transform to uneven surfaces, and as you can see from the first image is worked great ... but only if you want to stand like a sugar plum fairy ... and movement wasn't much better either.

 

Speaking of SHENANIGANS!

It had been brought to my attention, via SteamDB that Airship Dragoon had spiked in player count, a good 12 years after release.

 Bizarre.

 I had ignored this and thought that it must have been a bug, yet ... Steamworks verified the player count. 

 And the nations were somewhat surprising ...

I hope no-one is using this actual military tactics ...

 So ... there you go, highest consecutive play count ever, in 12 years ... so I'm thinking ... bots going for trading cards? Not sure anyone is buying those trading cards though ... so ... it's a mystery.

 Anyhow, just like Skeletor memes, until we meet again! When I will (hopefully) have some video of my warband game in full action over a real playable landscape! Not that there is anything for the player to do yet, but hopefully human fleshoids aren't as prone to fubaring everything up as a machine.

Hopeful, ever hofepul ... 

Monday, 30 September 2024

Autumn Arrives And Ai Attack

 The big Summer fan has been put away - not that it got much use anyway - and the Autumn duvet (which is just a second Summer duvet doubling up) is out. The slow cooker has been dusted off for comfy one pot meals, and the hot water bottles are at the ready.

And it finally rained, and my parched veg patch was happy, and all the water barrels got filled up, and now it won't stop raining and the veg patch is flooding.

Code wise, I've been working on my Melee Combat Demo, getting the Ai to fight one another.

The first problem was, well, the other Ai, and them getting in the each others way. In Monsters Loot Swag this was a more simple problem, as I could just have them jostle each other out of the way, with a variable to succumb to any charging monsters who were "coming through no matter what", like bosses.

In Melee Combat Demo I don't really want to shoving everyone and everything out of the way so much, especially if all the people in front of Mr.Ai are already engaged in combat. It's not very helpful to shoving your comrades onto the sharp pointy bits of your foes' weapons.

I came up with a simple; "is there a better target?" check. And if not; "can we easily get around the side?" of the queue in front of us, and if not then just wait. And if no useful data comes back, then to hell with it and go charging through like a bull in a china shop.

Ai use an alert system for readiness, which decides on how fast their thinking routine is called. It starts off at "chilled", increases to "look for trouble" and hits the summit of "oh shit things are kicking off" ... also known as 1 to 3. All these schedules for looping the think routine are modified by the skill or leveling of the Ai, and that is currently based on what weapon rank they are using.

Starting alert looks to do something, but at the moment all I want them to do is test combat, so they move to search mode and head towards any enemy that they can find. There is a brief lull between this and going into combat alert which means that in the test they do make physcial contact between the two teams before all hell breaks loose.

And here is the result of the testing, after I inserted many, many lines of debugging to the console to find out which bits of my maths were bad. Team Bill the blocky blue guys massacre Team Bob the purple-ish LODed guys with a score of 5-2.

Needs more work but it's a decent start and at least does work as team based melee combat.

In non-dev news, I actually played a game recently - shock horror.

Not since Ace Combat 7 came out have I actually played anything, but I got Kingdom Come Deliverance on sale some time ago, and took a couple of weeks out to hammer a good 130 hours into  it. I wasn't really playing the story much, just bimbling around medieval Bohemia accidentally finding side quests and generally shooting bad guys with arrows to slow them down and then stabbing them in the neck if they got too close. It's a strategy I'm sure worked in the 15th century too.

The game world is quite pretty to look at, the first person combat is autistic but passable.

So to the future, more getting Ai melee combat to work nicely, and then start thinking about equipping the characters with more kit. I'll probably also start thinking about making another playable character to be unlocked in Monsters Loot Swag, and probably complain about the weather more, but that's probably called sport to my Saxon blood. Also three probably's in one sentence is terrible grammar, so I'll probably stop writing there ...


Thursday, 30 September 2021

One Year Of Aeronauticals

 So it has been an ENTIRE YEAR (from 1st October 2020) of working on my aeronaut/aeronauticals/dogfighter game that was loosely inspired by Ace Combat with 1930s aircraft and a lot more tightly inspired by Descent: The Great War space combat simulator but with gravity.

How it started (after a month or so anyhow) ...

And, how it's going ...

 
So ... that's been a bit of a change then ...
 
First up, I've created a brand new class of object, aeronautVehicle, that derives off vehicle class, which derives off rigidShape which is the thing that controls the physics, and shapeBase class ... which everything and it's dog seems to derive off if you want it be any form of a dynamic object.
 
This meant that I had to work out how an aircraft actually flew worked. Obviously this would be incredibly boring so instead I worked out how an exciting arcade style flight model worked basing it on ideas and physics values that I mostly pulled out of my bum.
 
Actually that's not entirely true, I did detailed research for months previously, basing everything on real world values and compiled lengthy text files on how the whole thing would work; eg: hitpoints were based on empty aircraft weight divided by length per area element (wings, tail, etc); and thrust was based off maximum take-off weight divided by kilo-watts of power per engine (or something like that) with modifiers for total aircraft area versus air friction... eg: fat aircraft would lose speed faster than smaller ones, etc, etc.

Similarly gun damage was based off calibre, calibre per 10mm modifier, number of guns, and some other stuff, with more guns increasing both damage and overheat timing.

The real problem was creating an Ai system to fly the aircraft against the player. Not only did they not have to crash into anything --- which ended up being much harder than you'd think --- they also needed to act as if they were a real pilot, so I ended up making 12 (?) evasive maneuvers that they could pull when neccessary. Stalling ended up being a huge issue depending on speed and attitude of the aircraft and tightness of a turn. I ended up creating a class of super-Ai pilots who I never stood a chance against, and had to dial the whole OP back, discovering that the margin between genius Ai flyer and absolute idiot was very small.

Damageable elements reduced performance of the aircraft's speed, turning, rudder, etc, and the whole thing had to modeled in 3D and textures to give the player good visual feedback as to what is happening to their aircraft.

PBR was a thing ... a thing which I did not know what ORM stood for and so ended up putting the rough and occlusion maps into the wrong channels because that is how they are set out in the materials editor.

My grasp of networking certainly improved, I had managed to create a co-op mode - based on seperate instances on the same box because I only have the one machine - and I soon realized that I wasn't supposed to just fill the whole of pack/unpack with all of the read/write data because much of that was on the server anyway. Trailing definately need to be on both or either Ai/players would trail and the others wouldn't depending on how they were handling their aircraft. Huge amounts of pack/unpack were commented out and the weird jittering my AI aircraft had been doing in debug mode stopped.

I created a crude lobby system were the level loaded without the mission starting except a briefing to give the player the details of the mission via a seperate file and to choose their aircraft and paint schemes. The player would then wait in this psuedo-lobby for other clients to connect or start a co-op multiplayer mission alone and newly connected players could drop in and out. Debriefing required a bit more voodoo as shifting large amounts of player-mission contextual descriptors - that's text - required some fancy thinking to avoid abusing huge numbers of server to client calls - something that I had been very keen on working smoothly and with the least possible amount of bandwidth.

 Creating missions was a series of timed and triggered events based on what the player and Ai pilots were doing. This required lots of scripting due to the lack of physical triggers which a player could walk into on a more normal character based game of the types I had previously demoed or developed.

And so that is kinda of it. After a year of development I have a fully functioning dogfighting game that plays halfway between an arcade shooter and simulator with a mission complete with playable roster of aircraft, briefing, debriefing and drop in and drop out online co-op mode. So naturally it's time to relegate this to the backburner and go return to my previous game project (and really tidy up it's networking) as I want something that can at least be released for Early Access early(ish) next year and Freespace-style dogfighter will require the most work whilst topdown catgirl mayhem is around halfway complete but needs "fluff" adding for the player's ease of life for the first few levels.

Wednesday, 30 June 2021

Events Dear Boy, Events

 So this month I have been coding a "Mission Events System" loosely based on how Descent: Freespace did it.

Chief amongst this creating a system that read all of the spawnPoint data which held all the info for various events, and anything inside the mission's own custom event file, then tried to organize all of that into something which wasn't gibberish.

I can give you a quick rundown ...

   //this is where the mission relevant data is started
   //all missions related events are controlled from here
   //before we spawn the player we need to load the MissionEventFile (MEF) and all it's functions
   //to do this we need to find out how many players we have
   //treat this number as 1 for single player game and start the mission with the first client joining
   //MissionEventFile holds the missionEventList (arrayObject) and all mission event functions
   //spawnPoints inside the missionEvents folder are for spawning and events
      //spawnStart;
         //1 timed or immediate spawn from player arrival; 1 = spawn immediately
      //spawnNear;
         //object that we should spawn near, if spawnDistance > 0; this overrides our spawnPoint location; defaults to player
      //spawnDistance;
         //distance from spawnNear object in kilometers;
      //dataBlock; <<<<< spawnDatablock
         //literally datablock name for player; eg: F11Goshawk, etc. Never AiF11Goshawk though, Ai gets added later
      //dataType; <<<<< spawnClass
         //type of datablock; eg: aeronautVehicle, etc. Never AiAeronautVehicle though, Ai gets added later
      //startingThrust;
         //starting engine setting as F32, default 0.6
      //team;
         //0 greenFor(neutral); 1 blueFor(ally); 2 redFor(enemy); 3 yellowFor(aggressor);
      //skillLevel;
         //Ai skillLevel 1-10; modified with difficulty
      //callsign;
         //name for vehicle or wing of aircraft based on wingNum and isWing number;
         //eg: solitary isWing0 "bob"
         //eg: isWing 2, wingNum 3 "bob3_2"
      //isWing;
         //0 = no not a wing only 1 vehicle or was a wing which has already been reduced to 0
         //1+ = is a wing, this number goes down everytime the wing is destroyed
         //wings respawn with wingDelayMin/Max time when reduced to wingMin number of remaining aircraft
         //a new arrayObject is created for the wing and all aircraft are added to this from that wing
         //eg: callsign "bob", arrayObject "bob_wing"
      //wingNum;
         //number of aircraft in the wing
      //spawnedNum;
         //number of the aircraft spawned in a wing, ++ until > wingNum then back to 1; this is set by scripts not editor
      //wingDelayMin;
         //minimum number in seconds for the wing to wait before spawning another wing and reducing isWing value by 1
      //wingDelayMax;
         //maximum number in seconds for the wing to wait before spawning another wing and reducing isWing value by 1
      //wingMin;
         //number of surviving aircraft when a new wing will spawn with wingDelayMin/Max. Default is 0, but best set to 1;
      //mainTask;
         //mainTask; 0 do waypoints; 1 dogfight anything; 2 strike target; 3 escort;
      //mainTaskTgt;
         //object for mainTask, can be vehicle, arrayObject list of targets, waypoint or path
      //eventTrigger#;
         //type of event to happen
            //onArrive - has spawned
            //onDepart - has departed
            //onDamagePercent - damage has gone below threshold
            //onDestroyed - uses callback onDisabled and onDestroyed for second check
            //onWaypoint - has moved to waypoint position
            //onPathComplete - has completed the total path
      //eventObject#;
         //object id; eg: onWaypoint = waypoint id; default blank/0/"" is spawnDatablock's object
      //eventDelay#;
         //delay in seconds from the eventTrigger# being completed
      //eventResult#;
         //result of the eventTrigger# occuring
            //script name; function to be activated from missionEventFile (MEF)
      //eventTarget#;
         //target of the event to do something, specifically used for spawn;
         //if no target then it should refer to a local wing or aircraft
         //eg: scorpio wing now spawns in 10 seconds due to eventTrigger1 "onWaypoint", eventObject1 "player", eventResult1 "spawn", eventDelay1 10, eventTarget1 scorpio wing
So that's my own comment notes in the file, though some of that has since been changed ... probably.

Part of this is "wings"; groups of aircraft that spawn together and can respawn in "waves" when their number has been depleted to a certain amount.

Contextual Messaging about Events in the top left

And what are events without victory and defeat conditions? Not very interesting that's what.

Events - hurray you didn't bugger it all up!

So with all of this in place it was time to create something which looked like a proper game mission. And here it is!

Here's a quick overview of what happens:

  • Victory Condition: All enemy are destroyed
  • Failure Condition: All allied reinforcements are destroyed
  • Player Spawns Event
  • First enemy wing SCORPIO spawns with a delay in response
  • Enemy wing SCORPIO is destroyed
  • Allied wing of reinforcements spawn in response to SCORPIO onDestroyed
  • Enemy wing LIBRA spawns after delay of reinforcements arriving. Also enemy wing TAURUS spawns with an even longer delay, near reinforcements.
  • After losing 3 out of 4 reinforcements I go and help out the last one before completing the mission.

In this playthrough the reinforcements were not very effective and got pounced on early by the enemy fighters, in other tests they accounted for some kills and assists.

When the mission is over status of all aircarft is printed to the console, detailing kills, assists, damage and the such. Eventually this will be part of a debriefing screen.


So that is the month that was. Roll on July.



Wednesday, 31 March 2021

Replace The Placeholder Plane

 Placeholder aeroplane, which I downloaded from some modding site that I can't remember, has been replaced by my own aircraft model.

It's an F11C Goshawk biplane, which is now itself a placeholder for all other aircraft which I haven't yet modeled.

I also coded a damageable area system to give the model a visual personification (don't really think that was the word I wanted but hey ...) of the GUI damage system.

Model now displays damaged areas the same as the HUD damage indicator bottom right

Initially this was just meshes that used the same colour system as the GUI/HUD damage indicator for area based damage so that I could see that it was working. The idea is that the aircraft model is made of multiple meshes, engine, body, tail, wings 1, 2, 3 etc and these meshes are displayed hidden depending on how much damage each individual section has taken. There are 5 levels of damage, the first being undamaged and the last being destroyed. Eventually when an area is completely destroyed it will spawn a debris or rigidShape of the part of the plane which has been shot off. Eg: the top wing will appear to rip off and the aircraft will plummet to the ground.

I also use this show/hide mesh system for the muzzle flashes of weapons. Previously I had simply hidden the meshes inside the model at a hugely shrunk scale, and then animated them into full size.

Next up was to test the PBR and make up some textures. I knocked up a very quick normal map and some metal and roughness maps. Initially they were rather dark, eventually I discovered this was due to too little roughness so that the metal map was rather overwhelming things.

Ignore the catgirls at the back, just comparing PBR ...

After a bit of faffing I got PBR materials working, and thought that the whole looked pretty good actually.

Not bad if I say so myself

After this I proceeded to test the damage system with bullet holes. Here I noticed a fair bit of stretching which could only be remedied by completely redoing the UV mapping.

And here is a test of an AI air battle using the PBR textures. In the end I get my top wing shot off, which disappears as there is currently no debris object for destroyed areas.

So, that was the month that was.

Next up are redoing all the texture maps, albedo - which I never seem to be able to spell correctly, never had this problem when it was called diffuse - normal, metal, roughness , AO and of cause all the accompanying damage meshes and maps. After that, on to more model aircraft.






Sunday, 31 January 2021

Space Year 2021: Stage 1 of 12 Complete! Dogfight!

It's the futuristic space year of 2021 AD, stage 1 (January) of 12 (the Annum) has been completed ... though you might be forgiven for not noticing ... 


Having previously worked out my issues with Ai pilots taking a leading aim on a moving target I have spent all of January getting them to actually dogfight one another. Choose target, go fast to get into shooting range, slow down to follow it and blow it out of the sky. Took a bit of doing but worked nicely. 

Next up was creating a system of evading when an AI came under attack rather than just sit there and get shot at. Reading through vast tomes of air combat and aerobatics, I managed to come away with ten meaningful emergency maneuvers to try and shake an enemy fighter, and added a barrel roll if none of the others seemed to be an oppropriate match for the defenders circumstances.

 That's not a barrel roll (ノಠ益ಠ)ノ彡┻━┻

This brought some problems itself, that in high-G maneuvers such as a Stall Turn, the Ai had a nasty habit of losing all energy and ... well, stalling ... a lot.

He's written his Artificial Intelligence Pilot Engine Management System? Stall it.

So then I embarked on a complete rewrite of how my Ai would use engine management. Previously it had been a simple case of setting engine percentage with a nose attitude modifier, now it was all about maintaining the desired speed. This massively reduced stalling in tight turns but not completely eradicated. So I added an anti-stall system that would force the Ai to move to a desired rate of knots should their airspeed drop at a rate that would bring them within the losing height at level flight, with a nose attitude modifier. I reused the anti-stall method which I had written for spawning aircraft and getting them up to their starting speed immediately. The maths required a bit of evening out for an object that already had velocity in 3 dimensions and initial attempts had some supersonic thrust propelling the vehicle across the sky like Warp Factor 9 but I ironed these out eventually.

Unedited video of an 8x8 dogfight

Coupled with all of this was the the obvious need for collision avoidance, both from other aircraft and the ground and max ceiling which each aircraft type can go up to before the engine is starved of oxygen and stalls. Dynamic collision avoidance of other moving objects was somewhat of a pain in the maths but I got there eventually with very little happening in the way of head-on collisions during mass heda-on attacks at each other team's formations.

32 aircraft head on attack - no collisions just 2 shot down
64 aircraft battle moments after the first pass, and why it's called a dogfight I guess

In other news I decided to update the banners on my youtube account, and give them some new artwork. Here I discovered that it doesn't actually let you reposition your artwork and keep scale after upload, so had to edit the image to fit into their stock measurements and orientation.

I also spent quite a bit of time viewing train stations webcams on a spare monitor whilst I worked for maximum comfy.



Everywhere seemed to be getting snow ... except me, it just rained here. (๑′°︿°à¹‘)

So, that was January, Year of The Koof Part Deux, pubs are still shut then ... Join me again in next months exciting episode of "why is maths hard?"


Monday, 30 September 2019

Big Boss Battles


The Big Lad

So after the joy/struggle/despair/awkwardness* (*delete as applicable) of learning how the new Blender3D works and then creating an actual character to replace the player's Small Yellow Placeholder Cube, it was time to go after the remaining Big Red Placeholder Cube which had been standing in for the level boss character.

As ever things went horribly wrong for seemingly know apparent reason other than the entire universe having it in for me.


I had split up animations from the actual mesh - that way it keeps loading times down whilst changing things on the fly during development, and means that multiple models with the same armature skeleton can share animation data and thus reduce file sizes - when suddenly everything stopped playing nicely and went back to mutating into a horrendous mess of twisted limbs and multiplied rotations.

The reason this time turned out to be because I was exporting the mesh model in the first frame of the root animation - which is what you would want for blended animations - but I should have exported it out in a copy of the rest pose ... regardless of the fact that this had previously been fine with another model ... which meant that the solution was far down my list of things to test to see if it worked ...

Exporting COLLADA/DAE format from Blender to Torque has become even more specific in Blender 2.8, mostly due to there being a huge number more options available and thus a huge number more things to possibly go wrong ...

https://pbs.twimg.com/media/EDtDhZyXoAApzaI?format=jpg&name=large
I before E except after C ... Also Hierarchy which breaks the rule, and hierarchy is very important ...

I ended writing a little explanation of Blender3D to Torque3D Collada exporting and the importance of hierarchy over on the forums.

Eventually I managed to get "The Big Lad" - as he is currently known unless I can think up a name later - into the game and working. Here's a quick look at him in action. I say "quick" because he squashed me in not too much time. Select quality 720x60fps manually or youtube's autoHD says it's selected it but it's telling fibs.

I fearsome foe! Especially as I end up as pate ...

Apart from that, I modified my laser-beam-wielding veclociraptors by adding helmets and power-packs to them so that they now look different from the other dinosaurs which just bite.

Sharks Dinosaurs, with frikken laser beams on their heads!

I also spent some time modelling industrial scenery, lots of pipes and stuff for a forthcoming level. This will be the fifth level in the game, out of a total of ten - though they will loop for long play. No actual pictures of that yet as it is still all in bits.

So, that was the month that was. It got really warm and now Autumn has truly arrived and I've put socks on. Lot's of other things happened game development-wise but I can't really remember them. Next up is the Overgrown Industrial Level which has been reclaimed by nature, and more boss monsters.

Thursday, 31 January 2019

Terrible Tentacle Terror!

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.

Sunday, 25 November 2018

Dimensional Knight Animation Anarchy

Remember this guy?


He is one of two Knight models which I customized into my Unstable Dimensional Knight enemies all the way back in summer (summer now a distant memory as I hundle under a blankie whilst freezing rain peppers the external windows). Dimensional Knights suffer from "instability", something most RPG and fantasy wargamers know affects inter-dimensional beings, and that's why parts of them kinda of warp in and out of existence. Whilst the models were good quality and rather (too) detailed - way more polygons than I need - I found that their animations were a bit lacklustre having not been based from motion capture footage. Not particularly seeing any mocap which I liked for a reasonable price commercially, to get some decent custom animations I decided to amalgamate their stock animations with some free mocap and rotoscoping - the latter being a horrbily time consuming animation but more exact than "best guess manual animation", at least for positioning large items like limbs.

And this is where total chaos ensued.

It didn't help that was now using three seperate armature rigs (skeletons and bones), what with the bvh format mocap files being different structure from the models' source files which were different from my generic animation rig. Now it's not too difficult to rename bones, animations and mesh vertex groups, except at some point quite early on, I changed the basic non-animated root pose - thus throwing all the rotations for animations off. Annoyingly I only realised my mistake towards the end, and with four variants of two models, ended up having to manually repose all eight enemy models individually by a mixture of copying coordinates and using the judgement of the old fashioned Mark 1 Eyeball. Between this and manually merging different animations together along with rotoscoping over other animated meshes and video stills created a huge gravity well which sucked in vast amounts of time and effort.

Eventually I had a two spawning animations were our Demonic Knight salutes or issues a challenge to the player, two idle animations with some weapon flexing, three attack animations, one leaping overhead special attack animation and various jump, fall, land and other animations.

 2 models, 2 idle animation poses, 4 colours

Then there was the slight issue of how to get this enemy type to move. If you are an "Inter-Dimensional Being" then walking seems like a rather mundane method of traversing the game world. Having them just ski along in their root animation made it look like I couldn't be bothered doing a movement animation so instead I created a floating animation. This also looked a bit unexciting at first, initially because the animation resembled the "T-Pose" that many models revert to when they are not animated. I changed this to create two seperate movement animations, one were the enemy holds their weapon in front of them a little like the holy pose that sculptures on the stone coffins of dead knights have, and the other were they are reaching out towards their target with one hand and raising their sword as a sort of challenge in the other.

To the models I added some extra effects to give them more of an other-worldly feel and an intimidating presence of power. One of these is a simple translucent cloud which looks like a particle effect but is actually just three rotating textures of differing intensity and colour. The other is an aura of power on the ground which is connected to the enemy's animations. This gently pulses when they are not moving, spreads and rises during their attacks, and shoots up to envelop the model when they move, making for a much more interesting floating animation. They model also elongates slightly when they move which makes them more intimidating. To the Knight's textures I added a bright animated outline to help with a shimmering glow around the edges and dropped the actual glow shader I had been using on the materials. This reduced drawcalls by a couple whilst reducing the need to draw an extra 27K mesh triangles. As one of the models was a 16K triangles, I decimated it automatically down to a more manageable 12K with no visual impact.

I created a new special attack for this enemy type which involves them teleporting close to a clear area near the player. They start their special attack animation of a jumping overhead axe swing and particle effects surround them and the position that they will teleport into to complete their attack. This gives the player 1 second of warning to get out of the way. Initially I also created an invisble collision shape into the area to block the player and other enemies from occupying that space but realized that it would interfere with how decals are positioned, so I swapped the collision mesh for a physics zone which keeps other enemies out of the area but can slow the player down if they enter it. This seemed to work rather nicely. Originally all of the Dimensional Knights had this special attack but as I based it off the movement phase rather than just the attack phase I realized that would cancel out directly hunting the player as an option to the enemy AI's thought cycle. Now only half the Knights have this teleportation attack whilst the others move as normal, either heading for the player's last position or following directly as a hunter.

Here's an early look at the Dimensional Knights in action before I had finalized their animations.



So that was the Unstable Dimensional Knights of level 7 completed. A tough slog which took far more time than I wanted ... but I say that every month when I write these blogs ...

So, what left? There are a few more enemy types I want to make. Going back to the old Monstrous Morris Men Wendigo style enemies, I want to add a nymph-liek character with a special attack that includes a dash through the player, however as they will share various animation characteristics with player characters, that is something to leave until the more monstrous monsters are done (rather than constantly going back and forth between things). So next up on the list of over nine thousand things to tick off are those of a more Cosmic Horror motif. Cue tentacles and Lovecraftian madness ... and Lovecraftian madness seems to be a good description of indie game development ...

Monday, 29 October 2018

Glowing Golems And The Curious Tale Of The Non-Invertable Bind Shape Matrix

Whilst agonizing over golem design followed by golem re-design, I had a mangled LOD mesh which resulted in a crash. Making a slight change to the mesh and re-exporting fixed the crash, but I also noticed a curious error warning in the console (which probably wasn't related).

bind_shape_matrix in mesh# controller is not invertible (may cause problems with skinning)

 Wut?

 A little bit of digging around the codebase led to these most useful code comments.

   // Some exporters (AutoDesk) generate invalid bind_shape matrices. Warn if
   // the bind_shape_matrix is not invertible.

Wut? 
 
Okay that wasn't very helpful. What would the skinning problem be (I had not noticed any) and how do I fix it for export from Blender3D? Alas, the interwebz were not particularly useful in  determining how to do this, so I started a process of elimination, based on the logic available. Deducing that many of my models were rotated and vastly resized soley using the armature, I eventually found that uncoupling the mesh from the skeleton, and manually editing the mesh to resizing, rotate and align it to the bones cleaned up this error message.

The downside turned out to be how many instances of this error there was. I have so far created a variety of characters which weighed in at ~110 seperate meshes, and 85 of them needed resizing and manually aligning - and as it was the meshes which required directly editing, I couldn't just snap one object to another - which is actually part of what caused the problem in the first place. At least it was an error caught before I got to the end of character creation, but it would have been much less hassle to have found this out at the beginning, possibly with some huge flashing warning than a few red lines in hidden amongst the jumble of text in the console soley during first importation.

Golems, golems a plenty

So this brings us to golems, and the constant redesign of the little blighters. Who would have thought that creating a vaguely humanoid shape out of clay/rock/earth would have been so complicated. The problem was, I didn't really like any of the designs which I came up with, thus creating a whole array of slightly different clay men ensued. Eventaully I went back to my first design and added glowing cracks. Initially I had these cracks animated, first with a pulsing effect which didn't seem to be very obvious, so I changed that to an animated one. This looked quite cool when they were not moving but became rather busy and not particularly obvious with them running about, so in the end I decided to keep the glowing cracks static.

I made a rather interesting spawn animation from which the golems are created from animated rocks gathering together and then fall away to reveal the monster within. It looked quite fancy having it happen over time but this is an action game so the whole thing had to be compressed into one second. Likewise when a golem is slain it collapses into it's constituent parts of rock.

Golems Spawing, pre-glowing cracks

In game, the golem is a small and heavy enemy, best suited to swarming the player. As they are made from earth/rock/stone/etc they are very heavy and cannot be pushed out of the way (at least not by the physically weak gun wielding, range-based default player character). Golem has death in Hebrew written on it's face - not that you can see this at the scale and angle, but hey it does.

I also changed the overall colour scheme of the game, getting rid of the greenish colour and replacing all of the HUD elements and user interface with an old blue colour I liked.

Green out, blue in

And here's  the golem level in action.


So far I have around 70% of enemies for levels done - not including level bosses, and of course there are a number of player characters to yet create and replace that yellow cube. I am leaving those until last as they are all a variation on a theme and will share the same skeletal structure for animation.

Next up is organizing animations and data for attacks for my old "Dimensional Knights".

Soon ...

Saturday, 31 March 2018

Math Is Hard

Apparently ... as our Western cousins like to say ...

Math Is Hard

And sometimes, it actually is.

 I was attempting to redo ... reimagine ... resomethingerother ... my current game's difficulty curve. This proved harder than I was expecting, and resulted in much flagrant use of Post-It Notes(™?).

Here is the issue. 

Cash dropped by defeated enemies increases by enemy lifeforce (not to be confused with Lifeforce, the 1980s UK/US collaboration which featured this hot bird with massive ... tracks of land ...

(insert own joke, image or reference here)


This film is severley underrated ... for scifi reasons ... also boobz ...

 And back to math ... or as us colonial imperialistic types call it ... MATHS.

I had previously devised (with help of arcane magick, alchemy and winged goblins) a perfectly good manner for AI enemies to have less cash as the player progressed. Here is the CRUX of the issue (somewhat appropriate as it is Easter weekend). The player score points on ANYTHING - especially cash transactions. So limiting the available cash to buy SWAG (powerups) in later levels was good ... but also decreased points which were available to be added to the player score.

So obviously I wanted to reverse the points reduction by letting the AI enemy have a fully score ... whilst increasing the cost of buying SWAG by points x levels x f***knowswot. And f***knowswot became an issue. Much mathematics was done - insert your own doge meme here - nah have this one:





Now you'd kinda expect this to be a simple mathematical reversal ... but that didn't happen. Much toil and even more trouble and three times as much bubble occured (note the reference to prove that I am a psuedo-intellectual). Anyhow, eventually, and after using half the world's supply of Post-It Notes I managed a solution


 
Like this but way more vacant in the eyes ... also more crying

 And so I emerged victorious, after destroying all the world's rainforests in little yellow, sticky papers.

Cost of opening SWAG parcels increased in line with AI  enemy's strength. And all was well in the kingdom of ... er ... game dev.

Tune in next month for all that stuff which I promised I would be doing months ago but have still not got round to!

That stuff I said I was going to do next