(C++) มาทำโกดังเก็บ Assets สำหรับเกมกัน

เวลาเราจะเขียนเกมแน่นอนว่าจะต้องมีการเรียกฟังก์ชันและโยนที่อยู่ของ Texture,Font,Sount,…etc ซึ่งถ้าเราเรียกแค่ครั้งเดียวก็ไม่มีปัญหาหรอก แต่เกมของเราคงจะจืดชืดหน้าดู ครั้นจะเขียนหลายๆรอบก็หงุดหงิดน่าดู ดังนั้นเราจะมาทำโกดังเก็บ assets ต่างๆของตัวเกมกัน

__credit:https://www.kisspng.com/png-warehouse-building-logistics-distribution-cartoon-266902/

Project Structure

Game
|-assets
| |-texture1.png
| |-texture2.png
|-main.cpp
|-AssetsManager.hpp
|-AssetsManager.cpp
|-TextureManager.hpp
|-TextureManager.cpp

ในส่วนของ main.cpp เราจะไม่บังคับกัน freestyle ตาม lib ของตัวเองเลย

เราจะกระโดดมาที่ TextureManager.hpp กัน

ก่อนอื่นอย่าลืม #pragma onceกันนะจ๊ะ

ต่อเลย

class TextureManager{
public:
static Texture* LoadTexture(const char* filepath);
};

เจ้าคลาส TextureManager เนี่ยเราจะเอาไว้ใช้จัดการพวก Texture ต่างๆในที่นี้เราจะใช้สำหรับ Load ซึ่งเราจะโยนค่าที่อยู่ไปแค่นั้นเอง

เสร็จแล้วมา define function LoadTexture ให้เรียบร้อยใน TextureManager.cpp

#include "TextureManager.hpp"
Texture* TextureManager::LoadTexture(const char* path){
Texture *tex ;
tex = IMG_Load(path);
return tex;
}

วิธีการโหลดTextureในแต่ละ libary จะแตกต่างกันออกไปแต่เราโฟกัสไปที่การ return ค่าออกมาเป็น Textureให้ได้

เอาหละมาต่อที่เมนูหลักเราเลยที่ AssetsManager.hpp

เหมือนเดิม #pragma once

#include<map> //พระเอกของเราเอาไว้เก็บtextureนี่แหละ
#include<string>
#include"TextureManager.hpp"
class AssetsManager
{
public:
void AddTexture(std::string id,const char* path);
Texture *getTexture(std::string id);
private:
std::map<std::string,Texture*> textures;
};

AssetsManager.cpp

#include"AssetsManager.hpp"
void AssetManager::AddTexture(std::string id,const char* path){
textures.emplace(id,TextureManager::LoadTexture(path));
}
Texture *AssetsManager::GetTexture(std::string id){
return texture[id];
}

เรียบร้อยพร้อมใช้งานแล้ว มาทำความเข้าใจก่อน

คือเจ้า AddTexture เนี่ยจะช่วยให้เรากำหนดชื่อของ texture นั้นได้เลยโดยการโยนชื่อ string และ path ของ texture ไป และจะถูกเก็บเข้าไปใน map ที่ชื่อ textures

ต่อมาการนำไปใช้งานจะใช้ผ่านเจ้า GetTexture เราแค่โยนชื่อ texture ไปมันก็คืนค่า texture ชื่อนั้นกลับมา พร้อมนำไป render ต่อทันที พูดไปคงไม่เห็นภาพ มาดูตัวอย่างการใช้งานกัน

ใน main.cpp

//stuff...
#include"AssetsManager.hpp"
Assetsmanager *assets;

main(){
//init zone
//lib init
assets = new AssetsManager();
//load assets zone
assets->AddTexture("Cat","assets/texture1.png");
assets->AddTexture("Tac","assets/texture2.png");
//end init zone
while(gamerunning){
update();
draw(asset->GetTexture("Cat"),sourceproperty
,destinationproperty);
eventhandler();
}
clean();
}

จะเห็นว่าเราจะไม่ได้สร้างตัวแปรมาเก็บ texture ตลอดเวลาที่ใช้งาน เพียงแค่โหลดให้เสร็จตังแต่ส่วนเริ่มเปิดเกม ซึ่งเราอาจนำไปประยุกต์กับการทำ Loading Progress ได้ด้วย

จบไปแล้วครับกับการสร้างโกดังเก็บ assets ซึ่งผมอยากให้เป็นแนวทางในการ implement มากกว่าเพราะ libary ที่มีให้เลือกหลากหลายตามความชอบซึ่งบทความนี้ก็คลุ๊กคลีกับ SDL2 เป็นส่วนใหญ่ ก็ลองๆปรับใช้ดูนะครับ

GLHF with game dev.”


แถม

เราสามารถใช้ AssetManager ในการเปลี่ยนฉากตามเลเวลของด่าได้ด้วย อย่างแบบนี้ (สมมติตัวแปร level เป็น int)

Draw(Game::assets->GetTexture("scene"+std::to_string(level)
,sourceproperty
,destinationproperty);

ที่นี้พอ level เราเพิ่ม scene ของด่านก็จะเปลี่ยนไป จาก 1 เป็น 2 ไปเรื่อยๆ