DirectX 2D/DirectX 2D 게임

230114 과녁 게임 만들기

무면허 개발자 2023. 1. 14. 16:54
  • [x] 1. 좌우에서 목표물이 랜덤의 속도와 타이밍, 각도를 가지고 스폰
  • [x] 2. 목표물은 포물선을 그리면서 날라가기
  • [ ] 3. 중앙에 두개의 에임을 생성하고 가장 가까운 목표물 따라서 y값 맞추기
  • [x] 4. 에임에 들어왔을때 입력처리로 목표물 제거
  • [x] 5. 사운드 추가하기

날아오는 과녁을 맞추는 게임을 한창 유행했던 후르츠닌자 게임식으로 각색하여 만들어봄

과일은 총 6가지로 풀링기능을 사용하여 랜덤한 과일, 사이즈 , 속도를 가지고 스폰되며, 클릭하여 과일을 자르면 해당 과일에 맞게 과일이 잘려서 밑으로 떨어짐

 

Fruit.cpp

더보기
Fruit::Fruit(wstring file, int key)
	:Quad(file)
{
	isActive = false;
	gravity = Random(0.1f, 1.5f);
	float randomScale = Random(1.0f, 2.0f);
	localScale = { randomScale, randomScale };
	rotate_Power = Random(1.0f, 3.0f);
	speed = Random(200.0f, 500.0f);

	switch (key)
	{
	case 0:
		splitfruit_left = new SplitFruit(L"Textures/FruitNinja/apple_left.png", true, randomScale);
		splitfruit_right = new SplitFruit(L"Textures/FruitNinja/apple_right.png", false, randomScale);
		break;
	case 1:
		splitfruit_left = new SplitFruit(L"Textures/FruitNinja/grape_left.png", true, randomScale);
		splitfruit_right = new SplitFruit(L"Textures/FruitNinja/grape_right.png", false, randomScale);
		break;
	case 2:
		splitfruit_left = new SplitFruit(L"Textures/FruitNinja/mango_left.png", true, randomScale);
		splitfruit_right = new SplitFruit(L"Textures/FruitNinja/mango_right.png", false, randomScale);
		break;
	case 3:
		splitfruit_left = new SplitFruit(L"Textures/FruitNinja/orange_left.png", true, randomScale);
		splitfruit_right = new SplitFruit(L"Textures/FruitNinja/orange_right.png", false, randomScale);
		break;
	case 4:
		splitfruit_left = new SplitFruit(L"Textures/FruitNinja/pear_left.png", true, randomScale);
		splitfruit_right = new SplitFruit(L"Textures/FruitNinja/pear_right.png", false, randomScale);
		break;
	case 5:
		splitfruit_left = new SplitFruit(L"Textures/FruitNinja/strawberry_left.png", true, randomScale);
		splitfruit_right = new SplitFruit(L"Textures/FruitNinja/strawberry_right.png", false, randomScale);
		break;
	}
}

Fruit::~Fruit()
{
}

void Fruit::Update()
{
	((SplitFruit*)splitfruit_left)->Update();
	((SplitFruit*)splitfruit_right)->Update();

	if (!isActive) return;

	direction.y -= gravity * DELTA;
	
	localPosition += direction * speed * DELTA;

	if (localPosition.x < 0 || localPosition.x > WIN_WIDTH)
		isActive = false;

	if (localPosition.y < 0 || localPosition.y > WIN_HEIGHT)
		isActive = false;

	Rotate();
	GameObject::Update();
}

void Fruit::Render()
{
	Quad::Render();
	((SplitFruit*)splitfruit_left)->Render();
	((SplitFruit*)splitfruit_right)->Render();
}

void Fruit::Spawn(Vector2 pos, Vector2 direction)
{
	isActive = true;

	localPosition = pos;
	this->direction = direction;

	localRotation.z = direction.Angle();
}

void Fruit::Rotate()
{
	localRotation.z += DELTA * rotate_Power;
}

void Fruit::Deactivate()
{
	this->isActive = false;
	((SplitFruit*)splitfruit_left)->Spawn(Pos());
	((SplitFruit*)splitfruit_right)->Spawn(Pos());
	Pos() = { CENTER_X, - size.y };
}

 

FruitManager.cpp

더보기
FruitManager::FruitManager()
{
	fruits.resize(40);

	for (Fruit*& fruit : fruits)
	{
		int random_fruit = Random(0, 6);

		switch (random_fruit)
		{
		case 0:
			fruit = new Fruit(L"Textures/FruitNinja/apple.png", random_fruit);
			break;
		case 1:
			fruit = new Fruit(L"Textures/FruitNinja/grape.png", random_fruit);
			break;
		case 2:
			fruit = new Fruit(L"Textures/FruitNinja/mango.png", random_fruit);
			break;
		case 3:
			fruit = new Fruit(L"Textures/FruitNinja/orange .png", random_fruit);
			break;
		case 4:
			fruit = new Fruit(L"Textures/FruitNinja/pear.png", random_fruit);
			break;
		case 5:
			fruit = new Fruit(L"Textures/FruitNinja/strawberry.png", random_fruit);
			break;
		}
	}
}

FruitManager::~FruitManager()
{
	for (Fruit* fruit : fruits)
		delete fruit;
}

void FruitManager::Update()
{
	for (Fruit* fruit : fruits)
		fruit->Update();
}

void FruitManager::Render()
{
	for (Fruit* fruit : fruits)
		fruit->Render();
}

void FruitManager::Spawn()
{
	int random = Random(0, 2); // 좌우 결정

	for (; fruitIndex < fruits.size(); fruitIndex++)
	{
		if (!fruits[fruitIndex]->Active())
		{
			if (random == 0)
			{
				fruits[fruitIndex]->Spawn({ 0, 100 }, { 1, 1 });
				fruitIndex++;

				if (fruitIndex == 29)
				{
					fruitIndex = 0;
				}
				return;
			}
			else if (random == 1)
			{
				fruits[fruitIndex]->Spawn({ WIN_WIDTH, 100 }, { -1, 1 });
				fruitIndex++;

				if (fruitIndex == 29)
				{
					fruitIndex = 0;
				}
				return;
			}

			if (fruitIndex == 29)
			{
				fruitIndex = 0;
			}
		}
	}

}

 

SplitFruit.cpp

더보기
SplitFruit::SplitFruit(wstring file, bool left, float scale)
	: Quad(file)
{
	isActive = false;
	localScale = { scale, scale };
	isLeft = left; // 왼쪽 true, 오른쪽 false
}

SplitFruit::~SplitFruit()
{
}

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

	direction.y -= gravity * DELTA;

	localPosition += direction * SPEED * DELTA;

	if (localPosition.x < 0 || localPosition.x > WIN_WIDTH)
		isActive = false;

	if (localPosition.y < 0)
		isActive = false;

	Rotate();
	GameObject::Update();
}

void SplitFruit::Render()
{
	Quad::Render();
}

void SplitFruit::Spawn(Vector2 pos)
{
	localPosition = pos;
	isActive = true;

	if (isLeft)
		direction = { -0.4, 1 };
	else
		direction = { 0.4, 1 };

	localRotation.z = direction.Angle();
}

void SplitFruit::Rotate()
{
	if (isLeft)
		localRotation.z += DELTA * rotate_Power;
	else
		localRotation.z += DELTA * -rotate_Power;
}

 

Sword.cpp

더보기
Sword::Sword()
	:Quad(L"Textures/FruitNinja/sword.png")
{
	tag = "Sword";
	localScale = { 3, 3 };
	
	fruits = FruitManager::Get()->GetFruits();
}

Sword::~Sword()
{
}

void Sword::Update()
{
	localPosition = mousePos;
	ShowCursor(false);
	Hit();
	GameObject::Update();
}

void Sword::Render()
{
	Quad::Render();
}

void Sword::Hit()
{

	for (Fruit* fruit : fruits)
	{
		if (mousePos.x + COLLIDE_OFFSET.x < fruit->Pos().x + fruit->Half().x 
			&& mousePos.x - COLLIDE_OFFSET.x > fruit->Pos().x - fruit->Half().x
			&& mousePos.y + COLLIDE_OFFSET.y< fruit->Pos().y + fruit->Half().y
			&& mousePos.y - COLLIDE_OFFSET.y > fruit->Pos().y - fruit->Half().y )
		{
			{
				if (KEY_DOWN(VK_LBUTTON))
				{
					Audio::Get()->Play("Hit");
					Timer::Get()->SetScore(100);
					fruit->Deactivate();
					return;
				}
			}
		}
	}
}