Undersea Game

undersea2

Full Demo: Youtube link, Code

Project Description & Overview

Creating a 3D game in OpenGL is both challenging and rewarding. There are many resources and libraries available to create a very realistic and high-end video game. I made use of OpenGL and SDL library to create a 3D adventure game that is set undersea. This game requires navigating through a 3D virtual scene to catch jellyfishes meanwhile avoid sharks to reach the goal. By implementing advanced features, the overall game play quality went up as well as the look and feel of the game.
My goal is to create a realistic undersea world. The major task is to make the scene realistic. I need to implement complex objects and textures in the scene as well as special effects like shadows, fog and caustic. Another obstacle is to add text to the game. Moreover, a smooth motion of the character by keyboard input and a friendly menu with a mini-map will add to a better experience.

Background

  1. Rendering Pipeline is the sequence of steps that OpenGL takes when rendering objects. Vertex attribute and other data go through a sequence of steps to generate the final image on the screen. First apply transform in 3D world coordinate system, next add illuminate according to lighting and reflectance. Then transform into 3D camera coordinate system, then 2D screen coordinate system, Clip primitives outside camera’s view. Finally, draw Pixels, also texturing.
    I use glTranslatef and glRotatef for matrix transformation. I also apply the perspective switch by F2 to show the transformation:

undersea3

  1. Lights I used include ambient light, which a scene-wide global ambient light to be applied to all primitives; directional light that models point light at infinity at certain direction; spotlight as a headlight that falls out smoothly and cut off. The images below show the effect of spotlight, you can turn it off by F3.

undersea4

  1. Shadow is also very important to detect objects around. It is created by projection from the 3D project to the ground turning the projection to a fixed dark color. The projection is scaled a little to make it bigger when it gets closer to the ground. You can turn it off by F5 if you don’t like it.

undersea5

  1. For the color of the scene, I use Gouraud shading model that calculates the surface normals at the vertices of polygons in a 3D computer model. These normals are then averaged for all the polygons that meet at each point. Lighting computations are then performed to produce color intensities at vertices.
    Also the reflections and refractions. One of the special effects of water is caustic, referring to patches of light or their bright edges. It is caused by light rays reflected or refracted by a curved surface or object, or the projection of that envelope of rays on another surface. I create this effect by adding 3 layers of texture to the sea bottom. You can also turn off the effect by F4.

undersea6

Installation

Build on Ubuntu 16.04. Install dependencies:

1
2
3
$ sudo apt-get install libsdl2-dev
$ sudo apt-get install libsdl2-ttf-dev
$ sudo apt-get install libsdl2-image-dev

Download the files,

1
$ git clone https://github.com/SnowflyLXF/OpenGL-3D-game.git

run the makefile inside the source code folder,

1
2
$ cd OpenGL-3D-game/project/src
$ make

run the executable file to start the game:

1
$ ./Undersea

Manual control

  1. Startup

Once you start the game, a tutorial appears for 10s then disappears(see tutorial.cpp). As you can see from the image, there is a stopwatch showing the remaining time (starting at 90s), a scoreboard showing accumulative scores up till now, and a mini-map at the left bottom corner, showing the position of sharks (marked by red spot) and jellyfishes (marked by blue spot)(see minimap.cpp). I use SDL-TTF to render text, the font is Oswald-bold(see textrender.cpp).

undersea1

  1. Control

Direction Keys:

Key ‘w’: Move forward, Key ‘s’: Move backward

Key ‘q’: Move upward, Key ‘e’: Move downward

Key ‘a’: Turn left, Key ‘d’: Turn right

Other:

Key ‘ESC’: Terminate the game

key SPACE: Accelerate

F1: Help F2: switch perspective F3: Headlight F4: Reflection F5: Shadow

In order to move more smoothly and realistically, I apply Newton’s law of Motion to the object. F=ma, taking friction in water into account F=-f (f for friction, which is set to constant, see Patrick.h). Speed will decrease to zero if no extra force is imposed, Δv = a. If Space is pressed, you will obtain acceleration in the moving direction. “Turbo” will appears on the top right corner. Notice that you can only use this function once in 5s. The velocity and acceleration are calculated as vector and are updated with the control system(see Dostep function in Patrick.cpp).

  1. Collision Detection

Since there are various objects located in the game, the implementation of collision detection is required to detect when the player the items. Each object is bounded by a rectangular box–bounding box(in Mesh.cpp ComputeBoundingBox). A collision is detected when the volumes of the two objects’ boxes intercept one another. The condition for a collision is: for each dimension (i.e. x,y,z), there is an overlap between the space occupied by object 1 and object 2 in that dimension. Once you collide with a jellyfish, you will gain 10 points, Once you collide with a shark, game over.

Game Design

In creating the game, many different OpenGL programming techniques are used for drawing and viewing objects and adding special effects.

  1. Characters

Items in the game are drawn with different shapes which are loaded from obj files(). They comprise of triangle meshes. The mesh components are vertices, edges and triangles. First read all the vertices, normals, texcoords & triangles into the allocated arrays. Then use Gouraud shading model that computes the lighting at the corners of each triangle and linearly interpolating the resulting colors for each pixel covered by the triangle. (see mesh.cpp)

undersea7

Patrick is the major character of the game that represents the player. The game uses a first-person view, so you can only see the back of him.
Jellyfish is the bonus(see Jellyfish.cpp). They are generated randomly. A new jellyfish is added every 3s in random position at the same height, and falling at a certain speed, it disappears beneath the ground(see JellyManager.cpp). Notice that jellyfish is translucent, to create the effect, I use blend function of OpenGL to decrease the alpha value of the object to allow some light to travel through jellyfishes.

undersea8

Shark is the villian, there are 3 sharks in total moving towards you at a certain speed(see Enemy.cpp, EnemyManager.cpp). Other objects like seaweed and starfish at sea bottom are for decoration (see Map.cpp).
Transformation functions including glRotatef and glTranslatef are applied to each object.

  1. Camera

The camera in the game is defined with the gluLookAt function. Throughout the main part of the game, the player explores the maze in the first-person view. He is able to look around the maze from his current position by using keyboard. This was done with SDL_Keycode which allows the game to record keyboard input.

  1. Lighting and Material Variation

Light sources, namely, specular, diffuse and ambient, are set. The light sources settings are initialized with the function glLightfv. These light sources are created with the code below(a direction light).
The diffuse light is used to define the bright areas of the object and the ambient light defines the color of the object.

Another effect is fog by glFog.

  1. Texture Mapping

In designing the game, we used the technique of texture mapping in order to provide a professional touch to our graphics. Texture mapping is the process of coloring pixels based on an image. In our game, we used bitmaps as our textures and mapped them to different objects in the game.

undersea9

Future Work

  1. Add more characters like different fish as enemy to decrease your score or bonus to increase score. For example, collision with octopus-lose 10 points; collision with barracuda-gain 5 points.

  2. Procedurally generate levels

  3. Add more functions like attacking the enemy

  4. Simulate the water effect of flow as well as seaweed and jellyfish floating with the flow to make it more realistic

  5. create an intelligent agent that plays the game automatically