view LightClone/Source/Bot.cpp @ 65:41980ff0607d

Added shader and textures for bot
author koryspansel <koryspansel@bendbroadband.com>
date Wed, 05 Oct 2011 12:55:46 -0700
parents 3507bd831c7f
children f7095bce01cf
line wrap: on
line source

/*
 * Bot
 */

#include "Bot.h"
#include "Clock.h"
#include "VertexTypes.h"

/*
 * DirectionAngle
 *	Angles for the different directions the bot could be facing
 */
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};

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

	pEffect			= NULL;
	pVertexBuffer	= NULL;
	pTexture		= NULL;
}

/*
 * Initialize
 */
ErrorCode Bot::Initialize(ServiceProvider* pServiceProvider)
{
	ResourceManager* pResourceManager = NULL;

	ErrorCode eCode = pServiceProvider->GetService("ResourceManager", &pResourceManager);
	if(eCode == Error_Success)
	{
		eCode = pResourceManager->CreateEffectFromFile("Data\\Shaders\\Bot.fx", &pEffect);
		if(eCode == Error_Success)
		{
			eCode = pResourceManager->CreateTextureFromFile("Data\\Textures\\Bot.tga", &pTexture);
			if(eCode == Error_Success)
			{
				eCode = pResourceManager->CreateTextureFromFile("Data\\Textures\\BotMask.tga", &pMask);
				if(eCode == Error_Success)
				{
					eCode = pResourceManager->CreateVertexBuffer(VerticesPerBlock * sizeof(Vertex::Block), D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED, &pVertexBuffer);
					if(eCode == Error_Success)
					{
						eCode = SetupVertexBuffer();
					}
				}
			}
		}
	}

	return eCode;
}

/*
 * Terminate
 */
void Bot::Terminate()
{
	if(pVertexBuffer)
	{
		pVertexBuffer->Release();
		pVertexBuffer = NULL;
	}
}

/*
 * Setup
 */
void Bot::Setup(Environment* pInstance)
{
	pEnvironment	= pInstance;
	nState			= BotState_Idle;
	nColor			= D3DCOLOR_XRGB(192, 0, 0);
}

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

	kMachine.Reset();
}

/*
 * SetPosition
 */
void Bot::SetPosition(const Position& kValue)
{
	kPosition = kValue;
}

/*
 * SetDirection
 */
void Bot::SetDirection(uint32 nValue)
{
	kDirection = nValue;
}

/* 
 * 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;
}

/*
 * Upload
 */
ErrorCode Bot::Upload(const Program& kProgram)
{
	ErrorCode eCode = kProgram.Upload(kMachine);
	if(eCode == Error_Success)
	{
		nState = BotState_Evaluate;
	}

	return eCode;
}

/*
 * Update
 */
bool 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 + GetOffsetFromDirectionX(kDirection);
						kSequencer.kPosition.Y	= (int32)kPosition.Y + GetOffsetFromDirectionY(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 + GetOffsetFromDirectionX(kDirection);
						kSequencer.kPosition.Y	= (int32)kPosition.Y + GetOffsetFromDirectionY(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, 192);
					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(192, 0, 0);
				kSequencer.fTimer	= 0.4f;
			}
		}
	}
	else

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

	return false;
}

/*
 * Render
 */
void Bot::Render(RenderContext& kContext, Camera& kCamera)
{
	const D3DXVECTOR3& kPosition	= GetWorldPosition();
	const D3DXVECTOR3& kOrientation	= GetWorldOrientation();

	const float fOffsetX	= -0.5f * (pEnvironment->GetWidth() * pEnvironment->GetScale().x) + 0.5f * pEnvironment->GetScale().x;
	const float fOffsetZ	= -0.5f * (pEnvironment->GetHeight() * pEnvironment->GetScale().z) + 0.5f * pEnvironment->GetScale().z;

	uint32 nPasses = 0;

	kContext.ApplyCameraToEffect(kCamera, pEffect);

	pEffect->SetTechnique(pEffect->GetTechnique(0));
	pEffect->Begin(&nPasses, 0);
	pEffect->BeginPass(0);

	D3DXMATRIX kScale;
	D3DXMatrixScaling(&kScale, kSize.x, kSize.y, kSize.z);

	D3DXMATRIX kTranslate;
	D3DXMatrixTranslation(&kTranslate, fOffsetX + kPosition.x, kPosition.y, fOffsetZ + kPosition.z);

	D3DXMATRIX kRotate;
	D3DXMatrixRotationY(&kRotate, kOrientation.y);

	D3DXMATRIX kTempMatrix;
	D3DXMATRIX kWorldMatrix;
	D3DXMatrixMultiply(&kWorldMatrix, D3DXMatrixMultiply(&kTempMatrix, &kScale, &kRotate), &kTranslate);

	const float fAlpha	= ((nColor >> 24) & 0xFF) / 255.0f;
	const float fRed	= ((nColor >> 16) & 0xFF) / 255.0f;
	const float fGreen	= ((nColor >> 8 ) & 0xFF) / 255.0f;
	const float fBlue	= ((nColor >> 0 ) & 0xFF) / 255.0f;

	const D3DXVECTOR4 kColorVector(fRed, fGreen, fBlue, fAlpha);

	pEffect->SetMatrix(pEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
	pEffect->SetVector(pEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
	pEffect->SetTexture(pEffect->GetParameterByName(NULL, "kTexture"), pTexture);
	pEffect->SetTexture(pEffect->GetParameterByName(NULL, "kTextureMask"), pMask);
	pEffect->CommitChanges();

	kContext.DrawTriangles(Vertex::Block::Declaration, pVertexBuffer, sizeof(Vertex::Block), FacesPerCube * TrianglesPerFace);

	pEffect->EndPass();
	pEffect->End();
}

/*
 * SetupVertexBuffer
 */
ErrorCode Bot::SetupVertexBuffer()
{
	Vertex::Block* pVertices = NULL;
	
	HRESULT hResult = pVertexBuffer->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
	if(FAILED(hResult))
	{
		return Error_Fail;
	}

	const float fU1	= 0.66f;
	const float fV1 = 0.66f;

	const float fScaleU = 64.0f / 320.0f;
	const float fScaleV = 128.0f / 128.0f;

	// right
	pVertices[0]	= Vertex::Block(-0.5f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, 3 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[1]	= Vertex::Block(-0.5f, 1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 3 * fScaleU + 0 * fScaleU, 0 * fScaleV);
	pVertices[2]	= Vertex::Block(+0.5f, 1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 3 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[3]	= Vertex::Block(-0.5f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, 3 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[4]	= Vertex::Block(+0.5f, 1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 3 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[5]	= Vertex::Block(+0.5f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, 3 * fScaleU + 1 * fScaleU, 1 * fScaleV);
	// left
	pVertices[6]	= Vertex::Block(+0.5f, 0.0f, +0.5f, 0.0f, 0.0f, +1.0f, 2 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[7]	= Vertex::Block(+0.5f, 1.0f, +0.5f, 0.0f, 0.0f, +1.0f, 2 * fScaleU + 0 * fScaleU, 0 * fScaleV);
	pVertices[8]	= Vertex::Block(-0.5f, 1.0f, +0.5f, 0.0f, 0.0f, +1.0f, 2 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[9]	= Vertex::Block(+0.5f, 0.0f, +0.5f, 0.0f, 0.0f, +1.0f, 2 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[10]	= Vertex::Block(-0.5f, 1.0f, +0.5f, 0.0f, 0.0f, +1.0f, 2 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[11]	= Vertex::Block(-0.5f, 0.0f, +0.5f, 0.0f, 0.0f, +1.0f, 2 * fScaleU + 1 * fScaleU, 1 * fScaleV);
	// back
	pVertices[12]	= Vertex::Block(-0.5f, 0.0f, +0.5f, -1.0f, 0.0f, 0.0f, 1 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[13]	= Vertex::Block(-0.5f, 1.0f, +0.5f, -1.0f, 0.0f, 0.0f, 1 * fScaleU + 0 * fScaleU, 0 * fScaleV);
	pVertices[14]	= Vertex::Block(-0.5f, 1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 1 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[15]	= Vertex::Block(-0.5f, 0.0f, +0.5f, -1.0f, 0.0f, 0.0f, 1 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[16]	= Vertex::Block(-0.5f, 1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 1 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[17]	= Vertex::Block(-0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.0f, 1 * fScaleU + 1 * fScaleU, 1 * fScaleV);
	// front
	pVertices[18]	= Vertex::Block(+0.5f, 0.0f, -0.5f, +1.0f, 0.0f, 0.0f, 0 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[19]	= Vertex::Block(+0.5f, 1.0f, -0.5f, +1.0f, 0.0f, 0.0f, 0 * fScaleU + 0 * fScaleU, 0 * fScaleV);
	pVertices[20]	= Vertex::Block(+0.5f, 1.0f, +0.5f, +1.0f, 0.0f, 0.0f, 0 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[21]	= Vertex::Block(+0.5f, 0.0f, -0.5f, +1.0f, 0.0f, 0.0f, 0 * fScaleU + 0 * fScaleU, 1 * fScaleV);
	pVertices[22]	= Vertex::Block(+0.5f, 1.0f, +0.5f, +1.0f, 0.0f, 0.0f, 0 * fScaleU + 1 * fScaleU, 0 * fScaleV);
	pVertices[23]	= Vertex::Block(+0.5f, 0.0f, +0.5f, +1.0f, 0.0f, 0.0f, 0 * fScaleU + 1 * fScaleU, 1 * fScaleV);
	// top
	pVertices[24]	= Vertex::Block(-0.5f, 1.0f, -0.5f, 0.0f, +1.0f, 0.0f, 4 * fScaleU + 0 * fScaleU, 0.0f * fScaleV + 0.5f * fScaleV);
	pVertices[25]	= Vertex::Block(-0.5f, 1.0f, +0.5f, 0.0f, +1.0f, 0.0f, 4 * fScaleU + 0 * fScaleU, 0.0f * fScaleV + 0.0f * fScaleV);
	pVertices[26]	= Vertex::Block(+0.5f, 1.0f, +0.5f, 0.0f, +1.0f, 0.0f, 4 * fScaleU + 1 * fScaleU, 0.0f * fScaleV + 0.0f * fScaleV);
	pVertices[27]	= Vertex::Block(-0.5f, 1.0f, -0.5f, 0.0f, +1.0f, 0.0f, 4 * fScaleU + 0 * fScaleU, 0.0f * fScaleV + 0.5f * fScaleV);
	pVertices[28]	= Vertex::Block(+0.5f, 1.0f, +0.5f, 0.0f, +1.0f, 0.0f, 4 * fScaleU + 1 * fScaleU, 0.0f * fScaleV + 0.0f * fScaleV);
	pVertices[29]	= Vertex::Block(+0.5f, 1.0f, -0.5f, 0.0f, +1.0f, 0.0f, 4 * fScaleU + 1 * fScaleU, 0.0f * fScaleV + 0.5f * fScaleV);
	// bottom
	pVertices[30]	= Vertex::Block(-0.5f, 0.0f, +0.5f, 0.0f, -1.0f, 0.0f, 5 * fScaleU + 0 * fScaleU, 0.5f * fScaleV + 0.5f * fScaleV);
	pVertices[31]	= Vertex::Block(-0.5f, 0.0f, -0.5f, 0.0f, -1.0f, 0.0f, 5 * fScaleU + 0 * fScaleU, 0.5f * fScaleV + 0.0f * fScaleV);
	pVertices[32]	= Vertex::Block(+0.5f, 0.0f, -0.5f, 0.0f, -1.0f, 0.0f, 5 * fScaleU + 1 * fScaleU, 0.5f * fScaleV + 0.0f * fScaleV);
	pVertices[33]	= Vertex::Block(-0.5f, 0.0f, +0.5f, 0.0f, -1.0f, 0.0f, 5 * fScaleU + 0 * fScaleU, 0.5f * fScaleV + 0.5f * fScaleV);
	pVertices[34]	= Vertex::Block(+0.5f, 0.0f, -0.5f, 0.0f, -1.0f, 0.0f, 5 * fScaleU + 1 * fScaleU, 0.5f * fScaleV + 0.0f * fScaleV);
	pVertices[35]	= Vertex::Block(+0.5f, 0.0f, +0.5f, 0.0f, -1.0f, 0.0f, 5 * fScaleU + 1 * fScaleU, 0.5f * fScaleV + 0.5f * fScaleV);

	pVertexBuffer->Unlock();

	return Error_Success;
}