Difference between revisions of "Aaron's Independent Study"

From Earlham CS Department
Jump to navigation Jump to search
Line 59: Line 59:
 
* o - options menu -- change these key commands
 
* o - options menu -- change these key commands
 
* q - quit
 
* q - quit
 +
 +
== Notes on style ==
 +
The following are stylistic conventions that I would ask you to conform to as you make changes to the program.  This will help improve overall readability.  Any questions, comments, or suggestions with regard to style decisions can certainly be directed to me via email (amweeden06 at earlham dot edu).
 +
 +
=== Variable names ===
 +
* I use variable names that are as descriptive and short (in that order) as possible.  For example, I prefer `num_inputs' to `n'.  The exception are local variables that are used quickly, and for-loop indices.
 +
* I use all lower case names, with underscores used for whitespace (as in `num_spaces').  The exception is global constants (see below)
 +
 +
=== classes ===
 +
* For classes, I use CamelCase, and start with capital letters (e.g. CircuitObject)
 +
* Each class should have a default constructor and a copy constructor (see Object.hpp for an example).  If a default constructor is used, any parameters that can be passed to it should have default values in the header file.  For example:
 +
Object(string type = "");
 +
* If applicable, each class should have an extraction operator '<<', so that all of the relevant information of an instantiation of the class can be obtained by simply saying cout << classname << endl;
 +
 +
=== Member variables ===
 +
* I follow the convention of putting an underscore (_) at the beginning of private member variable names to help distinguish them from local or public variables.
 +
* Each member variable should be given an accessor (a constant member function that just returns the variable) and a mutator (which assigns the variable the value passed by a parameter), except for vectors and classes.  Vectors should have an accessor that takes a size_t and returns the element at that position in the vector)
 +
* If a member variable is to be changed, I always do it with a mutator, never directly (e.g. set_value(1); rather than _value = 1;)
 +
* If a member variable is to be used, I always do it with an accessor, never directly (e.g. new_val = value(); rather than new_val = _value;
 +
 +
=== Global constants ===
 +
* These are declared in the file constants.hpp
 +
* I follow the convention of declaring global constants in ALL CAPS, with (_) to represent whitespace (e.g. WALL_WIDTH).
 +
 +
=== Const member functions ===
 +
* Any function that does not modify a class's member variables should be declared as const.
 +
 +
=== Indenting, whitespace, and bracing ===
 +
* I use 4 spaces for indent.
 +
* I use this style of bracing:
 +
int main()
 +
{
 +
...
 +
}
 +
 +
=== Comments ===
 +
* Wherever possible, I like to put a comment per line of code.  I find this greatly improves readability.
 +
* Functions should list their preconditions and postconditions.
  
 
== Tasks ==
 
== Tasks ==

Revision as of 11:24, 24 February 2010

For my senior project I have been developing an educational computer game to teach digital logic, specifically the interactions of logical switches and gates. The working title is "Computer City: Sewers," since the game takes place in the lowest level of a city ( corresponding to digital logic, which is conceptually the lowest level of the computer architecture ). The game is puzzle-based and is written in C++ with the OpenGL API.

The game's source is available at http://github.com/amweeden06/SRSem-Project-2009/tree/master/Source/

I welcome any contributions to my project. See the directions below for instructions on how to do so, and my suggestions for adding to the game. Any questions, send email to amweeden06 at earlham dot edu .

Code description

Computer City: Sewers' Code is written in C++ using a hierarchy of classes, as delimited below:

  • GameEngine -- the biggest class; contains all the data and methods to run the game. It contains a number of instantiations of subclasses derived from the Object class. The GameEngine class is described in more detail below.
  • Object -- contains information to display an object using OpenGL. Each subclass of an Object has a method for drawing itself, as well as accessors and mutators for each of its coordinates (left, right, bottom, top, width, and height).
    • Avatar -- subclass of the Object class. Represents the player-controlled object. Essentially a moving object that has a notion of which direction it is facing. For the moment, the avatar is a blue-green figure that walks around the screen, interacting with other objects. It is named "Bitty," and its gender is not specified.
    • Entrance -- subclass of the Object class. Representation of how the player entered the current room. If the current room is the first room, the entrance is a ladder (Bitty climbed down into the Sewer), otherwise it is a doorway.
    • Computer -- subclass of the Object class. A computer located in the top-right corner of the room that turns on once the current room's puzzle has been solved, at which point the player can interact with it. In interacting with this computer, the player fills out a truth table for the current room. If the player fills out the table correctly, he/she receives a blueprint, which just increases the player's score for now.
    • CircuitObject -- subclass of the Object class. Can be linked together in a "circuit" with other CircuitObjects. Circuits are loaded from a circuit file (*.sew); and this is described in detail below. A CircuitObject contains 0, 1, or 2 inputs and 0 or 1 outputs. It determines its output based on its inputs and the type of object it is (for example, a NOT gate performs a logical negation on its input to produce its output).
      • Switch -- subclass of the CircuitObject class. Has 0 inputs and 1 output. Its output is determined by loading a circuit file. Has an optional button, which allows the player to change the output value.
      • NOT -- subclass of the CircuitObject class. Has 1 input and 1 output. It performs a logical negation on its input to produce its output (so 0 becomes 1, and vice versa).
      • AND -- subclass of the CircuitObject class. Has 2 inputs and 1 output. It performs a logical conjunction on its inputs to produce its output (so it produces 0 unless both of its inputs are 1).
      • OR -- subclass of the CircuitObject class. Has 2 inputs and 1 output. It performs a logical disjunction on its inputs to produce its output (so it produces 1 unless both of its inputs are 0).
      • Exit -- subclass of the CircuitObject class. Represents the player's exit from the room. Has 1 input and 0 outputs. If the input is 1, the exit is open. Otherwise it is closed. Once the exit opens, the room is "complete", and the player can leave the room. Or, the player can attempt to enter the correct truth table for the room (see "Computer" above).

The Game Engine

The GameEngine class is responsible for the following tasks:

  • Maintaining the current room (i.e. level)
    • Managing a list of objects -- all rooms have an avatar, a computer, an entrance, and an exit that have fixed initial positions (and only the avatar is allowed to move). Each room also has a circuit, which consists of a variable number of switches and gates (but not an infinite amount of either; see constants.hpp for the maximum amount allowed of each). The circuit of the room is obtained by loading a circuit file, which by convention has the extension ".sew" (see below for specifics on circuit files). The GameEngine keeps all of this information as private member variables.
    • Drawing and re-drawing objects -- Objects know how to draw themselves, so the GameEngine just has to tell them to do so. But, the GameEngine must know under which game conditions to draw the objects (typically after a mouse or keyboard click), and the proper order in which to draw the objects (e.g. so a gate isn't drawn on top of the avatar). Drawing happens in the draw() function.
  • Providing a consistent interface to the player -- Handling keyboard and mouse events, displaying windows, outputting text to the terminal. There should be as much accomplished as possible within one window with one input device (i.e. keyboard). Having to switch between mouse and keyboard and keep track of multiple windows decreases the playability. This interface should also be customizable to allow the player to personalize the game experience.
  • Keeping a collection of statistics based on player performance -- this includes the amount of time (or number of keyboard clicks) a player takes to complete a room, the amount of rooms completed, the number of tries it takes to complete a truth table, and the number of blueprints collected.

Contributing to the project

Getting Started

github is the source code control of choice for this project. Below are the instructions for downloading the source code from github:

  1. Set up an account at github (it's free)
  2. Let me know your username once you have created an account so I can add you to the contributors list (send email to amweeden06 at earlham dot edu)
  3. On a shell, type the following:
$ mkdir Sewers
$ cd Sewers
$ git init
$ git config user.name <your git username>
$ git config user.email <your email>
$ git remote add origin git@github.com:amweeden06/SRSem-Project-2009.git
$ git pull origin master
$ cd Source/ACL
  1. You should now be in the directory with the source code. To build, type
$ make
  1. This will make an executable called Sewers. To run, type
$ ./Sewers

Playing

Key commands

  • w - up
  • a - left
  • s - down
  • d - right
  • f - action button -- behavior depends on which object the avatar is next to
  • i - save -- save the current game state (avatar position and switch values)
  • u - load -- load game state from a file
  • h - help -- get information about the current game situation (description of objects)
  • o - options menu -- change these key commands
  • q - quit

Notes on style

The following are stylistic conventions that I would ask you to conform to as you make changes to the program. This will help improve overall readability. Any questions, comments, or suggestions with regard to style decisions can certainly be directed to me via email (amweeden06 at earlham dot edu).

Variable names

  • I use variable names that are as descriptive and short (in that order) as possible. For example, I prefer `num_inputs' to `n'. The exception are local variables that are used quickly, and for-loop indices.
  • I use all lower case names, with underscores used for whitespace (as in `num_spaces'). The exception is global constants (see below)

classes

  • For classes, I use CamelCase, and start with capital letters (e.g. CircuitObject)
  • Each class should have a default constructor and a copy constructor (see Object.hpp for an example). If a default constructor is used, any parameters that can be passed to it should have default values in the header file. For example:
Object(string type = "");
  • If applicable, each class should have an extraction operator '<<', so that all of the relevant information of an instantiation of the class can be obtained by simply saying cout << classname << endl;

Member variables

  • I follow the convention of putting an underscore (_) at the beginning of private member variable names to help distinguish them from local or public variables.
  • Each member variable should be given an accessor (a constant member function that just returns the variable) and a mutator (which assigns the variable the value passed by a parameter), except for vectors and classes. Vectors should have an accessor that takes a size_t and returns the element at that position in the vector)
  • If a member variable is to be changed, I always do it with a mutator, never directly (e.g. set_value(1); rather than _value = 1;)
  • If a member variable is to be used, I always do it with an accessor, never directly (e.g. new_val = value(); rather than new_val = _value;

Global constants

  • These are declared in the file constants.hpp
  • I follow the convention of declaring global constants in ALL CAPS, with (_) to represent whitespace (e.g. WALL_WIDTH).

Const member functions

  • Any function that does not modify a class's member variables should be declared as const.

Indenting, whitespace, and bracing

  • I use 4 spaces for indent.
  • I use this style of bracing:
int main()
{
...
}

Comments

  • Wherever possible, I like to put a comment per line of code. I find this greatly improves readability.
  • Functions should list their preconditions and postconditions.

Tasks

Here are some of the things that the game needs. I've broken them down into small, medium, and big based on how long I think they'll take. Let me know if you'd like a better description of any of these, or if you have other ideas!

Small

  1. Implement a counter for number of rooms completed
  2. Implement a counter for number of blueprints collected
  3. Implement a counter for number of steps taken in a room Fixed by Aaron 2/19/10
  4. Make a function to detect whether the avatar is next to an object (rather than intersecting it)
  5. Fix 'f' so it doesn't always implement truth table Fixed by Aaron 2/18/10

Medium

  1. Get a mechanism working for saving and loading game states. This will likely take place in the file GameEngine.cpp Fixed by Aaron 2/19/10
  2. Right now there is a mechanism in place for loading a "room file", which describes the circuit of a given room (e.g. Room1.sew). Get a mechanism working to load a series of rooms as the player progresses through the game.
  3. Fix the bug on Linux that places the gates on top of each other rather than spread out Fixed -- uninitialized variable
  4. Implement a timer to record how long it takes a player to complete a room
  5. Implement the interface to allow player to -- e.g. movement speed and keyboard controls
  6. Implement a help button interface -- if the player pushes the help button, a small description appears of any objects the avatar is next to

Big

  1. Evaluate the code's simplicity, clarity, and generality and suggest/implement corrections to this
  2. I envisioned the player interacting with the computer in the top right corner of the room as follows: when the player completes the room, a truth table of the room is presented to the player to be filled out. Get this interface working or come up with a better one.