diff --git a/Code/DanBias.sln b/Code/DanBias.sln index 033e050e..51ad5665 100644 --- a/Code/DanBias.sln +++ b/Code/DanBias.sln @@ -697,7 +697,8 @@ Global {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|Win32.ActiveCfg = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|Win32.Build.0 = Release|Win32 - {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|x64.ActiveCfg = Release|Win32 + {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|x64.ActiveCfg = Release|x64 + {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|x64.Build.0 = Release|x64 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|x86.ActiveCfg = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.MinSizeRel|x86.Build.0 = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.Release|Any CPU.ActiveCfg = Release|Win32 @@ -714,7 +715,8 @@ Global {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|Win32.Build.0 = Release|Win32 - {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|x64.ActiveCfg = Release|Win32 + {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|x64.Build.0 = Release|x64 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63}.RelWithDebInfo|x86.Build.0 = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.Debug|Any CPU.ActiveCfg = Debug|Win32 @@ -731,7 +733,8 @@ Global {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|Win32.ActiveCfg = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|Win32.Build.0 = Release|Win32 - {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|x64.ActiveCfg = Release|Win32 + {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|x64.ActiveCfg = Release|x64 + {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|x64.Build.0 = Release|x64 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|x86.ActiveCfg = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.MinSizeRel|x86.Build.0 = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.Release|Any CPU.ActiveCfg = Release|Win32 @@ -748,7 +751,8 @@ Global {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|Win32.Build.0 = Release|Win32 - {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x64.ActiveCfg = Release|Win32 + {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x64.Build.0 = Release|x64 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x86.Build.0 = Release|Win32 EndGlobalSection @@ -764,7 +768,6 @@ Global {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012} = {20720CA7-795C-45AD-A302-9383A6DD503A} {8690FDDF-C5B7-4C42-A337-BD5243F29B85} = {20720CA7-795C-45AD-A302-9383A6DD503A} {2A1BC987-AF42-4500-802D-89CD32FC1309} = {20720CA7-795C-45AD-A302-9383A6DD503A} - {6391E709-D9FA-4FEF-A3B9-4343DB5A0C63} = {20720CA7-795C-45AD-A302-9383A6DD503A} {C4C76A8D-44C5-4452-9F61-39C7E01CBDB4} = {F156EEBC-0195-4020-8700-4433208DE12B} {3EA5F14D-2A71-4588-A69D-87C4571C580F} = {F156EEBC-0195-4020-8700-4433208DE12B} {7E3990D2-3D94-465C-B58D-64A74B3ECF9B} = {1322B12B-5E37-448A-AAAF-F637460DCB23} @@ -773,6 +776,5 @@ Global {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE} = {1322B12B-5E37-448A-AAAF-F637460DCB23} {604A12A7-07BF-4482-BDF3-7101C811F121} = {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012} {C8CBA520-5D7D-4D61-A8DA-6E05FD132BCB} = {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012} - {67D0FB00-FF1F-4DE4-84BD-664AE93D25EE} = {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012} EndGlobalSection EndGlobal diff --git a/Code/Game/GameClient/DanBiasGame_Impl.cpp b/Code/Game/GameClient/DanBiasGame_Impl.cpp index 2a46b8d6..b461f908 100644 --- a/Code/Game/GameClient/DanBiasGame_Impl.cpp +++ b/Code/Game/GameClient/DanBiasGame_Impl.cpp @@ -103,7 +103,6 @@ namespace DanBias float dt = (float)data.timer.getElapsedSeconds(); data.timer.reset(); - Graphics::API::Update( dt ); data.capFrame += dt; if(data.capFrame > 0.03f) @@ -115,6 +114,8 @@ namespace DanBias case Result_error: return DanBiasClientReturn_Error; default: break; } + + Graphics::API::Update( data.capFrame ); if(Render() != S_OK) return DanBiasClientReturn_Error; data.capFrame -= 0.03f; diff --git a/Code/Game/GameClient/GameClientState/C_obj/C_DynamicObj.cpp b/Code/Game/GameClient/GameClientState/C_obj/C_DynamicObj.cpp index 73dd20b5..26619c0e 100644 --- a/Code/Game/GameClient/GameClientState/C_obj/C_DynamicObj.cpp +++ b/Code/Game/GameClient/GameClientState/C_obj/C_DynamicObj.cpp @@ -3,6 +3,7 @@ using namespace DanBias::Client; C_DynamicObj::C_DynamicObj(void) + :C_Object() { } diff --git a/Code/Game/GameClient/GameClientState/C_obj/C_StaticObj.cpp b/Code/Game/GameClient/GameClientState/C_obj/C_StaticObj.cpp index 42a12acd..22734a96 100644 --- a/Code/Game/GameClient/GameClientState/C_obj/C_StaticObj.cpp +++ b/Code/Game/GameClient/GameClientState/C_obj/C_StaticObj.cpp @@ -3,6 +3,7 @@ using namespace DanBias::Client; C_StaticObj::C_StaticObj(void) + :C_Object() { } diff --git a/Code/Game/GameClient/GameClientState/GameState.cpp b/Code/Game/GameClient/GameClientState/GameState.cpp index 078bc74b..37dda789 100644 --- a/Code/Game/GameClient/GameClientState/GameState.cpp +++ b/Code/Game/GameClient/GameClientState/GameState.cpp @@ -33,7 +33,8 @@ struct GameState::MyData ::std::map> *dynamicObjects; ::std::map> *lights; - C_Player player; + //C_Player player; + ::std::map> players; Camera_FPSV2 camera; int myId; @@ -75,7 +76,7 @@ bool GameState::Init( SharedStateContent &shared ) this->privData->camera.SetPerspectiveProjection( Utility::Value::Radian(90.0f), aspectRatio, 0.1f, 1000.0f ); Graphics::API::SetProjection( this->privData->camera.GetProjectionMatrix() ); gfxOp.AmbientValue = 0.5f; - gfxOp.GlobalGlowTint = Math::Float3(2,1,1); + gfxOp.GlobalGlowTint = Math::Float3(1,1,1); gfxOp.GlobalTint = Math::Float3(1,1,1); Graphics::API::SetOptions(gfxOp); @@ -113,8 +114,8 @@ void GameState::InitiatePlayer( int id, const std::string &modelName, const floa modelData.position = position; modelData.rotation = ArrayToQuaternion( rotation ); modelData.scale = scale; - StringToWstring( modelName, modelData.modelPath ); modelData.id = id; + StringToWstring(modelName,modelData.modelPath); // RB DEBUG RBInitData RBData; @@ -123,37 +124,30 @@ void GameState::InitiatePlayer( int id, const std::string &modelName, const floa RBData.scale = scale; RBData.type = RB_Type_Cube; // !RB DEBUG - if( isMyPlayer ) + C_Player *p = new C_Player(); + if( p->Init(modelData) ) { - if( this->privData->player.Init(modelData) ) - { - // RB DEBUG - this->privData->player.InitRB( RBData ); - // !RB DEBUG + // RB DEBUG + p->InitRB( RBData ); + // !RB DEBUG + // start with runing animation + p->playAnimation( L"run_forwards", true ); + (this->privData->players)[id] = p; + + if( isMyPlayer ) + { this->privData->myId = id; - this->privData->camera.SetPosition( this->privData->player.getPos() ); + this->privData->camera.SetPosition( p->getPos() ); Float3 offset = Float3( 0.0f ); // DEBUG position of camera so we can see the player model - //offset.y = this->privData->player.getScale().y * 5.0f; - //offset.z = this->privData->player.getScale().z * -5.0f; + offset.y = p->getScale().y * 5.0f; + offset.z = p->getScale().z * -5.0f; // !DEBUG this->privData->camera.SetHeadOffset( offset ); this->privData->camera.UpdateOrientation(); } } - else - { - C_DynamicObj *p = new C_DynamicObj(); - if( p->Init(modelData) ) - { - // RB DEBUG - this->privData->player.InitRB( RBData ); - // !RB DEBUG - - (*this->privData->dynamicObjects)[id] = p; - } - } } GameClientState::ClientState GameState::Update( float deltaTime ) @@ -187,7 +181,17 @@ bool GameState::Render() Oyster::Graphics::API::NewFrame(); // for debugging to be replaced with render weapon - this->privData->player.Render(); + auto playerObject = this->privData->players.begin(); + for( ; playerObject != this->privData->players.end(); ++playerObject ) + { + if(playerObject->second) + { + //if( this->privData->myId != playerObject->second->GetId() ) + { + playerObject->second->Render(); + } + } + } auto staticObject = this->privData->staticObjects->begin(); for( ; staticObject != this->privData->staticObjects->end(); ++staticObject ) @@ -211,11 +215,21 @@ bool GameState::Render() { Oyster::Graphics::API::StartRenderWireFrame(); - Oyster::Math3D::Float4x4 translation = Oyster::Math3D::TranslationMatrix(Float3( 0,132, 20)); - Oyster::Math3D::Float4x4 scale = Oyster::Math3D::ScalingMatrix(Float3( 0.5f, 0.5f, 0.5f)); - Oyster::Math3D::Float4x4 world = translation * scale; - Oyster::Graphics::API::RenderDebugCube( world ); - Oyster::Graphics::API::RenderDebugCube(this->privData->player.getRBWorld()); + playerObject = this->privData->players.begin(); + for( ; playerObject != this->privData->players.end(); ++playerObject ) + { + if(playerObject->second) + { + if( playerObject->second->getBRtype() == RB_Type_Cube) + { + Oyster::Graphics::API::RenderDebugCube( playerObject->second->getRBWorld()); + } + if( playerObject->second->getBRtype() == RB_Type_Sphere) + { + Oyster::Graphics::API::RenderDebugSphere( playerObject->second->getRBWorld()); + } + } + } staticObject = this->privData->staticObjects->begin(); for( ; staticObject != this->privData->staticObjects->end(); ++staticObject ) @@ -276,6 +290,12 @@ bool GameState::Release() Graphics::API::Option o = Graphics::API::GetOption(); if( privData ) { + auto playerObject = this->privData->players.begin(); + for( ; playerObject != this->privData->players.end(); ++playerObject ) + { + playerObject->second = nullptr; + } + auto staticObject = this->privData->staticObjects->begin(); for( ; staticObject != this->privData->staticObjects->end(); ++staticObject ) { @@ -381,6 +401,7 @@ void GameState::ReadKeyInput() this->key_showStats = false; } } + const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState::NetEvent &message ) { if( message.args.type == NetworkClient::ClientEventArgs::EventType_ProtocolFailedToSend ) @@ -459,42 +480,29 @@ const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState Protocol_ObjectPositionRotation decoded(data); Float3 position = decoded.position; Quaternion rotation = Quaternion( Float3(decoded.rotationQ), decoded.rotationQ[3] ); - - // if is this player. Remember to change camera - if( this->privData->myId == decoded.object_ID ) + C_Object *object; + object = (this->privData->players)[decoded.object_ID]; + if( !object) { - if( !Within(position.Dot(position), 2500.0f, 90000.0f) ) - { // HACK: bug trap - const char *breakPoint = "Something is wrong."; - position = Float3( 0.0f, 160.0f, 0.0f ); - } - - this->privData->camera.SetPosition( position ); - this->privData->camera.SetRotation( rotation ); - this->privData->player.setPos( position ); - this->privData->player.setRot( rotation ); - this->privData->player.updateWorld(); - // RB DEBUG - this->privData->player.setRBPos ( position ); - this->privData->player.setRBRot ( rotation ); - this->privData->player.updateRBWorld(); - // !RB DEBUG + // if it is not a player + object = (*this->privData->dynamicObjects)[decoded.object_ID]; } - else - { - C_DynamicObj *object = (*this->privData->dynamicObjects)[decoded.object_ID]; - if( object ) + if( object ) + { + if( this->privData->myId == decoded.object_ID ) { - object->setPos( position ); - object->setRot( rotation ); - object->updateWorld(); - // RB DEBUG - object->setRBPos ( position ); - object->setRBRot ( rotation ); - object->updateRBWorld(); - // !RB DEBUG + this->privData->camera.SetPosition( position ); + this->privData->camera.SetRotation( rotation ); } + object->setPos( position ); + object->setRot( rotation ); + object->updateWorld(); + // RB DEBUG + object->setRBPos ( position ); + object->setRBRot ( rotation ); + object->updateRBWorld(); + // !RB DEBUG } } return GameClientState::event_processed; @@ -534,7 +542,7 @@ const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState RBData.rotation = ArrayToQuaternion( decoded.position ); RBData.scale = Float3( decoded.scale ); - this->privData->player.InitRB( RBData ); + object->InitRB( RBData ); // !RB DEBUG (*this->privData->dynamicObjects)[decoded.object_ID] = object; @@ -553,17 +561,29 @@ const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState case protocol_Gameplay_ObjectWeaponEnergy: break; /** @todo TODO: implement */ case protocol_Gameplay_ObjectRespawn: { - // set player pos Protocol_ObjectRespawn decoded(data); - // move player. Remember to change camera - this->privData->camera.SetPosition( decoded.position ); - this->privData->player.setPos( decoded.position ); - this->privData->player.updateWorld(); - // RB DEBUG - this->privData->player.setRBPos ( decoded.position ); - this->privData->player.updateRBWorld(); - // !RB DEBUG + C_Object *object; + object = (this->privData->players)[decoded.objectID]; + if( !object) + { + // if it is not a player + object = (*this->privData->dynamicObjects)[decoded.objectID]; + } + + if( object ) + { + if( this->privData->myId == decoded.objectID ) + { + this->privData->camera.SetPosition( decoded.position ); + } + object->setPos( decoded.position ); + object->updateWorld(); + // RB DEBUG + object->setRBPos ( decoded.position ); + object->updateRBWorld(); + // !RB DEBUG + } this->currGameUI = this->gameUI; } return GameClientState::event_processed; @@ -571,6 +591,8 @@ const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState { Protocol_ObjectDie decoded(data); // if is this player. Remember to change camera + int killerID = decoded.killerID; + int victimID = decoded.objectID; if( this->privData->myId == decoded.objectID ) { this->currGameUI = this->respawnUI; @@ -581,7 +603,7 @@ const GameClientState::NetEvent & GameState::DataRecieved( const GameClientState return GameClientState::event_processed; case protocol_Gameplay_ObjectDisconnectPlayer: { - //Removes + //Remove the disconnected player Protocol_ObjectDisconnectPlayer decoded(data); auto object = this->privData->dynamicObjects->find( decoded.objectID ); if( object != this->privData->dynamicObjects->end() ) diff --git a/Code/Game/GameClient/GameClientState/GamingUI.cpp b/Code/Game/GameClient/GameClientState/GamingUI.cpp index 669b3d87..abe0a529 100644 --- a/Code/Game/GameClient/GameClientState/GamingUI.cpp +++ b/Code/Game/GameClient/GameClientState/GamingUI.cpp @@ -33,8 +33,12 @@ bool GamingUI::Init() // z value should be between 0.5 - 0.9 so that it will be behind other states // add textures and text this->plane = new Plane_UI(L"box_tex.png", Float3(0.5f, 0.0f, 0.5f), Float2(0.3f, 0.1f)); +<<<<<<< HEAD this->hp = new Text_UI(L"100", Float3(0.04f,0.91f,0.1f), Float2(0.1f,0.1f), Float4(1,0,0,1)); this->energy = new Text_UI(L"100", Float3(0.8f,0.91f,0.1f), Float2(0.4f,0.1f), Float4(1,1,0,1)); +======= + this->text = new Text_UI(L"hej", Float3(0.3f,0.0f,0.1f), Float2(0.1f,0.1f)); +>>>>>>> origin/GameLogic return true; } @@ -109,7 +113,7 @@ void GamingUI::ReadKeyInput() float yaw = this->input->GetYaw(); //if( yaw != 0.0f ) //This made the camera reset to a specific rotation. { - this->netClient->Send( Protocol_PlayerLeftTurn(yaw * mouseSensitivity) ); + this->netClient->Send( Protocol_PlayerLeftTurn(yaw * mouseSensitivity, camera->GetLook()) ); } } diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 8c096617..1baed344 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -62,6 +62,8 @@ bool LanMenuState::Init( SharedStateContent &shared ) this->privData->connectIP->ReserveLines( 1 ); this->privData->connectIP->AppendText( L"127.0.0.1" ); //this->privData->connectIP->AppendText( L"194.47.150.206" ); // HACK: connecting to Dennis's server + //this->privData->connectIP->AppendText( L"194.47.150.189" ); // HACK: connecting to Robins server + this->privData->connectIP->SetFontHeight( 0.08f ); this->privData->connectIP->SetLineSpacing( 0.005f ); this->privData->connectIP->SetTopAligned(); diff --git a/Code/Game/GameClient/GameClientState/NetLoadState.cpp b/Code/Game/GameClient/GameClientState/NetLoadState.cpp index 9ef0dac9..5553303e 100644 --- a/Code/Game/GameClient/GameClientState/NetLoadState.cpp +++ b/Code/Game/GameClient/GameClientState/NetLoadState.cpp @@ -231,7 +231,7 @@ void NetLoadState::LoadGame( const ::std::string &fileName ) pointLight.Color = light->color; pointLight.Pos = light->position; pointLight.Bright = light->intensity; - pointLight.Radius = light->raduis; + pointLight.Radius = light->radius; C_Light *newLight = new C_Light( pointLight, objectID ); @@ -242,5 +242,7 @@ void NetLoadState::LoadGame( const ::std::string &fileName ) } } + Graphics::API::EndLoadingModels(); + this->privData->nextState = ClientState::ClientState_Game; } diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.cpp b/Code/Game/GameLogic/AttatchmentMassDriver.cpp index 89de1f3e..62f3599e 100644 --- a/Code/Game/GameLogic/AttatchmentMassDriver.cpp +++ b/Code/Game/GameLogic/AttatchmentMassDriver.cpp @@ -11,10 +11,18 @@ AttatchmentMassDriver::AttatchmentMassDriver(void) this->owner = 0; this->heldObject = NULL; this->hasObject = false; + this->currentEnergy = StandardMaxEnergy; + this->maxEnergy = StandardMaxEnergy; + this->rechargeRate = StandardrechargeRate; + this->force = Standardforce; } AttatchmentMassDriver::AttatchmentMassDriver(Player &owner) { + this->currentEnergy = StandardMaxEnergy; + this->maxEnergy = StandardMaxEnergy; + this->rechargeRate = StandardrechargeRate; + this->force = Standardforce; this->owner = &owner; this->heldObject = NULL; @@ -36,15 +44,27 @@ void AttatchmentMassDriver::UseAttatchment(const GameLogic::WEAPON_FIRE &usage, switch (usage) { case WEAPON_FIRE::WEAPON_USE_PRIMARY_PRESS: - ForcePush(usage,dt); + if(currentEnergy >= 90.0f) + { + currentEnergy -= 90.0f; + ForcePush(usage,dt); + } break; case WEAPON_FIRE::WEAPON_USE_SECONDARY_PRESS: - ForcePull(usage,dt); + if(currentEnergy >= 1.0f) + { + currentEnergy -= 1.0f; + ForcePull(usage,dt); + } break; case WEAPON_FIRE::WEAPON_USE_UTILLITY_PRESS: - ForceZip(usage,dt); + if(currentEnergy >= 90.0f) + { + currentEnergy -= 90.0f; + ForceZip(usage,dt); + } break; } @@ -56,19 +76,22 @@ void AttatchmentMassDriver::Update(float dt) //update position of heldObject if there is an object being held if(hasObject) { - //Oyster::Physics::ICustomBody::State state; - //state = heldObject->GetState(); Oyster::Math::Float3 ownerPos = owner->GetPosition(); Oyster::Physics::ICustomBody::State ownerState = owner->GetRigidBody()->GetState(); Oyster::Math::Float3 up = -ownerState.GetOrientation().v[2]; up *= -0.3f; - Oyster::Math::Float3 pos = ownerPos + (owner->GetLookDir().GetNormalized()*5); - - //state.centerPos = pos; + Oyster::Math::Float3 pos = ownerPos + (owner->GetLookDir().GetNormalized()*2); heldObject->SetPosition(pos); + heldObject->SetLinearVelocity(Oyster::Math::Float3::null); - //heldObject->SetState(state); + currentEnergy += rechargeRate * 0.5f; //rechargeRate is halfed if you are holding an object } + else + { + currentEnergy += rechargeRate; + } + + } /******************************************************** @@ -82,10 +105,9 @@ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float if(hasObject) { - Oyster::Physics::API::Instance().ReleaseFromLimbo(heldObject); - pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (400); + pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (this->force); heldObject->ApplyImpulse((Oyster::Math::Float3)pushForce); - + ((DynamicObject*)(heldObject->GetCustomTag()))->RemoveManipulation(); hasObject = false; heldObject = NULL; return; @@ -96,14 +118,13 @@ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float Oyster::Math::Float lenght = 10; Oyster::Math::Float3 pos = owner->GetRigidBody()->GetState().centerPos; - pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (400); + pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (this->force * 0.6f); Oyster::Collision3D::Cone *hitCone = new Oyster::Collision3D::Cone(lenght,pos,(Oyster::Math::Float4)owner->GetRigidBody()->GetState().quaternion,radius); - - forcePushData args; args.pushForce = pushForce; + args.p = this->owner; Oyster::Physics::API::Instance().ApplyEffect(hitCone,&args,ForcePushAction); @@ -115,7 +136,7 @@ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float ********************************************************/ void AttatchmentMassDriver::ForceZip(const WEAPON_FIRE &usage, float dt) { - Oyster::Math::Float3 force = Oyster::Math::Float4(this->owner->GetLookDir()) * (1000); + Oyster::Math::Float3 force = Oyster::Math::Float4(this->owner->GetLookDir()) * (this->force); this->owner->GetRigidBody()->ApplyImpulse(force); } @@ -136,11 +157,12 @@ void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) Oyster::Math::Float lenght = 10; Oyster::Math::Float3 pos = owner->GetRigidBody()->GetState().centerPos; - Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (100); + Oyster::Math::Float4 pullForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (this->force * 0.2); Oyster::Collision3D::Cone *hitCone = new Oyster::Collision3D::Cone(lenght,pos,(Oyster::Math::Float4)owner->GetRigidBody()->GetState().quaternion,radius); forcePushData args; - args.pushForce = -pushForce; + args.pushForce = -pullForce; + args.p = this->owner; Oyster::Physics::API::Instance().ApplyEffect(hitCone,&args,ForcePushAction); @@ -149,7 +171,7 @@ void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) void AttatchmentMassDriver::PickUpObject(const WEAPON_FIRE &usage, float dt) { - Oyster::Math::Float3 pos = owner->GetPosition() + owner->GetLookDir().GetNormalized()*5; + Oyster::Math::Float3 pos = owner->GetPosition() + owner->GetLookDir().GetNormalized()*2; Oyster::Collision3D::Sphere *hitSphere = new Oyster::Collision3D::Sphere(pos,10); Oyster::Physics::API::Instance().ApplyEffect(hitSphere,this,AttemptPickUp); diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.h b/Code/Game/GameLogic/AttatchmentMassDriver.h index 51368e91..385fcca3 100644 --- a/Code/Game/GameLogic/AttatchmentMassDriver.h +++ b/Code/Game/GameLogic/AttatchmentMassDriver.h @@ -4,8 +4,14 @@ #ifndef ATTATCHMENTMASSDRIVER_H #define ATTATCHMENTMASSDRIVER_H #include "IAttatchment.h" + + + namespace GameLogic { + const Oyster::Math::Float StandardMaxEnergy = 100.0f; + const Oyster::Math::Float StandardrechargeRate = 0.5f; + const Oyster::Math::Float Standardforce = 1000.0f; class AttatchmentMassDriver : public IAttatchment { @@ -53,6 +59,19 @@ namespace GameLogic Oyster::Physics::ICustomBody *heldObject; bool hasObject; + Oyster::Math::Float force; + + Oyster::Math::Float maxEnergy; + Oyster::Math::Float currentEnergy; + + Oyster::Math::Float rechargeRate; + + struct Aim + { + + }; + + }; } #endif diff --git a/Code/Game/GameLogic/CollisionManager.cpp b/Code/Game/GameLogic/CollisionManager.cpp index 7b2b7ce1..d60d16ce 100644 --- a/Code/Game/GameLogic/CollisionManager.cpp +++ b/Code/Game/GameLogic/CollisionManager.cpp @@ -20,37 +20,50 @@ using namespace GameLogic; void Teleport(Oyster::Physics::ICustomBody &obj, Oyster::Math::Float3 target); //Physics::ICustomBody::SubscriptMessage - void Player::PlayerCollision(Oyster::Physics::ICustomBody *rigidBodyPlayer, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + void Player::PlayerCollision(Oyster::Physics::ICustomBody *objA, Oyster::Physics::ICustomBody *objB, Oyster::Math::Float kineticEnergyLoss) { - Player *player = ((Player*)(rigidBodyPlayer->GetCustomTag())); - Object *realObj = (Object*)obj->GetCustomTag(); //needs to be changed? + Object *realObjA = ((Object*)(objA->GetCustomTag())); + Player *player; + Object *realObjB = (Object*)objB->GetCustomTag(); //needs to be changed? - if(!realObj) + if(!realObjA) return; - if(!player) + if(!realObjB) return; - switch (realObj->GetObjectType()) + //check who is player and who is the object + if(realObjA->GetObjectType() == ObjectSpecialType::ObjectSpecialType_Player) + { + player = (Player*)realObjA; + } + else + { + player = (Player*)realObjB; + realObjB = realObjA; + } + + + switch (realObjB->GetObjectType()) { case ObjectSpecialType::ObjectSpecialType_Generic: - PlayerVObject(*player,*realObj, kineticEnergyLoss); + PlayerVObject(*player,*realObjB, kineticEnergyLoss); //return Physics::ICustomBody::SubscriptMessage_none; break; case ObjectSpecialType::ObjectSpecialType_StandardBox: - PlayerVObject(*player,*realObj, kineticEnergyLoss); + PlayerVObject(*player,*realObjB, kineticEnergyLoss); //return Physics::ICustomBody::SubscriptMessage_none; break; case ObjectSpecialType::ObjectSpecialType_Player: //return Physics::ICustomBody::SubscriptMessage_none; break; case ObjectSpecialType::ObjectSpecialType_World: - PlayerVObject(*player,*realObj, kineticEnergyLoss); + PlayerVObject(*player,*realObjB, kineticEnergyLoss); //player->playerState = PLAYER_STATE::PLAYER_STATE_WALKING; break; case ObjectSpecialType::ObjectSpecialType_CrystalFormation: - PlayerVLethalObject(*player,*realObj, kineticEnergyLoss,realObj->GetExtraDamageOnCollision()); + PlayerVLethalObject(*player,*realObjB, kineticEnergyLoss,realObjB->GetExtraDamageOnCollision()); //player->playerState = PLAYER_STATE::PLAYER_STATE_WALKING; break; } @@ -95,13 +108,31 @@ using namespace GameLogic; obj.SetPosition(target); } - void ExplosiveCrate::ExplosiveCrateCollision(Oyster::Physics::ICustomBody *rigidBodyCrate, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + void ExplosiveCrate::ExplosiveCrateCollision(Oyster::Physics::ICustomBody *objA, Oyster::Physics::ICustomBody *objB, Oyster::Math::Float kineticEnergyLoss) { - int forceThreashHold = 200000; //how much force for the box to explode of the impact + - Object *realObj = (Object*)obj->GetCustomTag(); //needs to be changed? + Object *realObjA = ((Object*)(objA->GetCustomTag())); + Object *realObjB = (Object*)objB->GetCustomTag(); + ExplosiveCrate* crate; - switch (realObj->GetObjectType()) + if(!realObjA) + return; + if(!realObjB) + return; + + //check who is player and who is the object + if(realObjA->GetObjectType() == ObjectSpecialType::ObjectSpecialType_RedExplosiveBox) + { + crate = (ExplosiveCrate*)realObjA; + } + else + { + crate = (ExplosiveCrate*)realObjB; + realObjB = realObjA; + } + + switch (realObjB->GetObjectType()) { case ObjectSpecialType::ObjectSpecialType_Generic: break; @@ -109,29 +140,15 @@ using namespace GameLogic; break; case ObjectSpecialType::ObjectSpecialType_Player: - ExplosiveCrate* crate = ((ExplosiveCrate*)rigidBodyCrate->GetCustomTag()); - - - Oyster::Math::Float3 pos = rigidBodyCrate->GetState().centerPos; + if(crate->hasExploaded) return; + Oyster::Math::Float3 pos = crate->GetRigidBody()->GetState().centerPos; Oyster::Collision3D::Sphere *hitSphere = new Oyster::Collision3D::Sphere(pos,crate->ExplosionRadius); Oyster::Physics::API::Instance().ApplyEffect(hitSphere,crate,Explode); - + crate->hasExploaded = true; delete hitSphere; break; } - /*if(kineticEnergyLoss > forceThreashHold) - { - ExplosiveCrate* crate = ((ExplosiveCrate*)rigidBodyCrate->GetCustomTag()); - - - Oyster::Math::Float3 pos = rigidBodyCrate->GetState().centerPos; - Oyster::Collision3D::Sphere *hitSphere = new Oyster::Collision3D::Sphere(pos,crate->ExplosionRadius); - - Oyster::Physics::API::Instance().ApplyEffect(hitSphere,crate,Explode); - - delete hitSphere; - }*/ } void ExplosiveCrate::Explode(Oyster::Physics::ICustomBody *obj, void* args) @@ -142,16 +159,21 @@ using namespace GameLogic; Oyster::Math::Float3 explosionCenterPos = ExplosionSource->GetPosition(); Oyster::Math::Float3 hitObjectPos = obj->GetState().centerPos; Oyster::Math::Float3 force = (((hitObjectPos- explosionCenterPos).GetNormalized()) * ExplosionSource->pushForceMagnitude); - + + if(realObj->GetObjectType() == ObjectSpecialType::ObjectSpecialType_Player) { Player *hitPlayer = (Player*)realObj; - + hitPlayer->DamageLife(ExplosionSource->extraDamageOnCollision); + //hitPlayer->GetRigidBody()->ApplyImpulse(force); + //hitPlayer->DamageLife(ExplosionSource->getExtraDamageOnCollision()); + realObj->GetRigidBody()->ApplyImpulse(force * 5); //do shredding damage } - realObj->GetRigidBody()->ApplyImpulse(force); + + } @@ -160,13 +182,32 @@ using namespace GameLogic; //Collision between a player and a general static or dynamic object //use kinetic energyloss of the collision in order too determin how much damage to take //use as part of the damage algorithm - int damageDone = 0; - int forceThreashHold = 200000; + Oyster::Math::Float3 objPrevVel = obj.GetRigidBody()->GetState().previousVelocity; + Oyster::Math::Float3 playerPrevVel = player.GetRigidBody()->GetState().previousVelocity; - if(kineticEnergyLoss > forceThreashHold) //should only take damage if the force is high enough + Oyster::Math::Float3 deltaPos = (player.GetPosition() - obj.GetPosition()); + Oyster::Math::Float deltaSpeed = (objPrevVel - playerPrevVel).GetMagnitude(); + Oyster::Math::Float angularFactor = deltaPos.GetNormalized().Dot( (objPrevVel - playerPrevVel).GetNormalized()); + + Oyster::Math::Float impactPower = deltaSpeed * angularFactor; + Oyster::Math::Float damageFactor = 0.01f; + + + int damageDone = 0; + int forceThreashHold = 30; //FIX: balance this + + if(impactPower > forceThreashHold) //should only take damage if the force is high enough { - damageDone = (int)(kineticEnergyLoss * 0.10f); - //player.DamageLife(damageDone); + if(obj.GetRigidBody()->GetState().mass == 0) + { + damageDone = impactPower * damageFactor; + } + else + { + damageDone = (impactPower * obj.GetRigidBody()->GetState().mass)* damageFactor; + } + + player.DamageLife(damageDone); } } @@ -189,6 +230,58 @@ using namespace GameLogic; { return Physics::ICustomBody::SubscriptMessage_none; } + + void DynamicObject::DynamicDefaultOnCollision(Oyster::Physics::ICustomBody *objA, Oyster::Physics::ICustomBody *objB, Oyster::Math::Float kineticEnergyLoss) + { + + DynamicObject *realObjA = dynamic_cast((Object*)objA->GetCustomTag()); + + DynamicObject *realObjB = dynamic_cast((Object*)objB->GetCustomTag()); + + if(!realObjA || !realObjB) // one of the objects cannot be cast into a dynamicObject and so we leave the function + { + return; + } + + //check which obj is the one that is already affected, if both are then use the special case of changing ownership. + if(realObjA->getAffectingPlayer() == NULL && realObjB->getAffectingPlayer() == NULL) //None of the objects have a player affecting them + { + return;//leave function as the are not to transfer any ownership + } + + if(realObjA->getAffectingPlayer() != NULL && realObjB->getAffectingPlayer() == NULL) + { + //realobjA is the affectedObject, transfer this to realobjB + realObjB->SetAffectedBy(*realObjA->getAffectingPlayer()); + + } + if(realObjB->getAffectingPlayer() != NULL && realObjA->getAffectingPlayer() == NULL) + { + //realobjB is the affectedObject, transfer this to realobjA + realObjA->SetAffectedBy(*realObjB->getAffectingPlayer()); + + } + + if(realObjA->getAffectingPlayer() != NULL && realObjB->getAffectingPlayer() != NULL) + { + //Both objects have a player affecting them, now use the special case + if(realObjA->GetRigidBody()->GetState().previousVelocity.GetMagnitude() > realObjB->GetRigidBody()->GetState().previousVelocity.GetMagnitude() ) + { + //realObjA is the winner and will change Bs ownership to A + realObjB->SetAffectedBy(*realObjA->getAffectingPlayer()); + } + else + { + realObjA->SetAffectedBy(*realObjB->getAffectingPlayer()); + //realObjB is the winner and will change As ownership to B + } + } + + + + + } + Oyster::Physics::ICustomBody::SubscriptMessage Player::PlayerCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) { return Physics::ICustomBody::SubscriptMessage_none; @@ -213,7 +306,17 @@ using namespace GameLogic; if(realObj->GetObjectType() == ObjectSpecialType::ObjectSpecialType_Player || realObj->GetObjectType() == ObjectSpecialType::ObjectSpecialType_World) return; + + obj->ApplyImpulse(((forcePushData*)(args))->pushForce); + + + DynamicObject *dynamicObj = dynamic_cast(realObj); + + if(dynamicObj) + { + dynamicObj->SetAffectedBy(*((forcePushData*)(args))->p); + } } void AttatchmentMassDriver::AttemptPickUp(Oyster::Physics::ICustomBody *obj, void* args) @@ -231,11 +334,21 @@ using namespace GameLogic; Object* realObj = (Object*)(obj->GetCustomTag()); //check so that it is an object that you can pickup - switch(realObj->GetObjectType()) + DynamicObject *dynamicObj = dynamic_cast(realObj); + + if(!dynamicObj) return; + + if(dynamicObj->getManipulatingPlayer() != NULL) + { + return; + } + + switch(dynamicObj->GetObjectType()) { case ObjectSpecialType::ObjectSpecialType_StandardBox: weapon->heldObject = obj; //weapon now holds the object weapon->hasObject = true; + dynamicObj->SetManipulatingPlayer(*weapon->owner); //TODO: add if this is to be a struggle of who has the most power in its weapon, the player that is already manipulating the object or you. if you then you take the object from the other player, if not then you do not take the object break; } diff --git a/Code/Game/GameLogic/DynamicObject.cpp b/Code/Game/GameLogic/DynamicObject.cpp index 6df5bef0..844deaf2 100644 --- a/Code/Game/GameLogic/DynamicObject.cpp +++ b/Code/Game/GameLogic/DynamicObject.cpp @@ -1,38 +1,123 @@ #include "DynamicObject.h" #include "CollisionManager.h" +#include "Player.h" using namespace GameLogic; +using namespace Oyster::Math; DynamicObject::DynamicObject() :Object() { - + this->isReleased = false; + this->isActive = true; + this->affectedBy = NULL; + this->manipulatedBy = NULL; } DynamicObject::DynamicObject(Oyster::Physics::ICustomBody *rigidBody , void (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID) :Object(rigidBody, EventOnCollision, type, objectID) { - + this->isReleased = false; + this->isActive = true; + this->affectedBy = NULL; + this->manipulatedBy = NULL; } DynamicObject::DynamicObject(Oyster::Physics::ICustomBody *rigidBody , Oyster::Physics::ICustomBody::SubscriptMessage (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID) :Object(rigidBody, EventOnCollision, type, objectID) { - + this->isReleased = false; + this->isActive = true; + this->affectedBy = NULL; + this->manipulatedBy = NULL; } DynamicObject::DynamicObject(Oyster::Physics::ICustomBody *rigidBody , void (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID, Oyster::Math::Float extraDamageOnCollision) :Object(rigidBody, EventOnCollision, type, objectID) { this->extraDamageOnCollision = extraDamageOnCollision; + this->isReleased = false; + this->isActive = true; + this->affectedBy = NULL; + this->manipulatedBy = NULL; } DynamicObject::DynamicObject(Oyster::Physics::ICustomBody *rigidBody , Oyster::Physics::ICustomBody::SubscriptMessage (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID, Oyster::Math::Float extraDamageOnCollision) :Object(rigidBody, EventOnCollision, type, objectID) { this->extraDamageOnCollision = extraDamageOnCollision; + this->isReleased = false; + this->isActive = true; + this->affectedBy = NULL; + this->manipulatedBy = NULL; } DynamicObject::~DynamicObject(void) { +} + +void DynamicObject::ReleaseDynamicObject() +{ + //TODO: Inactivate the physics object + if(this->isReleased) return; + + this->isReleased = true; + this->isActive = false; + this->lookDirection = Float3::null; + this->forwardDirection = Float3::null; + this->scale = Float3::null; + this->extraDamageOnCollision = 0; + +} +bool DynamicObject::IsReleased() +{ + return this->isReleased; +} +bool DynamicObject::IsActive() +{ + return this->isActive; +} +void DynamicObject::Inactivate() +{ + this->isActive = false; +} +void DynamicObject::Activate() +{ + this->isActive = true; + this->isReleased = false; +} + +void DynamicObject::SetAffectedBy(Player &player) +{ + this->affectedBy = &player; + if(this->type != ObjectSpecialType::ObjectSpecialType_Player) //should not add itself to its own list if its a player + { + player.AddAffectedObject(*this); + } + +} + +Player* DynamicObject::getAffectingPlayer() +{ + return this->affectedBy; +} + +void DynamicObject::RemoveAffectedBy() +{ + this->affectedBy = NULL; +} + +GameLogic::Player* DynamicObject::getManipulatingPlayer() +{ + return this->manipulatedBy; +} + +void DynamicObject::SetManipulatingPlayer(GameLogic::Player &player) +{ + this->manipulatedBy = &player; +} + +void DynamicObject::RemoveManipulation() +{ + this->manipulatedBy = NULL; } \ No newline at end of file diff --git a/Code/Game/GameLogic/DynamicObject.h b/Code/Game/GameLogic/DynamicObject.h index 2d5fa617..03a03ad6 100644 --- a/Code/Game/GameLogic/DynamicObject.h +++ b/Code/Game/GameLogic/DynamicObject.h @@ -9,6 +9,7 @@ namespace GameLogic { + class Player; class DynamicObject : public Object { @@ -22,7 +23,28 @@ namespace GameLogic ~DynamicObject(void); + void ReleaseDynamicObject(); + bool IsReleased(); + bool IsActive(); + void Inactivate(); + void Activate(); + + void SetAffectedBy(GameLogic::Player &player); + void SetManipulatingPlayer(GameLogic::Player &player); + void RemoveAffectedBy(); + void RemoveManipulation(); + GameLogic::Player* getAffectingPlayer(); + GameLogic::Player* getManipulatingPlayer(); + + static void DynamicObject::DynamicDefaultOnCollision(Oyster::Physics::ICustomBody *rigidBodyObject, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss); + private: + bool isActive; + bool isReleased; + protected: + GameLogic::Player *affectedBy; + GameLogic::Player *manipulatedBy; + }; diff --git a/Code/Game/GameLogic/ExplosiveCrate.cpp b/Code/Game/GameLogic/ExplosiveCrate.cpp index d236d400..cf011ce4 100644 --- a/Code/Game/GameLogic/ExplosiveCrate.cpp +++ b/Code/Game/GameLogic/ExplosiveCrate.cpp @@ -7,6 +7,7 @@ ExplosiveCrate::ExplosiveCrate(void) { this->pushForceMagnitude = 0; this->ExplosionRadius = 0; + this->hasExploaded = false; } ExplosiveCrate::ExplosiveCrate(Oyster::Physics::ICustomBody *rigidBody,ObjectSpecialType type, int objectID,Oyster::Math::Float extraDamageOnCollision, Oyster::Math::Float pushForceMagnitude, Oyster::Math::Float ExplosionRadius) @@ -15,6 +16,7 @@ ExplosiveCrate::ExplosiveCrate(Oyster::Physics::ICustomBody *rigidBody,ObjectSpe this->extraDamageOnCollision = extraDamageOnCollision; this->pushForceMagnitude = pushForceMagnitude; this->ExplosionRadius = ExplosionRadius; + this->hasExploaded = false; } ExplosiveCrate::~ExplosiveCrate(void) diff --git a/Code/Game/GameLogic/ExplosiveCrate.h b/Code/Game/GameLogic/ExplosiveCrate.h index 75afdc4a..b6054266 100644 --- a/Code/Game/GameLogic/ExplosiveCrate.h +++ b/Code/Game/GameLogic/ExplosiveCrate.h @@ -18,6 +18,7 @@ namespace GameLogic private: Oyster::Math::Float pushForceMagnitude; Oyster::Math::Float ExplosionRadius; + bool hasExploaded; }; diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index 8dd7ffa6..a33ce03c 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -43,6 +43,9 @@ Game::Game(void) : initiated(false) , onMoveFnc(0) , onDisableFnc(0) + , onDamageTakenFnc(0) + , onRespawnFnc(0) + , onDeadFnc(0) , frameTime(1.0f/120.0f) {} @@ -67,6 +70,17 @@ void Game::GetAllPlayerPositions() const Game::PlayerData* Game::CreatePlayer() { + //Se if there is a free player somewhere in our list + for (unsigned int i = 0; i < this->players.Size(); i++) + { + if(this->players[i] && this->players[i]->player->IsReleased()) + { + //We give the body to someone else + this->players[i]->player->Activate(); + return this->players[i]; + } + } + // Find a free space in array or insert at end int insert = InsertObject(this->players, (PlayerData*)0); int freeID = 0; @@ -94,6 +108,7 @@ Game::PlayerData* Game::CreatePlayer() this->players[insert] = new PlayerData(freeID, 0); // user constructor with objectID and teamID this->players[insert]->player->GetRigidBody()->SetSubscription(Game::PhysicsOnMove); + this->level->AddPlayerToGame(this->players[insert]); return this->players[insert]; } @@ -114,6 +129,9 @@ void Game::CreateTeam() bool Game::NewFrame() { + // HACK need dynamic delta time + this->level->Update(this->frameTime); + for (unsigned int i = 0; i < this->players.Size(); i++) { if(this->players[i] && this->players[i]->player) this->players[i]->player->BeginFrame(); @@ -145,7 +163,18 @@ void Game::SetSubscription(GameEvent::ObjectMovedFunction functionPointer) void Game::SetSubscription(GameEvent::ObjectDisabledFunction functionPointer) { this->onDisableFnc = functionPointer; - +} +void Game::SetHpSubscription(GameEvent::ObjectHpFunction functionPointer) +{ + this->onDamageTakenFnc = functionPointer; +} +void Game::SetRespawnSubscription(GameEvent::ObjectRespawnedFunction functionPointer) +{ + this->onRespawnFnc = functionPointer; +} +void Game::SetDeadSubscription(GameEvent::ObjectDeadFunction functionPointer) +{ + this->onDeadFnc = functionPointer; } bool Game::Initiate() @@ -177,4 +206,3 @@ void Game::PhysicsOnDestroy(::Utility::DynamicMemory::UniquePointer { if(gameInstance.onDisableFnc) gameInstance.onDisableFnc(0, 0); } - diff --git a/Code/Game/GameLogic/Game.h b/Code/Game/GameLogic/Game.h index 5ab19ba2..c03de2ed 100644 --- a/Code/Game/GameLogic/Game.h +++ b/Code/Game/GameLogic/Game.h @@ -40,12 +40,12 @@ namespace GameLogic Oyster::Math::Float3 GetScale() override; Oyster::Math::Float4x4 GetOrientation() override; int GetID() const override; - void Rotate(const Oyster::Math3D::Float3& lookDir, const Oyster::Math3D::Float3& right) override; + void SetLookDir(const Oyster::Math3D::Float3& lookDir) override; void TurnLeft(Oyster::Math3D::Float deltaLeftRadians ) override; ObjectSpecialType GetObjectType() const override; - - - + void Inactivate() override; + void Release() override; + Player* GetPlayer(); Player *player; }; @@ -63,7 +63,8 @@ namespace GameLogic int getNrOfDynamicObj()const override; IObjectData* GetObjectAt(int ID) const override; void GetAllDynamicObjects(Utility::DynamicMemory::DynamicArray& mem) const override; - + void Update(float deltaTime); + void AddPlayerToGame(IPlayerData *player); Level *level; }; @@ -80,20 +81,26 @@ namespace GameLogic void SetFrameTimeLength( float seconds ) override; void SetSubscription(GameEvent::ObjectMovedFunction functionPointer) override; void SetSubscription(GameEvent::ObjectDisabledFunction functionPointer) override; + void SetHpSubscription(GameEvent::ObjectHpFunction functionPointer) override; + void SetRespawnSubscription(GameEvent::ObjectRespawnedFunction functionPointer) override; + void SetDeadSubscription(GameEvent::ObjectDeadFunction functionPointer) override; bool Initiate() override; float GetFrameTime() const; static void PhysicsOnMove(const Oyster::Physics::ICustomBody *object); static void PhysicsOnDestroy(::Utility::DynamicMemory::UniquePointer proto); + static void PhysicsOnDead(const Oyster::Physics::ICustomBody *object); Utility::DynamicMemory::DynamicArray players; LevelData* level; float frameTime; bool initiated; - GameEvent::ObjectDisabledFunction onDisableFnc; - GameEvent::ObjectMovedFunction onMoveFnc; - + GameEvent::ObjectDisabledFunction onDisableFnc; + GameEvent::ObjectMovedFunction onMoveFnc; + GameEvent::ObjectHpFunction onDamageTakenFnc; + GameEvent::ObjectRespawnedFunction onRespawnFnc; + GameEvent::ObjectDeadFunction onDeadFnc; }; } diff --git a/Code/Game/GameLogic/GameAPI.h b/Code/Game/GameLogic/GameAPI.h index 66cf5ea2..8d0ff695 100644 --- a/Code/Game/GameLogic/GameAPI.h +++ b/Code/Game/GameLogic/GameAPI.h @@ -27,6 +27,9 @@ namespace GameLogic { typedef void(*ObjectMovedFunction)(IObjectData* object); // Callback method that recieves and object typedef void(*ObjectDisabledFunction)(IObjectData* object, float seconds); // Callback method that recieves and object + typedef void(*ObjectHpFunction)(IObjectData* object, float hp); // Callback method that sends obj HP + typedef void(*ObjectRespawnedFunction)(IObjectData* object, Oyster::Math::Float3 spawnPos ); // Callback method that sends spawnPos + typedef void(*ObjectDeadFunction)(IObjectData* victim, IObjectData* killer, float seconds); // Callback method that sends killer and death timer //etc... }; @@ -85,7 +88,7 @@ namespace GameLogic * @param x: The relative x axis * @param y: The relative y axis **/ - virtual void Rotate(const Oyster::Math3D::Float3& lookDir, const Oyster::Math3D::Float3& right) = 0; + virtual void SetLookDir(const Oyster::Math3D::Float3& lookDir) = 0; /** Relative rotation around given axis * @param leftRadians: The relative amount of radians to turn @@ -106,13 +109,18 @@ namespace GameLogic * @return The current player state ********************************************************/ virtual PLAYER_STATE GetState() const = 0; + + virtual void Inactivate() = 0; + virtual void Release() = 0; }; class ILevelData :public IObjectData { public: + virtual void Update(float deltaTime) = 0; virtual int getNrOfDynamicObj()const = 0; virtual IObjectData* GetObjectAt(int ID) const = 0; + virtual void AddPlayerToGame(IPlayerData *player) = 0; virtual void GetAllDynamicObjects(Utility::DynamicMemory::DynamicArray& destMem) const = 0; }; @@ -175,6 +183,9 @@ namespace GameLogic * @param */ virtual void SetSubscription(GameEvent::ObjectDisabledFunction functionPointer) = 0; + virtual void SetHpSubscription(GameEvent::ObjectHpFunction functionPointer) = 0; + virtual void SetRespawnSubscription(GameEvent::ObjectRespawnedFunction functionPointer) = 0; + virtual void SetDeadSubscription(GameEvent::ObjectDeadFunction functionPointer) = 0; }; } diff --git a/Code/Game/GameLogic/GameLogicStates.h b/Code/Game/GameLogic/GameLogicStates.h index 9ae0d482..f006ad27 100644 --- a/Code/Game/GameLogic/GameLogicStates.h +++ b/Code/Game/GameLogic/GameLogicStates.h @@ -2,8 +2,10 @@ #define GAMELOGICSTATES_H #include "OysterMath.h" + namespace GameLogic { + class Player; enum PLAYER_MOVEMENT { PLAYER_MOVEMENT_FORWARD = 0, @@ -18,7 +20,8 @@ namespace GameLogic PLAYER_STATE_WALKING = 1, PLAYER_STATE_IDLE = 2, PLAYER_STATE_DEAD = 4, - PLAYER_STATE_INVALID = 8, + PLAYER_STATE_DIED = 8, + PLAYER_STATE_INVALID = 16, }; enum WEAPON_FIRE @@ -41,6 +44,7 @@ namespace GameLogic struct forcePushData { Oyster::Math::Float3 pushForce; + Player *p; }; diff --git a/Code/Game/GameLogic/Game_LevelData.cpp b/Code/Game/GameLogic/Game_LevelData.cpp index 903cb959..f16f4072 100644 --- a/Code/Game/GameLogic/Game_LevelData.cpp +++ b/Code/Game/GameLogic/Game_LevelData.cpp @@ -54,9 +54,17 @@ IObjectData* Game::LevelData::GetObjectAt(int ID) const void Game::LevelData::GetAllDynamicObjects(Utility::DynamicMemory::DynamicArray& mem) const { - mem.Resize(level->dynamicObjects.Size()); - for(int i = 0; i < (int)level->dynamicObjects.Size(); i++) + mem.Resize(level->GetDynamicObject().Size()); + for(int i = 0; i < (int)level->GetDynamicObject().Size(); i++) { - mem[i] = level->dynamicObjects[i]; + mem[i] = level->GetDynamicObject()[i]; } +} +void Game::LevelData::Update(float deltaTime) +{ + this->level->Update(deltaTime); +} +void Game::LevelData::AddPlayerToGame(IPlayerData *player) +{ + this->level->AddPlayerToGame(((PlayerData*)player)->GetPlayer()); } \ No newline at end of file diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 045da742..88b4bbbe 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -86,11 +86,23 @@ ObjectSpecialType Game::PlayerData::GetObjectType() const { return this->player->GetObjectType(); } -void Game::PlayerData::Rotate(const Oyster::Math3D::Float3& lookDir, const Oyster::Math3D::Float3& right) +void Game::PlayerData::SetLookDir(const Oyster::Math3D::Float3& lookDir) { - this->player->Rotate(lookDir, right); + this->player->SetLookDir(lookDir); } void Game::PlayerData::TurnLeft(Oyster::Math3D::Float deltaLeftRadians ) { this->player->TurnLeft(deltaLeftRadians); +} +void Game::PlayerData::Inactivate() +{ + this->player->Inactivate(); +} +void Game::PlayerData::Release() +{ + this->player->ReleaseDynamicObject(); +} +Player* Game::PlayerData::GetPlayer() +{ + return this->player; } \ No newline at end of file diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index c9938dbd..d258cc27 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -12,7 +12,7 @@ using namespace GameLogic; using namespace Utility::DynamicMemory; using namespace Oyster::Physics; - +using namespace Oyster::Math; Level::Level(void) { @@ -59,19 +59,19 @@ Object* Level::CreateGameObj(ObjectHeader* obj, ICustomBody* rigidBody) break; case ObjectSpecialType_Stone: { - gameObj = new DynamicObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); + gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); } break; case ObjectSpecialType_StandardBox: { - gameObj = new DynamicObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); + gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); } break; case ObjectSpecialType_RedExplosiveBox: { - Oyster::Math::Float dmg = 50; - Oyster::Math::Float force = 50; - Oyster::Math::Float radie = 50; + Oyster::Math::Float dmg = 120; + Oyster::Math::Float force = 500; + Oyster::Math::Float radie = 3; gameObj = new ExplosiveCrate(rigidBody, (ObjectSpecialType)obj->specialTypeID, objID++, dmg, force, radie); } break; @@ -81,12 +81,12 @@ Object* Level::CreateGameObj(ObjectHeader* obj, ICustomBody* rigidBody) // break; case ObjectSpecialType_SpikeBox: { - gameObj = new DynamicObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); + gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); } break; case ObjectSpecialType_Spike: { - gameObj = new DynamicObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); + gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); } break; case ObjectSpecialType_CrystalFormation: @@ -98,7 +98,7 @@ Object* Level::CreateGameObj(ObjectHeader* obj, ICustomBody* rigidBody) break; case ObjectSpecialType_CrystalShard: { - gameObj = new DynamicObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); + gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID); } break; case ObjectSpecialType_JumpPad: @@ -393,7 +393,20 @@ void Level::AddPlayerToTeam(Player *player, int teamID) { this->teamManager.AddPlayerToTeam(player,teamID); } - +void Level::AddPlayerToGame(Player *player) +{ + this->playerObjects.Push(player); +} +void Level::RemovePlayerFromGame(Player *player) +{ + for(int i = 0; i < (int)this->playerObjects.Size(); i++) + { + if ((Player*)this->playerObjects[i] == player) + { + //this->playerObjects[i]. + } + } +} void Level::CreateTeam(int teamSize) { this->teamManager.CreateTeam(teamSize); @@ -401,9 +414,31 @@ void Level::CreateTeam(int teamSize) void Level::RespawnPlayer(Player *player) { - this->teamManager.RespawnPlayerRandom(player); -} + //this->teamManager.RespawnPlayerRandom(player); + Float3 spawnPoint = spawnPoints[0]; + player->Respawn(spawnPoint); +} +void Level::Update(float deltaTime) +{ + // update lvl-things + for(int i = 0; i < (int)this->playerObjects.Size(); i++) + { + if (this->playerObjects[i]->GetState() == PLAYER_STATE::PLAYER_STATE_DEAD) + { + // true when timer reaches 0 + if(this->playerObjects[i]->deathTimerTick(deltaTime)) + RespawnPlayer(this->playerObjects[i]); + } + else if (this->playerObjects[i]->GetState() == PLAYER_STATE::PLAYER_STATE_DIED) + { + this->playerObjects[i]->setDeathTimer(DEATH_TIMER); + // HACK to avoid crasch. affected by tag is NULL + ((Game*)&Game::Instance())->onDeadFnc(this->playerObjects[i], this->playerObjects[i], DEATH_TIMER); // add killer ID + //((Game*)&Game::Instance())->onDeadFnc(this->playerObjects[i], this->playerObjects[i]->getAffectingPlayer(), DEATH_TIMER); // add killer ID + } + } +} int Level::getNrOfDynamicObj() { return this->dynamicObjects.Size(); @@ -417,10 +452,23 @@ Object* Level::GetObj( int ID) const } return NULL; } + void Level::PhysicsOnMoveLevel(const ICustomBody *object) { // function call from physics update when object was moved Object* temp = (Object*)object->GetCustomTag(); ((Game*)&Game::Instance())->onMoveFnc(temp); - } +Utility::DynamicMemory::DynamicArray> Level::GetPlayers() +{ + return this->playerObjects; +} +Utility::DynamicMemory::DynamicArray> Level::GetStaticObjects() +{ + return this->staticObjects; +} +Utility::DynamicMemory::DynamicArray> Level::GetDynamicObject() +{ + return this->dynamicObjects; +} + diff --git a/Code/Game/GameLogic/Level.h b/Code/Game/GameLogic/Level.h index 9dce227d..9fb3dbad 100644 --- a/Code/Game/GameLogic/Level.h +++ b/Code/Game/GameLogic/Level.h @@ -16,6 +16,7 @@ #include "DynamicArray.h" #include "LevelLoader.h" +const int DEATH_TIMER = 5; namespace GameLogic { @@ -48,7 +49,8 @@ namespace GameLogic * @param teamID: ArrayPos of the team you want to add the player to ********************************************************/ void AddPlayerToTeam(Player *player, int teamID); - + void AddPlayerToGame(Player *player); + void RemovePlayerFromGame(Player *player); /******************************************************** * Respawns a player on a random teammate @@ -64,12 +66,21 @@ namespace GameLogic ********************************************************/ static Oyster::Physics::ICustomBody::SubscriptMessage LevelCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss); + void Update(float deltaTime); + int getNrOfDynamicObj(); Object* GetObj( int ID ) const; + + static void PlayerDied( Player* player ); static void PhysicsOnMoveLevel(const Oyster::Physics::ICustomBody *object); + Utility::DynamicMemory::DynamicArray> GetPlayers(); + Utility::DynamicMemory::DynamicArray> GetStaticObjects(); + Utility::DynamicMemory::DynamicArray> GetDynamicObject(); - //private: + private: + Utility::DynamicMemory::DynamicArray> playerObjects; + Utility::DynamicMemory::DynamicArray> deadPlayerObjects; TeamManager teamManager; Utility::DynamicMemory::DynamicArray> staticObjects; Utility::DynamicMemory::DynamicArray> dynamicObjects; diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index 5b855785..0ce95948 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -11,56 +11,28 @@ const float KEY_TIMER = 0.03f; Player::Player() :DynamicObject() { - + Player::initPlayerData(); + AffectedObjects.Reserve(15); + this->weapon = NULL; + this->teamID = -1; } Player::Player(Oyster::Physics::ICustomBody *rigidBody, void (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID, int teamID) :DynamicObject(rigidBody, EventOnCollision, type, objectID) { - weapon = new Weapon(2,this); - - this->life = 100; + this->weapon = new Weapon(2,this); + Player::initPlayerData(); + AffectedObjects.Reserve(15); this->teamID = teamID; - this->playerState = PLAYER_STATE_IDLE; - this->lookDir = Oyster::Math::Float3(0,0,-1); - key_forward = 0; - key_backward = 0; - key_strafeRight = 0; - key_strafeLeft = 0; - key_jump = 0; - invincibleCooldown = 0; - - this->previousPosition = Oyster::Math::Float3(0,0,0); - - this->moveDir = Oyster::Math::Float3(0,0,0); - this->moveSpeed = 100; - this->previousMoveSpeed = Oyster::Math::Float3(0,0,0); - - this->rotationUp = 0; } Player::Player(Oyster::Physics::ICustomBody *rigidBody, Oyster::Physics::ICustomBody::SubscriptMessage (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID, int teamID) :DynamicObject(rigidBody, EventOnCollision, type, objectID) { - weapon = new Weapon(2,this); - - this->life = 100; + this->weapon = new Weapon(2,this); + Player::initPlayerData(); + AffectedObjects.Reserve(15); this->teamID = teamID; - this->playerState = PLAYER_STATE_IDLE; - this->lookDir = Oyster::Math::Float3(0,0,-1); - key_forward = 0; - key_backward = 0; - key_strafeRight = 0; - key_strafeLeft = 0; - key_jump = 0; - invincibleCooldown = 0; - - this->previousPosition = Oyster::Math::Float3(0,0,0); - this->moveDir = Oyster::Math::Float3(0,0,0); - this->moveSpeed = 20; - this->previousMoveSpeed = Oyster::Math::Float3(0,0,0); - - this->rotationUp = 0; } Player::~Player(void) @@ -71,141 +43,164 @@ Player::~Player(void) weapon = NULL; } } +void Player::initPlayerData() +{ + this->playerStats.hp = MAX_HP; + this->playerStats.movementSpeed = BASIC_SPEED; + this->playerScore.killScore = 0; + this->playerScore.deathScore = 0; + this->playerState = PLAYER_STATE_IDLE; + this->lookDir = Oyster::Math::Float3(0,0,-1); + + this->key_forward = 0; + this->key_backward = 0; + this->key_strafeRight = 0; + this->key_strafeLeft = 0; + this->key_jump = 0; + this->invincibleCooldown = 0; + this->deathTimer = 0; + + this->rotationUp = 0; +} void Player::BeginFrame() { - //weapon->Update(0.002f); - //Object::BeginFrame(); + if( this->playerState != PLAYER_STATE_DEAD && PLAYER_STATE_DIED) + { + weapon->Update(0.002f); - Oyster::Math::Float maxSpeed = 30; + Oyster::Math::Float maxSpeed = 30; - // Rotate player accordingly - this->rigidBody->SetUp(this->rigidBody->GetState().centerPos.GetNormalized()); - Oyster::Math::Quaternion firstUp = this->rigidBody->GetState().quaternion; - this->rigidBody->SetRotationAsAngularAxis(Oyster::Math3D::Float4(this->rigidBody->GetState().centerPos.GetNormalized(), this->rotationUp)); - Oyster::Math::Quaternion secondTurn = this->rigidBody->GetState().quaternion; + // Rotate player accordingly + this->rigidBody->SetUp(this->rigidBody->GetState().centerPos.GetNormalized()); + Oyster::Math::Quaternion firstUp = this->rigidBody->GetState().quaternion; + this->rigidBody->SetRotationAsAngularAxis(Oyster::Math3D::Float4(this->rigidBody->GetState().centerPos.GetNormalized(), this->rotationUp)); + Oyster::Math::Quaternion secondTurn = this->rigidBody->GetState().quaternion; - this->rigidBody->SetRotation(secondTurn*firstUp); + this->rigidBody->SetRotation(secondTurn*firstUp); - // Direction data - Oyster::Math::Float4x4 xform; - xform = this->rigidBody->GetState().GetOrientation(); + // Direction data + Oyster::Math::Float4x4 xform; + xform = this->rigidBody->GetState().GetOrientation(); - Oyster::Math::Float3 forwardDir = xform.v[2]; - Oyster::Math::Float3 upDir = xform.v[1]; - Oyster::Math::Float3 rightDir = xform.v[0]; - forwardDir.Normalize(); - upDir.Normalize(); - rightDir.Normalize(); + Oyster::Math::Float3 forwardDir = xform.v[2]; + Oyster::Math::Float3 upDir = xform.v[1]; + Oyster::Math::Float3 rightDir = xform.v[0]; + forwardDir.Normalize(); + upDir.Normalize(); + rightDir.Normalize(); - // Previous velocities data - Oyster::Math::Float3 linearVelocity = this->rigidBody->GetLinearVelocity(); - Oyster::Math::Float3 forwardVelocity = linearVelocity*Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)); - Oyster::Math::Float forwardSpeed = (linearVelocity*forwardDir).GetLength(); - Oyster::Math::Float3 rightVelocity = linearVelocity*Oyster::Math::Float3(fabs(rightDir.x), fabs(rightDir.y), fabs(rightDir.z)); - Oyster::Math::Float rightSpeed = (linearVelocity*rightDir).GetLength(); - Oyster::Math::Float3 upVelocity = linearVelocity*Oyster::Math::Float3(fabs(upDir.x), fabs(upDir.y), fabs(upDir.z)); + // Previous velocities data + Oyster::Math::Float3 linearVelocity = this->rigidBody->GetLinearVelocity(); + Oyster::Math::Float3 forwardVelocity = linearVelocity*Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)); + Oyster::Math::Float forwardSpeed = (linearVelocity*forwardDir).GetLength(); + Oyster::Math::Float3 rightVelocity = linearVelocity*Oyster::Math::Float3(fabs(rightDir.x), fabs(rightDir.y), fabs(rightDir.z)); + Oyster::Math::Float rightSpeed = (linearVelocity*rightDir).GetLength(); + Oyster::Math::Float3 upVelocity = linearVelocity*Oyster::Math::Float3(fabs(upDir.x), fabs(upDir.y), fabs(upDir.z)); - // Walking data - Oyster::Math::Float3 walkDirection = Oyster::Math::Float3(0.0, 0.0, 0.0); - Oyster::Math::Float walkSpeed = this->moveSpeed*0.2f; + // Walking data + Oyster::Math::Float3 walkDirection = Oyster::Math::Float3(0.0, 0.0, 0.0); + Oyster::Math::Float walkSpeed = this->playerStats.movementSpeed*0.2f; - // Check for input - if(key_forward > 0.001) - { - key_forward -= gameInstance->GetFrameTime(); - walkDirection += forwardDir; - } - if(key_backward > 0.001) - { - key_backward -= gameInstance->GetFrameTime(); - walkDirection -= forwardDir; - } - if(key_strafeRight > 0.001) - { - key_strafeRight -= gameInstance->GetFrameTime(); - walkDirection += rightDir; - } - if(key_strafeLeft > 0.001) - { - key_strafeLeft -= gameInstance->GetFrameTime(); - walkDirection -= rightDir; - } - - // Dampen velocity if certain keys are not pressed - if(key_jump <= 0.001 && this->rigidBody->GetLambda() < 0.9f) - { - if(key_forward <= 0.001 && key_backward <= 0.001) + // Check for input + if(key_forward > 0.001) { - forwardVelocity *= Oyster::Math::Float3(0.2f*fabs(forwardDir.x), 0.2f*fabs(forwardDir.y), 0.2f*fabs(forwardDir.z)); + key_forward -= gameInstance->GetFrameTime(); + walkDirection += forwardDir; } - if(key_strafeRight <= 0.001 && key_strafeLeft <= 0.001) + if(key_backward > 0.001) { - rightVelocity *= Oyster::Math::Float3(0.2f*fabs(rightDir.x), 0.2f*fabs(rightDir.y), 0.2f*fabs(rightDir.z)); + key_backward -= gameInstance->GetFrameTime(); + walkDirection -= forwardDir; } - } - - // Walk if walkdirection is something - if(walkDirection != Oyster::Math::Float3::null) - { - walkDirection.Normalize(); - - // If on the ground, accelerate normally - if(this->rigidBody->GetLambda() < 0.9f) + if(key_strafeRight > 0.001) { - if(forwardSpeed < maxSpeed) + key_strafeRight -= gameInstance->GetFrameTime(); + walkDirection += rightDir; + } + if(key_strafeLeft > 0.001) + { + key_strafeLeft -= gameInstance->GetFrameTime(); + walkDirection -= rightDir; + } + + // Dampen velocity if certain keys are not pressed + if(key_jump <= 0.001 && this->rigidBody->GetLambda() < 0.9f) + { + if(key_forward <= 0.001 && key_backward <= 0.001) { - forwardVelocity += walkDirection*Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)) * walkSpeed; + forwardVelocity *= Oyster::Math::Float3(0.2f*fabs(forwardDir.x), 0.2f*fabs(forwardDir.y), 0.2f*fabs(forwardDir.z)); } - if(rightSpeed < maxSpeed) + if(key_strafeRight <= 0.001 && key_strafeLeft <= 0.001) { - rightVelocity += walkDirection*Oyster::Math::Float3(fabs(rightDir.x), abs(rightDir.y), fabs(rightDir.z)) * walkSpeed; + rightVelocity *= Oyster::Math::Float3(0.2f*fabs(rightDir.x), 0.2f*fabs(rightDir.y), 0.2f*fabs(rightDir.z)); } } - // If in the air, accelerate slower - if(this->rigidBody->GetLambda() >= 0.9f) + + // Walk if walkdirection is something + if(walkDirection != Oyster::Math::Float3::null) { - if(forwardSpeed < maxSpeed) + walkDirection.Normalize(); + + // If on the ground, accelerate normally + if(this->rigidBody->GetLambda() < 0.9f) { - forwardVelocity += walkDirection*Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)) * walkSpeed*0.2f; + if(forwardSpeed < maxSpeed) + { + forwardVelocity += walkDirection*Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)) * walkSpeed; + } + if(rightSpeed < maxSpeed) + { + rightVelocity += walkDirection*Oyster::Math::Float3(fabs(rightDir.x), abs(rightDir.y), fabs(rightDir.z)) * walkSpeed; + } } - if(rightSpeed < maxSpeed) + // If in the air, accelerate slower + if(this->rigidBody->GetLambda() >= 0.9f) { - rightVelocity += walkDirection*Oyster::Math::Float3(fabs(rightDir.x), fabs(rightDir.y), fabs(rightDir.z)) * walkSpeed*0.2f; + if(forwardSpeed < maxSpeed) + { + forwardVelocity += walkDirection*Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)) * walkSpeed*0.2f; + } + if(rightSpeed < maxSpeed) + { + rightVelocity += walkDirection*Oyster::Math::Float3(fabs(rightDir.x), fabs(rightDir.y), fabs(rightDir.z)) * walkSpeed*0.2f; + } + } + } + + // Adjust velocities so no squaring occurs + forwardVelocity *= Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)); + rightVelocity *= Oyster::Math::Float3(fabs(rightDir.x), fabs(rightDir.y), fabs(rightDir.z)); + upVelocity *= Oyster::Math::Float3(fabs(upDir.x), fabs(upDir.y), fabs(upDir.z)); + + this->rigidBody->SetLinearVelocity(forwardVelocity+rightVelocity+upVelocity); + + //Jump + if(key_jump > 0.001) + { + this->key_jump -= this->gameInstance->GetFrameTime(); + if(this->rigidBody->GetLambda() < 0.9f) + { + Oyster::Math::Float3 up = this->rigidBody->GetState().centerPos.GetNormalized(); + this->rigidBody->ApplyImpulse(up*this->rigidBody->GetState().mass * 20); + this->playerState = PLAYER_STATE::PLAYER_STATE_JUMPING; } } } - - // Adjust velocities so no squaring occurs - forwardVelocity *= Oyster::Math::Float3(fabs(forwardDir.x), fabs(forwardDir.y), fabs(forwardDir.z)); - rightVelocity *= Oyster::Math::Float3(fabs(rightDir.x), fabs(rightDir.y), fabs(rightDir.z)); - upVelocity *= Oyster::Math::Float3(fabs(upDir.x), fabs(upDir.y), fabs(upDir.z)); - - this->rigidBody->SetLinearVelocity(forwardVelocity+rightVelocity+upVelocity); - - //Jump - if(key_jump > 0.001) - { - this->key_jump -= this->gameInstance->GetFrameTime(); - if(this->rigidBody->GetLambda() < 0.9f) - { - Oyster::Math::Float3 up = this->rigidBody->GetState().centerPos.GetNormalized(); - this->rigidBody->ApplyImpulse(up*this->rigidBody->GetState().mass*20); - this->playerState = PLAYER_STATE::PLAYER_STATE_JUMPING; - } - } - - - - - //this->weapon->Update(0.01f); } void Player::EndFrame() { - - //Object::EndFrame(); + //check if there are any objects that can be removed from the AffectedObjects list + for(int i = 0; i < this->AffectedObjects.Size(); i++) + { + if(this->AffectedObjects[i] && (this->AffectedObjects[i]->GetRigidBody()->GetState().previousVelocity).GetMagnitude() <= 0.1f) + { + this->AffectedObjects[i]->RemoveAffectedBy(); + this->AffectedObjects.Remove(i); + } + } } void Player::Move(const PLAYER_MOVEMENT &movement) @@ -258,16 +253,19 @@ void Player::UseWeapon(const WEAPON_FIRE &usage) void Player::Respawn(Oyster::Math::Float3 spawnPoint) { - this->life = 100; - this->playerState = PLAYER_STATE::PLAYER_STATE_IDLE; - this->lookDir = Oyster::Math::Float4(1,0,0); - this->rigidBody->SetPosition(spawnPoint); + if( this->playerState == PLAYER_STATE_DEAD) + { + Player::initPlayerData(); + this->rigidBody->SetPosition(spawnPoint); + this->gameInstance->onRespawnFnc( this, spawnPoint); + this->gameInstance->onDamageTakenFnc( this, this->playerStats.hp); + } } -void Player::Rotate(const Oyster::Math3D::Float3& lookDir, const Oyster::Math3D::Float3& right) +void Player::SetLookDir(const Oyster::Math3D::Float3& lookDir) { // this is the camera right vector - this->lookDir = lookDir; + this->lookDir = -lookDir; } void Player::TurnLeft(Oyster::Math3D::Float deltaRadians) @@ -293,6 +291,11 @@ bool Player::IsIdle() return (this->playerState == PLAYER_STATE::PLAYER_STATE_IDLE); } +void Player::Inactivate() +{ + //this-> +} + Oyster::Math::Float3 Player::GetPosition() const { return (Oyster::Math::Float3) this->rigidBody->GetState().centerPos; @@ -316,13 +319,43 @@ PLAYER_STATE Player::GetState() const void Player::DamageLife(int damage) { - this->life -= damage; - this->life = 0; + this->playerStats.hp -= damage; + // send hp to client + this->gameInstance->onDamageTakenFnc( this, this->playerStats.hp); - if(this->life <= 0) + if(this->playerStats.hp <= 0) { - this->life = 0; - playerState = PLAYER_STATE_DEAD; - this->gameInstance->onDisableFnc(this, 0.0f); + this->playerStats.hp = 0; + this->playerState = PLAYER_STATE_DIED; } + +} + +void Player::AddAffectedObject(DynamicObject &AffectedObject) +{ + //check if object already exists in the list, if so then do not add + for(int i = 0; i < AffectedObjects.Size(); i++) + { + if(AffectedObjects[i]->GetID() == AffectedObject.GetID()) + { + //object already exists, exit function + return; + } + } + //else you add the object to the stack + AffectedObjects.Push(&AffectedObject); +} +bool Player::deathTimerTick(float dt) +{ + this->deathTimer -= dt; + if( this->deathTimer <= 0) + { + return true; + } + return false; +} +void Player::setDeathTimer(float deathTimer) +{ + this->deathTimer = deathTimer; + this->playerState = PLAYER_STATE_DEAD; } diff --git a/Code/Game/GameLogic/Player.h b/Code/Game/GameLogic/Player.h index 13c6e300..c64ba066 100644 --- a/Code/Game/GameLogic/Player.h +++ b/Code/Game/GameLogic/Player.h @@ -7,7 +7,10 @@ #include "GameLogicStates.h" #include "OysterMath.h" #include "DynamicObject.h" +#include "DynamicArray.h" +const float MAX_HP = 100.0f; +const float BASIC_SPEED = 30.0f; namespace GameLogic { @@ -15,6 +18,21 @@ namespace GameLogic class Player : public DynamicObject { public: + struct PlayerStats + { + Oyster::Math::Float hp; + Oyster::Math::Float movementSpeed; + //Oyster::Math::Float resistance; + }; + + struct PlayerScore + { + int killScore; + int deathScore; + // int assistScore; + // int suicideScore; + }; + Player(void); Player(Oyster::Physics::ICustomBody *rigidBody, void (*EventOnCollision)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), ObjectSpecialType type, int objectID, int teamID); @@ -46,9 +64,11 @@ namespace GameLogic void Respawn(Oyster::Math::Float3 spawnPoint); - void Rotate(const Oyster::Math3D::Float3& lookDir, const Oyster::Math3D::Float3& right); + void SetLookDir(const Oyster::Math3D::Float3& lookDir); void TurnLeft(Oyster::Math3D::Float deltaRadians); + + void AddAffectedObject(DynamicObject &AffectedObject); /******************************************************** * Collision function for player, this is to be sent to physics through the subscribe function with the rigidbody @@ -56,13 +76,15 @@ namespace GameLogic * @param rigidBodyPlayer: physics object of the player * @param obj: physics object for the object that collided with the player ********************************************************/ - static void PlayerCollision(Oyster::Physics::ICustomBody *rigidBodyPlayer, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss); + static void PlayerCollision(Oyster::Physics::ICustomBody *objA, Oyster::Physics::ICustomBody *objB, Oyster::Math::Float kineticEnergyLoss); bool IsWalking(); bool IsJumping(); bool IsIdle(); + void Inactivate(); + Oyster::Math::Float3 GetPosition() const; Oyster::Math::Float3 GetLookDir() const; Oyster::Math::Float4x4 GetOrientation() const; @@ -70,6 +92,8 @@ namespace GameLogic PLAYER_STATE GetState() const; void DamageLife(int damage); + void setDeathTimer(float deathTimer); + bool deathTimerTick(float dt); void BeginFrame(); void EndFrame(); @@ -77,9 +101,11 @@ namespace GameLogic private: void Jump(); + void initPlayerData(); private: - Oyster::Math::Float life; + + Utility::DynamicMemory::DynamicArray AffectedObjects; int teamID; Weapon *weapon; PLAYER_STATE playerState; @@ -91,16 +117,15 @@ namespace GameLogic float key_jump; - Oyster::Math::Float3 previousPosition; - Oyster::Math::Float3 moveDir; - Oyster::Math::Float moveSpeed; - Oyster::Math::Float3 previousMoveSpeed; - Oyster::Math::Float rotationUp; + float deathTimer; bool hasTakenDamage; float invincibleCooldown; + PlayerStats playerStats; + PlayerScore playerScore; + }; } #endif \ No newline at end of file diff --git a/Code/Game/GameProtocols/ObjectProtocols.h b/Code/Game/GameProtocols/ObjectProtocols.h index cae7c7f5..1ffc30ad 100644 --- a/Code/Game/GameProtocols/ObjectProtocols.h +++ b/Code/Game/GameProtocols/ObjectProtocols.h @@ -75,13 +75,15 @@ namespace GameLogic } Protocol_ObjectDamage(Oyster::Network::CustomNetProtocol& p) { - + this->object_ID = p[1].value.netInt; + this->healthLost = p[2].value.netFloat; } Protocol_ObjectDamage(int id, float hp) { this->protocol[0].value = protocol_Gameplay_ObjectDamage; this->protocol[0].type = Oyster::Network::NetAttributeType_Short; - + + this->protocol[1].type = Oyster::Network::NetAttributeType_Int; this->protocol[2].type = Oyster::Network::NetAttributeType_Float; object_ID = id; @@ -292,6 +294,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; + //#define protocol_Gameplay_ObjectEnabled 356 struct Protocol_ObjectPositionRotation :public Oyster::Network::CustomProtocolObject { short object_ID; @@ -366,7 +369,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectEnabled 356 + //#define protocol_Gameplay_ObjectEnabled 357 struct Protocol_ObjectEnable :public Oyster::Network::CustomProtocolObject { int objectID; @@ -399,7 +402,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectDisabled 357 + //#define protocol_Gameplay_ObjectDisabled 358 struct Protocol_ObjectDisable :public Oyster::Network::CustomProtocolObject { int objectID; @@ -439,7 +442,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectCreate 358 + //#define protocol_Gameplay_ObjectCreate 359 struct Protocol_ObjectCreate :public Oyster::Network::CustomProtocolObject { //ObjectType type; //ie player, box or whatever @@ -543,7 +546,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectCreatePlayer 359 + //#define protocol_Gameplay_ObjectCreatePlayer 360 struct Protocol_ObjectCreatePlayer :public Oyster::Network::CustomProtocolObject { /*1*/ int object_ID; @@ -673,7 +676,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectJoinTeam 360 + //#define protocol_Gameplay_ObjectJoinTeam 361 struct Protocol_ObjectJoinTeam :public Oyster::Network::CustomProtocolObject { int objectID; @@ -713,7 +716,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectLeaveTeam 361 + //#define protocol_Gameplay_ObjectLeaveTeam 362 struct Protocol_ObjectLeaveTeam :public Oyster::Network::CustomProtocolObject { int objectID; @@ -745,7 +748,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectWeaponCooldown 362 + //#define protocol_Gameplay_ObjectWeaponCooldown 363 struct Protocol_ObjectWeaponCooldown :public Oyster::Network::CustomProtocolObject { float seconds; @@ -777,7 +780,7 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectWeaponEnergy 363 + //#define protocol_Gameplay_ObjectWeaponEnergy 364 struct Protocol_ObjectWeaponEnergy :public Oyster::Network::CustomProtocolObject { float energy; @@ -809,42 +812,51 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectRespawn 364 + //#define protocol_Gameplay_ObjectRespawn 365 struct Protocol_ObjectRespawn :public Oyster::Network::CustomProtocolObject { + int objectID; float position[3]; Protocol_ObjectRespawn() { this->protocol[0].type = Oyster::Network::NetAttributeType_Short; this->protocol[0].value.netShort = protocol_Gameplay_ObjectRespawn; - - this->protocol[1].type = Oyster::Network::NetAttributeType_Float; + // ID + this->protocol[1].type = Oyster::Network::NetAttributeType_Int; + // POSITION this->protocol[2].type = Oyster::Network::NetAttributeType_Float; this->protocol[3].type = Oyster::Network::NetAttributeType_Float; + this->protocol[4].type = Oyster::Network::NetAttributeType_Float; + this->objectID = 0; memset(&this->position[0], 0, sizeof(float) * 3); } - Protocol_ObjectRespawn(float position[3]) + Protocol_ObjectRespawn(int id, float position[3]) { this->protocol[0].type = Oyster::Network::NetAttributeType_Short; this->protocol[0].value.netShort = protocol_Gameplay_ObjectRespawn; - this->protocol[1].type = Oyster::Network::NetAttributeType_Float; + // ID + this->protocol[1].type = Oyster::Network::NetAttributeType_Int; + // POSITION this->protocol[2].type = Oyster::Network::NetAttributeType_Float; this->protocol[3].type = Oyster::Network::NetAttributeType_Float; - + this->protocol[4].type = Oyster::Network::NetAttributeType_Float; + this->objectID = id; memcpy(&this->position[0], &position[0], sizeof(float) * 3); } Protocol_ObjectRespawn(Oyster::Network::CustomNetProtocol& p) { - this->position[0] = p[1].value.netFloat; - this->position[1] = p[2].value.netFloat; - this->position[2] = p[3].value.netFloat; + this->objectID = p[1].value.netInt; + this->position[0] = p[2].value.netFloat; + this->position[1] = p[3].value.netFloat; + this->position[2] = p[4].value.netFloat; } Oyster::Network::CustomNetProtocol GetProtocol() override { - this->protocol[1].value = this->position[0]; - this->protocol[2].value = this->position[1]; - this->protocol[3].value = this->position[2]; + this->protocol[1].value = this->objectID; + this->protocol[2].value = this->position[0]; + this->protocol[3].value = this->position[1]; + this->protocol[4].value = this->position[2]; return protocol; } @@ -852,10 +864,11 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; - //#define protocol_Gameplay_ObjectDie 365 + //#define protocol_Gameplay_ObjectDie 366 struct Protocol_ObjectDie :public Oyster::Network::CustomProtocolObject { int objectID; + int killerID; float seconds; Protocol_ObjectDie() @@ -863,28 +876,34 @@ namespace GameLogic this->protocol[0].type = Oyster::Network::NetAttributeType_Short; this->protocol[0].value.netShort = protocol_Gameplay_ObjectDie; this->protocol[1].type = Oyster::Network::NetAttributeType_Int; - this->protocol[2].type = Oyster::Network::NetAttributeType_Float; - this->objectID = 0; + this->protocol[2].type = Oyster::Network::NetAttributeType_Int; + this->protocol[3].type = Oyster::Network::NetAttributeType_Float; + this->objectID = -1; + this->killerID = -1; this->seconds = 0.0f; } - Protocol_ObjectDie(int objectID, float seconds) + Protocol_ObjectDie(int objectID, int killerID, float seconds) { this->protocol[0].type = Oyster::Network::NetAttributeType_Short; this->protocol[0].value.netShort = protocol_Gameplay_ObjectDie; this->protocol[1].type = Oyster::Network::NetAttributeType_Int; - this->protocol[2].type = Oyster::Network::NetAttributeType_Float; + this->protocol[2].type = Oyster::Network::NetAttributeType_Int; + this->protocol[3].type = Oyster::Network::NetAttributeType_Float; this->objectID = objectID; + this->killerID = killerID; this->seconds = seconds; } Protocol_ObjectDie(Oyster::Network::CustomNetProtocol& p) { - this->objectID = p[1].value.netInt; - this->seconds = p[2].value.netFloat; + this->objectID = p[1].value.netInt; + this->killerID = p[2].value.netInt; + this->seconds = p[3].value.netFloat; } Oyster::Network::CustomNetProtocol GetProtocol() override { this->protocol[1].value = this->objectID; - this->protocol[2].value = this->seconds; + this->protocol[2].value = this->killerID; + this->protocol[3].value = this->seconds; return protocol; } @@ -925,5 +944,45 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; } +//#define protocol_Gameplay_ObjectAction 368 + struct Protocol_ObjectAction :public Oyster::Network::CustomProtocolObject + { + short objectID; + float animationID; + + Protocol_ObjectAction() + { + this->protocol[0].value = protocol_Gameplay_ObjectAction; + this->protocol[0].type = Oyster::Network::NetAttributeType_Short; + this->protocol[1].type = Oyster::Network::NetAttributeType_Short; + this->protocol[2].type = Oyster::Network::NetAttributeType_Float; + + objectID = 0; + animationID = -1; + } + Protocol_ObjectAction(Oyster::Network::CustomNetProtocol& p) + { + objectID = p[1].value.netShort; + animationID = p[2].value.netFloat; + } + Protocol_ObjectAction(float animID, int id) + { + this->protocol[0].value = protocol_Gameplay_ObjectAction; + this->protocol[0].type = Oyster::Network::NetAttributeType_Short; + this->protocol[1].type = Oyster::Network::NetAttributeType_Short; + this->protocol[2].type = Oyster::Network::NetAttributeType_Float; + objectID = id; + animationID = animID; + } + Oyster::Network::CustomNetProtocol GetProtocol() override + { + this->protocol[1].value = objectID; + this->protocol[2].value = animationID; + return protocol; + } + + private: + Oyster::Network::CustomNetProtocol protocol; + }; #endif // !GAMELOGIC_PLAYER_PROTOCOLS_H \ No newline at end of file diff --git a/Code/Game/GameProtocols/PlayerProtocols.h b/Code/Game/GameProtocols/PlayerProtocols.h index 350c2cf6..eb34c07c 100644 --- a/Code/Game/GameProtocols/PlayerProtocols.h +++ b/Code/Game/GameProtocols/PlayerProtocols.h @@ -79,6 +79,7 @@ namespace GameLogic { public: float deltaRadian; + float lookdir[3]; Protocol_PlayerLeftTurn() { @@ -86,25 +87,40 @@ namespace GameLogic this->protocol[0].type = ::Oyster::Network::NetAttributeType_Short; // deltaRadian this->protocol[1].type = ::Oyster::Network::NetAttributeType_Float; + this->protocol[2].type = Oyster::Network::NetAttributeType_Float; + this->protocol[3].type = Oyster::Network::NetAttributeType_Float; + this->protocol[4].type = Oyster::Network::NetAttributeType_Float; + deltaRadian = 0.0f; + memset(&lookdir[0], 0, sizeof(float) * 3); } Protocol_PlayerLeftTurn( const ::Oyster::Network::CustomNetProtocol &p ) { this->deltaRadian = p[1].value.netFloat; + lookdir[0] = p[2].value.netFloat; + lookdir[1] = p[3].value.netFloat; + lookdir[2] = p[4].value.netFloat; } - Protocol_PlayerLeftTurn( float deltaRadian ) + Protocol_PlayerLeftTurn( float deltaRadian,float v[3] ) { this->protocol[0].value = protocol_Gameplay_PlayerLeftTurn; this->protocol[0].type = ::Oyster::Network::NetAttributeType_Short; - // deltaRadian this->protocol[1].type = ::Oyster::Network::NetAttributeType_Float; + this->protocol[2].type = Oyster::Network::NetAttributeType_Float; + this->protocol[3].type = Oyster::Network::NetAttributeType_Float; + this->protocol[4].type = Oyster::Network::NetAttributeType_Float; this->deltaRadian = deltaRadian; + memcpy(&lookdir[0], &v[0], sizeof(float) * 3); + } ::Oyster::Network::CustomNetProtocol GetProtocol() override { this->protocol[1].value = this->deltaRadian; + this->protocol[2].value = this->lookdir[0]; + this->protocol[3].value = this->lookdir[1]; + this->protocol[4].value = this->lookdir[2]; return protocol; } diff --git a/Code/Game/GameProtocols/ProtocolIdentificationID.h b/Code/Game/GameProtocols/ProtocolIdentificationID.h index cb630012..7aaf2eee 100644 --- a/Code/Game/GameProtocols/ProtocolIdentificationID.h +++ b/Code/Game/GameProtocols/ProtocolIdentificationID.h @@ -69,8 +69,8 @@ #define protocol_Gameplay_ObjectWeaponEnergy 364 #define protocol_Gameplay_ObjectRespawn 365 #define protocol_Gameplay_ObjectDie 366 -//Disconnect #define protocol_Gameplay_ObjectDisconnectPlayer 367 +#define protocol_Gameplay_ObjectAction 368 #define protocol_GameplayMAX 399 diff --git a/Code/Game/GameServer/GameClient.h b/Code/Game/GameServer/GameClient.h index 497e6c2e..aace26c7 100644 --- a/Code/Game/GameServer/GameClient.h +++ b/Code/Game/GameServer/GameClient.h @@ -55,6 +55,7 @@ namespace DanBias GameLogic::IPlayerData* ReleasePlayer(); Oyster::Network::NetClient ReleaseClient(); + bool IsInvalid(); void Invalidate(); int IncrementFailedProtocol(); void ResetFailedProtocolCount(); diff --git a/Code/Game/GameServer/GameSession.h b/Code/Game/GameServer/GameSession.h index ad9440e9..0247571d 100644 --- a/Code/Game/GameServer/GameSession.h +++ b/Code/Game/GameServer/GameSession.h @@ -96,10 +96,13 @@ namespace DanBias void General_Status ( GameLogic::Protocol_General_Status& p, DanBias::GameClient* c ); void General_Text ( GameLogic::Protocol_General_Text& p, DanBias::GameClient* c ); - //Callback method recieving from gamelogic + //Callback method receiving from game logic static void ObjectMove ( GameLogic::IObjectData* movedObject ); static void ObjectDisabled ( GameLogic::IObjectData* movedObject, float seconds ); - + static void ObjectDamaged ( GameLogic::IObjectData* movedObject, float hp ); + static void ObjectRespawned ( GameLogic::IObjectData* movedObject, Oyster::Math::Float3 spawnPos ); + static void ObjectDead ( GameLogic::IObjectData* victim, GameLogic::IObjectData* killer, float seconds ); + //Private member variables private: Utility::DynamicMemory::DynamicArray gClients; diff --git a/Code/Game/GameServer/Implementation/GameClient.cpp b/Code/Game/GameServer/Implementation/GameClient.cpp index 3293a383..90b412ef 100644 --- a/Code/Game/GameServer/Implementation/GameClient.cpp +++ b/Code/Game/GameServer/Implementation/GameClient.cpp @@ -19,18 +19,21 @@ GameClient::GameClient(Utility::DynamicMemory::SmartPointerclient = nwClient; this->player = 0; isReady = false; - this->character = L"crate_colonists.dan"; + this->character = L"char_orca.dan"; this->alias = L"Unknown"; this->secondsSinceLastResponse = 0.0f; } GameClient::~GameClient() { - this->client = 0; - this->player = 0; + if(this->player) + this->player->Inactivate(); + this->isReady = false; - this->character = L"crate_colonists.dan"; + this->character = L"char_orca.dan"; this->alias = L"Unknown"; this->secondsSinceLastResponse = 0.0f; + this->client = 0; + this->player = 0; } void GameClient::SetPlayer(GameLogic::IPlayerData* player) @@ -58,8 +61,14 @@ void GameClient::SetState(ClientState state) this->state = state; } +bool GameClient::IsInvalid() +{ + return this->isInvalid; +} void GameClient::Invalidate() { + this->player->Release(); + this->player = 0; this->isInvalid = true; this->isReady = false; this->state = ClientState_Invalid; diff --git a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp index 0c52dfff..6c8e6dc3 100644 --- a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp +++ b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp @@ -29,10 +29,10 @@ using namespace DanBias; float dt = (float)this->logicTimer.getElapsedSeconds(); if( dt >= this->logicFrameTime ) { + this->logicTimer.reset(); + this->ProcessClients(); this->gameInstance.NewFrame(); - - this->logicTimer.reset(); } } @@ -90,7 +90,7 @@ using namespace DanBias; { for (unsigned int i = 0; i < this->gClients.Size(); i++) { - if(this->gClients[i] ) + if(this->gClients[i] && !this->gClients[i]->IsInvalid()) { this->gClients[i]->UpdateClient(); } @@ -101,7 +101,7 @@ using namespace DanBias; bool returnValue = false; for (unsigned int i = 0; i < this->gClients.Size(); i++) { - if(this->gClients[i]) + if(this->gClients[i] && !this->gClients[i]->IsInvalid()) { this->gClients[i]->GetClient()->Send(message); returnValue = true; @@ -115,7 +115,7 @@ using namespace DanBias; { for (unsigned int i = 0; i < this->gClients.Size(); i++) { - if(this->gClients[i] && this->gClients[i]->GetClient()->GetID() == ID) + if(this->gClients[i] && !this->gClients[i]->IsInvalid() && this->gClients[i]->GetClient()->GetID() == ID) { this->gClients[i]->GetClient()->Send(protocol); return true; @@ -143,9 +143,6 @@ using namespace DanBias; Oyster::Math::Float3 temp = movedObject->GetPosition(); - if(temp.x < -300) - id = 0; - GameSession::gameSession->Send(p.GetProtocol()); //} } @@ -153,7 +150,18 @@ using namespace DanBias; { GameSession::gameSession->Send(Protocol_ObjectDisable(movedObject->GetID(), seconds).GetProtocol()); } - + void GameSession::ObjectDamaged( GameLogic::IObjectData* movedObject, float hp ) + { + GameSession::gameSession->Send(Protocol_ObjectDamage(movedObject->GetID(), hp).GetProtocol()); + } + void GameSession::ObjectRespawned( GameLogic::IObjectData* movedObject, Oyster::Math::Float3 spawnPos ) + { + GameSession::gameSession->Send(Protocol_ObjectRespawn(movedObject->GetID(), spawnPos).GetProtocol()); + } + void GameSession::ObjectDead( GameLogic::IObjectData* victim, GameLogic::IObjectData* killer, float seconds ) + { + GameSession::gameSession->Send(Protocol_ObjectDie(victim->GetID(), killer->GetID(), seconds).GetProtocol()); + } //*****************************************************// //****************** Protocol methods *****************// //******************************************************************************************************************// @@ -180,7 +188,6 @@ using namespace DanBias; break; case protocol_Gameplay_PlayerShot: this->Gameplay_PlayerShot ( Protocol_PlayerShot (p), c ); break; - case protocol_Gameplay_ObjectPickup: this->Gameplay_ObjectPickup ( Protocol_ObjectPickup (p), c ); break; case protocol_Gameplay_ObjectDamage: this->Gameplay_ObjectDamage ( Protocol_ObjectDamage (p), c ); @@ -193,7 +200,6 @@ using namespace DanBias; break; case protocol_Gameplay_ObjectCreate: this->Gameplay_ObjectCreate ( Protocol_ObjectCreate (p), c ); break; - case protocol_General_Status: this->General_Status ( Protocol_General_Status (p), c ); break; case protocol_General_Text: this->General_Text ( Protocol_General_Text (p), c ); @@ -224,6 +230,7 @@ using namespace DanBias; void GameSession::Gameplay_PlayerLeftTurn ( Protocol_PlayerLeftTurn& p, DanBias::GameClient* c ) { c->GetPlayer()->TurnLeft( p.deltaRadian ); + c->GetPlayer()->SetLookDir( p.lookdir ) ; } void GameSession::Gameplay_PlayerChangeWeapon ( Protocol_PlayerChangeWeapon& p, DanBias::GameClient* c ) { @@ -233,11 +240,8 @@ using namespace DanBias; { if(p.secondaryPressed) c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_SECONDARY_PRESS); if(p.primaryPressed) c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_PRIMARY_PRESS); - if(p.utilityPressed) c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_UTILLITY_PRESS); } - - void GameSession::Gameplay_ObjectPickup ( Protocol_ObjectPickup& p, DanBias::GameClient* c ) { diff --git a/Code/Game/GameServer/Implementation/GameSession_General.cpp b/Code/Game/GameServer/Implementation/GameSession_General.cpp index a201167d..0ad12987 100644 --- a/Code/Game/GameServer/Implementation/GameSession_General.cpp +++ b/Code/Game/GameServer/Implementation/GameSession_General.cpp @@ -36,8 +36,8 @@ GameSession::GameSession() this->isCreated = false; this->isRunning = false; this->gameSession = this; - this->logicFrameTime = DELTA_TIME_20; - this->networkFrameTime = DELTA_TIME_20; + this->logicFrameTime = DELTA_TIME_60; + this->networkFrameTime = DELTA_TIME_60; this->networkTimer.reset(); this->logicTimer.reset(); @@ -108,6 +108,9 @@ bool GameSession::Create(GameDescription& desc, bool forceStart) /* Set some game instance data options */ this->gameInstance.SetSubscription(GameSession::ObjectMove); this->gameInstance.SetSubscription(GameSession::ObjectDisabled); + this->gameInstance.SetHpSubscription(GameSession::ObjectDamaged); + this->gameInstance.SetRespawnSubscription(GameSession::ObjectRespawned); + this->gameInstance.SetDeadSubscription(GameSession::ObjectDead); this->gameInstance.SetFPS(60); this->description.clients.Clear(); @@ -214,14 +217,21 @@ bool GameSession::Join(gClient gameClient) { for (unsigned int i = 0; i < this->gClients.Size(); i++) { - if(this->gClients[i]) + if(this->gClients[i] && !this->gClients[i]->IsInvalid()) { IPlayerData* temp = this->gClients[i]->GetPlayer(); - Protocol_ObjectCreatePlayer oc( temp->GetPosition(), temp->GetRotation(), temp->GetScale(), + Protocol_ObjectCreatePlayer p1( temp->GetPosition(), temp->GetRotation(), temp->GetScale(), temp->GetID(), false, temp->GetTeamID(), Utility::String::WStringToString(this->gClients[i]->GetAlias(), std::string()), Utility::String::WStringToString(this->gClients[i]->GetCharacter(), std::string())); - nwClient->Send(oc); + nwClient->Send(p1); + + temp = playerData; + Protocol_ObjectCreatePlayer p2( temp->GetPosition(), temp->GetRotation(), temp->GetScale(), + temp->GetID(), false, temp->GetTeamID(), + Utility::String::WStringToString(gameClient->GetAlias(), std::string()), + Utility::String::WStringToString(gameClient->GetCharacter(), std::string())); + this->gClients[i]->GetClient()->Send(p2); } } } @@ -234,7 +244,7 @@ bool GameSession::Join(gClient gameClient) { //Protocol_ObjectPosition p(movedObject->GetPosition(), id); Protocol_ObjectPositionRotation p(objects[i]->GetPosition(), objects[i]->GetRotation(), objects[i]->GetID()); - gameClient->GetClient()->Send(p.GetProtocol()); + nwClient->Send(p.GetProtocol()); } } diff --git a/Code/Game/LanServer/GameServerDebugEnvironment/Source.cpp b/Code/Game/LanServer/GameServerDebugEnvironment/Source.cpp index 62332541..3357f52c 100644 --- a/Code/Game/LanServer/GameServerDebugEnvironment/Source.cpp +++ b/Code/Game/LanServer/GameServerDebugEnvironment/Source.cpp @@ -32,7 +32,7 @@ int WINAPI WinMain( HINSTANCE hinst, HINSTANCE prevInst, PSTR cmdLine, int cmdSh GameServerAPI::GameSetGameMode(L"free-for-all"); GameServerAPI::GameSetGameName(L"DebugServer"); GameServerAPI::GameSetGameTime(15); - GameServerAPI::GameSetMapName(L"2ofAll.bias"); + GameServerAPI::GameSetMapName(L"erik_250.bias"); GameServerAPI::GameSetMaxClients(10); if(GameServerAPI::GameStart(true)) diff --git a/Code/Game/LevelLoader/LevelParser.cpp b/Code/Game/LevelLoader/LevelParser.cpp index 5f5a5341..fe349988 100644 --- a/Code/Game/LevelLoader/LevelParser.cpp +++ b/Code/Game/LevelLoader/LevelParser.cpp @@ -166,16 +166,17 @@ std::vector> LevelParser::Parse(std::string filen case ObjectType_Light: { - LightType lightType; + //LightType lightType; //Get Light type - ParseObject(&buffer[counter+4], &lightType, sizeof(lightType)); + //ParseObject(&buffer[counter+4], &lightType, sizeof(lightType)); //We only support PointLight for now. BasicLight* header = new BasicLight; - ParseObject(&buffer[counter], header, sizeof(*header)); - counter += sizeof(*header); + + ParseLight(&buffer[counter], *header, counter); objects.push_back(header); + /*switch(lightType) { case LightType_PointLight: @@ -208,6 +209,7 @@ std::vector> LevelParser::Parse(std::string filen } break;*/ } + break; default: //Couldn't find typeID. FAIL!!!!!! break; diff --git a/Code/Game/LevelLoader/ObjectDefines.h b/Code/Game/LevelLoader/ObjectDefines.h index 918fb4e6..52f0e088 100644 --- a/Code/Game/LevelLoader/ObjectDefines.h +++ b/Code/Game/LevelLoader/ObjectDefines.h @@ -52,6 +52,7 @@ namespace GameLogic CollisionGeometryType_Box, CollisionGeometryType_Sphere, CollisionGeometryType_Cylinder, + CollisionGeometryType_CG_MESH, CollisionGeometryType_Count, CollisionGeometryType_Unknown = -1 @@ -161,6 +162,11 @@ namespace GameLogic float radius; }; + struct BoundingVolumeCGMesh : public BoundingVolumeBase + { + wchar_t filename[128]; + }; + struct BoundingVolume { CollisionGeometryType geoType; @@ -169,9 +175,9 @@ namespace GameLogic LevelLoaderInternal::BoundingVolumeBox box; LevelLoaderInternal::BoundingVolumeSphere sphere; LevelLoaderInternal::BoundingVolumeCylinder cylinder; + LevelLoaderInternal::BoundingVolumeCGMesh cgMesh; }; }; - } struct LevelMetaData : public ObjectTypeHeader @@ -253,8 +259,10 @@ namespace GameLogic LightType lightType; //Is not used right now float color[3]; float position[3]; - float raduis; + float radius; float intensity; + + virtual ~BasicLight(){} }; /* We only support pointlight right now. struct PointLight : public BasicLight diff --git a/Code/Game/LevelLoader/ParseFunctions.cpp b/Code/Game/LevelLoader/ParseFunctions.cpp index 09adb298..ac361c46 100644 --- a/Code/Game/LevelLoader/ParseFunctions.cpp +++ b/Code/Game/LevelLoader/ParseFunctions.cpp @@ -20,6 +20,32 @@ namespace GameLogic memcpy(header, buffer, size); } + void ParseLight(char* buffer, BasicLight& header, int& size) + { + int start = 0; + memcpy(&header.typeID, &buffer[start], 40); + start += 40; + /* + memcpy(&header.lightType, &buffer[start], 4); + start += 4; + + memcpy(&header.color, &buffer[start], 12); + start += 12; + + memcpy(&header.position, &buffer[start], 12); + start += 12; + + memcpy(&header.radius, &buffer[start], 4); + start += 4; + + memcpy(&header.intensity, &buffer[start], 4); + start += 4;*/ + + size += start; + + //memcpy(&header, buffer, size); + } + void ParseObject(char* buffer, ObjectHeader& header, int& size, bool loadCgf) { char tempName[128]; @@ -173,6 +199,22 @@ namespace GameLogic start += sizeof(volume.cylinder); break; + case CollisionGeometryType_CG_MESH: + { + memcpy(&volume.cgMesh, &buf[start], sizeof(float)*12); + start += sizeof(float)*12; + memcpy(&tempSize, &buf[start], sizeof(tempSize)); + start += 4; + memcpy(&tempName, &buf[start], tempSize); + tempName[tempSize] = '\0'; + + //convert from char[] to wchar_t[] + mbstowcs_s(NULL, volume.cgMesh.filename, tempSize+1, tempName, _TRUNCATE); + + start += tempSize; + } + break; + default: break; } diff --git a/Code/Game/LevelLoader/ParseFunctions.h b/Code/Game/LevelLoader/ParseFunctions.h index 0fc6dbc6..21e43858 100644 --- a/Code/Game/LevelLoader/ParseFunctions.h +++ b/Code/Game/LevelLoader/ParseFunctions.h @@ -18,6 +18,7 @@ namespace GameLogic */ void ParseObject(char* buffer, void *header, int size); + void ParseLight(char* buffer, BasicLight& header, int& size); void ParseObject(char* buffer, ObjectHeader& header, int& size , bool loadCgf); void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size); void ParseBoundingVolume(char* buffer, LevelLoaderInternal::BoundingVolume& volume, int &size); diff --git a/Code/Misc/OysterMath/LinearMath.h b/Code/Misc/OysterMath/LinearMath.h index 25b65331..5b87d83d 100644 --- a/Code/Misc/OysterMath/LinearMath.h +++ b/Code/Misc/OysterMath/LinearMath.h @@ -376,9 +376,13 @@ namespace LinearAlgebra3D template inline ::LinearAlgebra::Vector3 AngularAxis( const ::LinearAlgebra::Quaternion &rotation ) { // see http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - ScalarType angle = ScalarType(2) * (ScalarType)::std::acos( rotation.real ), - multiplier = angle / (ScalarType)::std::sqrt( ScalarType(1) - rotation.real * rotation.real ); - return multiplier * rotation.imaginary; + if( rotation.real < ScalarType(1) ) + { + ScalarType angle = ScalarType(2) * ScalarType( ::std::acos(rotation.real) ), + multiplier = angle / ScalarType( ::std::sqrt(ScalarType(1) - rotation.real * rotation.real) ); + return multiplier * rotation.imaginary; + } + else return ::LinearAlgebra::Vector3::null; } // All Matrix to AngularAxis conversions here is incorrect @@ -838,7 +842,7 @@ namespace LinearAlgebra3D template ::LinearAlgebra::Vector3 & SnapAngularAxis( const ::LinearAlgebra::Vector3 &startAngularAxis, const ::LinearAlgebra::Vector3 &localStartNormal, const ::LinearAlgebra::Vector3 &worldEndNormal, ::LinearAlgebra::Vector3 &targetMem = ::LinearAlgebra::Vector3() ) - { + { //! @todo TODO: This code is broken and do not work! ::LinearAlgebra::Vector3 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis), localStartNormal) ); targetMem = worldStartNormal.Cross( worldEndNormal ); targetMem *= (ScalarType)::std::acos( ::Utility::Value::Clamp(worldStartNormal.Dot(worldEndNormal), (ScalarType)0, (ScalarType)1) ); diff --git a/Code/Misc/Utilities/Resource/ResourceManager.cpp b/Code/Misc/Utilities/Resource/ResourceManager.cpp index 04c03a6f..e23ff398 100644 --- a/Code/Misc/Utilities/Resource/ResourceManager.cpp +++ b/Code/Misc/Utilities/Resource/ResourceManager.cpp @@ -437,6 +437,38 @@ int ResourceManager::GetResourceId(const wchar_t c[]) return -1; } +int ResourceManager::GetResourceCount(const wchar_t filename[]) +{ + ResourceData *t = FindResource(this->resources, filename); + + if(t) return t->referenceCount; + + return 0; +} +int ResourceManager::GetResourceCount(const HRESOURCE& resource) +{ + ResourceData *t = FindResource(this->resources, resource); + + if(t) return t->referenceCount; + + return 0; +} +int ResourceManager::GetResourceSize(const wchar_t filename[]) +{ + ResourceData *t = FindResource(this->resources, filename); + + if(t) return t->resourceSize; + + return 0; +} +int ResourceManager::GetResourceSize(const HRESOURCE& resource) +{ + ResourceData *t = FindResource(this->resources, resource); + + if(t) return t->resourceSize; + + return 0; +} diff --git a/Code/Misc/Utilities/Resource/ResourceManager.h b/Code/Misc/Utilities/Resource/ResourceManager.h index d5684538..b3de6af5 100644 --- a/Code/Misc/Utilities/Resource/ResourceManager.h +++ b/Code/Misc/Utilities/Resource/ResourceManager.h @@ -148,6 +148,14 @@ namespace Oyster * @return Returns the accociated ID */ int GetResourceId(const wchar_t filename[]); + + int GetResourceCount(const wchar_t filename[]); + + int GetResourceCount(const HRESOURCE& resource); + + int GetResourceSize(const wchar_t filename[]); + + int GetResourceSize(const HRESOURCE& resource); private: ResourceManager(const ResourceManager& obj); diff --git a/Code/Misc/Utilities/Utilities.h b/Code/Misc/Utilities/Utilities.h index b97d62d7..bf9bb65c 100644 --- a/Code/Misc/Utilities/Utilities.h +++ b/Code/Misc/Utilities/Utilities.h @@ -44,6 +44,7 @@ namespace Utility ReferenceCount() :count(0) { } ReferenceCount(const ReferenceCount& o) { count = o.count; } inline const ReferenceCount& operator=(const ReferenceCount& o) { count = o.count; return *this;} + operator int() { return this->count; } inline void Incref() { this->count++; } inline void Incref(int c) { this->count += c; } inline int Decref() { return --this->count;} diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index 3463ed8a..56425109 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -56,6 +56,17 @@ struct NetworkClient::PrivateData : public IThreadObject ThreadSafeQueue sendQueue; ThreadSafeQueue> recieveQueue; + //Testing for eventSelect. + HANDLE socketEvents[2]; + HANDLE shutdownEvent; + + //The OysterByte each message is packed in. + OysterByte tempMessage; + + //Used to buffer messages + OysterByte bufferedSend; + int numPackages; + //ID static unsigned int currID; const unsigned int ID; @@ -65,14 +76,18 @@ struct NetworkClient::PrivateData : public IThreadObject , parent(0) , owner(0) , outputEvent(0) - { + { + numPackages = 0; + bufferedSend.Resize(MAX_NETWORK_MESSAGE_SIZE); + tempMessage.Resize(MAX_NETWORK_MESSAGE_SIZE); InitWinSock(); this->thread.Create(this, false); this->thread.SetPriority(Oyster::Thread::OYSTER_THREAD_PRIORITY_1); } ~PrivateData() { - this->thread.Terminate(); + SetEvent(shutdownEvent); + this->thread.Wait(); ShutdownWinSock(); this->connection.Disconnect(); @@ -80,15 +95,150 @@ struct NetworkClient::PrivateData : public IThreadObject this->parent = 0; } + void ThreadEntry() + { + //Create alla events used in the thread + shutdownEvent = CreateEvent(NULL, true, false, NULL); + socketEvents[0] = WSACreateEvent(); + socketEvents[1] = WSACreateEvent(); + + if(socketEvents[0] == WSA_INVALID_EVENT) + { + //Error + } + + if(WSAEventSelect(this->connection.GetSocket(), socketEvents[0], FD_READ) == SOCKET_ERROR) + { + //Error + } + } + + void ThreadExit() + { + WSACloseEvent(socketEvents[0]); + WSACloseEvent(socketEvents[1]); + CloseHandle(shutdownEvent); + } + bool DoWork() override { - if(!this->connection.IsConnected()) return false; + WSANETWORKEVENTS wsaEvents; - Send(); - Recv(); - - return true; + while(WaitForSingleObject(shutdownEvent, 0) != WAIT_OBJECT_0) + { + if(!this->connection.IsConnected()) return false; + + int result = WSAWaitForMultipleEvents(2, socketEvents, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0; + if(result == 0) + { + WSAEnumNetworkEvents(this->connection.GetSocket(), socketEvents[0], &wsaEvents); + if((wsaEvents.lNetworkEvents & FD_READ) && (wsaEvents.iErrorCode[FD_READ_BIT] == 0)) + { + //Recieve a message + Recv(); + } + } + else if(result == 1) + { + //Send all messages in the sendQueue + int i = this->sendQueue.Size(); + WSAResetEvent(socketEvents[1]); + + if(i == 1) + { + Send(); + } + else if(i > 1) + { + for(int j = 0; j < i; j++) + BufferMessage(); + + SendBuffer(); + } + } + } + + return false; } + + void SendBuffer() + { + if(bufferedSend.GetSize() > 0) + { + this->connection.Send(bufferedSend); + //printf("2. %d, %d\n", numPackages, bufferedSend.GetSize()); + bufferedSend.Clear(); + + //Debug + numPackages = 0; + } + } + + void BufferMessage() + { + int errorCode = 0; + + if(!this->sendQueue.IsEmpty()) + { + CustomNetProtocol p = this->sendQueue.Pop(); + + this->translator.Pack(tempMessage, p); + + + if(tempMessage.GetSize() > MAX_NETWORK_MESSAGE_SIZE - bufferedSend.GetSize()) + { + //Send buffered message + errorCode = this->connection.Send(bufferedSend); + //printf("2. %d, %d\n", numPackages, bufferedSend.GetSize()); + bufferedSend.Clear(); + + //Debug + numPackages = 0; + } + + bufferedSend += tempMessage; + tempMessage.Clear(); + + //Debug + numPackages++; + + if(errorCode != 0 && errorCode != WSAEWOULDBLOCK) + { + if( errorCode == WSAECONNABORTED || errorCode == WSAENOTCONN) + { + CEA parg; + parg.type = CEA::EventType_Disconnect; + parg.data.protocol = p; + NetEvent e = { this->parent, parg }; + this->recieveQueue.Push(e); + + if(this->outputEvent) + { + printf("\t(ID: %i | IP: %s | Protocol: %i) - EventType_Disconnect && EventType_ProtocolFailedToSend \n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort); + } + } + else + { + CEA parg; + parg.type = CEA::EventType_ProtocolFailedToSend; + parg.data.protocol = p; + NetEvent e = { this->parent, parg }; + this->recieveQueue.Push(e); + + if(this->outputEvent) + { + printf("\t(ID: %i | IP: %s | Protocol: %i) - EventType_ProtocolFailedToSend\n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort); + } + } + } + + if(this->outputEvent) + { + printf("\t(ID: %i | IP: %s | Protocol: %i) Message sent!\n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort); + } + } + } + int Send() { int errorCode = 0; @@ -96,11 +246,11 @@ struct NetworkClient::PrivateData : public IThreadObject if(!this->sendQueue.IsEmpty()) { //printf("\t(%i)\n", this->sendQueue.Size()); - OysterByte temp; CustomNetProtocol p = this->sendQueue.Pop(); - this->translator.Pack(temp, p); - errorCode = this->connection.Send(temp); + this->translator.Pack(tempMessage, p); + errorCode = this->connection.Send(tempMessage); + tempMessage.Clear(); if(errorCode != 0 && errorCode != WSAEWOULDBLOCK) { @@ -144,12 +294,12 @@ struct NetworkClient::PrivateData : public IThreadObject { int errorCode = -1; - OysterByte temp = OysterByte(); - errorCode = this->connection.Recieve(temp); + errorCode = this->connection.Recieve(tempMessage); - if(errorCode == 0 && temp.GetSize()) + if(errorCode == 0 && tempMessage.GetSize()) { - HandleRecievedData(temp); + HandleRecievedData(tempMessage); + tempMessage.Clear(); /* Replaced with EmptyOutbufferedQueue() and HandleRecievedData(OysterByte) @@ -312,7 +462,7 @@ bool NetworkClient::Connect(ConnectionInfo& socket) if(this->privateData) return false; if(!this->privateData) this->privateData = new PrivateData(); - int result = this->privateData->connection.Connect(socket, false); + int result = this->privateData->connection.Connect(socket, true); //Connect has succeeded if(result != 0) return false; @@ -333,7 +483,7 @@ bool NetworkClient::Connect(unsigned short port, const char serverIP[]) if(!this->privateData) this->privateData = new PrivateData(); - int result = this->privateData->connection.Connect(port, serverIP, false); + int result = this->privateData->connection.Connect(port, serverIP, true); //Connect has succeeded if(result != 0) return false; @@ -381,7 +531,9 @@ void NetworkClient::Disconnect() { if(!privateData) return; - privateData->thread.Stop(); + SetEvent(privateData->shutdownEvent); + privateData->thread.Wait(); + privateData->connection.Disconnect(); this->privateData->sendQueue.Clear(); this->privateData->recieveQueue.Clear(); @@ -390,11 +542,13 @@ void NetworkClient::Disconnect() void NetworkClient::Send(CustomProtocolObject& protocol) { this->privateData->sendQueue.Push(protocol.GetProtocol()); + WSASetEvent(this->privateData->socketEvents[1]); } void NetworkClient::Send(CustomNetProtocol& protocol) { this->privateData->sendQueue.Push(protocol); + WSASetEvent(this->privateData->socketEvents[1]); } void NetworkClient::SetOwner(NetworkSession* owner) diff --git a/Code/Network/NetworkAPI/NetworkServer.h b/Code/Network/NetworkAPI/NetworkServer.h index 593c3847..82693310 100644 --- a/Code/Network/NetworkAPI/NetworkServer.h +++ b/Code/Network/NetworkAPI/NetworkServer.h @@ -22,16 +22,16 @@ namespace Oyster { struct BroadcastOptions { - //bool broadcast; - //float broadcastInterval; - //std::wstring subnetToBroadcast; - //CustomNetProtocol broadcastMessage; - //BroadcastOptions() - //{ - // broadcast = true; - // broadcastInterval = 1.0f; - // subnetToBroadcast = L"192.168.0.1"; - //} + bool broadcast; + float broadcastInterval; + std::wstring subnetToBroadcast; + CustomNetProtocol broadcastMessage; + BroadcastOptions() + { + broadcast = true; + broadcastInterval = 1.0f; + subnetToBroadcast = L"192.168.0.1"; + } } broadcastOptions; struct MainOptions @@ -117,6 +117,23 @@ namespace Oyster */ int NetworkServer::GetPort(); + + + /*************************************** + Broadcast functions + ***************************************/ + //Set broadcast settings. + void SetBroadcast(CustomNetProtocol& broadcastMessage, float interval = 1.0f, bool enable = true); + + //Set broadcast settings. + void SetBroadcastMessage(CustomNetProtocol& broadcastMessage); + + //Enable/disable broadcast. + void SetBroadcast(bool enable); + + //Set interval between each broadcast message in seconds. + void SetBroadcastInterval(float interval); + private: struct PrivateData; PrivateData* privateData; diff --git a/Code/Network/NetworkDependencies/Connection.cpp b/Code/Network/NetworkDependencies/Connection.cpp index 2cd992a2..0b0a6a3d 100644 --- a/Code/Network/NetworkDependencies/Connection.cpp +++ b/Code/Network/NetworkDependencies/Connection.cpp @@ -188,8 +188,8 @@ int Connection::Recieve(OysterByte &bytes) if(this->closed) return -1; int nBytes; - bytes.Resize(1000); - nBytes = recv(this->socket, bytes, 1000, 0); + bytes.Resize(MAX_NETWORK_MESSAGE_SIZE); + nBytes = recv(this->socket, bytes, MAX_NETWORK_MESSAGE_SIZE, 0); if(nBytes == SOCKET_ERROR) { bytes.SetSize(0); @@ -263,6 +263,11 @@ std::string Connection::GetIpAddress() return this->addr; } +int Connection::GetSocket() +{ + return socket; +} + /////////////////////////////////////// //Private functions /////////////////////////////////////// diff --git a/Code/Network/NetworkDependencies/Connection.h b/Code/Network/NetworkDependencies/Connection.h index 054537fc..e1c98a76 100644 --- a/Code/Network/NetworkDependencies/Connection.h +++ b/Code/Network/NetworkDependencies/Connection.h @@ -39,6 +39,8 @@ namespace Oyster int SetBlockingMode( bool blocking ); std::string GetIpAddress(); + int GetSocket(); + private: int InitiateSocket(); diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.cpp b/Code/Network/NetworkDependencies/ConnectionUDP.cpp index e7d065a6..44a49d2d 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.cpp +++ b/Code/Network/NetworkDependencies/ConnectionUDP.cpp @@ -135,10 +135,10 @@ int ConnectionUDP::Recieve(OysterByte &bytes) sockaddr_in from; int fromLength = sizeof( from ); - bytes.Resize(1000); + bytes.Resize(MAX_NETWORK_MESSAGE_SIZE); nBytes = recvfrom(this->socket, bytes, - 1000, + MAX_NETWORK_MESSAGE_SIZE, 0, (sockaddr*)&from, &fromLength diff --git a/Code/Network/NetworkDependencies/IConnection.h b/Code/Network/NetworkDependencies/IConnection.h index debdfe7b..b4c3627c 100644 --- a/Code/Network/NetworkDependencies/IConnection.h +++ b/Code/Network/NetworkDependencies/IConnection.h @@ -11,6 +11,8 @@ namespace Oyster { namespace Network { + const int MAX_NETWORK_MESSAGE_SIZE = 1400; + struct ConnectionInfo { int socket; @@ -44,6 +46,8 @@ namespace Oyster //Disconnects the client or server TODO: optimize! virtual int Disconnect() = 0; + + virtual int GetSocket() { return -1; }; }; } } diff --git a/Code/OysterGraphics/Definitions/GraphicalDefinition.h b/Code/OysterGraphics/Definitions/GraphicalDefinition.h index f6a6431c..77aecdc8 100644 --- a/Code/OysterGraphics/Definitions/GraphicalDefinition.h +++ b/Code/OysterGraphics/Definitions/GraphicalDefinition.h @@ -90,6 +90,14 @@ namespace Oyster Math::Float3 GlowTint; Math::Float PAD2; }; + + struct RenderInstanceData + { + Math::Matrix WV; + Math::Matrix WVP; + Math::Float3 Tint; + Math::Float3 GTint; + }; } } } \ No newline at end of file diff --git a/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp b/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp index 8f01bea4..ee3d9f8a 100644 --- a/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp +++ b/Code/OysterGraphics/DllInterfaces/GFXAPI.cpp @@ -19,6 +19,7 @@ namespace Oyster Math::Float4x4 Projection; std::vector Lights; float deltaTime; + int MostModel; #ifdef _DEBUG Model::Model* cube; Model::Model* sphere; @@ -57,9 +58,11 @@ namespace Oyster debugSRV = (ID3D11ShaderResourceView*)API::CreateTexture(L"color_white.png"); cube = CreateModel(L"generic_cube.dan"); - cube->Tint = Math::Float3(0.0f,0.0f,1.0f); + cube->Tint = Math::Float3(1.0f,0.0f,0.0f); + cube->Instanced = false; sphere = CreateModel(L"generic_sphere.dan"); sphere->Tint = Math::Float3(1.0f,0.5f,182/255.0f); + sphere->Instanced = false; D3D11_RASTERIZER_DESC desc; @@ -133,6 +136,35 @@ namespace Oyster return API::Sucsess; } + void API::BeginLoadingModels() + { + } + + void API::EndLoadingModels() + { + //TODO finalize instance buffers and create rendering map; + int maxModels = 0; + for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) + { + if((*i).second->Models > maxModels) + { + maxModels = (*i).second->Models; + } + (*i).second->rid = new Definitions::RenderInstanceData[(*i).second->Models+1]; + } + + Core::Buffer::BUFFER_INIT_DESC desc; + + + desc.ElementSize = sizeof(Definitions::RenderInstanceData); + desc.Type = Core::Buffer::VERTEX_BUFFER; + desc.Usage = Core::Buffer::BUFFER_CPU_WRITE_DISCARD; + desc.InitData = 0; + desc.NumElements = maxModels+1; + + Render::Resources::Gather::InstancedData.Init(desc); + } + //returns null for invalid filenames Model::Model* API::CreateModel(std::wstring filename) { @@ -142,6 +174,7 @@ namespace Oyster m->Animation.AnimationPlaying = NULL; m->Tint = Math::Float3(1); m->GlowTint = Math::Float3(1); + m->Instanced = true; m->info = (Model::ModelInfo*)Core::loader.LoadResource((Core::modelPath + filename).c_str(),Oyster::Graphics::Loading::LoadDAN, Oyster::Graphics::Loading::UnloadDAN); Model::ModelInfo* mi = (Model::ModelInfo*)m->info; @@ -152,6 +185,18 @@ namespace Oyster delete mi; return NULL; } + + if(!m->info->Animated) + { + if(Core::loader.GetResourceCount(m->info) == 1) + { + Render::Resources::RenderData[m->info] = new Render::Resources::ModelDataWrapper(); + } + else + { + Render::Resources::RenderData[m->info]->Models++; + } + } return m; } @@ -187,6 +232,12 @@ namespace Oyster SAFE_RELEASE(Core::deviceContext); SAFE_RELEASE(Core::device); + for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) + { + SAFE_DELETE((*i).second->rid); + SAFE_DELETE((*i).second); + } + } void API::AddLight(Definitions::Pointlight light) @@ -208,9 +259,9 @@ namespace Oyster void API::StartRenderWireFrame() { - Core::deviceContext->OMSetRenderTargets((UINT)Render::Resources::Gather::Pass.RTV.size(),&Render::Resources::Gather::Pass.RTV[0],NULL); + //Core::deviceContext->OMSetRenderTargets((UINT)Render::Resources::Gather::AnimatedPass.RTV.size(),&Render::Resources::Gather::AnimatedPass.RTV[0],NULL); Core::deviceContext->RSSetState(wire); - Core::deviceContext->OMSetRenderTargets((UINT)Render::Resources::Gather::Pass.RTV.size(),&Render::Resources::Gather::Pass.RTV[0],NULL); + //Core::deviceContext->OMSetRenderTargets((UINT)Render::Resources::Gather::AnimatedPass.RTV.size(),&Render::Resources::Gather::AnimatedPass.RTV[0],NULL); } void API::RenderDebugCube(Math::Matrix world) diff --git a/Code/OysterGraphics/DllInterfaces/GFXAPI.h b/Code/OysterGraphics/DllInterfaces/GFXAPI.h index 795f649a..7f338cce 100644 --- a/Code/OysterGraphics/DllInterfaces/GFXAPI.h +++ b/Code/OysterGraphics/DllInterfaces/GFXAPI.h @@ -42,6 +42,10 @@ namespace Oyster static State Init(HWND Window, bool MSAA_Quality, bool Fullscreen, Option options); + static void BeginLoadingModels(); + + static void EndLoadingModels(); + static State ReloadShaders(); //should be called after rendered normal models, before GUI or Text rendering diff --git a/Code/OysterGraphics/Model/Model.h b/Code/OysterGraphics/Model/Model.h index 5985dbcd..6d4e96f2 100644 --- a/Code/OysterGraphics/Model/Model.h +++ b/Code/OysterGraphics/Model/Model.h @@ -26,6 +26,7 @@ namespace Oyster Oyster::Math::Float3 Tint; Oyster::Math::Float3 GlowTint; bool Visible; + bool Instanced; AnimationData Animation; }; } diff --git a/Code/OysterGraphics/OysterGraphics.vcxproj b/Code/OysterGraphics/OysterGraphics.vcxproj index 8faf4d0f..f4a3d130 100644 --- a/Code/OysterGraphics/OysterGraphics.vcxproj +++ b/Code/OysterGraphics/OysterGraphics.vcxproj @@ -239,13 +239,25 @@ Vertex Vertex + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + Compute Compute Compute Compute - + Pixel Pixel Pixel @@ -281,7 +293,7 @@ Compute 5.0 - + Vertex Vertex Vertex @@ -328,8 +340,9 @@ + - + diff --git a/Code/OysterGraphics/OysterGraphics.vcxproj.filters b/Code/OysterGraphics/OysterGraphics.vcxproj.filters index d76a066f..83731090 100644 --- a/Code/OysterGraphics/OysterGraphics.vcxproj.filters +++ b/Code/OysterGraphics/OysterGraphics.vcxproj.filters @@ -100,8 +100,6 @@ - - @@ -109,6 +107,10 @@ + + + + @@ -117,8 +119,9 @@ - + + \ No newline at end of file diff --git a/Code/OysterGraphics/Render/DefaultRenderer.cpp b/Code/OysterGraphics/Render/DefaultRenderer.cpp index 7d0d987b..4b979be8 100644 --- a/Code/OysterGraphics/Render/DefaultRenderer.cpp +++ b/Code/OysterGraphics/Render/DefaultRenderer.cpp @@ -19,7 +19,6 @@ namespace Oyster Preparations::Basic::ClearBackBuffer(Oyster::Math::Float4(0,0,0,0)); Preparations::Basic::ClearDepthStencil(Resources::Gui::depth); Preparations::Basic::ClearRTV(Resources::GBufferRTV,Resources::GBufferSize,Math::Float4(0,0,0,0)); - Core::PipelineManager::SetRenderPass(Graphics::Render::Resources::Gather::Pass); Lights[1]; void* data; @@ -39,15 +38,39 @@ namespace Oyster data = Resources::Light::PointLightsData.Map(); memcpy(data, Lights, sizeof(Definitions::Pointlight) * numLights); Resources::Light::PointLightsData.Unmap(); + + for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) + { + (*i).second->Models=0; + } + + Core::PipelineManager::SetRenderPass(Resources::Gather::AnimatedPass); } void DefaultRenderer::RenderScene(Model::Model* models, int count, Math::Matrix View, Math::Matrix Projection, float deltaTime) { for(int i = 0; i < count; ++i) { - if(&models[i] == NULL) + if(&models[i] == NULL || !models[i].Visible) continue; - if(models[i].Visible) + + Model::ModelInfo* info = models[i].info; + if(!info->Animated && models[i].Instanced) + { + Definitions::RenderInstanceData rid; + Math::Float3x3 normalTransform; + normalTransform = Math::Float3x3(models[i].WorldMatrix.v[0].xyz, models[i].WorldMatrix.v[1].xyz, models[i].WorldMatrix.v[2].xyz); + normalTransform.Transpose().Invert(); + Math::Matrix m = Math::Matrix(Math::Vector4(normalTransform.v[0],0.0f), Math::Vector4(normalTransform.v[1],0.0f), Math::Vector4(normalTransform.v[2],0.0f), Math::Vector4(0.0f)); + rid.WV = View * m; + rid.WVP = Projection * View * models[i].WorldMatrix; + + rid.Tint = models[i].Tint; + rid.GTint = models[i].GlowTint; + + Resources::RenderData[info]->rid[Resources::RenderData[info]->Models++] = rid; + } + else { Definitions::PerModel pm; Math::Float3x3 normalTransform; @@ -55,7 +78,6 @@ namespace Oyster normalTransform.Transpose().Invert(); Math::Matrix m = Math::Matrix(Math::Vector4(normalTransform.v[0],0.0f), Math::Vector4(normalTransform.v[1],0.0f), Math::Vector4(normalTransform.v[2],0.0f), Math::Vector4(0.0f)); pm.WV = View * m; - //pm.WV = models[i].WorldMatrix.GetTranspose().GetInverse(); pm.WVP = Projection * View * models[i].WorldMatrix; Model::ModelInfo* info = models[i].info; @@ -207,9 +229,47 @@ namespace Oyster Core::deviceContext->Dispatch((UINT)(Core::resolution.x/2), (UINT)((Core::resolution.y/2 + 127U) / 128U), 1); } + void RenderModel(Model::ModelInfo* info, Definitions::RenderInstanceData* rid , int count) + { + if(count < 1) + return; + if(info->Material.size()) + { + Core::deviceContext->PSSetShaderResources(0,(UINT)info->Material.size(),&(info->Material[0])); + } + info->Vertices->Apply(); + if(info->Indexed) + { + info->Indecies->Apply(); + } + + void* data = Resources::Gather::InstancedData.Map(); + memcpy(data, rid, sizeof(Definitions::RenderInstanceData)*count); + Resources::Gather::InstancedData.Unmap(); + + if(info->Indexed) + { + Core::deviceContext->DrawIndexedInstanced(info->IndexCount,count,0,0,0); + //Core::deviceContext->DrawIndexed(info->IndexCount,0,0); + } + else + { + Core::deviceContext->DrawInstanced(info->VertexCount,count,0,0); + //Core::deviceContext->Draw(info->VertexCount,0); + } + } + void DefaultRenderer::EndFrame() { + Core::PipelineManager::SetRenderPass(Graphics::Render::Resources::Gather::InstancedPass); + Resources::Gather::InstancedData.Apply(1); + + for(auto i = Render::Resources::RenderData.begin(); i != Render::Resources::RenderData.end(); i++ ) + { + RenderModel((*i).first,(*i).second->rid, (*i).second->Models); + } + Core::PipelineManager::SetRenderPass(Resources::Light::Pass); Core::deviceContext->Dispatch((UINT)((Core::resolution.x + 15U) / 16U), (UINT)((Core::resolution.y + 15U) / 16U), 1); diff --git a/Code/OysterGraphics/Render/Resources.cpp b/Code/OysterGraphics/Render/Resources.cpp index 2e693472..cced13e9 100644 --- a/Code/OysterGraphics/Render/Resources.cpp +++ b/Code/OysterGraphics/Render/Resources.cpp @@ -33,7 +33,8 @@ namespace Oyster ID3D11UnorderedAccessView* Resources::Blur::BufferUAV = {0}; ID3D11ShaderResourceView* Resources::Blur::BufferSRV = {0}; - Shader::RenderPass Resources::Gather::Pass; + Shader::RenderPass Resources::Gather::AnimatedPass; + Shader::RenderPass Resources::Gather::InstancedPass; Shader::RenderPass Resources::Light::Pass; Shader::RenderPass Resources::Post::Pass; Shader::RenderPass Resources::Gui::Pass; @@ -43,6 +44,7 @@ namespace Oyster Buffer Resources::Gather::ModelData = Buffer(); Buffer Resources::Gather::AnimationData = Buffer(); + Buffer Resources::Gather::InstancedData = Buffer(); Buffer Resources::Light::LightConstantsData = Buffer(); Buffer Resources::Gui::Data = Buffer(); Buffer Resources::Color = Buffer(); @@ -63,6 +65,8 @@ namespace Oyster ID3D11ShaderResourceView* Resources::Gui::Text::Font = NULL; ID3D11DepthStencilView* Resources::Gui::depth = NULL; + + std::map Resources::RenderData = std::map(); #pragma endregion @@ -76,8 +80,12 @@ namespace Oyster std::wstring end = L".cso"; #endif //Load Shaders - Core::PipelineManager::Init(path + L"GatherPixel" + end, ShaderType::Pixel, L"Gather"); - Core::PipelineManager::Init(path + L"GatherVertex" + end, ShaderType::Vertex, L"Gather"); + Core::PipelineManager::Init(path + L"GatherAnimPixel" + end, ShaderType::Pixel, L"AGather"); + Core::PipelineManager::Init(path + L"GatherAnimVertex" + end, ShaderType::Vertex, L"AGather"); + + + Core::PipelineManager::Init(path + L"GatherInstPixel" + end, ShaderType::Pixel, L"IGather"); + Core::PipelineManager::Init(path + L"GatherInstVertex" + end, ShaderType::Vertex, L"IGather"); #ifdef _DEBUG path = PathToHLSL+L"Light\\"; #endif @@ -151,6 +159,7 @@ namespace Oyster desc.NumElements = MAX_LETTER_COUNT; Gui::Text::Vertex.Init(desc); + return Core::Init::Success; } @@ -356,10 +365,11 @@ namespace Oyster { ////---------------- Geometry Pass Setup ---------------------------- - Gather::Pass.Shaders.Pixel = GetShader::Pixel(L"Gather"); - Gather::Pass.Shaders.Vertex = GetShader::Vertex(L"Gather"); +#pragma region Animated Pass + Gather::AnimatedPass.Shaders.Pixel = GetShader::Pixel(L"AGather"); + Gather::AnimatedPass.Shaders.Vertex = GetShader::Vertex(L"AGather"); - D3D11_INPUT_ELEMENT_DESC indesc[] = + D3D11_INPUT_ELEMENT_DESC AnimInDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, @@ -368,20 +378,163 @@ namespace Oyster { "BONEWEIGHT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; - Shader::CreateInputLayout(indesc,5,GetShader::Vertex(L"Gather"),Gather::Pass.IAStage.Layout); - Gather::Pass.IAStage.Topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - Gather::Pass.CBuffers.Vertex.push_back(Gather::AnimationData); - Gather::Pass.CBuffers.Vertex.push_back(Gather::ModelData); - Gather::Pass.CBuffers.Pixel.push_back(Color); - Gather::Pass.RenderStates.Rasterizer = RenderStates::rs; - Gather::Pass.RenderStates.SampleCount = 1; - Gather::Pass.RenderStates.SampleState = RenderStates::ss; - Gather::Pass.RenderStates.DepthStencil = RenderStates::dsState; + Shader::CreateInputLayout(AnimInDesc,5,GetShader::Vertex(L"AGather"),Gather::AnimatedPass.IAStage.Layout); + Gather::AnimatedPass.IAStage.Topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + Gather::AnimatedPass.CBuffers.Vertex.push_back(Gather::AnimationData); + Gather::AnimatedPass.CBuffers.Vertex.push_back(Gather::ModelData); + Gather::AnimatedPass.CBuffers.Pixel.push_back(Color); + Gather::AnimatedPass.RenderStates.Rasterizer = RenderStates::rs; + Gather::AnimatedPass.RenderStates.SampleCount = 1; + Gather::AnimatedPass.RenderStates.SampleState = RenderStates::ss; + Gather::AnimatedPass.RenderStates.DepthStencil = RenderStates::dsState; for(int i = 0; i RenderData; static const int GBufferSize = 3; static const int LBufferSize = 3; @@ -44,9 +54,11 @@ namespace Oyster struct Gather { - static Core::PipelineManager::RenderPass Pass; + static Core::PipelineManager::RenderPass AnimatedPass; + static Core::PipelineManager::RenderPass InstancedPass; static Core::Buffer ModelData; static Core::Buffer AnimationData; + static Core::Buffer InstancedData; }; struct Light diff --git a/Code/OysterGraphics/Shader/Passes/Gather/Header.hlsli b/Code/OysterGraphics/Shader/Passes/Gather/AnimHeader.hlsli similarity index 97% rename from Code/OysterGraphics/Shader/Passes/Gather/Header.hlsli rename to Code/OysterGraphics/Shader/Passes/Gather/AnimHeader.hlsli index 75a297bb..6f69bfca 100644 --- a/Code/OysterGraphics/Shader/Passes/Gather/Header.hlsli +++ b/Code/OysterGraphics/Shader/Passes/Gather/AnimHeader.hlsli @@ -1,4 +1,4 @@ -struct VertexIn +struct AnimVertexIn { float3 pos : POSITION; float2 UV : TEXCOORD; diff --git a/Code/OysterGraphics/Shader/Passes/Gather/GatherPixel.hlsl b/Code/OysterGraphics/Shader/Passes/Gather/GatherAnimPixel.hlsl similarity index 95% rename from Code/OysterGraphics/Shader/Passes/Gather/GatherPixel.hlsl rename to Code/OysterGraphics/Shader/Passes/Gather/GatherAnimPixel.hlsl index 11447238..dede36c2 100644 --- a/Code/OysterGraphics/Shader/Passes/Gather/GatherPixel.hlsl +++ b/Code/OysterGraphics/Shader/Passes/Gather/GatherAnimPixel.hlsl @@ -1,4 +1,4 @@ -#include "Header.hlsli" +#include "AnimHeader.hlsli" @@ -42,7 +42,7 @@ PixelOut main(VertexOut input) PixelOut output; float4 DiffGlow = Diffuse.Sample(S1, input.UV); float3 tint = Color*(1-DiffGlow.w) + GlowColor * DiffGlow.w; - tint = Color*(1-DiffGlow.w) + GlowColor * DiffGlow.w; + //tint = Color*(1-DiffGlow.w) + GlowColor * DiffGlow.w; output.DiffuseGlow = DiffGlow * float4(tint,1); //NORMALIZE diff --git a/Code/OysterGraphics/Shader/Passes/Gather/GatherVertex.hlsl b/Code/OysterGraphics/Shader/Passes/Gather/GatherAnimVertex.hlsl similarity index 90% rename from Code/OysterGraphics/Shader/Passes/Gather/GatherVertex.hlsl rename to Code/OysterGraphics/Shader/Passes/Gather/GatherAnimVertex.hlsl index 79c21eec..7e7a803f 100644 --- a/Code/OysterGraphics/Shader/Passes/Gather/GatherVertex.hlsl +++ b/Code/OysterGraphics/Shader/Passes/Gather/GatherAnimVertex.hlsl @@ -1,6 +1,6 @@ -#include "Header.hlsli" +#include "AnimHeader.hlsli" -VertexOut main( VertexIn input ) +VertexOut main( AnimVertexIn input ) { VertexOut output; diff --git a/Code/OysterGraphics/Shader/Passes/Gather/GatherInstPixel.hlsl b/Code/OysterGraphics/Shader/Passes/Gather/GatherInstPixel.hlsl new file mode 100644 index 00000000..72fce8c5 --- /dev/null +++ b/Code/OysterGraphics/Shader/Passes/Gather/GatherInstPixel.hlsl @@ -0,0 +1,63 @@ +#include "InstHeader.hlsli" + + + +float3x3 cotangent_frame( float3 N, float3 p, float2 uv ) +{ + // get edge vectors of the pixel triangle + float3 dp1 = ddx( p ); + float3 dp2 = ddy( p ); + float2 duv1 = ddx( uv ); + float2 duv2 = ddy( uv ); + + // solve the linear system + float3 dp2perp = cross( dp2, N ); + float3 dp1perp = cross( N, dp1 ); + float3 T = dp2perp * duv1.x + dp1perp * duv2.x; + float3 B = dp2perp * duv1.y + dp1perp * duv2.y; + + // construct a scale-invariant frame + float invmax = rsqrt( max( dot(T,T), dot(B,B) ) ); + return transpose(float3x3( T * invmax, B * invmax, N )); +} + +float3 perturb_normal( float3 N, float3 V, float2 texcoord ) +{ + // assume N, the interpolated vertex normal and + // V, the view vector (vertex to eye) + float3 map = Normal.Sample(S1,texcoord).xyz; + map = map * 255./127. - 128./127.; +#ifdef WITH_NORMALMAP_2CHANNEL + map.z = sqrt( 1. - dot( map.xy, map.xy ) ); +#endif +#ifdef WITH_NORMALMAP_GREEN_UP + map.y = -map.y; +#endif + float3x3 TBN = cotangent_frame( N, -V, texcoord ); + return normalize( mul(transpose(TBN), map) ); +} + +PixelOut main(VertexOut input) +{ + PixelOut output; + float4 DiffGlow = Diffuse.Sample(S1, input.UV); + float3 tint = input.tint * (1-DiffGlow.w) + input.gtint * DiffGlow.w; + //tint = Color*(1-DiffGlow.w) + GlowColor * DiffGlow.w; + output.DiffuseGlow = DiffGlow * float4(tint,1); + + //NORMALIZE + float3x3 CoTangentFrame = cotangent_frame(input.normal, normalize(input.ViewPos), input.UV); + + float3 map = Normal.Sample(S1,input.UV).xyz; + //map = normalize((map * 2) -1); + map = map * 255./127. - 128./127.; + //map = map * 255; + float3 normal = normalize(mul(CoTangentFrame, map)); + //normal = perturb_normal( normal, normalize(-input.ViewPos), input.UV ); + + output.NormalSpec = float4(normal, Normal.Sample(S1, input.UV).w*255); + + //output.NormalSpec = float4(input.normal, Normal.Sample(S1, input.UV).w * 0); + //output.NormalSpec = float4(map,0); + return output; +} \ No newline at end of file diff --git a/Code/OysterGraphics/Shader/Passes/Gather/GatherInstVertex.hlsl b/Code/OysterGraphics/Shader/Passes/Gather/GatherInstVertex.hlsl new file mode 100644 index 00000000..525ff982 --- /dev/null +++ b/Code/OysterGraphics/Shader/Passes/Gather/GatherInstVertex.hlsl @@ -0,0 +1,18 @@ +#include "InstHeader.hlsli" + +VertexOut main( InstVertexIn input ) +{ + VertexOut output; + + matrix WV = transpose(matrix(input.wv1, input.wv2, input.wv3, input.wv4)); + matrix WVP = transpose(matrix(input.wvp1, input.wvp2, input.wvp3, input.wvp4)); + + output.pos = mul(WVP, float4(input.pos,1)); + output.ViewPos = mul(WV, float4(input.pos,1)); + output.normal = mul(WV, float4(input.normal,0)).xyz; + output.UV = input.UV; + output.tint = input.Tint; + output.gtint = input.GlowTint; + + return output; +} \ No newline at end of file diff --git a/Code/OysterGraphics/Shader/Passes/Gather/InstHeader.hlsli b/Code/OysterGraphics/Shader/Passes/Gather/InstHeader.hlsli new file mode 100644 index 00000000..497374b4 --- /dev/null +++ b/Code/OysterGraphics/Shader/Passes/Gather/InstHeader.hlsli @@ -0,0 +1,44 @@ +struct InstVertexIn +{ + float3 pos : POSITION; + float2 UV : TEXCOORD; + float3 normal : NORMAL; + float4 boneIndex : BONEINDEX; + float4 boneWeight : BONEWEIGHT; + //instance Data + //WV MATRIX + float4 wv1 : WV0; + float4 wv2 : WV1; + float4 wv3 : WV2; + float4 wv4 : WV3; + + //WVP MATRIX + float4 wvp1 : WVP0; + float4 wvp2 : WVP1; + float4 wvp3 : WVP2; + float4 wvp4 : WVP3; + + float3 Tint : TINT; + float3 GlowTint : GTINT; +}; + +struct VertexOut +{ + float4 pos : SV_POSITION; + float4 ViewPos : POSITION; + float2 UV : TEXCOORD; + float3 normal : NORMAL; + float3 tint : TINT; + float3 gtint : GTINT; +}; + +struct PixelOut +{ + float4 DiffuseGlow : SV_TARGET0; + float4 NormalSpec : SV_TARGET1; +}; + +Texture2D Diffuse : register(t0); +Texture2D Normal : register(t1); + +SamplerState S1 : register(s0); \ No newline at end of file diff --git a/Code/OysterGraphics/Shader/Passes/Light/Defines.hlsli b/Code/OysterGraphics/Shader/Passes/Light/Defines.hlsli index adf01e9d..fb125b12 100644 --- a/Code/OysterGraphics/Shader/Passes/Light/Defines.hlsli +++ b/Code/OysterGraphics/Shader/Passes/Light/Defines.hlsli @@ -25,6 +25,16 @@ cbuffer LightConstants : register(b0) float4x4 View; } +struct FrustrumPoints +{ + float3 v0; + float3 v1; + float3 v2; + float3 v3; + float3 v4; + float3 v5; +}; + Texture2D DiffuseGlow : register(t0); Texture2D NormalSpec : register(t1); Texture2D GUI : register(t2); diff --git a/Code/OysterGraphics/Shader/Passes/Light/LightCalc.hlsli b/Code/OysterGraphics/Shader/Passes/Light/LightCalc.hlsli index 3dc2b45e..81fa2fa1 100644 --- a/Code/OysterGraphics/Shader/Passes/Light/LightCalc.hlsli +++ b/Code/OysterGraphics/Shader/Passes/Light/LightCalc.hlsli @@ -27,4 +27,9 @@ DiffSpec LightCalc(PointLight pl, float3 pos, int2 texCoord) float SpecCo = normalSpec.w < 1 ? 0.0f : 1.0f; output.Specular = output.Specular * SpecCo; return output; +} + +bool intersects(FrustrumPoints box, int Index) +{ + return true; } \ No newline at end of file diff --git a/Code/OysterGraphics/Shader/Passes/Light/LightPass.hlsl b/Code/OysterGraphics/Shader/Passes/Light/LightPass.hlsl index 89ed06d3..ddaed99e 100644 --- a/Code/OysterGraphics/Shader/Passes/Light/LightPass.hlsl +++ b/Code/OysterGraphics/Shader/Passes/Light/LightPass.hlsl @@ -8,13 +8,85 @@ //Calc Ambience Done //Write Glow +#define EXPAND 1024.0f +#define SHRINK 1.0f/EXPAND +#define UINT_MAX 0xFFFFFFFF +#define FLOAT_MAX 3.402823466e+38 +#define BLOCKSIZE 16 +#define NUMTHREADS BLOCKSIZE * BLOCKSIZE +#define MAXLIGHTS 100 -[numthreads(16, 16, 1)] -void main( uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID ) + +// -- Shared Memory ------------------------------------------------- // + +groupshared uint iMinDepth = UINT_MAX, + iMaxDepth = 0; +groupshared uint numVisiblePointLights = 0, + visiblePointlightIndex[MAXLIGHTS]; + +// ------------------------------------------------------------------ // + +[numthreads(BLOCKSIZE, BLOCKSIZE, 1)] +void main( uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex ) { float2 UV = DTid.xy / Pixels; UV.x = UV.x * 2 - 1; UV.y = 1 - 2 * UV.y; + + float3 posN = float3(UV, DepthTexture[DTid.xy].x); + + // store and load shared minDepth and maxDepth + float minDepth = 0.0f, maxDepth = 0.0f, + depth = posN.z; + { + uint uidepth = (uint)( depth * EXPAND); + InterlockedMin( iMinDepth, uidepth ); + InterlockedMax( iMaxDepth, uidepth ); + + GroupMemoryBarrierWithGroupSync(); + minDepth = (float)( iMinDepth ) * SHRINK; + maxDepth = (float)( iMaxDepth ) * SHRINK; + } + + + // -- Switching to LightCulling ------------------------------------- // + + //define collision volume + float2 size = BLOCKSIZE / Pixels; + FrustrumPoints tile; + tile.v0 = float3(size * Gid,minDepth); + tile.v1 = float3(tile.v0.xy+size,maxDepth); + tile.v2 = float3(tile.v1.xy, minDepth); + tile.v3 = float3(tile.v0.x,tile.v1.y,minDepth); + tile.v4 = float3(tile.v1.x, tile.v0.y, minDepth); + tile.v5 = float3(tile.v0.xy, maxDepth); + + + + // culling the tile's near and far to minDepth & maxDepth ( with tolerance ) + + + uint numPass = (Lights + NUMTHREADS - 1) / NUMTHREADS; + numPass = min( numPass, MAXLIGHTS / NUMTHREADS ); + + for( uint passI = 0; passI < numPass; ++passI ) + { + uint lightIndex = (passI * NUMTHREADS) + GI; + lightIndex = min( lightIndex, Lights ); + + if( lightIndex < Lights ) + if( intersects(tile, lightIndex) ) + { + uint offset; + InterlockedAdd( numVisiblePointLights, 1, offset ); + visiblePointlightIndex[offset] = lightIndex; + } + } + + GroupMemoryBarrierWithGroupSync(); + + + float3 ViewPos = ToVpos(DTid.xy, UV); DiffSpec Shaded; Shaded.Diffuse = float3(0,0,0); @@ -47,7 +119,7 @@ void main( uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID ) DepthBase = DepthBase /4; Ambient[DTid.xy/2] = float4(DiffBase.xyz, AmbValue); Ambient[DTid.xy/2 + float2(Pixels.x/2, 0)] = GUI[DTid.xy]; - Ambient[DTid.xy/2 + float2(0, Pixels.y/2)] = float4(DiffBase.xyz * DiffBase.w /* * (2-DepthBase) */,DiffBase.w); + Ambient[DTid.xy/2 + float2(0, Pixels.y/2)] = float4(DiffBase.xyz * DiffBase.w ,DiffBase.w); Ambient[DTid.xy/2 + Pixels/2] = float4(NormalSpec[DTid.xy].xyz * float3(1,1,-1),1); } diff --git a/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index df66bc12..b86f3821 100644 --- a/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -287,10 +287,11 @@ void API_Impl::UpdateWorld() if(simpleBody->GetRigidBody()->getActivationState() == ACTIVE_TAG) { this->customBodies[i]->CallSubscription_Move(); - } + } + simpleBody->SetPreviousVelocity(simpleBody->GetLinearVelocity()); } - this->dynamicsWorld->stepSimulation(this->timeStep, 1, this->timeStep); + this->dynamicsWorld->stepSimulation(this->timeStep, 10, this->timeStep); ICustomBody::State state; @@ -312,9 +313,34 @@ void API_Impl::UpdateWorld() ICustomBody* bodyA = (ICustomBody*)obA->getUserPointer(); ICustomBody* bodyB = (ICustomBody*)obB->getUserPointer(); + + - bodyA->CallSubscription_AfterCollisionResponse(bodyA, bodyB, 0.0f); - bodyB->CallSubscription_AfterCollisionResponse(bodyB, bodyA, 0.0f); + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + if (pt.getDistance()<0.f) + { + if(bodyA->GetState().mass == 40 && bodyB->GetState().centerPos == Float3::null) + { + const char* breakPoint = "STOP"; + } + if(bodyB->GetState().mass == 40 && bodyA->GetState().centerPos == Float3::null) + { + const char* breakPoint = "STOP"; + } + + const btVector3& ptA = pt.getPositionWorldOnA(); + const btVector3& ptB = pt.getPositionWorldOnB(); + const btVector3& normalOnB = pt.m_normalWorldOnB; + + bodyA->CallSubscription_AfterCollisionResponse(bodyA, bodyB, 0.0f); + bodyB->CallSubscription_AfterCollisionResponse(bodyB, bodyA, 0.0f); + } + } + + } } diff --git a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp index e2d87ce7..25c57e3b 100644 --- a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -22,6 +22,8 @@ SimpleRigidBody::SimpleRigidBody() this->state.restitutionCoeff = 0.0f; this->state.reach = Float3(0.0f, 0.0f, 0.0f); + this->collisionFlags = 0; + this->afterCollision = NULL; this->onMovement = NULL; @@ -85,7 +87,7 @@ void SimpleRigidBody::SetMotionState(btDefaultMotionState* motionState) void SimpleRigidBody::SetRigidBody(btRigidBody* rigidBody) { this->rigidBody = rigidBody; - + this->collisionFlags = rigidBody->getCollisionFlags(); } void SimpleRigidBody::SetSubscription(EventAction_AfterCollisionResponse function) @@ -421,5 +423,10 @@ void SimpleRigidBody::MoveToLimbo() void SimpleRigidBody::ReleaseFromLimbo() { - this->rigidBody->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT); + this->rigidBody->setCollisionFlags(this->collisionFlags); +} + +void SimpleRigidBody::SetPreviousVelocity(::Oyster::Math::Float3 velocity) +{ + this->state.previousVelocity = velocity; } \ No newline at end of file diff --git a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h index 4290b540..f3e7e0c6 100644 --- a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h @@ -64,6 +64,7 @@ namespace Oyster void SetCollisionShape(btCollisionShape* shape); void SetMotionState(btDefaultMotionState* motionState); void SetRigidBody(btRigidBody* rigidBody); + void SetPreviousVelocity(Math::Float3 velocity); void PreStep(const btCollisionWorld* collisionWorld); @@ -72,6 +73,8 @@ namespace Oyster void MoveToLimbo(); void ReleaseFromLimbo(); + + private: btCollisionShape* collisionShape; @@ -90,6 +93,8 @@ namespace Oyster btVector3 raySource[2]; btVector3 rayTarget[2]; btScalar rayLambda[2]; + + int collisionFlags; }; } } diff --git a/Code/Physics/GamePhysics/PhysicsStructs-Impl.h b/Code/Physics/GamePhysics/PhysicsStructs-Impl.h index 87cfcb17..56d5c4e8 100644 --- a/Code/Physics/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/Physics/GamePhysics/PhysicsStructs-Impl.h @@ -10,7 +10,7 @@ namespace Oyster { namespace Struct { - inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float3 reach, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float dynamicFrictionCoeff, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Quaternion& quaternion) + inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float3 reach, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float dynamicFrictionCoeff, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Quaternion& quaternion, ::Oyster::Math::Float3 previousVelocity) { this->mass = mass; this->reach = reach; @@ -19,6 +19,7 @@ namespace Oyster this->dynamicFrictionCoeff = dynamicFrictionCoeff; this->centerPos = centerPos; this->quaternion = quaternion; + this->previousVelocity = ::Oyster::Math::Float3::null; } inline CustomBodyState & CustomBodyState::operator = ( const CustomBodyState &state ) @@ -30,6 +31,7 @@ namespace Oyster this->dynamicFrictionCoeff = state.dynamicFrictionCoeff; this->centerPos = state.centerPos; this->quaternion = state.quaternion; + this->previousVelocity = state.previousVelocity; return *this; } diff --git a/Code/Physics/GamePhysics/PhysicsStructs.h b/Code/Physics/GamePhysics/PhysicsStructs.h index 2f369b90..2ee7a59e 100644 --- a/Code/Physics/GamePhysics/PhysicsStructs.h +++ b/Code/Physics/GamePhysics/PhysicsStructs.h @@ -16,12 +16,13 @@ namespace Oyster public: // Default constructor CustomBodyState( ::Oyster::Math::Float mass = 1.0f, - ::Oyster::Math::Float3 reach = ::Oyster::Math::Float3(0,0,0), + ::Oyster::Math::Float3 reach = ::Oyster::Math::Float3::null, ::Oyster::Math::Float restitutionCoeff = 0.5f, ::Oyster::Math::Float staticFrictionCoeff = 1.0f, ::Oyster::Math::Float dynamicFrictionCoeff = 1.0f, const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null, - const ::Oyster::Math::Quaternion &quaternion = ::Oyster::Math::Quaternion(::Oyster::Math::Float3(0, 0, 0), 1)); + const ::Oyster::Math::Quaternion &quaternion = ::Oyster::Math::Quaternion(::Oyster::Math::Float3(0, 0, 0), 1), + ::Oyster::Math::Float3 previousVelocity = ::Oyster::Math::Float3::null); // Assignment operator CustomBodyState & operator = ( const CustomBodyState &state ); @@ -34,7 +35,7 @@ namespace Oyster // Variables for state ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, dynamicFrictionCoeff; - ::Oyster::Math::Float3 reach, centerPos; + ::Oyster::Math::Float3 reach, centerPos, previousVelocity; ::Oyster::Math::Quaternion quaternion; }; }