summaryrefslogtreecommitdiff
path: root/src/uiInteract.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/uiInteract.cpp')
-rw-r--r--src/uiInteract.cpp331
1 files changed, 331 insertions, 0 deletions
diff --git a/src/uiInteract.cpp b/src/uiInteract.cpp
new file mode 100644
index 0000000..7a0d504
--- /dev/null
+++ b/src/uiInteract.cpp
@@ -0,0 +1,331 @@
+/***********************************************************************
+ * Source File:
+ * UI INTERACT
+ * Author:
+ * Br. Helfrich
+ * Description:
+ * Implement the interfaces specified in uiInterface.h. This handles
+ * all the interfaces and events necessary to work with OpenGL. Your
+ * program will interface with this thorough the callback function
+ * pointer towards the bottom of the file.
+ ************************************************************************/
+
+#include <string> // need you ask?
+#include <sstream> // convert an integer into text
+#include <cassert> // I feel the need... the need for asserts
+#include <time.h> // for clock
+#include <cstdlib> // for rand()
+
+
+#ifdef __APPLE__
+#include <openGL/gl.h> // Main OpenGL library
+#include <GLUT/glut.h> // Second OpenGL library
+#endif // __APPLE__
+
+#ifdef __linux__
+#include <GL/gl.h> // Main OpenGL library
+#include <GL/glut.h> // Second OpenGL library
+#endif // __linux__
+
+#ifdef _WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <Gl/glut.h> // OpenGL library we copied
+#include <ctime> // for ::Sleep();
+#include <Windows.h>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+#endif // _WIN32
+
+#include "uiInteract.h"
+#include "point.h"
+
+using namespace std;
+
+
+/*********************************************************************
+ * SLEEP
+ * Pause for a while. We want to put the program to sleep until it
+ * is time to draw again. Note that this requires us to tell the OS
+ * that we are idle. the nanosleep function performs this task for us
+ * INPUT: msSleep: sleep time in milliseconds
+ *********************************************************************/
+void sleep(unsigned long msSleep)
+{
+ // Windows handles sleep one way
+#ifdef _WIN32
+ ::Sleep(msSleep + 35);
+
+ // Unix-based operating systems (OS-X, Linux) do it another
+#else // LINUX, XCODE
+ timespec req = {};
+ time_t sec = (int)(msSleep / 1000);
+ msSleep -= (sec * 1000);
+
+ req.tv_sec = sec;
+ req.tv_nsec = msSleep * 1000000L;
+
+ while (nanosleep(&req, &req) == -1)
+ ;
+#endif // LINUX, XCODE
+ return;
+}
+
+/************************************************************************
+ * DRAW CALLBACK
+ * This is the main callback from OpenGL. It gets called constantly by
+ * the graphics engine to refresh and draw the window. Here we will
+ * clear the background buffer, draw on it, and send it to the forefront
+ * when the appropriate time period has passsed.
+ *
+ * Note: This and all other callbacks can't be member functions, they must
+ * have global scope for OpenGL to see them.
+ *************************************************************************/
+void drawCallback()
+{
+ // even though this is a local variable, all the members are static
+ Interface ui;
+ // Prepare the background buffer for drawing
+ glClear(GL_COLOR_BUFFER_BIT); //clear the screen
+ glColor3f(1,1,1);
+
+ //calls the client's display function
+ assert(ui.callBack != NULL);
+ ui.callBack(&ui, ui.p);
+
+ //loop until the timer runs out
+ if (!ui.isTimeToDraw())
+ sleep((unsigned long)((ui.getNextTick() - clock()) / 1000));
+
+ // from this point, set the next draw time
+ ui.setNextDrawTime();
+
+ // bring forth the background buffer
+ glutSwapBuffers();
+
+ // clear the space at the end
+ ui.keyEvent();
+}
+
+/************************************************************************
+ * KEY DOWN CALLBACK
+ * When a key on the keyboard has been pressed, we need to pass that
+ * on to the client. Currently, we are only registering the arrow keys
+ * INPUT key: the key we pressed according to the GLUT_KEY_ prefix
+ * x y: the position in the window, which we ignore
+ *************************************************************************/
+void keyDownCallback(int key, int x, int y)
+{
+ // Even though this is a local variable, all the members are static
+ // so we are actually getting the same version as in the constructor.
+ Interface ui;
+ ui.keyEvent(key, true /*fDown*/);
+}
+
+/************************************************************************
+ * KEY UP CALLBACK
+ * When the user has released the key, we need to reset the pressed flag
+ * INPUT key: the key we pressed according to the GLUT_KEY_ prefix
+ * x y: the position in the window, which we ignore
+ *************************************************************************/
+void keyUpCallback(int key, int x, int y)
+{
+ // Even though this is a local variable, all the members are static
+ // so we are actually getting the same version as in the constructor.
+ Interface ui;
+ ui.keyEvent(key, false /*fDown*/);
+}
+
+/***************************************************************
+ * KEYBOARD CALLBACK
+ * Generic callback to a regular ascii keyboard event, such as
+ * the space bar or the letter 'q'
+ ***************************************************************/
+void keyboardCallback(unsigned char key, int x, int y)
+{
+ // Even though this is a local variable, all the members are static
+ // so we are actually getting the same version as in the constructor.
+ Interface ui;
+ ui.keyEvent(key, true /*fDown*/);
+}
+
+/***************************************************************
+ * INTERFACE : KEY EVENT
+ * Either set the up or down event for a given key
+ * INPUT key which key is pressed
+ * fDown down or brown
+ ****************************************************************/
+void Interface::keyEvent(int key, bool fDown)
+{
+ switch(key)
+ {
+ case GLUT_KEY_DOWN:
+ isDownPress = fDown;
+ break;
+ case GLUT_KEY_UP:
+ isUpPress = fDown;
+ break;
+ case GLUT_KEY_RIGHT:
+ isRightPress = fDown;
+ break;
+ case GLUT_KEY_LEFT:
+ isLeftPress = fDown;
+ break;
+ case GLUT_KEY_F1:
+ isYPress = fDown;
+ break;
+ case GLUT_KEY_HOME:
+ case ' ':
+ isSpacePress = fDown;
+ break;
+ }
+}
+/***************************************************************
+ * INTERFACE : KEY EVENT
+ * Either set the up or down event for a given key
+ * INPUT key which key is pressed
+ * fDown down or brown
+ ****************************************************************/
+void Interface::keyEvent()
+{
+ if (isDownPress)
+ isDownPress++;
+ if (isUpPress)
+ isUpPress++;
+ if (isLeftPress)
+ isLeftPress++;
+ if (isRightPress)
+ isRightPress++;
+ isYPress = false;
+ isSpacePress = false;
+}
+
+
+/************************************************************************
+ * INTEFACE : IS TIME TO DRAW
+ * Have we waited long enough to draw swap the background buffer with
+ * the foreground buffer?
+ *************************************************************************/
+bool Interface::isTimeToDraw()
+{
+ return ((unsigned int)clock() >= nextTick);
+}
+
+/************************************************************************
+ * INTERFACE : SET NEXT DRAW TIME
+ * What time should we draw the buffer again? This is a function of
+ * the current time and the frames per second.
+ *************************************************************************/
+void Interface::setNextDrawTime()
+{
+ nextTick = clock() + static_cast<int> (timePeriod * CLOCKS_PER_SEC);
+}
+
+/************************************************************************
+ * INTERFACE : SET FRAMES PER SECOND
+ * The frames per second dictates the speed of the game. The more frames
+ * per second, the quicker the game will appear to the user. We will default
+ * to 30 frames/second but the client can set this at will.
+ * INPUT value The number of frames per second. 30 is default
+ *************************************************************************/
+void Interface::setFramesPerSecond(double value)
+{
+ timePeriod = (1 / value);
+}
+
+/***************************************************
+ * STATICS
+ * All the static member variables need to be initialized
+ * Somewhere globally. This is a good spot
+ **************************************************/
+int Interface::isDownPress = 0;
+int Interface::isUpPress = 0;
+int Interface::isLeftPress = 0;
+int Interface::isRightPress = 0;
+bool Interface::isYPress = false;
+bool Interface::isSpacePress = false;
+bool Interface::initialized = false;
+double Interface::timePeriod = 1.0 / 30; // default to 30 frames/second
+unsigned int Interface::nextTick = 0; // redraw now please
+void * Interface::p = NULL;
+void (*Interface::callBack)(const Interface *, void *) = NULL;
+
+
+/************************************************************************
+ * INTERFACE : DESTRUCTOR
+ * Nothing here!
+ ***********************************************************************/
+Interface::~Interface()
+{
+}
+
+
+/************************************************************************
+ * INTEFACE : INITIALIZE
+ * Initialize our drawing window. This will set the size and position,
+ * get ready for drawing, set up the colors, and everything else ready to
+ * draw the window. All these are part of initializing Open GL.
+ * INPUT argc: Count of command-line arguments from main
+ * argv: The actual command-line parameters
+ * title: The text for the titlebar of the window
+ *************************************************************************/
+void Interface::initialize(int argc, char ** argv, const char * title, Point topLeft, Point bottomRight)
+{
+ if (initialized)
+ return;
+
+ // set up the random number generator
+ srand((unsigned int)time(NULL));
+
+ // create the window
+ glutInit(&argc, argv);
+ Point point;
+ glutInitWindowSize( // size of the window
+ (int)(bottomRight.getX() - topLeft.getX()),
+ (int)(topLeft.getY() - bottomRight.getY()));
+
+ glutInitWindowPosition( 10, 10); // initial position
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); // double buffering
+ glutCreateWindow(title); // text on titlebar
+ glutIgnoreKeyRepeat(true);
+
+ // set up the drawing style: B/W and 2D
+ glClearColor(0, 0, 0, 0); // Black is the background color
+ gluOrtho2D((int)topLeft.getX(), (int)bottomRight.getX(),
+ (int)bottomRight.getY(), (int)topLeft.getY()); // 2D environment
+
+ // register the callbacks so OpenGL knows how to call us
+ glutDisplayFunc( drawCallback );
+ glutIdleFunc( drawCallback );
+ glutKeyboardFunc( keyboardCallback);
+ glutSpecialFunc( keyDownCallback );
+ glutSpecialUpFunc( keyUpCallback );
+ initialized = true;
+
+ // done
+ return;
+}
+
+/************************************************************************
+ * INTERFACE : RUN
+ * Start the main graphics loop and play the game
+ * INPUT callBack: Callback function. Every time we are beginning
+ * to draw a new frame, we first callback to the client
+ * to see if he wants to do anything, such as move
+ * the game pieces or respond to input
+ * p: Void point to whatever the caller wants. You
+ * will need to cast this back to your own data
+ * type before using it.
+ *************************************************************************/
+void Interface::run(void (*callBack)(const Interface *, void *), void *p)
+{
+ // setup the callbacks
+ this->p = p;
+ this->callBack = callBack;
+
+ glutMainLoop();
+
+ return;
+}
+