1. 기존 코드 정리하기

a. 프로젝트 복사하기

  • 목적: 기존에 작업한 코드를 보존하면서 새로운 프로젝트를 생성하여 작업을 이어가기 위함.
  • 방법: 기존 프로젝트를 복사해서 새 프로젝트로 만든다. 복사는 프로젝트 폴더 자체를 복사하여 새로운 위치에 붙여넣는 방식으로 이루어짐.
  • 결과: 새로운 프로젝트 이름은 GameCoding3으로 설정되었으며, 기존 코드를 삭제하지 않고 작업을 새로 시작할 수 있다.

b. 불필요한 파일 삭제

  • 프로젝트 복사 후, 사용하지 않는 파일들을 삭제. 이는 프로젝트에서 제거하는 것이 아니라 실제 파일을 디렉토리에서 삭제함.
  • .txt 파일도 함께 삭제.
  • obj 파일:
    • obj 파일은 빌드의 중간과정에서 생성되는 파일로, 삭제해도 다시 생성되므로 지워도 무방.
    • 주로 x64 폴더에 위치.

c. 폴더 정리하기

  • 새로 정리된 폴더 구조:
    1. Resources: 리소스를 관리하는 폴더.
    2. Binaries: 빌드 결과물이 저장되는 폴더.
    3. Intermediate: 빌드 과정에서 중간에 생성되는 파일을 저장.
  • 출력 디렉터리와 중간 디렉터리를 각각 설정:
    • 출력 디렉터리 → Binaries.
    • 중간 디렉터리 → Intermediate.
  • 리소스는 소스 코드 외부에서 관리되며, 결과물은 올바르게 저장됨.

2. 스프라이트

🌟 스프라이트란?

  • 정의: 게임 내에서 사용되는 그래픽 요소를 의미.
    • 2D 게임: 캐릭터, 아이템, 배경 등이 포함.
    • 3D 게임: 텍스처, 파티클, UI 요소 등도 스프라이트로 사용.
  • 형태: 비트맵 이미지 또는 벡터 이미지.
  • 기능: 움직임이나 상호작용 시 변화를 보여줌.

a. 리소스 파일 다운로드 및 경로 지정

  1. 리소스 파일 다운로드: 사용하려는 그래픽 파일을 다운로드.
  2. 경로 지정:
    • 헤더 파일에 경로를 추가하여 프로젝트 전역에서 사용할 수 있도록 설정.
    • 리소스 매니저를 통해 리소스 경로 정보를 관리.
  3. 초기화 코드:
    • 초기화 시 실행되는 코드를 작성하여, 리소스 경로 설정 및 추가적인 옵션을 포함.

💙 오브젝트와 리소스 차이점

  • 공유의 개념:
    • 리소스는 하나의 자원을 여러 오브젝트가 공유.
    • 예: 동일한 캐릭터 이미지를 여러 번 로드하지 않고 한 번 로드한 이미지를 재사용.

b. 텍스처 만들기

  1. 정의: 이미지를 로드하여 게임에서 사용할 텍스처로 관리.
  2. 코드 작성:
    • ResourceBase를 상속받아 텍스처를 생성.
    • 텍스처를 관리하는 코드를 추가.
  3. 용어 정리:
    • VectorVec2로 변경 (혼동 방지).
    • 정수 버전 Vec2Int 추가.
  4. 투명도(transparent):
    • 이유:
      • BMP 파일은 RGB만 포함 (24비트).
      • 최신 파일에서는 RGBA(알파 채널 포함) 사용.
    • 결론: 현재는 RGB만 포함된 BMP 파일을 사용하므로, 알파 채널을 추가해야 함.

c. 이미지 가져오기

  1. 역할: 텍스처를 기반으로 이미지를 가져오는 용도.
  2. 리소스 매니저:
    • 텍스처 관리 함수 (get, load) 작성.
    • loadTexture 함수 구현 → 스마트 포인터 사용을 권장.
  3. 메모리 관리:
    • 리소스 해제 시 스마트 포인터를 활용.

d. 이미지 테스트하기

  1. 테스트 방법:
    • DevScene에서 테스트 진행.
    • 텍스처를 로드하여 렌더링.
  2. 문제 발생:
    • 테스트 중 이미지 파일 (sword) 누락 시 에러 발생.
  3. 결과: 문제를 해결하고 이미지 렌더링 성공.

e. 스프라이트 생성하기

  1. 역할: 텍스처에서 필요한 부분만 잘라 사용.
  2. 코드 작성:
    • 스프라이트 생성 코드 작성.
    • 텍스처와 유사한 방식으로 관리.

f. 스프라이트 리소스 지정하기

  1. 역할: 리소스 매니저를 통해 스프라이트 관리.
  2. 함수 작성:
    • CreateSprite 함수 구현.
    • 로드된 텍스처를 스프라이트로 변환.

g. 스프라이트 렌더링하기

  1. 과정:
    • 텍스처를 기반으로 스프라이트 생성.
    • 렌더링하여 특정 부분만 출력.
  2. 결과: 필요한 이미지 부분만 정확히 잘라 렌더링 성공.

3. 벡터 및 정수형 정의 (Stat, Vector, VectorInt)

using 키워드 및 정수형 타입 정의

using int8 = __int8;
using int16 = __int16;
using int32 = __int32;
using int64 = __int64;
using uint8 = unsigned __int8;
using uint16 = unsigned __int16;
using uint32 = unsigned __int32;
using uint64 = unsigned __int64;
  • 의도: 다양한 크기의 정수형 타입을 정의하여 코드 가독성을 높이고, 특정 크기의 정수형을 명시적으로 사용할 수 있도록 합니다.

Stat 구조체 정의

struct Stat
{
	int32 hp = 0;
	int32 maxHp = 0;
	float speed = 0;
};
  • Stat 구조체: 캐릭터나 게임 오브젝트의 상태를 나타내는 기본 데이터 구조.
    • hp: 현재 체력.
    • maxHp: 최대 체력.
    • speed: 이동 속도.

Vector 클래스

struct Vector
{
	Vector() {}
	Vector(float x, float y) : x(x), y(y) {}
	Vector(POINT pt) : x((float)pt.x), y((float)pt.y) {}
};
  • 벡터 기본 생성자 및 초기화:
    • Vector(): 기본 생성자.
    • Vector(float x, float y): x, y 좌표를 초기화하는 생성자.
    • Vector(POINT pt): POINT 구조체를 통해 초기화.

벡터 연산자 오버로딩

Vector operator+(const Vector& other)
{
	Vector ret;
	ret.x = x + other.x;
	ret.y = y + other.y;
	return ret;
}
  • operator+: 두 벡터의 합을 반환.
    • xy 좌표를 각각 더하여 새로운 Vector 반환.
Vector operator-(const Vector& other)
{
	Vector ret;
	ret.x = x - other.x;
	ret.y = y - other.y;
	return ret;
}
  • operator-: 두 벡터의 차를 반환.
    • xy 좌표를 각각 빼서 새로운 Vector 반환.

벡터 길이 및 정규화

float Length()
{
	return ::sqrt(LengthSquared());
}

void Normalize()
{
	float length = Length();
	if (length < 0.00000000001f)
		return;

	x /= length;
	y /= length;
}
  • Length: 벡터의 길이를 계산.
  • Normalize: 벡터를 정규화하여 방향만 유지하고 크기를 1로 만듦.

벡터 내적 및 외적

float Dot(Vector other)
{
	return x * other.x + y * other.y;
}

float Cross(Vector other)
{
	return x * other.y - y * other.x;
}
  • Dot: 벡터의 내적을 계산.
  • Cross: 벡터의 외적을 계산.

4. 텍스처 클래스

클래스 선언 및 기본 메서드

class Texture : public ResourceBase
{
public:
	Texture();
	virtual ~Texture();

	Texture* LoadBmp(HWND hwnd, const wstring& path);
	HDC GetDC();
};
  • Texture 클래스:
    • LoadBmp: 비트맵 이미지를 로드.
    • GetDC: 텍스처에 대한 디바이스 컨텍스트 반환.

텍스처 로드 메서드 구현

Texture* Texture::LoadBmp(HWND hwnd, const wstring& path)
{
	HDC hdc = ::GetDC(hwnd);
	_hdc = ::CreateCompatibleDC(hdc);
	_bitmap = (HBITMAP)::LoadImage(nullptr, path.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

	if (_bitmap == 0)
	{
		::MessageBox(hwnd, path.c_str(), L"Image Load Failed", NULL);
	}
	HBITMAP prev = (HBITMAP)::SelectObject(_hdc, _bitmap);
	::DeleteObject(prev);

	BITMAP bit = {};
	::GetObject(_bitmap, sizeof(BITMAP), &bit);

	_size.x = bit.bmWidth;
	_size.y = bit.bmHeight;

	return this;
}
  • 텍스처 로드 과정:
    1. ::CreateCompatibleDC: 호환되는 디바이스 컨텍스트 생성.
    2. ::LoadImage: 비트맵 파일을 로드.
    3. ::GetObject: 비트맵 정보 획득.
    4. _size: 텍스처 크기를 설정.

5. 스프라이트 클래스

스프라이트 선언 및 생성자

class Sprite : public ResourceBase
{
public:
	Sprite(Texture* texture, int32 x, int32 y, int32 cx, int32 cy);
	virtual ~Sprite();

	HDC GetDC();
	int32 GetTransparent();
	Vec2Int GetPos() { return Vec2Int{ _x,_y }; }
	Vec2Int GetSize() { return Vec2Int{ _cx, _cy }; }
};
  • Sprite 클래스:
    • 생성자: 텍스처와 위치, 크기를 기반으로 초기화.
    • GetDC: 텍스처의 디바이스 컨텍스트 반환.
    • GetTransparent: 투명도 정보 반환.

스프라이트 렌더링 구현

void DevScene::Render(HDC hdc)
{
	Sprite* sprite = GET_SINGLE(ResourceManager)->GetSprite(L"Start_On");
	::BitBlt(hdc, 0, 0, GWinSizeX, GWinSizeY, sprite->GetDC(), sprite->GetPos().x, sprite->GetPos().y, SRCCOPY);
}
  • 스프라이트 렌더링:
    • ::BitBlt: 스프라이트를 화면에 그리는 함수.
    • 매개변수:
      • hdc: 대상 디바이스 컨텍스트.
      • sprite->GetDC(): 소스 디바이스 컨텍스트.
      • sprite->GetPos(): 스프라이트의 위치.

6. 리소스 매니저

클래스 선언 및 주요 메서드

class ResourceManager
{
public:
	Texture* LoadTexture(const wstring& key, const wstring& path, uint32 transparent = RGB(255, 0, 255));
	Sprite* CreateSprite(const wstring& key, Texture* texture, int32 x, int32 y, int32 cx, int32 cy);
};
  • LoadTexture: 텍스처를 로드하고 관리.
  • CreateSprite: 텍스처 기반으로 스프라이트를 생성.

텍스처 로드 구현

Texture* ResourceManager::LoadTexture(const wstring& key, const wstring& path, uint32 transparent)
{
	if (_textures.find(key) != _textures.end())
		return _textures[key];

	fs::path fullPath = _resourcePath / path;

	Texture* texture = new Texture();
	texture->LoadBmp(_hwnd, fullPath.c_str());
	texture->SetTransparent(transparent);
	_textures[key] = texture;

	return texture;
}
  • 텍스처 관리:
    • 이미 존재하는 텍스처는 새로 로드하지 않음.
    • 경로를 결합하여 로드 경로 설정.

profile
李家네_공부방

0개의 댓글