perjantai 11. joulukuuta 2009

T+x

As I said in the very first posting, I wasn't going to make this blog a burden for myself. This is the reason I did not write anything when the deadlines started to approach. The two games were part of a bigger project: getting me graduated before xmas. The sheer amount of work writing all the reports and finishing the loose ends felt pretty masocistic at times, but I'm now very happy that I finally reached my goal.

I think I might just stick with this blog btw. The name "Keely 440" has kind of funny vibe. I know there won't be too many readers, but I write for myself mostly so it doesn't matter. I have no idea that I'm going to write about, but I guess I'll just write whatever feels interesting, whether it's gamedev-related or not. Now I feel like writing a few passages of post-mortem about school, so here goes:

I never had great ambitions for education or consider graduating some kind of larger-than-life event. At some point earlier in life, I actually made peace with myself on the subject: If I'd graduate, great. If not, no biggie. Six years ago, I applied to our school, because that was something "everyone does" or something that "you are supposed to do". I don't regret the decision. I made it based on what I felt was right at the time. If I could rewind back time, and be myself six years ago, with the self awereness I have now, I would skip the ordinary education and teach myself. I think by now, I'm an expert - when compared to our school organization - on how, what and why I need to learn. I also think that - albeit trying to foresee the future is kind of retarded - the working culture is shifting more away from the formal education and the degree I now have probably makes a near zero impact on my career or life in general.

School had a positive impact too. I met alot of interesting people and new friends along the way. I'm still in touch with many of the guys we started the school with (even though they graduated 3 years before me). Also, now in the final months, I suddenly had like dozen new gamedeving pals through the Gamelab @ school, when earlier I had none. There was big chunks of "free time" in school to think about what I want to do or what is it that makes me tick. All great stuff.

But, for a critical thinker that I am, these are all pretty much false arguments. It's pretty hard to predict what kind of people would I have met or what kind of positive situations might have risen, if I had skipped the school all together. No way of arguing one way or the other. It is called results-oriented thinking, and narration of random events into what seems like solid arguments. This kind of phenomena is very common in a very complicated modern society, where people like politicians, businessmen and other decision-makers, have to cover their ego from the fact that there is actually very little that they know or can do in terms of making the right choice, because there is no such thing as right choice to begin with.

We are all children of the primitive men of the savannas. Results-oriented thinking makes sense, when you avoid getting killed by lions or try to hunt for rabbits. It doesn't make sense in the complex society of 21st century. There is just no way to measure a value of a hard decision, like going or not going to school, before or after, with the way you measure a simple decision like "should I hide from this lion to tree or run for the caves". Back then, you got an instant and accurate feedback. Fast forward a few million years of evolution and BOOM, here we are: Children of these primal men, now in a totally different new world of information and complex structures, crippled by our past.

Of course there is randomness in the lion example too. You could find your mates in the way to the caves, who make the lion back away. Or maybe all the trees nearby could be too hard to climb. But when you compare this to the randomness of the modern world, you might understand where I'm getting at: We are trapped by our primitive genes and protect ourselves and our precious egos from the fact that many of the big decisions we make, are just a diceroll with a tiny fraction of determinism. It is hard for a human being to let go of the idea, that you could control your destiny. I'm not even sure that anything positive follows from my realization, that there is very little I can do, or atleast no proof to think otherwise. Sometimes I think that I'd actually rather be the ignorant young fool that I used to be, but I can't help being the critical thinker that I am now.

Wisdom brings pain, but I hope some more joy also. Maybe the ultimate conclusion that you can derive from this, is that not everything in life is random, and you can still try to make good decisions. It's just that you should not get too stuck with the negative results of your hard decisions when they (eventually) arise. When you can indentify the sheer amount of "dicerolling" taking part in the course of your life, you might become more relaxed to face the hardest of decisions and the worst of results, and still be able to enjoy the ride.

Now I'm going to make some nice cup of coffee and just watch my dogs play outside. I've earned it.

torstai 3. joulukuuta 2009

T+305

We were required to write a short documentation on the project to pass the course, so I went on to write one for the Tanksalot. I'll just copy-paste most of it here, because I think it'll make a nice blog entry on it's own.

---

PREFACE


Introduction to Game Development Tools was a joint course of University of Turku, University of Applied Sciences of Turku and Digital Arts, Turku. It was a course which emphasis on practical work. The requirement of the course was to create a (small) computer game. One could use any tools creating the game, but the lectures and examples were first concentrated around the Panda3D-engine and later on around Unity3D-engine.


LANGUAGE


I had some game-related code sitting on my PC in Java already, so we decided to be rebels and do our game with Java and OpenGL. To be honest, I (Juha) decided it, and the rest of the group did not object (out loud anyways). Later on, I was worried that I might have ruined the course from the others, by dominating the selection of the language. However I discovered that Tomi and Joose, aside from doing modeling, audio and graphics for the main game, ended up doing some moonlight experimenting on their own with Panda3D and Unity3D. I think it all ended up nicely and everyone got what they wanted.

TOOLS


The models of the game (mainly the tank) were done with Blender, and then we used Newtek’s Lightwave as a pass-through solution to save our model in the correct .obj –format, so that my existing parser could understand it. There was no need to do yet another parser for yet another new format. Miro used to Adobe Photoshop CS3 to create our 2D graphics. Audio placeholders were recorded with Adobe Soundbooth, but we eventually replaced them with free audio effects from various internet sites which we fine tuned in Cubase. We used Eclipse as an IDE for programming .


ENGINE


As mentioned earlier, we used some of my already made Java-code for the basis of the project. It is not a game-engine, but rather a large codebase to draw features from. All of the code is built on top of the Java Lightweight Game Library (LWJGL), which is very low-level wrapper to interfaces such as OpenGL, OpenAL and DirectPlay. To create our nice looking graphical outlook, we also used custom GLSL-shaders, which employed a standard commonly reffered as the “shader model 3.0”. It narrows down the display adapters that can run the game, but 3.0 is a common choice for a minimum requirement for a new game in late 2009, and it is hard to do good looking post-processing effects (like Bloom) or celshading with older shader models like 1.0 and 2.0. For the physics side of things, we plugged Bullet Physics -middleware to do the work for us. Actually we used the JBullet, which is Java porting of the original library. Bullet Physics is a new open-source physics middleware, which is supposedly also used in multiple AAA-games. It has native support for raycasting vehicle, which made our tank driving model with 6 wheels very easy to create.


GAME


In the first meeting, we had two options. A game where you could control a ball in a maze with physics. The second was a top-down tank duel. The war mongers that we are, we wen’t for the shooting. At the end, it wasn’t a top-down game, but a split-screen 3d battle. The original IP also had some kind of maze or walls in it, but later we decided to make the game arena sort of a round desert. Main reason for this was the quick deadline we had to commit to, because of graduating timeline that some of the group members had setup for December, and there was no time to make the objects work and look good in our game.


When the game starts, players are dropped in the corners of the arena. There is a little hole in a place where they start, so that they can’t see each other just yet. Each player is given 3 ammunitions (out of 5 max), and full health. These are clearly visible on the HUD. Powerups (health and ammo) are dropping at a constant pace out from the sky. They are wooden boxes that slowly float down with parachute on top. The idea of the game is simple: kill or get killed. The round ends if one of the players drop health down to zero and the winner is given a point.


TERRAIN


The terrain is not totally flat, and it is 100% procedural. There is a heightmap generated at load-time, with diamond-square algorithm. We also made the algorithm to raise from the edges in circular matter, so that the form of the round arena is generated. We also made a small foxhole in two spots where the players start. From this heightmap, the polygons of the terrain are created in a obvious and straightforward zigzag. Bullet Physics has a support for heightmap-collision shape (which is actually converts to a normal trimesh), which suited us well, since we already had a heightmap lying around in our code.


The terrain is rendered with a special shader. This custom shader was needed, to get the lights of the missiles to make a brighter areas where the missile was close. We used OpenGL standard light-structure to pass the light positions (maximum of 8 simultaniously) to our shader, which then calculated a sum of the missile light intensities for each vertex real-time. This value was then added to a per-vertex sunlight value, which we precalculated from the normal vectors during the pre-calc.


CELSHADING


Our celshading approach was the one you could call “the easy way”. It doesn’t use post-processing pipeline or complicated depth-buffer magic. We simply scale up each of our models slightly (with OpenGL glScale) and render all the back-culling faces in outline color (which is usually black). Then on top of this black shape, we render the object with normal shading and normal scaling. Since the size of the black rendering is slightly bigger, this creates a black outline around the object. This is a neat and fast trick, but it has some artifacts when the shape of the object is not very round and conformed. You can see the problem for example in the tip of the cannon of the tanks, where the outlining is not what you would expect from a cartoon artist. The other part of the vanilla celshading is the polarization of light. This means that we do not draw smooth transitions of light, but rather a more binary on/off kind of shadow. This is done at the end of the light calculations of the pixel shader, with a simple if/then-structure. You could also use some 1D-texture to “wrap around” the linear gradient that your Phong, Gouraund or whatever-light-algorithm produces, but we decided to do it in the dirty hard-coded way.


AUDIO


There is an inherent problem with a split-screen game IP and OpenAL 3D-sound interface. OpenAL paradigm is based on the assumption, that there is only one listener object in the scene, with a singular position coordinates. This makes sense for the 99% of the games. You render your view of the world from one camera at the time, and can assume that the sounds of the game can be rendered based on what is heard in that position. In a split-screen game however, this is not the case. You have two equally important listeners and cameras, and can’t represent 3D audio with this single listener paradigm. So we had to make a workaround for this. We made a parallel fony world only for our audio. In this world we put the listener object in the origo. Then we put two audio source objects on fixed positions at front-left and front-right. This represents a two-speaker system with a listener in the middle. Then if a missile (sound source) in a game created sound, we would manually measure which player it was closest to, and then played back the sample accordingly in our parallel audio space. We could not use the great 3D-features like the Doppler effect, but this didn’t hurt too much.


SCREENSHOTS


Finally some in-development screenshots of the game to illustrate the development cycle of the visuals.





tiistai 1. joulukuuta 2009

T+272

I think there was a bug in my 440h takeoff calculator. I "dirtyfixed" it now in the headline of this entry, and I have now exactly 7 days (168h) to go. I'm writing this entry after some extreme coding strech. I think I woke up at 12pm yesterday and went straight to my PC. I did some coding and then headed for my dayjob at 3pm. There I coded some more and left around 8-9pm, just to eat a quick pizza and do some MORE CODING back home. As I'm writing this, it is now 8-9am the next day, and I'm still pushing it. So far that's 20 hours of straight coding, which would normally make me into a passive-aggressive zombie, but I'm feeling suprisingly zen-like now. It must be those D-vitamin supplements I've been eating a few weeks now.

My projects have gone forward and I'm more pleased than I was when I wrote the last post. I have finished Tanksalot now, and all I need to do is write some light documentation about it, and it's wrapped. I think it still would not work on those 64-bit win7 machines @ school, but I'm not going to spend my energy on that. I have more important nuts to crack at the moment. The toughest being the networking in the Quickrally.


Last post included a video with four players on LAN with the very first multiplayer demo I managed to pull together. It worked well, but there was still some stuff and inconsistensies when the cars collided with each other. I also used too heavy frequency of updates because I knew that we would be testing in LAN and I didn't want to tinker with all the details just yet. Now I'm happy to say that in these past few days, I was able to get the whole thing much more robust. It's pretty smooth and consistent at the clientside, even if I send something like 5 packets per second from server to clients. If I'd throw in 20+ players now, I think the scalability in the networking-side of things should be playable. I'd be more worried about physics calculations with 20+ raycasting vehicles. Of course the networking could still potentially explode with 5 players. Testing multiplayer stuff locally with one PC and NIC loopbacks is just not going to make me feel like 100% confident, but I'm feeling about 96% right now.


The new IP


My friend showed me this youtube clip of some PS2 "partygame" they were supposedly playing the night before. I forgot what was the name of the game, and can't find it anymore, but I will post it later when I do. It was a multiplayer racing game with single top-down view and pretty arcade gfx and controls. The idea was simple: The camera follows the top car and if you drop out of the camera, you lose. When all but one player has dropped out, the player who survived gets one point. Then everyone is respawned again in the current camera location and another round begins. The game ends after some player has 20 points and he is the ultimate winner of the whole match.


I have never played this kind of game, or even heard such things exists. After 5 seconds of watching the youtube video, I felt like "WOW!". It was somehow instantly clear to me, how superior this idea actually was. "Perfect for multiplayer racing!" I thought. The very reason it is so good, is that it cleverly removes the greatest obstacle between fun and multiplayer driving games: It's boring to drive alone. When you take your average Need for Speed, and go for a spin with couple of online buddies, this is what happens: First there is a big hazzle at the start, followed by couple of critical knockouts. After this comes the "10 minutes of boredom", where you try to catch your friend who is playing it safe. At the same time, you are taking huge risks, and eventually crash (with curses and moaning). There is the good ole "catch-up" concept, where the game gives extra boost to guys behind, but that just feels so lame! What is the purpose of trying to get ahead, if the looser behind you always gets back with fony catch-ups, and eventually the winner is the one, who gets the timing of the last corner right. This new format with very quick knockout rounds is very different. It's action all the way. There is constant
interaction between the players. That is what multiplaying is all about, right?

I'm going to try to implement this in the Quickrally asap. I will do couple of twists compared to original game, since mine has multiple views and I don't want it too be too arcade. I think I'm going to do it in a way that if you are leading the race, you gather some kind of "mojo", and after it's "full" you win the round. If you are overtaken, the mojo will go down fast. Also I think I will make the player who is in the last position, when the round ends, lose a point. This motivates the guys at the back, who were knocked offroad by evil peers, still put in the effort, even if it seems they lost the changes of winning the round. I'm pretty excited about this, and I hope my implentation is atleast half as fun as the original. I'm still trying to find that youtube-clip with no luck, and probably need to ask about it from my friend again.. Anyone know this game?

update:



This is the game I was talking about.

perjantai 27. marraskuuta 2009

T+167

Over 100 hours since my last post. Feels bizarre. I had to recheck to make sure it was correct, since I was sure it was yesterday. I also have a minor sleep deprivation thing going on. Last night I finally brute-forced the first working network implementation for the Quickrally with pure willpower. When I finally got it up and running, it was something like 7-8am. I collapsed to bed for 4 hours, just to wake up for a afternoon lecture @ school, only to find out that the damned thing was cancelled. Fortunately I didn't wake up for nothing, since there was a weekly meeting of Load (our gamedev club @ school) soon after. We were able to do a little testing on the new multiplayer version, and even recorded a short video:



As you can see, I have removed all the eyecandy from Quickrally for testing purposes, just to underline the stuff about prioritising the gameplay/fun over the fancy (yet technically more intriguing) visuals. This also cut back my pregame loading times alot, which is great.

I realized today, that I need to start specifying some concrete todos for the crunch now. I knew beforehand, that my crunching would be more concentrated on december, and there were more "other stuff" for november. Yet I still have the feeling, that things haven't progressed as much as I'd liked. I really have to separate the must-have features from the rest. The truth is -- and I'm very glad this is the case -- that only the Tanksalot needs to be in a robust and polished form after the crunch. Quickrally can (and will) be more of a prototypish demo when I pass it on to my teacher. It has to run, it has to look decent and it has to come with documentation and that's about it. This gives me some leeway on what I'm trying to get crunched until the 9th of December.

Tanksalot
  1. Replace the powerup placeholders with actual 3d-models
  2. Polish the audio
  3. Add a "Rematch" button
  4. Clean up all the debugging data and unused assets
Quickrally
  1. Make the server more robust with players coming and going
  2. Give the players waypoints and subgoals (laptimes, scoreboard, etc.)
  3. Try to test and optimize the network code for WAN connections
  4. Finalize the carmodel
  5. Bring back the old shaders and eyecandy when the other stuff is done
  6. Figure out if the preload times can be optimized
  7. Try celshading
There is also a common task for both of the games, which I left out from the lists: Try to make them work smoothly on different setups and OSes. Today I tried the Tanksalot @ school with a 64-bit Windows 7 and I got it to run, but it had a flickering loading screen and it eventually crashed on OpenAL initialization. I got the Quickrally multiplayer demo to run alright on the same machine, but it had some weird jaggs and jitters on frame rate every now and then, even though the CPU load never went over 30%. It was weird. Couple weeks ago we were also able to get the eyecandy version of the Quickrally to run on an iMac, but for now I'm trying to focus on getting the two games work on all the Windows setups smoothly.

maanantai 23. marraskuuta 2009

T+63

I got home from work and eventually ended up doing the health/ammo -powerups on the Tanksalot. You can see the red and blue placeholder boxes in the background. I also put some touches on the missile. There is now a shiny billboard texture to respresent bright light from the afterburn + some more flash with the same texture when it explodes. It made the missiles much more visible which is excellent. It was kind of disturbing when you couldn't get any feedback behind those sexy smoke particles. I also added a little more ground texture to see where the ground is, since there aren't much shadows or other artifacts lying around.

I have one informational bit to share with you who are planning to make a split-screen game: It is a very hard to determine if your split-screen game is fun. You can't test it with your friends over the internet (unless you make support for it) and testing it alone is just a waste of time. Sure you find the bugs, but the actual gameplay needs two players on one machine. Period. When I played a prototype of Tanksalot with our team for the first time, I felt like a utter retard. I just had some kind of false expectation, that two tanks fighting against each other, on plain ground with unlimited ammo, would be fun. It worked for the Rocket Arena-mod in Quakeworld, so why not here too? Well all I can say that it was a very very sad five seconds for me personally.

I took some lessons from my disapointment and even found some deeper insight later: I noticed how my pattern of doing gamedev has always been the visuals and the engine beneath the game. I just end up using huge amount of time to get some textures or bloom (oh I just love the bloom) for some early prototype, where no one else gives a s**t how it looks. Or maybe try to optimize some part of the code to give me +0.23 frames per second. The truth is that I have never really paid too much attention to what is (or could be) really fun for the player. I was just too busy having fun myself with building stuff out from nothing and making it look extra nice
. One of my friends nailed it down in a simple slogan: "You have to decide if you are making games or game engines". The right way to make great games is just the opposite of what I was doing. You need to prototype your idea without the glitter and make it fun. You can paint it with pretty colors afterwards. Well, I'm still a new kid on the block, and there is a lot to learn, so mistakes are bound to happen.

That's it. Now it's time for this new kid to get some sleep. Ciao!

sunnuntai 22. marraskuuta 2009

T+49

I pretty much sat in front of my PC the whole day. I was feeling very unproductive thought, and everything seemed to take me longer than expected. I guess it was just one of those days. I'm glad it wasn't a total disaster and I was able to get things done too. I focused on the Quickrally's client/server implementation like I planned in my long post yesterday, but didn't get to drive my car around the server yet, like I was hoping for.

My networking engine was missing a system for reliable packet delivery over UDP and that took me many many many hours to get those ACK-packets to do their job. Now it's finally up and running, and I was able to transfer settings, heightmap and roadspline to client-side, without worrying about missing packets along the way. You can get away with losing a packet of current coordinates for some arbitary world object, but losing a packet describing your vehicles suspension or maybe some curve in your road is another thing.


I was planning to explain the way I'm going to implement the networking in Quickrally, but I feel that it is going to be more useful to write about it after I get the first working prototype out of the oven. I already have a pretty good idea how everything is going to be implemented, but I never used a physics middleware like Bullet along with my networking stuff, so there might be some surprises in store for me.


Tomorrow I'm going to focus only on Tanksalot. My goal is to add collectable ammo and health packets, which are going to drop out from the sky in some parachuting manner. This is going to make the gameplay much more sensible, because players now have motive to drive around and not go straight for the kill, which made the game pretty retarded so far. I don't have the 3d-models for the powerups yet, but I'm going to use some placeholders. I'm also going @ my dayjob tomorrow, so I don't think I have time to do anything else for the game. Well I could stick in the new audiosamples if I still have time & energy left.

lauantai 21. marraskuuta 2009

T+26

By now there might be some random (missclicked) readers who are not affiliated with me @ school or otherwise and might want to know what are these two games about. Actually Tanksalot is maybe over 80% complete and Quickrally - while never going to be totally finished - has come a rather long way too.

Quickrally


Quickrally is my flagship project at the moment. It is going to be very much multiplayer-only driving game. I'm leaving out all the boring career modes and fony stories. Focus will be on driving and driving only. One feature that sets Quickrally apart from other driving games is the procedural side of it: The track will be different everytime you race. Now it's more about driving skills and less about memorizing all the tracks to beat your friends.

Tanksalot

Tanksalot is a game I've been coding couple of months now. It's a school project for a course called "Introduction to Game Development Tools". I have three other people besides myself in the group doing modelling, 2d-art and audio. It is split-screen tank duel with non-linear fire and very simple game mechanics. We decided to do cartoon-like style celshading and I really like how it looks now. I might do celshading in Quickrally too.

First day of war


I got over the fence and into the trenches tonight. Coke bottles were opened, coffee ended up being very strong and beautiful code started to emerge. Well, not so much emerged, but the existing code took some refactoring blows and heavy cleaning was being made by our late night coding hero. I also started to get better vision how to implement networking into Quickrally and that is what I'm going to explain next.

Networking


Networking in a real-time fast-action multiplayer game is not very easy or straightforward. I would not recommend it to anyone doing their first project. There are no complicated mathemathics involved, but quite alot of ways to hang yourself while implementing your multiplayer extravaganza. Be warned: You are almost always screwed, if you try to add multiplaying features to your game afterwards, unless you have used some very sophisticated event-based architecture in your game. And even then you are still probably screwed anyway.

The story of multiplayer networking

Once upon a time, you were player in this distributed world (it means that the world exists in multiple computers). You decide, that it is time for you to walk forward, so you send the server a message: "dear server, I would like to walk forward, if this is anyway convenient for you, sir". Notice the polite tone in the message. This is due the fact, that in this very world, the server is in charge of everything. The server is the KING. You do not f*** with the king. After all, what kind of world would it be, if every person could decide the laws of physics for themselves? A world very hard to implement in any programming language I know.

So back to the story: The allmighty server gets your request. It does some calculations and decides to reply: "So you little punk, you wan't to walk eh? ... well go ahead, your coordinates are now x,y,z and your velocity is v". This message is sent to all the players nearby, so that they all would see you in your new position. After all, all the other players are in a different dimensions, interconnected only by his highness the server.

So everyone got your new location. Well, everyone except your cousin riding on a horse toward you. The king uses high-speed messagepidgeons to deliver these messages, and the very bird that was going to deliver your cousin the information, had one too many tortillas for lunch, and has stopped somewhere along the way to take a dump. So now you're cousin is not aware of our hero's new location, which happens to be right across his path. The king has also set a new law, that in order to save money, he always waits for the pidgeons to get back to send new messages. So while the king is waiting for your cousins constipating pigdeon, his next physics calculations get closer and closer to a crueling outcome: You, my friend, are kaputt.

Afterwards, your cousin decides to bury you right there in the spot. While he is digging your grave, the unfortunate pidgeon finally arrives and delivers the message. The cousin reads it and goes red-hot-al-qaida-mad, screaming his lungs out: "what the f*** am I going do with this now?!". If only the message got there in time.

The pidgeons in this story were UDP-based by the way. It means that they are fast and light, but not guaranteed to arrive in order, or better yet, not arrive at all. There is a simple solution: The king has to send pidgeons after pidgeons and not wait for the comebacks. In a time-critical game, the information gets old the very second it is being sent. Nobody wants to know your location 2 seconds ago. It's yesterdays news.

TCP or UDP?

Awhile back, when I started to research the subject, there was alot of dispute over which protocol to use. I don't know if the disputes still go on. If I had to guess, they are. Have you ever heard a dispute being settled in the wonderful world of interwww? I sure haven't.

My advice is this: The more time-critical your games, the more you want to lean toward UDP. If I'm doing a game like fast FPS-shooter or driving game, all the milliseconds in our response-time are going to make a huge difference. UDP gets things done faster and lighter, so it is the weapon of choice for fast-action. After all, how wrong can mr. Carmack be?

Then again, if you are creating turn-based strategy or slow-based roleplaying game: Go for the TCP. It guarantees order and delivery which makes life alot easier when your needs are more toward events and less about current state.

There is also third option: the hybrid model. Use UDP for time-critical data and TCP when you need more hi-fidelity order and delivery. I personally dislike this approach (in theory) for it's messiness, but have actually never tried it myself, so I try to refrain myself from making foolish comments about stuff that I'm too retarded to implement.


This ended up to be a very long post indeed. I got a little carried away by the subject, but no harm done I guess. Tommorow I might get my multiplayer implementation to actually work and maybe I'll explain my approach in a little more detail.