You still with me? That previous chapter of The Brick Dead Project, a journal of my trials and tribulations while making a Unity game, sure was quite an ordeal. We could both probably use some therapy after that one. No time now! There’s vidya gamin’ work to do!
I had little enemy dudes. They had someplace to go. They knew how to walk. And, finally, they could be killed. Now they just needed someplace to live. I had just the abode in mind. Remember that “Make Your Fantasy Game” demo from xiaolianhuastudio? The one that inspired the whole undead motif in the first place? Well, it came with more than just fences and tombstones. It came with full blown tombs!
I selected the largest and most exquisite, of course, for my new minions. But it wasn’t quite exquisite enough. Designed with mobile platforms in mind, I was going to do some touch-up work. The textures were up-rezed and sharpened compliments of GNU’s free, open source Photoshop replacement GIMP. From there it was off to a magical little utility called CrazyBump.
Now, I know I’ve mentioned normal or bump maps a couple times previously, but let’s just take a sec and give both this tech and CrazyBump their due.
A normal map a transparent layer that sits on top of your texture. Rather that drawing detail in the traditional sense, it dictates how light reacts to the surface. If you’ve ever seen a metal panel in a modern game and noticed how the creases and rivets react to light and look 3D but aren’t modeled with polygons, you’ve seen normal maps in action. Rocks, trees, dirt, all kinds of bumpy stuff that appears to have three dimensional detail, but doesn’t. If games modeled every little scratch or divit, your video card would burst into flames. This allows fine detail work to look like it’s in 3D without it needing to be in 3D. It can make a huge visual impact on what might be a blah-looking flat surface. Normally (Er, no pun intended), the artist creating the model and textures would either over-model the item in question and take the data from there or, alternately, ‘paint’ a normal map himself, working with light and shadow as opposed to colors. In my case, I had textures, but no high-poly model or inclination to try making a normal map by hand. Enter CrazyBump.
CrazyBump is, in the most scientific and technical terms, magic. CrazyBump takes any texture you throw at it, ask you one question that basicly amounts to “Is this an iny or an outy,” and spits out spectacular looking normal maps seconds later. CrazyBump also refers to itself in the third person and calls the user “Puny humans,” so… Ya know, bonus points there. The free, 30-day trial has thus far saved me an amazing amount of work and my wallet’s gonna cry when it’s over. Which reminds me:
if (gameBudget>0) pimp Amazon shopping link to support GUO Crazy Projects
Properly normal mapped, the BigTomb, as I had taken to calling it, was a good deal more spectacular, but it still needed more.
Using the transparent polygon trick to create fake ‘God rays’ like those over the mana statue, I placed an otherworldly green glow at the entrance to the BigTomb. Still not enough! I added a second, yellow glow inside the green one and tacked on a couple lines of code to slowly rotate it to add a bit of (un?)life. Pretty close, but not quite there. The final piece was a billowing smoke cloud that flowed outward from the entrance. That did it!
The final result was amazing.
Well, ImgFlip.com wasn’t too kind to it, but you get the idea Also note the pillar closest to the camera. This is an excellent example of bump/normal mapping. As a stock texture, the pillar is smooth. After a normal map was applied, you can see the light play off of the seams and warps in the stone without that detail actually existing in the model.
Great! Let’s blow it up!
Every act of creation is first an act of destruction – Pablo Picasso
My first idea was to simply add some additional items around BigTomb to act as both targets and hit points. It didn’t work out very well for a number of reasons. First, it was an unreasonable expectation on the player to knock out targets on each side of the tomb to stop something as critical as an infinite monster spawner. Secondly, it didn’t look very good. Knocking out a low wall next to the building didn’t really feel like destroying it. Finally, I didn’t actually have a destroyed BigTomb model and simply turning off the glow was unsatisfying.
So… Yeah, back to Blender.
Fortunately, the truce between this cantankerous grandpop and the cantankerous 3D modeling program was holding. Barely. I took a few stabs at cutting large chunks of the tomb out for holes, but noticed that you could see through several pieces of the geometry once this was done. Most 3D modelers don’t waste time and processing power on texturing the insides of models. This saves on rendering the “wrong side” of polygons that a player will never see. Rather than attempting to build the inside of the tomb’s walls, an act that would surely anger the Blender Beast and screw up the existing texture mapping of the tomb itself, I contented myself with removing the corner pillars one by one. For the final destroyed model of the tomb, I simply cut out the whole middle and placed the roof on the ground.
It was… acceptable. A hatchet job, to be sure, but enough to keep moving forward. Once back in game, particle systems spewing various sized rocks and dust were added to each of the pillars as they were destroyed creating a lively bit of smoke and debris to cover the ol’ switch-a-roo performed on the tomb model. It wasn’t my favorite batch of effects in the game, but it would do for now.
This is my boomstick! – Ash, Army of Darkness
Balancing turned out to be a bigger issue. As skeletons marched endlessly from the BigTomb, the dance was on to find a happy crossroads of spawn speed vs move speed vs player ability. Too few skeletons and it wasn’t a threat. Too many and the player was overwhelmed. Too slow and they all bunched up for an easy target. Too fast and hitting them, already a tricky proposition in this style of game, became impossible.
I gave some thought to letting skeletons bounce or be stunned by the shield. I didn’t go too far down this road. I just didn’t like the concept very much. Also, I had already, quite unwittingly, created a melee weapon.
See, from the first second you start charging Force Ball, it exists. There’s no trickery there. You’re holding a tiny, baby Force Ball with all the same properties of a normal one (Except for movement, a source of many frustrating early game bugs). I made sure this worked way back in the beginning as a ‘pro move’ where a player can actually use a charging ball to bounce an incoming one rather than canceling the charge to pop the shield back up. Well, as it so happens, Force Balls do more than just bounce. They kill skeletons. Thus, holding a charged Force Ball and running into skely results in a satisfying burst of bones, chainsaw style.
It wasn’t enough, though. Force Ball costs too much mana to be an on-demand weapon. I needed some kind of alt-fire ‘panic button’ when things got hairy. I needed a shotgun. Well, not quite a shotgun. I didn’t want a “Get Out of Jail Free” card. I just needed to give the player a stay of execution. Something like a… wind blast… or Force push. Yeah, that was the answer! A cheap, quick firing spell that would knock back your enemies. Then, after a time, they would get up and…
It had been exactly seven days since my dramatic outburst in the middle Ragdoll Week.
Just when I thought I was out... they pull me back in – Michael Corleone, The Godfather: Part III
Can I have a “Get Out of Jail Free” card? Please?
Well, fine. Hmph. I’ll give it one more shot. But I’m not gonna go nuts this time. And first I’m gonna write the code to cast the spell to warm up.
Let’s see. Casting Repulse Undead. Need a new casting animation. Put that there. Time it out to… 0.4 seconds. Gotta make it an IEnumerator to use WaitForSeconds in C#. That’s still weird. I’ll just reuse the old shield graphic for now ‘cause I am so NOT in the mood to do more art crap. Power down shield function, instantiate spell prefab, flag the animation transition, AddForce… Do I want AddForce or AddRelativeForce? Let me just check the scripting guide and… yeah, AddRelativeForce. Power the shield back up… Lots of red error messages. Let’s see, parsing error… and… Ah, unexpected symbol. Yep, missed a parenthesis. Pfft. Parenthesis around if statements. C# and it’s excessive punctuation… Setup the key binding in Input Manager. Turn off collision for non-enemies and… Okay, that one flew off into space. So… Lock the rigidbody rotations and… There we go!
Wait! That went well. Like, really well. Did I just read and comprehended both the error console AND the scripting reference manual? Without searching the ‘Net? I did! Wholy Carp! I… I’m learning! I just banged out this whole function in record time while only missing one stupid parenthesis and one stupid checkbox! And I called it a function!
I am become game programmer! I’m gonna need more mini-fedoras!
Alright, Ragdoll Script, you’re next.
I dove back into the only enemy to defeat me thus far. I… still couldn’t find where it went wrong. I could see the flow, but the math and nuance was over my head. I shifted some code around. Nothing. Toggled off a few more of skely’s components. Zip-dot-squat. Changed the interaction of the physics layers. No lu- Wait a sec…
The skeleton pushed itself up from the ground and stood upright.
“Up from belly.” I whispered the name of the animation to myself. My eyes were like saucers. I sat starting slack jawed at the screen. It worked! The whole thing. The Force push, the ragdoll, the get back freaking up animation.
I tapped the right mouse button again, not quite expecting it to work a second time. The skeleton flew up and backwards as the Repulse wall hit it. It lay crumpled on the ground for what felt like an eternity. Then… Slowly, deliberately, it planted a bony arm on the ground, bent its knees, and stood up.
“Up from back!” I shouted. The cat bolted from the top of the couch where it was sleeping and darted under a table. I heard the Mrs. grumble and shift in the bedroom down the hall. It was nearly 4AM.
With a triumphant “Woo!” I leapt from my chair and extended my arms to the sky in victory.
A split-second later I brought my arm back down and recoiled in pain. I had stuck one hand into the ceiling fan.