[C++] 1.3 상호작용 맛보기 - 키보드 입력과 반응
카테고리: C++ games
태그: Cpp Graphics OpenGL Programming
인프런에 있는 홍정모 교수님의 홍정모의 게임 만들기 연습 문제 패키지 강의를 듣고 정리한 필기입니다.😀
🌜 공부에 사용된 홍정모 교수님의 코드들 보러가기
🌜 [홍정모의 게임 만들기 연습 문제 패키지] 강의 들으러 가기!
Chapter 1. 기본 기능 구현
1.3 상호작용 맛보기 - 키보드 입력과 반응
📃 TankExample.h
코드 설명
- class 3개
- MyTank
- 탱크 객체를 찍어낼 클래스
- MyBullet
- 총알 객체를 찍어낼 클래스
- TankExample
- Game2D를 상속받으며 update함수를 가지고 있다.
- 게임을 실행시킴
- MyTank
#pragma once
#include "Game2D.h"
namespace jm
{
class MyTank // 탱크 클래스
{
public:
vec2 center = vec2(0.0f, 0.0f); // ⭐ 탱크의 현재 위치 (처음엔 원점. 사용자의 키보드 조작에 따라 계속 갱신될 것)
void draw() // 탱크를 그리는 함수.
{
beginTransformation();
{
translate(center); // 실행순서 <6>. ✨ body는 'center'로, barrel은 'center + (0.13f, 0.1f)'로, turret은 'center + (-0.02f, 0.1f)'로 이동한다.
drawFilledBox(Colors::green, 0.25f, 0.1f); // 실행순서 <1>. body를 그린다.
translate(-0.02f, 0.1f); // 실행순서 <5>. ✨ barrel은 (0.13f, 0.1f)로, turret은 (-0.02f, 0.1f)로 이동한다.
drawFilledBox(Colors::blue, 0.15f, 0.09f); // 실행순서 <2>. turret을 그린다.
translate(0.15f, 0.0f); // 실행순서 <4>. ✨ barrel이 (0.15f, 0.0f)로 이동한다.
drawFilledBox(Colors::red, 0.15f, 0.03f); // 실행순서 <3>. barrel을 그린다.
}
endTransformation();
}
};
class MyBullet // 총알 클래스
{
public:
vec2 center = vec2(0.0f, 0.0f); // ⭐총알의 현재 위치 (처음엔 원점. 시간에 따라 계속 갱신될 것)
vec2 velocity = vec2(0.0f, 0.0f); // ⭐총알의 속도
void draw() // 총알 그리는 함수.
{
beginTransformation();
translate(center); // 실행순서 <3>. 아래 두 도형이 함께 평행이동한다.
drawFilledRegularConvexPolygon(Colors::yellow, 0.02f, 8); // 실행순서 <1>.
drawWiredRegularConvexPolygon(Colors::gray, 0.02f, 8); // 실행순서 <2>.
endTransformation();
}
void update(const float& dt) // ⭐ 총알의 위치인 center 값을 시간마다 업데이트 한다.(이 update 함수는 MyBullet 자체의 함수)
{
center += velocity * dt; // ⭐ 총알의 위치가 '속도 * 시간'에 따라 바뀜. dt는 시간 간격이 됨
}
};
class TankExample : public Game2D // 게임을 실행시킬 클래스. Game2D를 상속 받음.
{
public:
MyTank tank;
MyBullet *bullet = nullptr; // bullet은 총알이 발사 됐을 때만 존재하기 때문에 포인터로 되어있고 null 포인터로 초기화한다.
public:
TankExample()
: Game2D("This is my digital canvas!", 1024, 768, false, 2)
{}
~TankExample() // ⭐ 소멸자 !! nullptr 아닐때만 총알 객체 동적 메모리를 delete 시켜주는 역할을 한다.
{
if(bullet != nullptr) delete bullet;
}
// update() 은 run 안에서 ⭐무한루프⭐로 돌아가니까 아래 키들이 눌렸는지 매 프레임마다 계속 체크한다.
// Game2D의 update함수 오버라이딩. 메인 무한 루프를 돌리는 run()안에서 호출된다.
void update() override
{
// ⭐ 탱크 이동 ! 키보드 방향키에 따라 부드럽게 움직이도록 한칸 * 1/60 만큼 움직이게.
// getTimeStep() 함수는 Game2D에 있는 함수로 상속받아 사용할 수 있게 된 함수다. 프레임을 리턴함.
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();
// ⭐ 포탄 발사 ! 포탄을 발사하는건 곧 포탄을 생성한다는 것. 스페이스바 누르면 발사
if (isKeyPressedAndReleased(GLFW_KEY_SPACE))
{
bullet = new MyBullet; // ⭐ 포탄 생성
bullet->center = tank.center; // ⭐ 탱크의 현재위치로 총알 현재위치가 정해짐 (탱크에서 발사되니까 )
bullet->center.x += 0.2f; // ⭐ 그래도 발포하는 곳에서 발사될 수 있게 위치 조정
bullet->center.y += 0.1f;
bullet->velocity = vec2(2.0f, 0.0f); // ⭐ 속도 지정.
}
// 시간에 따라 총알의 위치를 업뎃한다.
if (bullet != nullptr) bullet->update(getTimeStep());
// ⭐ dt는 getTimeStep()의 리턴값이 된다. ( 1/60 )
// ⭐ if ( bullet != nullptr ) 로 nullptr 체크 안하고 그냥 bullet->update 호출해버리면 런타임 에러가 발생한다.
// 왜냐하면 스페이스 누르기 전까진 bullet이 nullptr이라 아무것도 가리키고 있지 않은데 (총알 객체가 없는데) update을 호출 하려고 할테니까
// rendering
tank.draw(); // ⭐ 탱크 그리기
if (bullet != nullptr) bullet->draw(); // ⭐ 총알은 포인터라 nullptr이 아닐때만 draw하기.
}
};
}
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글남기기