summaryrefslogtreecommitdiffstats
path: root/matchblox/engine/C_MatchBloxEngine.h
blob: 5d9029166594ad15cc7004b48ff3c56ffc24cd0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#ifndef C_MATCHBLOXENGINE_HEADER_FILE

#define C_MATCHBLOXENGINE_HEADER_FILE

#include "message_queue.h"
#include "message_input.h"
#include "typedefs.h"
#include <list>
#include "C_Smoother.h" 
//#include <pair>

using namespace std;

class C_3DObject;
class C_Block;
class C_Hand;
class C_Log;
class C_Environment;
class C_Box;


typedef enum GameResult
{
  GR_FINISHED,
  GR_BUSY,
  GR_ERROR
} GameResult;

enum EngineState
{
  ES_INITIALISED,
  ES_ERROR,
  ES_GET_READY,    //game initialised, waiting for start signal from player
  ES_PLAYING_GRAB_BLOCK, //no block in hand -> grab floating block
  ES_PLAYING_PUT_BLOCK,  //block in hand -> put block in box
  ES_PAUSED,             //pause... -> menu
  ES_FINISHED            //finished -> show score and goto init
};

enum BlockType
{
  BT_SQUARE   = 0,
  BT_CIRCLE   = 1,
  BT_TRIANGLE = 2,
  BT_CROSS    = 3
};

enum BoxSize
{
  BS_SMALL = 0,
  BS_MED   = 1,
  BS_LARGE = 2
};

struct GameSettings
{
      int    m_iNrOfTurns;
      double m_dMinProximity, //The minimum allowed squared (xz) distance between 
                              //the center of the block and the center of the hole
                              //for the block to be considered to be in the hole
             m_dHoleDepth;    //Depth of a hole; the minimum z distance between block
                              //and a hole, for the block to be successfully inserted
                              //into the box
};

struct GameSession
{
  int           m_iTotalTurns,
                m_iCurrentTurn;
  unsigned int  m_uiSessionStart, //time in ms
                m_uiTurnStart,
                m_uiPauseStart,
                *m_puiTurnResult;
  int           m_iBlocksLeft[4]; //number of blocks per type
  BlockType     m_CurrentBlockType;
  
  GameSession(int f_iNrOfBlocks, BoxSize f_BS) 
    : m_iTotalTurns(f_iNrOfBlocks), m_iCurrentTurn(0)
  {
    m_puiTurnResult = new unsigned int[f_iNrOfBlocks];

    //divide the number of blocks between the block types
    int l_iNrPerType = f_iNrOfBlocks/4,
        l_iLeft      = f_iNrOfBlocks%4; //the left-over count
    for(int i=0; i<4; i++)
    {
      m_iBlocksLeft[i] = l_iNrPerType;
      if (l_iLeft > 0) 
      {
        m_iBlocksLeft[i]++; l_iLeft--;
      }
    }
  }
  ~GameSession()
  {
    delete m_puiTurnResult;
  }
  
  bool NextTurn(BlockType &f_NewBlock)
  {
    unsigned int l_uiTime = glutGet(GLUT_ELAPSED_TIME);

    if (m_iCurrentTurn == 0)
    {
      //session start
      m_uiSessionStart = m_uiTurnStart = l_uiTime;
      m_iCurrentTurn++;
    }
    else
    {
      //next turn -> save turn result
      m_puiTurnResult[m_iCurrentTurn] = l_uiTime - m_uiTurnStart;
      m_iCurrentTurn++;
      m_uiTurnStart = l_uiTime;
    }

    if (m_iCurrentTurn < m_iTotalTurns)
    {
      f_NewBlock = GetRandomBlockType();
      return true;
    }
    else 
    {
      return false;
    }
  }

  BlockType GetRandomBlockType()
  {
    int l_iBlockType = rand()%4;
    while (m_iBlocksLeft[l_iBlockType] <= 0)
      l_iBlockType = (l_iBlockType+1)%4;

    m_iBlocksLeft[l_iBlockType]--;
    return (BlockType)l_iBlockType;
  }
  void PauseSession()
  {
    //record the time at which the pause starts
    m_uiPauseStart = glutGet(GLUT_ELAPSED_TIME);
  }
  void ResumeSession()
  {
    //add the total pause time to the timers 
    unsigned int l_uiPauseTime = glutGet(GLUT_ELAPSED_TIME) - m_uiPauseStart;
    m_uiSessionStart += l_uiPauseTime;
    m_uiTurnStart += l_uiPauseTime;
  }
};

class C_MatchBloxEngine
{
public:
  C_MatchBloxEngine(const char *f_strModelPath, 
                    const char *f_strLogFile,
                    GameSettings f_GameSettings);
  ~C_MatchBloxEngine();

  GameResult ProcessMsgs(void);
  void Render(unsigned int f_uiElapsedTime, input_payload_wiimote &f_HTWiimote, FrustumParms_t &f_FrustParms);
  
  bool NewGame(int f_iGameMode);
  bool StartGame();
  bool Pause();
  bool Resume();
  bool Abort();

private:
  C_Environment *m_pEnvMap;
  C_Block     *m_pBlock[4];
  C_Hand      *m_pHand;
  C_3DObject  *m_pTiles[5];
  C_Box       *m_pBox[3];
  C_Log       *m_pLog;

  GLuint      m_uiWood1Tex,
              m_uiWood2Tex,
              m_uiWood3Tex;

  EngineState m_State, m_SavedState;
  GameSession *m_pCurrentSession;
  GameSettings m_GameSettings;
  BoxSize      m_CurrentBox;
  BlockType    m_CurrentBlock;
  unsigned int m_uiCurrentTime,
               m_uiLastPosValid;
  C_Smoother<double>   *m_pWorldZSmoother[2];  //2 to smooth the computed world z coordinate
  double        m_dInitialWiimoteDist; //initial distance of wiimote in mm, this distance is
                                       //mapped to the z=0.0 in world coordinates
  BoundingBox_t m_WorldBox; //an invisible box that limits the movement of the 
                            //player
  bool m_bHeadTrackingEnabled,
       m_bStereoEnabled;
  GLuint          m_GrayScaleShaderProgram;   //handle to the grayscale shader program
  GLint           m_GSConvScaleLocation,      //handle to the g_ConversionScale variable in the shader
                  m_GSTextureLocation;        //
  GLfloat         m_GSConvScale[3];           //grayscale conversion scale (default 0.299, 0.587, 0.114)


  //init routines
  bool LoadModels(const char* f_strModelDir);
  void DeleteModels();
  void LoadTexture(const char* f_BmpName, GLuint &f_uiTexHandle);
  bool LoadGrayScaleShader();

  //render routines
  void RenderEnv(unsigned int f_uiElapsedTime);
  void RenderMain(unsigned int f_uiElapsedTime);
  void RenderOverlay(unsigned int f_uiElapsedTime);

  void RenderGetReady();
  void RenderHUD(unsigned int f_uiElapsedTime);
  void RenderResults();
  void RenderPointHere();
  void RenderText(GLint x, GLint y, char *string, struct ColorStruct f_sColor);

  //event/input handlers
  void CursorMove(Vect3D_t &f_NewCursorPos);
  bool CursorMove_GrabBlock(Vect3D_t &f_NewCursorPos);
  bool CursorMove_PutBlock(Vect3D_t &f_NewCursorPos);
  bool Check_PutBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CusrBBox);
  //bool Check_GrabBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CusrBBox);
  void NewBlock();
  void GameFinished();

  //wiimote functions
  bool ConvertWiimoteToWorld(input_payload_wiimote *f_pWiimote, Vect3D_t *f_WorldPos);

};

#endif //C_MATCHBLOXENGINE_HEADER_FILE