Project Description

Description

Light em up was a group project of 13 students. The team was divided as programmers, artists and designers. Light em up is about a fish that emits light and is armed with weapons to shoot his enemy.

My Tasks on this project:
– Creating a hit shader, Which made an enemy colored red when hit.
– The AI for the Mechanical BossPiranha.
– The AI for the regular Enemies.

Details

  • Type: Game, Group Project
  • Tech: C++, Ogre3D
  • Duration: ~16 Weeks 1 day a week
  • Status: Finished

Code

#ifndef _BOSSPIRANHA_
#define _BOSSPIRANHA_
#include "./Creature.h"

class Player;
class BossPiranha : public Creature
{
	public:
		// Constructor
		BossPiranha();
		// Deconstructor
		~BossPiranha();
		// Initialises the BossPiranha
		virtual void Initialize(Ogre::Vector3 pos);
		// Updates the BossPiranha
		virtual void Update(float dt);
		// Resets the BossPiranha
		virtual void Reset();
		// Shoots bullets or explodes
		virtual void Shoot();

private:
	void StartUp(float dt);
	void AttackLaser(float dt);
	void AttackCharge(float dt);
	void AttackPowerball(float dt);
	void JawOpens(float dt);
	void JawClose(float dt);
	void Shield(float dt);
	void CockpitOpen(float dt);
	void CockpitClose(float dt);
	void Delay(float dt);
	void NextBehavior(float dt);
	void ChangeBehavior(float dt);
	void Hit(float damage, Ogre::Vector3 hitPosition);
	void Dead(float dt);
	void Dance(float dt);
	void BehaviorHit(float dt);
	void ChangeColor();

	void SetAnimation(int state, bool loop);

	Player* m_Player;
	int   m_Stage;
	int   m_State;
	int   m_Behavior;
	int   m_NextState;
	float m_Delay;
	bool  m_AnimationPlaying;
	bool  m_AttackDone;
	bool  m_CanReceiveDamage;

	int m_StateDetail;

	float m_ShootCountDown;
	int   m_BulletsToShoot;
	int   m_BulletsShot;
	float m_BulletShootSpeed;
	float m_BulletShootCountDown;

	bool m_IsDancing;

	float m_AnimationChanger;

	Ogre::String  m_MatName;

	Ogre::AnimationState* m_Anim;
};
#endif
#include "../../GamePlayDefines.h"
#include "./BossPiranha.h"
#include "../../../GameMain/GameMain.h"
#include "../CollisionShapePool.h"
#include "Player.h"
#include "OgreMath.h"
#include "OgreSubMesh.h"
#include "OgreSubEntity.h"
#include "../../../OISInput/InputManager.h"

/*--------------------------------------------------------------------------*/
namespace BossState
{
	enum
	{
		STARTUP = 0,
		IDLE,
		DELAY,
		ATTACKLASER,
		ATTACKCHARGE,
		ATTACKPOWERBALL,
		JAWOPENS,
		JAWCLOSE,
		COCKPITOPEN,
		COCKPITCLOSE,
		SHIELD,
		BEHAVIORHIT, 
		FULLDEAD,
		DEAD,
		DANCESTART,
		DANCE,
		HIGH,
		MID,
		LOW
	};
};
/*--------------------------------------------------------------------------*/
BossPiranha::BossPiranha() : Creature(ObjectType::BOSSPIRANHA)
{
	//If there is no shape for this projectile
	if(gGameMain->GetCollisionShapePool()->GetShapeFor(ObjectType::BOSSPIRANHA)==NULL)
	{
		//Create shape for this projectile
		gGameMain->GetCollisionShapePool()->CreateShapeFor(ObjectType::BOSSPIRANHA,gGameMain->GetWorldPhysics()->CreateBoxShape(Ogre::Vector3(10,10,10)));
	}
	m_Model.LoadModel("piranhaBoss.mesh", 5);

	GetNode()->scale(Ogre::Vector3(2.0f));

	m_Position = Ogre::Vector3(1,0,0);

	assert(gGameMain->GetCollisionShapePool()->GetShapeFor(ObjectType::BOSSPIRANHA));
	InitializeKinematicObject(gGameMain->GetCollisionShapePool()->GetShapeFor(ObjectType::BOSSPIRANHA)
							,m_Position,1,ObjectCollisionTypes::ENEMY,COLL_MASK_FOR_ENEMY);
	SetActive(false);

	m_AnimationChanger = 1.0f;

}
/*--------------------------------------------------------------------------*/
BossPiranha::~BossPiranha()
{
}
/*--------------------------------------------------------------------------*/
void BossPiranha::Initialize(Ogre::Vector3 pos)
{
	m_Position = pos;
	m_Player = gGameMain->GetPlayer();
	if(!m_Active)
	{
		SetActive(true);
	}
	
	m_health = BOSSPIRANHA_START_HEALTH;
	m_damage = BOSSPIRANHA_DAMAGE;

	m_MatName = m_Model.mEntities[0]->getSubEntity(1)->getMaterialName();
	m_NormalMaterial = static_cast(Ogre::MaterialManager::getSingleton().getByName(m_MatName) );
	m_HitMaterial =    static_cast(Ogre::MaterialManager::getSingleton().getByName("enemy_hit") );

	m_Model.mEntities[0]->getSubEntity(20)->setMaterialName("ball_green");

	m_collisionDamage = BOSSPIRANHA_COLLISION_DAMAGE;

	m_ShootCountDown = BOSSPIRANHA_SHOOT_WAIT_TIME * 1000;
	m_BulletsToShoot = 0;
	m_BulletsShot    = 0;
	m_BulletShootSpeed = 0;
	m_BulletShootCountDown = 0;
	m_healthRegained = 20;

	m_Delay = -10;

	m_AnimationPlaying = false;
	m_AttackDone       = false;

	m_CanReceiveDamage = true;
	m_damage = BOSSPIRANHA_DAMAGE;

	m_State = BossState::STARTUP;
	m_Behavior = BossState::HIGH;
	m_NextState = BossState::IDLE;

	m_AnimationChanger = 1.0f;

	m_Anim = NULL;
	SetAnimation(BossState::IDLE, true);

	m_IsDancing = false;
	m_Stage = 0;
	m_StateDetail = 0;

	m_lightRadius = 0.1f;
	m_lightColor = 0xFF00FF00;
}
/*--------------------------------------------------------------------------*/
void BossPiranha::Update(float dt)
{
	if(m_IsHit)
	{
		m_CurrentHitTime+= dt;
		if(m_CurrentHitTime > ENEMY_LIGHT_HIT_TIME)
		{
			m_IsHit = false;
			m_Model.mEntities[0]->setMaterial(m_NormalMaterial);
			ChangeColor();
		}
	}

	if(m_health > 0)
	{
		m_Anim->addTime(dt * 0.0015f);
	}
	else
	{
		m_Anim->addTime(dt * 0.0010f);
	}
	

	if(m_Delay >= -1.0f){ Delay(dt); return;}

	if(m_Player->IsDead())
	{
		Dance(dt);
	}

	if(m_State == BossState::STARTUP)			{	StartUp(dt);		}else
	if(m_State == BossState::COCKPITCLOSE)		{	CockpitClose(dt);	}else
	if(m_State == BossState::COCKPITOPEN)		{	CockpitOpen(dt);	}else
	if(m_State == BossState::JAWOPENS)			{ 	JawOpens(dt);		}else
	if(m_State == BossState::JAWCLOSE)			{   JawClose(dt);		}else
	if(m_State == BossState::SHIELD)			{   Shield(dt);			}else
	if(m_State == BossState::ATTACKCHARGE)		{   AttackCharge(dt);   }else
	if(m_State == BossState::ATTACKLASER)		{   AttackLaser(dt);    }else
	if(m_State == BossState::ATTACKPOWERBALL)   {   AttackPowerball(dt);}else
	if(m_State == BossState::BEHAVIORHIT)		{   BehaviorHit(dt);    }else
	if(m_State == BossState::DEAD)				{   Dead(dt);			}else

	if(m_State == BossState::DELAY)				{   m_State = BossState::IDLE; }else
	if(m_State == BossState::IDLE)				{	NextBehavior(dt);   }else

	if(m_CanReceiveDamage)
	{
		float differenceY = (m_Position.y - gGameMain->GetCameraPosition().y);
		m_Position.y += -(differenceY / BOSSPIRANHA_MOVEMENT_Y_DAMPING) * dt;
	}

	SetKinematicBodyPosition(m_Position);
}
/*--------------------------------------------------------------------------*/
void BossPiranha::Shoot()
{

}
/*--------------------------------------------------------------------------*/
void BossPiranha::Reset()
{

}
/*--------------------------------------------------------------------------*/
void BossPiranha::StartUp(float dt)
{
	Ogre::Vector3 targetpos = Ogre::Vector3((gGameMain->GetCameraPosition().x + BOSSPIRANHA_SCREEN_RIGHT_POSITION), gGameMain->GetCameraPosition().y, m_Player->GetPosition().z); 

	if(m_Position.squaredDistance(targetpos) <= 10) 	{ 		NextBehavior(dt);  	} 	float diff = (m_Position.x - (gGameMain->GetCameraPosition().x + BOSSPIRANHA_SCREEN_RIGHT_POSITION));
	m_Position.x += -(diff / BOSSPIRANHA_STARTUP_DAMPING) * dt;

	float differenceY = (m_Position.y - gGameMain->GetCameraPosition().y);
	m_Position.y += -(differenceY / BOSSPIRANHA_MOVEMENT_Y_DAMPING) * dt;
}
/*--------------------------------------------------------------------------*/
void BossPiranha::AttackLaser(float dt)
{
	if(m_BulletShootCountDown < 0) 	{ 		m_BulletShootCountDown = BOSSPIRANHA_LASER_COUNTDOWN; 		gGameMain->BossPiranhaShoot(m_Position - Ogre::Vector3(10, 10, 10), Ogre::Vector3(-1, 1, 0).normalisedCopy()); // Up Left
		gGameMain->BossPiranhaShoot(m_Position - Ogre::Vector3(10, 10, 10), Ogre::Vector3(-1, 0, 0)); // left
		gGameMain->BossPiranhaShoot(m_Position - Ogre::Vector3(10, 10, 10), Ogre::Vector3(-1,-1, 0).normalisedCopy()); // down left
		m_BulletsShot++;
		if(m_BulletsShot >= m_BulletsToShoot)
		{
			m_BulletsShot = 0;
			m_BulletsToShoot = 0;
			m_BulletShootCountDown = 0;
			NextBehavior(dt);
		}
	}
	else
	{
		m_BulletShootCountDown -= dt;
	}
}
/*--------------------------------------------------------------------------*/
void BossPiranha::AttackCharge(float dt)
{
	if(!m_AttackDone)
	{
		float diff = (m_Position.x - (gGameMain->GetCameraPosition().x - BOSSPIRANHA_SCREEN_LEFT_POSITION) );
		m_Position.x += -(diff / BOSSPIRANHA_ATTACK_DAMPING) * dt;
		if(m_Position.x <= (gGameMain->GetCameraPosition().x - BOSSPIRANHA_SCREEN_LEFT_POSITION) + 15.0f)
		{
			if(m_Anim->hasEnded())
			{
				m_AttackDone = true;
				SetAnimation(BossState::IDLE, true);
			}
		}
	}
	else
	{
		float diff = (m_Position.x - (gGameMain->GetCameraPosition().x + BOSSPIRANHA_SCREEN_RIGHT_POSITION));
		m_Position.x += -(diff / BOSSPIRANHA_ATTACK_DAMPING) * dt;
		if(m_Position.x >= (gGameMain->GetCameraPosition().x + BOSSPIRANHA_SCREEN_RIGHT_POSITION-1.5f))
		{
			m_AttackDone = false;
			NextBehavior(dt);
		}
	}
}
/*--------------------------------------------------------------------------*/
void BossPiranha::AttackPowerball(float dt)
{
	gGameMain->BossPiranhaPowerballShoot(Ogre::Vector3(m_Position.x - 35, m_Position.y -8, m_Position.z), Ogre::Vector3(-5, 0, 0));
	NextBehavior(dt);
}
/*--------------------------------------------------------------------------*/
void BossPiranha::JawOpens(float dt)
{
	if(!m_AnimationPlaying)
	{
		printf("Jaw Opens \n");
		m_AnimationPlaying = true;
	}
	else
	{
			NextBehavior(dt);
	}
}
/*--------------------------------------------------------------------------*/
void BossPiranha::JawClose(float dt)
{
	if(!m_AnimationPlaying)
	{
		printf("Jaw Close \n");
		m_AnimationPlaying = true;
	}
	else
	{
			NextBehavior(dt);
	}
}
/*--------------------------------------------------------------------------*/
void BossPiranha::CockpitOpen(float dt)
{
	if(!m_AnimationPlaying)
	{
		printf("Cockpit Open\n");
		m_AnimationPlaying = true;
	}
	else
	{
		NextBehavior(dt);
	}
}
/*--------------------------------------------------------------------------*/
void BossPiranha::CockpitClose(float dt)
{
	if(!m_AnimationPlaying)
	{
		printf("Cockpit Close\n");
		m_AnimationPlaying = true;
	}
	else
	{
			NextBehavior(dt);
	}
}
/*--------------------------------------------------------------------------*/
void BossPiranha::Shield( float dt )
{
	NextBehavior(dt);
}
/*--------------------------------------------------------------------------*/
void BossPiranha::Delay(float dt)
{
	m_Delay-= dt;
	if(m_Delay <= 0) 	{ 		m_Delay = -10; 	} } /*--------------------------------------------------------------------------*/ void BossPiranha::Dead( float dt ) { 	if(!m_Anim->hasEnded()){return;}
	SetAnimation(BossState::FULLDEAD, true);
	m_State = BossState::FULLDEAD;
	gGameMain->UnfixCamera();
}
/*--------------------------------------------------------------------------*/
void BossPiranha::NextBehavior(float dt)
{	
	m_Anim->setLoop(false);
	if(!m_Anim->hasEnded()){ m_State = BossState::IDLE; return;}
	if(m_Delay >= 0){return;}
	SetAnimation(BossState::IDLE, true);
	m_Anim->setLoop(true);
	m_AnimationPlaying = false;

	float diff = (m_Position.x - (gGameMain->GetCameraPosition().x + BOSSPIRANHA_SCREEN_RIGHT_POSITION));
	m_Position.x += -(diff / BOSSPIRANHA_STARTUP_DAMPING) * dt;

	float differenceY = (m_Position.y - gGameMain->GetCameraPosition().y);
	m_Position.y += -(differenceY / BOSSPIRANHA_MOVEMENT_Y_DAMPING) * dt;

	float oneprocent = BOSSPIRANHA_START_HEALTH / 100;
	float CurrentProcent = m_health / oneprocent;
	//printf("%f\n", CurrentProcent);
	if(CurrentProcent > 70.0f)
	{
		if(m_Behavior != BossState::HIGH)
		{
			m_Behavior = BossState::HIGH;
			ChangeBehavior(dt);
		}
		else
		{
			m_Stage++;
			if(m_Stage == 1){m_State = BossState::ATTACKCHARGE; m_AttackDone = false; SetAnimation(BossState::ATTACKCHARGE, false); m_Delay = 1.3 * 1000;}
			if(m_Stage == 2){m_State = BossState::DELAY; m_Delay = 2.0 * 1000;}
			if(m_Stage == 3){m_State = BossState::ATTACKLASER; m_BulletShootCountDown = 0; m_BulletsToShoot = 1; SetAnimation(BossState::ATTACKLASER, false); m_Delay = 0.6 * 1000;}
			if(m_Stage == 4){m_State = BossState::DELAY; m_Delay = 2.0 * 1000;}
			if(m_Stage == 5){m_State = BossState::ATTACKPOWERBALL; SetAnimation(BossState::ATTACKPOWERBALL, false); m_Delay = 2.2f * 1000;}
			if(m_Stage == 6){m_State = BossState::DELAY; m_Delay = 2.0 * 1000;}
			if(m_Stage == 7){m_State = BossState::SHIELD; SetAnimation(BossState::SHIELD, false);}
			if(m_Stage == 8){m_Stage = 0; NextBehavior(dt);}
		}
	}else
	if(CurrentProcent <= 70.0f && CurrentProcent > 30.0f)
	{
		if(m_Behavior != BossState::MID)
		{
			m_Behavior = BossState::MID;
			ChangeBehavior(dt);
		}
		else
		{
			m_Stage++;
			if(m_Stage == 1){m_State = BossState::ATTACKCHARGE; m_AttackDone = false; SetAnimation(BossState::ATTACKCHARGE, false); m_Delay = 1.3 * 1000;}
			if(m_Stage == 2){m_State = BossState::DELAY; m_Delay = 1.0 * 1000;}
			if(m_Stage == 3){m_State = BossState::ATTACKLASER; m_BulletShootCountDown = 0; m_BulletsToShoot = 2; SetAnimation(BossState::ATTACKLASER, false); m_Delay = 0.6 * 1000;}
			if(m_Stage == 4){m_State = BossState::DELAY; m_Delay = 1.0 * 1000;}
			if(m_Stage == 5){m_State = BossState::ATTACKLASER; m_BulletShootCountDown = 0; m_BulletsToShoot = 2; SetAnimation(BossState::ATTACKLASER, false); m_Delay = 0.6 * 1000;}
			if(m_Stage == 6){m_State = BossState::DELAY; m_Delay = 1.0 * 1000;}
			if(m_Stage == 7){m_State = BossState::ATTACKPOWERBALL; SetAnimation(BossState::ATTACKPOWERBALL, false); m_Delay = 2.2f * 1000;}
			if(m_Stage == 8){m_State = BossState::SHIELD; SetAnimation(BossState::SHIELD, false);}
			if(m_Stage == 9){m_Stage = 0; NextBehavior(dt);}
		}
	}else
	if (CurrentProcent <= 30.0f) 	{ 		if(m_Behavior != BossState::LOW) 		{ 			m_Behavior = BossState::LOW; 			ChangeBehavior(dt); 		} 		else 		{ 			m_Stage++; 			if(m_Stage == 1){m_State = BossState::ATTACKCHARGE; m_AttackDone = false; SetAnimation(BossState::ATTACKCHARGE, false); m_Delay = 1.3 * 1000;} 			if(m_Stage == 2){m_State = BossState::ATTACKLASER; m_BulletShootCountDown = 0; m_BulletsToShoot = 3; SetAnimation(BossState::ATTACKLASER, false); m_Delay = 0.6 * 1000;} 			if(m_Stage == 3){m_State = BossState::ATTACKLASER; m_BulletShootCountDown = 0; m_BulletsToShoot = 3; SetAnimation(BossState::ATTACKLASER, false); m_Delay = 0.6 * 1000;} 			if(m_Stage == 4){m_State = BossState::ATTACKPOWERBALL; SetAnimation(BossState::ATTACKPOWERBALL, false); m_Delay = 2.2f * 1000;} 			if(m_Stage == 5){m_State = BossState::ATTACKPOWERBALL; SetAnimation(BossState::ATTACKPOWERBALL, false); m_Delay = 2.2f * 1000;} 			if(m_Stage == 6){m_State = BossState::SHIELD; SetAnimation(BossState::SHIELD, false);} 			if(m_Stage == 7){m_Stage = 0; NextBehavior(dt);} 		} 	} } /*--------------------------------------------------------------------------*/ void BossPiranha::ChangeBehavior( float dt ) {     SetAnimation(BossState::BEHAVIORHIT, false);     m_Stage = 0; 	m_State = BossState::BEHAVIORHIT; 	m_Delay = 2.2 * 1000; 	ChangeColor(); } /*--------------------------------------------------------------------------*/ void BossPiranha::BehaviorHit( float dt ) { 	SetAnimation(BossState::IDLE, true); 	m_State = BossState::IDLE; 	m_Stage = 0; } /*--------------------------------------------------------------------------*/ void BossPiranha::Dance( float dt) { 	if(!m_IsDancing) 	{ 		m_IsDancing = true; 		SetAnimation(BossState::DANCESTART, false); 	} 	else 	{ 		if(m_Anim->hasEnded())
		{
			SetAnimation(BossState::DANCE, true);
		}
	}

	float differenceY = (m_Position.y - gGameMain->GetCameraPosition().y);
	m_Position.y += -(differenceY / BOSSPIRANHA_MOVEMENT_Y_DAMPING) * dt;

	float diff = (m_Position.x - (gGameMain->GetCameraPosition().x + 30.0f) );
	m_Position.x += -(diff / BOSSPIRANHA_STARTUP_DAMPING) * dt;
}
/*--------------------------------------------------------------------------*/
void BossPiranha::SetAnimation(int state, bool loop)
{
	if(m_Anim != NULL){ m_Anim->setEnabled(false);}

	if(state == BossState::IDLE)			{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_swim"); m_CanReceiveDamage = true; }
	if(state == BossState::ATTACKCHARGE)	{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_charge"); m_CanReceiveDamage = false; }
	if(state == BossState::ATTACKLASER)		{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_attack_forward"); m_CanReceiveDamage = false;}
	if(state == BossState::ATTACKPOWERBALL)	{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_powerAttack"); m_CanReceiveDamage = false; }
	if(state == BossState::SHIELD)			{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_shield"); m_CanReceiveDamage = false; }
	if(state == BossState::BEHAVIORHIT)		{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_death"); m_CanReceiveDamage = false; }
	if(state == BossState::DEAD)            { m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_death"); m_CanReceiveDamage = false; }
	if(state == BossState::FULLDEAD)		{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_deathLoop"); m_CanReceiveDamage = false; }
	if(state == BossState::DANCESTART)		{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_danceStart"); m_CanReceiveDamage = false; }
	if(state == BossState::DANCE)			{ m_Anim  = m_Model.mEntities[0]->getAnimationState("piranhaBoss_an_danceLoop"); m_CanReceiveDamage = false; }

	m_Anim->setEnabled(true);
	m_Anim->setTimePosition(0);
	m_Anim->setLoop(loop);
}
/*--------------------------------------------------------------------------*/
void BossPiranha::Hit( float damage, Ogre::Vector3 hitPosition )
{
	if(m_CanReceiveDamage)
	{
		if(hitPosition.distance(m_Position) <= BOSSPIRANHA_HIT_RADIUS) 		{ 			m_health-=damage; 			 			m_HitMaterial->setDiffuse(ENEMY_LIGHT_HIT_COLOR_R,ENEMY_LIGHT_HIT_COLOR_G,ENEMY_LIGHT_HIT_COLOR_B,ENEMY_LIGHT_HIT_COLOR_A);
			m_Model.mEntities[0]->setMaterial(m_HitMaterial);
	
			m_IsHit = true;
			m_CurrentHitTime = 0;
		}

		if(m_health<=0) 		{ 			m_CanReceiveDamage = false; 			m_State = BossState::DEAD; 			m_Delay = 0; 			SetAnimation(BossState::DEAD, false); 			m_collisionDamage = 0; 		} 	} } /*--------------------------------------------------------------------------*/ void BossPiranha::ChangeColor() { 	if(m_Behavior == BossState::HIGH) 	{ 		m_Model.mEntities[0]->getSubEntity(20)->setMaterialName("ball_green");
		m_AnimationChanger = 1.0f;
		m_lightColor = 0xFF00FF00;
	}
	else if(m_Behavior == BossState::MID)
	{
		m_Model.mEntities[0]->getSubEntity(20)->setMaterialName("ball_orange");
		m_AnimationChanger = 1.1f;
		m_lightColor = 0xFFFF9900;
	}
	else if(m_Behavior == BossState::LOW)
	{
		m_Model.mEntities[0]->getSubEntity(20)->setMaterialName("ball_red");
		m_AnimationChanger = 1.2f;
		m_lightColor = 0xFFFF0000;
	}
}