문서의 이전 판입니다!
목차
준비
- 이전 기사는 한글 출력하기이다.
- 스타팅 파일은 Flappy Bird에 장애물 만들기 스타팅 파일이다.
장애물 클래스 만들기
1. 개념
플래피 버드에서는 파이프 장애물이 존재한다. 이를 네모난 박스로 구조화하면 다음과 같다.
위와 아래의 장애물 좌표를 구하려면 위의 장애물 높이와, 아래 장애물 높이, 그리고 중간 빈 공간의 높이가 필요하다.
위의 장애물 높이와 중간 빈 공간의 높이를 정해 놓으면 아래 장애물 높이는 전체 화면 높이에서 빼면 될 것이다.
굳이 서식으로 해보자면
아래장애물 높이 = 전체 화면 높이 - (위 장애물 높이 + 중간 빈 공간의 높이)
이다.
2. obstacle.h
- obstacle.h
#pragma once #include "raylib.h" enum class ObstacleType { top = 0, bottom, both }; typedef struct Box { int x; int y; int bWidth; int bHeight; } Box ; class Obstacle { public: void Init(); void Update(); void Draw(); int GetPipePosition(); private: Box upPipe; Box downPipe; int upPipeHeight; int width; int middleHeight; int speed = 2; ObstacleType type = ObstacleType::top; };
장애물은 네모난 박스로 그릴 것이므로 int형의 박스 구조체를 만들었다. 그리고 장애물의 종류를 설정했다. 위에 달린 장애물, 아래에 달린 장애물 위와 아래 모두에 달린 장애물의 세 가지 종류를 만들었다.
3. obstacle.cpp
- obstacle.cpp
#include "obstacle.h" void Obstacle::Init() { int typeValue = GetRandomValue(0, 2); // 장애물 타입 0은 top, 1은 bottom, 2는 both type = ObstacleType(typeValue); // 장애물 타입을 랜덤하게 설정함 width = GetRandomValue(100, 150); // 파이프 너비는 위와 아래 파이프가 동일 하다 upPipeHeight = GetRandomValue(250, 400); // 위 파이프의 높이 middleHeight = GetRandomValue(300, 400); // 위와 아래 파이프 사이의 공간 upPipe = {GetScreenWidth(), 0, width, upPipeHeight}; downPipe = {GetScreenWidth(), upPipeHeight + middleHeight, width, GetScreenHeight() - (upPipeHeight + middleHeight)}; } void Obstacle::Update() { upPipe.x -= speed; downPipe.x -= speed; } // 파이프가 화면 왼쪽끝을 넘어가면 지우기 위해 왼쪽 끝의 값을 가져옴 int Obstacle::GetPipePosition() { return upPipe.x + upPipe.bWidth; } void Obstacle::Draw() { if (type == ObstacleType::top) { DrawRectangle(upPipe.x, upPipe.y, upPipe.bWidth, upPipe.bHeight, DARKGREEN); }else if (type == ObstacleType::bottom) { DrawRectangle(downPipe.x, downPipe.y, downPipe.bWidth, downPipe.bHeight, DARKGREEN); }else { DrawRectangle(upPipe.x, upPipe.y, upPipe.bWidth, upPipe.bHeight, DARKGREEN); DrawRectangle(downPipe.x, downPipe.y, downPipe.bWidth, downPipe.bHeight, DARKGREEN); } }
가. Init() 함수
장애물은 랜덤하게 위, 아래, 양쪽을 나오게 했다. 따라서 GetRandomValue()함수를 이용하여 랜덤 값을 처음에 만들어 준다.
각 장애물(파이프)의 높이도 랜덤하게 만들 것이므로 랜덤 하게 변수를 설정하게 했다. 이후에 위와 아래 파이프의 상자를 그리기 위하여 4개의 값을 요소로 하는 구조체에 넣어주게 하였다.
나. Update() 함수
왼쪽으로만 움직이게 할 것이므로 x 값만 바꿔주면 된다.
다. GetPipePosition() 함수
Game 클래스에서 파이프가 화면에 왼쪽 끝으로 완전히 가게 되면 파이프를 제거하는 로직을 만들 것이다.
그래서 파이프가 왼쪽 끝으로 가는지를 리턴하는 함수를 만들었다. 파이프의 오른쪽 끝이 0이 되게 만들어야 하므로 x+width값을 리턴하게 하였다.
라. Draw() 함수
각 상황에 따라 달리 그린다. 현재 상태가 top이면 위에 있는 파이프만, 그리고 bottom이면 아래에 있는 파이프만 그리는 방식이다.
Game 클래스에서 구현하기
1. 전역 변수 선언하기
장애물로 사용할 변수를 게임클래스 전역에서 사용할 것이다. 따라서 game.cpp 최상단에 다음과 같이 장애물 벡터 배열을 선언하였다.
장애물(파이프)의 전체 갯수에 대하여 동적으로 선언할 것이므로 벡터를 이용하였다.
// 장애물 변수 선언 std::vector<Obstacle> pipes; int timer = 0; int maxTimer = 120;
vector를 사용할 것이므로
#include <vector>
를 미리 선언해야 한다.
2. 장애물 초기화하기
Gaeme::Init()에는 다음과 같이 장애물을 초기화한다.
// 장애물 초기화하기 Obstacle pipe = Obstacle(); pipe.Init(); pipes.push_back(pipe); maxTimer = GetRandomValue(120, 240);
- 벡터 배열에서 요소를 추가하는 것은 push_back을 이용한다. 그러면 동적 배열에 요소가 하나씩 들어간다.
- maxTimer는 다음 장애물이 생성될 텀이다. timer가 maxTimmer 만족하면 다음 장애물을 만들게 할 것이다.
3. Update() 로직
가. 장애물을 새롭게 만드는 로직
초당 60번의 프레임을 돌리게 하였으므로 60프레임이면 1초다.
게임이 Update루프를 돌면서 maxTimer를 만족하면 새롭게 장애물을 만들게 하였다.
// 장애물 로직 시작 // 타이머를 만족하면 새로운 파이프 장애물을 만든다. timer++; if (timer >= maxTimer) { timer = 0; maxTimer = GetRandomValue(120, 240); Obstacle newPipe; newPipe.Init(); pipes.push_back(newPipe); }
나. 장애물 제거하는 로직
업데이트 루프를 돌다가 장애물이 왼쪽 끝에 가면 사라지게 만들어야 한다. 장애물을 무한정으로 생성하면 메모리는 계속 쌓이기만 할 것이기 때문에 왼쪽 끝에 다다라서 소용 없는 장애물은 배열에서 제거해야 하기 때문이다.
벡터에서 요소를 제거하는 것은 다음 코드와 같이 하면 된다.
// 전체 파이프를 루프 돌려서 업데이트 메서드 실행 for (unsigned int i =0; i < pipes.size(); i++) { pipes[i].Update(); if (pipes[i].GetPipePosition() <= 0) { pipes.erase(pipes.begin() + i); // 장애물이 왼쪽 끝에 가면 배열에서 제거 } } // 장애물 로직 끝
4. Draw() 로직
장애물은 하나가 아니므로 For 루프를 돌려서 장애물을 모두 돌려야 한다. 다음과 같이 짜면 된다.
// 전체 파이프를 루프 돌려서 드로우 메서드 실행 for (unsigned int j =0; j < pipes.size();j++) { pipes[j].Draw(); } DrawText(TextFormat("Pipes : %d", pipes.size()), GetScreenWidth() - 200, 40, 20, DARKGRAY);
전체 장애물(파이프)가 몇 개가 있는지를 확인하기 위해 DrawText() 메서드도 이용하였다. 게임을 실행하여 장애물이 왼쪽 끝에 다다르면 숫자가 사라지는지 확인해 보자.
로그인