From 0a04c1c9f10148d1c7186e82801df0199b5eaf8b Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Thu, 30 Jan 2014 14:52:40 +0100 Subject: [PATCH 01/18] Added document --- ...erp rotation axis towards new up normal.odt | Bin 0 -> 134706 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Code/Dokumentation/Other/Slerp rotation axis towards new up normal.odt diff --git a/Code/Dokumentation/Other/Slerp rotation axis towards new up normal.odt b/Code/Dokumentation/Other/Slerp rotation axis towards new up normal.odt new file mode 100644 index 0000000000000000000000000000000000000000..6ed3d36f51b494b356eb5568f89382f220f29af9 GIT binary patch literal 134706 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 z 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 b^1e92x&7I#9-JQB15*g3G#YwN3iAI07eDVX literal 0 HcmV?d00001 From e718048f7f7bc871ead0329c7f3b1bae81f21d7d Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 10:49:52 +0100 Subject: [PATCH 02/18] GL - Lan State --- Code/Game/DanBiasGame/DanBiasGame_Impl.cpp | 16 +++--- .../Game/DanBiasGame/GameClientRecieverFunc.h | 2 + .../GameClientState/GameClientState.h | 1 + .../GameClientState/LanMenuState.cpp | 51 +++++++++++++++++++ .../GameClientState/LanMenuState.h | 2 + .../GameClientState/LoginState.cpp | 5 ++ 6 files changed, 68 insertions(+), 9 deletions(-) diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index 3a62ade1..b28a543f 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -38,7 +38,7 @@ namespace DanBias public: WindowShell* window; InputClass* inputObj; - Utility::WinTimer* timer; + Utility::WinTimer timer; GameRecieverObject* recieverObj; bool serverOwner; @@ -68,12 +68,11 @@ namespace DanBias m_data->serverOwner = false; // Start in lobby state - m_data->recieverObj->gameClientState = new Client::LoginState(); + m_data->recieverObj->gameClientState = new Client::LanMenuState(); if(!m_data->recieverObj->gameClientState->Init(m_data->recieverObj)) return DanBiasClientReturn_Error; - m_data->timer = new Utility::WinTimer(); //why dynamic memory? - m_data->timer->reset(); + m_data->timer.reset(); return DanBiasClientReturn_Sucess; } @@ -82,8 +81,8 @@ namespace DanBias // Main message loop while(m_data->window->Frame()) { - float dt = (float)m_data->timer->getElapsedSeconds(); - m_data->timer->reset(); + float dt = (float)m_data->timer.getElapsedSeconds(); + m_data->timer.reset(); capFrame += dt; if(capFrame > 0.03) @@ -130,8 +129,8 @@ namespace DanBias HRESULT DanBiasGame::Update(float deltaTime) { - - m_data->recieverObj->Update(); + if(m_data->recieverObj->IsConnected()) + m_data->recieverObj->Update(); m_data->inputObj->Update(); if(m_data->serverOwner) @@ -191,7 +190,6 @@ namespace DanBias delete m_data->recieverObj->gameClientState; m_data->recieverObj->Disconnect(); delete m_data->recieverObj; - delete m_data->timer; delete m_data->inputObj; delete m_data; diff --git a/Code/Game/DanBiasGame/GameClientRecieverFunc.h b/Code/Game/DanBiasGame/GameClientRecieverFunc.h index c5293738..2bd8c9a1 100644 --- a/Code/Game/DanBiasGame/GameClientRecieverFunc.h +++ b/Code/Game/DanBiasGame/GameClientRecieverFunc.h @@ -2,6 +2,8 @@ #define DANBIAS_CLIENTRECIEVEROBJECT_H //WTF!? No headers included??? +#include "../DanBiasGame/Include/DanBiasGame.h" +#include "../GameProtocols/GeneralProtocols.h" namespace DanBias { diff --git a/Code/Game/DanBiasGame/GameClientState/GameClientState.h b/Code/Game/DanBiasGame/GameClientState/GameClientState.h index a369233a..378eeefc 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameClientState.h +++ b/Code/Game/DanBiasGame/GameClientState/GameClientState.h @@ -53,6 +53,7 @@ public: { ClientState_Login, ClientState_Lobby, + ClientState_Lan, ClientState_LobbyCreated, ClientState_Game, ClientState_Same, diff --git a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp index fdb02fa9..8df39bfa 100644 --- a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp @@ -5,6 +5,10 @@ #include "C_obj/C_DynamicObj.h" #include "DllInterfaces/GFXAPI.h" +#include "LobbyState.h" +#include "GameState.h" +#include "../GameClientRecieverFunc.h" + #include using namespace DanBias::Client; @@ -16,6 +20,10 @@ struct LanMenuState::myData Oyster::Math3D::Float4x4 proj; C_Object* object[2]; int modelCount; + + GameRecieverObject* recieverObj; + bool serverOwner; + // UI object // game client* }privData; @@ -83,6 +91,49 @@ bool LanMenuState::InitCamera(Oyster::Math::Float3 startPos) } GameClientState::ClientState LanMenuState::Update(float deltaTime, InputClass* KeyInput) +{ + /*ChangeState(KeyInput); + + if(privData->recieverObj->IsConnected()) + privData->recieverObj->Update(); + KeyInput->Update(); + + if(privData->serverOwner) + { + DanBias::GameServerAPI::ServerUpdate(); + } + + DanBias::Client::GameClientState::ClientState state = DanBias::Client::GameClientState::ClientState_Same; + state = privData->recieverObj->gameClientState->Update(deltaTime, KeyInput); + + if(state != Client::GameClientState::ClientState_Same) + { + privData->recieverObj->gameClientState->Release(); + delete privData->recieverObj->gameClientState; + privData->recieverObj->gameClientState = NULL; + + switch (state) + { + case Client::GameClientState::ClientState_LobbyCreated: + privData->serverOwner = true; + case Client::GameClientState::ClientState_Lobby: + privData->recieverObj->gameClientState = new Client::LobbyState(); + break; + case Client::GameClientState::ClientState_Game: + privData->recieverObj->gameClientState = new Client::GameState(); + break; + default: + //return E_FAIL; + break; + } + privData->recieverObj->gameClientState->Init(privData->recieverObj); // send game client + + }*/ + + return ChangeState(KeyInput); +} + +GameClientState::ClientState LanMenuState::ChangeState(InputClass* KeyInput) { // create game if( KeyInput->IsKeyPressed(DIK_C)) diff --git a/Code/Game/DanBiasGame/GameClientState/LanMenuState.h b/Code/Game/DanBiasGame/GameClientState/LanMenuState.h index 5182c80c..6b11fd20 100644 --- a/Code/Game/DanBiasGame/GameClientState/LanMenuState.h +++ b/Code/Game/DanBiasGame/GameClientState/LanMenuState.h @@ -17,6 +17,8 @@ namespace DanBias virtual bool Init(Oyster::Network::NetworkClient* nwClient); virtual ClientState Update(float deltaTime, InputClass* KeyInput); + ClientState ChangeState(InputClass* KeyInput); + bool LoadModels(std::wstring file); bool InitCamera(Oyster::Math::Float3 startPos); diff --git a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp index cd1e4663..a5188306 100644 --- a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp @@ -88,6 +88,8 @@ GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* Key // send data to server // check data from server + + // create game if( KeyInput->IsKeyPressed(DIK_C)) { @@ -118,6 +120,9 @@ GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* Key } return ClientState_Lobby; } + + + return ClientState_Same; } bool LoginState::Render() From c7bc7281d8502094cfb6b1ded01500713d6e40ff Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Fri, 31 Jan 2014 13:41:06 +0100 Subject: [PATCH 03/18] Prefix for "sinking" objects --- .../Implementation/PhysicsAPI_Impl.cpp | 25 +++++++++++-------- Code/GamePhysics/PhysicsAPI.h | 2 +- Code/GamePhysics/PhysicsStructs.h | 4 ++- Code/OysterPhysics3D/OysterCollision3D.cpp | 4 +-- Code/OysterPhysics3D/RigidBody.cpp | 7 +++++- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 6f164810..30ced129 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -26,7 +26,7 @@ namespace ICustomBody::State protoState; proto->GetState( protoState ); ICustomBody::State deuterState; deuter->GetState( deuterState ); - Float4 protoG = protoState.GetLinearMomentum( worldPointOfContact.xyz ), + Float4 protoG = protoState.GetLinearMomentum(worldPointOfContact.xyz ), deuterG = deuterState.GetLinearMomentum( worldPointOfContact.xyz ); // calc from perspective of deuter @@ -198,24 +198,27 @@ void API_Impl::Update() proto = updateList.begin(); for( ; proto != updateList.end(); ++proto ) { - Float3 lM = state.GetLinearMomentum() + state.GetLinearImpulse(); + (*proto)->GetState( state ); + Float3 lM = state.GetLinearMomentum(); - if( lM.x < this->epsilon ) + //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); + + + if( abs(lM.x) < this->epsilon ) { - state.SetLinearMomentum( Float3(0, lM.y, lM.z) ); - state.SetLinearImpulse( Float3(0, lM.y, lM.z) ); + state.linearMomentum.x = 0; } - if( lM.y < this->epsilon ) + if( abs(lM.y) < this->epsilon ) { - state.SetLinearMomentum( Float3(lM.x, 0, lM.z) ); - state.SetLinearImpulse( Float3(lM.x, 0, lM.z) ); + state.linearMomentum.y = 0; } - if( lM.z < this->epsilon ) + if( abs(lM.z) < this->epsilon ) { - state.SetLinearMomentum( Float3(lM.x, lM.y, 0) ); - state.SetLinearImpulse( Float3(lM.x, lM.y, 0) ); + state.linearMomentum.z = 0; } + (*proto)->SetState( state ); + switch( (*proto)->Update(this->updateFrameLength) ) { case UpdateState_altered: diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 78b65f5e..080b8d30 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -34,7 +34,7 @@ namespace Oyster namespace Constant { const float gravity_constant = (const float)6.67284e-11; //!< The _big_G_! ( N(m/kg)^2 ) Used in real gravityforcefields. - const float epsilon = (const float)1.0e-7; + const float epsilon = (const float)1.0e-3; } class PHYSICS_DLL_USAGE API diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index 00c07b2d..aef157a8 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -115,11 +115,13 @@ namespace Oyster { namespace Physics bool IsDisturbed() const; bool IsForwarded() const; + ::Oyster::Math::Float3 linearMomentum; + private: ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, kineticFrictionCoeff; ::Oyster::Physics3D::MomentOfInertia inertiaTensor; ::Oyster::Math::Float3 reach, centerPos, angularAxis; - ::Oyster::Math::Float3 linearMomentum, angularMomentum; + ::Oyster::Math::Float3 angularMomentum; ::Oyster::Math::Float3 linearImpulse, angularImpulse; ::Oyster::Math::Float3 deltaPos, deltaAxis; // Forwarding data sum ::Oyster::Math::Float3 gravityNormal; diff --git a/Code/OysterPhysics3D/OysterCollision3D.cpp b/Code/OysterPhysics3D/OysterCollision3D.cpp index 169b5add..89b3af8a 100644 --- a/Code/OysterPhysics3D/OysterCollision3D.cpp +++ b/Code/OysterPhysics3D/OysterCollision3D.cpp @@ -784,8 +784,8 @@ namespace Oyster { namespace Collision3D { namespace Utility if( Intersect(box, sphere) ) { Float distance; - Ray ray( box.center, sphere.center - box.center ); - + Ray ray( box.center, (sphere.center - box.center).Normalize() ); + Intersect( sphere, ray, distance ); worldPointOfContact = ray.origin + ray.direction*distance; return true; diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index 0c60c597..f053e8dd 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -50,7 +50,12 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the linear // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G - this->centerPos += ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); + Float3 deltaPos = ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); + if( deltaPos.GetLength() < 0.001f ) + { + deltaPos = Float3::null; + } + this->centerPos += deltaPos; // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H From 190f7e28829dfd35e857eb18ae50ef31b4be12a8 Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 13:42:17 +0100 Subject: [PATCH 04/18] SnapAngularAxis introduced --- Code/OysterMath/LinearMath.h | 15 +++++++++++++++ Code/OysterMath/OysterMath.h | 1 + 2 files changed, 16 insertions(+) diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index 50bcd36b..2fa66e26 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -325,6 +325,12 @@ namespace LinearAlgebra2D namespace LinearAlgebra3D { + template + inline ::LinearAlgebra::Vector3 WorldAxisOf( const ::LinearAlgebra::Quaternion &rotation, const ::LinearAlgebra::Vector3 &localAxis ) + { + return (rotation*localAxis*rotation.GetConjugate()).imaginary; + } + // All Matrix to AngularAxis conversions here is incorrect //template //inline ::LinearAlgebra::Vector4 AngularAxis( const ::LinearAlgebra::Matrix3x3 &rotationMatrix ) @@ -741,6 +747,15 @@ namespace LinearAlgebra3D inline ::LinearAlgebra::Vector4 NormalProjection( const ::LinearAlgebra::Vector4 &vector, const ::LinearAlgebra::Vector4 &normalizedAxis ) { return normalizedAxis * ( vector.Dot(normalizedAxis) ); } + template + ::LinearAlgebra::Vector3 & SnapAngularAxis( ::LinearAlgebra::Vector4 &startAngularAxis, const ::LinearAlgebra::Vector4 &localStartNormal, const ::LinearAlgebra::Vector4 &worldEndNormal, ::LinearAlgebra::Vector3 &targetMem = ::LinearAlgebra::Vector3() ) + { + ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis), localStartNormal), (ScalarType)0 ); + targetMem = worldStartNormal.xyz.Cross(worldEndNormal.xyz); + targetMem *= (ScalarType)::std::asin( worldStartNormal.Dot(worldEndNormal) ); + return targetMem; + } + template ::LinearAlgebra::Matrix4x4 & SnapAxisYToNormal_UsingNlerp( ::LinearAlgebra::Matrix4x4 &rotation, const ::LinearAlgebra::Vector4 &normalizedAxis ) { diff --git a/Code/OysterMath/OysterMath.h b/Code/OysterMath/OysterMath.h index 5970face..7e123183 100644 --- a/Code/OysterMath/OysterMath.h +++ b/Code/OysterMath/OysterMath.h @@ -324,6 +324,7 @@ namespace Oyster { namespace Math3D //! Oyster's native math library specialized using ::LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingNonRigidNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingSlerp; + using ::LinearAlgebra3D::SnapAngularAxis; } } #endif \ No newline at end of file From ac635ccaef70d5fd1229141ca8c5a608bbfd1305 Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 13:47:40 +0100 Subject: [PATCH 05/18] SnapAngularAxis fix --- Code/OysterMath/LinearMath.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index 2fa66e26..0ec46b5c 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -748,12 +748,12 @@ namespace LinearAlgebra3D { return normalizedAxis * ( vector.Dot(normalizedAxis) ); } template - ::LinearAlgebra::Vector3 & SnapAngularAxis( ::LinearAlgebra::Vector4 &startAngularAxis, const ::LinearAlgebra::Vector4 &localStartNormal, const ::LinearAlgebra::Vector4 &worldEndNormal, ::LinearAlgebra::Vector3 &targetMem = ::LinearAlgebra::Vector3() ) + ::LinearAlgebra::Vector4 & SnapAngularAxis( ::LinearAlgebra::Vector4 &startAngularAxis, const ::LinearAlgebra::Vector4 &localStartNormal, const ::LinearAlgebra::Vector4 &worldEndNormal, ::LinearAlgebra::Vector4 &targetMem = ::LinearAlgebra::Vector4() ) { ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis), localStartNormal), (ScalarType)0 ); - targetMem = worldStartNormal.xyz.Cross(worldEndNormal.xyz); + targetMem = ::LinearAlgebra::Vector4( worldStartNormal.xyz.Cross(worldEndNormal.xyz), (ScalarType)0); targetMem *= (ScalarType)::std::asin( worldStartNormal.Dot(worldEndNormal) ); - return targetMem; + return targetMem += startAngularAxis; } template From 7a62121fa0f8ea5d0fbdf125f47276100282141c Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 13:49:09 +0100 Subject: [PATCH 06/18] SnapAngularAxis fix accidently used asin instead of acos --- Code/OysterMath/LinearMath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index 0ec46b5c..9ea4bf42 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -752,7 +752,7 @@ namespace LinearAlgebra3D { ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis), localStartNormal), (ScalarType)0 ); targetMem = ::LinearAlgebra::Vector4( worldStartNormal.xyz.Cross(worldEndNormal.xyz), (ScalarType)0); - targetMem *= (ScalarType)::std::asin( worldStartNormal.Dot(worldEndNormal) ); + targetMem *= (ScalarType)::std::acos( worldStartNormal.Dot(worldEndNormal) ); return targetMem += startAngularAxis; } From 57c230d45848c3233ffc72dd23b7bc9dd0cf0009 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Fri, 31 Jan 2014 13:56:22 +0100 Subject: [PATCH 07/18] GL - will merge with physics --- Code/Game/DanBiasGame/GameClientRecieverFunc.h | 12 ++++++++++++ Code/Game/DanBiasGame/GameClientState/LobbyState.h | 1 + Code/Game/DanBiasGame/GameClientState/LoginState.cpp | 2 +- Code/Game/GameLogic/CollisionManager.cpp | 6 ------ Code/Game/GameLogic/Level.cpp | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientRecieverFunc.h b/Code/Game/DanBiasGame/GameClientRecieverFunc.h index 36b831a0..ef65e46a 100644 --- a/Code/Game/DanBiasGame/GameClientRecieverFunc.h +++ b/Code/Game/DanBiasGame/GameClientRecieverFunc.h @@ -100,6 +100,18 @@ namespace DanBias ((Client::GameState*)gameClientState)->Protocol(&protocolData); } break; + case protocol_Lobby_Start: + { + /* + if(dynamic_cast(gameClientState)) + { + gameClientState->Release(); + delete gameClientState; + gameClientState = new Client::GameState(); + gameClientState->Init(m_data->recieverObj); + }*/ + } + break; default: break; diff --git a/Code/Game/DanBiasGame/GameClientState/LobbyState.h b/Code/Game/DanBiasGame/GameClientState/LobbyState.h index 057fc850..6a8d9772 100644 --- a/Code/Game/DanBiasGame/GameClientState/LobbyState.h +++ b/Code/Game/DanBiasGame/GameClientState/LobbyState.h @@ -36,6 +36,7 @@ public: bool Release(); void Protocol(ProtocolStruct* protocol)override; void PlayerJoinProtocol(PlayerName* name); + void GameStarted(); };};}; #endif // ! DANBIAS_CLIENT_GAMECLIENTSTATE_H diff --git a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp index cd1e4663..4d1079bc 100644 --- a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp @@ -109,7 +109,7 @@ GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* Key if( KeyInput->IsKeyPressed(DIK_J)) { // game ip - nwClient->Connect(15151, "194.47.150.56"); + nwClient->Connect(15151, "193.11.184.109"); if (!nwClient->IsConnected()) { diff --git a/Code/Game/GameLogic/CollisionManager.cpp b/Code/Game/GameLogic/CollisionManager.cpp index 196aed09..f343720e 100644 --- a/Code/Game/GameLogic/CollisionManager.cpp +++ b/Code/Game/GameLogic/CollisionManager.cpp @@ -87,12 +87,6 @@ using namespace GameLogic; Oyster::Math::Float3 pushForce = Oyster::Math::Float4(1,0,0) * (500); Oyster::Physics::ICustomBody::State state; Object *realObj = (Object*)obj->GetCustomTag(); - if(realObj->GetObjectType() == OBJECT_TYPE_BOX) - { - state = obj->GetState(); - state.SetOrientation(Oyster::Math::Float3(1,0.5,1),Oyster::Math::Float3(1,0.5,1)); - obj->SetState(state); - } if(realObj->GetObjectType() == OBJECT_TYPE_PLAYER || realObj->GetObjectType() == OBJECT_TYPE_WORLD) return; diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index e09f9bb0..e95f95c6 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -44,7 +44,7 @@ void Level::InitiateLevel(float radius) sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,320,0,0); sbDesc_TestBox.ignoreGravity = false; sbDesc_TestBox.mass = 50; - sbDesc_TestBox.size = Oyster::Math::Float4(1,1,1,0); + sbDesc_TestBox.size = Oyster::Math::Float4(4,4,4,0); ICustomBody* rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); From 16a342da49a821c1d0d4aff11a5729073abda907 Mon Sep 17 00:00:00 2001 From: Erik Persson Date: Fri, 31 Jan 2014 14:05:52 +0100 Subject: [PATCH 08/18] GL - adjusting in GL, added forcepushData struct for passing args when shooting. connect changes in network --- Code/Game/DanBiasGame/GameClientState/LobbyState.cpp | 4 ++-- Code/Game/DanBiasGame/GameClientState/LoginState.cpp | 2 +- Code/Game/GameLogic/AttatchmentMassDriver.cpp | 8 +++++--- Code/Game/GameLogic/CollisionManager.cpp | 11 ++--------- Code/Game/GameLogic/GameLogicStates.h | 7 +++++++ Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 2 +- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp index 35a5f295..c1cc4ae1 100644 --- a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp @@ -91,8 +91,8 @@ GameClientState::ClientState LobbyState::Update(float deltaTime, InputClass* Key if( KeyInput->IsKeyPressed(DIK_G)) { - if(!DanBias::GameServerAPI::GameStart()) - return GameClientState::ClientState_Same; + //if(!DanBias::GameServerAPI::GameStart()) + //return GameClientState::ClientState_Same; return ClientState_Game; } diff --git a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp index cd1e4663..4d1079bc 100644 --- a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp @@ -109,7 +109,7 @@ GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* Key if( KeyInput->IsKeyPressed(DIK_J)) { // game ip - nwClient->Connect(15151, "194.47.150.56"); + nwClient->Connect(15151, "193.11.184.109"); if (!nwClient->IsConnected()) { diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.cpp b/Code/Game/GameLogic/AttatchmentMassDriver.cpp index 7554c879..839293d9 100644 --- a/Code/Game/GameLogic/AttatchmentMassDriver.cpp +++ b/Code/Game/GameLogic/AttatchmentMassDriver.cpp @@ -1,5 +1,6 @@ #include "AttatchmentMassDriver.h" #include "PhysicsAPI.h" +#include "GameLogicStates.h" using namespace GameLogic; @@ -45,13 +46,14 @@ void AttatchmentMassDriver::UseAttatchment(const GameLogic::WEAPON_FIRE &usage, ********************************************************/ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float dt) { - //Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); + Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); - int arg = 0; + forcePushData args; + args.pushForce = pushForce; - Oyster::Physics::API::Instance().ApplyEffect(hitFrustum,&arg,ForcePushAction); + Oyster::Physics::API::Instance().ApplyEffect(hitFrustum,&args,ForcePushAction); } /******************************************************** diff --git a/Code/Game/GameLogic/CollisionManager.cpp b/Code/Game/GameLogic/CollisionManager.cpp index 27aa6db6..512be3d6 100644 --- a/Code/Game/GameLogic/CollisionManager.cpp +++ b/Code/Game/GameLogic/CollisionManager.cpp @@ -81,20 +81,13 @@ using namespace GameLogic; void AttatchmentMassDriver::ForcePushAction(Oyster::Physics::ICustomBody *obj, void *args) { - Oyster::Math::Float3 pushForce = Oyster::Math::Float4(1,0,0) * (500); Oyster::Physics::ICustomBody::State state; Object *realObj = (Object*)obj->GetCustomTag(); - if(realObj->GetObjectType() == OBJECT_TYPE_BOX) - { - state = obj->GetState(); - state.SetOrientation(Oyster::Math::Float3(1,0.5,1),Oyster::Math::Float3(1,0.5,1)); - obj->SetState(state); - } if(realObj->GetObjectType() == OBJECT_TYPE_PLAYER || realObj->GetObjectType() == OBJECT_TYPE_WORLD) return; + state = obj->GetState(); - state.ApplyLinearImpulse(pushForce); + state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce); obj->SetState(state); - //((Object*)obj->GetCustomTag())->ApplyLinearImpulse(pushForce); } \ No newline at end of file diff --git a/Code/Game/GameLogic/GameLogicStates.h b/Code/Game/GameLogic/GameLogicStates.h index 2b0d0b8b..00c2e7ff 100644 --- a/Code/Game/GameLogic/GameLogicStates.h +++ b/Code/Game/GameLogic/GameLogicStates.h @@ -1,5 +1,6 @@ #ifndef GAMELOGICSTATES_H #define GAMELOGICSTATES_H +#include "OysterMath.h" namespace GameLogic { @@ -46,6 +47,12 @@ namespace GameLogic WEAPON_STATE_RELOADING = 2, }; + struct forcePushData + { + Oyster::Math::Float3 pushForce; + }; + + }; diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 18f57212..72f9ea1f 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -9,7 +9,7 @@ Game::PlayerData::PlayerData() Oyster::Physics::API::SimpleBodyDescription sbDesc; sbDesc.centerPosition = Oyster::Math::Float3(0,320,0); sbDesc.size = Oyster::Math::Float3(4,7,4); - sbDesc.mass = 10; + sbDesc.mass = 90; //create rigid body Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index c0b0685b..78633444 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -44,7 +44,7 @@ void Level::InitiateLevel(float radius) sbDesc_TestBox.centerPosition = Oyster::Math::Float4(4,320,0,0); sbDesc_TestBox.ignoreGravity = false; sbDesc_TestBox.mass = 10; - sbDesc_TestBox.size = Oyster::Math::Float4(0.5f,0.5f,0.5f,0); + sbDesc_TestBox.size = Oyster::Math::Float4(4,4,4,0); ICustomBody* rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); From b753387649ba6eec14ca1d6514ce5ab0cd94274d Mon Sep 17 00:00:00 2001 From: Erik Persson Date: Fri, 31 Jan 2014 14:14:20 +0100 Subject: [PATCH 09/18] asd --- .merge_file_a01532 | 171 ++++++++++++++++++ .merge_file_a04876 | 93 ++++++++++ .merge_file_a05028 | 66 +++++++ .merge_file_a06880 | 171 ++++++++++++++++++ .merge_file_a07272 | 98 ++++++++++ .merge_file_a07484 | 81 +++++++++ .merge_file_a07992 | 93 ++++++++++ .merge_file_a08280 | 66 +++++++ .merge_file_a08532 | 96 ++++++++++ .merge_file_a08608 | 166 +++++++++++++++++ .merge_file_a09540 | 100 ++++++++++ .merge_file_a11072 | 70 +++++++ .merge_file_a11132 | 70 +++++++ .merge_file_a11320 | 103 +++++++++++ .merge_file_a11560 | 74 ++++++++ Code/Game/DanBiasGame/DanBiasGame_Impl.cpp | 15 +- .../Game/DanBiasGame/GameClientRecieverFunc.h | 6 +- .../GameClientState/GameClientState.h | 1 + .../GameClientState/LanMenuState.cpp | 51 ++++++ .../GameClientState/LanMenuState.h | 2 + Code/Game/GameLogic/Object.h | 1 + .../Implementation/PhysicsAPI_Impl.cpp | 2 +- Code/Misc/EventHandler/EventButton.cpp | 0 Code/Misc/EventHandler/EventButton.h | 0 .../EventHandler/EventButtonCollection.cpp | 25 +++ .../Misc/EventHandler/EventButtonCollection.h | 31 ++++ Code/Misc/EventHandler/EventHandler.cpp | 37 ++++ Code/Misc/EventHandler/EventHandler.h | 35 ++++ Code/Misc/Misc.vcxproj | 6 + Code/Misc/Misc.vcxproj.filters | 18 ++ 30 files changed, 1737 insertions(+), 11 deletions(-) create mode 100644 .merge_file_a01532 create mode 100644 .merge_file_a04876 create mode 100644 .merge_file_a05028 create mode 100644 .merge_file_a06880 create mode 100644 .merge_file_a07272 create mode 100644 .merge_file_a07484 create mode 100644 .merge_file_a07992 create mode 100644 .merge_file_a08280 create mode 100644 .merge_file_a08532 create mode 100644 .merge_file_a08608 create mode 100644 .merge_file_a09540 create mode 100644 .merge_file_a11072 create mode 100644 .merge_file_a11132 create mode 100644 .merge_file_a11320 create mode 100644 .merge_file_a11560 create mode 100644 Code/Misc/EventHandler/EventButton.cpp create mode 100644 Code/Misc/EventHandler/EventButton.h create mode 100644 Code/Misc/EventHandler/EventButtonCollection.cpp create mode 100644 Code/Misc/EventHandler/EventButtonCollection.h create mode 100644 Code/Misc/EventHandler/EventHandler.cpp create mode 100644 Code/Misc/EventHandler/EventHandler.h diff --git a/.merge_file_a01532 b/.merge_file_a01532 new file mode 100644 index 00000000..0a50fbd0 --- /dev/null +++ b/.merge_file_a01532 @@ -0,0 +1,171 @@ +#include "LoginState.h" +#include "DllInterfaces/GFXAPI.h" +#include "OysterMath.h" +#include "C_obj/C_Player.h" +#include "C_obj/C_StaticObj.h" +#include "C_obj/C_DynamicObj.h" +#include + +using namespace DanBias::Client; + +struct LoginState::myData +{ + myData(){} + Oyster::Math3D::Float4x4 view; + Oyster::Math3D::Float4x4 proj; + C_Object* object[2]; + int modelCount; + // UI object + // game client* +}privData; + +LoginState::LoginState(void) +{ + +} + +LoginState::~LoginState(void) +{ + +} + +bool LoginState::Init(Oyster::Network::NetworkClient* nwClient) +{ + privData = new myData(); + this->nwClient = nwClient; + // load models + LoadModels(L"UImodels.txt"); + InitCamera(Oyster::Math::Float3(0,0,5.4f)); + return true; +} +bool LoginState::LoadModels(std::wstring file) +{ + Oyster::Graphics::Definitions::Pointlight plight; + plight.Pos = Oyster::Math::Float3(-2,3,0); + plight.Color = Oyster::Math::Float3(0,1,0); + plight.Radius = 10; + plight.Bright = 1; + Oyster::Graphics::API::AddLight(plight); + // open file + // read file + // init models + privData->modelCount = 2; + + ModelInitData modelData; + + modelData.world = Oyster::Math3D::Float4x4::identity; + modelData.visible = true; + modelData.modelPath = L"..\\Content\\Models\\box_2.dan"; + // load models + privData->object[0] = new C_StaticObj(); + privData->object[0]->Init(modelData); + + Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(-2,-2,-2)); + modelData.world = modelData.world * translate; + + privData->object[1] = new C_DynamicObj(); + privData->object[1]->Init(modelData); + return true; +} + +bool LoginState::InitCamera(Oyster::Math::Float3 startPos) +{ + privData->proj = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/2,1024.0f/768.0f,.1f,1000); + //privData->proj = Oyster::Math3D::ProjectionMatrix_Orthographic(1024, 768, 1, 1000); + Oyster::Graphics::API::SetProjection(privData->proj); + + privData->view = Oyster::Math3D::OrientationMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos); + privData->view = Oyster::Math3D::InverseOrientationMatrix(privData->view); + return true; +} +GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* KeyInput) +{ + // picking + // mouse events + // different menus + // play sounds + // update animation + // send data to server + // check data from server + + + + // create game + if( KeyInput->IsKeyPressed(DIK_C)) + { + DanBias::GameServerAPI::ServerInitDesc desc; + + DanBias::GameServerAPI::ServerInitiate(desc); + DanBias::GameServerAPI::ServerStart(); + // my ip + nwClient->Connect(15151, "127.0.0.1"); + + if (!nwClient->IsConnected()) + { + // failed to connect + return ClientState_Same; + } + return ClientState_LobbyCreated; + } + // join game + if( KeyInput->IsKeyPressed(DIK_J)) + { + // game ip + nwClient->Connect(15151, "193.11.184.109"); + + if (!nwClient->IsConnected()) + { + // failed to connect + return ClientState_Same; + } + return ClientState_Lobby; + } + + + + return ClientState_Same; +} +bool LoginState::Render() +{ + + Oyster::Graphics::API::SetView(privData->view); + Oyster::Graphics::API::SetProjection( privData->proj); + + + Oyster::Graphics::API::NewFrame(); + // render objects + for (int i = 0; i < privData->modelCount; i++) + { + privData->object[i]->Render(); + } + + // render effects + + // render lights + + Oyster::Graphics::API::EndFrame(); + return true; +} +bool LoginState::Release() +{ + for (int i = 0; i < privData->modelCount; i++) + { + privData->object[i]->Release(); + delete privData->object[i]; + privData->object[i] = NULL; + } + + delete privData; + privData = NULL; + return true; +} +void LoginState::Protocol(ProtocolStruct* protocol) +{ + if((PlayerName*)protocol) + PlayerJoinProtocol((PlayerName*)protocol); + +} +void LoginState::PlayerJoinProtocol(PlayerName* name) +{ + +} \ No newline at end of file diff --git a/.merge_file_a04876 b/.merge_file_a04876 new file mode 100644 index 00000000..c0b0685b --- /dev/null +++ b/.merge_file_a04876 @@ -0,0 +1,93 @@ +#include "Level.h" +#include "CollisionManager.h" + +using namespace GameLogic; +using namespace Utility::DynamicMemory; +using namespace Oyster::Physics; + + +Level::Level(void) +{ + +} +Level::~Level(void) +{ +} + +void Level::InitiateLevel(std::string levelPath) +{ + +} +void Level::InitiateLevel(float radius) +{ + + // add level sphere + API::SphericalBodyDescription sbDesc; + sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); + sbDesc.ignoreGravity = true; + sbDesc.radius = 300; + sbDesc.mass = 10e12f; + + ICustomBody* rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); + + ICustomBody::State state; + rigidBody->GetState(state); + state.SetRestitutionCoeff(0.01); + rigidBody->SetState(state); + + levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); + rigidBody->SetCustomTag(levelObj); + + + // add box + API::SimpleBodyDescription sbDesc_TestBox; + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(4,320,0,0); + sbDesc_TestBox.ignoreGravity = false; + sbDesc_TestBox.mass = 10; + sbDesc_TestBox.size = Oyster::Math::Float4(0.5f,0.5f,0.5f,0); + + ICustomBody* rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); + rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + + testBox = new DynamicObject(rigidBody_TestBox, OBJECT_TYPE::OBJECT_TYPE_BOX); + rigidBody_TestBox->SetCustomTag(testBox); + rigidBody_TestBox->GetState(state); + state.ApplyLinearImpulse(Oyster::Math::Float3(0,20,0)); + rigidBody_TestBox->SetState(state); + + + // add gravitation + API::Gravity gravityWell; + gravityWell.gravityType = API::Gravity::GravityType_Well; + gravityWell.well.mass = 1e15f; + gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); + API::Instance().AddGravity(gravityWell); +} + +void Level::AddPlayerToTeam(Player *player, int teamID) +{ + this->teamManager.AddPlayerToTeam(player,teamID); +} + +void Level::CreateTeam(int teamSize) +{ + this->teamManager.CreateTeam(teamSize); +} + +void Level::RespawnPlayer(Player *player) +{ + this->teamManager.RespawnPlayerRandom(player); +} + +Object* Level::GetObj( int ID) const +{ + if( ID == 0 ) + return (Object*)levelObj; + else + return (Object*)testBox; +} +void Level::PhysicsOnMoveLevel(const ICustomBody *object) +{ + // function call from physics update when object was moved + Object* temp = (Object*)object->GetCustomTag(); +} diff --git a/.merge_file_a05028 b/.merge_file_a05028 new file mode 100644 index 00000000..93fcfba6 --- /dev/null +++ b/.merge_file_a05028 @@ -0,0 +1,66 @@ +#include "Game.h" +#include "Player.h" + +using namespace GameLogic; + +Game::PlayerData::PlayerData() +{ + //set some stats that are appropriate to a player + Oyster::Physics::API::SimpleBodyDescription sbDesc; + sbDesc.centerPosition = Oyster::Math::Float3(10,350,0); + sbDesc.size = Oyster::Math::Float3(4,7,4); + sbDesc.mass = 70; + //create rigid body + Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); + + //create player with this rigid body + this->player = new Player(rigidBody,Object::DefaultCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); + this->player->GetRigidBody()->SetCustomTag(this); + +} +Game::PlayerData::PlayerData(int playerID,int teamID) +{ + this->player = new Player(); +} +Game::PlayerData::~PlayerData() +{ + delete this->player; +} + +void Game::PlayerData::Move(const PLAYER_MOVEMENT &movement) +{ + this->player->Move(movement); +} +void Game::PlayerData::UseWeapon(const WEAPON_FIRE &usage) +{ + this->player->UseWeapon(usage); +} +Oyster::Math::Float3 Game::PlayerData::GetPosition() +{ + return this->player->GetPosition(); +} +Oyster::Math::Float4x4 Game::PlayerData::GetOrientation() +{ + return this->player->GetOrientation(); +} +PLAYER_STATE Game::PlayerData::GetState() const +{ + return this->player->GetState(); +} +int Game::PlayerData::GetID() const +{ + return this->player->GetID(); +} +int Game::PlayerData::GetTeamID() const +{ + return this->player->GetTeamID(); +} + +OBJECT_TYPE Game::PlayerData::GetObjectType() const +{ + return this->player->GetObjectType(); +} +void Game::PlayerData::Rotate(const Oyster::Math3D::Float3 lookDir) +{ + this->player->Rotate(lookDir); +} \ No newline at end of file diff --git a/.merge_file_a06880 b/.merge_file_a06880 new file mode 100644 index 00000000..a5188306 --- /dev/null +++ b/.merge_file_a06880 @@ -0,0 +1,171 @@ +#include "LoginState.h" +#include "DllInterfaces/GFXAPI.h" +#include "OysterMath.h" +#include "C_obj/C_Player.h" +#include "C_obj/C_StaticObj.h" +#include "C_obj/C_DynamicObj.h" +#include + +using namespace DanBias::Client; + +struct LoginState::myData +{ + myData(){} + Oyster::Math3D::Float4x4 view; + Oyster::Math3D::Float4x4 proj; + C_Object* object[2]; + int modelCount; + // UI object + // game client* +}privData; + +LoginState::LoginState(void) +{ + +} + +LoginState::~LoginState(void) +{ + +} + +bool LoginState::Init(Oyster::Network::NetworkClient* nwClient) +{ + privData = new myData(); + this->nwClient = nwClient; + // load models + LoadModels(L"UImodels.txt"); + InitCamera(Oyster::Math::Float3(0,0,5.4f)); + return true; +} +bool LoginState::LoadModels(std::wstring file) +{ + Oyster::Graphics::Definitions::Pointlight plight; + plight.Pos = Oyster::Math::Float3(-2,3,0); + plight.Color = Oyster::Math::Float3(0,1,0); + plight.Radius = 10; + plight.Bright = 1; + Oyster::Graphics::API::AddLight(plight); + // open file + // read file + // init models + privData->modelCount = 2; + + ModelInitData modelData; + + modelData.world = Oyster::Math3D::Float4x4::identity; + modelData.visible = true; + modelData.modelPath = L"..\\Content\\Models\\box_2.dan"; + // load models + privData->object[0] = new C_StaticObj(); + privData->object[0]->Init(modelData); + + Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(-2,-2,-2)); + modelData.world = modelData.world * translate; + + privData->object[1] = new C_DynamicObj(); + privData->object[1]->Init(modelData); + return true; +} + +bool LoginState::InitCamera(Oyster::Math::Float3 startPos) +{ + privData->proj = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/2,1024.0f/768.0f,.1f,1000); + //privData->proj = Oyster::Math3D::ProjectionMatrix_Orthographic(1024, 768, 1, 1000); + Oyster::Graphics::API::SetProjection(privData->proj); + + privData->view = Oyster::Math3D::OrientationMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos); + privData->view = Oyster::Math3D::InverseOrientationMatrix(privData->view); + return true; +} +GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* KeyInput) +{ + // picking + // mouse events + // different menus + // play sounds + // update animation + // send data to server + // check data from server + + + + // create game + if( KeyInput->IsKeyPressed(DIK_C)) + { + DanBias::GameServerAPI::ServerInitDesc desc; + + DanBias::GameServerAPI::ServerInitiate(desc); + DanBias::GameServerAPI::ServerStart(); + // my ip + nwClient->Connect(15151, "127.0.0.1"); + + if (!nwClient->IsConnected()) + { + // failed to connect + return ClientState_Same; + } + return ClientState_LobbyCreated; + } + // join game + if( KeyInput->IsKeyPressed(DIK_J)) + { + // game ip + nwClient->Connect(15151, "194.47.150.56"); + + if (!nwClient->IsConnected()) + { + // failed to connect + return ClientState_Same; + } + return ClientState_Lobby; + } + + + + return ClientState_Same; +} +bool LoginState::Render() +{ + + Oyster::Graphics::API::SetView(privData->view); + Oyster::Graphics::API::SetProjection( privData->proj); + + + Oyster::Graphics::API::NewFrame(); + // render objects + for (int i = 0; i < privData->modelCount; i++) + { + privData->object[i]->Render(); + } + + // render effects + + // render lights + + Oyster::Graphics::API::EndFrame(); + return true; +} +bool LoginState::Release() +{ + for (int i = 0; i < privData->modelCount; i++) + { + privData->object[i]->Release(); + delete privData->object[i]; + privData->object[i] = NULL; + } + + delete privData; + privData = NULL; + return true; +} +void LoginState::Protocol(ProtocolStruct* protocol) +{ + if((PlayerName*)protocol) + PlayerJoinProtocol((PlayerName*)protocol); + +} +void LoginState::PlayerJoinProtocol(PlayerName* name) +{ + +} \ No newline at end of file diff --git a/.merge_file_a07272 b/.merge_file_a07272 new file mode 100644 index 00000000..93c41976 --- /dev/null +++ b/.merge_file_a07272 @@ -0,0 +1,98 @@ +#include "Level.h" +#include "CollisionManager.h" + +using namespace GameLogic; +using namespace Utility::DynamicMemory; +using namespace Oyster::Physics; + + +Level::Level(void) +{ + +} +Level::~Level(void) +{ +} + +void Level::InitiateLevel(std::string levelPath) +{ + +} +void Level::InitiateLevel(float radius) +{ + + // add level sphere + API::SphericalBodyDescription sbDesc; + sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); + sbDesc.ignoreGravity = true; + sbDesc.radius = 300; + sbDesc.mass = 10e12f; + + ICustomBody* rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); + + ICustomBody::State state; + rigidBody->GetState(state); + state.SetRestitutionCoeff(0.01); + rigidBody->SetState(state); + + levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); + rigidBody->SetCustomTag(levelObj); + + + // add box + API::SimpleBodyDescription sbDesc_TestBox; + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,320,0,0); + sbDesc_TestBox.ignoreGravity = false; +<<<<<<< .merge_file_a07272 + sbDesc_TestBox.mass = 10; + sbDesc_TestBox.size = Oyster::Math::Float4(4,4,4,0); +======= + sbDesc_TestBox.mass = 50; + sbDesc_TestBox.size = Oyster::Math::Float4(1,1,1,0); +>>>>>>> .merge_file_a07992 + + ICustomBody* rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); + rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + + testBox = new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX); + rigidBody_TestBox->SetCustomTag(testBox); + rigidBody_TestBox->GetState(state); + state.ApplyLinearImpulse(Oyster::Math::Float3(0,0,0)); + rigidBody_TestBox->SetState(state); + + + // add gravitation + API::Gravity gravityWell; + gravityWell.gravityType = API::Gravity::GravityType_Well; + gravityWell.well.mass = 1e15f; + gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); + API::Instance().AddGravity(gravityWell); +} + +void Level::AddPlayerToTeam(Player *player, int teamID) +{ + this->teamManager.AddPlayerToTeam(player,teamID); +} + +void Level::CreateTeam(int teamSize) +{ + this->teamManager.CreateTeam(teamSize); +} + +void Level::RespawnPlayer(Player *player) +{ + this->teamManager.RespawnPlayerRandom(player); +} + +Object* Level::GetObj( int ID) const +{ + if( ID == 0 ) + return (Object*)levelObj; + else + return (Object*)testBox; +} +void Level::PhysicsOnMoveLevel(const ICustomBody *object) +{ + // function call from physics update when object was moved + Object* temp = (Object*)object->GetCustomTag(); +} diff --git a/.merge_file_a07484 b/.merge_file_a07484 new file mode 100644 index 00000000..f0a2a4d6 --- /dev/null +++ b/.merge_file_a07484 @@ -0,0 +1,81 @@ +#include "AttatchmentMassDriver.h" +#include "PhysicsAPI.h" +#include "GameLogicStates.h" + +using namespace GameLogic; + + + +AttatchmentMassDriver::AttatchmentMassDriver(void) +{ + this->owner = 0; +} + +AttatchmentMassDriver::AttatchmentMassDriver(Player &owner) +{ + + this->owner = &owner; +} + + +AttatchmentMassDriver::~AttatchmentMassDriver(void) +{ + +} + +/******************************************************** +* Uses the attatchment and will from here switch case the different WEAPON_FIRE's that are to be used +********************************************************/ +void AttatchmentMassDriver::UseAttatchment(const GameLogic::WEAPON_FIRE &usage, float dt) +{ + //switch case to determin what functionallity to use in the attatchment + switch (usage) + { + case WEAPON_FIRE::WEAPON_USE_PRIMARY_PRESS: + ForcePush(usage,dt); + break; + case WEAPON_FIRE::WEAPON_USE_SECONDARY_PRESS: + ForcePull(usage,dt); + break; + } + +} + +/******************************************************** +* Pushes objects in a cone in front of the weapon when fired +********************************************************/ +void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float dt) +{ +<<<<<<< .merge_file_a07484 + Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); + Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); +======= + //Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); + + Oyster::Math::Float3 look = owner->GetLookDir(); + Oyster::Math::Float3 up = -owner->GetRigidBody()->GetGravityNormal(); + Oyster::Math::Float3 pos = owner->GetPosition(); + Oyster::Math::Float4x4 aim = Oyster::Math3D::OrientationMatrix_LookAtDirection(owner->GetLookDir(), -owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); +>>>>>>> .merge_file_a11560 + Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); + Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); + forcePushData args; + args.pushForce = pushForce; + + Oyster::Physics::API::Instance().ApplyEffect(hitFrustum,&args,ForcePushAction); +} + +/******************************************************** +* Pulls the player in the direction he is looking, used for fast movement(kinda like a jetpack) +********************************************************/ +void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) +{ + Oyster::Physics::Struct::CustomBodyState state = this->owner->GetRigidBody()->GetState(); + + //do something with state + state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt)); + + this->owner->GetRigidBody()->SetState(state); +} + + diff --git a/.merge_file_a07992 b/.merge_file_a07992 new file mode 100644 index 00000000..e09f9bb0 --- /dev/null +++ b/.merge_file_a07992 @@ -0,0 +1,93 @@ +#include "Level.h" +#include "CollisionManager.h" + +using namespace GameLogic; +using namespace Utility::DynamicMemory; +using namespace Oyster::Physics; + + +Level::Level(void) +{ + +} +Level::~Level(void) +{ +} + +void Level::InitiateLevel(std::string levelPath) +{ + +} +void Level::InitiateLevel(float radius) +{ + + // add level sphere + API::SphericalBodyDescription sbDesc; + sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); + sbDesc.ignoreGravity = true; + sbDesc.radius = 300; + sbDesc.mass = 10e12f; + + ICustomBody* rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); + + ICustomBody::State state; + rigidBody->GetState(state); + state.SetRestitutionCoeff(0.01); + rigidBody->SetState(state); + + levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); + rigidBody->SetCustomTag(levelObj); + + + // add box + API::SimpleBodyDescription sbDesc_TestBox; + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,320,0,0); + sbDesc_TestBox.ignoreGravity = false; + sbDesc_TestBox.mass = 50; + sbDesc_TestBox.size = Oyster::Math::Float4(1,1,1,0); + + ICustomBody* rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); + rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + + testBox = new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX); + rigidBody_TestBox->SetCustomTag(testBox); + rigidBody_TestBox->GetState(state); + state.ApplyLinearImpulse(Oyster::Math::Float3(0,0,0)); + rigidBody_TestBox->SetState(state); + + + // add gravitation + API::Gravity gravityWell; + gravityWell.gravityType = API::Gravity::GravityType_Well; + gravityWell.well.mass = 1e15f; + gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); + API::Instance().AddGravity(gravityWell); +} + +void Level::AddPlayerToTeam(Player *player, int teamID) +{ + this->teamManager.AddPlayerToTeam(player,teamID); +} + +void Level::CreateTeam(int teamSize) +{ + this->teamManager.CreateTeam(teamSize); +} + +void Level::RespawnPlayer(Player *player) +{ + this->teamManager.RespawnPlayerRandom(player); +} + +Object* Level::GetObj( int ID) const +{ + if( ID == 0 ) + return (Object*)levelObj; + else + return (Object*)testBox; +} +void Level::PhysicsOnMoveLevel(const ICustomBody *object) +{ + // function call from physics update when object was moved + Object* temp = (Object*)object->GetCustomTag(); +} diff --git a/.merge_file_a08280 b/.merge_file_a08280 new file mode 100644 index 00000000..18f57212 --- /dev/null +++ b/.merge_file_a08280 @@ -0,0 +1,66 @@ +#include "Game.h" +#include "Player.h" + +using namespace GameLogic; + +Game::PlayerData::PlayerData() +{ + //set some stats that are appropriate to a player + Oyster::Physics::API::SimpleBodyDescription sbDesc; + sbDesc.centerPosition = Oyster::Math::Float3(0,320,0); + sbDesc.size = Oyster::Math::Float3(4,7,4); + sbDesc.mass = 10; + //create rigid body + Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); + + //create player with this rigid body + this->player = new Player(rigidBody,Object::DefaultCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); + this->player->GetRigidBody()->SetCustomTag(this); + +} +Game::PlayerData::PlayerData(int playerID,int teamID) +{ + this->player = new Player(); +} +Game::PlayerData::~PlayerData() +{ + delete this->player; +} + +void Game::PlayerData::Move(const PLAYER_MOVEMENT &movement) +{ + this->player->Move(movement); +} +void Game::PlayerData::UseWeapon(const WEAPON_FIRE &usage) +{ + this->player->UseWeapon(usage); +} +Oyster::Math::Float3 Game::PlayerData::GetPosition() +{ + return this->player->GetPosition(); +} +Oyster::Math::Float4x4 Game::PlayerData::GetOrientation() +{ + return this->player->GetOrientation(); +} +PLAYER_STATE Game::PlayerData::GetState() const +{ + return this->player->GetState(); +} +int Game::PlayerData::GetID() const +{ + return this->player->GetID(); +} +int Game::PlayerData::GetTeamID() const +{ + return this->player->GetTeamID(); +} + +OBJECT_TYPE Game::PlayerData::GetObjectType() const +{ + return this->player->GetObjectType(); +} +void Game::PlayerData::Rotate(const Oyster::Math3D::Float3 lookDir) +{ + this->player->Rotate(lookDir); +} \ No newline at end of file diff --git a/.merge_file_a08532 b/.merge_file_a08532 new file mode 100644 index 00000000..019df6f4 --- /dev/null +++ b/.merge_file_a08532 @@ -0,0 +1,96 @@ +#include "PhysicsAPI.h" +#include "Object.h" +#include "DynamicObject.h" +#include "Player.h" +#include "Level.h" +#include "AttatchmentMassDriver.h" +#include "Game.h" + +using namespace Oyster; + +using namespace GameLogic; + + void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss); + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss); + + //Physics::ICustomBody::SubscriptMessage + void Player::PlayerCollision(Oyster::Physics::ICustomBody *rigidBodyPlayer, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + + Player *player = ((Game::PlayerData*)(rigidBodyPlayer->GetCustomTag()))->player; + Object *realObj = (Object*)obj->GetCustomTag(); //needs to be changed? + + switch (realObj->GetObjectType()) + { + case OBJECT_TYPE::OBJECT_TYPE_GENERIC: + PlayerVObject(*player,*realObj, kineticEnergyLoss); + //return Physics::ICustomBody::SubscriptMessage_none; + break; + + case OBJECT_TYPE::OBJECT_TYPE_BOX: + PlayerVBox(*player,(*(DynamicObject*) realObj), kineticEnergyLoss); + //return Physics::ICustomBody::SubscriptMessage_none; + break; + case OBJECT_TYPE::OBJECT_TYPE_PLAYER: + //return Physics::ICustomBody::SubscriptMessage_none; + break; + case OBJECT_TYPE::OBJECT_TYPE_WORLD: + int test = 5; + break; + } + + //return Physics::ICustomBody::SubscriptMessage_none; + } + + void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss) + { + //use kinetic energyloss of the collision in order too determin how much damage to take + //use as part of the damage algorithm + player.DamageLife(20); + } + + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss) + { + //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 = 200; + + if(kineticEnergyLoss > forceThreashHold) //should only take damage if the force is high enough + { + damageDone = kineticEnergyLoss * 0.10f; + player.DamageLife(damageDone); + } + + } + Oyster::Physics::ICustomBody::SubscriptMessage Object::DefaultCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_none; + } + Oyster::Physics::ICustomBody::SubscriptMessage Object::DefaultCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + return Physics::ICustomBody::SubscriptMessage_none; + } + //Oyster::Physics::ICustomBody::SubscriptMessage + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + + void AttatchmentMassDriver::ForcePushAction(Oyster::Physics::ICustomBody *obj, void *args) + { + Oyster::Physics::ICustomBody::State state; + Object *realObj = (Object*)obj->GetCustomTag(); + + if(realObj->GetObjectType() == OBJECT_TYPE_PLAYER || realObj->GetObjectType() == OBJECT_TYPE_WORLD) + return; + + state = obj->GetState(); + state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce); + obj->SetState(state); + } \ No newline at end of file diff --git a/.merge_file_a08608 b/.merge_file_a08608 new file mode 100644 index 00000000..cd1e4663 --- /dev/null +++ b/.merge_file_a08608 @@ -0,0 +1,166 @@ +#include "LoginState.h" +#include "DllInterfaces/GFXAPI.h" +#include "OysterMath.h" +#include "C_obj/C_Player.h" +#include "C_obj/C_StaticObj.h" +#include "C_obj/C_DynamicObj.h" +#include + +using namespace DanBias::Client; + +struct LoginState::myData +{ + myData(){} + Oyster::Math3D::Float4x4 view; + Oyster::Math3D::Float4x4 proj; + C_Object* object[2]; + int modelCount; + // UI object + // game client* +}privData; + +LoginState::LoginState(void) +{ + +} + +LoginState::~LoginState(void) +{ + +} + +bool LoginState::Init(Oyster::Network::NetworkClient* nwClient) +{ + privData = new myData(); + this->nwClient = nwClient; + // load models + LoadModels(L"UImodels.txt"); + InitCamera(Oyster::Math::Float3(0,0,5.4f)); + return true; +} +bool LoginState::LoadModels(std::wstring file) +{ + Oyster::Graphics::Definitions::Pointlight plight; + plight.Pos = Oyster::Math::Float3(-2,3,0); + plight.Color = Oyster::Math::Float3(0,1,0); + plight.Radius = 10; + plight.Bright = 1; + Oyster::Graphics::API::AddLight(plight); + // open file + // read file + // init models + privData->modelCount = 2; + + ModelInitData modelData; + + modelData.world = Oyster::Math3D::Float4x4::identity; + modelData.visible = true; + modelData.modelPath = L"..\\Content\\Models\\box_2.dan"; + // load models + privData->object[0] = new C_StaticObj(); + privData->object[0]->Init(modelData); + + Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(-2,-2,-2)); + modelData.world = modelData.world * translate; + + privData->object[1] = new C_DynamicObj(); + privData->object[1]->Init(modelData); + return true; +} + +bool LoginState::InitCamera(Oyster::Math::Float3 startPos) +{ + privData->proj = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/2,1024.0f/768.0f,.1f,1000); + //privData->proj = Oyster::Math3D::ProjectionMatrix_Orthographic(1024, 768, 1, 1000); + Oyster::Graphics::API::SetProjection(privData->proj); + + privData->view = Oyster::Math3D::OrientationMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos); + privData->view = Oyster::Math3D::InverseOrientationMatrix(privData->view); + return true; +} +GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* KeyInput) +{ + // picking + // mouse events + // different menus + // play sounds + // update animation + // send data to server + // check data from server + + // create game + if( KeyInput->IsKeyPressed(DIK_C)) + { + DanBias::GameServerAPI::ServerInitDesc desc; + + DanBias::GameServerAPI::ServerInitiate(desc); + DanBias::GameServerAPI::ServerStart(); + // my ip + nwClient->Connect(15151, "127.0.0.1"); + + if (!nwClient->IsConnected()) + { + // failed to connect + return ClientState_Same; + } + return ClientState_LobbyCreated; + } + // join game + if( KeyInput->IsKeyPressed(DIK_J)) + { + // game ip + nwClient->Connect(15151, "194.47.150.56"); + + if (!nwClient->IsConnected()) + { + // failed to connect + return ClientState_Same; + } + return ClientState_Lobby; + } + return ClientState_Same; +} +bool LoginState::Render() +{ + + Oyster::Graphics::API::SetView(privData->view); + Oyster::Graphics::API::SetProjection( privData->proj); + + + Oyster::Graphics::API::NewFrame(); + // render objects + for (int i = 0; i < privData->modelCount; i++) + { + privData->object[i]->Render(); + } + + // render effects + + // render lights + + Oyster::Graphics::API::EndFrame(); + return true; +} +bool LoginState::Release() +{ + for (int i = 0; i < privData->modelCount; i++) + { + privData->object[i]->Release(); + delete privData->object[i]; + privData->object[i] = NULL; + } + + delete privData; + privData = NULL; + return true; +} +void LoginState::Protocol(ProtocolStruct* protocol) +{ + if((PlayerName*)protocol) + PlayerJoinProtocol((PlayerName*)protocol); + +} +void LoginState::PlayerJoinProtocol(PlayerName* name) +{ + +} \ No newline at end of file diff --git a/.merge_file_a09540 b/.merge_file_a09540 new file mode 100644 index 00000000..27aa6db6 --- /dev/null +++ b/.merge_file_a09540 @@ -0,0 +1,100 @@ +#include "PhysicsAPI.h" +#include "Object.h" +#include "DynamicObject.h" +#include "Player.h" +#include "Level.h" +#include "AttatchmentMassDriver.h" +#include "Game.h" + +using namespace Oyster; + +using namespace GameLogic; + + void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss); + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss); + + //Physics::ICustomBody::SubscriptMessage + void Player::PlayerCollision(Oyster::Physics::ICustomBody *rigidBodyPlayer, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + + Player *player = ((Game::PlayerData*)(rigidBodyPlayer->GetCustomTag()))->player; + Object *realObj = (Object*)obj->GetCustomTag(); //needs to be changed? + + return; + switch (realObj->GetObjectType()) + { + case OBJECT_TYPE::OBJECT_TYPE_GENERIC: + PlayerVObject(*player,*realObj, kineticEnergyLoss); + //return Physics::ICustomBody::SubscriptMessage_none; + break; + + case OBJECT_TYPE::OBJECT_TYPE_BOX: + PlayerVBox(*player,(*(DynamicObject*) realObj), kineticEnergyLoss); + //return Physics::ICustomBody::SubscriptMessage_none; + break; + case OBJECT_TYPE::OBJECT_TYPE_PLAYER: + //return Physics::ICustomBody::SubscriptMessage_none; + break; + case OBJECT_TYPE::OBJECT_TYPE_WORLD: + int test = 5; + break; + } + + //return Physics::ICustomBody::SubscriptMessage_none; + } + + void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss) + { + //use kinetic energyloss of the collision in order too determin how much damage to take + //use as part of the damage algorithm + player.DamageLife(20); + } + + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss) + { + //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 = 200; + + if(kineticEnergyLoss > forceThreashHold) //should only take damage if the force is high enough + { + damageDone = kineticEnergyLoss * 0.10f; + player.DamageLife(damageDone); + } + + } + Oyster::Physics::ICustomBody::SubscriptMessage Object::DefaultCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_none; + } + //Oyster::Physics::ICustomBody::SubscriptMessage + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + + void AttatchmentMassDriver::ForcePushAction(Oyster::Physics::ICustomBody *obj, void *args) + { + Oyster::Math::Float3 pushForce = Oyster::Math::Float4(1,0,0) * (500); + Oyster::Physics::ICustomBody::State state; + Object *realObj = (Object*)obj->GetCustomTag(); + if(realObj->GetObjectType() == OBJECT_TYPE_BOX) + { + state = obj->GetState(); + state.SetOrientation(Oyster::Math::Float3(1,0.5,1),Oyster::Math::Float3(1,0.5,1)); + obj->SetState(state); + } + + if(realObj->GetObjectType() == OBJECT_TYPE_PLAYER || realObj->GetObjectType() == OBJECT_TYPE_WORLD) + return; + state = obj->GetState(); + state.ApplyLinearImpulse(pushForce); + obj->SetState(state); + //((Object*)obj->GetCustomTag())->ApplyLinearImpulse(pushForce); + } \ No newline at end of file diff --git a/.merge_file_a11072 b/.merge_file_a11072 new file mode 100644 index 00000000..4f47006e --- /dev/null +++ b/.merge_file_a11072 @@ -0,0 +1,70 @@ +#include "Game.h" +#include "Player.h" + +using namespace GameLogic; + +Game::PlayerData::PlayerData() +{ + //set some stats that are appropriate to a player + Oyster::Physics::API::SimpleBodyDescription sbDesc; + sbDesc.centerPosition = Oyster::Math::Float3(10,350,0); + sbDesc.size = Oyster::Math::Float3(4,7,4); +<<<<<<< .merge_file_a11072 + sbDesc.mass = 90; +======= + sbDesc.mass = 70; +>>>>>>> .merge_file_a05028 + //create rigid body + Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); + + //create player with this rigid body + this->player = new Player(rigidBody,Object::DefaultCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); + this->player->GetRigidBody()->SetCustomTag(this); + +} +Game::PlayerData::PlayerData(int playerID,int teamID) +{ + this->player = new Player(); +} +Game::PlayerData::~PlayerData() +{ + delete this->player; +} + +void Game::PlayerData::Move(const PLAYER_MOVEMENT &movement) +{ + this->player->Move(movement); +} +void Game::PlayerData::UseWeapon(const WEAPON_FIRE &usage) +{ + this->player->UseWeapon(usage); +} +Oyster::Math::Float3 Game::PlayerData::GetPosition() +{ + return this->player->GetPosition(); +} +Oyster::Math::Float4x4 Game::PlayerData::GetOrientation() +{ + return this->player->GetOrientation(); +} +PLAYER_STATE Game::PlayerData::GetState() const +{ + return this->player->GetState(); +} +int Game::PlayerData::GetID() const +{ + return this->player->GetID(); +} +int Game::PlayerData::GetTeamID() const +{ + return this->player->GetTeamID(); +} + +OBJECT_TYPE Game::PlayerData::GetObjectType() const +{ + return this->player->GetObjectType(); +} +void Game::PlayerData::Rotate(const Oyster::Math3D::Float3 lookDir) +{ + this->player->Rotate(lookDir); +} \ No newline at end of file diff --git a/.merge_file_a11132 b/.merge_file_a11132 new file mode 100644 index 00000000..7554c879 --- /dev/null +++ b/.merge_file_a11132 @@ -0,0 +1,70 @@ +#include "AttatchmentMassDriver.h" +#include "PhysicsAPI.h" + +using namespace GameLogic; + + + +AttatchmentMassDriver::AttatchmentMassDriver(void) +{ + this->owner = 0; +} + +AttatchmentMassDriver::AttatchmentMassDriver(Player &owner) +{ + + this->owner = &owner; +} + + +AttatchmentMassDriver::~AttatchmentMassDriver(void) +{ + +} + +/******************************************************** +* Uses the attatchment and will from here switch case the different WEAPON_FIRE's that are to be used +********************************************************/ +void AttatchmentMassDriver::UseAttatchment(const GameLogic::WEAPON_FIRE &usage, float dt) +{ + //switch case to determin what functionallity to use in the attatchment + switch (usage) + { + case WEAPON_FIRE::WEAPON_USE_PRIMARY_PRESS: + ForcePush(usage,dt); + break; + case WEAPON_FIRE::WEAPON_USE_SECONDARY_PRESS: + ForcePull(usage,dt); + break; + } + +} + +/******************************************************** +* Pushes objects in a cone in front of the weapon when fired +********************************************************/ +void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float dt) +{ + //Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); + Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); + Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); + Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); + int arg = 0; + + Oyster::Physics::API::Instance().ApplyEffect(hitFrustum,&arg,ForcePushAction); +} + +/******************************************************** +* Pulls the player in the direction he is looking, used for fast movement(kinda like a jetpack) +********************************************************/ +void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) +{ + Oyster::Physics::Struct::CustomBodyState state = this->owner->GetRigidBody()->GetState(); + + //do something with state + state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt)); + + this->owner->GetRigidBody()->SetState(state); +} + + diff --git a/.merge_file_a11320 b/.merge_file_a11320 new file mode 100644 index 00000000..196aed09 --- /dev/null +++ b/.merge_file_a11320 @@ -0,0 +1,103 @@ +#include "PhysicsAPI.h" +#include "Object.h" +#include "DynamicObject.h" +#include "Player.h" +#include "Level.h" +#include "AttatchmentMassDriver.h" +#include "Game.h" + +using namespace Oyster; + +using namespace GameLogic; + + void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss); + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss); + + //Physics::ICustomBody::SubscriptMessage + void Player::PlayerCollision(Oyster::Physics::ICustomBody *rigidBodyPlayer, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + + Player *player = ((Game::PlayerData*)(rigidBodyPlayer->GetCustomTag()))->player; + Object *realObj = (Object*)obj->GetCustomTag(); //needs to be changed? + + switch (realObj->GetObjectType()) + { + case OBJECT_TYPE::OBJECT_TYPE_GENERIC: + PlayerVObject(*player,*realObj, kineticEnergyLoss); + //return Physics::ICustomBody::SubscriptMessage_none; + break; + + case OBJECT_TYPE::OBJECT_TYPE_BOX: + PlayerVBox(*player,(*(DynamicObject*) realObj), kineticEnergyLoss); + //return Physics::ICustomBody::SubscriptMessage_none; + break; + case OBJECT_TYPE::OBJECT_TYPE_PLAYER: + //return Physics::ICustomBody::SubscriptMessage_none; + break; + case OBJECT_TYPE::OBJECT_TYPE_WORLD: + int test = 5; + break; + } + + //return Physics::ICustomBody::SubscriptMessage_none; + } + + void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss) + { + //use kinetic energyloss of the collision in order too determin how much damage to take + //use as part of the damage algorithm + player.DamageLife(20); + } + + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss) + { + //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 = 200; + + if(kineticEnergyLoss > forceThreashHold) //should only take damage if the force is high enough + { + damageDone = kineticEnergyLoss * 0.10f; + player.DamageLife(damageDone); + } + + } + Oyster::Physics::ICustomBody::SubscriptMessage Object::DefaultCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_none; + } + Oyster::Physics::ICustomBody::SubscriptMessage Object::DefaultCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + return Physics::ICustomBody::SubscriptMessage_none; + } + //Oyster::Physics::ICustomBody::SubscriptMessage + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + + void AttatchmentMassDriver::ForcePushAction(Oyster::Physics::ICustomBody *obj, void *args) + { + Oyster::Math::Float3 pushForce = Oyster::Math::Float4(1,0,0) * (500); + Oyster::Physics::ICustomBody::State state; + Object *realObj = (Object*)obj->GetCustomTag(); + if(realObj->GetObjectType() == OBJECT_TYPE_BOX) + { + state = obj->GetState(); + state.SetOrientation(Oyster::Math::Float3(1,0.5,1),Oyster::Math::Float3(1,0.5,1)); + obj->SetState(state); + } + + if(realObj->GetObjectType() == OBJECT_TYPE_PLAYER || realObj->GetObjectType() == OBJECT_TYPE_WORLD) + return; + state = obj->GetState(); + state.ApplyLinearImpulse(pushForce); + obj->SetState(state); + //((Object*)obj->GetCustomTag())->ApplyLinearImpulse(pushForce); + } \ No newline at end of file diff --git a/.merge_file_a11560 b/.merge_file_a11560 new file mode 100644 index 00000000..94efbb71 --- /dev/null +++ b/.merge_file_a11560 @@ -0,0 +1,74 @@ +#include "AttatchmentMassDriver.h" +#include "PhysicsAPI.h" + +using namespace GameLogic; + + + +AttatchmentMassDriver::AttatchmentMassDriver(void) +{ + this->owner = 0; +} + +AttatchmentMassDriver::AttatchmentMassDriver(Player &owner) +{ + + this->owner = &owner; +} + + +AttatchmentMassDriver::~AttatchmentMassDriver(void) +{ + +} + +/******************************************************** +* Uses the attatchment and will from here switch case the different WEAPON_FIRE's that are to be used +********************************************************/ +void AttatchmentMassDriver::UseAttatchment(const GameLogic::WEAPON_FIRE &usage, float dt) +{ + //switch case to determin what functionallity to use in the attatchment + switch (usage) + { + case WEAPON_FIRE::WEAPON_USE_PRIMARY_PRESS: + ForcePush(usage,dt); + break; + case WEAPON_FIRE::WEAPON_USE_SECONDARY_PRESS: + ForcePull(usage,dt); + break; + } + +} + +/******************************************************** +* Pushes objects in a cone in front of the weapon when fired +********************************************************/ +void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float dt) +{ + //Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); + + Oyster::Math::Float3 look = owner->GetLookDir(); + Oyster::Math::Float3 up = -owner->GetRigidBody()->GetGravityNormal(); + Oyster::Math::Float3 pos = owner->GetPosition(); + Oyster::Math::Float4x4 aim = Oyster::Math3D::OrientationMatrix_LookAtDirection(owner->GetLookDir(), -owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); + Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); + Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); + int arg = 0; + + Oyster::Physics::API::Instance().ApplyEffect(hitFrustum,&arg,ForcePushAction); +} + +/******************************************************** +* Pulls the player in the direction he is looking, used for fast movement(kinda like a jetpack) +********************************************************/ +void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) +{ + Oyster::Physics::Struct::CustomBodyState state = this->owner->GetRigidBody()->GetState(); + + //do something with state + state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt)); + + this->owner->GetRigidBody()->SetState(state); +} + + diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index 06f200bf..4a54297f 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -38,7 +38,7 @@ namespace DanBias public: WindowShell* window; InputClass* inputObj; - Utility::WinTimer* timer; + Utility::WinTimer timer; GameRecieverObject* recieverObj; bool serverOwner; @@ -69,12 +69,11 @@ namespace DanBias m_data->serverOwner = false; // Start in lobby state - m_data->recieverObj->gameClientState = new Client::LoginState(); + m_data->recieverObj->gameClientState = new Client::LoginState(); if(!m_data->recieverObj->gameClientState->Init(m_data->recieverObj)) return DanBiasClientReturn_Error; - m_data->timer = new Utility::WinTimer(); //why dynamic memory? - m_data->timer->reset(); + m_data->timer.reset(); return DanBiasClientReturn_Sucess; } @@ -83,8 +82,8 @@ namespace DanBias // Main message loop while(m_data->window->Frame()) { - float dt = (float)m_data->timer->getElapsedSeconds(); - m_data->timer->reset(); + float dt = (float)m_data->timer.getElapsedSeconds(); + m_data->timer.reset(); capFrame += dt; if(capFrame > 0.03) @@ -131,8 +130,9 @@ namespace DanBias HRESULT DanBiasGame::Update(float deltaTime) { + if(m_data->recieverObj->IsConnected()) + m_data->recieverObj->Update(); - m_data->recieverObj->Update(); m_data->inputObj->Update(); if(m_data->serverOwner) @@ -192,7 +192,6 @@ namespace DanBias delete m_data->recieverObj->gameClientState; m_data->recieverObj->Disconnect(); delete m_data->recieverObj; - delete m_data->timer; delete m_data->inputObj; delete m_data; diff --git a/Code/Game/DanBiasGame/GameClientRecieverFunc.h b/Code/Game/DanBiasGame/GameClientRecieverFunc.h index 36b831a0..de8f63a6 100644 --- a/Code/Game/DanBiasGame/GameClientRecieverFunc.h +++ b/Code/Game/DanBiasGame/GameClientRecieverFunc.h @@ -2,6 +2,8 @@ #define DANBIAS_CLIENTRECIEVEROBJECT_H //WTF!? No headers included??? +#include "../DanBiasGame/Include/DanBiasGame.h" +#include "../GameProtocols/GeneralProtocols.h" namespace DanBias { @@ -128,8 +130,8 @@ namespace DanBias break; case protocol_Lobby_GameData: //this->LobbyGameData (Protocol_LobbyGameData (p), c); { - GameLogic::Protocol_LobbyGameData temp(p); - printf("%s, %i.%i\n", temp.mapName.c_str(), temp.majorVersion, temp.minorVersion); + //GameLogic::Protocol_LobbyGameData temp(p); + //printf("%s, %i.%i\n", temp.mapName.c_str(), temp.majorVersion, temp.minorVersion); } break; case protocol_Lobby_ClientData: //this->LobbyMainData (Protocol_LobbyClientData (p), c); diff --git a/Code/Game/DanBiasGame/GameClientState/GameClientState.h b/Code/Game/DanBiasGame/GameClientState/GameClientState.h index a369233a..378eeefc 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameClientState.h +++ b/Code/Game/DanBiasGame/GameClientState/GameClientState.h @@ -53,6 +53,7 @@ public: { ClientState_Login, ClientState_Lobby, + ClientState_Lan, ClientState_LobbyCreated, ClientState_Game, ClientState_Same, diff --git a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp index fdb02fa9..8df39bfa 100644 --- a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp @@ -5,6 +5,10 @@ #include "C_obj/C_DynamicObj.h" #include "DllInterfaces/GFXAPI.h" +#include "LobbyState.h" +#include "GameState.h" +#include "../GameClientRecieverFunc.h" + #include using namespace DanBias::Client; @@ -16,6 +20,10 @@ struct LanMenuState::myData Oyster::Math3D::Float4x4 proj; C_Object* object[2]; int modelCount; + + GameRecieverObject* recieverObj; + bool serverOwner; + // UI object // game client* }privData; @@ -83,6 +91,49 @@ bool LanMenuState::InitCamera(Oyster::Math::Float3 startPos) } GameClientState::ClientState LanMenuState::Update(float deltaTime, InputClass* KeyInput) +{ + /*ChangeState(KeyInput); + + if(privData->recieverObj->IsConnected()) + privData->recieverObj->Update(); + KeyInput->Update(); + + if(privData->serverOwner) + { + DanBias::GameServerAPI::ServerUpdate(); + } + + DanBias::Client::GameClientState::ClientState state = DanBias::Client::GameClientState::ClientState_Same; + state = privData->recieverObj->gameClientState->Update(deltaTime, KeyInput); + + if(state != Client::GameClientState::ClientState_Same) + { + privData->recieverObj->gameClientState->Release(); + delete privData->recieverObj->gameClientState; + privData->recieverObj->gameClientState = NULL; + + switch (state) + { + case Client::GameClientState::ClientState_LobbyCreated: + privData->serverOwner = true; + case Client::GameClientState::ClientState_Lobby: + privData->recieverObj->gameClientState = new Client::LobbyState(); + break; + case Client::GameClientState::ClientState_Game: + privData->recieverObj->gameClientState = new Client::GameState(); + break; + default: + //return E_FAIL; + break; + } + privData->recieverObj->gameClientState->Init(privData->recieverObj); // send game client + + }*/ + + return ChangeState(KeyInput); +} + +GameClientState::ClientState LanMenuState::ChangeState(InputClass* KeyInput) { // create game if( KeyInput->IsKeyPressed(DIK_C)) diff --git a/Code/Game/DanBiasGame/GameClientState/LanMenuState.h b/Code/Game/DanBiasGame/GameClientState/LanMenuState.h index 5182c80c..6b11fd20 100644 --- a/Code/Game/DanBiasGame/GameClientState/LanMenuState.h +++ b/Code/Game/DanBiasGame/GameClientState/LanMenuState.h @@ -17,6 +17,8 @@ namespace DanBias virtual bool Init(Oyster::Network::NetworkClient* nwClient); virtual ClientState Update(float deltaTime, InputClass* KeyInput); + ClientState ChangeState(InputClass* KeyInput); + bool LoadModels(std::wstring file); bool InitCamera(Oyster::Math::Float3 startPos); diff --git a/Code/Game/GameLogic/Object.h b/Code/Game/GameLogic/Object.h index 44b0ca48..d3a3690f 100644 --- a/Code/Game/GameLogic/Object.h +++ b/Code/Game/GameLogic/Object.h @@ -42,6 +42,7 @@ namespace GameLogic void setAfterCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss)); static Oyster::Physics::ICustomBody::SubscriptMessage DefaultCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj); + static Oyster::Physics::ICustomBody::SubscriptMessage DefaultCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss); private: OBJECT_TYPE type; int objectID; diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 6f164810..5fa3a982 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -26,7 +26,7 @@ namespace ICustomBody::State protoState; proto->GetState( protoState ); ICustomBody::State deuterState; deuter->GetState( deuterState ); - Float4 protoG = protoState.GetLinearMomentum( worldPointOfContact.xyz ), + Float4 protoG = protoState.GetLinearMomentum(worldPointOfContact.xyz ), deuterG = deuterState.GetLinearMomentum( worldPointOfContact.xyz ); // calc from perspective of deuter diff --git a/Code/Misc/EventHandler/EventButton.cpp b/Code/Misc/EventHandler/EventButton.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp new file mode 100644 index 00000000..b3d37bfe --- /dev/null +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -0,0 +1,25 @@ +#include "EventButtonCollection.h" + +using namespace Oyster::Event; + +EventButtonCollection::EventButtonCollection() +{ + +} + +EventButtonCollection::~EventButtonCollection() +{ +} + +void EventButtonCollection::Update(InputClass* inputObject) +{ + for(int i = 0; i < buttons.size(); i++) + { + buttons.at(i)->Update(inputObject); + } +} + +EventButton* EventButtonCollection::AddButton(EventButton* button) +{ + +} \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h new file mode 100644 index 00000000..31201f9c --- /dev/null +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -0,0 +1,31 @@ +#ifndef EVENT_BUTTON_COLLECTION_H +#define EVENT_BUTTON_COLLECTION_H + +#include "../../Input/L_inputClass.h" + +#include "EventButton.h" + +#include + +namespace Oyster +{ + namespace Event + { + class EventButtonCollection + { + public: + EventButtonCollection(); + ~EventButtonCollection(); + + void Update(InputClass* inputObject); + + EventButton* AddButton(EventButton* button); + + private: + std::vector buttons; + + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp new file mode 100644 index 00000000..8f6705df --- /dev/null +++ b/Code/Misc/EventHandler/EventHandler.cpp @@ -0,0 +1,37 @@ +#include "EventHandler.h" + +using namespace Oyster::Event; + +EventHandler EvtHandler; + +EventHandler& EventHandler::Instance() +{ + return EvtHandler; +} + +EventHandler::EventHandler() +{ + +} + +EventHandler::~EventHandler() +{ +} + +void EventHandler::Update(InputClass* inputObject) +{ + for(int i = 0; i < collections.size(); i++) + { + collections.at(i)->Update(inputObject); + } +} + +EventButtonCollection* EventHandler::CreateCollection() +{ + +} + +EventButtonCollection* EventHandler::GetCollection(/*ID*/); +{ + +} \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h new file mode 100644 index 00000000..c3ecc0a2 --- /dev/null +++ b/Code/Misc/EventHandler/EventHandler.h @@ -0,0 +1,35 @@ +#ifndef EVENT_HANDLER_H +#define EVENT_HANDLER_H + +#include "../../Input/L_inputClass.h" + +#include "EventButtonCollection.h" +#include "EventButton.h" + +#include + +namespace Oyster +{ + namespace Event + { + class EventHandler + { + EventHandler(); + ~EventHandler(); + + EventHandler& Instance(); + + void Update(InputClass* inputObject); + + EventButtonCollection* CreateCollection(); + EventButtonCollection* GetCollection(/*ID*/); + + + private: + std::vector collections; + + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index 6c3db1ec..52b7c96c 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -146,6 +146,9 @@ + + + @@ -162,8 +165,11 @@ + + + diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index 8413642a..d4874b4c 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -51,6 +51,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -116,5 +125,14 @@ Header Files + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file From 79872a45eeb1a0bc64213f185a84e92e82379578 Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 14:27:33 +0100 Subject: [PATCH 10/18] SnapAngularAxis fix + added overload compilation error fix + Float3 version --- Code/OysterMath/LinearMath.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index 9ea4bf42..7874cb52 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -750,12 +750,20 @@ namespace LinearAlgebra3D template ::LinearAlgebra::Vector4 & SnapAngularAxis( ::LinearAlgebra::Vector4 &startAngularAxis, const ::LinearAlgebra::Vector4 &localStartNormal, const ::LinearAlgebra::Vector4 &worldEndNormal, ::LinearAlgebra::Vector4 &targetMem = ::LinearAlgebra::Vector4() ) { - ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis), localStartNormal), (ScalarType)0 ); + ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis.xyz), localStartNormal), (ScalarType)0 ); targetMem = ::LinearAlgebra::Vector4( worldStartNormal.xyz.Cross(worldEndNormal.xyz), (ScalarType)0); targetMem *= (ScalarType)::std::acos( worldStartNormal.Dot(worldEndNormal) ); return targetMem += startAngularAxis; } + template + ::LinearAlgebra::Vector3 & SnapAngularAxis( ::LinearAlgebra::Vector3 &startAngularAxis, const ::LinearAlgebra::Vector3 &localStartNormal, const ::LinearAlgebra::Vector3 &worldEndNormal, ::LinearAlgebra::Vector3 &targetMem = ::LinearAlgebra::Vector3() ) + { + return targetMem = SnapAngularAxis( ::LinearAlgebra::Vector4(startAngularAxis, (ScalarType)0), + ::LinearAlgebra::Vector4(localStartNormal, (ScalarType)0), + ::LinearAlgebra::Vector4(worldEndNormal, (ScalarType)0), ).xyz; + } + template ::LinearAlgebra::Matrix4x4 & SnapAxisYToNormal_UsingNlerp( ::LinearAlgebra::Matrix4x4 &rotation, const ::LinearAlgebra::Vector4 &normalizedAxis ) { From 22d0722dfa718b46c33d090daff9098b31588022 Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 14:29:49 +0100 Subject: [PATCH 11/18] SnapAngularFix compilation fix forgot to remove a copy pasted comma --- Code/OysterMath/LinearMath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index 7874cb52..0a4611b1 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -761,7 +761,7 @@ namespace LinearAlgebra3D { return targetMem = SnapAngularAxis( ::LinearAlgebra::Vector4(startAngularAxis, (ScalarType)0), ::LinearAlgebra::Vector4(localStartNormal, (ScalarType)0), - ::LinearAlgebra::Vector4(worldEndNormal, (ScalarType)0), ).xyz; + ::LinearAlgebra::Vector4(worldEndNormal, (ScalarType)0) ).xyz; } template From 2a816469d564d0d49d0750a690db47004cb43880 Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 14:40:09 +0100 Subject: [PATCH 12/18] SnapAngularAxis fix --- Code/OysterMath/LinearMath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index 0a4611b1..dce7a026 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -750,7 +750,7 @@ namespace LinearAlgebra3D template ::LinearAlgebra::Vector4 & SnapAngularAxis( ::LinearAlgebra::Vector4 &startAngularAxis, const ::LinearAlgebra::Vector4 &localStartNormal, const ::LinearAlgebra::Vector4 &worldEndNormal, ::LinearAlgebra::Vector4 &targetMem = ::LinearAlgebra::Vector4() ) { - ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis.xyz), localStartNormal), (ScalarType)0 ); + ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis.xyz), localStartNormal.xyz), (ScalarType)0 ); targetMem = ::LinearAlgebra::Vector4( worldStartNormal.xyz.Cross(worldEndNormal.xyz), (ScalarType)0); targetMem *= (ScalarType)::std::acos( worldStartNormal.Dot(worldEndNormal) ); return targetMem += startAngularAxis; From b3656a052742f100da432e772b7130e50a6f0fba Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 15:15:08 +0100 Subject: [PATCH 13/18] Gravity fix --- Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp | 2 +- Code/GamePhysics/Implementation/SphericalRigidBody.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 30ced129..12c46cd5 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -187,7 +187,7 @@ void API_Impl::Update() if( gravityImpulse != Float4::null ) { state.ApplyLinearImpulse( gravityImpulse.xyz ); - (*proto)->SetGravityNormal( gravityImpulse.GetNormalized().xyz ); + state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); (*proto)->SetState( state ); } diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index 539093db..633997ef 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -105,6 +105,7 @@ void SphericalRigidBody::SetState( const SphericalRigidBody::State &state ) this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic(); this->rigid.SetMass_KeepMomentum( state.GetMass() ); this->rigid.SetMomentOfInertia_KeepMomentum( state.GetMomentOfInertia() ); + this->rigid.gravityNormal = state.GetGravityNormal(); if( state.IsForwarded() ) { From 7b503bcb5233a60a339665beecc3142c601c9796 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Fri, 31 Jan 2014 15:17:09 +0100 Subject: [PATCH 14/18] GL - working with snap --- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 2 +- Code/Game/GameLogic/Object.cpp | 16 ++++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 93fcfba6..8f303cea 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -7,7 +7,7 @@ Game::PlayerData::PlayerData() { //set some stats that are appropriate to a player Oyster::Physics::API::SimpleBodyDescription sbDesc; - sbDesc.centerPosition = Oyster::Math::Float3(10,350,0); + sbDesc.centerPosition = Oyster::Math::Float3(0,320,0); sbDesc.size = Oyster::Math::Float3(4,7,4); sbDesc.mass = 70; //create rigid body diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index e95f95c6..cb3abe49 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -41,7 +41,7 @@ void Level::InitiateLevel(float radius) // add box API::SimpleBodyDescription sbDesc_TestBox; - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,320,0,0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,0); sbDesc_TestBox.ignoreGravity = false; sbDesc_TestBox.mass = 50; sbDesc_TestBox.size = Oyster::Math::Float4(4,4,4,0); diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index 3b8094fb..fc0ac4c4 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -118,18 +118,22 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { + Oyster::Math::Float4 axis; + if(setState.GetGravityNormal()!= Float3::null) + { + Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(setState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, -Oyster::Math::Float4(setState.GetGravityNormal()), axis); + setState.SetRotation(axis.xyz); + + Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); + debug += setState.GetGravityNormal(); + } + this->rigidBody->SetState(this->setState); - } // update physic void Object::EndFrame() { - - Oyster::Math::Float4x4 rotMatrix = setState.GetOrientation(); //Oyster::Math3D::RotationMatrix(rot, axis); - //Oyster::Math3D::SnapAxisYToNormal_UsingNlerp(rotMatrix, -setState.GetGravityNormal()); - //setState.SetOrientation(rotMatrix); - this->getState = this->rigidBody->GetState(); this->setState = this->getState; } From 8f576c9a757d12a708c1e56030fbd2e6672834bd Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 15:30:23 +0100 Subject: [PATCH 15/18] Removed malign obsolete hack fix --- Code/GamePhysics/PhysicsStructs-Impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h index 05cba2da..af2fb91c 100644 --- a/Code/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/GamePhysics/PhysicsStructs-Impl.h @@ -124,7 +124,7 @@ namespace Oyster inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularAxis() const { - return ::Utility::Value::Radian(this->angularAxis); + return this->angularAxis; } inline ::Oyster::Math::Float4x4 CustomBodyState::GetRotation() const From fabf471e76884b0d6b42d77c925ce2c6b6fcf0a3 Mon Sep 17 00:00:00 2001 From: Dander7BD Date: Fri, 31 Jan 2014 15:58:02 +0100 Subject: [PATCH 16/18] Removed malign obsolete hack fix --- Code/GamePhysics/Implementation/SimpleRigidBody.cpp | 2 +- Code/GamePhysics/Implementation/SphericalRigidBody.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index ef3027ee..a2871229 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -128,7 +128,7 @@ SimpleRigidBody::State & SimpleRigidBody::GetState( SimpleRigidBody::State &targ void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) { this->rigid.centerPos = state.GetCenterPosition(); - //this->rigid.SetRotation( state.GetRotation() ); //! HACK: @todo Rotation temporary disabled + this->rigid.axis = state.GetAngularAxis(); this->rigid.boundingReach = state.GetReach(); this->rigid.momentum_Linear = state.GetLinearMomentum(); this->rigid.momentum_Angular = state.GetAngularMomentum(); diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index 633997ef..f6f89c64 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -94,7 +94,7 @@ SphericalRigidBody::State & SphericalRigidBody::GetState( SphericalRigidBody::St void SphericalRigidBody::SetState( const SphericalRigidBody::State &state ) { this->rigid.centerPos = state.GetCenterPosition(); - //this->rigid.SetRotation( state.GetRotation() ); //! HACK: @todo Rotation temporary disabled + this->rigid.axis = state.GetAngularAxis(); this->rigid.boundingReach = state.GetReach(); this->rigid.momentum_Linear = state.GetLinearMomentum(); this->rigid.momentum_Angular = state.GetAngularMomentum(); From e327f64702158fa44ccecbe22f8950962d7e1108 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Fri, 31 Jan 2014 16:33:16 +0100 Subject: [PATCH 17/18] GL - can play with two characters --- Code/Game/DanBiasGame/DanBiasGame_Impl.cpp | 6 ++++++ .../DanBiasGame/GameClientState/GameState.cpp | 19 +++++++++++++++++-- .../DanBiasGame/GameClientState/GameState.h | 3 ++- .../GameClientState/LobbyState.cpp | 3 --- .../GameClientState/LoginState.cpp | 2 +- Code/Game/GameLogic/Game_PlayerData.cpp | 3 ++- Code/Game/GameLogic/Level.cpp | 2 +- Code/Game/GameLogic/Object.cpp | 2 +- .../Implementation/GameSession_Gameplay.cpp | 14 ++++++++------ 9 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index 06f200bf..205f826f 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -157,7 +157,13 @@ namespace DanBias m_data->recieverObj->gameClientState = new Client::LobbyState(); break; case Client::GameClientState::ClientState_Game: + if(m_data->serverOwner) + DanBias::GameServerAPI::GameStart(); m_data->recieverObj->gameClientState = new Client::GameState(); + if(m_data->serverOwner) + ((Client::GameState*)m_data->recieverObj->gameClientState)->setClientId(2); + else + ((Client::GameState*)m_data->recieverObj->gameClientState)->setClientId(3); break; default: return E_FAIL; diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 43b25ba7..cd281717 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -114,6 +114,18 @@ bool GameState::LoadModels(std::wstring mapFile) privData->object.push_back(obj); privData->object[privData->object.size() -1 ]->Init(modelData); + // add player model 2 + modelData.world = Oyster::Math3D::Float4x4::identity; + translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(10, 320, 0)); + + modelData.world = modelData.world * translate; + modelData.visible = true; + modelData.modelPath = L"..\\Content\\Models\\char_white.dan"; + modelData.id = 3; + // load models + obj = new C_Player(); + privData->object.push_back(obj); + privData->object[privData->object.size() -1 ]->Init(modelData); return true; @@ -137,7 +149,10 @@ bool GameState::InitCamera(Oyster::Math::Float3 startPos) privData->view = Oyster::Math3D::InverseOrientationMatrix(privData->view); return true; } - +void GameState::setClientId(int id) +{ + myId = id; +} GameClientState::ClientState GameState::Update(float deltaTime, InputClass* KeyInput) { switch (privData->state) @@ -344,7 +359,7 @@ void GameState::Protocol( ObjPos* pos ) //camera->setRight((Oyster::Math::Float3(world[0], world[1], world[2]))); //camera->setUp((Oyster::Math::Float3(world[4], world[5], world[6]))); //camera->setLook((Oyster::Math::Float3(world[8], world[9], world[10]))); - if(i == 2) // playerobj + if(i == myId) // playerobj { camera->SetPosition(Oyster::Math::Float3(world[12], world[13]+2.2f, world[14]-1)); camera->UpdateViewMatrix(); diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.h b/Code/Game/DanBiasGame/GameClientState/GameState.h index f8f1b67b..04d5b791 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.h +++ b/Code/Game/DanBiasGame/GameClientState/GameState.h @@ -26,6 +26,7 @@ private: bool key_Jump; Camera* camera; + int myId; struct myData; myData* privData; public: @@ -36,7 +37,7 @@ public: bool LoadModels(std::wstring mapFile) ; bool InitCamera(Oyster::Math::Float3 startPos) ; gameStateState LoadGame(); - + void setClientId(int id); void readKeyInput(InputClass* KeyInput); bool Render()override; bool Release()override; diff --git a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp index 35a5f295..538408c5 100644 --- a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp @@ -87,12 +87,9 @@ GameClientState::ClientState LobbyState::Update(float deltaTime, InputClass* Key // update animation // send data to server // check data from server - if( KeyInput->IsKeyPressed(DIK_G)) { - if(!DanBias::GameServerAPI::GameStart()) - return GameClientState::ClientState_Same; return ClientState_Game; } diff --git a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp index 4d1079bc..9beb6657 100644 --- a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp @@ -109,7 +109,7 @@ GameClientState::ClientState LoginState::Update(float deltaTime, InputClass* Key if( KeyInput->IsKeyPressed(DIK_J)) { // game ip - nwClient->Connect(15151, "193.11.184.109"); + nwClient->Connect(15151, "127.0.0.1"); if (!nwClient->IsConnected()) { diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 8f303cea..e19af2f3 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -7,9 +7,10 @@ Game::PlayerData::PlayerData() { //set some stats that are appropriate to a player Oyster::Physics::API::SimpleBodyDescription sbDesc; - sbDesc.centerPosition = Oyster::Math::Float3(0,320,0); + sbDesc.centerPosition = Oyster::Math::Float3(0,308,0); sbDesc.size = Oyster::Math::Float3(4,7,4); sbDesc.mass = 70; + sbDesc.restitutionCoeff = 0.5; //create rigid body Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index cb3abe49..50737eb9 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -32,7 +32,7 @@ void Level::InitiateLevel(float radius) ICustomBody::State state; rigidBody->GetState(state); - state.SetRestitutionCoeff(0.01); + state.SetRestitutionCoeff(0.2); rigidBody->SetState(state); levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index fc0ac4c4..a0823247 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -123,7 +123,7 @@ void Object::BeginFrame() { Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(setState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, -Oyster::Math::Float4(setState.GetGravityNormal()), axis); setState.SetRotation(axis.xyz); - + setState.SetAngularMomentum(Float3::null); Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); debug += setState.GetGravityNormal(); } diff --git a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp index c0041301..8235c903 100644 --- a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp +++ b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp @@ -86,12 +86,14 @@ namespace DanBias if(dynamic_cast (movedObject)) { IPlayerData* temp = (IPlayerData*)movedObject; - temp->GetID(); + + int id = temp->GetID(); Oyster::Math::Float4x4 world = temp->GetOrientation(); - Protocol_ObjectPosition p(world, 2); + Protocol_ObjectPosition p(world, id); GameSession::gameSession->Send(*p.GetProtocol()); } + GameLogic::IObjectData* obj = NULL; if(dynamic_cast(movedObject)) { @@ -100,10 +102,10 @@ namespace DanBias { if(obj->GetObjectType() == OBJECT_TYPE_WORLD) { - obj->GetID(); + int id = obj->GetID(); Oyster::Math::Float4x4 world =obj->GetOrientation(); - Protocol_ObjectPosition p(world, 0); + Protocol_ObjectPosition p(world, id); GameSession::gameSession->Send(*p.GetProtocol()); } } @@ -114,9 +116,9 @@ namespace DanBias { if(obj->GetObjectType() == OBJECT_TYPE_BOX) { - obj->GetID(); + int id = obj->GetID(); Oyster::Math::Float4x4 world = obj->GetOrientation(); - Protocol_ObjectPosition p(world, 1); + Protocol_ObjectPosition p(world, id); GameSession::gameSession->Send(*p.GetProtocol()); } } From 83ca3c2ff23525ca29fbd4c365ae4242c2962600 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Fri, 31 Jan 2014 16:43:18 +0100 Subject: [PATCH 18/18] GL - remove buttons from GL branch --- Code/Misc/EventHandler/EventButton.cpp | 0 Code/Misc/EventHandler/EventButton.h | 0 .../EventHandler/EventButtonCollection.cpp | 25 ------------- .../Misc/EventHandler/EventButtonCollection.h | 31 ---------------- Code/Misc/EventHandler/EventHandler.cpp | 37 ------------------- Code/Misc/EventHandler/EventHandler.h | 35 ------------------ 6 files changed, 128 deletions(-) delete mode 100644 Code/Misc/EventHandler/EventButton.cpp delete mode 100644 Code/Misc/EventHandler/EventButton.h delete mode 100644 Code/Misc/EventHandler/EventButtonCollection.cpp delete mode 100644 Code/Misc/EventHandler/EventButtonCollection.h delete mode 100644 Code/Misc/EventHandler/EventHandler.cpp delete mode 100644 Code/Misc/EventHandler/EventHandler.h diff --git a/Code/Misc/EventHandler/EventButton.cpp b/Code/Misc/EventHandler/EventButton.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h deleted file mode 100644 index e69de29b..00000000 diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp deleted file mode 100644 index b3d37bfe..00000000 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "EventButtonCollection.h" - -using namespace Oyster::Event; - -EventButtonCollection::EventButtonCollection() -{ - -} - -EventButtonCollection::~EventButtonCollection() -{ -} - -void EventButtonCollection::Update(InputClass* inputObject) -{ - for(int i = 0; i < buttons.size(); i++) - { - buttons.at(i)->Update(inputObject); - } -} - -EventButton* EventButtonCollection::AddButton(EventButton* button) -{ - -} \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h deleted file mode 100644 index 31201f9c..00000000 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef EVENT_BUTTON_COLLECTION_H -#define EVENT_BUTTON_COLLECTION_H - -#include "../../Input/L_inputClass.h" - -#include "EventButton.h" - -#include - -namespace Oyster -{ - namespace Event - { - class EventButtonCollection - { - public: - EventButtonCollection(); - ~EventButtonCollection(); - - void Update(InputClass* inputObject); - - EventButton* AddButton(EventButton* button); - - private: - std::vector buttons; - - }; - } -} - -#endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp deleted file mode 100644 index 8f6705df..00000000 --- a/Code/Misc/EventHandler/EventHandler.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "EventHandler.h" - -using namespace Oyster::Event; - -EventHandler EvtHandler; - -EventHandler& EventHandler::Instance() -{ - return EvtHandler; -} - -EventHandler::EventHandler() -{ - -} - -EventHandler::~EventHandler() -{ -} - -void EventHandler::Update(InputClass* inputObject) -{ - for(int i = 0; i < collections.size(); i++) - { - collections.at(i)->Update(inputObject); - } -} - -EventButtonCollection* EventHandler::CreateCollection() -{ - -} - -EventButtonCollection* EventHandler::GetCollection(/*ID*/); -{ - -} \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h deleted file mode 100644 index c3ecc0a2..00000000 --- a/Code/Misc/EventHandler/EventHandler.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef EVENT_HANDLER_H -#define EVENT_HANDLER_H - -#include "../../Input/L_inputClass.h" - -#include "EventButtonCollection.h" -#include "EventButton.h" - -#include - -namespace Oyster -{ - namespace Event - { - class EventHandler - { - EventHandler(); - ~EventHandler(); - - EventHandler& Instance(); - - void Update(InputClass* inputObject); - - EventButtonCollection* CreateCollection(); - EventButtonCollection* GetCollection(/*ID*/); - - - private: - std::vector collections; - - }; - } -} - -#endif \ No newline at end of file