ArduinoRGB Amp

Tutorial

Arduino has fast become one of my favourite hobbies. A cheap and reliable board based on an ATMEL microprocessor that allows for easy and quick prototyping.

One use is to control a strip of LEDs, check out my tutorial on controlling a RGB strip with IR for more information!

D.M.A. Distributing

Visit

The website is heavily based off this one but is a demonstration of my ability to use and maintain websites involcing xHTML and CSS

JavaScript Sample

Sample Page Download

VBScript Sample

Sample Page Download

Python Sample

Code Download

Requires OpenSSL

SQL Sample

Code Download

Create a database named "SE4M03" to test, run create, data, show, query in sequence

Tested on a IBM DB2 system

Project T

Doxygen Download

Project T was a final year project completed by me and 3 others. A majority of the C++ codeing was done by myself. Above you can find the documentation as well as a download link for the game.

To start, Extract, Open C4.exe, Press '~', and type 'start intro'

Below is a sample of the code.

Platform Controller




platform.h


/**
 * @file PTPlatform.h
 *	PLatform controller
 *
 * @brief Platform controller
 *
 *	This controller pushes an object in any combination of forward directions in the world
 *	Due to a design flaw it is nesecary to comensate for negative shifts by placing the object
 *	at the destination and setting the current position to the maximum distance traveled.
 *  The platforms rely on the engines gravity to move the models along the Z axis. The X and Y
 *	movements are applied to models that fall with in the bounds of the platform.
 *
 * @author Daryl Dippel
 * @version 1
 * */
// ================================================================================================

#ifndef PTPlatform_h
#define PTPlatform_h

#include "C4Controller.h"
#include "C4Properties.h"
#include "C4Effects.h"

#include "PTControllers.h"
#include "PTPlayer.h"



namespace C4
{


	/**
	 * @brief Controller class for Vector Platform
	 *
	 * Takes a x,y,z distance and x,y,z speed and oscilates with that data
	 *
	 */
class VectorPlatformController : public Controller
{
   private:
 
        float         spinRate;             // In radians per millisecond
        float         spinAngle;            // The current angle, in radians

		float         push;            // Are we pushing
		float         count;            // reduce number of contacts

		float         xMoveRate;             
		float         yMoveRate;             
		float         zMoveRate;             

        float         xMoveDistance;            
		float         yMoveDistance;            
		float         zMoveDistance;            

		int				xFlip;
		int				yFlip;
		int				zFlip;

		float           xCurPos;              // The current position along X path
		float           yCurPos;              // The current position along Y path
		float           zCurPos;              // The current position along Z path

        Transform4D   originalTransform;    // The targets original transform
 
        VectorPlatformController(const VectorPlatformController& tpinController);
 
        Controller *Replicate(void) const;
 
   public:
 
        VectorPlatformController();
		VectorPlatformController(float rate, float xr, float yr, float zr, float x, float y, float z, float xc, float yc, float zc);
        ~VectorPlatformController();
 
        float GetSpinRate(void) const
        {
            return (spinRate);
        }
 
        void SetSpinRate(float rate)
        {
            spinRate = rate;
        }
 
        static bool ValidNode(const Node *node);
 
        // Serialization functions
        void Pack(Packer& data, unsigned long packFlags) const;
        void Unpack(Unpacker& data, unsigned long unpackFlags);
 
        // User interface functions
        long GetSettingCount(void) const;
        Setting *GetSetting(long index) const;
        void SetSetting(const Setting *setting);
 
        void Preprocess(void);
 
        // The function that moves the target node
        void Move(void);
};
}

#endif
			
		}

		

platform.cpp

		
/**
 * @file PTPlatform.cpp
 *	PLatform controller
 *
 * @brief Platform controller
 *
 *	This controller pushes an object in any combination of forward directions in the world
 *	Due to a design flaw it is nesecary to comensate for negative shifts by placing the object
 *	at the destination and setting the current position to the maximum distance traveled.
 *  The platforms rely on the engines gravity to move the models along the Z axis. The X and Y
 *	movements are applied to models that fall with in the bounds of the platform.
 *
 * @author Group 1 4GP6 
 * @version 1
 * */
// ================================================================================================

#include "PTGame.h"
#include "PTPlatform.h"
#include "PTControllers.h"


using namespace C4;



////////////////// VectorPlatform
VectorPlatformController::VectorPlatformController() : Controller(kControllerVectorPlatform)
{
    spinRate = 0.0F;
    spinAngle = 0.0F;
	// must initialize with movement or div by 0 explodes world ankd sets fire to souls
	xMoveRate = 100.0F;
	yMoveRate = 100.0F;
	zMoveRate = 100.0F;
	xMoveDistance = 10.0F;
	yMoveDistance = 10.0F;
	zMoveDistance = 10.0F;
	xCurPos = 0.0F;
	yCurPos = 0.0F;
	zCurPos = 0.0F;
	xFlip = 0;
	yFlip = 0;
	zFlip = 0;
	count =0;

}
 

 


VectorPlatformController::VectorPlatformController(float rate, float xr,float yr,float zr, float x, float y, float z, float xc, float yc, float zc) : Controller(kControllerVectorPlatform)
{
    spinRate = rate;
    spinAngle = 0.0F;
	xMoveRate = xr;
	yMoveRate = yr;
	zMoveRate = zr;
	xMoveDistance = x;
	yMoveDistance = y;
	zMoveDistance = z;
	xCurPos = xc;
	yCurPos = yc;
	zCurPos = zc;
	xFlip = 0;
	yFlip = 0;
	zFlip = 0;
	count =0;
}
 
VectorPlatformController::~VectorPlatformController()
{
}

VectorPlatformController::VectorPlatformController(const VectorPlatformController& VectorPlatformController) : Controller(VectorPlatformController)
{
    spinRate = VectorPlatformController.spinRate;
    spinAngle = 0.0F;
	xMoveRate = VectorPlatformController.xMoveRate;
	yMoveRate = VectorPlatformController.yMoveRate;
	zMoveRate = VectorPlatformController.zMoveRate;
	xMoveDistance = VectorPlatformController.xMoveDistance;
	yMoveDistance = VectorPlatformController.yMoveDistance;
	zMoveDistance = VectorPlatformController.zMoveDistance;
	xCurPos = VectorPlatformController.xCurPos;
	yCurPos = VectorPlatformController.yCurPos;
	zCurPos = VectorPlatformController.zCurPos;
	xFlip = 0;
	yFlip = 0;
	zFlip = 0;
}

Controller *VectorPlatformController::Replicate(void) const
{
    return (new VectorPlatformController(*this));
}

bool VectorPlatformController::ValidNode(const Node *node)
{
    return (node->GetNodeType() == kNodeGeometry);
}

void VectorPlatformController::Pack(Packer& data, unsigned long packFlags) const
{
    Controller::Pack(data, packFlags);
 
    // Write the spin rate
    data << spinRate;
 
    // Write the current angle
    data << spinAngle;
 
    // Write the original transform
    data << originalTransform;

	// Write moar
    data << xMoveRate;
	data << yMoveRate;
	data << zMoveRate;
	data << xMoveDistance;
	data << yMoveDistance;
	data << zMoveDistance;
	data << xCurPos;
	data << yCurPos;
	data << zCurPos;
}
 
void VectorPlatformController::Unpack(Unpacker& data, unsigned long unpackFlags)
{
    Controller::Unpack(data, unpackFlags);
 
    // Read the spin rate
    data >> spinRate;
 
    // Read the current angle
    data >> spinAngle;
 
    // Read the original transform
    data >> originalTransform;

	
	data >> xMoveRate;
	data >> yMoveRate;
	data >> zMoveRate;
	data >> xMoveDistance;
	data >> yMoveDistance;
	data >> zMoveDistance;
	data >> xCurPos;
	data >> yCurPos;
	data >> zCurPos;
}

long VectorPlatformController::GetSettingCount(void) const
{
    // Theres only one setting
    return (10);
}
 
Setting *VectorPlatformController::GetSetting(long index) const
{
    
    if (index == 0)
    {
        // spin value in revolutions per second
        return (new TextSetting('rate', Text::FloatToString(spinRate * 1000.0F / K::two_pi),
            "Spin rate", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 1)
    {
        // move rate value
        return (new TextSetting('mvrx', Text::FloatToString(xMoveRate),
            "X Move Rate", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 2)
    {
        // move rate value
        return (new TextSetting('mvry', Text::FloatToString(yMoveRate),
            "Y Move Rate", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 3)
    {
        // move rate value
        return (new TextSetting('mvrz', Text::FloatToString(zMoveRate),
            "Z Move Rate", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 4)
    {
        // move dist value
        return (new TextSetting('mvdx', Text::FloatToString(xMoveDistance),
            "X Move Distance", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 5)
    {
        // move dist value
        return (new TextSetting('mvdy', Text::FloatToString(yMoveDistance),
            "Y Move Distance", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 6)
    {
        // move dist valur
        return (new TextSetting('mvdz', Text::FloatToString(zMoveDistance),
            "Z Move Distance", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 7)
    {
        // move dist value
        return (new TextSetting('mvcx', Text::FloatToString(xCurPos),
            "X Start Distance", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 8)
    {
        // move dist value
        return (new TextSetting('mvcy', Text::FloatToString(yCurPos),
            "Y Start Distance", 7, &EditableTextElement::FloatNumberFilter));
    }
	if (index == 9)
    {
        // move dist valur
        return (new TextSetting('mvcz', Text::FloatToString(zCurPos),
            "Z Start Distance", 7, &EditableTextElement::FloatNumberFilter));
    }
 
    return (nullptr);
}
 
void VectorPlatformController::SetSetting(const Setting *setting)
{
    
    if (setting->GetSettingIdentifier() == 'rate')
    {
        // get spin and convert
        const char *text = static_cast(setting)->GetText();
        spinRate = Text::StringToFloat(text) * K::two_pi / 1000.0F;
    }
	if (setting->GetSettingIdentifier() == 'mvrx')
    {
        // get move rate
        const char *text = static_cast(setting)->GetText();
        xMoveRate = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvry')
    {
        // get move rate
        const char *text = static_cast(setting)->GetText();
        yMoveRate = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvrz')
    {
        // get move rate
        const char *text = static_cast(setting)->GetText();
        zMoveRate = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvdx')
    {
        // get move dist
        const char *text = static_cast(setting)->GetText();
        xMoveDistance = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvdy')
    {
        // get move dist
        const char *text = static_cast(setting)->GetText();
        yMoveDistance = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvdz')
    {
        // get move dist
        const char *text = static_cast(setting)->GetText();
        zMoveDistance = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvcx')
    {
        // get move dist
        const char *text = static_cast(setting)->GetText();
        xCurPos = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvcy')
    {
        // get move dist
        const char *text = static_cast(setting)->GetText();
        yCurPos = Text::StringToFloat(text);
    }
	if (setting->GetSettingIdentifier() == 'mvcz')
    {
        // get move dist
        const char *text = static_cast(setting)->GetText();
        zCurPos = Text::StringToFloat(text);
    }

}

void VectorPlatformController::Preprocess(void)
{
    Controller::Preprocess();
 
    // Grab the original transform of the target node
    const Node *target = GetTargetNode();
    originalTransform = target->GetNodeTransform();
 
    // Set the kGeometryDynamic flag for any geometry nodes
    const Node *node = target;
    do
    {
        if (node->GetNodeType() == kNodeGeometry)
        {

			// Node is a geometry, so grab its object
            GeometryObject *object = static_cast(node)->GetObject();
 
            // Set the kGeometryDynamic flag
            object->SetGeometryFlags(object->GetGeometryFlags() | kGeometryDynamic);


        }
 
        // Iterate through entire subtree
        node = target->GetNextNode(node);
    } while (node);
}

void VectorPlatformController::Move(void)
{
    Matrix3D    rotator;
 
    // Calculate the new spin angle based on how much time has passed
    float angle = spinAngle + spinRate * TheTimeMgr->GetFloatDeltaTime();
 
    // Make sure its in the [-pi, pi] range
    if (angle > K::pi) angle -= K::two_pi;
    else if (angle < -K::pi) angle += K::two_pi;
 
    spinAngle = angle;
 
    // Now make a 3x3 rotation matrix
    rotator.SetRotationAboutZ(angle);
 
    // We'll rotate about the center of the target node's bounding sphere
    Node *target = GetTargetNode();
    const Point3D& worldCenter = target->GetBoundingSphere()->GetCenter();
    Point3D objectCenter = target->GetInverseWorldTransform() * worldCenter; 
 

	const float& platRadius = target->GetBoundingSphere()->GetRadius();


    // Make a 3x4 transform that rotates about the center point
    Transform4D transform(rotator, objectCenter - rotator * objectCenter);
 
    // Apply the rotation transform to the original transform and
    // assign it to the node as its new transform
    //Code added for a translation along the y axis

	// /moveRate + curPos


    Transform4D translation;
    Point3D myTranslation;

	
	
	Node *block = this->GetTargetNode();
	Point3D blockPosition = block->GetNodePosition();
	Object *blockObj = block->GetObject();


	// Grab PLayer Info

	PlayerController *player = TheGame->GetPlayerController();
	Point3D p = player->GetTargetNode()->GetNodePosition();
	Point3D pnew = player->GetTargetNode()->GetNodePosition();
	
	
	
	/*TheEngine->Report(String<16>(objectCenter.x + xCurPos));
	TheEngine->Report(String<16>(objectCenter.y + yCurPos));
	TheEngine->Report(String<16>(objectCenter.z + zCurPos));
	TheEngine->Report(String<16>("Block Cord"));
	TheEngine->Report(String<16>(blockPosition.x + xCurPos));
	TheEngine->Report(String<16>(blockPosition.y + yCurPos));
	TheEngine->Report(String<16>(blockPosition.z + zCurPos));*/

	float sampler = 5;
	push = 4.0;

	

   

	//////// TODO MOVE PLAYER
	if ((p.z < (15+ blockPosition.z)) && (p.z > (blockPosition.z)) )
		{if ((p.y < (blockPosition.y + (objectCenter.y * 2))) && (p.y > (blockPosition.y )) )
			{if ((p.x <  (blockPosition.x + (objectCenter.x * 2))) && (p.x > (blockPosition.x)) )
			{
				if (count == 0)
				
				{push = 1.0;
				
				if (xFlip == 0)
				{pnew.x = p.x + sampler * (xMoveRate);}
				if (xFlip == 1)
				{pnew.x = p.x - sampler * (xMoveRate);}
				if (yFlip == 0)
				{pnew.y = p.y + sampler * (yMoveRate);}
				if (yFlip == 1)
				{pnew.y = p.y - sampler * (yMoveRate);}

				player->SetRigidBodyPosition(pnew);
				}
				if (count ==  (sampler-1))
				{
					count = 0;}
				else {count++;}


			}
	
		}




	}
	
	TheDebugInterface->UpdateTmpVar((blockPosition.x),(blockPosition.y),(yCurPos), (blockPosition.x + (objectCenter.x * 2)),(blockPosition.y + (objectCenter.y * 2)),push);
	
	//TheEngine->Report(String<16>("Bounding"));
	//TheEngine->Report(String<16>(push));
	// Positive Move Dist
	if (xCurPos > xMoveDistance)
	{
	xFlip = 1;
	}
	if (xCurPos < 0)
	{
	xFlip = 0;
	}
	// Check Direction and Move
	if (xFlip == 0)
	{
	xCurPos = xCurPos + xMoveRate;
	}
	if (xFlip == 1)
	{
	xCurPos = xCurPos - xMoveRate;
	}
	// Update Object Translation
    myTranslation.x = xCurPos;
	
	// Y Transform
	if (yCurPos > yMoveDistance)
	{
	yFlip = 1;
	}
	if (yCurPos < 0)
	{
	yFlip = 0;
	}
	if (yFlip == 0)
	{
	yCurPos = yCurPos + yMoveRate;
	}
	if (yFlip == 1)
	{
	yCurPos = yCurPos - yMoveRate;
	}
	myTranslation.y =  yCurPos;
	
	//Debugging output to demonstrate platform variables
	//TheEngine->Report(String<16>(yCurPos));
	//TheEngine->Report(String<16>(yFlip));
	//TheEngine->Report(String<16>(yMoveDistance));

	// Z Transform
	if (zCurPos > zMoveDistance)
	{
	zFlip = 1;
	}
	if (zCurPos < 0)
	{
	zFlip = 0;
	}
	if (zFlip == 0)
	{
	zCurPos = zCurPos + zMoveRate;
	}
	if (zFlip == 1)
	{
	zCurPos = zCurPos - zMoveRate;
	}
    myTranslation.z = zCurPos;
    translation.SetIdentity();
    translation.SetTranslation(myTranslation);
 
    //apply the rotation and the translation to the original transform
    target->SetNodeTransform(originalTransform * translation * transform);
 
    // Invalidate the target node so that it gets updated properly
    target->Invalidate();
}









 * @brief Main player controller
 *
 *	This is the main player controller that the player uses to interact with our world.
 *	It includes variables to track position, as well as direction, player mode, frame animation
 *	health, speed and point states as well as various attack moves.
 *
 * @author Daryl Dippel
 * @version 1
 * */
// ================================================================================================
#include "PTPlayer.h"

#include "PTCamera.h"
#include "PTGame.h"


// Player constants
static const long CANNON_LOAD_TIME = 3000;	// Time between each cannon shot in milliseconds

PlayerController::PlayerController(float azimuth) : CharacterController(kControllerPlayer)
{
	playerAnimation		= kAnimationNone;

	// --------------------------------

	movementFlags		= 0;
	modelAzimuth		= azimuth;
	modelAltitude		= 0.0f;

	state.Health		= 100;

	state.EnergyBlue	= 100;
	state.EnergyRed		= 100;
	state.Mode			= kModeNormal;

	state.Speed			= 50.0f;
	state.Strength		= 50.0f;

	state.Score			= 0;

	strengthMod			= 1.0f;
	speedMod			= 1.0f;

	canFireCannon = true;
	cannonTimer = new Timer(&PlayerController::HandleCannonTimer, this);
	TheTimeMgr->AddEvent(cannonTimer);

	isBrawling = false;
	isExploding = false;

	playedDeathSound = false;
}

PlayerController::~PlayerController(void)
{
}

void PlayerController::SendInitialStateMessages(Player *player) const
{
	// Ignore if this machine isnt server
	if (!TheMessageMgr->Server()) return;

	PlayerSpawnMessage msg(TheMessageMgr->GetLocalPlayerKey(), this->GetControllerIndex(), this->GetTargetNode()->GetNodePosition(), this->GetModelAzimuth(), this->GetModelAltitude(), this->GetMovementFlags(), this->GetMode());

	TheMessageMgr->SendMessage(player->GetPlayerKey(), msg);
}

void PlayerController::Preprocess(void)
{
	CharacterController::Preprocess();

	this->SetRigidBodyFlags(kRigidBodyKeepAwake | kRigidBodyFixedOrientation);
	this->SetFrictionCoefficient(0.0f);

	Model *player = this->GetTargetNode();
	frameAnimator.SetTargetModel(player);
	player->SetRootAnimator(&frameAnimator);

	this->redFlareEffect = this->GetRedFlareEffect();
	this->blueFlareEffect = this->GetBlueFlareEffect();

	this->redFlareEffect->GetObject()->SetOcclusionRadius(0.3f);
	this->blueFlareEffect->GetObject()->SetOcclusionRadius(0.3f);

	this->MAX_HEALTH = 100.0f;
	this->MIN_HEALTH = 0.0f;

	this->MAX_ENERGY = 100.0f;
	this->MIN_ENERGY = 0.0f;

	this->ENERGY_DEPLETION_RATE = 0.05f;

	this->SetMode(kModeNormal);	

	(this->state).Health = MAX_HEALTH;
	(this->state).EnergyBlue = MAX_ENERGY;
	(this->state).EnergyRed = MAX_ENERGY;
}

void PlayerController::Move(void)
{
	
	Model *model = this->GetTargetNode();
	Point3D oldPosition = model->GetNodePosition();

	// Kill the player if theyre below certain height
	if (model->GetNodePosition().z <= -50.0f) {
		this->RemoveHealth(999999.0f);
	}

	// Set movement matrix
	static const unsigned char movementIndexTable[16] = {
		8, 0, 1, 8,
		2, 4, 6, 2,
		3, 5, 7, 3,
		8, 0, 1, 8
	};

	// Calculate model azimuth and altitude
	float azm = modelAzimuth + TheInputMgr->GetMouseDeltaX();
	if (azm < -K::pi) azm += K::two_pi;
	else if (azm > K::pi) azm -= K::two_pi;
 
	float alt = modelAltitude + TheInputMgr->GetMouseDeltaY();
	if (alt < -1.45F) alt = -1.45F;
	else if (alt > 1.45F) alt = 1.45F;
 
	modelAzimuth = azm;
	modelAltitude = alt;

	// Only do these if player is alive
	if (this->GetHealth() > 0.99f) {
		long animation = playerAnimation;
		Vector3D propel(0.0f, 0.0f, 0.0f);
 
		// Set movement and select appropriate animation
		long index = movementIndexTable[movementFlags & kMovementPlanarMask];

		if (index < 8) {
			static const float movementDirectionTable[8] = {
				0.0F, 4.0F, 2.0F, -2.0F, 1.0F, -1.0F, 3.0F, -3.0F
			};
			float direction = movementDirectionTable[index] * K::pi_over_4 + modelAzimuth;
			propel.x = Cos(direction) * this->GetSpeed() * this->GetSpeedMod();
			propel.y = Sin(direction) * this->GetSpeed() * this->GetSpeedMod();

			animation = ((index == 1) || (index >= 6)) ? kAnimationBackward : kAnimationForward;
		}
		else {
			animation = kAnimationStand;
		}

		if (movementFlags >= 16) {
				animation = kAnimationJump;
				propel.z = this->GetStrength() * this->GetStrengthMod() * 1.2f; // Jump Modifier = 0.80f
		}

		if (GroundContact()) {
			SetExternalLinearResistance(Vector3D(10.0f, 10.0f, 0.0f));
			SetExternalForce(propel);
		}
		else {
			SetExternalLinearResistance(Vector3D(0.0f, 0.0f, 0.0f));
			propel.x *= 0.0001f * this->GetStrength();
			propel.y *= 0.0001f * this->GetStrength(); 
			propel.z *= 0.02f;
			SetExternalForce(propel); // Air Control Modifier = 0.02f
		}
 
		SetCharacterOrientation(modelAzimuth);
 
		// Attack animations
		if (this->IsBrawling()) animation = kAnimationBrawl;
		else if (this->IsExploding()) animation = kAnimationExplode;

		if (animation != playerAnimation) SetPlayerAnimation(animation);
 
		GetTargetNode()->Animate();

		// Check for any triggers the player might be activating
		model->GetWorld()->ActivateTriggers(oldPosition, model->GetNodePosition(), 0.5f, model);

		// Mode dependant effects
		if (this->GetMode() == kModeRed) {
			this->RemoveRedEnergy(this->ENERGY_DEPLETION_RATE);
			if (this->GetRedEnergy() <= 0.0f) this->SetMode(kModeNormal);
		}		
		else if (this->GetMode() == kModeBlue) {
			this->RemoveBlueEnergy(this->ENERGY_DEPLETION_RATE);
			if (this->GetBlueEnergy() <= 0.0f) this->SetMode(kModeNormal);
		}
		else {
			// Do nothing
		}

		//DD Debug Cord Update
		TheDebugInterface->UpdatePlayerPos();
	}
	else {
		// If player is dead, play the death sound only once
		if (!playedDeathSound) {
			playedDeathSound = true;
			Sound *sound = new Sound;
			sound->Load("sound/death");
			sound->Play();
		}
		TheDeathInterface->Open();
	}

	TheHudInterface->UpdateInterface();
}

void PlayerController::SetMode(ModeType m)
{
	state.Mode = m;
	World *world = TheWorldMgr->GetWorld();
	Zone *zone = world->GetRootNode();
	
	Sound *sound = new Sound;

	switch (m) {
	case kModeRed:
		if (TheBlueInterface)
		{
			TheBlueInterface->Close();
		}
		this->SetStrength(40.0f);
		this->SetSpeed(120.0f);

		sound->Load("sound/gun_change01");
		sound->Play();

		this->redFlareEffect->Enable();
		this->blueFlareEffect->Disable();
		//spiral->ChangeColor(ColorRGB(1.0f,0.0f,0.0f));
		TheRedInterface->Open();
		break;
	case kModeBlue:
		if (TheRedInterface)
		{
			TheRedInterface->Close();
		}
		this->SetStrength(150.0f);
		this->SetSpeed(25.0f);

		sound->Load("sound/gun_change01");
		sound->Play();

		this->redFlareEffect->Disable();
		this->blueFlareEffect->Enable();
		TheBlueInterface->Open();
		break;
	case kModeNormal:
	default:
		if (TheRedInterface)
		{
			TheRedInterface->Close();
		}
		if (TheBlueInterface)
		{
			TheBlueInterface->Close();
		}
		this->SetStrength(90.0f);
		this->SetSpeed(50.0f);
		
		sound->Load("sound/gun_change02");
		sound->Play();

		this->redFlareEffect->Disable();
		this->blueFlareEffect->Disable();
		break;
	}
}

bool PlayerController::Collect(DynamicObjectController *dyno)
{
	// Get all DynObj modifiers and add them to the player
	this->AddHealth(dyno->GetHealthModifier());
	this->AddBlueEnergy(dyno->GetBlueEnergyModifier());
	this->AddRedEnergy(dyno->GetRedEnergyModifier());
	this->AddScore(dyno->GetScoreModifier());

	int i = dyno->GetKeyNum();
	
	/*
	//TODO : Key Collection
	if (i == 1)
	{TheRedDoor->Key();}
	*/
	Sound *sound = new Sound;
	sound->Load("sound/pop");
	sound->Play();

	// Interface Update
	TheDebugInterface->UpdatePlayerScore();
	TheDebugInterface->UpdatePlayerHealth();
	return true;
}


void PlayerController::SetPlayerAnimation(long animation)
{
	Interpolator *interpolator = frameAnimator.GetFrameInterpolator();

	if (animation == kAnimationStand) {
		frameAnimator.SetAnimation("model/Idle");
		interpolator->SetMode(kInterpolatorForward | kInterpolatorLoop);
	}
	else if (animation == kAnimationForward) {
		frameAnimator.SetAnimation("model/Walk");
		interpolator->SetMode(kInterpolatorForward | kInterpolatorLoop);
	}
	else if (animation == kAnimationBackward) {
		frameAnimator.SetAnimation("model/Walk");
		interpolator->SetMode(kInterpolatorForward | kInterpolatorLoop);
	}
	else if (animation == kAnimationJump) {
		frameAnimator.SetAnimation("model/Jump");
		interpolator->SetMode(kInterpolatorForward);
	}
	else if (animation == kAnimationBrawl) {
		frameAnimator.SetAnimation("model/Brawl");
		interpolator->SetMode(kInterpolatorForward);
	}
	else if (animation == kAnimationExplode) {
		frameAnimator.SetAnimation("model/Explode");
		interpolator->SetMode(kInterpolatorForward);
	}
 
	playerAnimation = animation;
}

void PlayerController::FireCannon(void)
{
	if (this->CanFireCannon()) {
		World *world = TheWorldMgr->GetWorld();

		Point3D position = this->GetTargetNode()->GetNodePosition();

		Vector3D positionOffset(Cos(this->modelAzimuth), Sin(this->modelAzimuth), 1.6f);

		position += positionOffset;

		Model *model = Model::Get(kModelCannonball);
		CannonballController *controller = new CannonballController(this->modelAzimuth, this->modelAltitude);
		model->SetController(controller);
		Zone *zone = world->GetRootNode();

		zone->AddNewSubnode(model);

		controller->SetRigidBodyPosition(position);

		controller->Fire();

		// TODO Put a setting that can disable camera shake
		PTCamera *camera = static_cast(world->GetCamera());
		camera->Shake();

		this->DisableCannonFire();
		cannonTimer->SetTime(CANNON_LOAD_TIME);

		// Recoil
		float k = -(controller->GetKickbackForce());

		// If in air, reduce the recoil
		if (!this->GroundContact()) k /= 4.0f;

		Vector3D v(k, 0.0f, 0.0f);

		Sound *sound = new Sound;
		sound->Load("sound/cannon");
		sound->Play();

		this->ApplyImpulse(v);

		//Particle Effects!
		Point3D effectPos = this->GetTargetNode()->GetNodePosition() + Point3D(0.0f,0.0f,this->modelAltitude+1.6f);

		SparksSystem *sparks = new SparksSystem(20);
		sparks->SetNodePosition(effectPos);
		zone->AddNewSubnode(sparks);

		const ConstColorRGBA smokeColor = {0.6F,0.6F,0.6F,0.7F};
		SmokeTrail *smoke = new SmokeTrail(smokeColor, "texture/Trail");
		smoke->SetNodePosition(effectPos);
		zone->AddNewSubnode(smoke);
		float smokeDrift = 0.00f;
		int count = 4 + Math::Random(20);
		
		Point3D delta = Point3D(Cos(this->modelAzimuth),sin(this->modelAzimuth),smokeDrift);

		do {
			smoke->CreateSmoke(effectPos + delta, Math::Random(1000) + 1000, 0.01F);
			delta += Point3D(Cos(this->modelAzimuth),sin(this->modelAzimuth),smokeDrift);
		} while ((count -= 1.0F) > 0.0F);
		
	}
}

void PlayerController::Brawl(void) {
	if (!this->isBrawling) {
		this->isBrawling = true;
		Point3D p1 = this->GetTargetNode()->GetNodePosition() + Point3D(Cos(this->GetModelAzimuth())*3, Sin(this->GetModelAzimuth())*3, 1.0f);
		Point3D p2 = p1 + Point3D(0.0f, 0.0, 1.0f);
		CollisionData *data = new CollisionData();
		CollisionState s = TheWorldMgr->GetWorld()->QueryWorld(p1, p2, 0.8f, kCollisionProjectile, data);

		// Very messy and dirty fix
		if (s == kCollisionStateRigidBody) {
			if (data) {
				if (data->rigidBody->GetControllerType() == kControllerTurret) {
					TheEngine->Report("Turret!");

					TurretController *turret = static_cast(data->rigidBody);

					float h = 30.0f;

					if (this->GetMode() == kModeBlue) {
						h = 10.0f;
					}

					turret->RemoveHealth(h);
				}
			}
		}

		else if (s == kCollisionStateGeometry) {
			if (data) {
				const char *name = data->geometry->GetNodeName();
				TheEngine->Report(name);
			}
		}

		else {
			TheEngine->Report("No Collision!");
		}
	}
}

void PlayerController::UnBrawl(void) {
	this->isBrawling = false;
}

void PlayerController::Explode(void) {
	this->isExploding = true;
	World *world = TheWorldMgr->GetWorld();
	Zone *zone = world->GetRootNode();
	
}

void PlayerController::UnExplode(void) {
	this->isExploding = false;
}

void PlayerController::HandleCannonTimer(DeferredEvent *timer, void *data)
{
	PlayerController *player = static_cast(data);

	if (!player->CanFireCannon())
		player->EnableCannonFire();
}

FlareEffect *PlayerController::GetRedFlareEffect(void) const {
	Node *root = this->GetTargetNode();
	Node *node = root;

	String<31> name;
	name = "red";
	String<31> nodeName("");
	do {
		
		if (node->GetNodeName()) nodeName = node->GetNodeName();
		if (name == static_cast(nodeName)) {
			break;
		}
		node = root->GetNextNode(node);
	} while (node);

	FlareEffect *effect = static_cast(node);

	return effect;
}

FlareEffect *PlayerController::GetBlueFlareEffect(void) const {
	Node *root = this->GetTargetNode();
	Node *node = root;

	String<31> name;
	name = "blue";
	String<31> nodeName("");
	do {
		
		if (node->GetNodeName()) nodeName = node->GetNodeName();
		if (name == static_cast(nodeName)) {
			break;
		}
		node = root->GetNextNode(node);
	} while (node);

	FlareEffect *effect = static_cast(node);

	return effect;
}

void PlayerController::print_stats(void)
{
	TheEngine->Report(String<16>("Health: ") + String<16>(this->GetHealth()));
}
		}