Battle Zone with OpenGl and Full 3D
Git: https://github.com/ivanzamoraarias/lab_computer_graphics_1
This is a tribute to the original Battle Zone game made by Atari. However I decided to made it as a full 3D environment with OpenGL and first person shooter mechanics like DOOM or Metroid Prime character controllers.
This web page explains the design decisions for the development of a game engine for the Battle Zone game[1]. Battle Zone has mechanics that involves the player and the behavior of the enemies in an apparently endless scene[3]. Furthermore, the original Battle Zone was consider a vehicle simulation game and one of the first using ”tank controls” for that genre[2], with vector graphics for describing the game world[3].Therefore, the main goal of the engine had to focus on simulation inside a tank represented in vector graphics. With those two goals in mind the development of the engine was divided in three phases: Graphics, Player mechanics and Enemy Mechanics.
Special tanks:This project uses the computer grpahics lab at chalmers as base code for rendering functions, also most assets I got form turbosquid.com.
This is a tribute to the original Battle Zone game made by Atari. However I decided to made it as a full 3D environment with OpenGL and first person shooter mechanics like DOOM or Metroid Prime character controllers.
This web page explains the design decisions for the development of a game engine for the Battle Zone game[1]. Battle Zone has mechanics that involves the player and the behavior of the enemies in an apparently endless scene[3]. Furthermore, the original Battle Zone was consider a vehicle simulation game and one of the first using ”tank controls” for that genre[2], with vector graphics for describing the game world[3].Therefore, the main goal of the engine had to focus on simulation inside a tank represented in vector graphics. With those two goals in mind the development of the engine was divided in three phases: Graphics, Player mechanics and Enemy Mechanics.
Special tanks:This project uses the computer grpahics lab at chalmers as base code for rendering functions, also most assets I got form turbosquid.com.
- Game Object Model
- In order to create any of previously mentioned goals, a game object model had to be defined. The Game Object Model to be chosen is the Pure component model, in which a game object could have a collection of components[4].
- This means that the components should be inherit from a common class(Interface or abstract) with an update method. In specific, I decided that the game object has nothing but a way to manage a map of object components as value and a component type enumeration.
- I decided to use a map because queering with a key is a O(1) operation, so it is really fast. Therefore if a game object is added to the engine it wont appear neither has a position.
- So if a programmer needs to create a game object with the presented engine , he should create a game object , then add as much components as he needs.
- However there are two basic components that should be added, so that an object can appear in the scene, these components are Renderable and Transformable which provides a model to be rendered and transformation matrix for the world description respectively.
- Engine Desription
- The engine object is the one in charge to update all objects that are in the game in a three dimentional environment. In order to do this I decided to merge the rendering logic to the Engine class so the engine could have a reference to the shader programs, linght maps, window and camera transformation matrices(view-Matrix and projection-matrix).
- The game engine for this project was decided to be as a state amchine with three states described by three functions: start, update, and stop. These states handle openGl functionalities like loading shaders, enabling culling algorithms and define light maps at the start of the engine.
- On the other hand the update method updates all the objects in contained in the engine. And the stop function which stops the execution of the engine.
- Graphics
- As mentioned previously , the original Battle Zone game uses vector graphics, which makes the illusion of a three dimensional space, so the engine needed a way to show the three dimensions to the player. In order to solve that I decided to use complete three dimensional graphics with OpenGl. However, Battle Zone has different model shapes on its world , like cubes, pyramids, enemy tanks , UFOs and a guided missile[3], which makes the buffer array drawing method difficult to do by hand. Therefore I decided to load textues and obj models instead of drawing by creating a matrix my self.
- Then the modeling and structuring of a scene were made in Autodesk Maya which helped to add polygons and pong materials.
- Worth mentioning that in early development objects in scene happened to be placed in a weird way, as a consequence movement was not precise. This was happening because an an object is positioned with respect to its pivot. So I had to place by hand each pivot to its respective object in the middle of the object. ---- It is safe to use other types of format
- Also, I decided to put the models as part of the Renderable component for a game object.
- Game Mechanics and controllers
- TANK MOVE/FPS
- AIMING/SHOOT
- EXPLORE THE GAME WORLD
- Entities
- Enemies:
- As explained in the Graphics section, there are three enemy entities originally made for the game which are the enemy tanks, the UFOs and the guided missile which have its own behaviors, movements and attacks, however the behaviors described in the engine are presented as the vision that I have for the enemies rather than a faithful replica of the original. Therefore the engine had to support different behaviors working at the same time. In order to do that I decided to add a component type called BEHAVIOR which can contain any particular component with specific properties. For example: the UFO has a behavior in which it follows a predefined path in the world and it does not shoot to the player, these properties are contained in the UFO Behavior Component; The tank behavior defined by the Tank Behavior Component, in which a bullet is going to be shoot at a specified rate. Likewise, the player score and life is contained in the Player Behavior component.
- Moreover, all enemy’s behaviors can be described with artificial intelligence in specific with Seek and Wandering algorithms. In the case of tanks, their movement is always wandering until they find the player character in a vision radius, then a seek algorithm is activated facing the player’s character. Also, the UFO behavior contains a set of points which describes a curve(spline) to patrol using seek algorithm to follow each control point in the curve.
- Player:
- Because the original game has a first person view for vehicle simulation, the engine to be developed had to have that functionality as well since I consider that it is the main substance in the experience of Battle Zone. Also, for personal reasons I decided to use the mouse as a controller like a classic first person shooter for PC[2], nevertheless I decided to base on the first DOOM[5] and Metroid Prime[6] for the camera movement.
- The player is described in the engine with a unique player behavior(with score and life as integers), and position shared with the main camera. The player behavior help to keep updating the life and score, and also to comunicate its presense with other behaviors, for instance when a bullet from a tank is shoot the way the collidable of that bullet undestands that it has to damage a player is by checking the collided object behavior. On the other hand, the translation component in the player object updates with the camaera position, therefore in the game loop the positions are updated, however direction and rotation are handled by mouse and keyboard input.
- The player moves by transformations based on mouse and keyboard input. The keys to be used for the translation matrix are the W, S, A, and D for moving front, back, left and right respectivelly. Likewise, for the rotation matrix the mouse input is being used, but it is only reading the left and right position in order to be perform as described in DOOM or Matroid Prime. As a consequence, in early development I realized that rotation in the border of the window stops, so I added a gap and comparison near to the border where the mouse input could be and added a faster rotation so camera can change faster so the user can continue looking for enemies without waiting too much on rotation to complete. Personally I thing there should be a better algorithm to do so since the Metroid Prime series has a soft and continuous rotation.
- World Distribution:
- Once the game was fully functioning( main character working, enemies moving and controllers working), I realized that the world was kind of empty and also some friends that were testing my results. Therefore I tried to find a better way to achieve a normal world sensation into the game. So I found 3 ways to achieve that.
- OBJECTS ARE ARRANGED IN A SINE POSITION
- Real world objects are not placed perfectly , therefore position stuff in a straight line did not work to show a "living" environment
- This gives a felling of full space, which I could say that is another Aesthetic and a potential Gameplay design patern.
- ENEMIES ARE ARRANGED IN A LINE
- NO NEED TO BE COMPLEX BECAUSE OF THE WANDERING AI
- AI UPDATED EVERY 12 FRAMES
- 9 TERRAIN TILES
- BOX BOUNDING
- UFO curved path
- Based on seek AI algorith, the UFO behavior contains a set of points which describes a curve(spline) to patrol using seek algorithm to follow each control point in the curve.
void UfoBehavior::update() { vec3 currentPos = this->transform->getTranslate(); vec3 nextPos = this->points[currentPoint]; float dist = distance(currentPos, nextPos); if (dist<=1) { if (currentPoint + 1 > 8) currentPoint = 0; else currentPoint += 1; } this->rigidBody->velocity = this->seekPoint(this->points[currentPoint]); }
- Tank Behavior
- The enemy tanks are the main enemies , so they will always patroll around the level. I decided to use the wonder walk AI algorithm for their behavior. However, they would also need to seek the player, so I created a specific radius for them to see the player. So the tanks will walk around in random directions until they see the player character.
- Code:
void TankBehavior::update() { int cTime = this->engine->getCurrentTime(); if (cTime % rate == 0 && count!=cTime) { SDL_Log("CREATE"); createTankBullet(); this->count = cTime; } Collidable* myColli = (Collidable*)this->gameObject->getComponent(COLLIDABLE); bool isCollided = myColli->isCollided; if (!isCollided || !myColli->currentColided) return; ObjectComponent* behavior = myColli->currentColided->getComponent(BEHAVIOR); BulletBehavior* t = dynamic_cast
(behavior); RockBehavior* rock = dynamic_cast (behavior); if (t != nullptr) { ObjectComponent* ownerBehav = t->getOwner()->getComponent(BEHAVIOR); TankBehavior* ownerTank = dynamic_cast (ownerBehav); if (ownerTank) return; if(ownerBehav) this->gameObject->Destroy(); } if (rock != nullptr) { RigidBodyComponent* rigidBody = (RigidBodyComponent*)this->gameObject->getComponent(RIGID_BODY); rigidBody->velocity *= -1.0f; } } void WandeSeekComponent::update() { RigidBodyComponent* charRigidBody = (RigidBodyComponent*)this ->gameObject ->getComponent(componentType::RIGID_BODY); Transformable* charTransform = (Transformable*)this ->gameObject ->getComponent(componentType::TRANSFORMABLE); maxVelosity = 5.0f; vec3 charPos = charTransform->getTranslate(); vec3 targetPos = vec3(target->x, 0.0f, target->z); double dist = distance(targetPos,charPos); if (dist < 100) { faceToTarget(charTransform, targetPos); charRigidBody->velocity = this->getSeekSteating(charTransform, charRigidBody); return; } charRigidBody->velocity = this->getWanderingStearing(charTransform, charRigidBody); }
- Distribution Design
The terrain in the game world is made by a 3D object exported from Maya.
Because I wanted to show a big world so I decided to distribute the model in
nine different positions. This made the world to look bast and let the user to
explore it. Although this is not typical of the original game, I think it gives
added value to the resulting game.
On the other hand, the objects like pyramids and cubes are arranged in
a sin function. I realized that a periodic function is good to place object in
a scene because to users can feel that the world is filled, otherwise if I use a
linear function to place various objects it wont be seen as natural and players
could notice that something is odd about the environment.
External Sources:
[1] Atari ; Battlezone 1980
[2] Carl Therrien ; Inspecting Video Game Historiography Through Critical Lens: Etymology of the First-Person Shooter Genre, http://gamestudies.org/1502/articles/therrien
[3] Fandom ; Battlezone https://videogamehistory.fandom.com/wiki/Battlezone
[4] Jason Gregory ; Game Engine Architecture
[5] ID software ; DOOM 1993
[6] Retro Studios; Metroid Prime 2002
Comments
Post a Comment