Improve user input handling and function prototypes
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 25 Apr 2023 06:19:16 +0000 (06:19 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 25 Apr 2023 06:19:16 +0000 (06:19 +0000)
MATT-README.txt
pacman.c
pacman.h

index b91c44f..a1c574f 100644 (file)
@@ -14,6 +14,7 @@ IMPROVEMENTS:
 - Use flushinp(3) instead of ad hoc getch(3) to flush input.
 - Added an atexit(3) cleanup handler for endwin(3).
 - Added hiscore/level tracking and display, now requires 33 lines.
+- More keys are accepted for movement.
 
 
 BUGFIXES:
@@ -26,6 +27,8 @@ BUGFIXES:
   one secod on Linux+glibc but that doesn't sleep on NetBSD.  These
   were replaced with sleep(1).  This affected transitions and the
   score display.
+- There were issues with input flushing, often preventing the Game
+  Over screen from displaying.
 
 
 ISSUES:
@@ -38,3 +41,5 @@ ISSUES:
   to 64-bit or other fixes.  Did not bother.
 - There are some globals in pacman.h that should really be macro
   definitions, and/or moved to the main module.
+- Uses ad-hoc command line arguments processing rather than getopt(3).
+- Should save/load/remember the high score.
index 54f2e58..68f646d 100755 (executable)
--- a/pacman.c
+++ b/pacman.c
@@ -22,7 +22,6 @@
 #include "pacman.h"
 
 #define EXIT_MSG "Good bye!"
-#define END_MSG "Game Over"
 #define QUIT_MSG "Bye"
 #define LEVEL_ERR "Cannot find level file: "
 #define LEVEL_WIDTH 28
 /*************
 * PROTOTYPES *
 *************/
-void IntroScreen();                                     //Show introduction screen and menu
-int  CheckCollision();                                  //See if Pacman and Ghosts collided
-void CheckScreenSize();                                 //Make sure resolution is at least 33x29
+void IntroScreen(void);                                 //Show introduction screen and menu
+int  CheckCollision(void);                              //See if Pacman and Ghosts collided
+void CheckScreenSize(void);                             //Make sure resolution is at least 33x29
 void CreateWindows(int y, int x, int y0, int x0);       //Make ncurses windows
-void Delay();                                           //Slow down game for better control
-void DrawWindow();                                      //Refresh display
+void Delay(void);                                       //Slow down game for better control
+void DrawWindow(void);                                  //Refresh display
 void Cleanup(void);                                    //endwin(3) cleanup handler
 void ExitProgram(const char *message);                  //Exit and display something
-void GetInput();                                        //Get user input
-void InitCurses();                                      //Start up ncurses
+void GetInput(void);                                    //Get user input
+void InitCurses(void);                                  //Start up ncurses
 void LoadLevel(char *levelfile);                        //Load level into memory
-int  MainLoop();                                        //Main program function
-void MoveGhosts();                                      //Update Ghosts' location
-void MovePacman();                                      //Update Pacman's location
-void PauseGame();                                       //Pause
+int  MainLoop(void);                                    //Main program function
+void MoveGhosts(void);                                  //Update Ghosts' location
+void MovePacman(void);                                  //Update Pacman's location
+void PauseGame(void);                                   //Pause
 void PrintHelp(char* name);                             //Print help and exit
 
 /*******************
@@ -256,40 +255,38 @@ void CheckScreenSize() {
 }
 
 int GameOverScreen() {
-    char chr = ' ';
-    int a, b;
+    int ch;
 
     if (Points > HiPoints) {
            HiPoints = Points;
            HiLevelNumber = LevelNumber;
     }
 
-    for(a = 0; a < 29; a++) for(b = 0; b < 28; b++) {
-        mvwaddch(win, a, b, chr);
-    }
-
+    werase(win);
     wattron(win, COLOR_PAIR(Pacman));
     mvwprintw(win, 8, 11, "Game Over");
-
     wattron(win, COLOR_PAIR(Normal));
     mvwprintw(win, 14, 2, "Press q to quit ...");
     mvwprintw(win, 16, 2, "... or any other key");
     mvwprintw(win, 17, 6, "to play again");
-
     wrefresh(win);
 
-    //And wait
-    int chtmp;
+    sleep(1);
+
+    /* For some reason we really need both */
     (void)flushinp();
+    while (getch() != ERR) ;
+
+    /* Wait in blocking mode */
     (void)curs_set(1);
     (void)nodelay(stdscr, FALSE);
     do {
-        chtmp = getch();
-    } while (chtmp == ERR);
+        ch = getch();
+    } while (ch == ERR);
     (void)nodelay(stdscr, TRUE);
     (void)curs_set(0);
 
-    if(chtmp == 'q' || chtmp == 'Q')
+    if(ch == 'q' || ch == 'Q')
         return 1;
     return 0;
 }
@@ -312,20 +309,6 @@ void CreateWindows(int y, int x, int y0, int x0) {
 * Returns:     none                                             *
 * Description: Pause the game and still get keyboard input      *
 ****************************************************************/
-#if 0
-void Delay() {
-
-    //Needed to get time
-    struct timeb t_start, t_current;
-    ftime(&t_start);
-
-    //Slow down the game a little bit
-    do {
-        GetInput();                 //Still get the input from keyboard
-        ftime(&t_current);          //Update time and check if enough time has overlapped
-    } while (abs(t_start.millitm - t_current.millitm) < SpeedOfGame);
-}
-#endif
 void
 Delay(void)
 {
@@ -451,7 +434,7 @@ void GetInput() {
 
     //Determine which button is pushed
     switch (ch) {
-    case KEY_UP:    case 'w': case 'W':            //Move pacman up
+    case KEY_UP: case 'w': case 'i': case '8':     //Move pacman up
         if(Loc[4][0] <= 0) tmp = LEVEL_HEIGHT - 1;
         else tmp = Loc[4][0] - 1;
         if((Level[tmp][Loc[4][1]] != 1)
@@ -459,7 +442,7 @@ void GetInput() {
             { Dir[4][0] = -1; Dir[4][1] =  0; }
         break;
 
-    case KEY_DOWN:  case 's': case 'S':            //Move pacman down
+    case KEY_DOWN: case 's': case 'k': case '5': case '2': //Move pacman down
         if(Loc[4][0] >= 28) tmp = 0;
         else tmp = Loc[4][0] + 1;
         if((Level[tmp][Loc[4][1]] != 1)
@@ -467,7 +450,7 @@ void GetInput() {
             { Dir[4][0] =  1; Dir[4][1] =  0; }
         break;
 
-    case KEY_LEFT:  case 'a': case 'A':            //Move pacman left
+    case KEY_LEFT: case 'a': case 'j': case '4':   //Move pacman left
         if(Loc[4][1] <= 0) tmp = LEVEL_WIDTH - 1;
         else tmp = Loc[4][1] - 1;
         if((Level[Loc[4][0]][tmp] != 1)
@@ -475,7 +458,7 @@ void GetInput() {
             { Dir[4][0] =  0; Dir[4][1] = -1; }
         break;
 
-    case KEY_RIGHT: case 'd': case 'D':            //Move pacman right
+    case KEY_RIGHT: case 'd': case 'l': case '6':  //Move pacman right
         if(Loc[4][1] >= 27) tmp = 0;
         else tmp = Loc[4][1] + 1;
         if((Level[Loc[4][0]][tmp] != 1)
@@ -538,7 +521,9 @@ void IntroScreen() {
     int a = 0;
     int b = 23;
 
-    (void)flushinp(); // Clear input buffer
+    /* Flush input */
+    (void)flushinp();
+    while (getch() != ERR) ;
 
     mvwprintw(win, 20, 8, "Press any key...");
 
@@ -859,6 +844,7 @@ void PauseGame() {
     
     //And wait until key is pressed
     (void)flushinp();
+    while (getch() != ERR) ;
     (void)curs_set(1);
     (void)nodelay(stdscr, FALSE);
     do {
index d9d0792..db027f0 100755 (executable)
--- a/pacman.h
+++ b/pacman.h
@@ -9,5 +9,4 @@ int FreeLife = 1000;                //Starting points for free life
 int Points = 0;                     //Initial points
 int Lives = 3;                      //Number of lives you start with
 int HowSlow = 3;                    //How slow vulnerable ghost move
-int SpeedOfGame = 175;              //How much of a delay is in the game
 #define FPS 5