For our final project, we created a 2.5 dimension platforming game that has many
of the necessary features for platforming game: coins, moving platforms, enemies that
bounce and track the player, and decorative fire textures (the most important part of making
any video game look sick). The game is built on a .scn file that takes in the parameters for nearly everything in a level, from the skybox to the textures to the coin location, and the game transitions smoothly between levels (e.g. loads a new scene file immediately once the goal is reached). Our most useful and creative feature, though, is a level editor that
allows you to generate platforms by mouse, move platforms, create coins, create enemies, and so forth, and then immediately play the game in the window.
Here are the features that we implemented, for a total of 4 basic features and 8 extra features
- 3D perspective viewing and objects.
- Lighting and smooth shading.
- User Input
- Computer Control over some element in the scene
- 1) Texture Mapping
- 2) Multiple Views
- 3) On-Screen Control Panel
- 4) Procedural and physically-based modeling.
- 5) Collision Detection
- 6) Simulated Dynamics
- 7) Sound
- 8) Game Level Editor
There are also many features of the game that do not fit under these 8 categories. We list them following our overview of the important features.
Our game is built in 3D using R3Scene.cpp as a base, OpenGL libraries to set up the basic game properties, and raytrace.cpp and particle.cpp for various functions related to collisions and particle creations. The game is created primarily in a single XY plane, and the movement is entirely 2D, so the game genre can be considered 2.5D. This is very useful for the game editor (so a simple click can create an object only in the XY plane, rather than having to specify distance from camera). The camera that follows the player shifts based on the speed of the player.
We used OpenGL to implement lighting and smooth shading. Directional lights in the scn files light up the scene. The materials for all of the objects are defined in the scene.
The user controls the player character with three keys: "w", "a", and "d" mapped to up, left, and right. Many other keys are used for auxiliary functions: "c" brings up the overview of the entire level, "m" toggles the minimap, "p" prints out a new scene file with the entire game in its current state, and the level editor allows the user to click anywhere in the scene and immediately create (or alter) objects. "r" restarts the level.
We have an enemy AI for each of the enemies that is able to track the player's location and navigate towards him. Pairing this with a jumping ability and a lot of size, this creates significant challenges to the player navigating through the scene. We also create a fire particle source that creates particles that slowly fade from yellow to red.
We implemented texture mapping using OpenGL's libraries for texture maps. The texture file is passed as an argument to the material in the scene file, which is then loaded onto the list of materials and applied onto an object through OpenGL. We texture mapped all players and enemies, coins, platforms, and the skybox behind the object (but only in one direction, to save memory). We also texture mapped the images in the sidebar of the level editor.
We created a minimap on the bottom left corner that allows viewing of the entire map at the same time as the actual game, with a transparent background so it blends easily into the game. Furthermore, holding down "c" zooms the camera out to the entire map in fullscreen.
There are multiple examples of on-screen control panels in our game. In the top left is a counter of the number of coins collected by the player. In the bottom left is a minimap HUD that allows the user to see the entire map at a time. In the level editor, there is a sidebar on the right side that allows you to choose between camera mode (for viewing), adding platforms, add enemies,
We created particle sources that emanated particles that changed colors slowly from yellow to red, imitating fire as a decorative addition. We also created red GL_QUADs that fly out from the player in all directions once the player dies, simulating an explosion.
We implemented collision detection between the player and other objects, and between the enemies and other objects (including other enemies and players). All of the collisions are axis-aligned. We also detect the direction of collisions (e.g. the player hits the enemy from the top), so that the player can kill and be killed by enemies depending on the direction of approach. Collision detection handles impossible setups smoothly and without crashing (e.g. crushing blocks between platforms), though sometimes it may jump the block out in the wrong direction given an impossible situation. Collisions between moving objects are handled realistically: a jumping enemy on a jumping enemy will jump higher from the extra velocity.
We have several examples of simulated dynamics. The player moves left and right on a platform, accelerating to a max_speed, and jumps by adding a force in the upwards direction. The movement left and right is slowed by drag, so the player continues moving for a short time after holding left/right. Platforms accelerate away from their start points and slow towards the end points, and the player on a platform has equivalent acceleration (e.g. moving up quickly increases jump velocity). Enemies follow the same simulated dynamics and also have the ability to jump and follow the player wherever the player is, reacting dynamically to their environment. Fire particles go from yellow to red as they age.
We used the irrKlang library for sound, allowing wav files to be played whenever events occur. The user can select music to be played in the background in the scene file. Sounds are played during jumps, and the sound of enemy's jumps attenuates with the player's distance from the enemies. Collecting coins creates a Mario sound, death sounds are played when the player dies, and success sounds are played when a level is completed.
The level editor is a large proportion of our project. With the level editor, you can change the camera view to anywhere in the scene. You can select any block, platform, or enemy, and drag it to a different place using the mouse, as well as delete the object. You can select an enemy and make it bigger or smaller by dragging the mouse. You can also spawn enemies, stationary platforms, coins, or fire sources using only a mouse click at the location desired. All of these features are implemented using a convenient sidebar picker with 7 options, where you can simply click the option you want and then immediately begin creating objects.
Furthermore, we can immediately start the game at any time in the level editor by immediately pressing "n" to initiate the game. The current state of the game be printed at any time (requiring a lot of reverse engineering of Read()) by simply pressing "p", in which case a new .scn file is automatically generated with the location of all players, objects, fire sources, enemies, platforms, and coins, along with their associated textures.
Our scn file has support for practically every variable in the game. Blocks and platforms can be created with any texture, and platforms move between two specified locations. The player and enemies can be created with any box shape at any location, with a given max speed. Enemies can be initialized to jump, to jump with any velocity, to follow the player, or to initially move in some direction (if it does not follow the player). Coins and fire sources can be created anywhere. The skybox image, minimum scene height, soundtrack to the scene, and next level after completion can all be set in the scene.
All relevant scene information can be immediately printed back out to another file ../levels/output.scn using "p", by reverse engineering Read() for all relevant objects. This is very useful for saving game state and creating new levels using the level editor.
In our game, completing a level will immediately jump you to the next level as specified in the scn file. This transition is smooth, and can be used by level designers to build an integrated massive game (e.g. transitioning betwen many levels or dungeons).