/* *tux_thread * DESCRIPTION: Function executed by tux helper thread. * * INPUTS: none (ignored) * OUTPUTS: none * RETURN VALUE: NULL * SIDE EFFECTS: get the command from the tux and do the corrosponding operations. */ static void* tux_thread (void* ignore) { cmd_t cmd; struct timeval start_time, tick_time; struct timeval cur_time; /* current time (during tick) */ /* Record the starting time--assume success. */ (void)gettimeofday (&start_time, NULL); /* Calculate the time at which the first event loop tick should occur. */ tick_time = start_time; if ((tick_time.tv_usec += TICK_USEC) > 1000000) { tick_time.tv_sec++; tick_time.tv_usec -= 1000000; } while(1) { (void)pthread_mutex_lock (&cmd_lock); cmd = get_tux_command (); switch (cmd) { case CMD_UP: move_photo_down (); break; case CMD_RIGHT: move_photo_left (); break; case CMD_DOWN: move_photo_up (); break; case CMD_LEFT: move_photo_right (); break; case CMD_MOVE_LEFT: enter_room = (TC_CHANGE_ROOM == try_to_move_left (&game_info.where)); break; case CMD_ENTER: enter_room = (TC_CHANGE_ROOM == try_to_enter (&game_info.where)); break; case CMD_MOVE_RIGHT: enter_room = (TC_CHANGE_ROOM == try_to_move_right (&game_info.where)); break; case CMD_QUIT: game = GAME_QUIT; break; default: break; } (void)pthread_mutex_unlock (&cmd_lock); /* If player wins the game, their room becomes NULL. */ if (NULL == game_info.where) { game = GAME_WON; } /* * Wait for tick. The tick defines the basic timing of our * event loop, and is the minimum amount of time between events. */ do { if (gettimeofday (&cur_time, NULL) != 0) { /* Panic! (should never happen) */ clear_mode_X (); shutdown_input (); perror ("gettimeofday"); exit (3); } } while (!time_is_after (&cur_time, &tick_time)); /* * Advance the tick time. If we missed one or more ticks completely, * i.e., if the current time is already after the time for the next * tick, just skip the extra ticks and advance the clock to the one * that we haven't missed. */ do { if ((tick_time.tv_usec += TICK_USEC) > 1000000) { tick_time.tv_sec++; tick_time.tv_usec -= 1000000; } } while (time_is_after (&cur_time, &tick_time)); } return NULL; }
/* * game_loop * DESCRIPTION: Main event loop for the adventure game. * INPUTS: none * OUTPUTS: none * RETURN VALUE: GAME_QUIT if the player quits, or GAME_WON if they have won * SIDE EFFECTS: drives the display, etc. */ static game_condition_t game_loop () { /* * Variables used to carry information between event loop ticks; see * initialization below for explanations of purpose. */ struct timeval start_time, tick_time; struct timeval cur_time; /* current time (during tick) */ cmd_t cmd; /* command issued by input control */ int32_t enter_room; /* player has changed rooms */ /* Record the starting time--assume success. */ (void)gettimeofday (&start_time, NULL); /* Calculate the time at which the first event loop tick should occur. */ tick_time = start_time; if ((tick_time.tv_usec += TICK_USEC) > 1000000) { tick_time.tv_sec++; tick_time.tv_usec -= 1000000; } /* The player has just entered the first room. */ enter_room = 1; /* The main event loop. */ while (1) { /* * Update the screen, preparing the VGA palette and photo-drawing * routines and drawing a new room photo first if the player has * entered a new room, then showing the screen (and status bar, * once you have it working). */ if (enter_room) { /* Reset the view window to (0,0). */ game_info.map_x = game_info.map_y = 0; set_view_window (game_info.map_x, game_info.map_y); /* Discard any partially-typed command. */ reset_typed_command (); /* Adjust colors and photo drawing for the current room photo. */ prep_room (game_info.where); /* Draw the room (calls show. */ redraw_room (); /* Only draw once on entry. */ enter_room = 0; } show_screen (); //lock status_msg to prevent changes (void)pthread_mutex_lock (&msg_lock); room_t* curr_room = game_info.where; // This is the current room pointer // Now call fill_status_bar with all the possible strings as params fill_status_bar(room_name(curr_room), get_typed_command(), status_msg); (void)pthread_mutex_unlock (&msg_lock); //unlock // Calculate game time display_time_on_tux (cur_time.tv_sec - start_time.tv_sec); /* * Wait for tick. The tick defines the basic timing of our * event loop, and is the minimum amount of time between events. */ do { if (gettimeofday (&cur_time, NULL) != 0) { /* Panic! (should never happen) */ clear_mode_X (); shutdown_input (); perror ("gettimeofday"); exit (3); } } while (!time_is_after (&cur_time, &tick_time)); /* * Advance the tick time. If we missed one or more ticks completely, * i.e., if the current time is already after the time for the next * tick, just skip the extra ticks and advance the clock to the one * that we haven't missed. */ do { if ((tick_time.tv_usec += TICK_USEC) > 1000000) { tick_time.tv_sec++; tick_time.tv_usec -= 1000000; } } while (time_is_after (&cur_time, &tick_time)); /* * Handle asynchronous events. These events use real time rather * than tick counts for timing, although the real time is rounded * off to the nearest tick by definition. */ /* (none right now...) */ /* * Handle synchronous events--in this case, only player commands. * Note that typed commands that move objects may cause the room * to be redrawn. */ cmd = get_command (); switch (cmd) { case CMD_UP: move_photo_down (); break; case CMD_RIGHT: move_photo_left (); break; case CMD_DOWN: move_photo_up (); break; case CMD_LEFT: move_photo_right (); break; case CMD_MOVE_LEFT: enter_room = (TC_CHANGE_ROOM == try_to_move_left (&game_info.where)); break; case CMD_ENTER: enter_room = (TC_CHANGE_ROOM == try_to_enter (&game_info.where)); break; case CMD_MOVE_RIGHT: enter_room = (TC_CHANGE_ROOM == try_to_move_right (&game_info.where)); break; case CMD_TYPED: if (handle_typing ()) { enter_room = 1; } break; case CMD_QUIT: return GAME_QUIT; default: break; } // Repeat the same thing for the tux cmd = get_tux_command(); switch (cmd) { case CMD_UP: move_photo_down (); break; case CMD_RIGHT: move_photo_left (); break; case CMD_DOWN: move_photo_up (); break; case CMD_LEFT: move_photo_right (); break; case CMD_MOVE_LEFT: enter_room = (TC_CHANGE_ROOM == try_to_move_left (&game_info.where)); break; case CMD_ENTER: enter_room = (TC_CHANGE_ROOM == try_to_enter (&game_info.where)); break; case CMD_MOVE_RIGHT: enter_room = (TC_CHANGE_ROOM == try_to_move_right (&game_info.where)); break; case CMD_QUIT: return GAME_QUIT; default: break; } /* If player wins the game, their room becomes NULL. */ if (NULL == game_info.where) { return GAME_WON; } } /* end of the main event loop */ }
/* * main * DESCRIPTION: Initializes and runs the two threads * INPUTS: none * OUTPUTS: none * RETURN VALUE: 0 on success, -1 on failure * SIDE EFFECTS: none */ int main() { int ret; struct termios tio_new; unsigned long update_rate = 32; /* in Hz */ pthread_t tid1; pthread_t tid2; pthread_t tid3; // Initialize RTC fd = open("/dev/rtc", O_RDONLY, 0); // Enable RTC periodic interrupts at update_rate Hz // Default max is 64...must change in /proc/sys/dev/rtc/max-user-freq ret = ioctl(fd, RTC_IRQP_SET, update_rate); ret = ioctl(fd, RTC_PIE_ON, 0); //Initialize Tux control tux_fd=open("/dev/ttyS0", O_RDWR | O_NOCTTY); int ldsic_num = N_MOUSE; ioctl(tux_fd, TIOCSETD, &ldsic_num); ioctl(tux_fd, TUX_INIT); // Initialize Keyboard // Turn on non-blocking mode if (fcntl (fileno (stdin), F_SETFL, O_NONBLOCK) != 0) { perror ("fcntl to make stdin non-blocking"); return -1; } // Save current terminal attributes for stdin. if (tcgetattr (fileno (stdin), &tio_orig) != 0) { perror ("tcgetattr to read stdin terminal settings"); return -1; } // Turn off canonical (line-buffered) mode and echoing of keystrokes // Set minimal character and timing parameters so as tio_new = tio_orig; tio_new.c_lflag &= ~(ICANON | ECHO); tio_new.c_cc[VMIN] = 1; tio_new.c_cc[VTIME] = 0; if (tcsetattr (fileno (stdin), TCSANOW, &tio_new) != 0) { perror ("tcsetattr to set stdin terminal settings"); return -1; } // Perform Sanity Checks and then initialize input and display if ((sanity_check () != 0) || (set_mode_X (fill_horiz_buffer, fill_vert_buffer) != 0)) { return 3; } // Create the threads pthread_create(&tid1, NULL, rtc_thread, NULL); pthread_create(&tid2, NULL, keyboard_thread, NULL); pthread_create(&tid3, NULL, tux_thread, NULL); // Wait for all the threads to end pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); // Shutdown Display clear_mode_X(); // Close Keyboard (void)tcsetattr (fileno (stdin), TCSANOW, &tio_orig); // Close RTC close(fd); //Close Tux Control close(tux_fd); // Print outcome of the game if (winner == 1) { printf ("You win the game! CONGRATULATIONS!\n"); } else if (quit_flag == 1) { printf ("Quitter!\n"); } else { printf ("Sorry, you lose...\n"); } // Return success return 0; }