SpelunkyRemake / Spider.cpp
Spider.cpp
Raw
#include "pch.h"
#include "Spider.h"

Texture* Spider::m_pTextures{ nullptr };
int Spider::m_Count{ 0 };

Spider::Spider(int x, int y)
	: Spider{ Point2f{ x * Tile::m_Size, y * Tile::m_Size } }
{

}

Spider::Spider(const Point2f& pos)
	: Enemy{ pos }
	, m_ActionState{ ActionState::HANGING }
	, m_JumpTimer{ }
	, m_JumpDuration{ 0.5f }
	, m_JumpSpeed{ 620.f }
	, m_MoveSpeed{ 240.f }
	, m_JumpSFX{ "Resources/Sounds/spider_jump.wav" }
	, m_IdleDuration{ 1 }
	, m_IdleTimer{ }
	, m_BrakeSpeed { 250.f }
{
	m_Hitbox.width = 58;
	m_Hitbox.height = 36;
	m_HitboxMargin.x = 12;
	m_HitboxMargin.y = 19;

	m_Lives = 1;

	if (m_Count == 0)
	{
		m_pTextures = new Texture{ "Resources/Sprites/enemy_spider.png" };
	}
	m_pTexture = m_pTextures;

	SetAction(ActionState::HANGING);

	m_Count++;
}

Spider::~Spider()
{
	m_Count--;

	if (m_Count == 0)
	{
		delete m_pTextures;
		m_pTextures = nullptr;
	}
}

void Spider::Draw() const
{
	Enemy::Draw();
}

void Spider::Update(float elapsedSec, const Level& level, Player* pPlayer, ParticleManager* pParticleManager)
{
	if (m_ActionState != ActionState::HANGING)
	{
		if (!level.IsOnGround(m_Hitbox)) m_Velocity += elapsedSec * m_GravityAcceleration;

		if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec)
		{
			(m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec;
		}
		else
		{
			m_Velocity.x = 0;
		}

		m_Hitbox.bottom += m_Velocity.y * elapsedSec;
		m_Hitbox.left += m_Velocity.x * elapsedSec;

		level.HandleCollision(m_Hitbox, m_Velocity);
	}

	if (pPlayer->GetState() != Player::ActionState::HURT)
	{
		if (utils::IsOverlapping(m_Hitbox, pPlayer->GetHitbox()))
		{
			if (pPlayer->DidJumpOnEnemy(GetTopVertices()))
			{
				pParticleManager->CreateBlood(Point2f{ GetHitbox().left, GetHitbox().bottom });
				m_Lives--;
			}
			else
			{
				(pPlayer->GetHitbox().left < m_Hitbox.left) ? m_Direction = Direction::LEFT : m_Direction = Direction::RIGHT;

				pParticleManager->CreateBlood(Point2f{ pPlayer->GetHitbox().left, pPlayer->GetHitbox().bottom });

				pPlayer->Hit(1, int(m_Direction));
			}
		}
	}

	utils::HitInfo hitInfo{};

	switch (m_ActionState)
	{
	case ActionState::HANGING:
		if (utils::Raycast(pPlayer->GetTopVertices(), Point2f{ m_Hitbox.left + m_Hitbox.width / 2, m_Hitbox.bottom }, Point2f{ m_Hitbox.left + m_Hitbox.width / 2, m_Hitbox.bottom - Tile::m_Size * 6 }, hitInfo))
		{
			SetAction(ActionState::DROPPING);
			break;
		}
		break;
	case ActionState::DROPPING:
		if (level.IsOnGround(m_Hitbox))
		{
			SetAction(ActionState::IDLE);
			break;
		}
		break;

	case ActionState::IDLE:

		m_IdleTimer += elapsedSec;
		if (m_IdleTimer >= m_IdleDuration)
		{
			(pPlayer->GetHitbox().left < m_Hitbox.left) ? m_Velocity.x = -m_MoveSpeed : m_Velocity.x = m_MoveSpeed;
			SetAction(ActionState::JUMPING);
			break;
		}

		break;
	case ActionState::JUMPING:
		m_JumpTimer += elapsedSec;
		if (m_JumpTimer >= m_JumpDuration)
		{
			SetAction(ActionState::IDLE);
			break;
		}
		break;
	default:
		break;
	}

	m_AnimTime += elapsedSec;
	if (m_AnimTime >= 1.f / m_NrFramesPerSec)
	{
		m_AnimFrame++;
		if (m_AnimFrame >= m_AnimLength)
		{
			if (m_AnimLoop)
			{
				m_AnimFrame = 0;
			}
			else
			{
				m_AnimFrame = m_AnimLength;
			}
		}

		m_AnimTime = 0;
	}

	m_SpriteRect.left = m_Hitbox.left - m_HitboxMargin.x;
	m_SpriteRect.bottom = m_Hitbox.bottom - m_HitboxMargin.y;
}

void Spider::SetAction(ActionState action)
{
	m_ActionState = action;

	m_AnimFrame = 0;
	m_AnimLoop = true;

	switch (action)
	{
	case ActionState::IDLE:
		m_IdleTimer = 0;
		m_Velocity.x = 0;

		m_AnimFirstFrameId = 17;
		m_AnimLength = 4;
		m_NrFramesPerSec = 15;
		break;

	case ActionState::HANGING:
		m_AnimLoop = false;

		m_Velocity.x = 0;

		m_AnimFirstFrameId = 11;
		m_AnimLength = 0;
		m_NrFramesPerSec = 0;
		break;

	case ActionState::DROPPING:
		m_JumpSFX.Play(0);
		m_AnimLoop = false;

		m_JumpTimer = 0;
		m_Velocity.x = 0;

		m_AnimFirstFrameId = 11;
		m_AnimLength = 6;
		m_NrFramesPerSec = 12;
		break;

	case ActionState::JUMPING:
		m_Velocity.y += m_JumpSpeed;

		m_JumpTimer = 0;

		m_JumpSFX.Play(0);
		m_AnimLoop = false;

		m_AnimFirstFrameId = 7;
		m_AnimLength = 3;
		m_NrFramesPerSec = 8;
		break;

	default:
		break;
	}
}