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.





Ei kommentteja:

Lähetä kommentti