#include "window.h" #include "symbol_table.h" #include "game_object.h" #include "event_manager.h" #include "gpl_assert.h" #include #include #include #ifdef __APPLE__ #include #include #else #include #include #endif extern Window *window; int clock_tick; static Symbol_table *symbol_table = Symbol_table::instance(); static Event_manager *event_manager = Event_manager::instance(); void draw_all_game_objects() { glClear(GL_COLOR_BUFFER_BIT); Game_object::draw_all_game_objects(); glutSwapBuffers(); } // if the window is resized, must redraw void window_reshape_callback(int width, int height) { draw_all_game_objects(); } // called when windowing-system determines the graphics in the window // may be out of date void window_visibility_callback(int state) { draw_all_game_objects(); } void draw_callback() { // only redraw the game objects if one of them has changed // Note: if any field of any game object has changed since the last // time the screen was drawn, graphics_out_of_date_with_last_rendering() // will return true if (Game_object::graphics_out_of_date_with_last_rendering()) { draw_all_game_objects(); } } void timer_callback(int value) { // cout << "timer_callback()" << endl; Game_object::animate_all_game_objects(); draw_callback(); // glut timer functions must be reregistered each time glutTimerFunc(clock_tick, timer_callback, 0); } void keyboard_callback(unsigned char key, int x, int y) { switch (key) { case ' ' : event_manager->execute_handlers(Window::SPACE); break; case 'A' : case 'a' : event_manager->execute_handlers(Window::AKEY); break; case 'S' : case 's' : event_manager->execute_handlers(Window::SKEY); break; case 'D' : case 'd' : event_manager->execute_handlers(Window::DKEY); break; case 'F' : case 'f' : event_manager->execute_handlers(Window::FKEY); break; case 'H' : case 'h' : event_manager->execute_handlers(Window::HKEY); break; case 'J' : case 'j' : event_manager->execute_handlers(Window::JKEY); break; case 'K' : case 'k' : event_manager->execute_handlers(Window::KKEY); break; case 'L' : case 'l' : event_manager->execute_handlers(Window::LKEY); break; case 'W' : case 'w' : event_manager->execute_handlers(Window::WKEY); break; case 'Q' : case 'q' : // SHOULD DELETE EVERYTHING AS A MEMORY CHECK // send signal to self so gpl.cpp can print symbol table kill(getpid(), SIGUSR1); exit(0); } } void special_callback(int key, int x, int y) { switch (key) { case GLUT_KEY_F1: event_manager->execute_handlers(Window::F1); break; case GLUT_KEY_UP: event_manager->execute_handlers(Window::UPARROW); break; case GLUT_KEY_DOWN: event_manager->execute_handlers(Window::DOWNARROW); break; case GLUT_KEY_LEFT: event_manager->execute_handlers(Window::LEFTARROW); break; case GLUT_KEY_RIGHT: event_manager->execute_handlers(Window::RIGHTARROW); break; } } void read_keypresses_from_standard_input_callback() { while (true) { // skip whitespace (except actual spaces, they are legal input) while (isspace(cin.peek()) && cin.peek() != ' ') cin.ignore(); char keypress; cin.get(keypress); // if there was a problem (such as reaching EOF) stop if (!cin.good()) break; switch(keypress) { case 6: // ^F event_manager->execute_handlers(Window::F1); break; case 1: // ^A event_manager->execute_handlers(Window::UPARROW); break; case 2: // ^B event_manager->execute_handlers(Window::DOWNARROW); break; case 4: // ^D event_manager->execute_handlers(Window::LEFTARROW); break; case 3: // ^C event_manager->execute_handlers(Window::RIGHTARROW); break; default: keyboard_callback(keypress, 0, 0); } draw_callback(); } // only call this function the first time we are idle // it is assumed that all the commands will have been read by now glutIdleFunc(0); } Window::Window(int x, int y, int w, int h, string title, int speed, double red, double green, double blue, bool read_keypresses_from_standard_input /* = false */) { m_x = x; m_y = y; m_w = w; m_h = h; m_title = title; m_read_keypresses_from_standard_input = read_keypresses_from_standard_input; if (speed > 100) speed = 100; if (speed < 1) speed = 1; // This formula sets up the meaning of the speed // Speed is very machine dependent, this may have to be changed // for very fast or very slow machine // special case, low speeds are really slow for debugging if (speed <= 10) clock_tick = (11 - speed) * 1000; else clock_tick = ((103 - speed) * (103 - speed))/10; // glut can be controlled by command line arguments pass to glutInit(). // In order to simplify argument parsing in gpl.cpp, command line // arguments are not passed to glutInit() int phony_argc = 1; static char* phony_argv[] = {"gpl"}; glutInit(&phony_argc,phony_argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(m_w,m_h); glutInitWindowPosition(m_x,m_y); glutCreateWindow(m_title.c_str()); // if we are suppose to read characters from the command line // (this is a testing/debugging tool) if (m_read_keypresses_from_standard_input) // use an idle function to read the commands glutIdleFunc(read_keypresses_from_standard_input_callback); // redraws all objects if window is changed by windowing system glutReshapeFunc(window_reshape_callback); glutVisibilityFunc(window_visibility_callback); glutDisplayFunc(draw_callback); glutTimerFunc(clock_tick, timer_callback, 0); glutKeyboardFunc(keyboard_callback); glutSpecialFunc(special_callback); glViewport(0, 0, m_w, m_h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, m_w, 0, m_h); glClearColor (red, green, blue, 0.0); } void Window::initialize() { event_manager->execute_handlers(Window::INITIALIZE); } void Window::main_loop() { glutMainLoop(); }