[C++] 2.1 객체 지향 : 클래스와 캡슐화
카테고리: C++ games
태그: Cpp Graphics OpenGL Programming
인프런에 있는 홍정모 교수님의 홍정모의 게임 만들기 연습 문제 패키지 강의를 듣고 정리한 필기입니다.😀
🌜 공부에 사용된 홍정모 교수님의 코드들 보러가기
🌜 [홍정모의 게임 만들기 연습 문제 패키지] 강의 들으러 가기!
Chapter 2. 객체 지향으로 가는 길
2.1 객체 지향 : 클래스와 캡슐화
3개의 집을 그려보자.
1. 비슷한 코드의 “단순 반복”으로 그리기
- 아래는 사진 속 집 3개를 그리는 코드이다.
- 집 그리는 똑같은 코드를 3번 반복해서 집을 3개 그리니 너무 복잡하고 가독성도 떨어지고 해당 집의 코드를 찾기도 힘들다.
#include "Game2D.h"
#include "Examples/PrimitivesGallery.h"
#include "RandomNumberGenerator.h"
namespace jm
{
class Example : public Game2D
{
public:
void update() override
{
// 왼쪽 집 그리기
beginTransformation();
{
rotate(10);
// wall
drawFilledBox(Colors::yellow, 0.2f, 0.2f);
// roof
drawFilledTriangle(Colors::red, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
drawWiredTriangle(Colors::red, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
// window
drawFilledBox(Colors::skyblue, 0.1f, 0.1f);
drawWiredBox(Colors::gray, 0.1f, 0.1f);
drawLine(Colors::gray, { 0.0f, -0.05f }, Colors::gray, { 0.0f, 0.05f });
drawLine(Colors::gray, { -0.05f, 0.0f }, Colors::gray, { 0.05f, 0.0f });
}
endTransformation();
// 가운데 집 그리기
beginTransformation();
{
translate(0.5f, 0.0f);
// wall
drawFilledBox(Colors::yellow, 0.2f, 0.2f);
// roof
drawFilledTriangle(Colors::red, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
drawWiredTriangle(Colors::red, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
// window
drawFilledBox(Colors::skyblue, 0.1f, 0.1f);
drawWiredBox(Colors::gray, 0.1f, 0.1f);
drawLine(Colors::gray, { 0.0f, -0.05f }, Colors::gray, { 0.0f, 0.05f });
drawLine(Colors::gray, { -0.05f, 0.0f }, Colors::gray, { 0.05f, 0.0f });
}
endTransformation();
// 오른쪽 집 그리기
beginTransformation();
{
translate(-0.5f, 0.0f);
// wall
drawFilledBox(Colors::yellow, 0.2f, 0.2f);
// roof
drawFilledTriangle(Colors::red, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
drawWiredTriangle(Colors::red, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
// window
drawFilledBox(Colors::skyblue, 0.1f, 0.1f);
drawWiredBox(Colors::gray, 0.1f, 0.1f);
drawLine(Colors::gray, { 0.0f, -0.05f }, Colors::gray, { 0.0f, 0.05f });
drawLine(Colors::gray, { -0.05f, 0.0f }, Colors::gray, { 0.05f, 0.0f });
}
endTransformation();
}
};
}
int main(void)
{
jm::Example().run();
return 0;
}
2. “함수” 사용 : 반복되는 부분들은 함수로 묶기
void drawHouse()
- 반복 되는 부분을
함수
로만 묶어 사용해도 훨씬 깔끔해진다 - 집 3개를 함수 써서 깔끔한 코드로 만들 수 있다.
- 집 그리는 코드 3번 반복할 필요 x
- 매개변수 값을 다르게 하여 각각 조금씩 다른 모양으로 그릴 수 있다.
- 단,
함수
로 해결하는 것의 단점- 다르게 하고 싶은 부분이 있을 때마다 파라미터를 계속해서 추가해야 해서
- 오히려 함수가 점점 복잡해진다.
- 각각 다르게 하고 싶은 요소가 생길 때마다 매개변수를 추가해야 하니까
- 이렇게 👉 void drawHouse(
const RGB& roof_color, const vec2& pos, const float& angle = 0.0f
)
- 오히려 함수가 점점 복잡해진다.
- 다르게 하고 싶은 부분이 있을 때마다 파라미터를 계속해서 추가해야 해서
#include "Game2D.h"
#include "Examples/PrimitivesGallery.h"
#include "RandomNumberGenerator.h"
namespace jm
{
// 함수 -> 그리는 집마다 지붕 색깔, 위치, 회전각도가 다르게 할 수 있도록 매개변수 3개 설정했다.
void drawHouse(const RGB& roof_color, const vec2& pos, const float& angle = 0.0f)
{
beginTransformation();
{
translate(pos);
rotate(angle);
// wall
drawFilledBox(Colors::yellow, 0.2f, 0.2f);
// roof
drawFilledTriangle(roof_color, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
drawWiredTriangle(roof_color, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
// window
drawFilledBox(Colors::skyblue, 0.1f, 0.1f);
drawWiredBox(Colors::gray, 0.1f, 0.1f);
drawLine(Colors::gray, { 0.0f, -0.05f }, Colors::gray, { 0.0f, 0.05f });
drawLine(Colors::gray, { -0.05f, 0.0f }, Colors::gray, { 0.05f, 0.0f });
}
endTransformation();
}
class Example : public Game2D
{
public:
void update() override
{
drawHouse(vec2(0.0f,0.0f), 0.0f); // center house
drawHouse(vec2(-0.5f, 0.0f), 10.0f); // left house (약간 기울어진)
drawHouse(vec2(0.5f, 0.0f), 0.0f); // right house
}
};
}
int main(void)
{
jm::Example().run();
return 0;
}
3. “클래스” 사용
- 클래스를 사용하는 이유
- 집 여러개를 그리려면 같은 코드를 여러번 반복해야 하고 해당 집의 코드를 읽기도 찾기도 힘들어진다.
- 반복되고 자주쓰이는 부분을 클래스로 묶어서 객체화 해서 쓸 수 있도록 캡슐화
- 실존하는 집을 만들어 낼 수 있는
틀
(클래스)을 만들고 그 틀로 집을 여러개 찍어냄(객체)
- 실존하는 집을 만들어 낼 수 있는
- ‘집’이라는 ‘객체’를 정의하고 그 객체(집)을 일반화, 추상화시켜서 클래스를 만든다.
- 클래스를 활용하면 객체를 그리는 기능(함수) 말고도 여러가지 기능을 할 수 있음.
#include "Game2D.h"
#include "Examples/PrimitivesGallery.h"
#include "RandomNumberGenerator.h"
namespace jm
{
class House // '집' 클래스
{
private:
RGB roof_color; // 함수였으면 파라미터로 일일이 쓰였을 변수들을 멤버 변수로 세팅
vec2 pos;
float angle = 0.0f;
public:
House()
: roof_color(Colors::red), pos(0.0f,0.0f), angle (0.0f) // 생성자 !! 객체가 생성되면 이렇게 자동으로 생성되자마자 세팅 됨
{}
void setPos(const vec2& _pos) // private 변수인 pos와 angle 값을 설정하기 위한 setter 함수
{
pos = _pos;
}
void setAngle(const float& _angle)
{
angle = _angle;
}
void draw() // 클래스를 사용하니까 멤버 변수로 다 빼놔서 이렇게 매개변수 없이 깔끔하게! draw(). 파라미터 넘겨 받을 필요 없이 변수들을 쓸 수 있게 됐다.
{
beginTransformation();
{
translate(pos);
rotate(angle);
// wall
drawFilledBox(Colors::yellow, 0.2f, 0.2f);
// roof
drawFilledTriangle(roof_color, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
drawWiredTriangle(roof_color, { -0.13f, 0.1f }, { 0.13f, 0.1f }, { 0.0f, 0.2f });
// window
drawFilledBox(Colors::skyblue, 0.1f, 0.1f);
drawWiredBox(Colors::gray, 0.1f, 0.1f);
drawLine(Colors::gray, { 0.0f, -0.05f }, Colors::gray, { 0.0f, 0.05f });
drawLine(Colors::gray, { -0.05f, 0.0f }, Colors::gray, { 0.05f, 0.0f });
}
endTransformation();
}
};
class Example : public Game2D
{
public:
void update() override
{
House left_house, center_house, right_house; // 집 객체 3개 찍어냄
left_house.setPos(vec2(-0.5f, 0.0f)); // 각 집의 위치와 각도를 함수로 다르게 설정하기
center_house.setPos(vec2(0.0f, 0.0f));
center_house.setAngle(10.0f);
right_house.setPos(vec2(0.5f, 0.0f));
left_house.draw();
center_house.draw();
right_house.draw();
}
};
}
int main(void)
{
jm::Example().run();
return 0;
}
배열 사용하여 집 10개 여러개 그리기
House houses[10]
: House 객체 10개를 담을 수 있는 배열
void update() override
{
House houses[10]; // 일일이 첫번째집,,, 두번째집,,,, 열번째집,, 이렇게 변수 안놔도 됨.
for (int i = 0; i < 10; i++) // 각 객체들 (원소들) 위치 지정
{
houses[i].setPos(vec2(-1.3f + 0.3f * float(i), 0.0f));
}
for (int i = 0; i < 10; i++) // 각 객체들 (원소들) 그리기
{
houses[i].draw();
}
}
10개의 집 위치를 각각 랜덤으로 설정 해보기
RandomNumberGenerator.h
include 해야 함- `getFloat(-0.5f, 0.5f)
- RandomNumberGenerator의 함수
- 0.5f~0.5f 사이의 랜덤한 수 리턴
- 집 객체들의 y좌표를 랜덤으로 해보자.
#include "RandomNumberGenerator.h"
class Example : public Game2D
{
public:
House houses[10];
Example() // 생성자
:Game2D() // 부모클래스Game2D 초기화
{
RandomNumberGenerator rnd; // 랜덤넘버생성기 객체 생성
for (int i = 0; i < 10; i++)
{
houses[i].setPos(vec2(-1.3f + 0.3f * float(i), rnd.getFloat(-0.5f, 0.5f)));
// 이걸 update()안 에서 해주면 집 위치들이 계속 매 프레임마다 랜덤으로 변함. 그래서 위치설정은 미리 생성자에서 1번만 실행 되도록 설정
}
}
void update() override
{
for (int i = 0; i < 10; i++)
{
houses[i].draw();
}
}
};
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기