랜더러 만들기
#pragma once
#include <iostream>
class Renderer
{
public:
Renderer() = delete;
~Renderer() = delete;
Renderer(const Renderer&) = delete;
Renderer& operator = (const Renderer&) = delete;
static bool Init();
static void Cleanup();
static void Flip();
static void DrawwText(const Text* text, int32_t numberOfChar, int32_t x, int32_t y);
private:
static void clear(HANDLE consoleHandle);
private:
static HANDLE s_consoleHandle;
static HANDLE s_screens[2];
static int s_backIndex;
};
HANDLE Renderer::s_consoleHandle;
HANDLE Renderer::s_screens[2];
int Renderer::s_backIndex;
bool Renderer::Init(void)
{
// 1. 콘솔에 대한 핸들을 얻는다.
s_consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE == s_consoleHandle)
{
return false;
}
// 2. 스크린을 만든다.
for (int32_t i = 0; i < 2; ++i)
{
s_screens[i] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
}
return true;
}
void Renderer::Cleanup(void)
{
CloseHandle(s_consoleHandle);
CloseHandle(s_screens[0]);
CloseHandle(s_screens[1]);
}
//void Renderer::clear(HANDLE consoleHandle)
//{
// CONSOLE_SCREEN_BUFFER_INFO csbi;
// GetConsoleScreenBufferInfo(consoleHandle, &csbi);
//
// SMALL_RECT scrollRect;
// scrollRect.Left = 0;
// scrollRect.Top = 0;
// scrollRect.Right = csbi.dwSize.X;
// scrollRect.Bottom = csbi.dwSize.Y;
//
// COORD scrollTarget;
// scrollTarget.X = 0;
// scrollTarget.Y = (SHORT)(0 - csbi.dwSize.Y);
//
// CHAR_INFO fill;
// fill.Char.UnicodeChar = TEXT(' ');
// fill.Attributes = csbi.wAttributes;
//
// ScrollConsoleScreenBuffer(consoleHandle, &scrollRect, NULL, scrollTarget, &fill);
//
// csbi.dwCursorPosition.X = 0;
// csbi.dwCursorPosition.Y = 0;
// SetConsoleCursorPosition(consoleHandle, csbi.dwCursorPosition);
//}
void Renderer::Flip(void)
{
// 1. 백 버퍼로 화면을 지정한다.
SetConsoleActiveScreenBuffer(s_screens[s_backIndex]);
// 2. 백 버퍼를 바꿔준다.
s_backIndex = !s_backIndex;
// 3. 백 버퍼에 있는 화면을 지워준다.
clear(s_screens[s_backIndex]);
}
void Renderer::DrawwText(const Text* text, int32 numberOfChar, int32_t x, int32_t y)
{
// 1. 백 버퍼에 대한 핸들을 가져온다.
HANDLE backBuffer = s_screens[s_backIndex];
// 2. 커서 위치를 옮겨준다.
COORD pos = { x, y };
SetConsoleCursorPosition(backBuffer, pos);
// 3. 백 버퍼에 텍스트를 출력한다.
for (int32 i = 0; i < numberOfChar; ++i)
{
SetConsoleTextAttribute(backBuffer, text[i].Attributes);
WriteConsole(backBuffer, &text[i].Char, 1, NULL, NULL);
}
SetConsoleTextAttribute(backBuffer, TEXT_COLOR_WHITE);
}
추상클래스 : 인스턴스를 만들지 않는 클래스, 상위클래스를 정의하는데 사용한다.
struct A
{
// 순수 가상 함수(Pure Virtual Function) -> 보통 선언만 한다.
virtual void Foo() = 0;
};
int main()
{
}
동적 할당
struct A
{
A() { std::cout << "Constructor"; }
~A() { std::cout << "Desturctor"; }
};
int main()
{
// malloc(sizeof(int))와 같다.
// 해제를 할 때는 new를 썼으면 delete 를 쓰면 된다.
int* p = new int; // 할당에는 new 연산자를
// C언어의 free(p) 이다.
delete p; // 해제에는 delete 연산자를 사용한다.
p = new int[3]; // 배열의 할당이 필요할 때는 new[] 연산자를 사용하며
delete[] p; // 해제에는 delete[] 연산자를 사용한다.
// 가장 크게 달라지는 부분은 클래스 타입을 동적 할당 할 때이다.
// new / delete 연산자는 클래스 타입일 때
// 자동으로 생성자와 소멸자를 호출한다.
A* a = new A();
delete a;
return 0;
struct A
{
A() { cout << "Constructor" << endl; }
~A() { cout << "Desturctor" << endl; }
};
int main()
{
A* a = new A();
// malloc(sizeof(int))와 같다.
// 해제를 할 때는 new를 썼으면 delete 를 쓰면 된다.
int* p = new int; // 할당에는 new 연산자를
// C언어의 free(p) 이다.
delete p; // 해제에는 delete 연산자를 사용한다.
p = new int[3]; // 배열의 할당이 필요할 때는 new[] 연산자를 사용하며
delete[] p; // 해제에는 delete[] 연산자를 사용한다.
// 가장 크게 달라지는 부분은 클래스 타입을 동적 할당 할 때이다.
// new / delete 연산자는 클래스 타입일 때
// 자동으로 생성자와 소멸자를 호출한다.
a = new A[5]; // 실제 필요한 메모리의 크기는 5바이트임에도 불구하고
// 13바이트가 된 이유는 인스턴스의 개수를 저장할 공간 8바이트를 추가적으로
// 사용하기 때문이다.
delete[] a;
return 0;
}
가상소멸자 연습
#include <iostream>
using namespace std;
struct Base
{
Base() { std::cout << "1_Constructor\\n\\n" << endl; }
virtual ~Base() { std::cout << "1_Destructor\\n\\n" << endl; }
};
struct Derived : Base
{
Derived() { std::cout << "2_Constructor\\n" << endl; }
~Derived() { std::cout << "2_Destructor\\n" << endl; }
};
struct AddDerived : Derived
{
AddDerived() { cout << "3_Constructor" << endl; }
~AddDerived() { cout << "3_Destructor" << endl; }
};
int main()
{
Base* d = new Derived();
Base* e = new AddDerived();
delete d;
delete e;
} // 정상적으로 생성과 소멸이 이뤄짐.
객체(object)
상태(state)와 행동(behavior)을 함께 지닌 실체다.
→ 객체가 협력에 참여하기 위해 어떤 행동을 해야 한다면 그 행동을 하는 데 필요한 상태도 함께 지니고 있다.
객체는 충분히 협력적이어야 한다
→ 다른 객체의 요청을 잘 처리해야 하고, 다른 객체에 적극적으로 도움을 요청해야 한다. 여러가지 책임을 가진 전지전능한 객체는 내부적인 복잡도에 의해 자멸한다..
객체는 충분히 자율적이어야 한다.
→ 요청에 응답하는 방식은 객체 스스로 판단하고 결정해야 하며 요청에 응할지 여부도 객체 스스로 결정해야 한다. 객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로 부터 나오게 되는데, 객체의 내부는 객체 스스로 관리하고 외부에서 일체 간섭할 수 없도록 차단해야 하며, 객체의 외부에서는 접근이 허락된 수단을 통해 의사소통을 하게 된다.
쩔지?