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-11 19:26

Here's a better version that loads 40x20 character maps (easily changeable) from a plaintext file into the array and colorizes the map by character. Also there's working doors and improved movement code.



#include <curses.h>
#include <fstream>
using namespace std;

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

// Map array
char MapArray[MAP_HEIGHT][MAP_WIDTH];

// 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) );
      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 );

  // Load map
  ifstream file;
  file.open( "maps/start.map" );
  for(int y = 0; y < MAP_HEIGHT; y++) {
    for(int x = 0; x < MAP_WIDTH; x++) {
      file.get(MapArray[y][x]);
    }
  }
  file.close();

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

    // Refresh screen
    refresh();

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

    // 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