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
|
#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...
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);
bool NewGame(int f_iUserID, int f_iGameId, BoxSize f_BS);
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
//init routines
bool LoadModels(const char* f_strModelDir);
void DeleteModels();
void LoadTexture(const char* f_BmpName, GLuint &f_uiTexHandle);
//render routines
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 FindIRDots(input_payload_wiimote *f_pWiimote, ir_dot_t f_Dot[2]);
//bool CalcWiimoteRelativeCursorPos(input_payload_wiimote *f_pWiimote, Vect3D_t *f_pRelPos);
bool ConvertWiimoteToWorld(input_payload_wiimote *f_pWiimote, Vect3D_t *f_WorldPos);
};
#endif //C_MATCHBLOXENGINE_HEADER_FILE
|