#include <curses.h> in your
.cpp files, and you need to compile with the -l ncurses
compiler flag, like g++ lab11v1.cpp -l ncurses.
Create and compile lab11v1.cpp under your account. This source code demonstrates some simple aspects of ncurses. Here's a few comments:
| Initializing Ncurses | Exiting Ncurses | Drawing something |
WINDOW *W = initscr(); cbreak(); noecho(); nodelay(W,true); curs_set(0); |
// Loop forever until user enters 'q' char c; while((c = wgetch(W)) && c != 'q'); // Clean up after ncurses endwin(); |
wmove(W,0,0); waddch(W,'1'); wrefresh(W); usleep(800000); |
This code should appear at the point in your main
when you're ready to go into "ncurses mode". When this
is executed, the screen goes blank and you are ready to
write to arbitrary locations in the terminal window.
The variable W is important. It's a
pointer to a struct object that the ncurses library
defines. You'll need to pass W to many
ncurses functions.
|
Ncurses (at least as we've initialized it) changes the
model for how we read data. You fetch the next
character with a call to wgetch(W). The
funny thing is that this is "non-blocking I/O", which
means that you don't hang around and wait for input to
come. If you call wgetch(W) and nobody
presses a key, wgetch simply returns immediate with an
error code. Contrast this with cin >> c
or cin.get(). Thus, this loop just spins
waiting for wgetch(W) to report that the user has
pressed q. The endwin() function call is
required in order for ncurses to clean up after itself
and restore the terminal window.
|
The model for writing to the screen in ncurses is this:
|
usleep(tus) (defined
in unistd.h), which is like the sleep(s) function
we've used before, except with finer resolution. The argument
is the tiume to sleep given in micro-seconds.
4 a (10,15) x (14,29) k (5,5) q (18,37)
curs_set(0);Note that this call must come after the call to
initscr().
do {
// draw character
// sleep for 100,000 usecs
// use wgetch to see if the user has pressed 'q'
// move character one step in its current direction
}while('q' has not been pressed);
Of course at this point your character moves off the screen and
things are not that interesting. So, to add a little drama
let's say that at each step, right before actually moving, the
character has a 1-in-10 chance of randomly turning
(i.e. changing its current direction) before moving, with a
50% chance of turning 90 left and a 50% chance of turning 90
degrees to the right.
int getmaxyx(Window *W, int &row, int & col);So the call
getmaxyx(W,height,width) sets height to
the number of rows on the screen, and width to the number of
columns. Note, then, that the valid positions you can
wmove(W,row,col) to are when 0 ≤ row < height
and 0 ≤ col < width.
Now that you can get the height and width of the terminal window, when you come to a "move" step you must check to see whether the move in question would take you off the screen. If it does, then instead of moving change direction and leave it at that. You can either randomly change direction, or "bounce" by simply reversing direction (north goes to south, east to west, etc). If you do this, your character will be walled in and will never leave the terminal window.
char kb = wgetch(W);... and if kb is an 'a', change the one character's direction to west, a 'd', change it to east, an 's' change it to south, and a 'w', change it to north. Note that this one character won't be subject to the random direction changes, and we won't worry about the walls for him ... it'll be up to the user to keep the player on the board.