#include #include #include #include #include #define X_MAX 80 #define Y_MAX 23 #define ROOMS 8 #define ROOM_SIZE 7 #define ENEMIES_IN_LEVEL 5 #define HP_MAX 50 #define MAX_POTIONS_PER_FLOOR 5 #define WALL 0xB2 #define EMPTY 0xFF #define PLAYER 0x02 #define ENEMY 'X' #define EXIT '>' #define DOUBLELINE 0xCD #define ITEM_SMALL_POTION 'p' #define ITEM_MEDIUM_POTION 'n' #define ITEM_BIG_POTION 'm' using namespace std; //Mappa del gioco unsigned char map[X_MAX][Y_MAX]; //Numero del piano raggiunto dal giocatore int depth = 1; //Inventario del giocatore int pozioni_vita_piccole = 3; int pozioni_vita_medie = 2; int pozioni_vita_grandi = 1; //Devo mettere due volte draw perchè ha bisogno della classe Player, a cui però serve la funzione draw. Idem per l'inventario... void draw(); void inventory(); //Classe entità generica, sia nemico sia giocatore class Entity { public: int x; int y; int hp; int move(); }; //Classe del giocatore class Player : public Entity { public: int hp = HP_MAX; int move() { bool waiting = true; //Rileva i tasti freccia while(waiting) { unsigned char input = getch(); if(input == 224) { switch(getch()) { case 72: //Freccia su if(map[x][y-1] == EMPTY) { map[x][y] = EMPTY; map[x][y-1] = PLAYER; y--; waiting = false; } else if(map[x][y-1] == ITEM_SMALL_POTION) { map[x][y] = EMPTY; map[x][y-1] = PLAYER; y--; pozioni_vita_piccole++; waiting = false; } else if(map[x][y-1] == ITEM_MEDIUM_POTION) { map[x][y] = EMPTY; map[x][y-1] = PLAYER; y--; pozioni_vita_medie++; waiting = false; } else if(map[x-1][y-1] == ITEM_BIG_POTION) { map[x][y] = EMPTY; map[x][y-1] = PLAYER; y--; pozioni_vita_grandi++; waiting = false; } else if(map[x][y-1] == EXIT) { return 1; } break; case 80: //Freccia giù if(map[x][y+1] == EMPTY) { map[x][y] = EMPTY; map[x][y+1] = PLAYER; y++; waiting = false; } else if(map[x][y+1] == ITEM_SMALL_POTION) { map[x][y] = EMPTY; map[x][y+1] = PLAYER; y++; pozioni_vita_piccole++; waiting = false; } else if(map[x][y+1] == ITEM_MEDIUM_POTION) { map[x][y] = EMPTY; map[x][y+1] = PLAYER; y++; pozioni_vita_medie++; waiting = false; } else if(map[x-1][y] == ITEM_BIG_POTION) { map[x][y] = EMPTY; map[x][y+1] = PLAYER; y++; pozioni_vita_grandi++; waiting = false; } else if(map[x][y+1] == EXIT) { return 1; } break; case 75: //Freccia sinistra if(map[x-1][y] == EMPTY) { map[x][y] = EMPTY; map[x-1][y] = PLAYER; x--; waiting = false; } else if(map[x-1][y] == ITEM_SMALL_POTION) { map[x][y] = EMPTY; map[x-1][y] = PLAYER; x--; pozioni_vita_piccole++; waiting = false; } else if(map[x-1][y] == ITEM_MEDIUM_POTION) { map[x][y] = EMPTY; map[x-1][y] = PLAYER; x--; pozioni_vita_medie++; waiting = false; } else if(map[x-1][y] == ITEM_BIG_POTION) { map[x][y] = EMPTY; map[x-1][y] = PLAYER; x--; pozioni_vita_grandi++; waiting = false; } else if(map[x-1][y] == EXIT) { return 1; } break; case 77: //Freccia destra if(map[x+1][y] == EMPTY) { map[x][y] = EMPTY; map[x+1][y] = PLAYER; x++; waiting = false; } else if(map[x+1][y] == ITEM_SMALL_POTION) { map[x][y] = EMPTY; map[x+1][y] = PLAYER; x++; pozioni_vita_piccole++; waiting = false; } else if(map[x+1][y] == ITEM_MEDIUM_POTION) { map[x][y] = EMPTY; map[x+1][y] = PLAYER; x++; pozioni_vita_medie++; waiting = false; } else if(map[x+1][y] == ITEM_BIG_POTION) { map[x][y] = EMPTY; map[x+1][y] = PLAYER; x++; pozioni_vita_grandi++; waiting = false; } else if(map[x+1][y] == EXIT) { return 1; } break; } } else if(input == 's') //S { //Salta un turno waiting = false; } else if(input == 'i') //I { //Apri l'inventario inventory(); //Torna alla mappa draw(); } } return 0; } } player; //Classe dei nemici class Enemy : public Entity { public: int move() { //Se intorno c'è il giocatore if(map[x-1][y] == PLAYER || map[x+1][y] == PLAYER || map[x][y-1] == PLAYER || map[x][y+1] == PLAYER) { //Forse sarebbe meglio fare una funzione per togliere vita che controlla anche se va a 0... player.hp--; } else { //Muoviti in una direzione casuale bool moving = true; while(moving) { int direction = rand() % 4; switch(direction) { case 0: //Sinistra if(map[x-1][y] == EMPTY) { map[x][y] = EMPTY; map[x-1][y] = ENEMY; x--; moving = false; } break; case 1: //Destra if(map[x+1][y] == EMPTY) { map[x][y] = EMPTY; map[x+1][y] = ENEMY; x++; moving = false; } break; case 2: //Su if(map[x][y-1] == EMPTY) { map[x][y] = EMPTY; map[x][y-1] = ENEMY; y--; moving = false; } break; case 3: //Giù if(map[x][y+1] == EMPTY) { map[x][y] = EMPTY; map[x][y+1] = ENEMY; y++; moving = false; } break; } } } } }; //Cura il giocatore di x void heal(int x) { if(player.hp + x > HP_MAX) { player.hp = HP_MAX; } else { player.hp += x; } } //Aggiorna la console con la situazione corrente del gioco. void draw() { //Svuota lo schermo della console. Sono sicuro che ci sia un modo molto migliore per farlo, ma non mi viene in mente... system("cls"); for(int y=0; y 0) { cout << pozioni_vita_piccole << "x Pozione di Vita (p)iccola\tRipristina 10 Vita\n"; } else { cout << '\n'; } if(pozioni_vita_medie > 0) { cout << pozioni_vita_medie << "x Pozione di Vita (n)ormale\tRipristina 20 Vita\n"; } else { cout << '\n'; } if(pozioni_vita_grandi > 0) { cout << pozioni_vita_grandi << "x Pozione di Vita (m)aggiore\tRipristina 50 Vita\n"; } else { cout << '\n'; } //Selezione dell'oggetto da usare. cout << "Scrivi la lettera corrispondente all'oggetto che vuoi usare.\n"; while(true) { //Effetto degli oggetti unsigned char selezione = getch(); if(selezione == 112) //p { if(pozioni_vita_piccole > 0) { pozioni_vita_piccole--; heal(10); break; } } else if(selezione == 110) //n { if(pozioni_vita_medie > 0) { pozioni_vita_medie--; heal(20); break; } } else if(selezione == 109) //m { if(pozioni_vita_grandi > 0) { pozioni_vita_grandi--; heal(50); break; } } } } //Funzioni per la generazione della mappa //Inizializza la mappa con spazi vuoti void init() { for(int y=0; y end_y) { for(int y=end_y; y<=start_y; y++) { map[start_x][y] = EMPTY; } } else { for(int y=start_y; y<=end_y; y++) { map[start_x][y] = EMPTY; } } if(start_x > end_x) { for(int x=end_x; x<=start_x; x++) { map[x][end_y] = EMPTY; } } else { for(int x=start_x; x<=end_x; x++) { map[x][end_y] = EMPTY; } } } else { if(start_x > end_x) { for(int x=end_x; x<=start_x; x++) { map[x][start_y] = EMPTY; } } else { for(int x=start_x; x<=end_x; x++) { map[x][start_y] = EMPTY; } } if(start_y > end_y) { for(int y=end_y; y<=start_y; y++) { map[end_x][y] = EMPTY; } } else { for(int y=start_y; y<=end_y; y++) { map[end_x][y] = EMPTY; } } } } //Genera il livello void generate(Enemy* list[ENEMIES_IN_LEVEL]) { int corridor_x; int corridor_y; //Creazione delle stanze for(int r=0; r 0) { int link_x = rand() % size_x + 1 + start_x; int link_y = rand() % size_y + 1 + start_y; corridor(link_x, link_y, corridor_x, corridor_y, rand() % 2); } corridor_x = rand() % size_x + start_x; corridor_y = rand() % size_y + start_y; //Posiziona il giocatore se è l'ultima stanza if(r == ROOMS - 1) { map[corridor_x][corridor_y] = PLAYER; player.x = corridor_x; player.y = corridor_y; } } //Posizionamento nemici for(int e=0; ex = x; created->y = y; list[e] = created; break; } } } //Posizionamento uscita while(true) { int x = rand() % (X_MAX - 1) + 1; int y = rand() % (Y_MAX - 1) + 1; if(map[x][y] == EMPTY) { map[x][y] = EXIT; break; } } //Posizionamento pozioni di vita int placed_potions = 0; int potions_in_floor = rand() % MAX_POTIONS_PER_FLOOR + 1; while(placed_potions < potions_in_floor) { int x = rand() % (X_MAX - 1) + 1; int y = rand() % (Y_MAX - 1) + 1; int size = rand() % 100; if(map[x][y] == EMPTY) { if(size < 60) { map[x][y] = ITEM_SMALL_POTION; } else if(size > 90) { map[x][y] = ITEM_BIG_POTION; } else { map[x][y] = ITEM_MEDIUM_POTION; } placed_potions++; } } cout << player.x << '|' << player.y; } //Processa il resto di un turno, dopo il movimento del giocatore. void tick(Enemy* list[ENEMIES_IN_LEVEL]) { for(int e=0; emove(); } } int main() { Enemy* list[ENEMIES_IN_LEVEL]; //Lista di tutti i nemici nel livello srand(0); //TODO: Rendere il seed modificabile...? //Ciclo del gioco while(true) { init(); generate(list); draw(); //Ciclo di un livello while(true) { int trigger = player.move(); if(trigger == 1) //Uscita toccata { break; } tick(list); draw(); } depth++; } return 0; }