Soren Rogiers

Game developer

Imperial Rule - Graphics programming Direct X


Imperial Rule is a game made in C++, using the DAE custom made engine "Overlord Engine".

The goal of the game was to escort your battletank to the evacuation point while destroying enemies in the way. There are health packs and fuel packs for you to pick up if you run low on resources.

In the video you can see all the necessary requirements that you had to implement in the engine and game.

Video


Code snippets


									
//**************
//ENEMY MANAGER
//**************
#pragma once
#include "Scenegraph/GameObject.h"
#include "CourseObjects/GameFiles/Scene/ExamScene.h"

class Player;
class Enemy_Base;

class EnemyManager : public GameObject
{
public:
	enum EnemyType
	{
		ENEMY_BATTLE_DROID,
		ENEMY_SUPER_BATTLE_DROID
	};

	EnemyManager(Player* pPlayer);
	virtual ~EnemyManager();

	Enemy_Base* CreateEnemy(const EnemyType enemyType, const XMFLOAT3& position = {});

	virtual void Initialize(const GameContext& gameContext)override;
	virtual void Update(const GameContext& gameContext)override;
	virtual void Draw(const GameContext& gameContext)override;

private:
	Player* m_pPlayer;
	std::vectorm_pEnemyList;

	Enemy_Base* GetEnemy(const unsigned int index) const;
private:
	EnemyManager(const EnemyManager& em);
	EnemyManager& operator=(const EnemyManager& em);
};

//**************
//ENEMY MANAGER
//**************
EnemyManager::EnemyManager(Player* pPlayer) : m_pPlayer(pPlayer)
{
}

EnemyManager::~EnemyManager()
{
	for (unsigned int i = 0; i < m_pEnemyList.size(); ++i)
	{
		m_pEnemyList[i] = nullptr;
		delete m_pEnemyList[i];
	}
	m_pEnemyList.clear();
}

Enemy_Base* EnemyManager::CreateEnemy(const EnemyType enemyType, const XMFLOAT3& position)
{
	Enemy_Base* enemy = nullptr;

	switch(enemyType)
	{
	case EnemyType::ENEMY_BATTLE_DROID:
		enemy = new Enemy_BattleDroid(m_pPlayer, 7.5f, 33.f);
		break;
	case EnemyType::ENEMY_SUPER_BATTLE_DROID:
		enemy = new Enemy_SuperBattleDroid(m_pPlayer, 8.f, 32.f);
		break;
	default:
		return enemy;
	}

	if (enemy)
	{
		m_pEnemyList.push_back(enemy);
		enemy->GetTransform()->Translate(position.x,enemy->GetHeight()/2,position.z);
		AddChild(enemy);
	}

	return enemy;
}

void EnemyManager::Initialize(const GameContext& gameContext)
{
	UNREFERENCED_PARAMETER(gameContext);
}

void EnemyManager::Update(const GameContext& gameContext)
{
	UNREFERENCED_PARAMETER(gameContext);

	for (unsigned int i = 0; i < m_pEnemyList.size(); ++i)
	{
		if (m_pEnemyList[i] != nullptr)
		{
			if (m_pEnemyList[i]->IsDead())
			{
				XMFLOAT3 pos = m_pEnemyList[i]->GetTransform()->GetPosition();
				XMFLOAT3 newPos = { pos.x, pos.y - 500.0f, pos.z };
				m_pEnemyList[i]->GetTransform()->Translate(newPos);
				//m_pEnemyList[i]->RemoveComponent(GetComponent());
				//RemoveChild(m_pEnemyList[i]);
				//SafeDelete(m_pEnemyList[i]);
			}
		}
	}
}

void EnemyManager::Draw(const GameContext& gameContext)
{
	UNREFERENCED_PARAMETER(gameContext);
}

Enemy_Base* EnemyManager::GetEnemy(const unsigned index) const
{
	return m_pEnemyList[index];
}

//************
//PLAYER CLASS
//************
Player::Player(float radius, float height, float moveSpeed):
m_Radius(radius),
m_Height(height),
m_MoveSpeed(moveSpeed),
m_pController(nullptr),
m_pCamera(nullptr),
m_Health(100),
m_Damage(50),
m_RotationSpeed(100.f),
m_CameraDistance(200.f),
m_RotationY(0),
m_FireRange(250.f),
m_MaxRunVelocity(150.0f),
m_TerminalVelocity(20),
m_Gravity(9.81f),
m_RunAccelerationTime(1.0f),
m_JumpAccelerationTime(0.8f),
m_RunAcceleration(m_MaxRunVelocity / m_RunAccelerationTime),
m_JumpAcceleration(m_Gravity / m_JumpAccelerationTime),
m_RunVelocity(0.f),
m_JumpVelocity(0.f),
m_ShootAnimationTimer(0.f),
m_ShootAnimationDelay(.75f),
m_IsShooting(false),
m_IsDead(false),
m_Velocity(0.f, 0.f, 0.f),
m_CharacterState(CharacterState::Idle),
m_ParticleVelocity(0, 0, 300),
m_pParticleEmitter(nullptr),
m_pModelcomponent(nullptr),
m_pGun(nullptr)
{
	SetTag(L"Player");
}


Player::~Player()
{
}

void Player::AddHealth(int health)
{
	m_Health += health;
	if (m_Health > MAX_HEALTH)
		m_Health = MAX_HEALTH;
}

void Player::TakeDamage(const int damage)
{
	m_Health -= damage;

	if (m_Health < 0)
	{
		m_IsDead = true;
		m_Health = 0;
	}
}

void Player::Initialize(const GameContext& gameContext)
{
	auto physX = PhysxManager::GetInstance()->GetPhysics();
	auto pDefaultMaterial = physX->createMaterial(.5f, .5f, .1f);

	this->GetTransform()->Translate(-800.f, 0.f, -750.f);

	//CREATE PARTICLE
	//***************
	m_pParticleEmitter = new ParticleEmitterComponent(L"./Resources/Textures/GameTextures/Rayside_Sprite_Tex.png", 1);

	m_pParticleEmitter->SetMinSize(17.5f);
	m_pParticleEmitter->SetMaxSize(17.5f);
	m_pParticleEmitter->SetMinEnergy(1.f);
	m_pParticleEmitter->SetMaxEnergy(1.f);
	m_pParticleEmitter->SetMinEmitterRange(.1f);
	m_pParticleEmitter->SetMaxEmitterRange(.1f);
	m_pParticleEmitter->SetColor(XMFLOAT4(Colors::Blue));
	m_pParticleEmitter->SetMaxSizeGrow(1.f);
	m_pParticleEmitter->SetMinSizeGrow(1.f);
	m_pParticleEmitter->StopEmitting(true);
	AddComponent(m_pParticleEmitter);
	
	//ADD GUN
	//*******
	m_pGun = new GameObject();
	m_pGun->GetTransform()->Translate(0, 1.f, 10.f);
	AddChild(m_pGun);

	//CREATE CHARACTER CONTROLLER
	//***************************
	m_pController = new ControllerComponent(pDefaultMaterial, m_Radius, m_Height,L"Player");
	AddComponent(m_pController);

	//ATTACH CAMERA
	//*************
	auto fixedCam = new FixedCamera();
	m_pCamera = fixedCam->GetComponent();
	AddChild(fixedCam);

	//TEXTURE
	//*******
	auto pDiffuseMaterial = new SkinnedDiffuseMaterial();
	pDiffuseMaterial->SetDiffuseTexture(L"./Resources/Textures/GameTextures/Player/Stormtrooper_Tex.dds");
	
	if (gameContext.pMaterialManager->GetMaterial(MaterialManager::MyMaterials::PLAYER) == nullptr)
		gameContext.pMaterialManager->AddMaterial(pDiffuseMaterial, MaterialManager::MyMaterials::PLAYER);
	else
		SafeDelete(pDiffuseMaterial);

	//MESH
	//****
	m_pModelcomponent = new ModelComponent(L"./Resources/Meshes/GameMeshes/PlayerAnimated_Mesh.ovm");
	m_pModelcomponent->SetMaterial(MaterialManager::MyMaterials::PLAYER);
	auto pObj = new GameObject();
	pObj->AddComponent(m_pModelcomponent);
	AddChild(pObj);
	pObj->GetTransform()->Translate(0,- m_Height/1.5f, 0);
	pObj->GetTransform()->Scale(2.3f, 2.3f, 2.3f);
	pObj->GetTransform()->Rotate(0.f, 180.f, 0.f);

	//INPUT
	//*****
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::FORWARD, InputTriggerState::Down, 'W'));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::BACKWARD, InputTriggerState::Down, 'S'));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::TURN_LEFT, InputTriggerState::Down, 'A'));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::TURN_RIGHT, InputTriggerState::Down, 'D'));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::SHOOT, InputTriggerState::Pressed, 0,VK_LBUTTON));
	//Additional arrow keys
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::UP, InputTriggerState::Down, VK_UP));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::DOWN, InputTriggerState::Down, VK_DOWN));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::LEFT, InputTriggerState::Down, VK_LEFT));
	gameContext.pInput->AddInputAction(InputAction(CharacterMovement::RIGHT, InputTriggerState::Down, VK_RIGHT));
	//Keep, just in case
	//gameContext.pInput->AddInputAction(InputAction(CharacterMovement::LEFT, InputTriggerState::Down, 'A'));
	//gameContext.pInput->AddInputAction(InputAction(CharacterMovement::RIGHT, InputTriggerState::Down, 'D'));
}

void Player::PostInitialize(const GameContext& gameContext)
{
	UNREFERENCED_PARAMETER(gameContext);
	
	// Set the camera as active
	// We need to do this in the PostInitialize because child game objects only get initialized after the Initialize of the current object finishes
	FixedCamera* pFixedCam = GetChild();
	pFixedCam->GetTransform()->Translate(0, 150.f, 225*-1);
	pFixedCam->GetTransform()->Rotate(20.0f, 0.0f, 0.0);
	GetScene()->SetActiveCamera(pFixedCam->GetComponent());

	m_pModelcomponent->GetAnimator()->SetAnimation(2);
}

void Player::Update(const GameContext& gameContext)
{
	if(!m_IsDead)
	{
		//If we're shooting lock other movement
		//so we stay in this animation
		if(m_IsShooting)
		{
			m_ShootAnimationTimer += gameContext.pGameTime->GetElapsed();

		} else
		{
			Rotate(gameContext);
			MovePlayer(gameContext);
		}

		if(m_ShootAnimationTimer > m_ShootAnimationDelay)
		{
			m_pParticleEmitter->StopEmitting(true);
			m_ShootAnimationTimer = 0;
			m_IsShooting = false;
		} else
		{
			Shoot(gameContext);
		}
		//Play animations depending on state
		//**********************************
		auto animator = m_pModelcomponent->GetAnimator();
		if(animator)
		{
			switch (m_CharacterState)
			{
			case CharacterState::WALKING:
			{
				if (animator->GetClipName() != L"Walking")
					animator->SetAnimation(0);

				break;
			}
			case CharacterState::Idle:
			{
				if (animator->GetClipName() != L"Idle")
					animator->SetAnimation(2);

				break;
			}
			case CharacterState::SHOOTING:
			{
				if (animator->GetClipName() != L"Shooting")
					animator->SetAnimation(1);
				break;
			}
			default:
			{
				if (animator->GetClipName() != L"Walking")
					animator->SetAnimation(0);
			}
			}
			animator->Play();
		}
		
	}
}

void Player::MovePlayer(const GameContext& gameContext)
{
	//MOVING PLAYER
	//*************
	XMFLOAT2 move = XMFLOAT2(0, 0);

	if(gameContext.pInput->IsActionTriggered(CharacterMovement::FORWARD) || gameContext.pInput->IsActionTriggered(CharacterMovement::UP))
	{
		move.y = 1.0f;
	} else
	{
		move.y = 0.f;
	}

	//move.y = gameContext.pInput->IsActionTriggered(CharacterMovement::FORWARD) ? 1.0f : 0.0f;
	//move.y = gameContext.pInput->IsActionTriggered(CharacterMovement::UP) ? 1.0f : 0.0f;

	if (move.y == 0)
	{
		if (gameContext.pInput->IsActionTriggered(CharacterMovement::BACKWARD) || gameContext.pInput->IsActionTriggered(CharacterMovement::DOWN))
		{
			move.y = -1.0f;
		}
		else
		{
			move.y = 0.f;
		}

		//move.y = -(gameContext.pInput->IsActionTriggered(CharacterMovement::BACKWARD) ? 1.0f : 0.0f);
		//move.y = -(gameContext.pInput->IsActionTriggered(CharacterMovement::DOWN) ? 1.0f : 0.0f);
	}

	XMFLOAT3 forward = GetChild()->GetTransform()->GetForward();
	XMFLOAT3 right = GetChild()->GetTransform()->GetRight();

	if (move.x != 0 || move.y != 0)
	{
		m_CharacterState = WALKING;
		m_RunVelocity += m_RunAcceleration * gameContext.pGameTime->GetElapsed();

		if (m_RunVelocity >= m_MaxRunVelocity)
		{
			m_RunVelocity = m_MaxRunVelocity;
		}

		m_Velocity = XMFLOAT3(m_RunVelocity * (forward.x * (move.y)) + m_RunVelocity * (right.x * (move.x)), 0, m_RunVelocity * (forward.z * (move.y)) + m_RunVelocity * (right.z * (move.x)));
	}
	else
	{
		//if we stand still reset to 0
		m_Velocity.x = 0;
		m_Velocity.z = 0;
		m_CharacterState = Idle;
	}

	//APPLY GRAVITY
	//*************
	if (m_pController->GetCollisionFlags() != PxControllerCollisionFlag::eCOLLISION_DOWN)
	{
		m_JumpVelocity -= m_JumpAcceleration * gameContext.pGameTime->GetElapsed();
		if (m_JumpVelocity >= m_TerminalVelocity)
		{
			m_JumpVelocity = m_TerminalVelocity;
		}
	}
	else
	{
		m_Velocity.y = 0;
	}

	m_Velocity.y += m_JumpVelocity;

	//MOVE
	//****
	XMFLOAT3 movement = m_Velocity;
	movement.x *= gameContext.pGameTime->GetElapsed();
	movement.y *= gameContext.pGameTime->GetElapsed();
	movement.z *= gameContext.pGameTime->GetElapsed();

	m_pController->Move(movement);
}

void Player::Rotate(const GameContext& gameContext)
{
	//ROTATING PLAYER
	//***************
	if (gameContext.pInput->IsActionTriggered(CharacterMovement::TURN_LEFT) || gameContext.pInput->IsActionTriggered(CharacterMovement::LEFT))
	{
		m_RotationY -= (m_RotationSpeed * gameContext.pGameTime->GetElapsed());
		this->GetTransform()->Rotate(0, m_RotationY, 0);
	}
	else if (gameContext.pInput->IsActionTriggered(CharacterMovement::TURN_RIGHT) || gameContext.pInput->IsActionTriggered(CharacterMovement::RIGHT))
	{
		m_RotationY += (m_RotationSpeed * gameContext.pGameTime->GetElapsed());
		this->GetTransform()->Rotate(0, m_RotationY, 0);
	}

}

void Player::Shoot(const GameContext& gameContext)
{
	if(gameContext.pInput->IsActionTriggered(CharacterMovement::SHOOT))
	{
		//Cheat animation
		m_CharacterState = SHOOTING;
		m_IsShooting = true;

		XMFLOAT3 direction = m_pGun->GetTransform()->GetForward();
		XMFLOAT3 startPosition = m_pGun->GetTransform()->GetWorldPosition();

		//Raycast to check
		PxVec3 rayStart = PxVec3(startPosition.x, startPosition.y, startPosition.z);
		PxVec3 rayDir = PxVec3(direction.x, direction.y, direction.z);
		PxRaycastBuffer hit;

		Enemy_Base* enemyHit = nullptr;

		if (GetScene()->GetPhysxProxy()->Raycast(rayStart, rayDir, m_FireRange, hit, PxHitFlag::eDEFAULT))
		{
			if (reinterpret_cast(hit.block.actor->userData)->GetGameObject()->GetTag() == L"Enemy")
			{
				//Get the gameobject
				GameObject* pObjectHit = reinterpret_cast(hit.block.actor->userData)->GetGameObject();
				//Deal damage to the enemy hit
				enemyHit = static_cast(pObjectHit);
				enemyHit->TakeDamage(m_Damage);

			}
		}

		//SHOOT PARTICLE
		//**************
		m_pParticleEmitter->StopEmitting(false);
		m_pParticleEmitter->SetVelocity(m_ParticleVelocity);		
	}
}

//***************
//PICKUP MANAGER
//***************
#pragma once
#include "Scenegraph/GameObject.h"
#include "Pickup_Base.h"

class Player;
class ImperialTank;

class PickupManager : public GameObject
{
public:
	PickupManager(Player* pPlayer,ImperialTank* pTank);
	virtual ~PickupManager();

	enum PickupType
	{
		PICKUP_HEALTH,
		PICKUP_FUEL
	};

	Pickup_Base* CreatePickup(const PickupType type, const XMFLOAT3& position, const float respawnTime = -1);

protected:
	virtual void Initialize(const GameContext& gameContext)override;
	virtual void Update(const GameContext& gameContext) override;

private:
	static PickupManager* m_pInstance;

	Player* m_pPlayer;
	ImperialTank* m_pImperialTank;

	std::vector m_PickupList;

private:
	// -------------------------
	// Disabling default copy constructor and default 
	// assignment operator.
	// -------------------------
	PickupManager(const PickupManager& pm) = delete;
	PickupManager& operator=(const PickupManager& pm) = delete;
};

//***************
//PICKUP MANAGER
//***************
#include "stdafx.h"
#include "PickupManager.h"
#include "Components/Components.h"
#include "Pickup_Health.h"
#include "Pickup_Fuel.h"

PickupManager* PickupManager::m_pInstance = nullptr;

PickupManager::PickupManager(Player* pPlayer, ImperialTank* pTank) : GameObject()
,m_pPlayer(pPlayer)
,m_pImperialTank(pTank)
{

}


PickupManager::~PickupManager()
{
}

Pickup_Base* PickupManager::CreatePickup(const PickupType type, const XMFLOAT3& position, const float respawnTime)
{
	Pickup_Base* temp = nullptr;

	switch (type)
	{
	case PickupType::PICKUP_HEALTH:
		temp = new Pickup_Health(m_pPlayer, position, L"HealthPack_Mesh", L"Healthpack_Diffuse_Tex.png", L"HealthPack_Mesh", MaterialManager::MyMaterials::PICKUP_HEALTH, respawnTime);
		break;
	case PickupType::PICKUP_FUEL:
		temp = new Pickup_Fuel(m_pImperialTank, position, L"Fuel_Mesh", L"Fuel_Diffuse_Tex.png", L"Fuel_Mesh", MaterialManager::MyMaterials::PICKUP_FUEL, respawnTime);
		break;
	default:
		return temp;
	}

	if (temp)
		AddChild(temp);
	return temp;
}

void PickupManager::Initialize(const GameContext& gameContext)
{
	UNREFERENCED_PARAMETER(gameContext);
}

void PickupManager::Update(const GameContext& gameContext)
{
	UNREFERENCED_PARAMETER(gameContext);
}

								
							

Screenshots


Go back