Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

curses roguelike starter code

Name: Anonymous 2012-06-11 9:55

found an old roguelike tutorial that teaches the basics but its code was written for some simplified windows console library. i redid the tutorial using curses for a game im working on. here is the code if anyone wants a template to experiment with roguelike stuff.

#include <curses.h>

// Map dimensions
#define MAP_WIDTH  20
#define MAP_HEIGHT 15

// Tile definitions
#define TILE_FLOOR 0
#define TILE_WALL  1
#define TILE_GRASS 2
#define TILE_OPENDOOR 3

// Map array
int MapArray[MAP_HEIGHT][MAP_WIDTH] = {
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

// Map drawing function
void DrawMap( void ) {
  for( int y = 0; y < MAP_HEIGHT; y++ ) {
   
    // Jump to next line
    move( y, 0 );
    for( int x = 0; x < MAP_WIDTH; x++ ) {
      switch( MapArray[y][x] ) {

        // Draw tiles
        case TILE_FLOOR:
          attron( COLOR_PAIR(3) );
          addch('.');
          attroff( COLOR_PAIR(3) );
        break;

        case TILE_WALL:
          addch('#');
        break;
      }
    }
  }
}

// Collision detect function
bool IsPassable( int MapX, int MapY ) {

  // Make area outside map impassible
  if( MapX < 0 || MapX >= MAP_WIDTH || MapY < 0 || MapY >= MAP_HEIGHT )
  return false;

  // Store the value of the tile specified
  int TileValue = MapArray[MapY][MapX];

  // Return true if it's passable
  if( TileValue == TILE_FLOOR || TileValue == TILE_GRASS || TileValue == TILE_OPENDOOR )
  return true;

  // If execution gets here, it's not passable
  return false;
}


int main( void ) {

  // Init curses
  keypad( initscr(), 1 );
  curs_set( 0 );

  // Init colors
  start_color();
  init_pair( 1, COLOR_RED, COLOR_BLACK );
  init_pair( 2, COLOR_YELLOW, COLOR_BLACK );
  init_pair( 3, COLOR_GREEN, COLOR_BLACK );
  init_pair( 4, COLOR_BLUE, COLOR_BLACK );

  // Init start position
  int PlayerX = 4;
  int PlayerY = 4;

  // Game Loop
  while( true ) {

    // Refresh screen
    refresh();

    // Draw map
    DrawMap();
   
    // Draw player
    attron( COLOR_PAIR(2) );
    mvaddch( PlayerY, PlayerX, '@' );
    attroff( COLOR_PAIR(2) );

    // Wait for input
    char PlayerKey = getch();

    // Process input
    switch( PlayerKey ) {

      case 'k': // Up
        if( IsPassable( PlayerX, PlayerY - 1 ) ) {
          PlayerY--;
        }
      break;

      case 'j': // Down
        if( IsPassable( PlayerX, PlayerY + 1 ) ) {
          PlayerY++;
        }
      break;

      case 'h': // Left
        if( IsPassable( PlayerX - 1, PlayerY ) ) {
          PlayerX--;
        }
      break;

      case 'l': // Right
        if( IsPassable( PlayerX + 1, PlayerY ) ) {
          PlayerX++;
        }
      break;

      case 'q': // Quit
      return endwin();
    }
  }
}

Name: Anonymous 2012-06-12 14:59

here is a working version of the code with a hardcoded map for simplicity and placeholders for text windows and all that. to person talking about 'pause', i dont know where you saw that because this code depends on nothing but curses, which is available on any platform.


#include <curses.h>

// Map dimensions
#define MAP_WIDTH  40
#define MAP_HEIGHT 24

// Map array
char MapArray[MAP_HEIGHT][MAP_WIDTH + 1]={

"^^*^*^^^********************************",
"^*^^^^**********************Y***********",
"^^^***************Y******Y**************",
"*^********************************Y*****",
"^^*****#######*********Y****************",
"^******#.....#**************Y***********",
"*******#.....#**************************",
"*******#.....#**************************",
"**Y****###+###*******~~~~~*********Y****",
"*******************~~~~~~~~*************",
"*******************~~~~~~~~*************",
"*********************~~~~~***Y**********",
"****Y***********************************",
"****************************************",
"***********************************Y****",
"****************************************",
"*********************####+#####*********",
"***************Y*****#........#*********",
"****Y****************#........#*********",
"*********************##+###...#**Y******",
"************Y********#....#...#*********",
"*********************#....#...#*******Y*",
"*******Y*************##########*********",
"****************************************"
};

// Map drawing function
void DrawMap( void ) {
  for( int y = 0; y < MAP_HEIGHT; y++ ) {
    for( int x = 0; x < MAP_WIDTH; x++ ) {
      if( MapArray[y][x] == '*' ) // Green grass
        attron( COLOR_PAIR(3) );
      if( MapArray[y][x] == '~' ) // Blue water
        attron( COLOR_PAIR(4) );
      if( MapArray[y][x] == 'Y' ) // Brown tree
        attron( COLOR_PAIR(2) );
      if( MapArray[y][x] == '^' ) // Red mountain
        attron( COLOR_PAIR(1) );
      if( MapArray[y][x] == '+' ) // Brown door closed
        attron( COLOR_PAIR(2) );
      if( MapArray[y][x] == '/' ) // Brown door open
        attron( COLOR_PAIR(2) );
      mvaddch(y, x, MapArray[y][x]);
      attroff( COLOR_PAIR(2) );   // Reset color
    }
  }
}

// Collision detect function
bool IsPassable( int MapX, int MapY ) {

  // Make area outside map impassible
  if( MapX < 0 || MapX >= MAP_WIDTH || MapY < 0 || MapY >= MAP_HEIGHT )
  return false;

  int Ch = MapArray[MapY][MapX];

  // Check which characters are passible.
  if( Ch == '.' || Ch == '*' || Ch == '/' )
  return true;

  // Otherwise not passible
  return false;
}


int main( void ) {

  // Init curses
  keypad( initscr(), 1 );
  curs_set( 0 );

  // Init colors
  start_color();
  init_pair( 1, COLOR_RED, COLOR_BLACK );
  init_pair( 2, COLOR_YELLOW, COLOR_BLACK );
  init_pair( 3, COLOR_GREEN, COLOR_BLACK );
  init_pair( 4, COLOR_BLUE, COLOR_BLACK );
  init_pair( 5, COLOR_CYAN, COLOR_BLACK );
  init_pair( 6, COLOR_MAGENTA, COLOR_BLACK );

  // Init start position
  int PlayerX = 9;
  int PlayerY = 5;
 
 // Game Loop
  while( true ) {

    // Refresh screen
    refresh();

    // Draw map
    DrawMap();
   
    // Draw player
    attron( COLOR_PAIR(5) );
    mvaddch( PlayerY, PlayerX, '@' );
    attroff( COLOR_PAIR(5) );

    // Info screen
    mvprintw(0, 41, "[name] the [title]");

    attron( COLOR_PAIR(1) );
    mvprintw(2, 41, "Life: xxx/xxx");
    attroff( COLOR_PAIR(1) );

    attron( COLOR_PAIR(2) );
    mvprintw(3, 41, "Level: xx");
    attroff( COLOR_PAIR(2) );

    attron( COLOR_PAIR(3) );
    mvprintw(2, 66, "Mana: xxx/xxx");
    attroff( COLOR_PAIR(3) );

    attron( COLOR_PAIR(5) );
    mvprintw(3, 66, "Exp: xxxxxxxx");
    attroff( COLOR_PAIR(5) );

    // Inventory screen
    mvprintw(5, 41, "---------------------------- Inventory");

    // Message screen
    mvprintw(16,41, "----------------------------- Messages\n");
    // Wait for input
    char PlayerKey = getch();

    // Process the input
    int DeltaX, DeltaY;

    switch( PlayerKey ) {

      // Move up
      case 'k':
        DeltaX = 0;
        DeltaY = -1;
        break;

      // Move left
      case 'h':
        DeltaX = -1;
        DeltaY = 0;
        break;

      // Move right
      case 'l':
        DeltaX = 1;
        DeltaY = 0;
        break;

      // Move down
      case 'j':
        DeltaX = 0;
        DeltaY = 1;
        break;

      // Quit
      case 'q':
        return endwin();
    }

    // Check if direction is passable
    if( IsPassable(PlayerX + DeltaX, PlayerY + DeltaY) ) {
      PlayerX += DeltaX;
      PlayerY += DeltaY;
    }

    // Open doors
    if( MapArray[PlayerY + DeltaY][PlayerX + DeltaX] == '+' ) {
      MapArray[PlayerY + DeltaY][PlayerX + DeltaX] = '/';
    }
  }
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List