2
cpp 엄청 명령형 프로그래밍이네 선언형 프로그래밍하려면 엄청 추상화해야할듯
소코반 게임
플레이어를 이동시켜서 박스를 목표 지점에 모두 옮기는 게임
- 플레이어가 박스를 이동시켜야 함
- 플레이어가 이동할 때 다음 위치가 이동 가능한지 판단해야 함
- 모든 액터에 접근이 가능하거나
- 또는 충돌 처리를 해주는 시스템을 만들어야함(비용 비쌈)
- 1번 선택
플레이어에게 모든 액터 정보를 전달(설계적으로 별로)- 플레이어가 모든 액터에 접근 가능한 누군가에게 이동 여부를 문의
특정 레벨(e.g. SokobanLevel)로 형변환해서 접근하는 방법- 중간에 인터페이스로 필요한 함수만 접근할 수 있게 제한
Engine 리뷰
Engine|- Level |- Actor|- Input---|- etc |- RTTI |- Vector2 |- Color |- Util |- Common(DLLEXPORT)Engine 클래스
주요 멤버 함수
생성자
- 전역변수이자 싱글톤인 instance를 자기 자신으로 초기화해준다
- Input 매니저를 동적 할당 초기화해줌
LoadSettings();실행"../Config/Settings.txt"파일을 읽고"frameRate = %f"포맷에 해당하는 설정값을&settings.frameRate에 할당해준다
- 커서 잠시 끄기
Run()
QueryPerformanceFrequency(&frequence)로 frequency 초기화QueryPerformanceCounter(&time)으로 time을 받아와 currentTime와 previousTime 설정LoadSettings()에서 설정된 frameRate로float oneFrameTime = 1.0f/settings.frameRate;설정- 종료 플래그 전까지 반복문을 순회하면서
deltaTime이oneFrameTime을 넘었을 때만 아래 함수들을 차례대로 수행하고 previousTime 최신화해주면서 다음 프레임 수행input->ProcessInput(): 사용자 인풋0x8000비트 곱연산해서isKeyDown배열에 저장BeginPlay(): Engine -> mainLevel -> actor->BeginPlay() 연쇄 호출, actor 인스턴스의 hasBegunPlay 플래그 true 토글Tick(deltaTime): Engine -> mainLevel -> actor->Tick() 연쇄 호출, 아무것도 안함Draw(): Engine -> mainLevel -> actor->Draw() 연쇄 호출,Renderer::Draw(position, color, image);호출input->SavePreviousInputStates(): 현재 Input 상태들을 previous 변수로 옮김mainLevel->ProcessAddAndDestoryActors(): 레벨에 있는 액터들을 돌면서 액터 인스턴스에 파괴요청이 있는 액터들만 레벨에서 제거해줌.addRequestedActors를 순회하면서 레벨 액터 배열에 추가해줌.
Quit(): isQuit = false 토글
SetNewLevel()
- engine 인스턴스의 mainLevel 멤버변수에 매개변수 newLevel을 할당
주요 멤버 변수
EngineSettings settings;Input* input = nullptr;class Level* mainLevel = nullptr;static Engine* instance: 전역 변수
Level 클래스
주요 멤버 함수
RTTI_DECLARATION(Level, RTTI): RTTI 클래스에 Level 상속BeginPlay(): 해당 레벨 인스턴스에 소속돼있는hasBegunPlay가 false인 액터들만actor->BeginPlay()실행(게임 실행 중에 동적으로 스폰될 수 있으며, 액터 인스턴스별로 한 번씩만 수행되어야 하므로)Draw(): 다른 액터 간에 위치가 같은 액터가 있다면 두 액터의 정렬 순서를 가져와 비교. 정렬 순서가 높은 액터만 그림(만약 같은 위치에 3개 이상의 액터가 있다면? 되긴 하겠네 ㅇㅇ)AddNewActor(Actor* newActor): 실행되는 즉시 액터를 추가하는게 아니라 프레임 루프 안 보장된 순서(ProcessAddAndDestroyActors())에 생성하기 위해addRequestedActors배열에 저장함. 추가로 현 레벨을 새 액터의 소유자로 설정
주요 멤버 변수
std::vector<Actors*> actorsstd::vector<Actors*> addRequestedActors
Vector
연속적인 메모리에 보관하는 배열과 비슷한 자료 구조. 원소 개수가 컴파일 타임에 결정이 되어야 하고 런타임(동작 도중)에는 변경할 수 없는 배열과 달리 vector는 런타임에 사이즈를 변경할 수 있음
동적 배열
- 원소 개수가 증가할 때마다 필요한 메모리를 확보해야한다.
- 연속된 메모리를 가져야 하기 때문에 현재 위치에서 용량을 더 늘릴 수 없다면 새 메모리 공간에 복사 및 추가공간 할당이 필요함
- 최대 수용 가능 용량을
capacity()로 알 수 있다reserve()함수로 현재 크기의 절반만큼 추가로 할당받음capacity는 한 번 늘어나면 임의로 줄일 수 없음
shrink_to_fit()함수로 남은 메모리 OS에 반납.clear()함수로 벡터 내 모든 원소 제거(capacity는 그대로이므로 메모리 공간 그대로 차지 중)

삽입, 삭제
- 조회, 처음과 끝 삽입/삭제 = O(1)
- 중간 삽입/삭제 = O(n)

빌드
.exe 뽑을 때 Assets, Config 폴더도 post build 이벤트에 .exe 한꺼풀 위에 복사되도록 추가해줘야함