This week I had to deal with kicking in doors and “swapping sectors”. Ever played Resident Evil 4 or 5? Then you know there are two ways to open a door; doing it gently or by force. Pressing the “open” button twice will let you kick or slam a door open. I was in the need of something similar. Normally you would open the doors as a gentlemen. Not just because the game isn’t that rushed, the noise will also attract enemies. But since the movie contains a chase scene, it would look quite stupid when the hero carefully opens a door after running for his life for 60 meters.
Doors in the engine are objects like any other, but with a couple of special features. The model itself could be a door of course, but also any other model. Having Anne Frank's closet as a door is perfectly possible. But on top of that, you define how the door is opened/closed with properties such as “angle closed”, “angle opened”, “position closed”, “position opened”, the squeak and slam sounds, and the speed of operation. Oh yes, and the kind of required access(keys, itemX in inventory) of course.
This allows to make simple rotation / slide animations by interpolating with an “elapsed time” between the opened and closed status. Kicking in a door simply boosts the deltaTime speed, and causes another sound effect plus animation for the player (kick, push, pull, …). Hi-tec Star Trek doors that curl up or something can use animated objects.
Last but not least, when placing a door it figures out at which portal and A* path connection it is. When closing a door, the path and portal will eventually get blocked, preventing enemies trying to take that route or rendering the sectors behind that door.
Police! Please wipe your bottom and get off the toilet with your pants up before we kick in the door!
Second issue, swapping sectors. Say what? Although a few (modern) games have total destruction and chaos abilities, it is still a common technique to replace a piece of map when something happened. Example. You wonder what happens when pushing that button labeled with “Detonator”. Bang. When going back, you notice uncle Buck’s chicken barn is completely gone.
In real life stuff like this only requires some TNT. In games you’ll need to adjust the visual mesh, reevaluate the collision mesh, alter path-finding routes, and eventually regenerate static lighting or reflection information. Which is why replacing a piece of map with a second pre-modeled variant is a common way to fix this little problem.
In my case I didn’t need to blow up barns. Nah, but nightmares tend to spawn complete new locations in all of a sudden. One second you were walking in your house, the next second you are suddenly in a metro station or cornfield. With this technique you could make dynamic “mazes” for example.
You have seen this chamber in a few hundred ways already. But now it's also possible to replace it with a complete different map (also the dimensions can be different).
Replacing a sector had a few difficulties though. As you may have read previous week, the world is one huge map. All sectors connect with each other, which means their absolute positions in 3D are important. Throwing one out can cause some problems. First of all, the world has 1 big global octree that helps you sorting out where you are
(function whereTheHellAmI( vector position ) : sector ).
Second, pathfinding may require a rerouting. Third, lights from neighbour sectors have to rebuild their “visible sectors” listing. Fourth, old info such as collisionMesh and local objects need to get removed / replaced. And last, if there were any global objects / characters inside that sector, they need to get transferred somewhere. There is a realistic chance this happens, since the enemies are free to walk everywhere.
I did it as follow. Both (or even more) sectors are placed at the same position, meaning they can overlap each other. But only one should be activated. By default all sectors are active, but sleeping sectors that pop-up later can be disabled by hand. When replacing:
- “Active flags” from both sectors are switched. Disabled sectors cannot be rendered, loaded or picked when requesting the sector at position XYZ.
- Unload previous sector completely. Just like the background roaming thread would remove sectors that were left behind / too far away. This also removes its physical mesh. Don’t want to stick behind invisible walls.
- For each global object inside the old sector, call a script callback that decides what to do with it. Enemies could get moved to a default location. Stuff like weapons or puzzle objects can get moved to a temporary “vault” sector somewhere outside the world. When loading back the previous sector, a custom script can ask these objects back from the vault.
- Load the new replacement sector
- For each neighbor sector of the old one (trace via its portals); adjust portals and force to reevaluate the lights to make sure the shadow depthMaps are correct. Each portal has a property that tells which sector can be seen behind it. In case this was the old sector, replace it with a reference to the new one.
- Path-finding… The game basically has one huge navigation mesh, also for unloaded sectors. When two sectors overlap, then just also model 2 pieces of nav-mesh at that point. But block all the connections that belong to a disabled sector so that the player cannot use that route.
You can guess the scripting was extended with a few new functions for swapping sectors.
Crikey, that was the detonator button
Sunday, September 26, 2010
Sunday, September 19, 2010
Multi-Headaches
As you may have seen, there are a few links added to the top-right corner on this blog page. Somebody suggested to add some project summaries and well, I think he was right. I was struggling what to tell and what not to tell about the story and gameplay elements, so I tried to outline the game, without spoiling too much. Nevertheless, you can find some details about the game itself that you may not have found between all the weekly yapyap.
There is also a "Movies !" section, without any movies. However, there is a list with remaining points that need to be done. If you ever get impatient, you could check the list to follow the progress. As you can see, I needed to model a fuse box, the end-section of the hallways I made earlier, storing animated sprites, and improving some camera work. When running, the player would actually pass the camera. Since there is this so called "body awareness", I would see my own eyeballs in front of the camera. That may happen when Chewbacca flies with the speed of light in its reversal, but here it occur. Turns out the camera matrix was always 1 cycle behind. Doh.
Then there is also that “Uncle Sam needs you” section in the top right corner. First I planned to finish that movie before asking any help, but since I was writing anyway, I added that too. I’m not in a hurry to assemble a huge team of programmers and artists to make a big commercial game, but one or two artists to help with a second demo movie are surely welcome.
When the first movie is finished, probably somewhere at the end of this year, I’ll have to plot the next targets. Improving ambient lighting, and real enemies with AI are two main goals. But also creating a second demo movie is one of those things to do. See, you are looking mostly at programmer art right now. It isn’t that bad, but it doesn’t really represent my actual ideas for this game either. It can be done a lot better, so the magic wand of an artist is what this project really needs sooner or later. So if you know somebody with talent and too much free time, you could send him or her that link. Who knows.
Anything else to report? Not really. Spend most of the time modeling and fixing(finding) the camera bug. The apartment and spooky corridor sectors are all connected now, so you can walk from A to B without needing teleporters. For the info, the map is divided into small pieces; “sectors”. A hallway or chamber would be a typical example of a sector. Each sector contains portals, the openings(doors, windows, …) that show connected neighbor sectors.
While walking around, the surrounding sectors will be loaded at a certain level of detail. Distant sectors will have a simple mesh and possibly simplified materials without all the fancy shader effects. Close sectors on the other hand are fully loaded with all the details. All the loading and dumping of sectors that were left behind, happens in a background process to prevent the game getting halted by the loading times. In short, pretty much how free roaming games like GTA work.
It did take me a few billion frustrating hours to remove the bugs caused by multithreading madness though. If you have no idea what I’m talking about… If you have a Dual- or Quadcore processor, you basically have 2 or 4 CPU's that can process tasks at the same time. But you'll have to tell your program how. Multi-Threading means you make another separate "thread" that runs a part of the program. For example, thread A does rendering, thread B physics, thread C sound and game logic, and thread D loads the sectors. The OS and CPU internals will cleverly throw tasks towards the processor(s) to make things run parallel. Sounds easy, but it isn't.
Ever worked as a team, or better said, NOT as a team? You bought a can of red paint. Bob didn't know that, so he bought the same can as well. You started to paint that wall, but crippled Joe walks in the way all the time. When you have a break, Jimmy decides to continue your work, but forgets to lacquer the wall first. The boss promised the client that his house will be finished yesterday, but the work isn’t even half done… If you want to work as a team, you'll need to communicate, make appointments and eventually clearly divide the work into separate tasks.
The problem with MT(Multithreading) is that you can't simply read/write variables. If process A reads while B writes on the same value, you'll read something terrible. If both A and B write at the same time, the value is messed up. Bob and Jim can't paint at the same place either, you'll have to pause either A or B. But having lots of pauses is not exactly the idea of MT. Your boss didn't hire 10 men to work in turns either.
In this case, the background thread loads data that is heavily used by the other thread for rendering, collisions, AI stuff, and so on. To prevent the main thread from using half-loaded bullshit, the sector will be loaded in “quarantine” first, then transferred to a "ready list". The other main thread will check this list every time to see if anything new became available. If so, it will be grabbed from the list and placed in another "active list".
- Thread A >>> load item apart from the rest
- Thread A >>> once finished loading, put it in a “ready list” (lock / unlock while inserting)
- Thread B >>> check if there is something in the “ready list” (again, lock / unlock while reading)
- Thread B >>> Ifso, move item to the active list. Delete from the ready list.
Here's where both threads can touch each other. Since the loading thread can insert items into that "ready list" while the other process reads from them. Again, do not do this at the same time. Lock the list with a “mutex’ or “critical section” while one of them either reads or writes. A common mechanism to share values between 2 (or more) threads.
After a long struggle, frustration and many bugs, it worked (for more than a year already). It introduces some extra difficulties like having an changing/unpredictable set of data for AI or special rendering routines. Or being careful about all the garbage(unused textures/models) will get removed 100%, otherwise the memory will flow over sooner or later. All in all, not the easiest way, but having the environment getting loaded without annoying loading times is worth it.
There is also a "Movies !" section, without any movies. However, there is a list with remaining points that need to be done. If you ever get impatient, you could check the list to follow the progress. As you can see, I needed to model a fuse box, the end-section of the hallways I made earlier, storing animated sprites, and improving some camera work. When running, the player would actually pass the camera. Since there is this so called "body awareness", I would see my own eyeballs in front of the camera. That may happen when Chewbacca flies with the speed of light in its reversal, but here it occur. Turns out the camera matrix was always 1 cycle behind. Doh.
Then there is also that “Uncle Sam needs you” section in the top right corner. First I planned to finish that movie before asking any help, but since I was writing anyway, I added that too. I’m not in a hurry to assemble a huge team of programmers and artists to make a big commercial game, but one or two artists to help with a second demo movie are surely welcome.
When the first movie is finished, probably somewhere at the end of this year, I’ll have to plot the next targets. Improving ambient lighting, and real enemies with AI are two main goals. But also creating a second demo movie is one of those things to do. See, you are looking mostly at programmer art right now. It isn’t that bad, but it doesn’t really represent my actual ideas for this game either. It can be done a lot better, so the magic wand of an artist is what this project really needs sooner or later. So if you know somebody with talent and too much free time, you could send him or her that link. Who knows.
Anything else to report? Not really. Spend most of the time modeling and fixing(finding) the camera bug. The apartment and spooky corridor sectors are all connected now, so you can walk from A to B without needing teleporters. For the info, the map is divided into small pieces; “sectors”. A hallway or chamber would be a typical example of a sector. Each sector contains portals, the openings(doors, windows, …) that show connected neighbor sectors.
While walking around, the surrounding sectors will be loaded at a certain level of detail. Distant sectors will have a simple mesh and possibly simplified materials without all the fancy shader effects. Close sectors on the other hand are fully loaded with all the details. All the loading and dumping of sectors that were left behind, happens in a background process to prevent the game getting halted by the loading times. In short, pretty much how free roaming games like GTA work.
It did take me a few billion frustrating hours to remove the bugs caused by multithreading madness though. If you have no idea what I’m talking about… If you have a Dual- or Quadcore processor, you basically have 2 or 4 CPU's that can process tasks at the same time. But you'll have to tell your program how. Multi-Threading means you make another separate "thread" that runs a part of the program. For example, thread A does rendering, thread B physics, thread C sound and game logic, and thread D loads the sectors. The OS and CPU internals will cleverly throw tasks towards the processor(s) to make things run parallel. Sounds easy, but it isn't.
Ever worked as a team, or better said, NOT as a team? You bought a can of red paint. Bob didn't know that, so he bought the same can as well. You started to paint that wall, but crippled Joe walks in the way all the time. When you have a break, Jimmy decides to continue your work, but forgets to lacquer the wall first. The boss promised the client that his house will be finished yesterday, but the work isn’t even half done… If you want to work as a team, you'll need to communicate, make appointments and eventually clearly divide the work into separate tasks.
The problem with MT(Multithreading) is that you can't simply read/write variables. If process A reads while B writes on the same value, you'll read something terrible. If both A and B write at the same time, the value is messed up. Bob and Jim can't paint at the same place either, you'll have to pause either A or B. But having lots of pauses is not exactly the idea of MT. Your boss didn't hire 10 men to work in turns either.
In this case, the background thread loads data that is heavily used by the other thread for rendering, collisions, AI stuff, and so on. To prevent the main thread from using half-loaded bullshit, the sector will be loaded in “quarantine” first, then transferred to a "ready list". The other main thread will check this list every time to see if anything new became available. If so, it will be grabbed from the list and placed in another "active list".
- Thread A >>> load item apart from the rest
- Thread A >>> once finished loading, put it in a “ready list” (lock / unlock while inserting)
- Thread B >>> check if there is something in the “ready list” (again, lock / unlock while reading)
- Thread B >>> Ifso, move item to the active list. Delete from the ready list.
Here's where both threads can touch each other. Since the loading thread can insert items into that "ready list" while the other process reads from them. Again, do not do this at the same time. Lock the list with a “mutex’ or “critical section” while one of them either reads or writes. A common mechanism to share values between 2 (or more) threads.
After a long struggle, frustration and many bugs, it worked (for more than a year already). It introduces some extra difficulties like having an changing/unpredictable set of data for AI or special rendering routines. Or being careful about all the garbage(unused textures/models) will get removed 100%, otherwise the memory will flow over sooner or later. All in all, not the easiest way, but having the environment getting loaded without annoying loading times is worth it.
Monday, September 13, 2010
Controlfreak
Super Mario's 25th anniversary! He's looking kinda old for 25 though... and dirty
Excuses for a later post. I had this little birthday last Saturday (no, not from Mario). With as a result that I couldn’t come any further than the sofa all Sunday, watching cartoons. Talking about sofas, I made one last week, see the screenshots. Other than that, I was busy with light flickering schemes and controls this week.
Light flicker schemes? Sounds more difficult than it is. Maybe Wolfenstein not yet, but Doom 1 already had the option to let a light flicker on a certain interval. You know, buzzing TL bulbs. Lights are a little bit more complicated these days though, but the idea remains the same. Compose a record of "random" values that tell how often, how strong and at which frequency the lighting changes. Continuously buzzing? Slow & steady on/off maybe? Light up with peeks sometimes? For each light, you can choose a schedule (normal, buzz, disco, rotating (sirens), etc) and fill in some random values. Scripts can also change this schedule setting. For example, when shooting a light you can select a schedule where the light flicker/sparks sometimes.
Ok next issue. Controls. I never understood all the fuzz on controls in game reviews. "Superb controls!"... Except with platform games maybe, I always took that for granted. But making your character move smoothly and gently taking the stairs is harder than it seems. Not only the physics, also handling the input on a smooth matter can get tricky when running at lower/fluctuating framerates. Losing control over your character is one of the most frustrating things that can happen in a game. Don’t want H@x0r or FunkySn!per1987 getting fragged in a Deathmatch game because of the sucking controls.
I had to smooth the mouse-look to start with. Certainly because recording that movie requires a smooth camera look as well of course. But it would move a little bit jerky, probably due the lower framerate. So I moved the mouse handling code to another background thread to get updates on a high, fixed interval. Easy right? Well, not really. I tried billion different filters, averaging, acceleration and damping before it would run a little bit. Now it looks like this:
------------- how the hell do you insert code blocks in Blogspot? ------------------
< thread makes about 200 samples per second.
getMousePos( point ); // Windows API call
deltaX += previousMouseX – point.x;
deltaY += previousMouseY – point.y;
if ( ++sampleCount == 2 )
{
rotationX = deltaX * _mouseSensitivty.X + rotationX * _dampingFactor ;
rotationY = deltaY * _mouseSensitivty.Y + rotationY * _dampingFactor ;
playerCamera.applyRotation( rotationX, rotationY );
deltaX = deltaY = 0; // Reset delta
sampleCount = 0;
// Centrate cursor
setMousePos( screenW/2, screenH/2 );
}
// And if you saw errors, yes that could be true as I'm writing Turbo Pascal actually
------------- EndOfCrap ------------------
Still not nice, but at least it improved. Have to make a shooting range for testing the mouse some day.
All right, furthermore a couple of basic moves were still missing. Sprinting and strafing. In most FPS games the player runs a 20 hour marathon at lightspeed. My game is somewhat slow-paced though, so I swapped it for fatguy controls that make you sweat after 20 meters. By default, the player just walks. When holding the shift button, the player starts "jogging". And when quickly tapping the shift, that lazy bastard finally starts to sprint… if the stamina bar didn’t reach zero. Pretty much the same way walking works in Grand Theft Auto games.
I bet your family will throw you and your computer out after banging the shift button for 10 minutes, but don't worry. You only sprint when shit hits the fan. Which shouldn't be too often. While sprinting you can't aim guns or make very sharp turns for example. Plus all the noise will attract enemies. On top, as you get more tired, aiming, vision, hearing and everything else will get distorted. One of the tactics in this game is to keep your heartbeat down. Stay cool dude.
We're still far from done with the controls. Lot's to improve when it comes to physics and stair walking(falling) for example. But that's for another time.
Got my chamber filled with the IKEA Hökebünker set
Sunday, September 5, 2010
Junk needed
Not much spectacular to report this week. Most of the time was used for completing invisible pieces of code. And I still needed to model a few things, including a piece of hallway that connects 2 chambers. Not even sure if I'll have a walk here in the movie, but having open portals that show a skybox behind isn't exactly nice either.
Another boring corridor. Yep, that's the downside of having a flat in mind. Corridors, stairways and apartments. That's pretty much it. Well that would suck of course, I have somewhat more ambitious plans with this flat. I'm hoping to give you a slight impression what that could be with the movie. Though I'm pretty much limited by my architectonic & modeling skills.
Nevertheless, dusty corridors are part of the job whether you like them or not. As simple as they seem, they are pretty hard to make them look nice. The shape doesn't really please the eye, and this particular hall doesn't even have windows. So you'll have to impress with other things. But what? Doorbells? Textures also repeat a lot here, and even doing lighting is difficult. Narrow spaces like hallways should have lot's of indirect bounces to spread the (ambient) light throughout the space, but as you may know, indirect lighting is damn difficult. The engine actually updates a lightmap for indirect light realtime, but its resolution is too low to have good results.
Corridor... boring. Need some lightshafts, better smoothing, more decals, junk on the floor. And probably a very different texture setup as well.
The answer is probably to add lot's of details, at the right places. Randomly throwing boxes won’t work either, the mess needs to make sense. Install switches, cables, pipes, fans, stuff like that. Paper and bubblegum on the floors, maybe a vacuum cleaner somewhere in the hall. If you need examples, iD Software are masters in making (eerie) corridor games like Doom3 or Quake4.
Another trick are decals. To break the repeating wall textures, paste dust, rust, blood, puke, poop, goop or cracks on top. Too bad my library doesn’t have much junk-objects and decals yet, so the hall looks awfully empty. But I played around with “torn-off plaster”, inspired by the picture below:
That's how every hallway should look like
Beautiful, isn't it? I mean the peeled wall. Ow, by the way, this screenshot is made by an artist that shows how Halflife2 *could* have looked with modern techniques. Well dammit, hurry on with that third expansion then. And start building Halflife3 already, I've seen enough Combine, Alyx and City17.
So that wall... There are 2 common tricks to achieve such an effect. A: Draw a flat texture/decal on top. B: Make an actual model of it. Option B is too difficult for me, and probably not worth all the polygons. Option A would work 5 years ago, but players are not stupid either. They'll notice it's flat. I'm not sure how the wall is made in this screenshot, but it doesn't look really flat, does it? Yet, if you check the wireframe from the same scene, you won't find curvy wallpaper polygons. Some sort of advanced decal with depth illusion then?
Whatever it is, my game will have quite many boring hallways, so I'd better think of something to make them somewhat more appealing. Regular decals look too flat, especially if they are relative big. So I came up with a somewhat more advanced decal shader, but still as flat as Will Smith's high-top-fade haircut in Prince of Bell Air. I think it's a little bit similar how F.E.A.R made it's bullet holes:
- 1 texture contains the "wall behind" part. Bricks or something. It includes an alpha channel to mask it. Transparent parts just pick the original background. Same like regular decals.
- 1 texture contains a normalMap. Not only for the brick part, also to override the surrounding wallpaper or plasterwork pixels to make it bumpy. That means different masking for the normalMap part of the decal. I'm using a deferred renderer, so overwriting pixel characteristics before the lighting happens goes pretty easy.
- For some additional depth, the normalMap contains height in it's channel for some slight parallax mapping.
- Shadows caused by the foreground are still drawn onto the brick layer. Not computed realtime. Keep them slim so you won't notice. You could however do self-shadowing with a more advanced parallax technique (marching through pixels).
It still sucks compared to the Halflife next-gen screenshot, but that’s probably due my drawing skills. Especially making that crumbled-paper normalMap. Stuff like this really requires an artist. As for the shader, maybe it can be done better with a more advanced parallax technique. I was thinking about making a displacement in the vertex-shader for a moment (like doing a terrain with a heightMap), but couldn’t figure out how to correctly pick the background pixels then. Next time Gadget, maybe.
Another boring corridor. Yep, that's the downside of having a flat in mind. Corridors, stairways and apartments. That's pretty much it. Well that would suck of course, I have somewhat more ambitious plans with this flat. I'm hoping to give you a slight impression what that could be with the movie. Though I'm pretty much limited by my architectonic & modeling skills.
Nevertheless, dusty corridors are part of the job whether you like them or not. As simple as they seem, they are pretty hard to make them look nice. The shape doesn't really please the eye, and this particular hall doesn't even have windows. So you'll have to impress with other things. But what? Doorbells? Textures also repeat a lot here, and even doing lighting is difficult. Narrow spaces like hallways should have lot's of indirect bounces to spread the (ambient) light throughout the space, but as you may know, indirect lighting is damn difficult. The engine actually updates a lightmap for indirect light realtime, but its resolution is too low to have good results.
Corridor... boring. Need some lightshafts, better smoothing, more decals, junk on the floor. And probably a very different texture setup as well.
The answer is probably to add lot's of details, at the right places. Randomly throwing boxes won’t work either, the mess needs to make sense. Install switches, cables, pipes, fans, stuff like that. Paper and bubblegum on the floors, maybe a vacuum cleaner somewhere in the hall. If you need examples, iD Software are masters in making (eerie) corridor games like Doom3 or Quake4.
Another trick are decals. To break the repeating wall textures, paste dust, rust, blood, puke, poop, goop or cracks on top. Too bad my library doesn’t have much junk-objects and decals yet, so the hall looks awfully empty. But I played around with “torn-off plaster”, inspired by the picture below:
That's how every hallway should look like
Beautiful, isn't it? I mean the peeled wall. Ow, by the way, this screenshot is made by an artist that shows how Halflife2 *could* have looked with modern techniques. Well dammit, hurry on with that third expansion then. And start building Halflife3 already, I've seen enough Combine, Alyx and City17.
So that wall... There are 2 common tricks to achieve such an effect. A: Draw a flat texture/decal on top. B: Make an actual model of it. Option B is too difficult for me, and probably not worth all the polygons. Option A would work 5 years ago, but players are not stupid either. They'll notice it's flat. I'm not sure how the wall is made in this screenshot, but it doesn't look really flat, does it? Yet, if you check the wireframe from the same scene, you won't find curvy wallpaper polygons. Some sort of advanced decal with depth illusion then?
Whatever it is, my game will have quite many boring hallways, so I'd better think of something to make them somewhat more appealing. Regular decals look too flat, especially if they are relative big. So I came up with a somewhat more advanced decal shader, but still as flat as Will Smith's high-top-fade haircut in Prince of Bell Air. I think it's a little bit similar how F.E.A.R made it's bullet holes:
- 1 texture contains the "wall behind" part. Bricks or something. It includes an alpha channel to mask it. Transparent parts just pick the original background. Same like regular decals.
- 1 texture contains a normalMap. Not only for the brick part, also to override the surrounding wallpaper or plasterwork pixels to make it bumpy. That means different masking for the normalMap part of the decal. I'm using a deferred renderer, so overwriting pixel characteristics before the lighting happens goes pretty easy.
- For some additional depth, the normalMap contains height in it's channel for some slight parallax mapping.
- Shadows caused by the foreground are still drawn onto the brick layer. Not computed realtime. Keep them slim so you won't notice. You could however do self-shadowing with a more advanced parallax technique (marching through pixels).
It still sucks compared to the Halflife next-gen screenshot, but that’s probably due my drawing skills. Especially making that crumbled-paper normalMap. Stuff like this really requires an artist. As for the shader, maybe it can be done better with a more advanced parallax technique. I was thinking about making a displacement in the vertex-shader for a moment (like doing a terrain with a heightMap), but couldn’t figure out how to correctly pick the background pixels then. Next time Gadget, maybe.
Subscribe to:
Posts (Atom)