68. 타일 맵
*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
- 화장실 타일 깔듯이 게임을 일정 구획으로 나누고, 구획별로 그림을 붙여서 커다란 맵을 만드는 방식
- 행렬 또는 이차원 배열 구성으로 생각해야 한다.
- 그러므로 각 타일은 X좌표와 Y좌표를 저장해야 한다.
- 슈퍼마리오가 대표적인 타일맵 구성이다.
flag.h
{ enum class ETileOption }
- 해당 타일이 갈 수 있는 곳인지 없는 곳인지를 저장하기 위해 만든 열거체
- Normal, Blocked
class CTile
- 각각 하나의 타일에 해당하는 클래스.
< 헤더파일 코드 전문 >
#pragma once
#include "../GameInfo.h"
//개별 타일 클래스
class CTile
{
friend class CTileMap;
private:
CTile();
~CTile();
private:
class CScene* m_Scene;
class CTileMap* m_Owner;
//타일 이미지
CSharedPtr<class CTexture> m_Texture;
public://전체적인 타일 정보 설정
void SetTileInfo(const Vector2& Pos, const Vector2& Size,
int IndexX, int IndexY, int Index, class CTexture* Texture);
private://타일이 갈 수 있는 곳인지 없는 곳인지
ETileOption m_Option;
public:
ETileOption GetOption() const;
void SetTileOption(ETileOption Option);
private://위치와 크기.
Vector2 m_Pos;
Vector2 m_Size;
public:
const Vector2& GetPos() const;
const Vector2& GetSize() const;
private://타일의 행렬 번호
int m_IndexX;
int m_IndexY;
int m_Index;
private://스프라이트 이미지 출력 위치 저장
int m_TileFrame;
Vector2 m_StartFrame;
Vector2 m_EndFrame;
public:
void SetFrame(const Vector2& Start, const Vector2& End);
public:
void Render(HDC hDC);
};
- 한 타일에 대한 정보를 저장할 클래스이다.
- 여기는 별거 없다. 자신의 위치값, 사이즈값, 타일맵 상에서의 행렬 번호를 단순히 저장하고,
자신의 이미지가 Frame인지 Sprite인지 확인한 후 자신의 위치에 출력해주면 끝이다.
class CTileMap
- 여기에 개별 타일맵을 모아서 배열로 저장한다.
- CGameObject로 취급하므로 렌더링 레이어를 지정해 주면 알아서 렌더링이 될 것이다.
< 헤더 코드 전문 >
#pragma once
#include "GameObject.h"
class CTileMap :
public CGameObject
{
friend class CScene;
protected:
CTileMap();
CTileMap(const CTileMap& Obj);
virtual ~CTileMap();
public:
virtual bool Init(class CGameObject* Obj = nullptr);
private:
std::vector<class CTile*> m_vecTile;
CSharedPtr<class CTexture> m_TileTexture;
int m_CountX;
int m_CountY;
Vector2 m_TileSize;
int m_StartX;
int m_StartY;
int m_EndX;
int m_EndY;
public:
int GetCountX() const;
int GetCountY() const;
public:
void ChangeTileOption(const Vector2& Pos, ETileOption Option);
void SetTileFrame(const Vector2& Pos, const Vector2& Start,
const Vector2& End);
class CTile* GetTile(const Vector2& Pos);
class CTile* GetTile(int Index);
class CTile* GetTile(int IndexX, int IndexY);
int GetTileIndexX(float x);
int GetTileIndexY(float y);
int GetTileIndex(const Vector2& Pos);
public:
//타일 생성 관련
bool CreateTile(int CountX, int CountY, const Vector2& TileSize);
void SetTileTexture(const std::string& Name);
void SetTileTexture(class CTexture* Texture);
void SetTileTexture(const std::string& Name, const std::tstring& FileName,
const std::string& PathName = TEXTURE_PATH);
void SetTileTextureFullPath(const std::string& Name, const std::tstring& FullPath);
void SetTileTexture(const std::string& Name, const std::vector<std::tstring>& vecFileName,
const std::string& PathName = TEXTURE_PATH);
void SetTileTextureFullPath(const std::string& Name, const std::vector<std::tstring>& vecFullPath);
bool SetTileColorKey(unsigned char r, unsigned char g, unsigned char b,
int Index = 0);
bool SetTileColorKeyAll(unsigned char r, unsigned char g, unsigned char b);
public:
virtual void Update(float DeltaTime);
virtual void Render(HDC hDC, float DeltaTime);
};
- 여기에는 타일맵의 x축 갯수, y축 갯수를 저장하고, 매 프레임마다 텍스처 수만큼 순회를 돌며 타일들을 렌더링해준다.
< Update() >
{ int m_StartX; }
{ int m_StartY; }
{ int m_EndX; }
{ int m_EndY; }
- 이 변수들은 오브젝트 컬링을 위한 용도이다.
- 타일맵을 100 * 100 사이즈로 만든다고 가정해보자. 그러면 한 프레임에 출력할 타일은 10000개이다.
- 10000개를 매 프레임 다 출력하면 성능이 매우 낮아질 것이므로 오브젝트 컬링을 필수적으로 해 주어야 한다.
- Update() 단계에서 미리 계산해 놓는다.
* 반드시 타일맵의 범위를 넘어갔을 때에 대한 예외처리를 해 주어야 한다.
< Render() >
- 위에서 이미 출력할 범위는 구했으니, 여기서는 가지고 있는 타일 벡터 m_vecTile을 출력할 범위 안에서 순회를 돌면서 렌더링해주면 된다.
- 다 만들고, CMainScene에서 생성해서 잘 작동하는지 확인해보았다.