how can I write an ANSI C console screen buffer?

前端 未结 4 1475
我在风中等你
我在风中等你 2021-01-18 09:35

I\'m working on making an ASCII based game, and everywhere I look people are saying to use Console.Write() from MSDN, which is dandy and all if you\'re using Windows, but I\

4条回答
  •  猫巷女王i
    2021-01-18 10:14

    An example header and source file illustrating a way to abstract curses from the application. Gathering dust; wrote it over 15 years ago. Caveat emptor.

    cursemu.h

    /***************************************************************************
     *                                                                          
     *  DO NOT CHANGE ANYTHING BETWEEN THIS LINE AND THE NEXT LINE THAT HAS THE 
     *  WORDS "KLAATU BARRATA NIKTO" ON IT                                      
     *                                                                          
     ***************************************************************************/
    #ifndef X__CURSEMU__H                                                        
    #define X__CURSEMU__H                                                        
    
    #include 
    
    #ifdef  linux
    #define _POSIX_VERSION
    #endif                
    
    #ifndef _POSIX_VERSION
    #include     
    #define  USE_OLD_TTY  
    #include 
    #undef  USE_OLD_TTY   
    
    #ifndef  CBREAK
    #define CBREAK RAW
    #endif            
    
    #if !defined(sun) && !defined(sequent) && !defined(hpux) && \
        !defined(_AIX) && !defined(aix)                          
    #include                                          
    #define strchr index                                         
    #else                                                        
    #include                                           
    #endif                                                       
    #else                                                        
    #include                                           
    #include                                          
    #endif                                                       
    
    #include 
    #include 
    #include       
    #include  
    #include  
    #include 
    #include 
    #include      
    #include     
    
    /* Keep looking ... */
    
    int _tty_ch;
    
    #ifdef  _POSIX_VERSION
    struct termios _tty;  
    tcflag_t _res_iflg,   
        _res_lflg;        
    
    #define cbreak()(_tty.c_lflag&=~ICANON, \
      tcsetattr( _tty_ch, TCSANOW, &_tty ))  
    
    #define noecho()(_tty.c_lflag &= ~(ECHO|ICRNL), \
      tcsetattr( _tty_ch, TCSADRAIN, &_tty ))        
    
    #define savetty()((void) tcgetattr(_tty_ch, &_tty), \
      _res_iflg = _tty.c_iflag, _res_lflg = _tty.c_lflag )
    
    #define resetty()(_tty.c_iflag = _res_iflg, _tty.c_lflag = _res_lflg,\
      (void) tcsetattr(_tty_ch, TCSADRAIN, &_tty))                        
    
    #define erasechar()(_tty.c_cc[VERASE])
    #else                                 
    struct sgttyb _tty;                   
    int _res_flg;                         
    
    #define cbreak()(_tty.sg_flags|=CBREAK, ioctl(_tty_ch, TIOCSETP, &_tty))
    
    #define noecho()(_tty.sg_flags &= ~(ECHO|CRMOD), \
      ioctl( _tty_ch, TIOCSETP, &_tty ))              
    
    #define savetty()((void) ioctl(_tty_ch, TIOCGETP, &_tty), \
      _res_flg = _tty.sg_flags )                               
    
    #define resetty()(_tty.sg_flags = _res_flg, \
      (void) ioctl(_tty_ch, TIOCSETP, &_tty))    
    #define erasechar()(_tty.sg_erase)           
    #endif                                       
    
    /* KLAATU BARRATA NIKTO */
    
    #define  TERMCAP_LENGTH 1024
    
    struct CtrlSeq
    {             
      char termcap[ TERMCAP_LENGTH ];
    
      int numRows, numCols;
    
      /*  These pointers are indexes into the termcap buffer, and represent the
       *  control sequences neccessary to send to the terminal window to perform
       *  their appropriately named feature.
       */
      char *highlight,
           *endMode,            /* End highlight mode, and other modes. */
           *clearScr,
           *clearEol,
           *scrollRegion,
           *moveCursor,
           *deleteRow,
           *insertRow,
           *saveCursor,         /* Save the current cursor position */
           *restoreCursor;      /* Restore the saved cursor position */
    
      int dumbTerm,             /* 1 if the terminal is a dumb terminal */
          flush;                /* 1 if the emulation should flush stdout */
    };
    
    struct CtrlSeq ctrlSeq;
    
    #define DEFAULT_COLS    80
    #define DEFAULT_ROWS    24
    
    void ce_flush( int toSet );
    void ce_puts( char *str );
    void ce_gotoRowCol( int row, int col );
    
    void ce_writeStrRowCol( char *theText, int row, int col );
    void ce_writeStr( char *theText );
    void ce_writeCharRowCol( char theChar, int row, int col );
    void ce_writeChar( char theChar );
    
    void ce_clearScreen( void );
    void ce_clearEol( void );
    
    void ce_highlight( int on );
    void ce_scrollRegion( int row1, int row2 );
    void ce_deleteRow( int row );
    void ce_insertRow( int row );
    void ce_saveCursor( void );
    void ce_restoreCursor( void );
    
    int ce_getRows( void );
    int ce_getCols( void );
    
    #endif
    

    cursemu.c

    #include "cursemu.h"
    
    int putchar_x( int c )
    {                     
      return( putchar( c ) );
    }                        
    
    /*  Returns 0 on success, -1 on error
     */                                  
    int ce_startCurses( void )           
    {                                    
      char *ptr,                         
           tempBuff[ 1024 ];             
      int  result = 0;                   
    
      if( (ptr = (char *)getenv( "TERM" )) != NULL )
        result = tgetent( tempBuff, ptr );          
      else                                          
        result = tgetent( tempBuff, "vt100" );      
    
      if( result < 1 )
      {               
        perror( "FATAL Error: No termcap entry found (even tried vt100)!\n" );
        return( -1 );                                                         
      }                                                                       
    
      ptr = ctrlSeq.termcap;
    
      if( (ctrlSeq.numCols = tgetnum( "co" )) == -1 )
        ctrlSeq.numCols = DEFAULT_COLS;              
      if( (ctrlSeq.numRows = tgetnum( "li" )) == -1 )
        ctrlSeq.numRows = DEFAULT_ROWS;              
    
      if( (ctrlSeq.moveCursor = (char *)tgetstr( "cm", &ptr )) == NULL )
        ctrlSeq.moveCursor = (char *)tgetstr( "cl", &ptr );             
      if( (ctrlSeq.highlight = (char *)tgetstr( "mr", &ptr )) == NULL ) 
        ctrlSeq.highlight = (char *)tgetstr( "md", &ptr );              
    
      ctrlSeq.endMode       = (char *)tgetstr( "me", &ptr );
      ctrlSeq.clearEol      = (char *)tgetstr( "ce", &ptr );
      ctrlSeq.clearScr      = (char *)tgetstr( "cl", &ptr );
      ctrlSeq.scrollRegion  = (char *)tgetstr( "cs", &ptr );
      ctrlSeq.deleteRow     = (char *)tgetstr( "dl", &ptr );
      ctrlSeq.insertRow     = (char *)tgetstr( "al", &ptr );
      ctrlSeq.saveCursor    = (char *)tgetstr( "sc", &ptr );
      ctrlSeq.restoreCursor = (char *)tgetstr( "rc", &ptr );
    
      ctrlSeq.dumbTerm = (ctrlSeq.moveCursor == NULL) ||
                         (ctrlSeq.scrollRegion == NULL) ||
                         (ctrlSeq.saveCursor == NULL) ||  
                         (ctrlSeq.restoreCursor == NULL) ||
                         (ctrlSeq.clearEol == NULL);       
    
      ctrlSeq.flush = 1;
    
      if( !ctrlSeq.dumbTerm )
      {                      
        if( (_tty_ch = open( "/dev/tty", O_RDWR, 0 ) ) == -1 )
          _tty_ch = 0;                                        
    
        savetty();
        cbreak(); 
        noecho(); 
        return( 0 );
      }             
    
      return( -1 );
    }              
    
    int ce_endCurses( void )
    {                       
      ce_scrollRegion( -1, -1 );
      ce_gotoRowCol( ce_getRows() - 1, 0 );
      resetty();                           
    }                                      
    
    void ce_flush( int toSet )
    {                         
      ctrlSeq.flush = toSet;  
    
      if( toSet == 1 )
        fflush( stdout );
    }                    
    
    void ce_puts( char *str )
    {                        
      tputs( str, 0, putchar_x );
    
      if( ctrlSeq.flush )
        fflush( stdout );
    }                    
    
    void ce_gotoRowCol( int row, int col )
    {                                     
      if( row > ctrlSeq.numRows )         
        row = ctrlSeq.numRows;            
      if( col > ctrlSeq.numCols )         
        col = ctrlSeq.numCols;            
    
      ce_puts( (char *)tgoto( ctrlSeq.moveCursor, col, row ) );
    }                                                          
    
    void ce_writeStrRowCol( char *theText, int row, int col )
    {                                                        
      ce_flush( 0 );                                         
      ce_gotoRowCol( row, col );                             
      ce_writeStr( theText );                                
      ce_flush( 1 );                                         
    }                                                        
    
    void ce_writeStr( char *theText )
    {                                
      ce_flush( 0 );                 
      printf( "%s", theText );       
      ce_flush( 1 );                 
    }                                
    
    void ce_writeCharRowCol( char theChar, int row, int col )
    {                                                        
      ce_flush( 0 );                                         
      ce_gotoRowCol( row, col );                             
      ce_writeChar( theChar );                               
      ce_flush( 1 );                                         
    }                                                        
    
    void ce_writeChar( char theChar )
    {                                
      ce_flush( 0 );                 
      printf( "%c", theChar );       
      ce_flush( 1 );                 
    }                                
    
    void ce_clearScreen( void )
    {                          
      ce_puts( ctrlSeq.clearScr );
    }
    
    void ce_clearEol( void )
    {
      ce_puts( ctrlSeq.clearEol );
    }
    
    void ce_highlight( int on )
    {
      if( on == 0 )
        ce_puts( ctrlSeq.endMode );
      else
        ce_puts( ctrlSeq.highlight );
    }
    
    void ce_scrollRegion( int row1, int row2 )
    {
      ce_puts( (char *)tgoto( ctrlSeq.scrollRegion, row1, row2 ) );
    }
    
    void ce_deleteRow( int row )
    {
      ce_gotoRowCol( row, 0 );
      ce_puts( ctrlSeq.deleteRow );
    }
    
    void ce_insertRow( int row )
    {
      ce_gotoRowCol( row, 0 );
      ce_puts( ctrlSeq.insertRow );
    }
    
    void ce_saveCursor( void )
    {
      ce_puts( ctrlSeq.saveCursor );
    }
    
    void ce_restoreCursor( void )
    {
      ce_puts( ctrlSeq.restoreCursor );
    }
    
    int ce_getRows( void )
    {
      return( ctrlSeq.numRows );
    }
    
    int ce_getCols( void )
    {
      return( ctrlSeq.numCols );
    }
    

    Compiling

    Requires:

    gcc -o cursemu.o -lcurses -ltermcap
    

提交回复
热议问题