Teil 3
← C Teil 2: Implementierung & Prototyp | ● | C Teil 4: Modularisierung →
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
- Tastendruck: getch() (siehe auch “man pages”)
- Pause: sleep(), msleep()=]
- NCurses Howto
NCurses Animation:
- Game-Loop
- Game-Loop = Endlosschleife, die Frame um Frame zeichnet
- Frames per second (fps) and Frame duration (dt = 1/fps)
- clear, render and update
- Nichtblockierende Interaktion mit getch()
- 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:
- schrittweise Animation anhand von Deltas
- z.B. ein sich hin- und her-bewegender Ball
Main:
int main()
{
// init
initscr();
timeout(0);
// start game loop
game_loop();
// restore initial window
endwin();
return(0);
}
Game-Loop:
static int px = 0, py = 0;
static int dx = 1;
// game loop
void game_loop()
{
px = COLS/2;
py = LINES/2;
while (getch() != 'q')
{
clear();
mvaddch(py, px, '*');
px += dx;
if (px <= 0 || px >= COLS-1) dx = -dx;
msleep(100); // 100ms = 10 fps
}
}
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
Praktikum:
Reproduzieren Sie nach dem Beispiel der Vorlesung mit NCurses ein Programm, welches einen fliegenden Vogel zeigt, wie z.B. folgenden als C-String definierten ASCII-Art Vogel:
" _ _ " " ~( v )~ " " ' ' "
Und nun zeichnen wir einen zweiten Vogel, der z.B. nicht von links nach rechts fliegt, sondern von rechts nach links.
Lassen Sie die Flügel schlagen, indem Sie Sich in einer weiteren modul-lokalen Variable den Zustand der Flügel merken und abhängig davon die Graphik wechseln:
" _ _ " " /( v )\\ " " ' ' "
Was sie nun implementiert haben, sind zwei sog. Sprites.
Hint: Am praktischsten ist ein neues Modul, das neben dem Game-Loop eine weitere neue Funktion print_bird(int y, int x, bool f)
enthält, wobei y und x die Koordinaten (d.h. die linke obere Ecke) des zu zeichnenden Vogels sind und f der Zustand der Flügel (true=oben, false=unten). Diese Koordinaten bzw. Parameter kann man dann im Game-Loop mit Hilfe von modul-lokalen Variablen wie px und py animieren, so dass jeweils ein Aufruf von print_bird
mit den passenden Parametern pro Frame und pro zu zeichnendem Vögelchen erfolgt.
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 den im Vergleich zur letzten Übung neu dazugekommenen Code auf. Und zusätzlich mindestens zwei Screenshots der obigen NCurses Anwendung, auf denen die Animation erkennbar ist! Wieviele Dateien mit Source-Code und wieviele Zeilen Code haben Sie nun? Welche Dateien sind kein Source-Code und nur temporär erzeugt worden? Nennen Sie diese!
← C Teil 2: Implementierung & Prototyp | ● | C Teil 4: Modularisierung →