A rouge-like rpg, heavily inspired on the binding of isaac. Running on a FRDM-K64F Mbed board. C++.

Dependencies:   mbed MotionSensor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 ELEC2645 Embedded Systems Project
00003 School of Electronic & Electrical Engineering
00004 University of Leeds
00005 Name: Steven Mahasin
00006 Username: el17sm
00007 Student ID Number: 201192939
00008 Date: 11/04/2019
00009 */
00010 #include "main.h"
00011 
00012 int main()
00013 {
00014     // Initialize
00015     init();
00016     
00017     while(1) { // Gameloop
00018         boss_room_exist = false;    // Game initialize variables
00019         number_of_enemies_killed = 0;
00020         total_time = 0;
00021         
00022         title.main(lcd, gamepad, global_contrast);
00023         srand(title.get_seed());
00024         player = new Player(39, 27);
00025         room_engine = new RoomEngine(global_contrast);
00026         
00027         game_loop();
00028         game_unload(); // Deletion of player, rooms, roomengine
00029     }
00030 }
00031 
00032 void init()
00033 {
00034     lcd.init();
00035     lcd.setContrast(global_contrast); 
00036     gamepad.init();
00037     for (int j = 0; j < MAX_ROOMS_MAP_Y; j++){
00038         for (int i = 0; i < MAX_ROOMS_MAP_X; i++){
00039             valid_rooms[j][i] = false;
00040         }
00041     }
00042 }
00043 
00044 void game_loop()
00045 {
00046     while(1) {  // Floor Loop 
00047         boss_room_number = 5 + rand() % 4; // Boss room appears after travelling 5-8 rooms
00048         boss_room_counter = 0;
00049         while(1) {  // Room Loop
00050             room_entrance();    // Generation of new room, loading of room and entrance scene
00051             while(room_engine->check_player_room_position() == INSIDE) {  // actions inside the Room
00052                 room_engine->read_input(gamepad);
00053                 room_engine->update(number_of_enemies_killed);
00054                 room_engine->render(lcd, gamepad);
00055                 minimap_detection();
00056                 total_time++;   // Incrementing time score
00057                 if  (player->get_hp() <= 0) {goto gameover;}    // gameover if player health depleted
00058                 if ((rooms[room_y][room_x]->get_room_type() == 10) && !(rooms[room_y][room_x]->enemies_exist())){goto winner;}  // wins game if room is a boss room, and the boss is dead
00059             }
00060             room_exit();    // Exit scene, deletion of existing entities and update of room coordinates
00061         }
00062     }
00063     gameover : { game_over(); goto displaystats;}
00064     winner : { win(); goto displaystats;}
00065     displaystats : { display_stats();}
00066 }
00067 
00068 void room_entrance()
00069 {
00070     update_room_coords();   // Accessor to room_engine room coords
00071     if (!valid_rooms[room_y][room_x]){generate_room();} // generate a new room if player enters a nonexistent room
00072     room_engine->load(player, rooms[room_y][room_x]);
00073     room_engine->entrance_scene(lcd, gamepad);
00074 }
00075 
00076 void room_exit()
00077 {
00078     room_engine->exit_scene(lcd, gamepad);
00079     rooms[room_y][room_x]->unload();
00080     player->delete_bullets();
00081     room_engine->update_current_room(); // Increments room coord
00082 }
00083 
00084 void generate_room()
00085 {
00086     valid_rooms[room_y][room_x] = true; // Sets the room coord to be valid
00087     if (boss_room_counter == 0) {   // if first room
00088         rooms[room_y][room_x] = new Room(0, 0); // no enemies
00089         rooms[room_y][room_x]->set_doorway(0, true);
00090     } else {
00091         rooms[room_y][room_x] = new Room(rand() % 4, 0);    // random enemies (0-3)
00092         if (boss_room_counter < boss_room_number) {no_of_doorways = 2 + (rand() % 100 < 10) + (rand() % 100 < 10);} // 20% chance of adding doorways
00093         else {no_of_doorways = 1;}  // If boss room exist, ensure all unexplored rooms branch out into a dead end
00094         while (count_doorways() < no_of_doorways) {
00095             rooms[room_y][room_x]->set_doorway(rand() % 4, true);   // Setting random doorways until number of desired doorways
00096         }
00097         update_definite_doorways();
00098         for (int i = 0; i < 4; i++) {   // Sets the definitive doorways
00099             if (cannot[i]){rooms[room_y][room_x]->set_doorway(i, false);}
00100             if (have_to[i]){rooms[room_y][room_x]->set_doorway(i, true);}
00101         }
00102         if ((boss_room_counter >= boss_room_number) && (!boss_room_exist)) {    // Sets the doorway towards the boss room to be a boss doorway
00103             rooms[room_y][room_x]->set_boss_doorway(available_boss_room());
00104             boss_room_exist = true;
00105         }
00106     }
00107     boss_room_counter++;
00108 }
00109 
00110 void update_room_coords()
00111 {
00112     room_y = room_engine->get_room_y();
00113     room_x = room_engine->get_room_x();
00114 }
00115 
00116 void minimap_detection()
00117 {
00118     while(gamepad.check_event(Gamepad::R_PRESSED)) {
00119         lcd.clear();
00120         for (int j = 0; j < MAX_ROOMS_MAP_Y; j++) {
00121             for (int i = 0; i < MAX_ROOMS_MAP_X; i++) {
00122                 if (valid_rooms[j][i]) {
00123                     draw_minimap(j,i);
00124                 }
00125             }
00126         }
00127         lcd.drawSpriteTransparent(33, 17, 15, 20, (char *)minimap_sprite[3]); // draws your current room
00128         lcd.refresh();
00129         wait_ms(1000/40);
00130     };
00131 }
00132 
00133 void draw_minimap(int j, int i)
00134 {
00135     lcd.drawSprite(33 + (i-room_x)*20, 17 + (j-room_y)*15, 15, 20, (char *)minimap_sprite[0]);  // draws normal room
00136     if (rooms[j][i]->get_room_type() == 10) {
00137         lcd.drawSprite(33 + (i-room_x)*20, 17 + (j-room_y)*15, 15, 20, (char *)minimap_sprite[2]);  // draws boss room
00138     } else if (rooms[j][i]->enemies_exist()) {
00139         lcd.drawSprite(33 + (i-room_x)*20, 17 + (j-room_y)*15, 15, 20, (char *)minimap_sprite[1]);  // draws mob room
00140     }
00141     if (rooms[j][i]->get_doorway(0)) {  // Drawing all doorways
00142         lcd.drawLine(42 + (i-room_x)*20, 17 + (j-room_y)*15, 43 + (i-room_x)*20, 17 + (j-room_y)*15, 1);
00143     }
00144     if (rooms[j][i]->get_doorway(1)) {
00145         lcd.drawLine(52 + (i-room_x)*20, 23 + (j-room_y)*15, 52 + (i-room_x)*20, 24 + (j-room_y)*15, 1);
00146     }
00147     if (rooms[j][i]->get_doorway(2)) {
00148         lcd.drawLine(42 + (i-room_x)*20, 31 + (j-room_y)*15, 43 + (i-room_x)*20, 31 + (j-room_y)*15, 1);
00149     }
00150     if (rooms[j][i]->get_doorway(3)) {
00151         lcd.drawLine(33 + (i-room_x)*20, 23 + (j-room_y)*15, 33 + (i-room_x)*20, 24 + (j-room_y)*15, 1);
00152     }
00153 }
00154 
00155 void game_over()
00156 {
00157     lcd.clear();
00158     lcd.setContrast(global_contrast);
00159     lcd.printString("Game Over", 0, 0);     
00160 }
00161 
00162 void win()
00163 {
00164     lcd.clear();
00165     lcd.setContrast(global_contrast);
00166     lcd.printString("You won!", 0, 0);   
00167 }
00168 
00169 void display_stats()
00170 {
00171     lcd.printString("Restart?", 0, 1);   
00172     lcd.printString("Enemies Killed:", 0, 2);
00173     char kills[10];
00174     sprintf(kills, "%d enemies", number_of_enemies_killed);
00175     lcd.printString(kills, 0, 3);
00176     lcd.printString("Time:", 0, 4);
00177     char total_duration[10];
00178     sprintf(total_duration, "%d seconds", (total_time/40));
00179     lcd.printString(total_duration, 0, 5);
00180     lcd.refresh();
00181     while(gamepad.check_event(Gamepad::A_PRESSED)) {
00182     }
00183     wait(0.05);
00184     while(!gamepad.check_event(Gamepad::A_PRESSED)) {
00185     }
00186     wait(0.05);
00187     while(gamepad.check_event(Gamepad::A_PRESSED)) {
00188     }
00189 }
00190 
00191 int available_boss_room()
00192 {
00193     if (!valid_rooms[room_y - 1][room_x]){  // if any of the adjacent room is invalid, it is replaced with a boss room
00194         rooms[room_y][room_x]->set_doorway(0, true);
00195         set_boss_room(room_y - 1, room_x, 0);
00196         return 0;
00197     } else if (!valid_rooms[room_y][room_x + 1]){
00198         rooms[room_y][room_x]->set_doorway(1, true);
00199         set_boss_room(room_y, room_x + 1, 1);
00200         return 1;
00201     } else if (!valid_rooms[room_y + 1][room_x]){
00202         rooms[room_y][room_x]->set_doorway(2, true);
00203         set_boss_room(room_y + 1, room_x, 2);
00204         return 2;
00205     } else if (!valid_rooms[room_y][room_x - 1]){
00206         rooms[room_y][room_x]->set_doorway(3, true);
00207         set_boss_room(room_y, room_x - 1, 3);
00208         return 3; }
00209     delete rooms[room_y - 1][room_x];   // if all adjacent room is valid, mutate the top room into a boss room (default case)
00210     rooms[room_y][room_x]->set_doorway(3, true);
00211     set_boss_room(room_y - 1, room_x, 0);
00212     return 0;
00213 }
00214 
00215 void set_boss_room(int room_y, int room_x, int side)
00216 {
00217     valid_rooms[room_y][room_x] = true;
00218     rooms[room_y][room_x] = new Room(0, 10);
00219     rooms[room_y][room_x]->set_doorway(opposite(side), true);   // Sets a definite doorway on the side player comes from
00220     if ((opposite(side) != 0) && (valid_rooms[room_y - 1][room_x])){ // Deletes any existing doorways unless player entered from that side
00221         if (rooms[room_y - 1][room_x]->get_doorway(2)){
00222             rooms[room_y - 1][room_x]->set_doorway(2, false);
00223     }}
00224     if ((opposite(side) != 1) && (valid_rooms[room_y][room_x + 1])){
00225         if (rooms[room_y][room_x + 1]->get_doorway(3)){
00226             rooms[room_y][room_x + 1]->set_doorway(3, false);
00227     }}
00228     if ((opposite(side) != 2) && (valid_rooms[room_y + 1][room_x])){
00229         if (rooms[room_y + 1][room_x]->get_doorway(0)){
00230             rooms[room_y + 1][room_x]->set_doorway(0, false);
00231     }}
00232     if ((opposite(side) != 3) && (valid_rooms[room_y][room_x - 1])){
00233         if (rooms[room_y][room_x - 1]->get_doorway(1)){
00234             rooms[room_y][room_x - 1]->set_doorway(1, false);
00235     }}
00236 }
00237 
00238 void game_unload()
00239 {
00240     delete room_engine;
00241     // Deletes every generated rooms
00242     for (int i = 0; i < MAX_ROOMS_MAP_X; i++) { 
00243         for (int j = 0; j < MAX_ROOMS_MAP_Y; j++) {
00244             if (valid_rooms[j][i]){
00245                 delete rooms[j][i];
00246                 valid_rooms[j][i] = false;
00247             }
00248         }
00249     }
00250     delete player;
00251 }
00252 
00253 // Functions
00254 int opposite(int value)
00255 {
00256     if (value <= 1) {
00257         return value + 2;
00258     } else {
00259         return value - 2;
00260     }
00261 }
00262 
00263 int count_doorways()    // counts number of exisisting doorways
00264 {
00265     int count = 0;
00266     for (int i = 0; i < 4; i++){
00267         if (rooms[room_y][room_x]->get_doorway(i)) {
00268             count++;
00269         }
00270     }
00271     return count;
00272 }
00273 
00274 void update_definite_doorways()
00275 {
00276     update_definite_doorways_up();
00277     update_definite_doorways_right();
00278     update_definite_doorways_down();
00279     update_definite_doorways_left();
00280 }
00281 
00282 void update_definite_doorways_up()
00283 {
00284     if (room_y == 1) {  // if room to be generated is on the border, then doorway cannot exist
00285         cannot[0] = true;
00286         have_to[0] = false;
00287     } else if (valid_rooms[room_y - 1][room_x]){    // if room to be generated has an existing room above it
00288         if (rooms[room_y - 1][room_x]->get_doorway(2)){ // if room to be generated has an existing doorway, then doorway must exist
00289             have_to[0] = true;
00290             cannot[0] = false;
00291         } else {    // if room to be generated does not have an existing doorway, then doorway must not exist
00292             have_to[0] = false;
00293             cannot[0] = true;
00294         }
00295     } else {    // else the room does not have any definite doorways set on it's north
00296         have_to[0] = false;
00297         cannot[0] = false;
00298     }
00299 }
00300 void update_definite_doorways_right()
00301 {
00302     if (room_x == 10) { // if room to be generated is on the border, then doorway cannot exist
00303         cannot[1] = true;
00304         have_to[1] = false;
00305     } else if (valid_rooms[room_y][room_x + 1]){    // if room to be generated has an existing room on it's right
00306         if (rooms[room_y][room_x + 1]->get_doorway(3)){ // if room to be generated has an existing doorway, then doorway must exist
00307             have_to[1] = true;
00308             cannot[1] = false;
00309         } else {    // if room to be generated does not have an existing doorway, then doorway must not exist
00310             have_to[1] = false;
00311             cannot[1] = true;
00312         }
00313     } else {    // else the room does not have any definite doorways set on it's right
00314         have_to[1] = false;
00315         cannot[1] = false;
00316     }
00317 }
00318 
00319 void update_definite_doorways_down()
00320 {
00321     if (room_y == 10) { // if room to be generated is on the border, then doorway cannot exist
00322         cannot[2] = true;
00323         have_to[2] = false;
00324     } else if (valid_rooms[room_y + 1][room_x]){    // if room to be generated has an existing room below it
00325         if (rooms[room_y + 1][room_x]->get_doorway(0)){ // if room to be generated has an existing doorway, then doorway must exist
00326             have_to[2] = true;
00327             cannot[2] = false;
00328         } else {    // if room to be generated does not have an existing doorway, then doorway must not exist
00329             have_to[2] = false;
00330             cannot[2] = true;
00331         }
00332     } else {    // else the room does not have any definite doorways set on it's south
00333         have_to[2] = false;
00334         cannot[2] = false;
00335     }
00336 }
00337 
00338 void update_definite_doorways_left()
00339 {
00340     if (room_x == 1) {  // if room to be generated is on the border, then doorway cannot exist
00341         cannot[3] = true;
00342         have_to[3] = false;
00343     } else if (valid_rooms[room_y][room_x - 1]){    // if room to be generated has an existing room on it's left
00344         if (rooms[room_y][room_x - 1]->get_doorway(1)){ // if room to be generated has an existing doorway, then doorway must exist
00345             have_to[3] = true;
00346             cannot[3] = false;
00347         } else {    // if room to be generated does not have an existing doorway, then doorway must not exist
00348             have_to[3] = false;
00349             cannot[3] = true;
00350         }
00351     } else {    // else the room does not have any definite doorways set on it's left
00352         have_to[3] = false;
00353         cannot[3] = false;
00354     }
00355 }