Teil 3
Wir werden mit NCurses einen kleinen Ausflug in die Spieleprogrammierung unternehmen, d.h. sprichwörtlich Bewegung in die Sache bringen, und dabei die folgenden Begrifflichkeiten kennenlernen:
Integrierte Entwicklungsumgebung (IDE):
- Verwenden von QtCreator als IDE für NCurses
- Import CMakeLists.txt as Project
- Edit, Compile & Run
- Settings: Projects → Run → Run in Terminal!
NCurses Basics:
- ASCII-Grafik: initscr(), endwin()
- C-Chars ('c') und C-Strings ("C-String" → {’C’, ‘-‘, ‘S’, … , 0} )
- Äquivalenz von C-Chars und ASCII-Code (z.B. 'a' = 97)
- Cursor-Koordinaten: move(y, x), addch('c'), refresh()
- Printing: mvprintw(y, x, "C-String")
- Attribute
- NCurses Alt-Charset
- Screen-Size: LINES, COLS
- Pause: getch(), sleep(), msleep()
- NCurses Howto
NCurses Animation:
- Game-Loop
- Game-Loop = Endlosschleife, die Frame nach Frame zeichnet
- Frames per second (fps) and Frame duration (dt = 1/fps)
- clear, render and update
- Nichtblockierende Interaktion
- curs_set(FALSE); // disable text cursor
- timeout(0); // configure getch() to be non-blocking
- noecho(); // do not echo keyboard input
- z.B.: Taste 'q' beendet den Game Loop
- Animierte Graphik mit NCurses
- sich fortbewegender Ball ('O')
- modul-lokale und
globale Variablen - globale Konstanten (z.B. LINES, COLS)
- Leapfrog: sich hin- und her-bewegender Ball
static int px = 0, py = LINES/2;
static int dx = 1;
// game loop
void game_loop()
{
while (getch() != 'q')
{
clear();
mvaddch(py, px, 'O');
px += dx;
if (dx <= 0 || dy >= COLS-1) dx = -dx;
msleep(100); // 100ms = 10 fps
}
}
// main function
int main()
{
// init
initscr();
timeout(0);
// start game loop
game_loop();
// restore initial window
endwin();
return(0);
}
Links:
- https://de.wikibooks.org/wiki/Ncurses:_Grundlegendes
- https://www.viget.com/articles/game-programming-in-c-with-the-ncurses-library/
- https://www.linuxjournal.com/content/getting-started-ncurses
Hilfsfunktion:
#include <unistd.h> // sleep for a period of time given in milli seconds (ms) void msleep(float ms) { int us = ms*1000; // micro secs usleep(us); }
Praktikum:
Reproduzieren Sie nach dem Beispiel der Vorlesung mit NCurses ein Programm, welches einen fliegenden Vogel zeigt, wie z.B. folgenden ASCII-Art Vogel:
\ |\ >====O- |/ /
Und nun zeichnen wir einen zweiten Vogel, der z.B. nicht von links nach rechts fliegt, sondern von rechts nach links.
Optional: Versuchen Sie die Flügel schlagen zu lassen!
Was sie nun implementiert haben, sind zwei sog. Sprites.
Hint: Am praktischsten wäre ein neues Modul, das eine neue Funktion print_bird(int y, int x) enthält, wobei y und x die Koordinaten (d.h. die linke obere Ecke) des zu zeichnenden Vogels sind. Diese Koordinaten kann man dann im Game-Loop übergeben und animieren. Aufruf von print_bird je einmal pro Frame und zu zeichnendem Vogel.
Protokoll:
Beschreiben Sie mit Ihren eigenen Worten die Begriffe global, modul-lokal, lokal, ASCII-Code, C-String, Game-Loop, Animation und Leap-Frog in Ihrem Ãœbungsprotokoll.
Nehmen Sie in Ihr Protokoll zwei Screenshots der obigen NCurses Anwendung auf, auf denen die Animation erkennbar ist! Wieviele Dateien mit Source-Code und wieviele Zeilen Code haben Sie nun?