본문으로 바로가기

DX11_2020_0806_목_FX

category DX11 2D Game Programming 2020. 8. 5. 23:03

200806_FX.zip
1.25MB

 

 

0. Effect(FX)

  a. Sprite, Action 으로 구성된 Framework 에서 작동하도록 기존 코드 수정

더보기
#pragma once

class FX : public Transform
{
private:
	Sprite* sprite;
	Action* action;
	bool isActive;
	//

public:
	FX(string path, string file, Action::Type type = Action::Type::END, float speed = 0.1f);
	~FX();
	//
	void Update();
	void Render();
	//
	void Play(Vector2 pos);
	void End();
	//
	bool Active() { return isActive; }
	//
	virtual void LoadAction(string path, string file, Action::Type type, float speed = 0.1f);
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "FX.h"

FX::FX(string path, string file, Action::Type type, float speed)
	:sprite(nullptr), isActive(false)
{
	sprite = new Sprite;
	LoadAction(path, file + ".xml", type, speed);
	action->SetEndEvent(bind(&FX::End, this));
}

FX::~FX()
{
	if (sprite)
	{
		delete sprite;
		sprite = nullptr;
	}
	//
	delete action;
}

void FX::Update()
{
	if (!isActive)
		return;

	Action::Clip curClip = action->GetCurClip();
	sprite->SetAction(curClip);
	//
	action->Update();
	//sprite->Update();
	//
	scale = curClip.size;
	//
	UpdateWorld();
}

void FX::Render()
{
	if (!isActive)
		return;

	SetWorldBuffer();
	//
	sprite->Render();
}

void FX::Play(Vector2 pos)
{
	this->pos = pos;
	isActive = true;
	action->Play();
}

void FX::End()
{
	isActive = false;
	//action->Stop();
}

void FX::LoadAction(string path, string file, Action::Type type, float speed)
{
	XmlDocument* document = new XmlDocument();
	document->LoadFile((path + file).c_str());
	//
	XmlElement* atlas = document->FirstChildElement();
	//
	string fileName = atlas->Attribute("imagePath");
	fileName = path + fileName;
	//
	wstring imagePath{};
	imagePath.assign(fileName.begin(), fileName.end()); // string -> wstring
	//
	Texture* texture = Texture::Add(imagePath);
	//
	vector<Action::Clip> clips{};
	XmlElement* sprite = atlas->FirstChildElement();
	//
	while (sprite != nullptr)
	{
		float x{}, y{}, w{}, h{};
		x = sprite->FloatAttribute("x");
		y = sprite->FloatAttribute("y");
		w = sprite->FloatAttribute("w");
		h = sprite->FloatAttribute("h");
		clips.emplace_back(x, y, w, h, texture);
		//
		sprite = sprite->NextSiblingElement();
	}
	//
	action = new Action(clips, type, speed);
	//
	delete document;
}

 

0. Effect Manager(FXManager)

  a. Sprite, Action 으로 구성된 Framework 에서 작동하도록 기존 코드 수정

더보기
#pragma once

class FXManager
{
private:
	//map<string, vector<FX*>> totalEffect;
	typedef vector<FX*> Effects;
	map<string, Effects> totalEffect;
	//
private:
	FXManager();
	~FXManager();

public:
	static FXManager* Get()
	{
		static FXManager instance;
		return &instance;
	}
	//
	void Update();
	void Render();
	//
	void Add(string key, string path, string file, int poolCount,
		Action::Type type = Action::Type::END, float speed = 0.1f);
	//void Add(string key, Texture* texture, int poolCount, double speed = 0.1);
	//void Add(string key, Texture* texture, int poolCount, Vector2 size, double speed = 0.1);
	void Play(string key, Vector2 pos);
	void Play(string key, Vector2 pos, Vector2 size);
	void Stop();
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "FXManager.h"

FXManager::FXManager()
{
}

FXManager::~FXManager()
{
	for (auto effects : totalEffect)
		for (FX* effect : effects.second)
			delete effect;
}

void FXManager::Update()
{
	for (auto effects : totalEffect)
		for (FX* effect : effects.second)
			effect->Update();
}

void FXManager::Render()
{
	for (auto effects : totalEffect)
		for (FX* effect : effects.second)
			effect->Render();
}

void FXManager::Add(string key, string path, string file, int poolCount,
	Action::Type type, float speed)
{
	Effects effects;
	for (int i = 0; i < poolCount; ++i)
		effects.emplace_back(new FX(path, file, type, speed));
	//
	totalEffect[key] = effects;
}

//void FXManager::Add(string key, Texture* texture, int poolCount, double speed)
//{
//	Effects effects;
//	for (int i = 0; i < poolCount; ++i)
//		effects.emplace_back(new FX(texture, speed));
//	//
//	totalEffect[key] = effects;
//}
//
//void FXManager::Add(string key, Texture* texture, int poolCount, Vector2 size, double speed)
//{
//	Effects effects;
//	for (int i = 0; i < poolCount; ++i)
//	{
//		FX* fx = new FX(texture, speed);
//		fx->SetSize(size);
//		effects.emplace_back(fx);
//	}
//	//
//	totalEffect[key] = effects;
//}

void FXManager::Play(string key, Vector2 pos)
{
	if (totalEffect.count(key) == 0)
		return;

	for (FX* effect : totalEffect[key])
		if (!effect->Active())
		{
			effect->Play(pos);
			return;
		}
}

void FXManager::Play(string key, Vector2 pos, Vector2 size)
{
	if (totalEffect.count(key) == 0)
		return;

	for (FX* effect : totalEffect[key])
		if (!effect->Active())
		{
			//effect->SetSize(size);
			effect->Play(pos);
			return;
		}
}

void FXManager::Stop()
{
	for (auto effects : totalEffect)
		for (FX* effect : effects.second)
			effect->End();
}

 

0. Character class

  a. Player와 Enemy class의 Parent class. 공통으로 사용되는 기능 구현, 상속

  b. sprite, collider 생성 및 Action(Animation) 관련 기능

더보기
#pragma once

class SunnyLandScene;

class Character : public Transform
{
public:
	enum ActionType
	{
		AT_0,
		AT_1,
		AT_2,
		AT_3,
		AT_4,
		AT_5,
	};

protected:
	SunnyLandScene* scene;
	//
	Sprite* sprite;
	Collider* collider;
	//
	vector<Action*> actions;
	ActionType curAction;
	//
	bool isRight;

public:
	Character();
	virtual ~Character();
	//
	virtual void Update();
	virtual void Render();
	virtual void PostRender();
	//
	virtual void SetPos(Vector2 pos) { this->pos = pos; }
	//
	virtual void LoadAction(string path, string file, Action::Type type, float speed = 0.1f);
	virtual void SetAction(int type);
	//
	virtual void SetScene(SunnyLandScene* value) { scene = value; }
	//
	virtual Collider* GetCollider() { return collider; }
	//
	virtual void Destroy();
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Character.h"
#include "Scenes/SunnyLandScene.h"

Character::Character()
	:sprite(nullptr), collider(nullptr),
	curAction(AT_0), isRight(true)
{
	isActive = false;
}

Character::~Character()
{
	if (sprite)
	{
		delete sprite;
		sprite = nullptr;
	}
	if (collider)
	{
		delete collider;
		collider = nullptr;
	}
	//
	if (actions.empty() == false)
	{
		for (auto action : actions)
			delete action;
		actions.clear();
	}
}

void Character::Update()
{
	if (!isActive)
		return;

	Action::Clip curClip = actions[curAction]->GetCurClip();
	sprite->SetAction(curClip);
	//
	actions[curAction]->Update();
	//sprite->Update();
	//
	scale.x = isRight ? curClip.size.x : -curClip.size.x; // scale로 좌우 flip
	scale.y = curClip.size.y;
	//
	UpdateWorld();
	//
	collider->Update();
}

void Character::Render()
{
	if (!isActive)
		return;
	//
	SetWorldBuffer();
	//
	sprite->Render();
	//
	collider->Render();
}

void Character::PostRender()
{
}

void Character::LoadAction(string path, string file, Action::Type type, float speed)
{
	XmlDocument* document = new XmlDocument();
	document->LoadFile((path + file).c_str());
	//
	XmlElement* atlas = document->FirstChildElement();
	//
	string fileName = atlas->Attribute("imagePath");
	fileName = path + fileName;
	//
	wstring imagePath{};
	imagePath.assign(fileName.begin(), fileName.end()); // string -> wstring
	//
	Texture* texture = Texture::Add(imagePath);
	//
	vector<Action::Clip> clips{};
	XmlElement* sprite = atlas->FirstChildElement();
	//
	while (sprite != nullptr)
	{
		float x{}, y{}, w{}, h{};
		x = sprite->FloatAttribute("x");
		y = sprite->FloatAttribute("y");
		w = sprite->FloatAttribute("w");
		h = sprite->FloatAttribute("h");
		clips.emplace_back(x, y, w, h, texture);
		//
		sprite = sprite->NextSiblingElement();
	}
	//
	actions.emplace_back(new Action(clips, type, speed));
	//
	delete document;
}

void Character::SetAction(int type)
{
	if (curAction != (ActionType)type)
	{
		curAction = (ActionType)type;
		actions[curAction]->Play();
	}
}

void Character::Destroy()
{
	isActive = false;
	FXM->Play("Destroy", pos);
}

 

0. Player

  a. Enemy와 접촉시 피해 및 Player 넉백 구현

    - Physics() 함수로 가로축, 세로축 힘 적용된 움직임 구현

  b. Enemy와 Jump 상태에서 Player(상)<->Enemy(하) 충돌시 Enemy 처치

  c. Item 획득시 Effect 출력

더보기
#pragma once

class Player : public Character
{
public:
	enum ActionType_Player
	{
		IDLE,
		JUMP_UP,
		JUMP_DOWN,
		RUN,
		HURT,
	};
	//
	float speed;
	//
	float gravity;
	float forceOfJump;
	bool isJump;
	//
	float hurtTimeCounter;
	float hurtTime;
	bool isHurt;
	//
	int curHP;
	int maxHP;
	//
	float horizontal_Force;
	float vertical_Force;

public:
	Player();
	~Player();
	// Character을(를) 통해 상속됨
	virtual void Update() override;
	virtual void Render() override;
	virtual void PostRender() override;
	//
	void Physics();
	//
	void HurtCount();
	//
	void Control();
	void Move();
	void Jump();
	void Stamping();
	//
	void Damage(Vector2 dir);
	void NuckBack(Vector2 dir);
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Player.h"
#include "Scenes/SunnyLandScene.h"

Player::Player()
	: speed(200.0f), gravity(980.0f), forceOfJump(300.0f), isJump(false),
	curHP(10), maxHP(10), hurtTime(1.0f), hurtTimeCounter(0), isHurt(false),
	horizontal_Force(0), vertical_Force(0)
{
	sprite = new Sprite;
	// Set actions
	string path = "Textures/Player/";
	LoadAction(path, "Player_Idle.xml", Action::LOOP);
	LoadAction(path, "Player_Jump_Up.xml", Action::LOOP);
	LoadAction(path, "Player_Jump_Down.xml", Action::LOOP);
	LoadAction(path, "Player_Run.xml", Action::LOOP);
	LoadAction(path, "Player_Hurt.xml", Action::LOOP);
	// Set Collider
	collider = new RectCollider(actions[curAction]->GetCurClip().size, this);
	collider->isActive = true;
	//
	FXM->Add("GetItem", "Textures/FX/", "GetItem", 10);
}

Player::~Player()
{
}

void Player::Update()
{
	Physics();
	HurtCount();
	Control();
	Character::Update();
}

void Player::Render()
{
	Character::Render();
}

void Player::PostRender()
{
	Character::PostRender();
	ImGui::Text("[HP]");
	ImGui::Text("%d / %d", curHP, maxHP);
	ImGui::Text("[Physics]");
	ImGui::Text("hForce : %f / vForce : %f", horizontal_Force, vertical_Force);
	ImGui::Text("isJump : %d", isJump);

}

void Player::Physics()
{
	if (pos.y < scene->groundLevel - 0.01f)
	{
		pos.y = scene->groundLevel;
		vertical_Force = 0;
		//
		if (isJump)
		{
			SetAction(IDLE);
			isJump = false;
		}
	}
	//
	if (horizontal_Force == 0 && vertical_Force == 0)
		return;
	//
	horizontal_Force -= horizontal_Force * DELTA;
	vertical_Force -= gravity * DELTA;
	//
	if (abs(horizontal_Force) < 0.01f)
		horizontal_Force = 0;
	//
	pos.x += horizontal_Force * DELTA;
	pos.y += vertical_Force * DELTA;
}

void Player::HurtCount()
{
	if (!isHurt)
		return;
	//
	hurtTimeCounter -= DELTA;
	//
	if (hurtTimeCounter < 0)
	{
		hurtTimeCounter = hurtTime;
		isHurt = false;
		SetAction(IDLE);
	}
}

void Player::Control()
{
	if (isHurt)
		return;

	Move();
	Jump();
}

void Player::Move()
{
	if (KEY_PRESS(VK_RIGHT))
	{
		if(!isJump)
			SetAction(RUN);
		pos.x += speed * DELTA;
		if (!isRight)
			isRight = true;
	}
	else if (KEY_PRESS(VK_LEFT))
	{
		if(!isJump)
			SetAction(RUN);
		pos.x -= speed * DELTA;
		if (isRight)
			isRight = false;
	}
	//
	if (KEY_UP(VK_RIGHT) || KEY_UP(VK_LEFT))
		SetAction(IDLE);
}

void Player::Jump()
{
	if (KEY_DOWN(VK_LCONTROL) && !isJump)
	{
		vertical_Force = forceOfJump;
		SetAction(JUMP_UP);
		isJump = true;
	}

	if(isJump)
		if (vertical_Force <= 0)
			SetAction(JUMP_DOWN);
}

void Player::Stamping()
{
	vertical_Force = forceOfJump * 0.5f;
	SetAction(JUMP_UP);
}


void Player::Damage(Vector2 dir)
{
	if (isHurt)
		return;
	//
	isHurt = true;
	--curHP;
	SetAction(HURT);
	NuckBack(dir);
}

void Player::NuckBack(Vector2 dir)
{
	float nuckBackForce = 100.0f;
	horizontal_Force = dir.x * nuckBackForce;
	vertical_Force = forceOfJump * 0.8f;
	isJump = true;
}

 

0. Enemy (Type : Frog)

  a. 랜덤으로 좌우 Jump 이동하는 AI 구현(Player::Physics 함수 변경하여 적용)

더보기
#pragma once

class Enemy_Frog : public Character
{
public:
	enum ActionType_Player
	{
		IDLE,
		JUMP_UP,
		JUMP_DOWN,
	};
	//
private:
	float speed;
	//
	float gravity;
	float forceOfJump;
	bool isJump;
	//
	float horizontal_Force;
	float vertical_Force;
	//
	Vector2 dir;
	float jumpTime;
	float jumpCounter;

public:
	Enemy_Frog();
	~Enemy_Frog();
	//
	virtual void Update() override;
	virtual void Render() override;
	virtual void PostRender() override;
	//
	void Destroy();
	//
	void Physics();
	void AI();
	void Jump();
	bool JumpTimer();
	void RandomDir();
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Enemy_Frog.h"
#include "Scenes/SunnyLandScene.h"

Enemy_Frog::Enemy_Frog()
	: speed(400.0f), gravity(980.0f), forceOfJump(300.0f), isJump(false),
	horizontal_Force(0), vertical_Force(0),
	dir(1.0f, 0), jumpTime(5.0f), jumpCounter(0)

{
	sprite = new Sprite;
	//
	string path = "Textures/Enemies/Frog/";
	LoadAction(path, "Enemy_Frog_Idle.xml", Action::LOOP);
	LoadAction(path, "Enemy_Frog_Jump_Up.xml", Action::LOOP);
	LoadAction(path, "Enemy_Frog_Jump_Down.xml", Action::LOOP);
	//
	collider = new RectCollider(actions[curAction]->GetCurClip().size, this);
	collider->isActive = true;
	//
	FXM->Add("Destroy", "Textures/FX/", "Destroy", 10);
}

Enemy_Frog::~Enemy_Frog()
{
}

void Enemy_Frog::Update()
{
	if (!isActive)
		return;
	
	Physics();
	AI();
	Character::Update();
}

void Enemy_Frog::Render()
{
	if (!isActive)
		return;

	Character::Render();
}

void Enemy_Frog::PostRender()
{
	Character::PostRender();
	ImGui::Text("[JumpTimer] : %f", jumpCounter);
}

void Enemy_Frog::Destroy()
{
	Character::Destroy();
}

void Enemy_Frog::Physics()
{
	if (pos.x < 100.0f || pos.x > WIN_WIDTH - 100.0f)
		horizontal_Force = 0;
	//
	if (pos.y < scene->groundLevel - 0.01f)
	{
		pos.y = scene->groundLevel;
		vertical_Force = 0;
		horizontal_Force = 0;
		//
		if (isJump)
		{
			SetAction(IDLE);
			isJump = false;
		}
	}
	//
	if (isJump)
		if (vertical_Force <= 0)
			SetAction(JUMP_DOWN);
	//
	if (horizontal_Force == 0 && vertical_Force == 0)
		return;
	//
	horizontal_Force -= horizontal_Force * DELTA;
	vertical_Force -= gravity * DELTA;
	//
	if (abs(horizontal_Force) < 0.01f)
		horizontal_Force = 0;
	//
	pos.x += horizontal_Force * DELTA;
	pos.y += vertical_Force * DELTA;
}

void Enemy_Frog::AI()
{
	if (JumpTimer())
	{
		RandomDir();
		Jump();
	}
}

void Enemy_Frog::Jump()
{
	horizontal_Force = forceOfJump * dir.x * 1.2f;
	vertical_Force = forceOfJump;
	SetAction(JUMP_UP);
	isJump = true;
}

bool Enemy_Frog::JumpTimer()
{
	if (isJump)
		return false;

	jumpCounter -= DELTA;
	//
	if (jumpCounter < 0)
	{
		jumpCounter = jumpTime;
		return true;
	}
	else
		return false;

}

void Enemy_Frog::RandomDir()
{
	dir.x = (rand() % 2 == 0) ? 1.0f : -1.0f;
	isRight = (dir.x == -1.0f);
}

 

0. Item ( Type : Cherry, Gem )

  a. 다양한 종류의 Item의 parent class

  b. 획득시 이펙트 출력

  c. 아이템 효과는 자식클래스에서 overriding - (미구현)

더보기
#pragma once

class Item : public Transform
{
protected:
	SunnyLandScene* scene;
	//
	Sprite* sprite;
	Collider* collider;
	//
	Action* action; // only have Idle Motion

public:
	Item();
	virtual ~Item();
	//
	virtual void Update();
	virtual void Render();
	virtual void PostRender();
	//
	virtual void LoadAction(string path, string file, Action::Type type, float speed = 0.1f);
	//
	virtual void SetPos(Vector2 pos) { this->pos = pos; }
	virtual void SetScene(SunnyLandScene* value) { scene = value; }
	//
	virtual void Destroy();
	//
	virtual Collider* GetCollider() { return collider; }
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Item.h"

Item::Item()
	:sprite(nullptr), collider(nullptr), scene(nullptr), action(nullptr)
{
	FXM->Add("GetItem", "Textures/FX/", "GetItem", 10);
}

Item::~Item()
{
	if (sprite)
	{
		delete sprite;
		sprite = nullptr;
	}
	if (collider)
	{
		delete collider;
		collider = nullptr;
	}
	if (action)
	{
		delete action;
		action = nullptr;
	}
	if (scene)
		scene = nullptr;
}

void Item::Update()
{
	if (!isActive)
		return;
	//
	Action::Clip curClip = action->GetCurClip();
	sprite->SetAction(curClip);
	//
	action->Update();
	sprite->Update();
	//
	scale = curClip.size;
	//
	UpdateWorld();
	//
	collider->Update();
}

void Item::Render()
{
	if (!isActive)
		return;
	//
	SetWorldBuffer();
	//
	sprite->Render();
	//
	collider->Render();
}

void Item::PostRender()
{
	if (!isActive)
		return;
}

void Item::LoadAction(string path, string file, Action::Type type, float speed)
{
	XmlDocument* document = new XmlDocument();
	document->LoadFile((path + file).c_str());
	//
	XmlElement* atlas = document->FirstChildElement();
	//
	string fileName = atlas->Attribute("imagePath");
	fileName = path + fileName;
	//
	wstring imagePath{};
	imagePath.assign(fileName.begin(), fileName.end()); // string -> wstring
	//
	Texture* texture = Texture::Add(imagePath);
	//
	vector<Action::Clip> clips{};
	XmlElement* sprite = atlas->FirstChildElement();
	//
	while (sprite != nullptr)
	{
		float x{}, y{}, w{}, h{};
		x = sprite->FloatAttribute("x");
		y = sprite->FloatAttribute("y");
		w = sprite->FloatAttribute("w");
		h = sprite->FloatAttribute("h");
		clips.emplace_back(x, y, w, h, texture);
		//
		sprite = sprite->NextSiblingElement();
	}
	// 단일 action
	action = new Action(clips, type, speed);
	//
	delete document;
}

void Item::Destroy()
{
	isActive = false;
	FXM->Play("GetItem", pos);
}
#pragma once

#include "Item.h"

class Item_Cherry : public Item
{
public:
	Item_Cherry();
	~Item_Cherry();
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Item_Cherry.h"

Item_Cherry::Item_Cherry()
{
	sprite = new Sprite;
	//
	string path = "Textures/Items/";
	LoadAction(path, "Item_Cherry.xml", Action::LOOP);
	//
	collider = new RectCollider(action->GetCurClip().size, this);
	collider->isActive = true;
}

Item_Cherry::~Item_Cherry()
{
}

 

0. BackGround

  a. Transfrom class 상속

  b. member 변수 : sprite

  c. member 함수 : Render()

  d. Sprite::SetTexture(wstring file) 함수를 사용, sprite에 texture 할당

더보기
void Sprite::SetTexture(wstring file)
{
	texture = Texture::Add(file);
}
#pragma once

#include "Object/BasicObject/Sprite.h"
#include "Framework/Math/Transform.h"

class BackGround : public Transform
{
private:
	Sprite* sprite;
	//
public:
	BackGround();
	~BackGround();
	//
	void Render();
	void Init();
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "BackGround.h"

BackGround::BackGround()
{
	Init();
}

BackGround::~BackGround()
{
	if (sprite)
	{
		delete sprite;
		sprite = nullptr;
	}
}

void BackGround::Render()
{
	if (!isActive)
		return;
	//
	SetWorldBuffer();
	sprite->Render();
}

void BackGround::Init()
{
	sprite = new Sprite;
	//
	wstring file = L"Textures/bg.png";
	sprite->SetTexture(file);
	//
	//Action::Clip curClip(0, 0, sprite->GetSize().x, sprite->GetSize().y, sprite->GetTexture());
	Action::Clip curClip(0, 0, WIN_WIDTH, sprite->GetSize().y, sprite->GetTexture());
	sprite->SetAction(curClip);
	//
	scale = curClip.size;
	//
	pos = { WIN_WIDTH * 0.5f, sprite->GetSize().y };
	UpdateWorld();
}

 

0. Game Scene

  a. 상속관계를 이용하여 Character, Item class 를 일괄 처리

더보기
#pragma once

#include "Object/GameObject/Item.h"
#include "Object/GameObject/Item_Cherry.h"
#include "Object/GameObject/Item_Gem.h"
#include "Object/GameObject/BackGround.h"

class SunnyLandScene : public Scene
{
private:
	Character* player;
	vector<Character*> enemies;
	vector<Item*> items;
	BackGround* bg;

public:
	float groundLevel;
	

public:
	SunnyLandScene();
	~SunnyLandScene();
	// Scene을(를) 통해 상속됨
	virtual void Update() override;
	virtual void Render() override;
	virtual void PostRender() override;
	//
	void InitObejcts();
	void ReleaseObjects();
	//
	void Collision();
	void CollisionPlayerToEnemy();
	void CollisionPlayerToItem();
};
/////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "SunnyLandScene.h"

SunnyLandScene::SunnyLandScene()
	:groundLevel(100.0f)
{
	InitObejcts();
}

SunnyLandScene::~SunnyLandScene()
{
	ReleaseObjects();
}

void SunnyLandScene::Update()
{
	player->Update();
	//
	for (auto enemy : enemies)
		enemy->Update();
	//
	for (auto item : items)
		item->Update();
	//
	Collision();
}

void SunnyLandScene::Render()
{
	bg->Render();
	//
	player->Render();
	//
	for (auto enemy : enemies)
		enemy->Render();
	//
	for (auto item : items)
		item->Render();
}

void SunnyLandScene::PostRender()
{
	player->PostRender();
	//
	for (auto enemy : enemies)
		enemy->PostRender();
	//
	for (auto item : items)
		item->PostRender();
}

void SunnyLandScene::InitObejcts()
{
	/* BackGround */
	bg = new BackGround;

	/* Make Player */
	player = new Player;
	player->SetPos({ 100, groundLevel });
	player->isActive = true;
	player->SetScene(this);

	/* Make Enemies */
	Character* enemy{};
	enemy = new Enemy_Frog;
	enemy->SetPos({ (float)WIN_WIDTH * 0.8f, groundLevel });
	enemy->isActive = true;
	enemy->SetScene(this);
	enemies.emplace_back(enemy);

	/* Make Items */
	Item* item{};
	item = new Item_Cherry;
	item->SetPos({ (float)WIN_WIDTH * 0.2f, groundLevel });
	item->SetScene(this);
	items.emplace_back(item);
	//
	item = new Item_Gem;
	item->SetPos({ (float)WIN_WIDTH * 0.4f, groundLevel });
	item->SetScene(this);
	items.emplace_back(item);
}

void SunnyLandScene::ReleaseObjects()
{
	delete player;
	player = nullptr;
	//
	for (auto enemy : enemies)
		delete enemy;
	enemies.clear();
	//
	for (auto item : items)
		delete item;
	items.clear();
	//
	delete bg;
}

void SunnyLandScene::Collision()
{
	CollisionPlayerToEnemy();
	CollisionPlayerToItem();
}

void SunnyLandScene::CollisionPlayerToEnemy()
{
	Player* playerDownCast = dynamic_cast<Player*>(player);
	//
	for (auto enemy : enemies)
	{
		if (enemy->isActive == false)
			continue;
		//
		if (player->GetCollider()->IsCollision(enemy->GetCollider()) == true)
		{
			float playerBottom = player->GetCollider()->WorldPos().y
				- (player->GetCollider()->GetSize().y * 0.5f);
			float enemyTop = enemy->GetCollider()->WorldPos().y
				+ (enemy->GetCollider()->GetSize().y * 0.5f);
			//
			if ((playerDownCast->vertical_Force < 0) && (playerBottom > enemyTop))
			{
				enemy->Destroy();
				playerDownCast->Stamping();
				return;
			}
			else
			{
				Vector2 dir = (player->pos - enemy->pos).Normal();
				playerDownCast->Damage(dir);
				return;
			}
		}
	}
}

void SunnyLandScene::CollisionPlayerToItem()
{
	for (auto item : items)
	{
		if (item->isActive == false)
			continue;
		//
		if (player->GetCollider()->IsCollision(item->GetCollider()) == true)
		{
			item->Destroy();
			// Get Point or HP
			return;
		}
	}
}

'DX11 2D Game Programming' 카테고리의 다른 글

DX11_2020_0810_월_Top-Down_Shooting  (0) 2020.08.10
DX11_2020_0807_금_Camera  (0) 2020.08.07
DX11_2020_0730_목_Animation(XML)  (0) 2020.07.30
DX11_2020_0729_수_Animation  (0) 2020.07.29
DX11_2020_0728_화_Collider Offset  (0) 2020.07.28