From e45b01ba4a9cf25d5733b4ed839c713a7b22ff2d Mon Sep 17 00:00:00 2001 From: "lapayo94@gmail.com" Date: Sat, 24 Dec 2011 01:36:15 +0000 Subject: Very alpha water physic for pickups (The swim now) but there are some problems (get stuck on some positions) so someone might look at it because I have no idea how to make it better :D git-svn-id: http://mc-server.googlecode.com/svn/trunk@102 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cPickup.cpp | 60 +++++++++++++++++++++++++++--- source/cPickup.h | 4 ++ source/cWaterSimulator.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++- source/cWaterSimulator.h | 18 +++++++++ 4 files changed, 168 insertions(+), 6 deletions(-) diff --git a/source/cPickup.cpp b/source/cPickup.cpp index db409c637..7b6e9e1d1 100644 --- a/source/cPickup.cpp +++ b/source/cPickup.cpp @@ -6,6 +6,7 @@ #include "cClientHandle.h" #include "cInventory.h" #include "cWorld.h" +#include "cWaterSimulator.h" #include "cServer.h" #include "cPlayer.h" #include "cPluginManager.h" @@ -28,11 +29,15 @@ cPickup::~cPickup() { delete m_Item; delete m_Speed; + delete m_ResultingSpeed; + delete m_WaterSpeed; } cPickup::cPickup(int a_X, int a_Y, int a_Z, const cItem & a_Item, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */) : cEntity( ((double)(a_X))/32, ((double)(a_Y))/32, ((double)(a_Z))/32 ) , m_Speed( new Vector3f( a_SpeedX, a_SpeedY, a_SpeedZ ) ) + , m_ResultingSpeed(new Vector3f()) + , m_WaterSpeed(new Vector3f()) , m_bOnGround( false ) , m_bReplicated( false ) , m_Timer( 0.f ) @@ -63,6 +68,8 @@ cPickup::cPickup(int a_X, int a_Y, int a_Z, const cItem & a_Item, float a_SpeedX cPickup::cPickup(cPacket_PickupSpawn* a_PickupSpawnPacket) : cEntity( ((double)a_PickupSpawnPacket->m_PosX)/32, ((double)a_PickupSpawnPacket->m_PosY)/32, ((double)a_PickupSpawnPacket->m_PosZ)/32 ) , m_Speed( new Vector3f() ) + , m_ResultingSpeed(new Vector3f()) + , m_WaterSpeed(new Vector3f()) , m_bOnGround( false ) , m_bReplicated( false ) , m_Timer( 0.f ) @@ -149,9 +156,11 @@ void cPickup::Tick(float a_Dt) void cPickup::HandlePhysics(float a_Dt) { + m_ResultingSpeed->Set(0.f, 0.f, 0.f); + cWorld* World = GetWorld(); + if( m_bOnGround ) // check if it's still on the ground { - cWorld* World = GetWorld(); int BlockX = (m_Pos->x)<0 ? (int)m_Pos->x-1 : (int)m_Pos->x; int BlockZ = (m_Pos->z)<0 ? (int)m_Pos->z-1 : (int)m_Pos->z; char BlockBelow = World->GetBlock( BlockX, (int)m_Pos->y -1, BlockZ ); @@ -179,18 +188,55 @@ void cPickup::HandlePhysics(float a_Dt) if( fabs(m_Speed->z) < 0.05 ) m_Speed->z = 0; } + + //get flowing direction + Direction WaterDir = World->GetWaterSimulator()->GetFlowingDirection((int) m_Pos->x - 1, (int) m_Pos->y, (int) m_Pos->z - 1); + + + *m_WaterSpeed *= 0.9; //Keep old speed but lower it + + switch(WaterDir) + { + case X_PLUS: + m_WaterSpeed->x = 1.f; + m_bOnGround = false; + break; + case X_MINUS: + m_WaterSpeed->x = -1.f; + m_bOnGround = false; + break; + case Z_PLUS: + m_WaterSpeed->z = 1.f; + m_bOnGround = false; + break; + case Z_MINUS: + m_WaterSpeed->z = -1.f; + m_bOnGround = false; + break; + + default: + break; + } + + *m_ResultingSpeed += *m_WaterSpeed; + + if( !m_bOnGround ) { float Gravity = -9.81f*a_Dt; m_Speed->y += Gravity; + // Set to hit position + *m_ResultingSpeed += *m_Speed; + cTracer Tracer( GetWorld() ); int Ret = Tracer.Trace( *m_Pos, *m_Speed, 2 ); if( Ret ) // Oh noez! we hit something { - // Set to hit position - if( (*Tracer.RealHit - Vector3f(*m_Pos)).SqrLength() <= ( *m_Speed * a_Dt ).SqrLength() ) + + + if( (*Tracer.RealHit - Vector3f(*m_Pos)).SqrLength() <= ( *m_ResultingSpeed * a_Dt ).SqrLength() ) { m_bReplicated = false; // It's only interesting to replicate when we actually hit something... if( Ret == 1 ) @@ -210,15 +256,19 @@ void cPickup::HandlePhysics(float a_Dt) } else - *m_Pos += *m_Speed*a_Dt; + *m_Pos += *m_ResultingSpeed*a_Dt; } else { // We didn't hit anything, so move =] - *m_Pos += *m_Speed*a_Dt; + *m_Pos += *m_ResultingSpeed * a_Dt; } } + //Usable for debugging + //SetPosition(m_Pos->x, m_Pos->y, m_Pos->z); + + } bool cPickup::CollectedBy( cPlayer* a_Dest ) diff --git a/source/cPickup.h b/source/cPickup.h index cad766e42..fead89447 100644 --- a/source/cPickup.h +++ b/source/cPickup.h @@ -2,6 +2,7 @@ #include "cEntity.h" + class cPacket_PickupSpawn; class cPlayer; class cItem; @@ -23,6 +24,9 @@ public: void HandlePhysics(float a_Dt); private: Vector3f* m_Speed; + Vector3f* m_ResultingSpeed; //Can be used to modify the resulting speed for the current tick ;) + + Vector3f* m_WaterSpeed; bool m_bOnGround; bool m_bReplicated; diff --git a/source/cWaterSimulator.cpp b/source/cWaterSimulator.cpp index 888ff69c4..9b41e42b9 100644 --- a/source/cWaterSimulator.cpp +++ b/source/cWaterSimulator.cpp @@ -2,6 +2,7 @@ #include "cWorld.h" #include "Vector3i.h" #include "BlockID.h" +#include "Defines.h" #include class cWaterSimulator::WaterData @@ -39,7 +40,7 @@ public: LowerPoints[i].y = a_Y; Points.push_back( LowerPoints[i] ); } - else if( (Block2 == E_BLOCK_WATER || Block2 == E_BLOCK_STATIONARY_WATER ) && ( Block1 == E_BLOCK_AIR || Block1 == E_BLOCK_WATER || Block1 == E_BLOCK_STATIONARY_WATER ) ) + else if( IsBlockWater(Block2) && ( Block1 == E_BLOCK_AIR || IsBlockWater(Block1) ) ) { bWaterFound = true; } @@ -127,6 +128,9 @@ void cWaterSimulator::Simulate( float a_Dt ) { m_Timer += a_Dt; + if(m_Data->m_ActiveWater->empty()) //Nothing to do if there is no ActiveWater ;) saves very little time ;D + return; + std::swap( m_Data->m_ActiveWater, m_Data->m_Buffer ); // Swap so blocks can be added to empty ActiveWater array m_Data->m_ActiveWater->clear(); @@ -213,4 +217,90 @@ void cWaterSimulator::Simulate( float a_Dt ) bool cWaterSimulator::IsWaterBlock( char a_BlockID ) { return a_BlockID == E_BLOCK_WATER || a_BlockID == E_BLOCK_STATIONARY_WATER; +} + +//TODO Not working very well yet :s +Direction cWaterSimulator::GetFlowingDirection(int a_X, int a_Y, int a_Z, bool a_Over) +{ + char BlockID = m_World->GetBlock(a_X, a_Y, a_Z); + if(!IsBlockWater(BlockID)) //No Water -> No Flowing direction :D + return NONE; + + + /* + Disabled because of causing problems and beeing useless atm + char BlockBelow = m_World->GetBlock(a_X, a_Y - 1, a_Z); //If there is nothing or water below it -> dominating flow is down :D + if(BlockBelow == E_BLOCK_AIR || IsBlockWater(BlockBelow)) + return Y_MINUS; + */ + + char LowestPoint = m_World->GetBlockMeta(a_X, a_Y, a_Z); //Current Block Meta so only lower points will be counted + int X, Y, Z; //Lowest Pos will be stored here + + if(IsBlockWater(m_World->GetBlock(a_X, a_Y + 1, a_Z)) && a_Over) //check for upper block to flow because this also affects the flowing direction + { + return GetFlowingDirection(a_X, a_Y + 1, a_Z, false); + } + + std::vector< Vector3i * > Points; + + //add blocks around the checking pos + Points.push_back(new Vector3i(a_X - 1, a_Y, a_Z)); + Points.push_back(new Vector3i(a_X + 1, a_Y, a_Z)); + Points.push_back(new Vector3i(a_X, a_Y, a_Z + 1)); + Points.push_back(new Vector3i(a_X, a_Y, a_Z - 1)); + + for(std::vector::iterator it = Points.begin(); it < Points.end(); it++) + { + Vector3i *Pos = (*it); + char BlockID = m_World->GetBlock(Pos->x, Pos->y, Pos->z); + if(IsBlockWater(BlockID)) + { + char Meta = m_World->GetBlockMeta(Pos->x, Pos->y, Pos->z); + + if(Meta > LowestPoint) + { + LowestPoint = Meta; + X = Pos->x; + Y = Pos->y; + Z = Pos->z; + } + }else if(BlockID == E_BLOCK_AIR) + { + LowestPoint = 9; //This always dominates + X = Pos->x; + Y = Pos->y; + Z = Pos->z; + + } + delete Pos; + } + + + if(LowestPoint == m_World->GetBlockMeta(a_X, a_Y, a_Z)) + return NONE; + + if(a_X - X > 0) + { + return X_MINUS; + } + + if(a_X - X < 0) + { + return X_PLUS; + } + + if(a_Z - Z > 0) + { + return Z_MINUS; + } + + if(a_Z - Z < 0) + { + return Z_PLUS; + } + + return NONE; + + } \ No newline at end of file diff --git a/source/cWaterSimulator.h b/source/cWaterSimulator.h index 1e45256f8..5962cd83e 100644 --- a/source/cWaterSimulator.h +++ b/source/cWaterSimulator.h @@ -1,5 +1,18 @@ #pragma once + +//TODO This definitly needs a better naming :D but how? +enum Direction +{ + X_PLUS, + X_MINUS, + Y_PLUS, + Y_MINUS, + Z_PLUS, + Z_MINUS, + NONE +}; + class Vector3i; class cWorld; class cWaterSimulator @@ -11,6 +24,9 @@ public: void Simulate( float a_Dt ); void WakeUp( int a_X, int a_Y, int a_Z ); + //Gets the flowing direction of a Waterblock if a_Over is true also the block over the current block affects the direction (standard) + Direction GetFlowingDirection(int a_X, int a_Y, int a_Z, bool a_Over = true); + private: void AddBlock( int a_X, int a_Y, int a_Z); char GetHighestLevelAround( int a_X, int a_Y, int a_Z ); @@ -22,4 +38,6 @@ private: class WaterData; WaterData* m_Data; + + }; \ No newline at end of file -- cgit v1.2.3