개발일지공부아이디어
    • 5월
    • 4월
    • 3월
    • 2월
    • 1월
  • 26

    26. 2. 27.

  • 26

    26. 2. 26.

  • 25

    26. 2. 25.

  • 24

    26. 2. 24.

  • 23

    26. 2. 23.

  • 22

    26. 2. 22.

  • 13

    26. 2. 13.

  • 10

    26. 2. 10.

  • 9

    26. 2. 9.

  • 6

    26. 2. 6.

  • 2

    26. 2. 2.

로딩 중...

2

2026. 2. 2.

cpp 엄청 명령형 프로그래밍이네 선언형 프로그래밍하려면 엄청 추상화해야할듯

소코반 게임

플레이어를 이동시켜서 박스를 목표 지점에 모두 옮기는 게임

  • 플레이어가 박스를 이동시켜야 함
  • 플레이어가 이동할 때 다음 위치가 이동 가능한지 판단해야 함
    • 모든 액터에 접근이 가능하거나
    • 또는 충돌 처리를 해주는 시스템을 만들어야함(비용 비쌈)
  • 1번 선택
    1. 플레이어에게 모든 액터 정보를 전달(설계적으로 별로)
    2. 플레이어가 모든 액터에 접근 가능한 누군가에게 이동 여부를 문의
      1. 특정 레벨(e.g. SokobanLevel)로 형변환해서 접근하는 방법
      2. 중간에 인터페이스로 필요한 함수만 접근할 수 있게 제한

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*> actors
  • std::vector<Actors*> addRequestedActors

Vector

연속적인 메모리에 보관하는 배열과 비슷한 자료 구조. 원소 개수가 컴파일 타임에 결정이 되어야 하고 런타임(동작 도중)에는 변경할 수 없는 배열과 달리 vector는 런타임에 사이즈를 변경할 수 있음

동적 배열

  • 원소 개수가 증가할 때마다 필요한 메모리를 확보해야한다.
  • 연속된 메모리를 가져야 하기 때문에 현재 위치에서 용량을 더 늘릴 수 없다면 새 메모리 공간에 복사 및 추가공간 할당이 필요함
  • 최대 수용 가능 용량을 capacity()로 알 수 있다
    • reserve() 함수로 현재 크기의 절반만큼 추가로 할당받음
      • capacity는 한 번 늘어나면 임의로 줄일 수 없음
    • shrink_to_fit() 함수로 남은 메모리 OS에 반납.
    • clear() 함수로 벡터 내 모든 원소 제거(capacity는 그대로이므로 메모리 공간 그대로 차지 중)

삽입, 삭제

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

빌드

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

왼쪽 화살표306오른쪽 화살표