view LightClone/Source/Bot.cpp @ 0:7e3a0ae9c016

Initial commit
author koryspansel <koryspansel@bendbroadband.com>
date Wed, 07 Sep 2011 12:36:37 -0700
parents
children 6f227dd9a94f
line wrap: on
line source

/*
 * Bot
 */

#include "Bot.h"
#include "Clock.h"
#include <d3d9.h>
#include <d3dx9.h>

/*
 * DirectionAngle
 */
const float DirectionAngle[] = {-1.0f * D3DX_PI / 2.0f, -4.0f * D3DX_PI / 2.0f, -3.0f * D3DX_PI / 2.0f, -2.0f * D3DX_PI / 2.0f};

/*
 * DirectionStepX
 */
const int32 DirectionStepX[] = {0, 1, 0, -1};

/*
 * DirectionStepY
 */
const int32 DirectionStepY[] = {1, 0, -1, 0};

/*
 * Bot
 */
Bot::Bot()
{
	pEnvironment	= 0;
	nState			= BotState_Idle;
	kSize			= D3DXVECTOR3(0.55f, 1.00f, 0.55f);
}

/*
 * Initialize
 */
void Bot::Initialize(Environment* pInstance)
{
	pEnvironment	= pInstance;
	nState			= BotState_Idle;
	nColor			= D3DCOLOR_XRGB(0, 255, 0);

	kMachine.RemoveAllFunctions();
}

/*
 * Reset
 */
void Bot::Reset()
{
	nState	= BotState_Idle;
	nColor	= D3DCOLOR_XRGB(0, 255, 0);

	kMachine.Reset();
}

/* 
 * GetWorldPosition
 */
const D3DXVECTOR3 Bot::GetWorldPosition() const
{
	const D3DXVECTOR3& kScale = pEnvironment->GetScale();

	D3DXVECTOR3 kWorldPosition;
	kWorldPosition.x = kScale.x * kPosition.X;
	kWorldPosition.y = kScale.y * pEnvironment->GetAltitude(kPosition.X, kPosition.Y);
	kWorldPosition.z = kScale.z * kPosition.Y;

	if(nState == BotState_Animate)
	{
		if(kSequencer.nSequence == BotSequence_Forward)
		{
			kWorldPosition.x = kScale.x * ((int32)kPosition.X + kSequencer.fTimer * ((int32)kSequencer.kPosition.X - (int32)kPosition.X));
			kWorldPosition.z = kScale.z * ((int32)kPosition.Y + kSequencer.fTimer * ((int32)kSequencer.kPosition.Y - (int32)kPosition.Y));
		}
		else

		if(kSequencer.nSequence == BotSequence_Jump)
		{
			const uint32 nHeightA = pEnvironment->GetAltitude(kPosition.X, kPosition.Y);
			const uint32 nHeightB = pEnvironment->GetAltitude(kSequencer.kPosition.X, kSequencer.kPosition.Y);

			const float fDistanceX	= kScale.x;
			const float fDistanceY	= kScale.y * ((float)nHeightB - (float)nHeightA);
			const float fHeight		= nHeightB > nHeightA ? 2.0f * kScale.y : kScale.y;

			const float fB = (fHeight - 0.25f * fDistanceY) / (-0.25f * fDistanceX + 0.5f * fDistanceX);
			const float fA = (fDistanceY - fB * fDistanceX) / (fDistanceX * fDistanceX);
			const float fX = kSequencer.fTimer * fDistanceX;

			kWorldPosition.x = kScale.x * ((int32)kPosition.X + kSequencer.fTimer * ((int32)kSequencer.kPosition.X - (int32)kPosition.X));
			kWorldPosition.y = nHeightA * kScale.y + fX * (fA * fX + fB);
			kWorldPosition.z = kScale.z * ((int32)kPosition.Y + kSequencer.fTimer * ((int32)kSequencer.kPosition.Y - (int32)kPosition.Y));
		}
	}

	return kWorldPosition;
}

/*
 * GetWorldOrientation
 */
const D3DXVECTOR3 Bot::GetWorldOrientation() const
{
	D3DXVECTOR3 kWorldOrientation;
	kWorldOrientation.x = 0.0f;
	kWorldOrientation.y = DirectionAngle[kDirection];
	kWorldOrientation.z = 0.0f;

	if(nState == BotState_Animate)
	{
		if(kSequencer.nSequence == BotSequence_RotateCW || kSequencer.nSequence == BotSequence_RotateCCW)
		{
			kWorldOrientation.y = InterpolateDirection(kDirection, kSequencer.kDirection, kSequencer.fTimer);
		}
	}

	return kWorldOrientation;
}

/*
 * AddFunction
 */
void Bot::AddFunction(uint32 nFunction, uint32 nSize)
{
	kMachine.AddFunction((uint8)nFunction, (uint8)nSize * 2);
}

/*
 * Upload
 */
ErrorCode Bot::Upload(Code* pCode, uint32 nCount)
{
	ErrorCode eCode = Error_Success;

	for(uint32 i = 0; i < nCount && eCode == Error_Success; ++i)
	{
		uint32 nSize = kMachine.GetFunctionSize(i);
		uint8* pData = kMachine.GetFunctionMemory(i);

		eCode = Compile(pCode + i, pData, nSize);
	}

	nState = BotState_Evaluate;

	return eCode;
}

/*
 * Compile
 */
ErrorCode Bot::Compile(Code* pInstance, uint8* pData, uint32 nSize)
{
	const uint32 nLength = pInstance->GetLength();

	for(uint32 i = 0; i < nLength; ++i)
	{
		const uint32 nAction = pInstance->GetSlot(i);

		if(Action_Forward <= nAction && nAction <= Action_Light)
		{
			if(nSize < 2)
				return Error_Fail;

			*pData++ = Instruction_Action;
			*pData++ = nAction;

			nSize -= 2;
		}
		else

		if(Action_FunctionA <= nAction && nAction <= Action_FunctionB)
		{
			if(nSize < 2)
				return Error_Fail;

			*pData++ = Instruction_Call;
			*pData++ = nAction - Action_FunctionA + 1;

			nSize -= 2;
		}
	}

	return Error_Success;
}

/*
 * Update
 */
void Bot::Update(float fElapsed)
{
	if(nState == BotState_Evaluate)
	{
		bool bHandled = false;

		kClock.Reset();

		while(!bHandled && kClock.GetElapsed(false) < fElapsed)
		{
			uint32 nAction = kMachine.Step();

			if(Action_Forward <= nAction && nAction <= Action_Light)
			{
				if(nAction == Action_Forward)
				{
					if(pEnvironment->IsMovementValid(nAction, kPosition.X, kPosition.Y, kDirection))
					{
						kSequencer.kPosition.X	= (int32)kPosition.X + DirectionStepX[kDirection];
						kSequencer.kPosition.Y	= (int32)kPosition.Y + DirectionStepY[kDirection];
						kSequencer.nSequence	= BotSequence_Forward;
						kSequencer.fTimer		= 0.0f;
						kSequencer.fSpeed		= 1.5f;
						nState					= BotState_Animate;
					}
				}
				else

				if(nAction == Action_RotateCW)
				{
					kSequencer.kDirection		= (kDirection + 1) % Direction_Count;
					kSequencer.nSequence		= BotSequence_RotateCW;
					kSequencer.fTimer			= 0.0f;
					kSequencer.fSpeed			= 1.5f;
					nState						= BotState_Animate;
				}
				else

				if(nAction == Action_RotateCCW)
				{
					nState						= BotState_Animate;
					kSequencer.kDirection		= (kDirection - 1 + Direction_Count) % Direction_Count;
					kSequencer.nSequence		= BotSequence_RotateCCW;
					kSequencer.fTimer			= 0.0f;
					kSequencer.fSpeed			= 1.5f;
				}
				else

				if(nAction == Action_Jump)
				{
					if(pEnvironment->IsMovementValid(nAction, kPosition.X, kPosition.Y, kDirection))
					{
						kSequencer.kPosition.X	= (int32)kPosition.X + DirectionStepX[kDirection];
						kSequencer.kPosition.Y	= (int32)kPosition.Y + DirectionStepY[kDirection];
					}
					else
					{
						kSequencer.kPosition.X	= kPosition.X;
						kSequencer.kPosition.Y	= kPosition.Y;
					}

					nState					= BotState_Animate;
					kSequencer.nSequence	= BotSequence_Jump;
					kSequencer.fTimer		= 0.0f;
					kSequencer.fSpeed		= 1.5f;
				}
				else

				if(nAction == Action_Light)
				{
					nState					= BotState_Animate;
					nColor					= D3DCOLOR_XRGB(0, 0, 255);
					kSequencer.nSequence	= BotSequence_Light;
					kSequencer.fTimer		= 0.0f;
					kSequencer.fSpeed		= 3.0f;
				}

				bHandled = true;
			}
		}
	}
	else

	if(nState == BotState_Animate)
	{
		kSequencer.fTimer += kSequencer.fSpeed * fElapsed;
		if(kSequencer.fTimer >= 1.0f)
		{
			if(kSequencer.nSequence == BotSequence_Forward)
			{
				nState				= BotState_Pause;
				kPosition			= kSequencer.kPosition;
				kSequencer.fTimer	= 0.4f;
			}
			else

			if(kSequencer.nSequence == BotSequence_RotateCW)
			{
				nState				= BotState_Pause;
				kDirection			= kSequencer.kDirection;
				kSequencer.fTimer	= 0.4f;
			}
			else

			if(kSequencer.nSequence == BotSequence_RotateCCW)
			{
				nState				= BotState_Pause;
				kDirection			= kSequencer.kDirection;
				kSequencer.fTimer	= 0.4f;
			}
			else

			if(kSequencer.nSequence == BotSequence_Jump)
			{
				nState				= BotState_Pause;
				kPosition			= kSequencer.kPosition;
				kSequencer.fTimer	= 0.4f;
			}
			else

			if(kSequencer.nSequence == BotSequence_Light)
			{
				pEnvironment->NotifyAction(kPosition.X, kPosition.Y);
					
				nState				= BotState_Pause;
				nColor				= D3DCOLOR_XRGB(0, 255, 0);
				kSequencer.fTimer	= 0.4f;
			}
		}
	}
	else

	if(nState == BotState_Pause)
	{
		kSequencer.fTimer -= fElapsed;
		if(kSequencer.fTimer <= 0.0f)
		{
			nState = BotState_Evaluate;
		}
	}
}