#include #include #include #include #include "C_MatchBloxEngine.h" #include "C_3DObject.h" #include "C_Environment.h" #include "C_Hand.h" #include "C_Block.h" #include "C_Box.h" #include "C_Log.h" #include "bitmap.h" C_MatchBloxEngine::C_MatchBloxEngine(const char *f_strModelPath, const char *f_strLogFile, GameSettings f_GameSettings) : m_GameSettings(f_GameSettings) { //create logger //Load models if (LoadModels(f_strModelPath)) { //set state to initialised; m_State = ES_INITIALISED; } else { m_State = ES_ERROR; } //initialise a random seed srand ( time(NULL) ); //init vars m_CurrentBox = BS_SMALL; //init the world bounding box m_WorldBox.m_Min = Vect3D_t(-50.0, -50.0, -50.0); m_WorldBox.m_Max = Vect3D_t(50.0, 50.0, 0.0); } C_MatchBloxEngine::~C_MatchBloxEngine() { //destroy logger //delete models DeleteModels(); } GameResult C_MatchBloxEngine::ProcessMsgs(void) { //msgStruct l_msg; ////process message queue //while (!f_Queue.empty()) //{ // //get the first msg // l_msg = f_Queue.front(); // f_Queue.pop(); // switch (l_msg.m_MessageType) // { // case WII_CURSOR_MOVE: // // break; // case WII_BUTTON_PRESS: // break; // } //} return GR_BUSY; } void C_MatchBloxEngine::Render_Basics(unsigned int f_uiElapsedTime) { glPushMatrix(); //set camera pitch glRotated(20.0, 1.0, 0.0, 0.0); //rotate the environment map about the y axis glRotated((GLdouble)f_uiElapsedTime/1000.0, 0.0, 1.0, 0.0); m_pEnvMap->Render(); glPopMatrix(); glPushMatrix(); //move the camera backwards glTranslated(0.0, 0.0, -16.0); glRotated(20.0, 1.0, 0.0, 0.0); //if (m_pCurrentSession) //{ m_pBox[(int)m_CurrentBox]->Render(); //for (int i=0; i<4; i++) //m_pBlock[i]->Render(f_uiElapsedTime); // m_pHand->Render(f_uiElapsedTime); //} glPopMatrix(); } void C_MatchBloxEngine::Render(unsigned int f_uiElapsedTime) { switch (m_State) { case ES_INITIALISED: Render_Basics(f_uiElapsedTime); break; case ES_ERROR: //render a red cube glPushMatrix(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glColor3d(1.0, 0.0, 0.0); glTranslated(0.0, 0.0, -5.0); glutSolidCube(5.0); glPopAttrib(); glPopMatrix(); break; case ES_GET_READY: Render_Basics(f_uiElapsedTime); //render some GET READY text break; case ES_PLAYING_GRAB_BLOCK: Render_Basics(f_uiElapsedTime); break; case ES_PLAYING_PUT_BLOCK: Render_Basics(f_uiElapsedTime); break; case ES_PAUSED: Render_Basics(f_uiElapsedTime); //render menu?? break; case ES_FINISHED: //render results... break; } //glPushMatrix(); //double l_dSeconds = (double)f_uiElapsedTime/1000.0; //glRotated(l_dSeconds * 5.0, 0.0, 1.0, 0.0); ////glRotated(l_dSeconds * 10, 0.0, 0.0, 1.0); //m_pEnvMap->Render(); //glPopMatrix(); //m_pBox[0]->Render(); //for(int i=0; i<4; i++) //{ // glPushMatrix(); // m_pBlock[i]->Render(f_uiElapsedTime); // glPopMatrix(); //} } bool C_MatchBloxEngine::NewGame(int f_iUserID, int f_iGameId, BoxSize f_BS) { if(m_State == ES_INITIALISED) { //log new game //prepare a session struct for administration m_pCurrentSession = new GameSession(8, f_BS); //randomize the box tiles m_pBox[(int)m_pCurrentSession->m_BoxSize]->RandomizeTiles(); m_CurrentBox = f_BS; //set state to GET READY m_State = ES_GET_READY; return true; } return false; } bool C_MatchBloxEngine::StartGame() { if (m_State == ES_GET_READY) { BlockType l_Block; //start the session timer l_Block = m_pCurrentSession->StartSession(); //move a block into the sky m_pBlock[(int)l_Block]->SetPos(0.0, 0.0, 15.0); m_State = ES_PLAYING_GRAB_BLOCK; return true; } return false; } bool C_MatchBloxEngine::Pause() { //only pause when playing if (m_State == ES_PLAYING_GRAB_BLOCK || m_State == ES_PLAYING_PUT_BLOCK) { //save current state m_SavedState = m_State; //probably do something with a time variable //set current state to paused m_State = ES_PAUSED; return true; } return false; } bool C_MatchBloxEngine::Resume() { if (m_State == ES_PAUSED) { //restore previous state m_State = m_SavedState; //restore timers // return true; } return false; } bool C_MatchBloxEngine::Abort() { //abort when not in error or init state if (m_State != ES_ERROR && m_State != ES_INITIALISED) { //set state to initialised m_State = ES_INITIALISED; //.. return true; } return false; } bool C_MatchBloxEngine::LoadModels(const char* f_strModelDir) { MatProps_t l_Mat; std::string l_BaseName = f_strModelDir; //create the environment mapped cube m_pEnvMap = new C_Environment("envmaps/brightday2_", 50.0); //load the bitmaps for the textures LoadTexture((l_BaseName + "/wood1.bmp").c_str(), m_uiWood1Tex); LoadTexture((l_BaseName + "/wood2.bmp").c_str(), m_uiWood2Tex); LoadTexture((l_BaseName + "/wood3.bmp").c_str(), m_uiWood3Tex); //load the block models //red squares l_Mat.setAmb(1.0, 0.0, 0.0, 1.0); l_Mat.setDif(1.0, 0.0, 0.0, 1.0); m_pBlock[BT_SQUARE] = new C_Block((l_BaseName + "/square.obj").c_str(), m_uiWood1Tex, l_Mat); if (!m_pBlock[BT_SQUARE]->Initialized()) return false; //yellow cricles l_Mat.setAmb(0.0, 1.0, 1.0, 1.0); l_Mat.setDif(0.0, 1.0, 1.0, 1.0); m_pBlock[BT_CIRCLE] = new C_Block((l_BaseName + "/circle.obj").c_str(), m_uiWood1Tex, l_Mat); if (!m_pBlock[BT_CIRCLE]->Initialized()) return false; //green triangles l_Mat.setAmb(0.0, 1.0, 0.0, 1.0); l_Mat.setDif(0.0, 1.0, 0.0, 1.0); m_pBlock[BT_TRIANGLE] = new C_Block((l_BaseName + "/triangle.obj").c_str(), m_uiWood1Tex, l_Mat); if (!m_pBlock[BT_TRIANGLE]->Initialized()) return false; //blue crosses l_Mat.setAmb(0.0, 0.0, 1.0, 1.0); l_Mat.setDif(0.0, 0.0, 1.0, 1.0); m_pBlock[BT_CROSS] = new C_Block((l_BaseName + "/cross.obj").c_str(), m_uiWood1Tex, l_Mat); if (!m_pBlock[BT_CROSS]->Initialized()) return false; //load the hand??? //Load the box tiles l_Mat.setAmb(1.0, 1.0, 1.0, 1.0); l_Mat.setDif(1.0, 1.0, 1.0, 1.0); m_pTiles[BT_SQUARE] = new C_3DObject((l_BaseName + "/tile_square.obj").c_str(), m_uiWood3Tex, l_Mat); if (!m_pTiles[BT_SQUARE]->Initialized()) return false; m_pTiles[BT_CIRCLE] = new C_3DObject((l_BaseName + "/tile_circle.obj").c_str(), m_uiWood3Tex, l_Mat); if (!m_pTiles[BT_CIRCLE]->Initialized()) return false; m_pTiles[BT_TRIANGLE] = new C_3DObject((l_BaseName + "/tile_triangle.obj").c_str(), m_uiWood3Tex, l_Mat); if (!m_pTiles[BT_TRIANGLE]->Initialized()) return false; m_pTiles[BT_CROSS] = new C_3DObject((l_BaseName + "/tile_cross.obj").c_str(), m_uiWood3Tex, l_Mat); if (!m_pTiles[BT_CROSS]->Initialized()) return false; m_pTiles[4] = new C_3DObject((l_BaseName + "/tile_no_hole.obj").c_str(), m_uiWood3Tex, l_Mat); if (!m_pTiles[4]->Initialized()) return false; //Load the box models m_pBox[0] = new C_Box((l_BaseName + "/box_small.obj").c_str(), m_uiWood2Tex, l_Mat, 2, 2, m_pTiles); if (!m_pBox[0]->Initialized()) return false; m_pBox[1] = new C_Box((l_BaseName + "/box_med.obj").c_str(), m_uiWood2Tex, l_Mat, 4, 2, m_pTiles); if (!m_pBox[1]->Initialized()) return false; m_pBox[2] = new C_Box((l_BaseName + "/box_large.obj").c_str(), m_uiWood2Tex, l_Mat, 4, 4, m_pTiles); if (!m_pBox[2]->Initialized()) return false; return true; } void C_MatchBloxEngine::DeleteModels() { //delete objects delete m_pEnvMap; delete m_pBlock[0]; delete m_pBlock[1]; delete m_pBlock[2]; delete m_pBlock[3]; //delete m_pHand; delete m_pBox[0]; delete m_pBox[1]; delete m_pBox[2]; delete m_pTiles[0]; delete m_pTiles[1]; delete m_pTiles[2]; delete m_pTiles[3]; delete m_pTiles[4]; //delete textures glDeleteTextures(1, &m_uiWood1Tex); glDeleteTextures(1, &m_uiWood2Tex); glDeleteTextures(1, &m_uiWood3Tex); } void C_MatchBloxEngine::LoadTexture(const char* f_BmpName, GLuint &f_uiTexHandle) { BitmapStruct l_Bmp; l_Bmp = BitmapLoad((char*)f_BmpName); f_uiTexHandle = (GLuint)l_Bmp.m_iImageId; glBindTexture(GL_TEXTURE_2D, f_uiTexHandle); //set the texture paramaters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } void C_MatchBloxEngine::CursorMove(Vect3D_t &f_NewCursorPos) { //check the state to see what 3d object currently has to be considered to //be the cursor currently is and which bounding box we need to check for overlap BoundingBox_t l_CursBBox; bool l_bCollision = false; //indicates a collission has happend switch (m_State) { case ES_PLAYING_PUT_BLOCK: //cursor is the current block figure (that is being held by the player) //translate the bounding box of the block with the cursor position l_CursBBox = m_pBlock[m_CurrentBlock]->GetBoundingBox() + f_NewCursorPos; break; default: //cursor is the hand object l_CursBBox = m_pHand->GetBoundingBox() + f_NewCursorPos; break; } //now we have the bounding box of the cursor which we use to do some simple hit tests //make sure the cursor is still completely contained in the world bounding box if (!m_WorldBox.Contains(l_CursBBox)) { //restore the previous cursor position, because the new one is invalid //... nothing to do actually //maybe generate some vibration event and collision animation??? l_bCollision = true; } else { //check for bounding box overlap with the static elements in the scene //actually only the block box if (m_pBox[m_CurrentBox]->GetAbsBoundBox().Overlap(l_CursBBox)) { //overlap with the block box, a collision is very likely so set //collision to true and reset to false when the player is putting //the block in the right hole (if the player is holding a block //that is, if the player isn't then there is certainly a collision) l_bCollision = true; //check if we are holding a block that has to be put in the box if (m_State == ES_PLAYING_PUT_BLOCK) { } else { //we are not holding a block so every contact with the //block box is a collision l_bCollision = true; } } } } bool C_MatchBloxEngine::CursorMove_PutBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CursBBox) { //check if the block is being put in the right hole //by testing whether the position of the cursor is close //enough to the center of the correct hole //note that the hole positions are relative to the position //of the box bool l_bCollision = false; Vect3D_t l_AbsHolePos = m_pBox[m_CurrentBox]->GetPos() + m_pTiles[m_CurrentBlock]->GetPos(); Vect3D_t l_PosDif = l_AbsHolePos - f_CursPos; double l_dXZProximity = l_PosDif.x * l_PosDif.x + l_PosDif.y * l_PosDif.y; if (l_dXZProximity < m_GameSettings.m_dMinProximity) { //the block the player is holding is considered to be in the right hole //l_bCollision = false; //?? would it not be better to check for bounding box intersection with hole? l_bCollision = !(m_pTiles[m_CurrentBlock]->GetAbsBoundBox() + m_pBox[m_CurrentBox]->GetPos()).Overlap(f_CursBBox); //now check if the block is far enough in the hole to count as a point if (l_PosDif.z > m_GameSettings.m_dHoleDepth) { //yipee!! we have got a winner!! m_CurrentBlock = m_pCurrentSession->NewTurn(); //m_GameState } } return false; } bool C_MatchBloxEngine::CursorMove_GrabBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CursBBox) { //grabbing a block: just check for bounding box intersection if (m_pBlock[(int)m_CurrentBlock]->GetAbsBoundBox().Overlap(f_CursBBox)) { } return true; }