[C++] 2.1 객체 지향 : 클래스와 캡슐화

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 게임 만들기 연습 문제 패키지 강의를 듣고 정리한 필기입니다.😀
🌜 공부에 사용된 홍정모 교수님의 코드들 보러가기
🌜 [홍정모의 게임 만들기 연습 문제 패키지] 강의 들으러 가기!


Chapter 2. 객체 지향으로 가는 길

2.1 객체 지향 : 클래스와 캡슐화

3개의 집을 그려보자.

1. 비슷한 코드의 “단순 반복”으로 그리기

image

  • 아래는 사진 속 집 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. “함수” 사용 : 반복되는 부분들은 함수로 묶기

image

  • 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개 여러개 그리기

image

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();
			}
		}
	};


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

C++ games 카테고리 내 다른 글 보러가기

댓글 남기기