Roguelike AoC – part 5
A fifth lesson of roguelike game tutorial was trivial and concentrated only on substituting X and Y position values with new struct named Position. The only logical changes were related to that. For the time being author did not go for all-in solution to use this struct everywhere (in the already existing methods), however I think it’s a wise decision considering changes that are still ahead. Doors, connections between rooms, monsters/items locations – code can be always changed in the future.
Code
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <curses.h> const char *WALL_SIGN = "#"; const char *FLOOR_SIGN = "."; const char *PLAYER_SIGN = "@"; typedef struct Position { int x; int y; } Position; typedef struct Room { Position position; int height; int width; } Room; typedef struct Player { Position position; int health; } Player; enum Direction {DIRECTION_NW, DIRECTION_N, DIRECTION_NE, DIRECTION_W, DIRECTION_E, DIRECTION_SW, DIRECTION_S, DIRECTION_SE}; // Config and bootstrap methods int screenSetup(void); Room **mapSetup(void); // Player methods Player *playerSetup(void); int playerMove(Player *user, enum Direction dir); int playerDraw(Player *user); // Room methods Room* createRoom(int y, int x, int height, int width); int drawRoom(Room *room); // Other methods int handleInput(char, Player *user); bool canGoToPosition(int y, int x); int main() { Player *user; char keyPressed; screenSetup(); mapSetup(); user = playerSetup(); /* Main game loop */ while((keyPressed = getch()) != 'q') { handleInput(keyPressed, user); } endwin(); return 0; } Player *playerSetup(void) { Player *newPlayer = malloc(sizeof(Player)); newPlayer->position.x = 14; newPlayer->position.y = 14; newPlayer->health = 20; playerDraw(newPlayer); return newPlayer; } int screenSetup(void) { initscr(); printw("Roguelike game!"); noecho(); refresh(); return 0; } Room **mapSetup(void) { Room **rooms = malloc(sizeof(Room)*3); rooms[0] = createRoom(13, 13, 6, 9); drawRoom(rooms[0]); rooms[1] = createRoom(13, 30, 6, 9); drawRoom(rooms[1]); rooms[2] = createRoom(25, 13, 6, 12); drawRoom(rooms[2]); return rooms; } Room *createRoom(int y, int x, int height, int width) { Room *newRoom = malloc(sizeof(Room)); newRoom->position.y = y; newRoom->position.x = x; newRoom->height = height; newRoom->width = width; return newRoom; } int drawRoom(Room *room) { int x, y; // Draw top and bottom for(x = room->position.x; x < room->position.x + room->width; x++) { mvprintw(room->position.y, x, WALL_SIGN); mvprintw(room->position.y + room->height - 1, x, WALL_SIGN); } // Draw floors and side walls for(y = room->position.y + 1; y < room->position.y + room->height - 1; y++) { // Draw side walls mvprintw(y, room->position.x, WALL_SIGN); mvprintw(y, room->position.x + room->width - 1, WALL_SIGN); // Draw floor inside specific row for(x = room->position.x + 1; x < room->position.x + room->width - 1; x++) { mvprintw(y, x, FLOOR_SIGN); } } return 0; } int handleInput(char keyPressed, Player *user) { switch (keyPressed) { // move up case 'w': case 'W': playerMove(user, DIRECTION_N); break; // move left case 'a': case 'A': playerMove(user, DIRECTION_W); break; // move right case 'd': case 'D': playerMove(user, DIRECTION_E); break; // move down case 's': case 'S': playerMove(user, DIRECTION_S); break; default: break; } return 0; } int playerMove(Player *user, enum Direction direction) { int possibleX = user->position.x; int possibleY = user->position.y; switch (direction) { // move up case DIRECTION_N: possibleY -= 1; break; // move left case DIRECTION_W: possibleX -= 1; break; // move right case DIRECTION_E: possibleX += 1; break; // move down case DIRECTION_S: possibleY += 1; break; default: break; // We stay in place (usually 'turn' will pass then) } // Cleanup of current position mvprintw(user->position.y, user->position.x, FLOOR_SIGN); if(canGoToPosition(possibleY, possibleX)) { user->position.y = possibleY; user->position.x = possibleX; } // We redraw the player no matter if the position changed or not playerDraw(user); return 0; } bool canGoToPosition(int y, int x) { const int ALLOWED_LOCATIONS_SIZE = 1; // Hard-coded to simplify iteration loop char allowedLocations[] = {*FLOOR_SIGN}; char locationToCheck = mvinch(y, x); for(int i = 0; i < ALLOWED_LOCATIONS_SIZE; i++) { if(locationToCheck == allowedLocations[i]) { return TRUE; } } return FALSE; } int playerDraw(Player *user) { mvprintw(user->position.y, user->position.x, PLAYER_SIGN); move(user->position.y, user->position.x); return 0; }
Leave a Reply
You must be logged in to post a comment.