Danbias/Code/Game/GameLogic/Level.cpp

475 lines
16 KiB
C++
Raw Normal View History

2013-11-19 11:07:14 +01:00
#include "Level.h"
2014-01-20 15:47:52 +01:00
#include "CollisionManager.h"
#include "Game.h"
2014-02-14 10:32:41 +01:00
#include "JumpPad.h"
#include "ExplosiveCrate.h"
#include "Portal.h"
#include <Resource\OResource.h>
//Conversion from wstring to string
#include <codecvt>
2013-11-19 11:07:14 +01:00
using namespace GameLogic;
using namespace Utility::DynamicMemory;
2014-01-16 11:40:29 +01:00
using namespace Oyster::Physics;
using namespace Oyster::Math;
2013-12-05 11:50:39 +01:00
2013-11-19 11:07:14 +01:00
Level::Level(void)
{
2014-02-14 10:32:41 +01:00
objID = 100;
2013-11-19 11:07:14 +01:00
}
Level::~Level(void)
{
2014-02-10 13:25:28 +01:00
delete this->levelObj;
this->levelObj = NULL;
2013-11-19 11:07:14 +01:00
}
Object* Level::CreateGameObj(ObjectHeader* obj, ICustomBody* rigidBody)
{
2014-02-14 11:07:03 +01:00
Object* gameObj = NULL;
2014-02-14 10:32:41 +01:00
switch ((ObjectSpecialType)obj->specialTypeID)
{
case ObjectSpecialType_None:
{
2014-02-19 11:09:37 +01:00
gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
2014-02-14 10:32:41 +01:00
}
break;
case ObjectSpecialType_Sky:
{
float skySize = ((SkyAttributes*)obj)->skySize;
2014-02-19 11:09:37 +01:00
//gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_World:
{
API::Instance().SetGravityPoint(Oyster::Math3D::Float3(0,0,0));
API::Instance().SetGravity(200); // could balance gravitation with the world size
float worldSize = ((WorldAttributes*)obj)->worldSize;
float atmosphereSize = ((WorldAttributes*)obj)->atmoSphereSize;
2014-02-19 11:09:37 +01:00
gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_Building:
{
2014-02-19 11:09:37 +01:00
gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_Stone:
{
2014-02-25 10:37:33 +01:00
gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
2014-02-14 10:08:29 +01:00
case ObjectSpecialType_StandardBox:
{
2014-02-25 10:37:33 +01:00
gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_RedExplosiveBox:
{
Oyster::Math::Float dmg = 120;
Oyster::Math::Float force = 500;
Oyster::Math::Float radie = 3;
2014-02-14 11:11:49 +01:00
gameObj = new ExplosiveCrate(rigidBody, (ObjectSpecialType)obj->specialTypeID, objID++, dmg, force, radie);
}
break;
//case ObjectSpecialType_BlueExplosiveBox:
// int dmg = 70;
// gameObj = new ExplosiveBox(rigidBody, ObjectSpecialType_BlueExplosiveBox);
// break;
case ObjectSpecialType_SpikeBox:
{
2014-02-25 10:37:33 +01:00
gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_Spike:
{
2014-02-25 10:37:33 +01:00
gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_CrystalFormation:
{
int dmg = 50;
//gameObj = new Crystal(rigidBody);
2014-02-19 11:09:37 +01:00
gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_CrystalShard:
{
2014-02-25 10:37:33 +01:00
gameObj = new DynamicObject(rigidBody, DynamicObject::DynamicDefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
case ObjectSpecialType_JumpPad:
{
2014-02-14 13:54:28 +01:00
float power = 500; //((JumpPadAttributes*)obj)->power;
Oyster::Math::Float3 dir = ((JumpPadAttributes*)obj)->direction;
2014-02-14 11:07:03 +01:00
Oyster::Math::Float3 pushForce = dir * power;
2014-02-19 10:55:59 +01:00
gameObj = new JumpPad(rigidBody, (ObjectSpecialType)obj->specialTypeID, objID , pushForce);
}
break;
case ObjectSpecialType_Portal:
{
Oyster::Math::Float3 destination = ((PortalAttributes*)obj)->destination;
2014-02-19 10:55:59 +01:00
gameObj = new Portal(rigidBody, (ObjectSpecialType)obj->specialTypeID, objID, destination);
}
break;
2014-02-14 15:36:19 +01:00
//case ObjectSpecialType_SpawnPoint:
//{
2014-02-14 10:32:41 +01:00
// save
2014-02-14 13:09:55 +01:00
2014-02-14 15:36:19 +01:00
//}
break;
case ObjectSpecialType_Player:
{
2014-02-14 10:32:41 +01:00
// should not be read from the lvl format
}
break;
case ObjectSpecialType_Generic:
{
2014-02-19 11:09:37 +01:00
gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
default:
{
2014-02-19 11:09:37 +01:00
gameObj = new StaticObject(rigidBody, Object::DefaultOnCollision, (ObjectSpecialType)obj->specialTypeID, objID);
}
break;
}
return gameObj;
}
ICustomBody* Level::InitRigidBodyCube( const ObjectHeader* obj)
{
ICustomBody* rigidBody = NULL;
Oyster::Math::Float3 rigidWorldPos;
Oyster::Math::Float4 rigidWorldRotation;
float rigidBodyMass;
Oyster::Math::Float3 rigidBodySize;
//offset the rigidPosition from modelspace to worldspace;
rigidWorldPos = (Oyster::Math::Float3)obj->position + (Oyster::Math::Float3)obj->boundingVolume.box.position;
2014-02-14 10:09:03 +01:00
//scales the position so the collision geomentry is in the right place
rigidWorldPos = rigidWorldPos * obj->scale;
//offset the rigidRotation from modelspace to worldspace;
Oyster::Math::Quaternion worldPosQuaternion = Oyster::Math::Quaternion(Oyster::Math::Float3(obj->rotation[0],obj->rotation[1],obj->rotation[2]), obj->rotation[3]);
Oyster::Math::Quaternion physicsPosQuaternion = Oyster::Math::Quaternion(Oyster::Math::Float3(obj->boundingVolume.sphere.rotation[0],obj->boundingVolume.sphere.rotation[1],obj->boundingVolume.sphere.rotation[2]), obj->boundingVolume.sphere.rotation[3]);
Oyster::Math::Quaternion rigidWorldQuaternion = worldPosQuaternion * physicsPosQuaternion;
rigidWorldRotation = Oyster::Math::Float4(rigidWorldQuaternion);
//mass scaled
rigidBodyMass = obj->scale[0] * obj->scale[1] * obj->scale[2] * obj->boundingVolume.box.mass;
//size scaled
rigidBodySize = (Oyster::Math::Float3)obj->boundingVolume.box.size * (Oyster::Math::Float3)obj->scale;
//create the rigid body
rigidBody = API::Instance().AddCollisionBox(rigidBodySize , rigidWorldRotation , rigidWorldPos , rigidBodyMass, obj->boundingVolume.box.restitutionCoeff , obj->boundingVolume.box.frictionCoeffStatic , obj->boundingVolume.box.frictionCoeffDynamic);
return rigidBody;
}
ICustomBody* Level::InitRigidBodySphere( const ObjectHeader* obj)
{
ICustomBody* rigidBody = NULL;
Oyster::Math::Float3 rigidWorldPos;
Oyster::Math::Float4 rigidWorldRotation;
float rigidBodyMass;
float rigidBodyRadius;
//offset the rigidPosition from modelspace to worldspace;
rigidWorldPos = (Oyster::Math::Float3)obj->position + (Oyster::Math::Float3)obj->boundingVolume.sphere.position;
//scales the position so the collision geomentry is in the right place
rigidWorldPos = rigidWorldPos * obj->scale;
//offset the rigidRotation from modelspace to worldspace;
Oyster::Math::Quaternion worldPosQuaternion = Oyster::Math::Quaternion(Oyster::Math::Float3(obj->rotation[0],obj->rotation[1],obj->rotation[2]), obj->rotation[3]);
Oyster::Math::Quaternion physicsPosQuaternion = Oyster::Math::Quaternion(Oyster::Math::Float3(obj->boundingVolume.sphere.rotation[0],obj->boundingVolume.sphere.rotation[1],obj->boundingVolume.sphere.rotation[2]), obj->boundingVolume.sphere.rotation[3]);
Oyster::Math::Quaternion rigidWorldQuaternion = worldPosQuaternion * physicsPosQuaternion;
rigidWorldRotation = Oyster::Math::Float4(rigidWorldQuaternion);
//mass scaled
rigidBodyMass = obj->scale[0] * obj->scale[1] * obj->scale[2] * obj->boundingVolume.sphere.mass;
//Radius scaled
2014-02-20 09:21:38 +01:00
rigidBodyRadius = (obj->scale[0]) * obj->boundingVolume.sphere.radius;
//rigidBodyRadius = (obj->scale[0] * obj->scale[1] * obj->scale[2]) * obj->boundingVolume.sphere.radius;
//create the rigid body
rigidBody = API::Instance().AddCollisionSphere( rigidBodyRadius , rigidWorldRotation , rigidWorldPos , rigidBodyMass, obj->boundingVolume.sphere.restitutionCoeff , obj->boundingVolume.sphere.frictionCoeffStatic , obj->boundingVolume.sphere.frictionCoeffDynamic);
return rigidBody;
}
bool Level::InitiateLevel(std::wstring levelPath)
{
LevelLoader ll;
ll.SetFolderPath("..\\Content\\Worlds\\");
std::vector<Utility::DynamicMemory::SmartPointer<ObjectTypeHeader>> objects;
//Convert from wstring to string
typedef std::codecvt_utf8<wchar_t> convert_typeX;
2014-02-19 15:57:52 +01:00
std::wstring_convert<convert_typeX, wchar_t> converterX;
std::string convertedLevelPath = converterX.to_bytes(levelPath);
objects = ll.LoadLevel(convertedLevelPath);
if(objects.size() == 0)
return false;
API::Instance().SetGravityPoint(Oyster::Math3D::Float3(0,0,0));
API::Instance().SetGravity(200);
2014-02-19 15:57:52 +01:00
int objCount = (int)objects.size();
for (int i = 0; i < objCount; i++)
{
2014-02-19 10:55:59 +01:00
++this->objID;
ObjectTypeHeader* obj = objects.at(i);
switch (obj->typeID)
{
case ObjectType::ObjectType_LevelMetaData:
{
LevelMetaData* LevelObjData = ((LevelMetaData*)obj);
std::string levelName = LevelObjData->levelName;
// LevelObjData->worldSize;
}
break;
case ObjectType::ObjectType_Static:
{
ObjectHeader* staticObjData = ((ObjectHeader*)obj);
staticObjData->ModelFile;
2014-02-12 14:48:58 +01:00
ICustomBody* rigidBody_Static = NULL;
2014-02-19 10:55:59 +01:00
2014-02-11 09:17:16 +01:00
// collision shape
if(staticObjData->boundingVolume.geoType == CollisionGeometryType_Sphere)
2014-02-12 14:48:58 +01:00
{
rigidBody_Static = InitRigidBodySphere(staticObjData);
2014-02-12 14:48:58 +01:00
}
else if(staticObjData->boundingVolume.geoType == CollisionGeometryType_Box)
{
2014-02-14 10:09:03 +01:00
rigidBody_Static = InitRigidBodyCube(staticObjData);
2014-02-12 14:48:58 +01:00
}
else if(staticObjData->boundingVolume.geoType == CollisionGeometryType_Cylinder)
{
//rigidBody_Static = InitRigidBodyCylinder(staticObjData);
2014-02-12 14:48:58 +01:00
}
if(rigidBody_Static != NULL)
{
// create game object
Object* staticGameObj = CreateGameObj(staticObjData, rigidBody_Static);
if(staticGameObj != NULL)
{
this->staticObjects.Push((StaticObject*)staticGameObj);
}
2014-02-12 14:48:58 +01:00
}
}
break;
case ObjectType::ObjectType_Dynamic:
{
2014-02-12 14:48:58 +01:00
ObjectHeader* dynamicObjData = ((ObjectHeader*)obj);
dynamicObjData->ModelFile;
2014-02-12 14:48:58 +01:00
ICustomBody* rigidBody_Dynamic = NULL;
2014-02-12 14:48:58 +01:00
// collision shape
if(dynamicObjData->boundingVolume.geoType == CollisionGeometryType_Sphere)
{
rigidBody_Dynamic = InitRigidBodySphere(dynamicObjData);
2014-02-12 14:48:58 +01:00
}
else if(dynamicObjData->boundingVolume.geoType == CollisionGeometryType_Box)
{
rigidBody_Dynamic = InitRigidBodyCube(dynamicObjData);
2014-02-12 14:48:58 +01:00
}
else if(dynamicObjData->boundingVolume.geoType == CollisionGeometryType_Cylinder)
{
//rigidBody_Dynamic = InitRigidBodyCylinder(dynamicObjData);
2014-02-12 14:48:58 +01:00
}
if(rigidBody_Dynamic != NULL)
{
// create game object
Object* dynamicGameObj = CreateGameObj(dynamicObjData, rigidBody_Dynamic);
if (dynamicGameObj != NULL)
{
dynamicGameObj->GetRigidBody()->SetSubscription(Level::PhysicsOnMoveLevel);
this->dynamicObjects.Push((DynamicObject*)dynamicGameObj);
}
2014-02-12 14:48:58 +01:00
}
}
break;
case ObjectType::ObjectType_Light:
// read on client
break;
case ObjectType::ObjectType_SpawnPoint:
{
Oyster::Math::Float3 pos;
pos.x = ((SpawnPointAttributes*)obj)->position[0];
pos.y = ((SpawnPointAttributes*)obj)->position[1];
pos.z = ((SpawnPointAttributes*)obj)->position[2];
spawnPoints.Push(pos);
}
default:
break;
}
}
return true;
2014-01-16 11:40:29 +01:00
}
bool Level::InitiateLevel(float radius)
2014-01-16 11:40:29 +01:00
{
2014-02-11 13:41:38 +01:00
API::Instance().SetGravityPoint(Oyster::Math3D::Float3(0,0,0));
2014-02-12 11:36:08 +01:00
API::Instance().SetGravity(200);
2014-02-05 15:16:31 +01:00
int idCount = 100;
// add level sphere
2014-02-10 15:54:38 +01:00
ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f);
2014-02-12 14:48:58 +01:00
levelObj = new StaticObject(rigidBody, LevelCollisionAfter, ObjectSpecialType_World, idCount++);
2014-02-12 14:48:58 +01:00
//this->levelObj->objectID = idCount++;
rigidBody->SetCustomTag(levelObj);
2014-02-03 10:42:40 +01:00
ICustomBody* rigidBody_TestBox;
int nrOfBoxex = 5;
2014-02-05 15:54:48 +01:00
int offset = 0;
for(int i =0; i< nrOfBoxex; i ++)
{
2014-02-18 13:47:40 +01:00
rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0.0f, 0.0f, 0.0f, 1.0f), Oyster::Math::Float3(0.0f, 605.0f + i*5.0f, 10.0f), 5.0f, 0.5f, 0.8f, 0.6f);
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox, Object::DefaultOnCollision, ObjectSpecialType_StandardBox, idCount++));
}
2014-02-10 12:42:31 +01:00
/*offset += nrOfBoxex;
2014-02-05 15:54:48 +01:00
for(int i =0; i< nrOfBoxex; i ++)
{
2014-02-09 21:24:09 +01:00
rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0,5, -605 -( i*5)), 5);
2014-02-05 15:54:48 +01:00
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultOnCollision, OBJECT_TYPE::OBJECT_TYPE_BOX));
2014-02-05 15:54:48 +01:00
rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]);
2014-02-09 21:24:09 +01:00
2014-02-05 15:54:48 +01:00
}
offset += nrOfBoxex;
for(int i =0; i< nrOfBoxex; i ++)
{
2014-02-09 21:24:09 +01:00
rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(200, 620 + ( i*7), 0), 5);
2014-02-05 15:54:48 +01:00
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultOnCollision, OBJECT_TYPE::OBJECT_TYPE_BOX));
2014-02-09 21:24:09 +01:00
rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]);
2014-02-05 15:54:48 +01:00
}
offset += nrOfBoxex;
for(int i =0; i< nrOfBoxex; i ++)
{
2014-02-09 21:24:09 +01:00
rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(5, 605 + i*5, 0), 5);
2014-02-05 15:54:48 +01:00
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultOnCollision, OBJECT_TYPE::OBJECT_TYPE_BOX));
2014-02-06 21:15:28 +01:00
rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i]);
2014-02-09 21:24:09 +01:00
2014-02-10 12:42:31 +01:00
}*/
// add crystal
2014-02-18 13:47:40 +01:00
ICustomBody* rigidBody_Crystal = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0.0f, 0.0f, 0.0f, 1.0f), Oyster::Math::Float3(10.0f, 605.0f, 0.0f), 5.0f, 0.5f, 0.8f, 0.6f);
this->dynamicObjects.Push(new DynamicObject(rigidBody_Crystal, Object::DefaultOnCollision, ObjectSpecialType_StandardBox, idCount++));
// add house
2014-02-18 13:47:40 +01:00
ICustomBody* rigidBody_House =API::Instance().AddCollisionBox(Oyster::Math::Float3(20.0f, 20.0f, 20.0f), Oyster::Math::Float4(0.0f, 0.0f, 0.0f, 1.0f), Oyster::Math::Float3(-50.0f, 590.0f, 0.0f), 0.0f, 0.5f, 0.8f, 0.6f);
this->staticObjects.Push(new StaticObject(rigidBody_House, Object::DefaultOnCollision, ObjectSpecialType_Generic, idCount++));
2014-02-12 13:37:21 +01:00
// add jumppad
2014-02-18 13:47:40 +01:00
ICustomBody* rigidBody_Jumppad = API::Instance().AddCollisionBox(Oyster::Math::Float3(1.0f, 1.0f, 1.0f), Oyster::Math::Float4(0.0f, 0.0f, 0.0f, 1.0f), Oyster::Math::Float3(4.0f, 600.3f, 0.0f), 5.0f, 0.5f, 0.8f, 0.6f);
this->staticObjects.Push(new JumpPad(rigidBody_Jumppad, ObjectSpecialType_JumpPad,idCount++ ,Oyster::Math::Float3(0,2000,0)));
return true;
}
void Level::AddPlayerToTeam(Player *player, int teamID)
{
2014-01-20 15:47:52 +01:00
this->teamManager.AddPlayerToTeam(player,teamID);
}
void Level::AddPlayerToGame(Player *player)
{
this->playerObjects.Push(player);
}
void Level::RemovePlayerFromGame(Player *player)
{
for(int i = 0; i < (int)this->playerObjects.Size(); i++)
{
if ((Player*)this->playerObjects[i] == player)
{
//this->playerObjects[i].
}
}
}
void Level::CreateTeam(int teamSize)
{
2014-01-20 15:47:52 +01:00
this->teamManager.CreateTeam(teamSize);
}
void Level::RespawnPlayer(Player *player)
{
//this->teamManager.RespawnPlayerRandom(player);
Float3 spawnPoint = spawnPoints[0];
player->Respawn(spawnPoint);
}
void Level::Update(float deltaTime)
{
// update lvl-things
for(int i = 0; i < (int)this->playerObjects.Size(); i++)
{
if (this->playerObjects[i]->GetState() == PLAYER_STATE::PLAYER_STATE_DEAD)
{
// true when timer reaches 0
if(this->playerObjects[i]->deathTimerTick(deltaTime))
RespawnPlayer(this->playerObjects[i]);
}
else if (this->playerObjects[i]->GetState() == PLAYER_STATE::PLAYER_STATE_DIED)
{
this->playerObjects[i]->setDeathTimer(DEATH_TIMER);
// HACK to avoid crasch. affected by tag is NULL
((Game*)&Game::Instance())->onDeadFnc(this->playerObjects[i], this->playerObjects[i], DEATH_TIMER); // add killer ID
//((Game*)&Game::Instance())->onDeadFnc(this->playerObjects[i], this->playerObjects[i]->getAffectingPlayer(), DEATH_TIMER); // add killer ID
}
}
}
int Level::getNrOfDynamicObj()
{
return this->dynamicObjects.Size();
}
Object* Level::GetObj( int ID) const
{
2014-02-18 13:47:40 +01:00
for (int i = 0; i < (int)this->dynamicObjects.Size(); i++)
{
if(this->dynamicObjects[i]->GetID() == ID)
return this->dynamicObjects[i];
}
return NULL;
}
void Level::PhysicsOnMoveLevel(const ICustomBody *object)
{
// function call from physics update when object was moved
Object* temp = (Object*)object->GetCustomTag();
((Game*)&Game::Instance())->onMoveFnc(temp);
}
Utility::DynamicMemory::DynamicArray<Utility::DynamicMemory::SmartPointer<Player>> Level::GetPlayers()
{
return this->playerObjects;
}
Utility::DynamicMemory::DynamicArray<Utility::DynamicMemory::SmartPointer<StaticObject>> Level::GetStaticObjects()
{
return this->staticObjects;
}
Utility::DynamicMemory::DynamicArray<Utility::DynamicMemory::SmartPointer<DynamicObject>> Level::GetDynamicObject()
{
return this->dynamicObjects;
}