Sunday, April 24, 2016

Walk the line

Most programming-time on this project, disappears into improving graphics, making the editor a better man, or fixing bugs. Although engines, programming techniques and strategies get better and more robust every time you try, stuff still feels like a Jenga brick tower sometimes. Shove a new shader in here, and crap falls out at the other side - without you noticing until a week later, then wondering what the hell happened.

But I shouldn't forget, that we're making a game here. Or trying to at least. Making something you and me can *play*. So, once in a while, I step away from graphics and dive into game mechanics. A whole different area, I must say. Whatever game you're planning, the fun part is probably making your foes even smarter, designing puzzles, tweaking guns, testing what happens if you drive that race-car into garbage cans, et cetera. But... you're too far ahead maybe. Because a game begins with decent controls & basic physics.


Sure thing doc. But you know what? Making them Right, is pretty damn hard! Even if you have a proper physics library. Certainly because game-control-mechanics often have to cheat, overruling standard physics, collision and gravity rules, rather than using them. Getting a box tumbling down the stairs isn’t too hard. But getting a 200 pound guy moving upstairs is. It will bump, get stuck, rocket-jump into the sky, or more likely; stick on the ground like an Easter Island head.




Shoe laces thight
I take good controls for granted, 99% of the games have them right more or less, nowadays. Though the foul memoires of broken games haven’t faded completely. How many platform games fucked up, 30 years ago? Games didn't have too many problems stealing the ideas and visuals of Mario Bros. But copying the controls and mechanics was a whole different league. The player character being too fast, as if feeding an ADHD kid 200 red M&M's, six cola, and a line of speed before going to mcDonalds. Controls too slippery, as if ice-skating on olive oil the whole time. Too stiff, as if moving a 1 ton statue with the friction of a Thwomp. Too artificial, as if moving a rectangular sprite in horizontal or vertical patterns over the screen. Too sluggish, as in having a jump-button, but Arnold Schwarzenegger being too old to jump over a 30 cm obstacle, making it useless. Too unrealistic, as in total absence of any physical rules. Too realistic, as in having no control at all once you're airborne, realising you miscalculated the jump and heading into the abyss imminent.

Many old platform games failed miserably, because of unbalanced controls, or a level-design with impossible jumps. Or both. And not to mention the weird bugs. One thing I hated, was sprite-physics-anorexia. What I mean is that, even though the player sprite is 1 meter wide, its collision hull (an invisible shape used to test if it hits another shape) seems to be much thinner. Your feet would land on the edge of a platform, yet you would still fall down because the hitbox of your player missed the jump. It sucked, it seemed relative easy to fix, yet dozens of games screwed up. Also the opposite happened. A bumblebee would fly one feet over your head, yet still kill the player instantly because its oversized hitbox caught it.
               
Why L ?!! Well, I can tell you why. Again, because making physics is hard-core stuff, even for a platform game. I can tell, because I had the same weird shit in my 2D-hobby-games, where players would end up in the middle of the wall, raising upwards, straight out of the television. Detecting a "hit" isn't too bad (in 2D), but deciding what to do next, and making a 100% waterproof system is. Velocities, bouncing off, material frictions, taking the angles into account properly, and a big dose of magic numbers. 
Having a built-in jump-tester in the level editors would have saved dozens of broken joysticks and frustrated crying kids. But probably a lot of those shitty games didn't even have visual editors back then.


3D Crapdoll physics
The big transfer to 3D didn't really help either. Although a game like -of course- Mario 64 did remarkably well for one of the first serious 3D platform games with advanced moves, I couldn't count the number of awkward stunts on a hundred hands. Soldiers would drop through the deck of a moving boat, sink like a brick to the ocean bottom, then warp high into the sky to fall down to their deaths eventually (yes, I'm talking about Hidden & Dangerous here). Ragdolls would start spinning up to hyper speed, tearing their limbs apart, because they got hit by a closing door. Dead guys float in the air until I touch them with a fingertip, as they finally drop peacefully straight down (Fallout 4 + plenty of other modern games). Wrecked cars being launched to the moon after hitting that wall at the G-spot (GTA). Getting your head stuck through a wall, horrible clunky vehicle steering, flying in Limbo, …

Should I go on? Yeah, why not.  Giant dinosaurs worming through a 2 meter radius cave portal. Player not being able to proceed because required object used as a step-up fell through
the floor. Tough action hero’s that would drown instantly once being in 40 centimetres deep water. Cannot reach key of dead guard as his ass lays half inside a concrete wall. Being able to disable gravity and collisions by taking a wrong step somewhere in the corner of a map. Not able to get off the sofa after jumping on it because the ceiling is too low (Tower22). The list is endless, and if you look on Youtube, you quickly waste another few hours on watching this kind of stuff. Sometimes it works out well, like the Quake1 Rocket-jump ability, or having fun with flying cars in GTA. But most of the time it’s just, well... stupid.


That looks... painful. I think.

And at this point, T22 is still tormented with the same kind of bugs as well. But not the funny type of glitches. More the types where you want to smack the keyboard through a door, and decide to become a garbage man instead of a game-programmer for the rest of your life.  As you may know, Engine22/Tower22 uses "Newton" (not the guy, the code library) physics as a base layer. I'm not too sure about recent trends -to me it seems physics engines are a bit out of development last years-, but it’s free, and Newton was said to be quite accurate. Accurate my ass, when that stupid ball falls right through the floor again. Probably my fault somehow, though I often really can't explain the quirks. It works, works, works, then it suddenly goes wrong.




Role of a physics engine
Tower22 won't be a Prince of Persia game where you can climb walls upside down, take long jumps, or have to balance on ropes while riding the back of a tiger. But for starters, it would be nice if you can just walk in a straight line, rather than a drunk hobo who gets stuck behind doorsill.

Problem with game-physics, is that it's sort of a hack. Like with graphics, we'd like to found our physics on, well, real physics laws instead of (much simpler) programming abracadabra. Which is a good thing, but also complicates the situation at the same time. Rotating and moving an object forward with pure vector math is easy peasy. But the physics engine won't agree to do so, as your (player)object has friction with the floor, wants to spin like a vertical rolling-pin while sliding along a wall, get stuck in narrow passages, bounces you back when hitting an object, et cetera. Which is terribly annoying, because you're the MAN with the Controls. IF I say LEFT, go LEFT dammit.

But, if physics engines are so realistic... what exactly is the problem then? I mean, unless being on ice or having an epileptic seizure, you're in control. You stop when you want to stop, you can manoeuvre through a crowd without bouncing in the air, you can climb stairs and do a handstand while taking a piss, drunk. So again, the realistic physics engine can manage that for you as well, right?

No, it doesn't. Physics engines typically do 4 or 5 things:
  • Collision detection between primitives (spheres, cubes, cylinders,..), convex-hulls, and triangles (the world). Highly optimized, because doing this requires horsepower.
  • Collision response (friction between 2 surfaces, bouncing off, E=MC^2, ...)
  • Joint physics (ball & chain, hinge door, but also a ragdoll is basically a string puppet made of lots of primitives and joints)
  • Apply forces on bodies (gravity, spin, torque, movement, custom forces)
  • Special types like Fluids, Buoyancy or Cloth physics

Which covers a big important deal, but not everything. Player-physics for example are a black-art. Humans aren't boxes or capsules flying into all directions when you hit them. Or well, if a cement truck hits... Yet physics engines treat us just like that. Because *REAL* physics would be way too complex.

Obviously walking in real life isn't a matter of pushing us human-shapes forward. It's more a controlled form of tumbling forward, step by step. Push up, tilt forward, fall on the other foot. And repeat. No miracle it takes a baby some time to practice on his two legs (though I sometimes whish our youngest son never had legs, now that he learned how to climb onto practical everything). It's so difficult that God or Evolution gave most animals 4 or more legs, for Pete's sake. It's so difficult that hordes of scientists spend billions of dollars and hours into making robots that can do nothing but climbing stairs.

So having true human movement kinematics into games... better not. Even if it was available, it would probably beat the hell out the CPU. And then we have an alien character with 3 legs, or a crippled guy that walks on his hands... Got to start all over again. Just no. What we do have, is
either old fashioned homebrew fake-physics that are guaranteed to generate amazing stunts, or use the tools we get from a physics engine. Usually we do a hybrid; special rules for players, yet using an existing physics engine so it integrates with the other stuff in the game. Meaning it will bounce away a box if it was in your way, and meaning you can benefit from the same optimized collision detection systems.
Even the ED-209 hates stairs.

Jalapeno on a stick
Until recently, the Tower22 player was really just a capsule. On a stick. The tiny stick (cube) did some special stair stuff, and the somewhat wider capsule does the collision detection with other objects and of course the environment. Fortunately you can't see it (physic collision hulls are always invisible, the 3D mesh does not represent the actual physics shape), but man, it's a ridiculous model. Imagine everyone on street would look like Jalapeno on a stick, sliding forward by some invisible force. Because that is what happens, we push that thing forward, and use an up-constraint to prevent it from tumbling over. Like an invisible rope in the air that keeps us up.

Biggest problem is the sliding / pushing forward thing. What happens if you push a 80 kilogram washing-machine-box forward? Probably nothing, because it's fucking heavy. If you smear green soap on the floor, it may work though. So let's say we have green soap all over the place. Yeah, we're sliding now! Smooth as air-hockey! But crap, there is a little stump on the floor. Even though its 1 cm tall, it’s enough to block. Push harder, and the box tumbles, you landing on top. This is why a capsule-shape may work better, thanks to the rounding at the bottom, it has minimal contact with the ground, and it can lift up itself gradually. Over small obstacles at least. A 35 cm stair-step is either impossible, or requires an incredible amount of force. Increasing force is easy enough in a computer simulation, but hold your horses! Don't forget we also need to stop almost immediately when we release the forward button.

Oh dear, stairs. In the past that would mean you had to take 10 steps back, then charge like a raging bull, hoping your momentum would be enough to bring you upstairs.

Controlling the player like this, feels like manoeuvring the Bismarck. There is no direct control over it, you're at the mercy of physics. Which is exactly NOT what you want. I don't know how people do it in other physics engines, but Newton offers a bunch of "overrides", sort of. Rather than rocket-fueling force into the rear of my player, I can set its velocity. Sort of a PID-control will monitor the velocity and eventually correct it every cycle, in case it drifts off. Same stuff for controlling the spin force. If I say the player should be rotated 270 degrees, he'd better listen. The rotation is measured and guarded every cycle, meaning a correction spin will be applied as soon as the physics engine thinks otherwise (for example, when the player hits or gets hit by something). It works, but be careful that in some situation, you actually want the environment to have effect on our player. Well. Magical rules, overrides, different states... code quickly gets dirty for sure.
                               

Scanning, Scanning, Error.
I didn't mention the stairs yet. The horror. As I tried to explain, we basically just push stuff forwards. But that's not how a human being climbs stairs! Lift a leg, place it one step higher, pull up. Well, we can't really simulate that with a stupid capsule on a stick. But we have some more David Copperfield magic up on our sleeves. If we can set forward-velocity, we can also set upward velocity. Obstacle in front of us? Add some "lift". Problem solved? Of course not.

How do hell do you know if there is an obstacle in front of you? And then I mean an obstacle you can pass, not a wall. Otherwise you would slowly lift yourself over the Chinese Wall, that's not how it should work. The player should scan its surroundings. For example, fire a ray forward from your toes, to see if there is something in front. If so, this *might* indicate a stair. But before rocketing up, do a second scan at balls-height. Still an obstacle? Then you can't simply step over it. You may need to leap over, if that's allowed in your game. But just sending some rays forward (like I did earlier) is prone to fail. Take a look at this picture:

That's a classy stair right? "Thanks" to its open gaps, my toe-sensors don't sense shit. So, no obstacle, no lifting. In other words, we're stuck. But wait a minute, there a are a billion other scenario's that can fool you. What if we were to climb to stairs while strafing or walking reverse? Toe-sensors have to measure into another direction, or it still fails. And what if we see the stairstep, but miss a metal pipe in front of our head? Head-bang. The most annoying are tiny obstacles (less than a CM tall), like rubble. Your sensor-rays may fly over them, but they are enough to stop or at least slow you down.

Scanning is one way to make decisions, but do not rely on a few rays only. Fortunately Newton provides convex-raycasting (like sending out a thicker volume, rather than a thin ray) which already does a better job, as it less likely slips through narrow holes or gaps. But a very different approach, is to simply flatten the stairs. And I'm quite sure older games did that a lot, and maybe even modern games still do so. In fact, due polygon limitations, old games actually had diagonal ramps rather than real block-shaped stairs. Yet, it feels a bit fake, as the player doesn't "hop up". Also the animation should change; you climb a stair, not run it. Idiot.

Looks like stairseps right? But look again, carefully at the edges. It's just a flat ramped polygon with a stairstep texture on it.

A third thing you can do, is making hints, or a context. And this sounds pretty logical. You could mark every "shape" as "floor", "wall", "ramp" or "stair". You decide what can be climbed, and what not. This at least avoids an automated scan to make mistakes, trying to climb stuff that shouldn't be. It also allows to make the player aware of more advanced manoeuvres on its path. Like "ladder", "rope" or "passable for AI only". Giving hints for players and NPC's. You would still have to scan forward, and as said, the level designer shouldn't forget to mark everything properly.

Yet at the same time, it feels as if this shouldn't be necessary. Can't remember having to do this for every possible obstacle in the Duke Nukem or Half life level editors. Also games with dynamic environments that can be altered by building or destructing stuff, probably don't have to mark everything. Obviously it would be nicer if the player-physics can figure out what to without hints.



So. How DID we do it?

As usual, I’m very good at showing a hundred and one failure situations. But more interesting, where is the cure? Well, I wasn’t exactly Newton’s best student back at school. Then again, as said, player physics is more about hacks anyway. In fact, the code is so… if there were Burqa’s for programming-code, this piece should definitely wear one. It’s the type of stuff you’re ashamed of. It’s not founded on rock-solid, robust, proven methods. But on numbers, case specific approaches, and cheap tricks. It feels as if it can collapse any moment. But reading Google, it seems this “Black Magic Code” just happens to be the norm. Okay… If you say so.


  • Skinny Capsule

So, first of all, I replaced “Jalapeno on a stick” with Jalapeno only; a Capsule. A relative thin capsule I must add, otherwise you’ll find your ass getting stuck in door portals. No Kim Kardashian collision hulls. This capsule has low friction and bounce settings. Basically we want as little contact with the environment as possible.


  • PID Controlled Velocity
As explained earlier, rather than just adding force into our desired direction, we measure the actual velocity (and spin), and add more or less if needed. This gives a more stabile speed, at surfaces with different friction settings.


  • Hover Shoes

Even though our capsule makes relative little contact, I still found myself getting stuck behind 5 millimetre floor height differences. A doorsill would be enough to keep me outside the room. Like Garlic hanging in front of Dracula’s nose, it just stopped moving. The solution? Sci-Fi hover shoes. I constantly apply upward force (or vice-versa, you could disable gravity while standing on the ground). Just a bit, to lift me off a few millimetres. Be careful not to add too much, or you will “wobble” like a flying space scooter.


  • Convex Cast ahead

No toe sensors, but we do a downward convex cast slightly ahead into our desired direction. I'm using a flat disc for this. Now we can compare our feet level with the obstacle height at the next step. If the difference is less than a defined “MAX_STEPHEIGHT”, we can engage our shoe thrusters further, giving upward velocity. Notice we can also do an upward scan. This is useful to signal NPC’s to start crouching, in case of an obstacle at head-height.

  • Downforce

We talked a lot about climbing stairs. But how about getting down, without flying through the air? By default, only gravity will pull you down. So you don’t really step down, you just fall. If you run fast enough, you won’t be touching the stair-steps at all, losing control while being airborne. What I did, is reversing my shoe thrusters to “press” you down rapidly. But only if the height difference isn’t too big. As shown in #4, the down-cast will get below the player feet. If less than “MAX_STEPHEIGHT”, downforce will be applied. In essence, it quickens the fall. Be careful not to apply downforce BEFORE you’re over the ledge, otherwise you get pinned to the ground just before taking a step down.
  • Baywatch

Just keep in mind you may walk through a wall, or fall through the floor for whatever reason. So you'd better have a lifeguard. Make a respawn point, or use some hard boundaries to prevent falling through. If the lowest point in a room is -2,5. then just disable gravity or even push up whenever the player threatens to get below that point. Yes, it's stupid and it shouldn't be necessary. But better safe than sorry.



Does this provide waterproof, fine controls? No, but at least it''s a step into the right direction. And moreover, I just wanted to give you an idea of things *can* be done. I still find myself in odd situations, like getting stuck in corners that are complex geometry-wise. Or flying up onto a steep ramped wall that shouldn't be climbed really. And for some reason I keep falling through that damn floor for no apparent reason. But at least its a lot better already.



No comments:

Post a Comment