프로그래밍/OpenGL

[홍정모의 게임 만들기 연습 문제 패키지] 1.3 과제 1번

바토파 2024. 2. 2. 20:25
반응형
#pragma once

#include "Game2D.h"
using namespace std;

namespace jm
{
	class MyTank
	{
	public:
		vec2 center = vec2(0.0f, 0.0f);
		//vec2 direction = vec2(1.0f, 0.0f, 0.0f);

		void draw()
		{
			beginTransformation();
			{
				translate(center);
				drawFilledBox(Colors::green, 0.25f, 0.1f); // body
				translate(-0.02f, 0.1f);
				drawFilledBox(Colors::blue, 0.15f, 0.09f); // turret
				translate(0.15f, 0.0f);
				drawFilledBox(Colors::red, 0.15f, 0.03f);  // barrel
			}
			endTransformation();
		}
	};

	class MyBullet
	{
	public:
		vec2 center = vec2(0.0f, 0.0f);
		vec2 velocity = vec2(0.0f, 0.0f);

		void draw()
		{
			beginTransformation();
			translate(center);
			drawFilledRegularConvexPolygon(Colors::yellow, 0.02f, 8);
			drawWiredRegularConvexPolygon(Colors::gray, 0.02f, 8);
			endTransformation();
		}

		void update(const float& dt)
		{
			center += velocity * dt;
		}
	};

	class TankExample : public Game2D
	{
	public:
		MyTank tank;

		// 유니티에서 오브젝트 풀링 구현했던 것처럼 queue를 쓰면 될 것이라 생각했지만
        // c++에서 queue는 iterator가 없기 때문에 vector를 사용하기로 했다.
		vector<MyBullet*> bullets;

		//TODO: allow multiple bullets
		//TODO: delete bullets when they go out of the screen

	public:
		TankExample()
			: Game2D("This is my digital canvas!", 1024, 768, false, 2)
		{}

		~TankExample()
		{
			//if(bullet != nullptr) delete bullet;
		}

		void update() override
		{
			// move tank
			if (isKeyPressed(GLFW_KEY_LEFT))	tank.center.x -= 0.5f * getTimeStep();
			if (isKeyPressed(GLFW_KEY_RIGHT))	tank.center.x += 0.5f * getTimeStep();
			if (isKeyPressed(GLFW_KEY_UP))		tank.center.y += 0.5f * getTimeStep();
			if (isKeyPressed(GLFW_KEY_DOWN))	tank.center.y -= 0.5f * getTimeStep();

			// shoot a cannon ball
			if (isKeyPressedAndReleased(GLFW_KEY_SPACE))
			{
				bullets.push_back(new MyBullet); // 벡터의 맨 뒤에 새로 만든 총알을 넣어준다

				MyBullet *bullet = bullets.back(); // 새로 만든 총알을 가져온다
				bullet->center = tank.center;
				bullet->center.x += 0.2f;
				bullet->center.y += 0.1f;
				bullet->velocity = vec2(2.0f, 0.0f);
			}

			// rendering
			tank.draw();
			
			if (!bullets.empty()) {
            	// 만들어진지 가장 오래된 총알만 화면을 넘어갔는지 확인해주었다
                // 테스트 해보니 x 좌표가 1.5 정도면 화면을 넘어간 것처럼 보였지만 넉넉하게 2로 해주었다
				if (bullets[0]->center.x > 2) {
					delete bullets[0]; // 가장 앞에 있는 총알 없애기
					bullets.erase(bullets.begin()); // 총알과 연결된 포인터 없애기
				}

				for (int i = 0; i < bullets.size(); i++) {
					bullets[i]->update(getTimeStep()); // 위치 업데이트
					bullets[i]->draw(); // 총알 그리기
				}
			}
		}
	};
}
반응형