diff --git a/TrustFall/TrustFall/TrustFall.vcxproj b/TrustFall/TrustFall/TrustFall.vcxproj index ff05b35..86edf0c 100644 --- a/TrustFall/TrustFall/TrustFall.vcxproj +++ b/TrustFall/TrustFall/TrustFall.vcxproj @@ -148,9 +148,7 @@ - - @@ -159,9 +157,7 @@ - - diff --git a/TrustFall/TrustFall/TrustFall.vcxproj.filters b/TrustFall/TrustFall/TrustFall.vcxproj.filters index 4c20cbd..0f73592 100644 --- a/TrustFall/TrustFall/TrustFall.vcxproj.filters +++ b/TrustFall/TrustFall/TrustFall.vcxproj.filters @@ -54,12 +54,6 @@ Source Files\TrustFallImplement - - Source Files - - - Source Files - Source Files\ScreensImplement @@ -86,12 +80,6 @@ Header Files\TrustFall - - Header Files - - - Header Files - Header Files\Screens diff --git a/TrustFall/TrustFall/catch.wav b/TrustFall/TrustFall/catch.wav new file mode 100644 index 0000000..c5e0a57 Binary files /dev/null and b/TrustFall/TrustFall/catch.wav differ diff --git a/TrustFall/TrustFall/catcher.cpp b/TrustFall/TrustFall/catcher.cpp deleted file mode 100644 index 3831755..0000000 --- a/TrustFall/TrustFall/catcher.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "catcher.h" - -Catcher::Catcher(int _position) { - position = _position; -} - -void Catcher::move_up() -{ -} diff --git a/TrustFall/TrustFall/catcher.h b/TrustFall/TrustFall/catcher.h deleted file mode 100644 index 0ad20af..0000000 --- a/TrustFall/TrustFall/catcher.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -class Catcher { -public: - int position; - - Catcher(int _position); - - void move_up(); -}; \ No newline at end of file diff --git a/TrustFall/TrustFall/cursor.cpp b/TrustFall/TrustFall/cursor.cpp index e591e93..b43c230 100644 --- a/TrustFall/TrustFall/cursor.cpp +++ b/TrustFall/TrustFall/cursor.cpp @@ -15,6 +15,7 @@ Cursor::Cursor() active = false; } +//Give items to the cursor, and set the selected item to be the first template void Cursor::activate(std::vector _items) { @@ -23,12 +24,14 @@ void Cursor::activate(std::vector _items) active = true; } +//Functionality that was not used for this game, may be used in future projects. template void Cursor::deactivate() { active = false; } +//Draw the menu options on the screen based on the x and y coordinates for the menu to start at template void Cursor::draw(float _x_start, float _y_start, float _y_offset, ALLEGRO_FONT* _font) { vector items_text = get_item_strings(); @@ -38,13 +41,14 @@ void Cursor::draw(float _x_start, float _y_start, float _y_offset, ALLEGRO_FO y_offset = _y_offset; font = _font; - for (int i = 0; i < items_text.size(); i++) { + for (unsigned int i = 0; i < items_text.size(); i++) { al_draw_text(font, al_map_rgb(255, 255, 255), x_start, y_start + (y_offset*i), ALLEGRO_ALIGN_LEFT, items_text.at(i).c_str()); } update_selector(); } +//Change the selection of the cursor template void Cursor::down() { @@ -68,6 +72,7 @@ T Cursor::get_selected() { return items.at(selected); } +//Clear screen before drawing menu template void Cursor::redraw() { @@ -75,6 +80,7 @@ void Cursor::redraw() draw(x_start, y_start, y_offset, font); } +//Draw selector to highlight proper selected item template void Cursor::update_selector() { ALLEGRO_COLOR white = al_map_rgb(255, 255, 255); @@ -89,6 +95,7 @@ void Cursor::update_selector() { al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, white); } +//Define how the template will function when given various types. Only string was needed for this project. template Cursor::Cursor(); template void Cursor::activate(std::vector _options); template void Cursor::deactivate(); diff --git a/TrustFall/TrustFall/cursor.h b/TrustFall/TrustFall/cursor.h index a668e6d..98df0d7 100644 --- a/TrustFall/TrustFall/cursor.h +++ b/TrustFall/TrustFall/cursor.h @@ -3,11 +3,12 @@ #include #include +//Default object used for menues template class Cursor { public: std::vector items; - int selected; + unsigned int selected; bool active; Cursor(); diff --git a/TrustFall/TrustFall/employee.cpp b/TrustFall/TrustFall/employee.cpp deleted file mode 100644 index 69382ae..0000000 --- a/TrustFall/TrustFall/employee.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "employee.h" - -Employee::Employee(int _line) { - position = 6; -} - -void Employee::move() { - position -= 1; -} - - diff --git a/TrustFall/TrustFall/employee.h b/TrustFall/TrustFall/employee.h deleted file mode 100644 index 90337cc..0000000 --- a/TrustFall/TrustFall/employee.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -class Employee { -public: - int position; - - Employee(int _line); - - void move(); -}; \ No newline at end of file diff --git a/TrustFall/TrustFall/enums.h b/TrustFall/TrustFall/enums.h index bccad62..9e06aa3 100644 --- a/TrustFall/TrustFall/enums.h +++ b/TrustFall/TrustFall/enums.h @@ -3,9 +3,13 @@ #define SCREEN_W 640 #define SCREEN_H 480 +//Collection of states run by state machine enum State { Start, - Gameplay, + Easy, + Medium, + Hard, + EXTREME, Help, End, Exit diff --git a/TrustFall/TrustFall/fall.wav b/TrustFall/TrustFall/fall.wav new file mode 100644 index 0000000..fb27628 Binary files /dev/null and b/TrustFall/TrustFall/fall.wav differ diff --git a/TrustFall/TrustFall/game.cpp b/TrustFall/TrustFall/game.cpp index 91b68d7..743e5cc 100644 --- a/TrustFall/TrustFall/game.cpp +++ b/TrustFall/TrustFall/game.cpp @@ -10,6 +10,7 @@ using std::pair; Game::Game() { } +//Load all global data for the game: sprites, audio, and font. void Game::init() { score = 0; state = Start; @@ -28,32 +29,72 @@ void Game::init() { sprites.insert(pair("KeyH", al_load_bitmap("small_key_h.bmp"))); sprites.insert(pair("KeyM", al_load_bitmap("small_key_m.bmp"))); sprites.insert(pair("KeyEsc", al_load_bitmap("small_key_esc.bmp"))); + sprites.insert(pair("MusicOn", al_load_bitmap("music_on.bmp"))); + sprites.insert(pair("MusicOff", al_load_bitmap("music_off.bmp"))); + al_reserve_samples(4); + samples.insert(pair("Theme", al_load_sample("rasputin.wav"))); + samples.insert(pair("Move", al_load_sample("move.wav"))); + samples.insert(pair("Catch", al_load_sample("catch.wav"))); + samples.insert(pair("Fall", al_load_sample("fall.wav"))); + samples.insert(pair("Place", al_load_sample("place.wav"))); + samples.insert(pair("LevelUp", al_load_sample("level.wav"))); + font = al_create_builtin_font(); } +//Was not used in this project void Game::reset() { - score = 0; - state = Start; } +//Run the game state machine void Game::run() { - GameScreen game_screen(sprites); + //Load screens + GameScreen game_screen(sprites, samples); StartScreen start_screen(sprites); - ResultScreen result_screen(sprites, 0, 0); + ResultScreen result_screen(sprites, 0, 0, Easy); + int difficulty = 1; //Difficulty to run + bool EXTREME_ON = false; //Flag for EXTREME easter egg while (state != Exit) { al_clear_to_color(al_map_rgb(0, 0, 0)); switch (state) { case Start: start_screen.run(font); - state = start_screen.next_state; + if (start_screen.next_state == EXTREME) { + EXTREME_ON = true; + state = Hard; + } + else { + state = start_screen.next_state; + } break; - case Gameplay: - game_screen.reset(3, 5, 3); + //The same set of code will be run for any difficulty state + case Easy: + case Medium: + case Hard: + //But we need to check once here whether the difficulty value needs to be adjusted + switch (state) { + case Medium: + difficulty = 3; + result_screen.prev_state = Medium; + break; + case Hard: + difficulty = 5; + result_screen.prev_state = Hard; + break; + } + if (EXTREME_ON) { + game_screen.reset(5, 5, difficulty); //If the EXTREME easter egg is enabled, the game will be run with 5 lines on hard mode + } + else { + game_screen.reset(3, 5, difficulty); + } + EXTREME_ON = false; game_screen.run(font); state = game_screen.next_state; break; case End: + //Send proper finishing values for this game to the result screen result_screen.score = game_screen.score; result_screen.difficulty = game_screen.difficulty; result_screen.run(font); @@ -61,4 +102,14 @@ void Game::run() { break; } } + + //Garbage collection + map::iterator it; + for (it = sprites.begin(); it != sprites.end(); it++) { + al_destroy_bitmap(it->second); + } + map::iterator it2; + for (it2 = samples.begin(); it2 != samples.end(); it2++) { + al_destroy_sample(it2->second); + } } \ No newline at end of file diff --git a/TrustFall/TrustFall/game.h b/TrustFall/TrustFall/game.h index 5b15833..1354ce1 100644 --- a/TrustFall/TrustFall/game.h +++ b/TrustFall/TrustFall/game.h @@ -12,6 +12,7 @@ #include "enums.h" +//Game state machine, contains data global to game class Game { public: //Allegro elements @@ -23,6 +24,7 @@ public: int score; std::map sprites; + std::map samples; Game(); diff --git a/TrustFall/TrustFall/game_screen.cpp b/TrustFall/TrustFall/game_screen.cpp index c4d2fcc..3e39b6e 100644 --- a/TrustFall/TrustFall/game_screen.cpp +++ b/TrustFall/TrustFall/game_screen.cpp @@ -1,9 +1,12 @@ #include #include +#include +#include #include #include #include #include +#include #include "game_screen.h" @@ -15,14 +18,15 @@ using std::ostringstream; using std::map; using std::pair; -GameScreen::GameScreen(std::map _sprites) { +GameScreen::GameScreen(std::map _sprites, std::map _samples) { sprites = _sprites; + samples = _samples; + srand(time(NULL)); //Seed random number generator with current time so sequence is unique each run } +//Resets game to default values, and uses new given values void GameScreen::reset(int _lines, int _max_catchers, int _difficulty) { - if (!lines.empty()) { - lines.erase(lines.begin(), lines.begin() + _lines); - } + lines.clear(); for (int i = 0; i < _lines; i++) { Line new_line(SCREEN_W / 2, SCREEN_H / _lines * i, sprites); lines.push_back(new_line); @@ -33,88 +37,139 @@ void GameScreen::reset(int _lines, int _max_catchers, int _difficulty) { catchers = 0; score = 0; difficulty = _difficulty; + music = true; } -void GameScreen::run(ALLEGRO_FONT* font) { - bool music = true; - bool help = false; +//If a sample needs to be played while it is still being played, it will be stopped first. +//Admittedly this was a hack solution to the fact that my sound effect samples are too long. +//In future projects I will use a better program for sound effect creation that does not have a large minimum length for audio export. +void play(ALLEGRO_SAMPLE_INSTANCE* x) { + if (al_get_sample_instance_playing(x)) { + al_stop_sample_instance(x); + } + al_play_sample_instance(x); +} +void GameScreen::run(ALLEGRO_FONT* font) { + //Map that represents difficulty scale map difficulty_map; difficulty_map.insert(pair(1, 15)); difficulty_map.insert(pair(2, 12)); difficulty_map.insert(pair(3, 10)); difficulty_map.insert(pair(4, 8)); difficulty_map.insert(pair(5, 5)); - + difficulty_map.insert(pair(6, 3)); + difficulty_map.insert(pair(7, 2)); + ALLEGRO_EVENT_QUEUE* event_queue = NULL; event_queue = al_create_event_queue(); al_register_event_source(event_queue, al_get_keyboard_event_source()); ALLEGRO_TIMER* timer = NULL; - timer = al_create_timer(0.1); + timer = al_create_timer(0.1); //Universally a "tick" in the context of the game is 1/10 of a second. al_register_event_source(event_queue, al_get_timer_event_source(timer)); redraw(font); al_flip_display(); - int ticks = 0; + //Create map of sample instances. This is more memory efficient than play samples over and over again individually, + //and allows the anti-overlap functionality implemented above. + map instances; + map::iterator it; + for (it = samples.begin(); it != samples.end(); it++) { + instances.insert(pair(it->first, al_create_sample_instance(it->second))); + al_attach_sample_instance_to_mixer(instances[it->first], al_get_default_mixer()); + } + + al_set_sample_instance_playmode(instances["Theme"], ALLEGRO_PLAYMODE_LOOP); + play(instances["Theme"]); + + int ticks = 0; //Counts the number of ticks, this is used to determine when to move the lines bool exit_screen = false; - bool ctrl = false; + bool ctrl = false; //whether ctrl key is currently held + bool help = false; //whether help screen is currently displayed + al_start_timer(timer); while (!exit_screen) { ALLEGRO_EVENT ev; al_wait_for_event(event_queue, &ev); if (ev.type == ALLEGRO_EVENT_TIMER) { - if (ticks == difficulty_map[difficulty]) { - int add_to = rand() % (lines.size() + 1); + if (ticks == difficulty_map[difficulty]) { //If at the current difficulty level, the lines are due to move + int add_to = rand() % (lines.size() + 1); //Randomly decide which line to add to, with a 1/lines.size() chance of not adding for (unsigned int i = 0; i < lines.size(); i++) { if (i == add_to) { lines.at(i).add_employee(); } - lines.at(i).move(); - if (lines.at(i).fall) { + lines.at(i).move(); //Every line will move regardless of any factors + if (lines.at(i).fall) { //If an employee has fallen, the game is over + map::iterator in_it; + for (in_it = instances.begin(); in_it != instances.end(); in_it++) { + al_stop_sample_instance(in_it->second); + } + al_play_sample_instance(instances["Fall"]); exit_screen = true; + al_clear_to_color(al_map_rgb(0, 0, 0)); + redraw(font); + al_flip_display(); + al_rest(2.0); } - else if (lines.at(i).caught) { + else if (lines.at(i).caught) { //If an employee is caught, add to the score and then check if difficulty should be adjusted + play(instances["Catch"]); catchers--; score++; - if ((score == 10 || score == 20 || score == 30 || score == 40 || score == 50) && difficulty < 5) { + if ((score == 10 || score == 20 || score == 30 || score == 40 || score == 50 || score == 75 || score == 100) && difficulty < 7) { + play(instances["LevelUp"]); difficulty++; } } } + //Refresh screen al_clear_to_color(al_map_rgb(0, 0, 0)); redraw(font); al_flip_display(); - ticks = 0; + ticks = 0; //reset ticks } else { + //if not time to move, add to ticks ticks++; } } if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { switch (ev.keyboard.keycode) { case ALLEGRO_KEY_DOWN: - if (selected < 2) selected++; + play(instances["Move"]); + if (selected < lines.size() - 1) selected++; break; case ALLEGRO_KEY_UP: + play(instances["Move"]); if (selected > 0) selected--; break; case ALLEGRO_KEY_SPACE: if (catchers < max_catchers) { - lines.at(selected).add_catcher(); - catchers++; + if (!lines.at(selected).catchers[2]) { + play(instances["Place"]); + lines.at(selected).add_catcher(); + catchers++; + } } break; case ALLEGRO_KEY_M: - if (ev.keyboard.modifiers == ALLEGRO_KEYMOD_CTRL) { + //Toggle music + if (ctrl) { + if (music) { + al_stop_sample_instance(instances["Theme"]); + } + else { + al_play_sample_instance(instances["Theme"]); + } music = !music; } break; case ALLEGRO_KEY_H: if (ctrl) { - help = true; + help = true; //help screen is up + //Draw the help screen al_clear_to_color(al_map_rgb(0, 0, 0)); al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 20, ALLEGRO_ALIGN_CENTER, "Place catchers at the ends of the conveyors"); al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 30, ALLEGRO_ALIGN_CENTER, "You can place 3 catchers per conveyor"); @@ -125,7 +180,9 @@ void GameScreen::run(ALLEGRO_FONT* font) { al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "Up and down - Move cursor"); al_draw_bitmap(sprites["Spacebar"], SCREEN_W / 8 + 20, SCREEN_H / 2 + 100, NULL); - al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - Place employee"); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - "); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 150, SCREEN_H / 1.3 - 15, ALLEGRO_ALIGN_LEFT, "Place Employee"); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 150, SCREEN_H / 1.3 - 25, ALLEGRO_ALIGN_LEFT, "Select Menu Item"); al_draw_bitmap(sprites["KeyEsc"], SCREEN_W / 2 + 58, SCREEN_H / 2 + 60, NULL); al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "Close menu"); @@ -137,50 +194,61 @@ void GameScreen::run(ALLEGRO_FONT* font) { al_flip_display(); - while (help) { + while (help) { //While the help screen is still down ALLEGRO_EVENT unhelp; al_wait_for_event(event_queue, &unhelp); if (unhelp.type == ALLEGRO_EVENT_KEY_DOWN) { if (unhelp.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { - help = false; + help = false; //Take the help screen down } } } } break; case ALLEGRO_KEY_ESCAPE: - back(); + //Force quit game + back(); exit_screen = true; break; case ALLEGRO_KEY_LCTRL: case ALLEGRO_KEY_RCTRL: - ctrl = true; + ctrl = true; //ctrl is held break; } if (ev.type == ALLEGRO_EVENT_KEY_UP) { if (ev.keyboard.keycode == ALLEGRO_KEY_LCTRL || ev.keyboard.keycode == ALLEGRO_KEY_RCTRL) { - ctrl = false; + ctrl = false; //ctrl is released } } + //Global refresh al_clear_to_color(al_map_rgb(0, 0, 0)); redraw(font); al_flip_display(); } } - if (next_state != Exit) { + if (next_state != Exit) { //If the game loop was exited naturally rather than forced by Esc cont(); } - al_rest(2.0); + + //Garbage collection + al_destroy_event_queue(event_queue); + al_destroy_timer(timer); + map::iterator it2; + for (it2 = instances.begin(); it2 != instances.end(); it2++) { + al_destroy_sample_instance(it2->second); + } } +//Redraw all elements of the screen void GameScreen::redraw(ALLEGRO_FONT* font) { - al_draw_bitmap(sprites["Mr. Manager"], 80, 0 + (SCREEN_H / lines.size() * selected), NULL); + al_draw_bitmap(sprites["Mr. Manager"], 80, 0 + (SCREEN_H / lines.size() * selected), NULL); //Draw the manager based on which line is selected - for (unsigned int i = 0; i < lines.size(); i++) { + for (unsigned int i = 0; i < lines.size(); i++) { //Draw each line lines.at(i).draw(); } + //Display score, number of catchers, current difficulty level, and whether the music is on or off ostringstream score_msg; score_msg << "Score: " << score; al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W - 90, 0, ALLEGRO_ALIGN_LEFT, score_msg.str().c_str()); @@ -193,6 +261,9 @@ void GameScreen::redraw(ALLEGRO_FONT* font) { ostringstream difficulty_msg; difficulty_msg << "Level: " << difficulty; al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W - 90, 75, ALLEGRO_ALIGN_LEFT, difficulty_msg.str().c_str()); + + string music_img = (music) ? "MusicOn" : "MusicOff"; + al_draw_bitmap(sprites[music_img], SCREEN_W - 60, 90, NULL); } void GameScreen::back() { diff --git a/TrustFall/TrustFall/game_screen.h b/TrustFall/TrustFall/game_screen.h index a0b61b4..c407043 100644 --- a/TrustFall/TrustFall/game_screen.h +++ b/TrustFall/TrustFall/game_screen.h @@ -2,17 +2,20 @@ #include "line.h" #include "screen.h" +//Main screen for gameplay class GameScreen : public Screen { public: std::map sprites; + std::map samples; std::vector lines; - int selected; + unsigned int selected; int max_catchers; int catchers; int score; int difficulty; + bool music; - GameScreen(std::map _sprites); + GameScreen(std::map _sprites, std::map _samples); void reset(int _lines, int _max_catchers, int _difficulty); void run(ALLEGRO_FONT* font); diff --git a/TrustFall/TrustFall/level.wav b/TrustFall/TrustFall/level.wav new file mode 100644 index 0000000..65965bd Binary files /dev/null and b/TrustFall/TrustFall/level.wav differ diff --git a/TrustFall/TrustFall/line.cpp b/TrustFall/TrustFall/line.cpp index fece562..5ed091f 100644 --- a/TrustFall/TrustFall/line.cpp +++ b/TrustFall/TrustFall/line.cpp @@ -20,7 +20,9 @@ Line::Line(int _start_x, int _start_y, map _sprites) { } } +//Move the line forward void Line::move() { + //If a catch was previously made, move catchers forward and reset catch state if (caught) { caught = false; catchers[0] = catchers[1]; @@ -28,12 +30,15 @@ void Line::move() { catchers[2] = 0; } + //move employees forward for (int i = 0; i < 5; i++) { employees[i] = employees[i + 1]; } + //check if an employee is set to be added to this line employees[5] = (queued) ? 1 : 0; queued = false; + //check if a catch was made if (employees[0]) { if (catchers[0]) { caught = true; @@ -44,10 +49,12 @@ void Line::move() { } } +//Add employee to this line void Line::add_employee() { queued = true; } +//Add a catched to this line void Line::add_catcher() { for (int i = 0; i < 3; i++) { if (!catchers[i]) { @@ -57,25 +64,26 @@ void Line::add_catcher() { } } +//Draw this line void Line::draw() { - al_draw_bitmap(sprites["Conveyor"], start_x, start_y, NULL); + al_draw_bitmap(sprites["Conveyor"], start_x, start_y, NULL); //Sprite for (int i = 1; i < 6; i++) { - if (employees[i]) { + if (employees[i]) { //If the array says there is a catcher at the current position al_draw_bitmap(sprites["Employee"], start_x + (40 * (i-1)), start_y, NULL); } } for (int i = 2; i > -1; i--) { - if (i == 0) { - if (caught) { + if (i == 0) { //If this is the position closes to the line + if (caught) { //If there was a catch al_draw_bitmap(sprites["EmployeeHappy"], start_x - 40, start_y, NULL); } - else if (fall) { + else if (fall) { //If there was not a catch al_draw_bitmap(sprites["EmployeeSad"], start_x - 40, start_y + 55, ALLEGRO_FLIP_VERTICAL); } } - if (catchers[i]) { + if (catchers[i]) { //If there is a catcher at this position al_draw_bitmap(sprites["Mr. Man"], start_x - 40 - (50*(i)), start_y + 40, NULL); } } diff --git a/TrustFall/TrustFall/line.h b/TrustFall/TrustFall/line.h index 245d335..3ee5c68 100644 --- a/TrustFall/TrustFall/line.h +++ b/TrustFall/TrustFall/line.h @@ -4,9 +4,7 @@ #include #include -#include "catcher.h" -#include "employee.h" - +//Represents a conveyor belt line, contains data for the employees and catchers attached as well as some data about its current state class Line { public: float start_x; diff --git a/TrustFall/TrustFall/logo.bmp b/TrustFall/TrustFall/logo.bmp index fff965d..d237a48 100644 Binary files a/TrustFall/TrustFall/logo.bmp and b/TrustFall/TrustFall/logo.bmp differ diff --git a/TrustFall/TrustFall/main.cpp b/TrustFall/TrustFall/main.cpp index 5943959..673c775 100644 --- a/TrustFall/TrustFall/main.cpp +++ b/TrustFall/TrustFall/main.cpp @@ -37,13 +37,18 @@ int main() return -1; } + //Create display ALLEGRO_DISPLAY* display = al_create_display(SCREEN_W, SCREEN_H); al_clear_to_color(al_map_rgb(0, 0, 0)); + //Create game, initialize and run it Game main_game; main_game.init(); main_game.run(); + //Garbage collection + al_uninstall_audio(); + al_uninstall_keyboard(); al_destroy_display(display); return 0; diff --git a/TrustFall/TrustFall/move.wav b/TrustFall/TrustFall/move.wav new file mode 100644 index 0000000..b5ee8ee Binary files /dev/null and b/TrustFall/TrustFall/move.wav differ diff --git a/TrustFall/TrustFall/music_off.bmp b/TrustFall/TrustFall/music_off.bmp new file mode 100644 index 0000000..3ef124e Binary files /dev/null and b/TrustFall/TrustFall/music_off.bmp differ diff --git a/TrustFall/TrustFall/music_on.bmp b/TrustFall/TrustFall/music_on.bmp new file mode 100644 index 0000000..9d43715 Binary files /dev/null and b/TrustFall/TrustFall/music_on.bmp differ diff --git a/TrustFall/TrustFall/place.wav b/TrustFall/TrustFall/place.wav new file mode 100644 index 0000000..5c23e50 Binary files /dev/null and b/TrustFall/TrustFall/place.wav differ diff --git a/TrustFall/TrustFall/rasputin.wav b/TrustFall/TrustFall/rasputin.wav new file mode 100644 index 0000000..a0b82c1 Binary files /dev/null and b/TrustFall/TrustFall/rasputin.wav differ diff --git a/TrustFall/TrustFall/result_screen.cpp b/TrustFall/TrustFall/result_screen.cpp index 1ae6aa7..4f5e565 100644 --- a/TrustFall/TrustFall/result_screen.cpp +++ b/TrustFall/TrustFall/result_screen.cpp @@ -6,14 +6,15 @@ using std::string; using std::vector; using std::ostringstream; -ResultScreen::ResultScreen(std::map _sprites, int _score, int _difficulty) { +ResultScreen::ResultScreen(std::map _sprites, int _score, int _difficulty, State _prev_state) { score = _score; difficulty = _difficulty; + prev_state = _prev_state; vector menu_options; - menu_options.push_back("Retry"); - menu_options.push_back("To Main Menu"); - menu_options.push_back("Exit"); + menu_options.push_back("Retry"); //Retry at previous difficulty + menu_options.push_back("To Main Menu"); //Go back to main menu to select new difficulty + menu_options.push_back("Exit"); //Quit game menu.activate(menu_options); sprites = _sprites; @@ -35,16 +36,20 @@ void ResultScreen::run(ALLEGRO_FONT* font) { if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { switch (ev.keyboard.keycode) { case ALLEGRO_KEY_UP: + //Move cursor up menu.up(); break; case ALLEGRO_KEY_DOWN: + //Move cursor down menu.down(); break; - case ALLEGRO_KEY_ENTER: + case ALLEGRO_KEY_SPACE: + //Select menu item cont(); exit_screen = true; break; case ALLEGRO_KEY_ESCAPE: + //Force quit game back(); exit_screen = true; break; @@ -53,12 +58,17 @@ void ResultScreen::run(ALLEGRO_FONT* font) { al_flip_display(); } } + + //Garbage collection + al_destroy_event_queue(event_queue); } void ResultScreen::redraw(ALLEGRO_FONT * font) { + //Determine whether the player receives the bad or good ending; minimum requirement for good ending is 30 catches. string manager_sprite = (score > 29) ? "Mr. ManagerHappy" : "Mr. ManagerSad"; - string result_text = (score > 29) ? "Great job! You helped Mr. Manager's team feel more close together!" : "You didn't catch a lot of employees. Try to catch more next time!"; + string result_text = (score > 29) ? "Great job! You helped Mr. Manager's team bond more than ever!" : "You didn't catch a lot of employees. Try to catch more next time!"; + //Display score, level, and menu al_draw_bitmap(sprites[manager_sprite], SCREEN_W / 2 - 120, SCREEN_H / 2 - 40, NULL); menu.draw(SCREEN_W / 2, SCREEN_H / 2 - 30, 20.0, font); ostringstream score_msg; @@ -77,7 +87,7 @@ void ResultScreen::back() { void ResultScreen::cont() { string result = menu.get_selected(); if(result == "Retry") { - next_state = Gameplay; + next_state = prev_state; } else if (result == "To Main Menu") { next_state = Start; diff --git a/TrustFall/TrustFall/result_screen.h b/TrustFall/TrustFall/result_screen.h index 1a314a5..ce388cd 100644 --- a/TrustFall/TrustFall/result_screen.h +++ b/TrustFall/TrustFall/result_screen.h @@ -2,14 +2,16 @@ #include "cursor.h" #include "screen.h" +//Screen to display results upon losing class ResultScreen : public Screen { public: int score; int difficulty; Cursor menu; std::map sprites; + State prev_state; - ResultScreen(std::map _sprites, int _score, int _difficulty); + ResultScreen(std::map _sprites, int _score, int _difficulty, State _prev_state); void run(ALLEGRO_FONT* font); void redraw(ALLEGRO_FONT* font); diff --git a/TrustFall/TrustFall/screen.h b/TrustFall/TrustFall/screen.h index 0a0c2eb..b0398a8 100644 --- a/TrustFall/TrustFall/screen.h +++ b/TrustFall/TrustFall/screen.h @@ -7,6 +7,7 @@ #include "enums.h" +//Screen base class, implemented by every game screen class Screen { public: State next_state; diff --git a/TrustFall/TrustFall/start_screen.cpp b/TrustFall/TrustFall/start_screen.cpp index d71892a..ac1b5cf 100644 --- a/TrustFall/TrustFall/start_screen.cpp +++ b/TrustFall/TrustFall/start_screen.cpp @@ -8,13 +8,16 @@ using std::string; StartScreen::StartScreen(std::map _sprites) { vector menu_options; - menu_options.push_back("Start"); - menu_options.push_back("Quit"); + menu_options.push_back("Easy"); //Select Difficulty + menu_options.push_back("Medium"); + menu_options.push_back("Hard"); + menu_options.push_back("Quit"); //Quit game menu.activate(menu_options); sprites = _sprites; } +//Run screen void StartScreen::run(ALLEGRO_FONT * font) { ALLEGRO_EVENT_QUEUE* event_queue = NULL; event_queue = al_create_event_queue(); @@ -24,6 +27,7 @@ void StartScreen::run(ALLEGRO_FONT * font) { menu.draw(300.0, 400.0, 20.0, font); al_flip_display(); + bool ctrl = false; bool exit_screen = false; while (!exit_screen) { ALLEGRO_EVENT ev; @@ -32,43 +36,72 @@ void StartScreen::run(ALLEGRO_FONT * font) { if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { switch (ev.keyboard.keycode) { case ALLEGRO_KEY_UP: + //Move cursor up menu.up(); break; case ALLEGRO_KEY_DOWN: + //Move cursor down menu.down(); break; - case ALLEGRO_KEY_ENTER: - cont(); + case ALLEGRO_KEY_SPACE: + if (ctrl) { //If the ctrl key is held regardless of option, they will enter EXTREME easter egg mode + next_state = EXTREME; + } + else { + cont(); //Otherwise select the menu item + } + exit_screen = true; break; case ALLEGRO_KEY_ESCAPE: + //Force quit game back(); exit_screen = true; break; + case ALLEGRO_KEY_LCTRL: + case ALLEGRO_KEY_RCTRL: + ctrl = true; //ctrl is held down + break; } redraw(font); al_flip_display(); } + if (ev.type == ALLEGRO_EVENT_KEY_UP) { + if (ev.keyboard.keycode == ALLEGRO_KEY_LCTRL || ev.keyboard.keycode == ALLEGRO_KEY_RCTRL) { + ctrl = false; //ctrl is released + } + } } + + //Garbage collection + al_destroy_event_queue(event_queue); } void StartScreen::redraw(ALLEGRO_FONT* font) { - al_draw_bitmap(sprites["Title"], 0, 20, NULL); - al_draw_bitmap(sprites["Mr. Manager"], SCREEN_W / 2 - 40, 120, NULL); + al_draw_bitmap(sprites["Title"], SCREEN_W/2 - 240, 20, NULL); //logo + al_draw_bitmap(sprites["Mr. Manager"], SCREEN_W / 2 - 40, 120, NULL); //manager for (int i = 1; i < 7; i++) { - al_draw_bitmap(sprites["Mr. Man"], SCREEN_W / 8 * i + 14, SCREEN_H / 2 - 30, NULL); + al_draw_bitmap(sprites["Mr. Man"], SCREEN_W / 8 * i + 14, SCREEN_H / 2 - 30, NULL); //army of catchers } - al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 20, ALLEGRO_ALIGN_CENTER, "Mr. Manager wants to run a teambuilding exercise for his employees."); - al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 30, ALLEGRO_ALIGN_CENTER, "Help Mr.Manager place his employees at the end of his"); - al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 40, ALLEGRO_ALIGN_CENTER, "conveyor belts to make sure no other employees fall off."); - + //Instructions + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 10, ALLEGRO_ALIGN_CENTER, "Mr. Manager wants to run a teambuilding exercise for his employees."); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 20, ALLEGRO_ALIGN_CENTER, "Help Mr.Manager place his 5 catchers at the end of his"); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 30, ALLEGRO_ALIGN_CENTER, "conveyor belts to make sure no other employees fall off."); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 40, ALLEGRO_ALIGN_CENTER, "Try to catch enough to help the team bond!"); + + //Keys and their associated functions al_draw_bitmap(sprites["KeyUp"], SCREEN_W / 8, SCREEN_H / 2 + 60, NULL); al_draw_bitmap(sprites["KeyUp"], SCREEN_W / 8 + 34, SCREEN_H / 2 + 60, ALLEGRO_FLIP_VERTICAL); al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "Up and down - Move cursor"); al_draw_bitmap(sprites["Spacebar"], SCREEN_W / 8 + 20, SCREEN_H / 2 + 100, NULL); - al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - Place employee"); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - "); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 150, SCREEN_H / 1.3 - 15, ALLEGRO_ALIGN_LEFT, "Place Employee"); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 150, SCREEN_H / 1.3 - 25, ALLEGRO_ALIGN_LEFT, "Select Menu Item"); + + al_draw_bitmap(sprites["KeyEsc"], SCREEN_W / 8 + 20, SCREEN_H / 2 + 140, NULL); + al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 68, SCREEN_H / 2 + 150, ALLEGRO_ALIGN_LEFT, "Exit Game"); al_draw_bitmap(sprites["KeyCtrl"], SCREEN_W / 2 + 40, SCREEN_H / 2 + 60, NULL); al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 70, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "+"); @@ -79,6 +112,8 @@ void StartScreen::redraw(ALLEGRO_FONT* font) { al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 70, SCREEN_H / 2 + 110, ALLEGRO_ALIGN_LEFT, "+"); al_draw_bitmap(sprites["KeyM"], SCREEN_W / 2 + 78, SCREEN_H / 2 + 100, NULL); al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Toggle Music"); + + al_draw_text(font, al_map_rgb(255, 255, 255), 0, SCREEN_H - 10, ALLEGRO_ALIGN_LEFT, "Copyright 2019 Braydon Kains"); } void StartScreen::back() { @@ -86,8 +121,14 @@ void StartScreen::back() { } void StartScreen::cont() { - if (menu.get_selected() == "Start") { - next_state = Gameplay; + if (menu.get_selected() == "Easy") { + next_state = Easy; + } + else if (menu.get_selected() == "Medium") { + next_state = Medium; + } + else if (menu.get_selected() == "Hard") { + next_state = Hard; } else { next_state = Exit; diff --git a/TrustFall/TrustFall/start_screen.h b/TrustFall/TrustFall/start_screen.h index e417fe1..85f1004 100644 --- a/TrustFall/TrustFall/start_screen.h +++ b/TrustFall/TrustFall/start_screen.h @@ -2,6 +2,7 @@ #include "screen.h" #include "cursor.h" +//Starting menu class StartScreen : public Screen { public: Cursor menu;