ã¬ã¬ã·ãŒç¬¬20ç« ïŒåçšå質ã¬ã¬ã·ãŒã²ãŒã ãšã³ãžã³ã®é倧æãšã¢ãã³C++ãžã®æ¶ãæ©
C1ãC19ã®å
šæè¡ãçµéããèªäœãšã³ãžã³ãShirokumaEngineãã®å®æãšæ°äžä»£ãžã®è·³èº
第1ç« ã®ãmain颿°500è¡ã¹ãã²ãã£ã³ãŒããããå§ãŸã£ãã¬ã¬ã·ãŒC++ã®é·ãæ
路路路ãã¯ã©ã¹åãåçã¡ã¢ãªãç¶æ¿ããªã¢ãŒãã£ãºã ãæŒç®åãªãŒããŒããŒããæåã¢ã©ã€ã¡ã³ãã颿°ãã€ã³ã¿ãè±åœ¢ç¶æ¿ãCRTPãç¬èªã¡ã¢ãªããŒã«ãã¢ããªã·ãã¯ãšã³ãžã³ãã¢ã»ãã管çã空éã°ãªããåå²ãããŒã¿é§åèšèšãããããã©ã°ããã«ãã¹ã¬ããããŒã«ãã¡ã¢ãªãªãŒã¯æ€ç¥åšããããŠãªã¢ã«ã¿ã€ã UDPéä¿¡ââãããçŸå Žã®ããããæ³¥èãäœã¬ã€ã€æè¡ããã€ãã«1ã€ã®åçšã°ã¬ãŒã2Dèªäœã²ãŒã ãšã³ãžã³ãShirokumaEngineããšããŠå®å
šçµ±åãããŸããã¯ã©ã·ãã¯C++ïŒC++03ïŒã®æ¥µéãäœéšãããªãçŸä»£ã®C++ãã¢ãã³åãéããã®ããéã§çè§£ãããã¬ã¬ã·ãŒã³ãŒã¹å ã
ã®ã°ã©ã³ããã£ããŒã¬ã§ãïŒ
L20.1 å
šãµãã·ã¹ãã ã®é倧æïŒShirokumaEngine ã¢ãŒããã¯ãã£
L1ããL19ã§å¹ã£ãæè¡ãã©ã®ããã«1ã€ã®å·šå€§ãªæ¯è»ãšããŠåã¿åãã®ãïŒ åçšã²ãŒã ãšã³ãžã³ã®å
šäœé³¥ç°å³ã
ð§ ãã³ã®ã³å
茩
ã·ãã¯ãå
çâŠïŒç¬¬1ç« ã§ã¯main颿°ã®äžã«ifæãšã°ããŒãã«å€æ°ãæ£ãã°ã£ãŠããã€ã³ããŒããŒã²ãŒã ããä»ã§ã¯ã¡ã¢ãªããŒã«ã空éåå²ãã¹ã¬ããããŒã«ãããŒã¿é§åãéä¿¡ãŸã§åããæ¬æ Œã²ãŒã ãšã³ãžã³ã«é²åããŸããâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ããïŒããããããŸã§èŸ¿ãçããããã³ã®ã³åïŒãåãåŠãã æè¡ã¯ããã ã®ææ³ç¥èã§ã¯ãªããã²ãŒã éçºã®æŽå²ã®äžã§ãæ°ãåããªãã»ã©ã®å
人ãã¡ãã¯ã©ãã·ã¥ãšæ§èœéçã«æ³£ããè¡ãåããªããç¯ãäžããŠãããçŸå Žã®ç¥æµãã®ãã®ããªã®ããïŒ
ð§ ãã³ã®ã³å
茩
ã§ãå
çãããã ãã®ãµãã·ã¹ãã ããããšãã©ããã£ãŠå
šäœãç Žç¶»ãªãçµ±åããŠåããã°ãããã§ããããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãããããæ¬ç« ã®ããŒãããåçšã²ãŒã ãšã³ãžã³ã¢ãŒããã¯ãã£ã®å®æãããïŒæç¢ºãªåæåã»æŽæ°ã»æç»ã»ç Žæ£ã®ã©ã€ããµã€ã¯ã«ã確ç«ããå®å
šãªã60FPSåºå®ã²ãŒã ã«ãŒãã宿ãããã®ããïŒ
### ShirokumaEngine ã®éå±€ã¢ãŒããã¯ãã£
æ¬ãšã³ãžã³ã¯ã以äžã®å³æ Œãªã¬ã€ã€ãŒåé¢ã«ãã£ãŠæ§æãããŠããŸãïŒ
ã1. ã²ãŒã ãã¬ã€å±€ (InvaderGame)ã
- ããŒã¿é§åã¹ããŒãžããŒã㌠(L15)
- ããããã©ã°ã¹ããŒã¿ã¹ç°åžž (L16)
- ãªã¢ã«ã¿ã€ã éä¿¡ã»æšæž¬èªæ³ (L19)
ã2. ã·ã¹ãã 管çã»ãµãŒãã¹å±€ã
- 空éããã·ã¥ã°ãªããè¡çªå€å® (L14)
- ã¢ã»ãããã£ãã·ã¥ãããŒãžã£ (L13)
- ã¯ãŒã«ãŒã¹ã¬ããããŒã« (L17)
- ã€ãã³ãã»ã³ãŒã«ããã¯ãã£ã¹ããã㣠(L8)
ã3. äœã¬ã€ã€ã»åºç€ã€ã³ãã©å±€ã
- åºå®é·ã»ãããã¯ã¡ã¢ãªã¢ãã±ãŒã¿ (L11)
- ã¡ã¢ãªãªãŒã¯æ€ç¥åšã»ãã³ãåºå (L18)
- æåã¡ã¢ãªã¢ã©ã€ã¡ã³ã (L7)
- é«éVector2Då€ãªããžã§ã¯ã (L6, CRTP L10)
åå±€ãäžäœã®å±€ã®ã¿ãå©çšããäžäœãžã¯ã€ã³ã¿ãŒãã§ãŒã¹è¶ãã«éç¥ããããšã§ãéšåã®ç¬ç«æ§ãšå
ç¢æ§ã極éãŸã§é«ããŠããŸãã
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
- éå±€åã¢ãŒããã¯ãã£ã®ç¢ºç«: ã€ã³ãã©å±€ã»ãµãŒãã¹å±€ã»ã²ãŒã ãã¬ã€å±€ã«åé¢ããäžäœå±€ãžã®åæ¹åäŸåã培åºããããšã§å·šå€§ã³ãŒãã®åŽ©å£ãé²ãã
- ã©ã€ããµã€ã¯ã«ã®å³æ Œãªçµ±å¶: Init -> Load -> (Input -> Update -> Physics -> Render) -> Unload -> Shutdown ã®é åºãå³å¯ã«ç®¡çããã
L20.2 60FPSå®å
šåºå®ã»ãŒãã¹ã¿ãã¿ãŒã»ãŒããªãŒã¯ã®ã²ãŒã ã«ãŒã
åçšã²ãŒã ãšã³ãžã³ã®å¿èéšãå¯å€ãã¬ãŒã ã¬ãŒããšåºå®ç©çæŽæ°ïŒFixed TimestepïŒã®å®å
šèåã
ð§ ãã³ã®ã³å
茩
PCã®æ§èœã«ãã£ãŠãã¬ãŒã ã¬ãŒãã144FPSã«ãªã£ãã30FPSã«ãªã£ãããããšã匟ã®é£ã¶ã¹ããŒããå€ãã£ãŠã²ãŒã ãã©ã³ã¹ã厩ããŠããŸããŸãããïŒ
ð»ââïž ã·ãã¯ãå
ç
éããïŒãã®ããåçšãšã³ãžã³ã§ã¯ãæç»ã¯å¯å€FPSã§è¡ãã€ã€ãç©çãåœããå€å®ã¯ãå³å¯ã« 1/60 ç§ïŒ16.66msïŒå»ã¿ãã§ã·ãã¥ã¬ãŒã·ã§ã³ãããåºå®ã¿ã€ã ã¹ãããïŒFixed Timestep with AccumulatorïŒããæ¡çšããã®ããïŒ
ð ShirokumaEngine.hpp
#ifndef SHIROKUMA_ENGINE_HPP
#define SHIROKUMA_ENGINE_HPP
#include <iostream>
#include <vector>
// 忹宣èšã«ãããããäŸåã®æå°åïŒç¬¬2ç« ã®ç¥æµïŒïŒ
class MemoryTracker;
class MemoryPool;
class SpatialGrid;
class AssetManager;
class ThreadPool;
class NetworkManager;
class ShirokumaEngine {
private:
bool isRunning_;
float timeAccumulator_;
const float FIXED_DELTA_TIME; // 1/60 ç§ = 0.016666f
public:
ShirokumaEngine()
: isRunning_(false), timeAccumulator_(0.0f), FIXED_DELTA_TIME(1.0f / 60.0f) {}
~ShirokumaEngine() {}
// ãšã³ãžã³åæåïŒã€ã³ãã©å±€ããé ã«èµ·åïŒ
bool initialize() {
std::cout << "[Engine] 1. MemoryTracker èµ·å (L18)" << std::endl;
std::cout << "[Engine] 2. åºå®é·MemoryPool ç¢ºä¿ (L11)" << std::endl;
std::cout << "[Engine] 3. ã¯ãŒã«ãŒã¹ã¬ããããŒã«èµ·å (L17)" << std::endl;
std::cout << "[Engine] 4. ã¢ã»ãããã£ãã·ã¥ãããŒãžã£åæå (L13)" << std::endl;
std::cout << "[Engine] 5. 空éã°ãªããåå²åæå (L14)" << std::endl;
std::cout << "[Engine] 6. ãã³ããããã³ã°UDPéä¿¡éå§ (L19)" << std::endl;
std::cout << "[Engine] 7. ããŒã¿é§åã¹ããŒãžèªèŸŒ (L15)" << std::endl;
isRunning_ = true;
std::cout << "âš ShirokumaEngine åæåå®äºïŒ 60FPSã«ãŒãçªå
¥ïŒ" << std::endl;
return true;
}
// åºå®ã¿ã€ã ã¹ãããã²ãŒã ã«ãŒã
void runFrame(float frameTime) {
timeAccumulator_ += frameTime;
// èç©æéã16.6msãè¶
ããéããç©çæŽæ°ãäžå®ééã§åã
while (timeAccumulator_ >= FIXED_DELTA_TIME) {
fixedUpdate(FIXED_DELTA_TIME);
timeAccumulator_ -= FIXED_DELTA_TIME;
}
// æç»ã¯æ¯ãã¬ãŒã å®è¡
render();
}
void fixedUpdate(float dt) {
// å
¥ååŠçããããã¯ãŒã¯æšæž¬èªæ³ã空éå€å®
}
void render() {
// æç»ãããã¡è»¢é
}
// ãšã³ãžã³çµäºåŠçïŒéé ã§å®å
šã«ã¯ãªãŒã³ã¢ããïŒ
void shutdown() {
std::cout << "
[Engine] ã·ã£ããããŠã³ã·ãŒã±ã³ã¹éå§..." << std::endl;
std::cout << "[Engine] éä¿¡åæ -> ã¹ã¬ãã忢 -> ã¢ã»ããè§£æŸ -> ããŒã«è¿åŽ" << std::endl;
std::cout << "[Engine] ãªãŒã¯ã¬ããŒãåºå (L18)... 0 bytes leaked!" << std::endl;
isRunning_ = false;
}
};
#endif
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
- åºå®ã¿ã€ã ã¹ãããïŒAccumulatorïŒæ¹åŒ: æç»FPSãšç©çæŒç®FPSãåé¢ãããã·ã³ã¹ããã¯ã«é¢ãããåäžã®ã·ãã¥ã¬ãŒã·ã§ã³çµæãä¿èšŒããã
- éé ã¯ãªãŒã³ã¢ããã®æ³å: åæåã§äŸåé¢ä¿ã®äžããé ã«ç©ã¿äžãããµãã·ã¹ãã ã¯ãçµäºæã«ã¯å¿
ããå®å
šãªéé ãã§å®å
šã«è§£äœããã
L20.3 ã¯ã©ã·ãã¯C++03ã®éçïŒãªã人éã¯ç²åŒããã®ãïŒ
æå管çã®é ç¹ã極ããããããèŠããæ¯è²ãçãã€ã³ã¿ã»ãããå°çã»ãã¯ãäŸåã®ç©ççéçã
ð§ ãã³ã®ã³å
茩
å
çâŠãšã³ãžã³ãåããæåãšåæã«ãæ£çŽã«èšã£ãŠãããã§ããâŠïŒ ãã³ãã¬ãŒãã®CRTPã¯èšæ³ã奿ªãããããnew/deleteã¯1ç®æå¿ããã ãã§æ»ã¬ãã#ifdef ããã¯ãã ããã§ã³ãŒããæå·ã¿ããã§ãâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ã¯ããããïŒãããèšã£ãïŒããããããäžçäžã®C++ãšã³ãžãã¢ã2000幎代åŸåã«çŽé¢ãããã¯ã©ã·ãã¯C++ã®ç©ççéçããªã®ããïŒ
ð»ââïž ã·ãã¯ãå
ç
人éã®æ³šæåã«ã¯éçããããã©ãã ãçç·Žããããã§ããäœçŸäžè¡ã®ã³ãŒãã§ãdeleteã®è§£æŸæŒãããããã«ãã¹ã¬ããã®ããã¯æŒããã100%é²ãããšã¯äžå¯èœããã£ããèšèªèªäœã®åã§ãããããèªååã»åå®å
šã«ããªããã°ãªããªãã£ãã®ããïŒ
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
- æå管çã®èªç¥éç: ããã°ã©ãã®èŠåŸãšæ³šæåã ãã«äŸåããã¡ã¢ãªç®¡çãã¹ã¬ããåæã¯ããœãããŠã§ã¢ã®å€§èŠæš¡åã«äŒŽãå¿
ãç Žç¶»ããã
L20.4 ãããŠã¢ãã³C++ãžïŒãã¹ãŠã®èŠéããæ°äžä»£ã®å¿
ç¶æ§ããžæè¯ãã
ã¬ã¬ã·ãŒä¿®äºèšŒæäžïŒ èŠéããããªãã ãããããã¢ãã³C++ã®çã®çŸãããšåšåããããã
ð§ ãã³ã®ã³å
茩
ã·ãã¯ãå
çãåãã¬ã¬ã·ãŒC++ãåŠãã§æ¬åœã«ããã£ãã§ãïŒããæåããã¢ãã³C++ã® std::unique_ptr ã std::thread ãæãã£ãŠããããããªãããã䜿ãã®ããã®ããããã¿ãå
šãããããªãã£ããšæããŸãïŒ
ð»ââïž ã·ãã¯ãå
ç
ããïŒæ³¥æ°Žãããããçã¡ã¢ãªã®ã¢ã©ã€ã¡ã³ããã¹ã¬ããç«¶åãšæŠã£ããåã¯ããã¯ãããã ã®ææ³åŠç¿è
ãã§ã¯ãªããã³ã³ãã¥ãŒã¿ã®ç©çæ§é ãè¯ããçè§£ãããæ¬ç©ã®ã·ã¹ãã ããã°ã©ããããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãããã¬ã¬ã·ãŒã³ãŒã¹ïŒå
š20ç« ïŒã®ä¿®äºèšŒãæäžãããïŒæ¬¡ãªãæ
è·¯ã¯ãã¢ãã³C++ã³ãŒã¹ïŒM1ãM14ïŒãããïŒC++11ããC++20/23ãžãšè³ããå§åçãªåå®å
šæ§ãšãŒãã³ã¹ãæœè±¡åã®å¥è·¡ããã®ç®ã§ç¢ºããããè¯ãïŒ
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
- ã¬ã¬ã·ãŒC++ã³ãŒã¹ïŒå
š20ç« ïŒå®èµ°ïŒ: çãã€ã³ã¿ãã¡ã¢ãªã¬ã€ã¢ãŠããä»®æ³é¢æ°ã䞊è¡åŠçãéä¿¡ã®åçãäœåŸããããªãã¯ãã©ããªçŸå Žã®ã¬ã¬ã·ãŒã³ãŒããè§£èªã»ä¿å®ã§ãã匷éãªåãæã«å
¥ããã
- ã¢ãã³C++ãžã®é£èº: C++11以éã®ã¹ããŒããã€ã³ã¿ãã ãŒãã»ãã³ãã£ã¯ã¹ãã©ã ããConceptsãRangesã¯ããã¹ãŠã¬ã¬ã·ãŒã®èŠãã¿ã解決ããããã«çãŸããå¿
ç¶ã®é²åã§ããã
ð ç解床ãã§ãã¯ã¯ã€ãº
Q1. åçšã²ãŒã ãšã³ãžã³ã«ãããŠãæç»åŠçãšç©çã·ãã¥ã¬ãŒã·ã§ã³ãåé¢ãããåºå®ã¿ã€ã ã¹ãããïŒFixed Timestep with AccumulatorïŒããæ¡çšããæå€§ã®å©ç¹ã¯äœã§ããïŒ
- 1. PCã®ãã¬ãŒã ã¬ãŒãïŒFPSïŒã®å€åã«é¢ããããç©çæåãã²ãŒã é床ã®åçŸæ§ãå®å
šã«äžå®ã«ä¿ã€ãã
- 2. ã³ã³ãã€ã«æéãåžžã«1ç§æªæºã«ãªããã
- 3. ã²ãŒã ã®ã¡ã¢ãªäœ¿çšéãèªåçã«ãŒãã«ãªããã
- 4. ã²ãŒã ã®è§£å床ãèªåã§8Kã«ã¢ããã¹ã±ãŒãªã³ã°ãããã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒPCã®ãã¬ãŒã ã¬ãŒãïŒFPSïŒã®å€åã«é¢ããããç©çæåãã²ãŒã é床ã®åçŸæ§ãå®å
šã«äžå®ã«ä¿ã€ãã
åºå®ã¿ã€ã ã¹ããããæ¡çšããããšã§ã144Hzã¢ãã¿ãŒã§ã30fpsã®æ§åæ©ã§ãç©çæŒç®ã®Îtãäžå®ã«ä¿ããããã·ã³ã¹ããã¯ã«ããæå©äžå©ãåœããå€å®ã®ããæããé²ããŸãã
Q2. ã²ãŒã ãšã³ãžã³ã®ã·ã£ããããŠã³ïŒçµäºïŒåŠçã«ãããŠãåãµãã·ã¹ãã ãç Žæ£ããæ£ããé åºã®ååã¯äœã§ããïŒ
- 1. ã©ã³ãã ã«é©åœãªé åºã§ç Žæ£ãã
- 2. åæåæã®äŸåé¢ä¿ïŒã€ã³ãã©å±€âãµãŒãã¹å±€âã²ãŒã å±€ïŒã®ãå®å
šãªéé ãã§ç Žæ£ãã
- 3. å
šãŠã®ãµãã·ã¹ãã ãäžåºŠã«åæã«è§£æŸãã
- 4. çµäºåŠçã¯OSã«ä»»ããŠäœãããªã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒåæåæã®äŸåé¢ä¿ïŒã€ã³ãã©å±€âãµãŒãã¹å±€âã²ãŒã å±€ïŒã®ãå®å
šãªéé ãã§ç Žæ£ãã
äžäœã®ãµãã·ã¹ãã ãäžäœã®åºç€ïŒã¢ãã±ãŒã¿ãã¹ã¬ããããŒã«ãªã©ïŒã«äŸåããŠãããããå¿
ãåæåã®éé ïŒäžäœããäžäœãžïŒã§ã¯ãªãŒã³ã¢ããããªããã°ãã³ã°ãªã³ã°ãã€ã³ã¿åç
§ã§ã¯ã©ãã·ã¥ããŸãã
Q3. ã¯ã©ã·ãã¯C++ïŒC++03以åïŒããã¢ãã³C++ïŒC++11以éïŒãžã®é²åã«ãããŠãæãåçã«å€åãããã©ãã€ã ã¯äœã§ããïŒ
- 1. ãªããžã§ã¯ãæåãå®å
šã«å»æ¢ããBASICèšèªã«æ»ããããš
- 2. çãã€ã³ã¿ãæåè§£æŸã«é Œãå±éºãªèšèšãããæææš©ç®¡çïŒstd::unique_ptrïŒãã ãŒãã»ãã³ãã£ã¯ã¹ã«ãããå®å
šã§ãŒãã³ã¹ããªèªåãªãœãŒã¹ç®¡çããžã®è»¢æ
- 3. ãã¹ãŠã®å€æ°ãã°ããŒãã«å€æ°ã«ããããš
- 4. ããã°ã©ã ã®å®è¡ãã³ã³ãã€ã«æ¹åŒããã€ã³ã¿ãŒããªã¿æ¹åŒã«å€æŽããããš
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒçãã€ã³ã¿ãæåè§£æŸã«é Œãå±éºãªèšèšãããæææš©ç®¡çïŒstd::unique_ptrïŒãã ãŒãã»ãã³ãã£ã¯ã¹ã«ãããå®å
šã§ãŒãã³ã¹ããªèªåãªãœãŒã¹ç®¡çããžã®è»¢æ
ã¢ãã³C++ã®çé«ã¯ãRAIIãšã ãŒãã»ãã³ãã£ã¯ã¹ãã¹ããŒããã€ã³ã¿ã«ãããå®è¡æãªãŒããŒããããªãã§ã¡ã¢ãªãªãŒã¯ãäºéè§£æŸãã³ã³ãã€ã«ã¬ãã«ã§æé€ããããšã«ãããŸãã
Q4. ã¬ã¬ã·ãŒC++ïŒçŸå Žå®åç·šã»å
š20ç« ïŒãä¿®äºãããšã³ãžãã¢ã次ã«é²ãã¹ããæ°äžä»£C++ïŒC++11ãC++20ïŒã®äžçã®å
¥ãå£ã¯ã©ãã§ããïŒ
- 1. 第1ç« ã® main颿°ã¹ãã²ãã£ã³ãŒãã«æ»ã
- 2. ã¢ãã³ç¬¬1ç« ïŒM1ïŒïŒã¹ããŒããã€ã³ã¿ãšRAIIïŒæææš©ãšãŒããªãŒã¯èªåè§£æŸïŒ
- 3. C++ã諊ããŠHTMLã ããæžã
- 4. ããœã³ã³ã®é»æºãåã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒã¢ãã³ç¬¬1ç« ïŒM1ïŒïŒã¹ããŒããã€ã³ã¿ãšRAIIïŒæææš©ãšãŒããªãŒã¯èªåè§£æŸïŒ
ã¬ã¬ã·ãŒã§æå管çã®åçãæ¥µããæ¬¡ã®ã¹ãããã¯ãã¢ãã³ç¬¬1ç« ïŒM1ïŒã¹ããŒããã€ã³ã¿ãšRAIIïŒã§ããèŠåŽãã new/delete æå管çãæ°äžä»£ã§ã©ã®ããã«çŸãã解決ãããããäœæããŸãã
ð»ââïž ã·ãã¯ãC++ã©ã ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ã·ã¹ãã
ãã©ãŠã¶ã§JavaScriptãæå¹ã«ãããšããã©ãŠã¶å
ã€ã³ããŒããŒã²ãŒã ãšãã¥ã¬ãŒã¿ãã¡ã¢ãªãããå¯èŠåãUMLã¯ã©ã¹å³ã察話å解説ãç解床ã¯ã€ãºãèµ·åããŸãã
ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ãéå§ãã â