From feacf51e22520a397115fd8cc1a243c305bcb90d Mon Sep 17 00:00:00 2001 From: Dennis Peeten Date: Tue, 20 May 2008 07:38:10 +0000 Subject: --- MatchBloxEngine/MatchBloxEngine/C_3DObject.cpp | 8 +- MatchBloxEngine/MatchBloxEngine/C_3DObject.h | 1 + .../MatchBloxEngine/C_MatchBloxEngine.cpp | 186 ++++++++++++++++++--- .../MatchBloxEngine/C_MatchBloxEngine.h | 105 +++++++++++- MatchBloxEngine/MatchBloxEngine/Makefile | 2 +- MatchBloxEngine/MatchBloxEngine/typedefs.h | 90 ++++++---- 6 files changed, 326 insertions(+), 66 deletions(-) diff --git a/MatchBloxEngine/MatchBloxEngine/C_3DObject.cpp b/MatchBloxEngine/MatchBloxEngine/C_3DObject.cpp index 0b819e7..75e7ead 100644 --- a/MatchBloxEngine/MatchBloxEngine/C_3DObject.cpp +++ b/MatchBloxEngine/MatchBloxEngine/C_3DObject.cpp @@ -147,9 +147,9 @@ bool C_3DObject::CreateObject(const char *f_pFilePath) << "\nNormals: " << l_Geom.m_norms.size()-1 << "\nTexCrds: " << l_Geom.m_texs.size()-1 << "\nTriangles: " << l_Geom.m_triangles.size() - << "\nBoundBox: x(" << m_BBox.m_dLeft << "," << m_BBox.m_dRight << ")" - << "\n y(" << m_BBox.m_dBottom << "," << m_BBox.m_dTop << ")" - << "\n z(" << m_BBox.m_dFront << "," << m_BBox.m_dBack << ")" + << "\nBoundBox: x(" << m_BBox.m_Min.x << "," << m_BBox.m_Max.x << ")" + << "\n y(" << m_BBox.m_Min.y << "," << m_BBox.m_Max.y << ")" + << "\n z(" << m_BBox.m_Min.z << "," << m_BBox.m_Max.z << ")" << std::endl; if(!l_bParseOk) @@ -250,7 +250,7 @@ bool C_3DObject::LoadGeometryData(const char *f_pFilePath, Geometry_t &f_Geom) { f_Geom.m_verts.push_back(l_v3); //update boundingbox - UpdBBox(m_BBox, l_v3); + m_BBox << l_v3; } break; diff --git a/MatchBloxEngine/MatchBloxEngine/C_3DObject.h b/MatchBloxEngine/MatchBloxEngine/C_3DObject.h index 4027596..55ae123 100644 --- a/MatchBloxEngine/MatchBloxEngine/C_3DObject.h +++ b/MatchBloxEngine/MatchBloxEngine/C_3DObject.h @@ -37,6 +37,7 @@ public: inline const Vect3D_t& GetRot() { return m_Rot; } inline const Vect3D_t& GetScale() { return m_Scale; } inline const BoundingBox_t& GetBoundingBox() { return m_BBox; } + inline const BoundingBox_t& GetAbsBoundBox() { return m_BBox + m_Pos; } inline bool Initialized() { return m_bDispListValid; } void TransRotateScale(); //applies the scaling, translation and rotation diff --git a/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.cpp b/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.cpp index 7e17b1b..80767b8 100644 --- a/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.cpp +++ b/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.cpp @@ -15,7 +15,9 @@ #include "bitmap.h" C_MatchBloxEngine::C_MatchBloxEngine(const char *f_strModelPath, - const char *f_strLogFile) + const char *f_strLogFile, + GameSettings f_GameSettings) +: m_GameSettings(f_GameSettings) { //create logger @@ -37,19 +39,10 @@ C_MatchBloxEngine::C_MatchBloxEngine(const char *f_strModelPath, //init vars m_CurrentBox = BS_SMALL; - //debug - m_pBox[0]->SetPos(0.0, -5.0, -15.0); - m_pBox[0]->SetRot(45.0, 0.0, 0.0); - m_pBox[0]->RandomizeTiles(); - - m_pBlock[0]->SetPos(-6.0, 1.0, -10.0); - m_pBlock[0]->SetRot(90.0, 0.0, 0.0); - m_pBlock[1]->SetPos(-2.0, 1.0, -10.0); - m_pBlock[1]->SetRot(90.0, 0.0, 0.0); - m_pBlock[2]->SetPos(2.0, 1.0, -10.0); - m_pBlock[2]->SetRot(90.0, 0.0, 0.0); - m_pBlock[3]->SetPos(6.0, 1.0, -10.0); - m_pBlock[3]->SetRot(90.0, 0.0, 0.0); + //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() @@ -60,10 +53,28 @@ C_MatchBloxEngine::~C_MatchBloxEngine() DeleteModels(); } -GameResult C_MatchBloxEngine::GameStep(msgQueue &f_Queue) +GameResult C_MatchBloxEngine::ProcessMsgs(msgQueue &f_Queue) { + msgStruct l_msg; + //process message queue - return GR_ERROR; + 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) @@ -71,10 +82,13 @@ void C_MatchBloxEngine::Render_Basics(unsigned int f_uiElapsedTime) //render the environment m_pEnvMap->Render(); - m_pBox[(intptr_t)m_CurrentBox]->Render(); - for (int i=0; i<4; i++) - m_pBlock[i]->Render(f_uiElapsedTime); -// m_pHand->Render(f_uiElapsedTime); + if (m_pCurrentSession) + { + m_pBox[(int)m_pCurrentSession->m_BoxSize]->Render(); + for (int i=0; i<4; i++) + m_pBlock[i]->Render(f_uiElapsedTime); + // m_pHand->Render(f_uiElapsedTime); + } } void C_MatchBloxEngine::Render(unsigned int f_uiElapsedTime) @@ -148,15 +162,17 @@ bool C_MatchBloxEngine::NewGame(int f_iUserID, int f_iGameId, BoxSize f_BS) { //log new game - //prepare a fresh box - m_CurrentBox = f_BS; - m_pBox[(int)m_CurrentBox]->RandomizeTiles(); + //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(); + //init box's position + m_pBox[(int)m_pCurrentSession->m_BoxSize]->SetPos(0.0, -6.0, -15.0); //set state to GET READY m_State = ES_GET_READY; - //init object positions - m_pBox[(int)m_CurrentBox]->SetPos(0.0, -6.0, -15.0); return true; } @@ -165,6 +181,20 @@ bool C_MatchBloxEngine::NewGame(int f_iUserID, int f_iGameId, BoxSize f_BS) 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; } @@ -178,7 +208,7 @@ bool C_MatchBloxEngine::Pause() m_SavedState = m_State; //probably do something with a time variable - + //set current state to paused m_State = ES_PAUSED; @@ -346,3 +376,107 @@ void C_MatchBloxEngine::LoadTexture(const char* f_BmpName, GLuint &f_uiTexHandle 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; + } + } + } + +} + +GameResult_t C_MatchBloxEngine::CursorMove_PutBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CusrBBox) +{ + //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 + 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_pGameSession->NewTurn(); + + m_GameState + } + + + } +} + +GameResult_t C_MatchBloxEngine::CursorMove_GrabBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CusrBBox) +{ + //grabbing a block: just check for bounding box intersection + if (m_pBlock[(int)m_CurrentBlock)->GetAbsBoundBox().Overlap(f_CursBBox)) + { + + } +} + diff --git a/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.h b/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.h index 97aa892..5ef6c5d 100644 --- a/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.h +++ b/MatchBloxEngine/MatchBloxEngine/C_MatchBloxEngine.h @@ -44,15 +44,99 @@ enum BoxSize 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; + BoxSize m_BoxSize; + + GameSession(int f_iNrOfBlocks, BoxSize f_BS) + : m_iTotalTurns(f_iNrOfBlocks), m_iCurrentTurn(0), + m_BoxSize(f_BS) + { + 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; + } + BlockType StartSession() + { + m_uiSessionStart = m_uiTurnStart = glutGet(GLUT_ELAPSED_TIME); + return GetRandomBlockType(); + } + BlockType NewTurn() + { + unsigned int l_uiTime = glutGet(GLUT_ELAPSED_TIME); + + //save turn result + m_puiTurnResult[m_iCurrentTurn] = l_uiTime - m_uiTurnStart; + m_iCurrentTurn++; + m_uiTurnStart = l_uiTime; + + return GetRandomBlockType(); + } + 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); + const char *f_strLogFile + GameSettings f_GameSettings); ~C_MatchBloxEngine(); - GameResult GameStep(msgQueue &f_Queue); + GameResult ProcessMsgs(msgQueue &f_Queue); void Render(unsigned int f_uiElapsedTime); bool NewGame(int f_iUserID, int f_iGameId, BoxSize f_BS); @@ -74,13 +158,26 @@ private: m_uiWood3Tex; EngineState m_State, m_SavedState; - BoxSize m_CurrentBox; + GameSession *m_pCurrentSession; + GameSettings m_GameSettings; - void Render_Basics(unsigned int f_uiElapsedTime); + 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 Render_Basics(unsigned int f_uiElapsedTime); + + //event/input handlers + void CursorMove(Vect3D_t &f_NewCursorPos); + GameResult_t CursorMove_PutBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CusrBBox); + GameResult_t CursorMove_GrabBlock(Vect3D_t &f_CursPos, BoundingBox_t &f_CusrBBox); + }; #endif //C_MATCHBLOXENGINE_HEADER_FILE diff --git a/MatchBloxEngine/MatchBloxEngine/Makefile b/MatchBloxEngine/MatchBloxEngine/Makefile index 383ce98..e6e6668 100644 --- a/MatchBloxEngine/MatchBloxEngine/Makefile +++ b/MatchBloxEngine/MatchBloxEngine/Makefile @@ -27,5 +27,5 @@ MatchBloxEngine: $(objects) include $(sources:.cpp=.d) clean: - -rm MatchBloxEngine $(objects) *.d + -rm MatchBloxEngine $(objects) *.d *.d.* diff --git a/MatchBloxEngine/MatchBloxEngine/typedefs.h b/MatchBloxEngine/MatchBloxEngine/typedefs.h index 0262c14..0b9190c 100644 --- a/MatchBloxEngine/MatchBloxEngine/typedefs.h +++ b/MatchBloxEngine/MatchBloxEngine/typedefs.h @@ -5,22 +5,6 @@ #include #include -typedef struct bb -{ - bb() { - //init a bounding box with the min values set to max double and visa versa - m_dLeft = m_dBottom = m_dFront = std::numeric_limits::max(); - m_dRight = m_dTop = m_dBack = -std::numeric_limits::max(); - } - - double m_dLeft, //min x - m_dBottom, //min y - m_dFront, //min z - m_dRight, //max x - m_dTop, //max y - m_dBack; //max z - -} BoundingBox_t; typedef struct vec3d { @@ -55,23 +39,67 @@ typedef struct vec3d { return vec3d(*this) *= scal; } } Vect3D_t; +typedef struct bb +{ + Vect3D_t m_Min, //minimal corner vertex (-x, -y, -z) + m_Max; //maximal corner vertex (+x, +y, +z) + //default constructor creates a maximum inverted bounding box + bb() + { + //init a bounding box with the min values set to max double and visa versa + double l_doubleMax = std::numeric_limits::max(); + m_Min = Vect3D_t(l_doubleMax, l_doubleMax, l_doubleMax); + m_Max = Vect3D_t(-l_doubleMax, -l_doubleMax, -l_doubleMax); + } + + //copy constructor + bb(const bb &b) : m_Min(b.m_Min), m_Max(b.m_Max) {} + + //translating a bounding box + inline bb& operator+=(const Vect3D_t &v) + { m_Min += v; m_Max += v; return *this; } + inline const bb& operator+(const Vect3D_t &v) + { return (bb(*this) += v); } + + //update the bounding box min/max coords with vertex v + inline bb& operator<<(const Vect3D_t &v) + { + if (v.x < m_Min.x) m_Min.x = v.x; + else if (v.x > m_Max.x) m_Max.x = v.x; + if (v.y < m_Min.y) m_Min.y = v.y; + else if (v.y > m_Max.y) m_Max.y = v.y; + if (v.z < m_Min.z) m_Min.z = v.z; + else if (v.z > m_Max.z) m_Max.z = v.z; + return *this; + } + + inline bool Contains(const Vect3D_t &v) + { + //check if the point is contained in the box + return m_Min.x < v.x && v.x < m_Max.x && + m_Min.y < v.y && v.y < m_Max.y && + m_Min.z < v.z && v.z < m_Max.z; + } + + inline bool Contains(const bb& b) + { + return Contains(b.m_Min) && Contains(b.m_Max); + } + + inline bool Overlap(const bb& rhs) + { + //check if the boxes overlap in all three axis + return ( ( m_Min.x < rhs.m_Min.x && rhs.m_Min.x < rhs.m_Max.x) || + ( m_Min.x < rhs.m_Max.x && rhs.m_Max.x < rhs.m_Max.x) ) && + ( ( m_Min.y < rhs.m_Min.y && rhs.m_Min.y < rhs.m_Max.y) || + ( m_Min.y < rhs.m_Max.y && rhs.m_Max.y < rhs.m_Max.y) ) && + ( ( m_Min.z < rhs.m_Min.z && rhs.m_Min.z < rhs.m_Max.z) || + ( m_Min.z < rhs.m_Max.z && rhs.m_Max.z < rhs.m_Max.z) ); + } + +} BoundingBox_t; -inline void UpdBBox(BoundingBox_t &B, Vect3D_t &V) -{ - if (V.x < B.m_dLeft) - B.m_dLeft = V.x; - else if (V.x > B.m_dRight) - B.m_dRight = V.x; - if (V.y < B.m_dBottom) - B.m_dBottom = V.y; - else if (V.y > B.m_dTop) - B.m_dTop = V.y; - if (V.z < B.m_dFront) - B.m_dFront = V.z; - else if (V.z > B.m_dBack) - B.m_dBack = V.z; -}; typedef struct triangle { -- cgit v0.12