
ãã®èšäºã§ã¯ãEntity-Component-SystemïŒ ECS ïŒèšèšãã¿ãŒã³ã«ã€ããŠèª¬æããŸãã ã€ã³ã¿ãŒãããã§ãã®ãããã¯ã«é¢ããå€ãã®æ å ±ãèŠã€ããããšãã§ããŸãã®ã§ãç§ã¯èª¬æã«æ·±ãå ¥ããŸããããç§èªèº«ã®å®è£ ã«ã€ããŠãã£ãšè©±ããŸãã
ããŒã1ïŒC ++ã§ã®Entity-Component-Systemãã³ãã¬ãŒãã®å®è£
ããçŽããŸãããã ECSå®è£ ã®å®å šãªãœãŒã¹ã³ãŒãã¯ã githubãªããžããªã«ãããŸãã
äž»ã«ã²ãŒã ã§äœ¿çšãããEntity-Component-Systemã¯ãäžè¬çãªãœãããŠã§ã¢ã¢ãŒããã¯ãã£ã®èšèšã«ãããŠéåžžã«é«ãæè»æ§ãæäŸããèšèšãã¿ãŒã³ã§ã[1] ã UnityãEpicãCrytekãªã©ã®å€§äŒæ¥ã¯ããã®ãã³ãã¬ãŒãããã¬ãŒã ã¯ãŒã¯ã§äœ¿çšããŠãéçºè ãç¬èªã®ãœãããŠã§ã¢ãéçºã§ããéåžžã«æ©èœè±å¯ãªããŒã«ãæäŸããŠããŸãã ãããã®æçš¿[2,3,4,5]ã§ããã®ãããã¯ã«é¢ããããåºç¯ãªè°è«ãèªãããšãã§ããŸãã
ãããã®èšäºãç 究ãããšãããããã¹ãŠã«å ±éã®ç®æšãããããšã«æ°ä»ãã§ãããïŒãšã³ãã£ãã£ïŒãšã³ãã£ãã£ïŒãã³ã³ããŒãã³ãïŒã³ã³ããŒãã³ãïŒãã·ã¹ãã ïŒã·ã¹ãã ïŒéã®ããŸããŸãªåé¡ãšã¿ã¹ã¯ã®åæ£ã ãããã¯ããã®ãã³ãã¬ãŒãã®3ã€ã®åºæ¬æŠå¿µã§ãããããªãèªç±ã«æ¥ç¶ãããŠããŸãã ãšã³ãã£ãã£ã¯éåžžãäžæã®èå¥åãäœæããåäžã®èŠçŽ ã®ååšã«é¢ããæ å ±ãç°å¢ã«æäŸããå€ãã®ã³ã³ããŒãã³ããçµã¿åãããäžçš®ã®ã«ãŒããªããžã§ã¯ããšããŠæ©èœããããã«äœ¿çšãããŸãã ã³ã³ããŒãã³ãã¯ãè€éãªããžãã¯ãæããªãã³ã³ãããªããžã§ã¯ãã«ãããŸããã çæ³çã«ã¯ããããã¯ãã¬ãŒã³ãªãŒã«ãããŒã¿ãªããžã§ã¯ãïŒPODïŒãæã€ãªããžã§ã¯ãã§ãã åã¿ã€ãã®ã³ã³ããŒãã³ãããšã³ãã£ãã£ã«ã¢ã¿ããããŠãããããã£ã®ãããªãã®ãäžããããšãã§ããŸãã ãHealth-Componentãããšã³ãã£ãã£ã«ã¢ã¿ãããããšããšã³ãã£ãã£ãèŽåœçã«ãªããã¡ã¢ãªå ã®éåžžã®æŽæ°å€ãŸãã¯å°æ°å€ã§ããhealthãäžããããŸãã
ç§ãåºäŒã£ãã»ãšãã©ã®èšäºã¯ããšã³ãã£ãã£ãšã³ã³ããŒãã³ãã®äœ¿çšã«é¢ããŠäºãã«äžè²«ããŠããŸãããã·ã¹ãã ã«é¢ããæèŠã¯ç°ãªããŸãã äžéšã®äººã ã¯ãã³ã³ããŒãã³ãã®ã¿ãã·ã¹ãã ã«ç¥ãããŠãããšä¿¡ããŠããŸãã ããã«ãåã¿ã€ãã®ã³ã³ããŒãã³ãã«ã¯ç¬èªã®ã·ã¹ãã ãå¿ èŠã§ãããšèšã人ãããŸããããšãã°ããCollision-Componentsãã®å Žåã¯ãCollision-SystemãããHealth-Componentsã-ãHealth-Systemããªã©ã§ãã ãã®ã¢ãããŒãã¯éåžžã«å³å¯ã§ãããããŸããŸãªã³ã³ããŒãã³ãã®çžäºäœçšãèæ ®ããŠããŸããã ããã»ã©å³å¯ã§ã¯ãªãã¢ãããŒãã¯ãç°ãªãã·ã¹ãã ãèªèãã¹ãã³ã³ããŒãã³ããåŠçããããšã§ãã ããšãã°ãç©çã·ã¹ãã ã¯è¡çªã³ã³ããŒãã³ããšãªãžããããã£ã³ã³ããŒãã³ãã«ã€ããŠç¥ã£ãŠããå¿ èŠããããŸããã©ã¡ããç©çã®ã·ãã¥ã¬ãŒã·ã§ã³ã«å¿ èŠãªæ å ±ãå«ãã§ããå¯èœæ§ãé«ãããã§ãã ç§ã®è¬èãªæèŠã§ã¯ã ã·ã¹ãã ã¯ãéããããç°å¢ãã§ãã ã€ãŸãããšã³ãã£ãã£ãŸãã¯ã³ã³ããŒãã³ãã®ããããææããŠããŸããã ç¬ç«ãããã£ã¹ãããã£ãªããžã§ã¯ããä»ããŠãããã«ã¢ã¯ã»ã¹ãããšã³ãã£ãã£ãšã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ãé çªã«å¶åŸ¡ããŸãã
ããã¯èå³æ·±ã質åãæèµ·ããŸãïŒãšã³ãã£ãã£ãã³ã³ããŒãã³ããããã³ã·ã¹ãã ã¯ãäºãã«å€å°ç¬ç«ããŠããå Žåãã©ã®ããã«æ å ±ã亀æããŸããïŒ çãã¯ç°ãªãå Žåããããå®è£ ã«ãã£ãŠç°ãªããŸãã ç§ã®å®è£ ã§ã¯ãçãã¯ã€ãã³ããœãŒã¹[6]ã§ãã ã€ãã³ãã¯ãã€ãã³ããããŒãžã£ãŒããéããŠé ä¿¡ãããã€ãã³ãã«èå³ããã人ã¯ãããŒãžã£ãŒãéä¿¡ããæ å ±ãåãåãããšãã§ããŸãã ãšã³ãã£ãã£ãã·ã¹ãã ããŸãã¯ã³ã³ããŒãã³ãã§ããããäœçœ®ãå€ãã£ãããŸãã¯ããã¬ã€ã€ãŒãæ»äº¡ããããªã©ãå ±åããå¿ èŠãããéèŠãªç¶æ ã®å€åãããå Žåããã€ãã³ããã£ã¹ãããã£ãŒãã«æ å ±ãéä¿¡ã§ããŸãã 圌ã¯ã€ãã³ãã«åæ Œãããã®ã€ãã³ãã«ãµãã¹ã¯ã©ã€ãããŠãããã¹ãŠã®äººãããã«ã€ããŠç¥ã£ãŠããŸãã ãããã£ãŠããã¹ãŠãçžäºã«æ¥ç¶ã§ããŸãã
å°å ¥ã¯ç§ãèšç»ãããããé·ãã£ãããã§ãã ã¡ãªã¿ã«ãC ++ 11ã§èšè¿°ãããã³ãŒãã®ç 究ãæãäžããåã«ãç§ã®ã¢ãŒããã¯ãã£ã®åºæ¬çãªç¹åŸŽã®æŠèŠã説æããŸãã
- ã¡ã¢ãªå¹ç -ãšã³ãã£ãã£ãã³ã³ããŒãã³ããã·ã¹ãã ãããã³ã€ãã³ãã®ãªããžã§ã¯ãããã°ããäœæããã³åé€ããããã«ãæšæºã®åçã¡ã¢ãªç®¡çã«é Œãããšã¯ã§ããŸããã ãã¡ããããã®å Žåã®è§£æ±ºçã¯ãç¬èªã®ã¡ã¢ãªã¢ãã±ãŒã¿ã§ãã
- ãã®ã³ã° -äœãèµ·ãã£ãŠãããã远跡ããããã«ããã®ã³ã°ã«log4cplus [7]ã䜿çšããŸããã
- ã¹ã±ãŒã©ããªã㣠-ã·ã¹ãã ã¡ã¢ãªãé€ããäžéãæå®ããã«æ°ããã¿ã€ãã®ãšã³ãã£ãã£ãã³ã³ããŒãã³ããã·ã¹ãã ãããã³ã€ãã³ããç°¡åã«å®è£ ã§ããŸãã
- æè»æ§ -ãšã³ãã£ãã£ãã³ã³ããŒãã³ããããã³ã·ã¹ãã éã«äŸåé¢ä¿ã¯ãããŸããïŒãã¡ããããšã³ãã£ãã£ãšã³ã³ããŒãã³ãã«ã¯äžçš®ã®äŸåé¢ä¿ããããŸãããçžäºã®ãã€ã³ã¿ã®ããžãã¯ã¯å«ãŸããŠããŸããïŒ
- ãªããžã§ã¯ãã®åçŽãªæ€çŽ¢/ããããžã®ã¢ã¯ã»ã¹ -ç¹å®ã®ã¿ã€ãã®ãã¹ãŠã®ã³ã³ããŒãã³ããå埩ããããã®EntityIdãŸãã¯ã³ã³ããŒãã³ãã®ã€ãã¬ãŒã¿ãŒãä»ãããšã³ãã£ãã£ãªããžã§ã¯ããšãã®ã³ã³ããŒãã³ãã®åçŽãªååŸ
- å®è¡å¶åŸ¡ -ã·ã¹ãã ã«ã¯åªå é äœããããçžäºã«äŸåã§ãããããå®è¡ããããããžã«ã«ãªé åºã確ç«ã§ããŸã
- 䜿ãããã -ã©ã€ãã©ãªã¯ä»ã®ãœãããŠã§ã¢ã§ç°¡åã«äœ¿çšã§ããã€ã³ã¯ã«ãŒãããã ãã§ååã§ãã
以äžã®ç»åã¯ãEntity-Component-Systemå®è£ ã®äžè¬çãªã¢ãŒããã¯ãã£ã瀺ããŠããŸãã

å³01ïŒECSã¢ãŒããã¯ãã£å³ïŒ ECS.dll ïŒã
ã芧ã®ãšããããã®å³ã«ã¯4ã€ã®ç°ãªãè²ã®é åããããŸãã åãšãªã¢ã¯ãã¢ãžã¥ãŒã«åãããã¢ãŒããã¯ãã£ãè¡šããŠããŸãã äžçªäž-å®éãäžçªäžã®å³ã§ã¯ãäžäžãéã«ãªã£ãŠããŸã-ã¡ã¢ãªç®¡çãšãžã£ãŒããªã³ã°ããããŸãïŒé»è²ã®é åïŒã ãããã®ç¬¬1ã¬ãã«ã®ã¢ãžã¥ãŒã«ã¯ãéåžžã«äœãã¬ãã«ã®ã¿ã¹ã¯ã§æ©èœããŸãã ãããã¯ãEntity-Component-SystemïŒéè²ã®é åïŒããã³ã€ãã³ããœãŒã¹ïŒèµ€è²ã®é åïŒã§ç¬¬2ã¬ãã«ã®ã¢ãžã¥ãŒã«ã䜿çšããŸãã ãããã®ã¢ãžã¥ãŒã«ã¯ãäž»ã«ãªããžã§ã¯ã管çã¿ã¹ã¯ãåŠçããŸãã ãããã®äžã«ã¯ã第3ã¬ãã«ã®ã¢ãžã¥ãŒã«ECS_EngineïŒç·è²ã®é åïŒããããŸãã æäžäœãšã³ãžã³ã®ãã®ã°ããŒãã«ãªããžã§ã¯ãã¯ã第2ã¬ãã«ã®ãã¹ãŠã®ã¢ãžã¥ãŒã«ãå¶åŸ¡ããåæåãšç Žæ£ã«é¢äžããŸãã ããŠãããã¯ç°¡æœã§éåžžã«æœè±¡çãªã¬ãã¥ãŒã§ããããä»åºŠã¯ã¢ãŒããã¯ãã£ãããã«è©³ããèŠãŠã¿ãŸãããã
ã¡ã¢ãªãããŒãžã£ãŒ
ã¡ã¢ãªãããŒãžã£ããå§ããŸãããã ãã®å®è£ ã¯ã gamedev.netã§èŠã€ããèšäº[8]ã«åºã¥ããŠããŸãã ãã®èãæ¹ã¯ãåçã¡ã¢ãªã®å²ãåœãŠãšè§£æŸãæå°éã«æããããšã§ãã ãããã£ãŠã mallocã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãèµ·åããå Žåã«ã®ã¿ã倧ããªã¡ã¢ãªé åãå²ãåœãŠãããŸãã ãã®ã¡ã¢ãªã¯ã1ã€ä»¥äžã®ã¢ãã±ãŒã¿ãŒã«ãã£ãŠå¶åŸ¡ãããŸãã ãã£ã¹ãã³ãµãŒã«ã¯å€ãã®ã¿ã€ã[9] ïŒç·åœ¢ãã¹ã¿ãã¯ãããªãŒãªã¹ãïŒããããããããã«é·æãšçæããããŸãïŒããã§ã¯èæ ®ããŸããïŒã ãã ããå éšã§ç°ãªãåäœããããšããäºå®ã«ããããããããã¹ãŠã«å ±éã®ãªãŒãã³ã€ã³ã¿ãŒãã§ã€ã¹ããããŸãã
class Allocator { public: virtual void* allocate(size_t size) = 0; virtual void free(void* p) = 0; };
äžèšã®ã³ãŒãã¹ããããã¯äžå®å šã§ãããåãã£ã¹ããªãã¥ãŒã¿ãæäŸããå¿ èŠããã2ã€ã®äž»ãªäžè¬çãªæ¹æ³ã瀺ããŠããŸãã
- allocate-ç¹å®ã®ãã€ãæ°ãå²ãåœãŠããã®é åã®ã¡ã¢ãªã¢ãã¬ã¹ãè¿ããŸã
- free-æå®ãããã¢ãã¬ã¹ã§ä»¥åã«å²ãåœãŠãããã¡ã¢ãªé åã解æŸããŸãã
ããã¯èšã£ãŠããããšãã°æ¬¡ã®ããã«ãããã€ãã®ãã£ã¹ããªãã¥ãŒã¿ãŒããã§ãŒã³ã«ãŸãšãããªã©ãèå³æ·±ãããšãè¡ãããšãã§ããŸãã

å³02ïŒã¢ãã±ãŒã¿ãŒã«ãã£ãŠå¶åŸ¡ãããã¡ã¢ãªã
ã芧ã®ãšããã1ã€ã®ã¢ãã±ãŒã¿ãŒã¯ãã®ã¡ã¢ãªãŒé åãå¶åŸ¡ã§ããå¥ã®ïŒèŠªïŒã¢ãã±ãŒã¿ãŒããå¶åŸ¡ããŸãã次ã«ãå¥ã®ïŒèŠªïŒã¢ãã±ãŒã¿ãŒã¯å¥ã®ã¢ãã±ãŒã¿ãŒããã¡ã¢ãªãååŸã§ããŸãã ãã®ããã«ããŠãããŸããŸãªã¡ã¢ãªç®¡çæŠç¥ãæ§ç¯ã§ããŸãã
ECSãå®è£ ããããã«ã1 GBã®ã·ã¹ãã ã¡ã¢ãªã®åæå²ãåœãŠé åãååŸããã«ãŒãã¹ã¿ãã¯ãã£ã¹ãã³ãµãŒãäœæããŸããã 第2ã¬ãã«ã®ã¢ãžã¥ãŒã«ã¯ãã«ãŒãã¢ãã±ãŒã¿ãŒããå¿ èŠãªéã®ã¡ã¢ãªãå²ãåœãŠãã¢ããªã±ãŒã·ã§ã³ã®å®äºåŸã«ã®ã¿è§£æŸããŸãã

å³03ïŒå¯èœãªã°ããŒãã«ã¡ã¢ãªå²ãåœãŠã
å³03ã¯ã第2ã¬ãã«ã®ã¢ãžã¥ãŒã«éã§ã¡ã¢ãªãå²ãåœãŠãæ¹æ³ã瀺ããŠããŸãã ãGlobal-Memory-User Aãã¯ãšã³ãã£ãã£ãããŒãžã£ã ãGlobal-Memory-User Bãã¯ã³ã³ããŒãã³ããããŒãžã£ã ãGlobal-Memory-User Cãã¯ãããŒãžã£ã§ããã·ã¹ãã ã
ãã®ã³ã°
log4cplus [7]ã䜿çšããã ããªã®ã§ããã°ã«ã€ããŠã¯ããŸã話ããŸãããããã¯ãã¹ãŠã®äœæ¥ãè¡ããŸãã Log4cplus :: Loggerãªããžã§ã¯ããšããLogInfoïŒïŒãããLogWarningïŒïŒããªã©ã®åçŽãªãã®ã³ã°åŒã³åºããæž¡ãã©ãããŒã¡ãœãããå®çŸ©ããåºæ¬ã¯ã©ã¹Loggerãèšå®ããã ãã§ããã
ãšã³ãã£ãã£ãããŒãžã£ãŒãIEntityããšã³ãã£ãã£<T>
ããã§ã¯ãã¢ãŒããã¯ãã£ã®ãèãã«ã€ããŠã話ããŸããããå³01ã®éè²ã®é åã§ãããã¹ãŠã®ãã£ã¹ããããªããžã§ã¯ããšãããã«å¯Ÿå¿ããã¯ã©ã¹ã®æ§é ã䌌ãŠããããšã«æ°ä»ãã§ãããã ããšãã°ã EntityManager ã IEntityãããã³Entity <T>ã¯ã©ã¹ãèŠãŠãã ããã EntityMangerã¯ã©ã¹ã¯ãå®è¡æã«ãã¹ãŠã®ãšã³ãã£ãã£ãªããžã§ã¯ãã管çããå¿ èŠããããŸãã 圌ã®ã¿ã¹ã¯ã«ã¯ãæ¢åã®ãšã³ãã£ãã£ãªããžã§ã¯ãã®äœæãåé€ãã¢ã¯ã»ã¹ãå«ãŸããŸãã IEntityã¯ããªããžã§ã¯ãèå¥åãïŒéçïŒåã®èå¥åãªã©ããšã³ãã£ãã£ãªããžã§ã¯ãã®æãåçŽãªç¹æ§ãæäŸããã€ã³ã¿ãŒãã§ã€ã¹ã¯ã©ã¹ã§ãã ããã°ã©ã ã®åæååŸã«å€æŽãããªããããéçã§ãã ãã®ã¯ã©ã¹èå¥åã¯ãã¢ããªã±ãŒã·ã§ã³ãèµ·åãããã³ã«äžå®ã§ããããœãŒã¹ã³ãŒããå€æŽãããå Žåã«ã®ã¿å€æŽã§ããŸãã
class IEntity { // ! EntityId m_Id; public: IEntity(); virtual ~IEntity(); virtual const EntityTypeId GetStaticEntityTypeID() const = 0; inline const EntityId GetEntityID() const { return this->m_Id; } };
ã¿ã€ãèå¥åã¯ãç¹å®ã®ãšã³ãã£ãã£ã¯ã©ã¹ããšã«ç°ãªãæŽæ°å€ã§ãã ããã«ãããå®è¡æã«IEntityãªããžã§ã¯ãã®ã¿ã€ãã確èªã§ããŸãã ãªã¹ãã®æåŸã«ãããŸãããéèŠã§ã¯ãããŸãããã ãšã³ãã£ã㣠<T>ãã³ãã¬ãŒãã¯ã©ã¹ã§ãã
template<class T> class Entity : public IEntity { // ! void operator delete(void*) = delete; void operator delete[](void*) = delete; public: static const EntityTypeId STATIC_ENTITY_TYPE_ID; Entity() {} virtual ~Entity() {} virtual const EntityTypeId GetStaticEntityTypeID() const override { return STATIC_ENTITY_TYPE_ID; } }; // template const EntityTypeId Entity::STATIC_ENTITY_TYPE_ID = util::Internal::FamilyTypeID::Get();
ãã®ã¯ã©ã¹ã®äž»ãªç®çã¯ãç¹å®ã®ãšã³ãã£ãã£ã¯ã©ã¹ã®ã¿ã€ãã®äžæã®èå¥åãåæåããããšã§ãã ããã§ã¯ã2ã€ã®äºå®ãå©çšããŸããããŸããéçå€æ°ã®å®æ°[10]ã®åæåã 第äºã«ããã³ãã¬ãŒãã¯ã©ã¹ã®åäœã®æ§è³ªã«ããã Entity <T>ãã³ãã¬ãŒãã¯ã©ã¹ã®åããŒãžã§ã³ã«ã¯ãç¬èªã®éçå€æ°STATIC_ENTITY_TYPE_IDããããŸãã ããã¯ããã¹ãŠã®åçåæåãå®äºããåã«åæåãããããšãä¿èšŒãããŠããŸãã ãã©ã°ã¡ã³ãã util :: Internal :: FamilyTypeID :: GetïŒïŒ ãã¯ãã¿ã€ãã«ãŠã³ã¿ãŒã¡ã«ããºã ã®ãããªãã®ãå®è£ ããããã«äœ¿çšãããŸãã å¥ã®Tã§åŒã³åºããããã³ã«ã«ãŠã³ã¿ãŒãã€ã³ã¯ãªã¡ã³ãããŸããã1ã€ã®Tã§å床åŒã³åºããããšåžžã«åãå€ãè¿ããŸãã ãã®ãã³ãã¬ãŒãã«ç¬èªã®ååããããã©ããã¯ããããŸããããéåžžã«äŸ¿å©ã§ãã ãã®æç¹ã§ãdeleteããã³delete []æŒç®åãåé€ããŸããã ãããã£ãŠã誀ã£ãŠããããåŒã³åºãããšãã§ããªããªããŸããã ããã«ãããã®ãããã§ïŒã³ã³ãã€ã©ãååã«è³¢ãå ŽåïŒããšã³ãã£ãã£ãªããžã§ã¯ãã«newãŸãã¯new []æŒç®åã䜿çšããããšãããšãå察ã®æŒç®åã¯ããååšããªããããèŠåãçºè¡ãããŸãã EntityManagerã¯ã©ã¹ããã¹ãŠã®ã¿ã¹ã¯ãåŠçããããããããã®æŒç®åã¯äœ¿çšããªãã§ãã ããã ããã§ãç§ãã¡ããã§ã«åŠãã ããšãèŠçŽããŸãã ãã£ã¹ãããã£ã¯ã©ã¹ã¯ããªããžã§ã¯ãã®äœæãåé€ãã¢ã¯ã»ã¹ãªã©ã®æãåçŽãªæ©èœãæäŸããŸãã ã€ã³ã¿ãŒãã§ã€ã¹ã¯ã©ã¹ã¯ãæãã«ãŒãã®åºæ¬ã¯ã©ã¹ãšããŠäœ¿çšãããäžæã®ãªããžã§ã¯ãèå¥åãšã¿ã€ãèå¥åãæäŸããŸãã ãã³ãã¬ãŒãã¯ã©ã¹ã¯ãã¿ã€ãèå¥åã®æ£ããåæåãä¿èšŒããåé€/åé€[]æŒç®åãæé€ããŸãã ãã£ã¹ãããã£ã¯ã©ã¹ã®åããã³ãã¬ãŒããã€ã³ã¿ãŒãã§ã€ã¹ãããã³ãã³ãã¬ãŒãããã³ã³ããŒãã³ããã·ã¹ãã ãããã³ã€ãã³ãã«äœ¿çšãããŸãã ãããã®ã°ã«ãŒãã®å¯äžã®éèŠãªéãã¯ããã£ã¹ãããã£ã¯ã©ã¹ããªããžã§ã¯ããä¿åããŠã¢ã¯ã»ã¹ããæ¹æ³ã§ãã
æåã«EntityManagerã¯ã©ã¹ãèŠãŠã¿ãŸãããã å³04ã¯ãã¢ã€ãã ãä¿åããããã®äžè¬çãªæ§é ã瀺ããŠããŸãã

å³04ïŒEntityManagerã¯ã©ã¹ãšãã®ãªããžã§ã¯ãã®ã¹ãã¬ãŒãžã®æœè±¡å³ã
æ°ãããšã³ãã£ãã£ãªããžã§ã¯ããäœæãããšãã¯ã EntityManager :: CreateEntity < T >ã¡ãœããïŒåŒæ°...ïŒã䜿çšããå¿ èŠããããŸãã ãã®äžè¬çãªã¡ãœããã¯æåã«ãäœæãããç¹å®ã®ãšã³ãã£ãã£ã®ã¿ã€ãã§ãããã³ãã¬ãŒããã©ã¡ãŒã¿ãŒãåãåããŸãã 次ã«ããã®ã¡ãœããã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒTã«æž¡ããããªãã·ã§ã³ã®ãã©ã¡ãŒã¿ãŒïŒãã©ã¡ãŒã¿ãŒããªãå ŽåããããŸãïŒãåãåããŸãã ãããã®ãã©ã¡ãŒã¿ãŒã®è»¢éã¯ãå¯å€æ°ã®åŒæ°ãæã€ãã³ãã¬ãŒããä»ããŠå®è¡ãããŸã[11] ã äœæäžã«ã次ã®ã¢ã¯ã·ã§ã³ãå éšã§çºçããŸãã
- ã¿ã€ãTã®ãšã³ãã£ãã£ãªããžã§ã¯ãã®ObjectPool [12]ãå€æããŸãã ãã®ããŒã«ãååšããªãå Žåãæ°ããããŒã«ãäœæãããŸã
- ã¡ã¢ãªã¯ãã®ããŒã«ããå²ãåœãŠãããŸãã ãªããžã§ã¯ãTãä¿åããã®ã«å¿ èŠãªã ãæ£ç¢ºã«
- ãã£ã¹ãããã£ãŒããTã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãåã«ãæ°ããEntityIdãååŸãããŸãã 以åã«ã¡ã¢ãªãå²ãåœãŠããããã®èå¥åã¯ãã«ãã¯ã¢ããããŒãã«ã«ä¿åãããŸãã ãã®ããã«ããŠãç®çã®èå¥åãæã€ãšã³ãã£ãã£ã€ã³ã¹ã¿ã³ã¹ãæ€çŽ¢ã§ããŸã
- 次ã«ãå ¥åãšããŠæž¡ãããåŒæ°ã䜿çšããŠC ++ newæŒç®å[13]ãåŒã³åºããã Tã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæãããŸã
- æåŸã«ãã¡ãœããã¯ãšã³ãã£ãã£ã®èå¥åãè¿ããŸãã
ãšã³ãã£ãã£ãªããžã§ã¯ãã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæããããäžæã®ãªããžã§ã¯ãèå¥åïŒ EntityId ïŒããã³EntityManager :: GetEntityïŒEntityId idïŒã䜿çšããŠã¢ã¯ã»ã¹ã§ããŸãã ãšã³ãã£ãã£ãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ãç Žæ£ããã«ã¯ã EntityManager :: DestroyEntityïŒEntityId idïŒã¡ãœãããåŒã³åºããŸãã
ComponentManagerã¯ã©ã¹ã¯åãããã«æ©èœããããã«å¥ã®æ¡åŒµæ©èœããããŸãã ããããçš®é¡ã®ãªããžã§ã¯ããæ ŒçŽããããã®ãªããžã§ã¯ãã®ããŒã«ã«å ããŠãã³ã³ããŒãã³ããææãããšã³ãã£ãã£ãªããžã§ã¯ãã«ã³ã³ããŒãã³ãããã€ã³ãããããã®è¿œå ã®ã¡ã«ããºã ãæäŸããå¿ èŠããããŸãã ãã®å¶éã¯ãæ€çŽ¢ã®ç¬¬2段éã«ã€ãªãããŸããæåã«ãæå®ãããEntityIdãæã€ãšã³ãã£ãã£ãååšãããã©ããã確èªããååšããå Žåã¯ãã³ã³ããŒãã³ãã®ãªã¹ããæ€çŽ¢ããŠç¹å®ã®ã¿ã€ãã®ã³ã³ããŒãã³ãããã®ãšã³ãã£ãã£ã«ã¢ã¿ãããããŠãããã©ããã確èªããŸã

å³05ïŒComponent-Managerãªããžã§ã¯ãã®ã¹ãã¬ãŒãžå³ã
ComponentManager :: CreateComponent <T>ã¡ãœããïŒEntityId idãåŒæ°...ïŒã䜿çšãããšãç¹å®ã®ã³ã³ããŒãã³ãããšã³ãã£ãã£ã«è¿œå ã§ããŸãã ComponentManager :: GetComponent <T>ïŒEntityId idïŒã䜿çšããŠããšã³ãã£ãã£ã®ã³ã³ããŒãã³ãã«ã¢ã¯ã»ã¹ã§ããŸããTã¯ãã¢ã¯ã»ã¹ããã³ã³ããŒãã³ãã®ã¿ã€ãã決å®ããŸãã ã³ã³ããŒãã³ããæ¬ èœããŠããå Žåã nullptrãè¿ãããŸãã ãšã³ãã£ãã£ããã³ã³ããŒãã³ããåé€ããã«ã¯ã ComponentManager :: RemoveComponent <T>ïŒEntityId idïŒã¡ãœããã䜿çšããå¿ èŠããããŸãã ããããåŸ ã£ãŠãä»ã«äœãããããŸãã ã³ã³ããŒãã³ãã«ã¢ã¯ã»ã¹ããå¥ã®æ¹æ³ã¯ã ComponentIterator <T>ã䜿çšããããšã§ãã ãããã£ãŠãç¹å®ã®ã¿ã€ãTã®ãã¹ãŠã®æ¢åã®ã³ã³ããŒãã³ãã«å¯ŸããŠå埩ã§ããŸããããã¯ãããšãã°ãç©çã·ã¹ãã ãªã©ã®ã·ã¹ãã ããã¹ãŠã®åºäœã®ã³ã³ããŒãã³ãã«éåãé©çšããå¿ èŠãããå Žåã«äŸ¿å©ã§ãã
SystemManagerã¯ã©ã¹ã«ã¯ãã·ã¹ãã ãä¿åããŠã¢ã¯ã»ã¹ããããã®ç¹å¥ãªè¿œå æ©èœã¯ãããŸããã ã·ã¹ãã ãä¿åããã«ã¯ãã¿ã€ãèå¥åãããŒãšããŠåçŽãªã¡ã¢ãªå²ãåœãŠã䜿çšãããŸãã
EventManagerã¯ã©ã¹ã¯ãã¡ã¢ãªé åã管çããç·åœ¢ã¢ãã±ãŒã¿ãŒã䜿çšããŸãã ãã®ã¡ã¢ãªã¯ã€ãã³ããããã¡ãšããŠäœ¿çšãããŸãã ã€ãã³ãã¯ãã®ãããã¡ã«ä¿åãããåŸã§éä¿¡ãããŸãã ã€ãã³ããéä¿¡ãããšããããã¡ãã¯ãªã¢ãããæ°ããã€ãã³ããããã«ä¿åã§ããŸãã ããã¯å°ãªããšããã¬ãŒã ããšã«1åçºçããŸãã

å³06ïŒæ¹èšãããECSã¢ãŒããã¯ãã£å³
ããŸãããã°ãç§ã®ECSãã¬ãŒã ã¯ãŒã¯ãã©ã®ããã«æ©èœãããã«ã€ããŠã®ã¢ã€ãã¢ãåŸãããŸããã ããã§ãªãå Žåã¯ãå¿é ããªãã§ãå³06ãèŠãŠãç°¡åã«ç¹°ãè¿ããŸãã ã芧ã®ãšããã EntityIdã¯éåžžã«éèŠã§ããEntityIdã䜿çšããŠããšã³ãã£ãã£ãªããžã§ã¯ããšãã®ãã¹ãŠã®ã³ã³ããŒãã³ãã®ç¹å®ã®ã€ã³ã¹ã¿ã³ã¹ã«ã¢ã¯ã»ã¹ããããã§ãã ãã¹ãŠã®ã³ã³ããŒãã³ãã¯ææè ãç¥ã£ãŠããŸããã€ãŸããã³ã³ããŒãã³ããªããžã§ã¯ããæã£ãŠããã®ã§ããã®ã³ã³ããŒãã³ãã®æå®ãããææè èå¥åã§EntityManagerã¯ã©ã¹ãç §äŒããããšã§ããšã³ãã£ãã£ãç°¡åã«ååŸã§ããŸãã ãšã³ãã£ãã£ãæž¡ãããã«ããã€ã³ã¿ãçŽæ¥æž¡ãããšã¯ãããŸãããã EntityIdãšçµã¿åãããŠã€ãã³ãã䜿çšããŸãã EntityDiedãªã©ã®ç¹å®ã®ã€ãã³ããäœæã§ããŸãããã®ã€ãã³ãïŒåçŽãªããŒã¿æ§é ãæã€ãªããžã§ã¯ãã§ããå¿ èŠããããŸãïŒã«ã¯ãã¿ã€ãEntityIdã®èŠçŽ ããããŸãã ãšã³ãã£ãã£ãã³ã³ããŒãã³ãããŸãã¯ã·ã¹ãã ã§ããå¯èœæ§ããããã¹ãŠã®ã€ãã³ãã¬ã·ãŒããŒïŒ IEventListener ïŒã«éç¥ããããã«ã EventManager :: SendEvent <EntityDied>ïŒentityIdïŒã䜿çšããŸãã äžæ¹ãã€ãã³ãã¬ã·ãŒããŒã¯ãæž¡ãããEntityIdã䜿çšããŠãEntityManagerã¯ã©ã¹ã§ãšã³ãã£ãã£ãªããžã§ã¯ããååŸããããComponentManagerã¯ã©ã¹ã§ãã®ãšã³ãã£ãã£ã®ç¹å®ã®ã³ã³ããŒãã³ããååŸãããã§ããŸãã ãã®åŸªç°ãã¹ã®çç±ã¯ç°¡åã§ããã¢ããªã±ãŒã·ã§ã³ã®å®è¡äžã¯ãã€ã§ããäœããã®ããžãã¯ã䜿çšããŠãšã³ãã£ãã£ãŸãã¯ãã®ã³ã³ããŒãã³ãã®1ã€ãåé€ã§ããŸãã è¿œå ã®ã¯ãªãŒãã³ã°æé ã§ã³ãŒããä¹±éã«ããªãããã EntityIdã䜿çšããŸã ã ãã£ã¹ãããã£ããã®EntityIdã«å¯ŸããŠnullptrãè¿ãå Žåããšã³ãã£ãã£ãŸãã¯ã³ã³ããŒãã³ããããååšããªãããšãããããŸãã ã¡ãªã¿ã«ãèµ€ãåè§ã¯å³01ã®åãéšåã«å¯Ÿå¿ããŠãããECSã®å¢çã瀺ããŠããŸãã
ãšã³ãžã³ãªããžã§ã¯ã
ç©äºãããå°ã䟿å©ã«ããããã«ããšã³ãžã³ãªããžã§ã¯ããäœæããŸããã ãšã³ãžã³ãªããžã§ã¯ãã¯ãã¯ã©ã€ã¢ã³ããœãããŠã§ã¢ã®ç°¡åãªçµ±åãšäœ¿çšãæäŸããŸãã ã¯ã©ã€ã¢ã³ãåŽã§ã¯ãããããŒãã¡ã€ã«ãECS / ECS.hããè¿œå ããŠã ECS :: InitializeïŒïŒã¡ãœãããåŒã³åºããŸãã ããã§ããšã³ãžã³ã®éçã°ããŒãã«ãªããžã§ã¯ããåæåããïŒ ECS :: ECS_Engine ïŒãã¯ã©ã€ã¢ã³ãåŽã§äœ¿çšããŠãã£ã¹ãããã£ãŒã¯ã©ã¹ã«ã¢ã¯ã»ã¹ã§ããŸãã ããã«ãã¡ãã»ãŒãžãéä¿¡ããããã®SendEvent <T>ã¡ãœãããšããã¹ãŠã®ã€ãã³ããèªåçã«éä¿¡ãããã¹ãŠã®ã·ã¹ãã ãæŽæ°ããUpdateã¡ãœãããæäŸããŸãã ECS :: TerminateïŒïŒã¯ãã¡ã€ã³ããã°ã©ã ãçµäºããåã«åŒã³åºãå¿ èŠããããŸãã ããã«ãããåä¿¡ãããã¹ãŠã®ãªãœãŒã¹ã解æŸãããŸãã 以äžã®ã³ãŒãã¹ããããã¯ãã°ããŒãã«ãšã³ãžã³ãªããžã§ã¯ãã®æãç°¡åãªäœ¿çšæ¹æ³ã瀺ããŠããŸãã
#include <ECS/ECS.h> int main(int argc,char* argv[]) { // 'ECS_Engine' ECS::Initialize(); const float DELTA_TIME_STEP = 1.0f / 60.0f; // 60 bool bQuit = false; // while(bQuit == false) { // , , // ... ECS::ECS_Engine->(DELTA_TIME_STEP); /* ECS::ECS_Engine->GetEntityManager()->...; ECS::ECS_Engine->GetComponentManager()->...; ECS::ECS_Engine->GetSystemManager()->...; ECS::ECS_Engine->SendEvent<T>(...); */ // ... } // 'ECS_Engine' ECS::Terminate(); return 0; }
ãããã«
ãã®èšäºã®ãã®éšåã§èª¬æããããšã³ãã£ãã£ã³ã³ããŒãã³ãã·ã¹ãã ãã¢ãŒããã¯ãã£ã¯å®å šã«æ©èœããããã«äœ¿çšã§ããŸãã ãããããã€ãã®ããã«ãåžžã«æ¹åã®ããã®èãããããŸãã ããã«ç§ã®é ã«æµ®ããã ã¢ã€ãã¢ã®ã»ãã®äžéšã§ãïŒ
- ã¢ãŒããã¯ãã£ãã¹ã¬ããã»ãŒãã«ãã
- ããããžãŒã®é åºãèæ ®ããŠãåã·ã¹ãã ãŸãã¯ã·ã¹ãã ã®ã°ã«ãŒããã¹ã¬ããã§å®è¡ããŸãã
- ã€ãã³ããœãŒã·ã³ã°ãšã¡ã¢ãªç®¡çããªãã¡ã¯ã¿ãªã³ã°ããŠãã¢ãžã¥ãŒã«ãšããŠäœ¿çšããŸãã
- é£èŒ
- ãããã¡ã€ãªã³ã°
- ...
ECSã®åäœã確èªã§ããããã«ããã¢ãæºåããŸããã
BountyHunterãã¢ã¯ECSãåºç¯å²ã«äœ¿çšãããã®ãã³ãã¬ãŒãã®åšåãå®èšŒããŸãã æçš¿ã®åŸåã§ã¯ã圌ã«ã€ããŠã話ããŸãã
åç §è³æ
[1] https://en.wikipedia.org/wiki/Entity-component-system
[2] http://gameprogrammingpatterns.com/component.html
[3] https://www.gamedev.net/articles/programming/general-and-gameplay-programming/understanding-component-entity-systems-r3013/
[4] https://github.com/junkdog/artemis-odb/wiki/Introduction-to-Entity-Systems
[5] http://scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.pdf
[6] https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing
[7] https://sourceforge.net/p/log4cplus/wiki/Home/
[8] https://www.gamedev.net/articles/programming/general-and-gameplay-programming/c-custom-memory-allocation-r3010/
[9] https://github.com/mtrebi/memory-allocatorshttps://www.gamedev.net/articles/programming/general-and-gameplay-programming/c-custom-memory-allocation-r3010/
[10] http://en.cppreference.com/w/cpp/language/constant_initialization
[11] https://en.wikipedia.org/wiki/Variadic_template
[12] http://gameprogrammingpatterns.com/object-pool.html
[13] http://en.cppreference.com/w/cpp/language/new
ããŒã2ïŒBountyHunterã²ãŒã
次ã«ãå®éã«ã¢ãŒããã¯ãã£ã䜿çšããŠã²ãŒã ãäœæããæ¹æ³ã瀺ããŸãã ç§ã®ã²ãŒã ã¯ããã»ã©è€éã«èŠããŸãããã UnityãUnrealãªã©ã®å€§ãããŠè€éãªã²ãŒã ãšã³ãžã³ã®ä»£ããã«ãç§ã®å®è£ ã䜿çšããŠç¬èªã®ã²ãŒã ãäœæããããšã«ããå Žåã¯ãç§ã®äœè ã«èšåã§ããŸãã ECSã®æ©èœãå®èšŒããã«ã¯ããã®ãããªã²ãŒã ã§ååã§ããã ãã®èŠåãç解ããŠããªãå Žåã¯ã次ã®å³ã圹ç«ã¡ãŸãã

å³01ïŒã²ãŒã BountyHunterã®ç®çãšã«ãŒã«ã ç®æšïŒåãã¬ã€ã€ãŒã¯ãã§ããã ãæ©ãèªåã®ç©è³ãè£å ããããšããŸãã ã«ãŒã«ïŒ1.ã²ãŒã ã«ã¯æéå¶éããããŸãã æéãçµéãããšãã²ãŒã ã¯çµäºããŸãã 2.ç²ç©ã«é¢ããŠãã³ã¬ã¯ã¿ãŒã¯ãããæŸããŸãã 3.ããã«ãŒã¯éãããéã®ç¥å¥ªåãéã¶ããšãã§ããŸãã å¶éã«éãããšãã³ã¬ã¯ã¿ãŒã¯ç²ç©ãåéã§ããªããªããç²ç©ã«è§Šãããšç Žå£ãããŸãã 4.ã³ã¬ã¯ã¿ãŒã圌ãŸãã¯æµã®è£çµŠåã«è§Šãããšãåéããããã¹ãŠã®ç²ç©ãè£çµŠåã«ææ£ãããã³ã¬ã¯ã¿ãŒã¯åã³ç²ç©ãåéã§ããŸãã 5.ã³ã¬ã¯ã¿ãŒã®è¡çªã§ã圌ãã¯ç Žå£ããããã°ããããŠã圌ãã¯äŸçµŠã®æç¹ã§çãŸãå€ãããŸãã åéãããçç£ã¯å€±ãããŸãã 6.ç²ç©ã¯äžçã®äžå€®éšã®ã©ã³ãã ãªå°ç¹ã«çŸãããã®ç涯ã®éããŸãã¯åéããããŸã§ååšããŸãã 7.ã³ã¬ã¯ã¿ãŒãäžçã®å¢çç·ãè¶ãããšãç»é¢ã®å察åŽãã衚瀺ãããŸãã
å·Šã®ç»åã¯ããããªã§èŠãã²ãŒã ã®ããæœè±¡çãªæŠèŠã§ãããããèŠæ £ãããã®ã«èŠããŸãã ã«ãŒã«ã¯ååã«æ確ã§ãããããèªäœãèªã£ãŠããŸãã ã芧ã®ãšãããã²ãŒã ã®äžçã«ã¯ããŸããŸãªçš®é¡ã®ãšã³ãã£ãã£ãååšããŸãã ããªãã¯ãããã圌ããå®éã«äœã§æ§æãããŠããã®ãçåã«æã£ãŠããŸããïŒ ãã¡ãããã³ã³ããŒãã³ãã®ã äžéšã®ã¿ã€ãã®ã³ã³ããŒãã³ãã¯ãã¹ãŠã®ãšã³ãã£ãã£ã«å ±éã§ãããä»ã®ã¿ã€ãã¯ä»ã®ãšã³ãã£ãã£ã«åºæã§ãã äžã®åçãèŠãŠãã ããã

å³02ïŒãšã³ãã£ãã£ãšãã®ã³ã³ããŒãã³ãã
ãã®å³ãèŠããšããšã³ãã£ãã£ãšãã®ã³ã³ããŒãã³ãã®é¢ä¿ãç°¡åã«ããããŸãïŒå³ã«ãã¹ãŠã衚瀺ãããŠããããã§ã¯ãããŸããïŒïŒã ãã¹ãŠã®ã²ãŒã ãšã³ãã£ãã£ã«ã¯Transform-ComponentããããŸã ã ã²ãŒã ãšã³ãã£ãã£ã¯äžçã®ã©ããã«é 眮ããå¿ èŠãããããããšã³ãã£ãã£ã®äœçœ®ãå転ãããã³ã¹ã±ãŒã«ãèšè¿°ããå€æããããŸãã ããã¯ããšã³ãã£ãã£ã«æ¥ç¶ãããŠããå¯äžã®ã³ã³ããŒãã³ãã§ããå ŽåããããŸãã ããšãã°ãã«ã¡ã©ãªããžã§ã¯ãã¯ããå€ãã®ã³ã³ããŒãã³ããå¿ èŠãšããŸããã Material-Componentã¯å¿ èŠãããŸãããããã¯ããã¬ãŒã€ãŒã«ã¯è¡šç€ºãããªãããã§ãïŒãã¹ããšãã§ã¯ãã䜿çšããå Žåã¯åœãŠã¯ãŸããªãå¯èœæ§ããããŸãïŒã äžæ¹ããšã³ãã£ãã£ãªããžã§ã¯ãBounty ïŒãããã¯ã·ã§ã³ïŒããã³Collector ïŒã³ã¬ã¯ã¿ãŒïŒã¯è¡šç€ºãããå¿ èŠãããããã衚瀺ããã«ã¯Material-Componentãå¿ èŠã§ãã ãŸããã²ãŒã ã®ä»ã®ãªããžã§ã¯ããšè¡çªããå¯èœæ§ããããããç©ççãªåœ¢ç¶ãèšè¿°ããè¡çªã³ã³ããŒãã³ãããããã«ã¢ã¿ãããããŸãã å¥ã®ã³ã³ããŒãã³ããBountyãšã³ãã£ãã£ã«æ¥ç¶ãããŸã-Lifetime-Component ã ãã®ã³ã³ããŒãã³ãã¯ã ããŠã³ãã£ãªããžã§ã¯ãã®æ®ãã®å¯¿åœã決å®ãããã®å¯¿åœãçµäºãããšãçç£ãç Žå£ãããŸãã
ããã§ã¯ã次ã¯äœã§ããïŒ ç¬èªã®ã³ã³ããŒãã³ãã»ããã䜿çšããŠãããã®ããŸããŸãªãšã³ãã£ãã£ããã¹ãŠäœæããã®ã§ãã²ãŒã èªäœã¯å®äºããŸããã§ããã ãŸããããããã®ç®¡çæ¹æ³ãç¥ã£ãŠãã人ãå¿ èŠã§ãã ãã¡ãããç§ã¯ã·ã¹ãã ã«ã€ããŠè©±ããŠããã ã·ã¹ãã ã¯çŽ æŽããããã®ã§ãã²ãŒã ããžãã¯å šäœãå°ããªèŠçŽ ã«åé¢ããããã«äœ¿çšã§ããŸãã åèŠçŽ ã¯ãã²ãŒã ã®ç¬èªã®åŽé¢ã§æ©èœããŸãã ãã¬ã€ã€ãŒã«ãã£ãŠå ¥åããããã¹ãŠã®ããŒã¿ãåŠçããå ¥åã·ã¹ãã ãæã£ãŠããå Žåãããã°ãæã£ãŠããå ŽåããããŸãã Render-System ããã¹ãŠã®åœ¢ç¶ãšè²ãç»é¢ã«è»¢éããŸãã ã²ãŒã ã®æ»ãã ãªããžã§ã¯ãã®åŸ©æŽ»ã®ããã®åŸ©æŽ»ã·ã¹ãã ã ããŠãããªãã¯ã¢ã€ãã¢ãåŸããšæããŸãã 以äžã®å³ã¯ã BountyHunterã®ãã¹ãŠã®ç¹å®ã®ãšã³ãã£ãã£ã¿ã€ããã³ã³ããŒãã³ããããã³ã·ã¹ãã ã®å®å šãªã¯ã©ã¹å³ã瀺ããŠããŸãã
å³03ïŒECS BountyHunterã¯ã©ã¹å³ïŒç»åãã¯ãªãã¯ããŠæ¡å€§ïŒã
ãšã³ãã£ãã£ãã³ã³ããŒãã³ããããã³ã·ã¹ãã ïŒECSïŒããããŸãããã€ãã³ãããããŸããïŒ ã·ã¹ãã ãšãšã³ãã£ãã£ãããŒã¿ã亀æã§ããããã«ã38åã®ã€ãã³ãã®ã³ã¬ã¯ã·ã§ã³ãäœæããŸããã
GameInitializedEvent GameRestartedEvent GameStartedEvent GamePausedEvent GameResumedEvent GameoverEvent GameQuitEvent PauseGameEvent ResumeGameEvent RestartGameEvent QuitGameEvent LeftButtonDownEvent LeftButtonUpEvent LeftButtonPressedEvent RightButtonDownEvent RightButtonUpEvent RightButtonPressedEvent KeyDownEvent KeyUpEvent KeyPressedEvent ToggleFullscreenEvent EnterFullscreenModeEvent StashFull EnterWindowModeEvent GameObjectCreated GameObjectDestroyed PlayerLeft GameObjectSpawned GameObjectKilled CameraCreatedãCameraDestroyed ToggleDebugDrawEvent WindowMinimizedEvent WindowRestoredEvent WindowResizedEvent PlayerJoined CollisionBeginEvent CollisionEndEvent
ãããŠããŸã BountyHunterãå®è£ ããããã«å¿ èŠãªããšããããããããŸãã
- äžè¬çãªã¢ããªã±ãŒã·ã§ã³ãã¬ãŒã ã¯ãŒã¯ -ãã¬ãŒã€ãŒã®å ¥åãåãåããã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠãèšå®ããããã®SDL2 ã
- ã°ã©ãã£ãã¯ã¹ -ãã®ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠã«ã¬ã³ããªã³ã°ã§ããããã«ãç¬èªã®OpenGLã¬ã³ãã©ãŒã䜿çšããŸããã
- math-ç·åœ¢ä»£æ°ã«ã¯glmã䜿çšããŸããã
- è¡çªèªè -圌女ã®ããã«ç§ã¯box2dç©çåŠã䜿çšããŸãã ã
- ã¹ããŒããã·ã³ -åçŽãªAIããã³ã²ãŒã ã®ç¶æ ã«äœ¿çšãããŸãã
ãã¡ãããããããã¹ãŠã®ã¡ã«ããºã ãæ€èšããã€ããã¯ãããŸããããããã¯ç§èªèº«ã®èšäºã«å€ããã®ã§ãåŸã§æžããããããŸããããããããŸã ãããã«ã€ããŠç¥ãããå Žåã¯ãç§ã¯ããªããç ©ãããããã®ãªã³ã¯ãæäŸããŸããç§ãèšåãããã¹ãŠã®ç¹æ§ãç 究ããã®ã§ãããã¯ããªãèªèº«ã®ã²ãŒã ãšã³ãžã³ã«ãšã£ãŠè¯ãã¹ã¿ãŒãã§ãããšæ±ºããããšãã§ããŸãããããã¿ã€ããå®æããããã£ããããšãã£ãŠãå®éã«ã¯å®è£ ããŠããªãé ç®ããªã¹ãã«ããã€ããããŸãã
- ãšã³ãã£ãã£ãã³ã³ããŒãã³ããã·ã¹ãã ãªã©ã管çããããã®ãšãã£ã¿ãŒ
- ã²ãŒã ã®ä¿å -ãšã³ãã£ãã£ãšãã®ã³ã³ããŒãã³ããORMã©ã€ãã©ãªïŒããšãã°codesynthesisïŒã䜿çšããŠããŒã¿ããŒã¹ã«ä¿åããŸã
- ãªãã¬ã€ã®åç -å®è¡æã«ã€ãã³ããèšé²ããåŸã§åçããŸã
- GUI â GUI- (, librocket )
- â (, , ..)
- â
ããªããã©ãã ãã¯ãŒã«ãã蚌æã§ããããã«ããããã®ãã€ã³ããã¿ã¹ã¯ãšããŠæ®ããŠãããŸãã
ãŸããECSã®äœ¿çšæ¹æ³ã瀺ãã³ãŒãã瀺ãå¿ èŠããããŸããããŠã³ãã£ã®ã²ãŒã ãšã³ãã£ãã£ãèŠããŠããŸããïŒç²ç©ã¯ãäžçã®äžå¿ã«ã©ã³ãã ã«äœæãããå°ããªé»è²ã倧ããªèµ€ãäžéã®æ£æ¹åœ¢ã§ãã以äžã¯ãããŠã³ãã£ãšã³ãã£ãã£ã¯ã©ã¹å®çŸ©ã³ãŒãã®ã¹ããããã§ãã
// Bounty.h class Bounty : public GameObject<Bounty> { private: // TransformComponent* m_ThisTransform; RigidbodyComponent* m_ThisRigidbody; CollisionComponent2D* m_ThisCollision; MaterialComponent* m_ThisMaterial; LifetimeComponent* m_ThisLifetime; // bounty float m_Value; public: Bounty(GameObjectId spawnId); virtual ~Bounty(); virtual void OnEnable() override; virtual void OnDisable() override; inline float GetBounty() const { return this->m_Value; } // OnEnable, void ShuffleBounty(); };
ã³ãŒãã¯éåžžã«ã·ã³ãã«ã§ç°¡åã§ãã IããåŸãããæ°ããªã²ãŒã ãšã³ãã£ãã£äœæã²ãŒã ãªããžã§ã¯ã< T >ïŒç±æ¥ããECSãšã³ãã£ãã£:: < T >ïŒã¯ã©ã¹èªäœïŒã«ããŠã³ãã£ãšããŠïŒTã ECSã¯ãã®ç¹å®ã®ãšã³ãã£ãã£ã¿ã€ããèªèããïŒéçïŒã¿ã€ãã®äžæã®èå¥åãäœæãããŸãããŸãã䟿å©ãªã¡ãœããAddComponent < U >ãGetComponent < U >ãRemoveComponent < U >ãžã®ã¢ã¯ã»ã¹ãååŸããŸããããã«è¡šç€ºããã³ã³ããŒãã³ãã«å ããŠããã1ã€ã®ããããã£ãçç£ã®äŸ¡å€ããããŸããBountyComponentã®ããã«ããã®ããããã£ãåå¥ã®ã³ã³ããŒãã³ãã«åé¢ããªãã£ãçç±ãæ£ç¢ºã§ã¯ãªããããæ£ç¢ºã«ã¯èŠããŠããŸããã代ããã«ãæŠå©åããããã£ãããŠã³ãã£ã¯ã©ã¹ã®ã¡ã³ããŒã«ããé ã«ç°ãæ¯ããããŸãããããããå®éã«ã¯ããã®ãã³ãã¬ãŒãã®éåžžã«é«ãæè»æ§ãã瀺ããŠããŸããããïŒããæ£ç¢ºã«ã¯ããã®ã³ã³ããŒãã³ã...
// Bounty.cpp Bounty::Bounty(GameObjectId spawnId) { Shape shape = ShapeGenerator::CreateShape<QuadShape>(); AddComponent<ShapeComponent>(shape); AddComponent<RespawnComponent>(BOUNTY_RESPAWNTIME, spawnId, true); // this->m_ThisTransform = GetComponent<TransformComponent>(); this->m_ThisMaterial = AddComponent<MaterialComponent>(MaterialGenerator::CreateMaterial<defaultmaterial>()); this->m_ThisRigidbody = AddComponent<RigidbodyComponent>(0.0f, 0.0f, 0.0f, 0.0f, 0.0001f); this->m_ThisCollision = AddComponent<CollisionComponent2d>(shape, this->m_ThisTransform->AsTransform()->GetScale(), CollisionCategory::Bounty_Category, CollisionMask::Bounty_Collision); this->m_ThisLifetime = AddComponent<LifetimeComponent>(BOUNTY_MIN_LIFETIME, BOUNTY_MAX_LIFETIME); } // ...
ã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããŠãBountyãšã³ãã£ãã£ãŒã«å¿ èŠãªãã¹ãŠã®ã³ã³ããŒãã³ããã¢ã¿ããããŸããããã®ã¢ãããŒãã¯ãªããžã§ã¯ãã®èª¿éãäœæããæè»æ§ããªãããšã«æ³šæããŠãã ãããã€ãŸããåžžã«åãã³ã³ããŒãã³ããã¢ã¿ãããããããŠã³ãã£ãªããžã§ã¯ããååŸããŸããããã¯ç§ã®ã²ãŒã ã«ãšã£ãŠååãªè§£æ±ºçã§ãããããè€éãªãã®ã«ãšã£ãŠã¯ééãã§ããããšãå€æããå ŽåããããŸãããã®å Žåãå€æŽå¯èœãªãšã³ãã£ãã£ãªããžã§ã¯ããäœæããããã¡ã¯ããªãŒããã³ãã¬ãŒããå®è£ ããå¿ èŠããããŸãã
äžèšã®ã³ãŒããããããããã«ãããªãã®æ°ã®ã³ã³ããŒãã³ããBountyãšã³ãã£ãã£ã«ã¢ã¿ãããããŠããŸããæã ã¯æã£ãŠããShapeComponentãšMaterialComponentãèŠèŠçã«è¡šç€ºãããããRigidbodyComponentããã³CollisionComponent2Dç©ççæåãšè¡çªã«å¯Ÿããåå¿ãRespawnComponentãããã«ãããBountyãæ»åŸã«çãŸãå€ããæ©äŒãåŸãããšãã§ããŸããæåŸã«ãªããŸããããéèŠãªããšã¯ããšã³ãã£ãã£ã®ååšãç¹å®ã®æéã«çµã³ä»ããLifetimeComponentã§ããTransformComponentã¯ãGameObject < T >ããååŸãããšã³ãã£ãã£ã«èªåçã«ãã€ã³ããããŸãã以äžã§ããã²ãŒã ã«æ°ãããšã³ãã£ãã£ãè¿œå ããŸããã
ããã§ãããããã¹ãŠã®ã³ã³ããŒãã³ãã®äœ¿çšæ¹æ³ãåŠã³ããå ŽåããããŸãã 2ã€ã®äŸã瀺ããŸããæåã¯RigidbodyComponentã§ãããã®ã³ã³ããŒãã³ãã«ã¯ãæ©æŠãå¯åºŠãç·åœ¢æžè¡°ãªã©ã®ç©ççç¹æ§ã«é¢ããæ å ±ãå«ãŸããŠããŸããããã«ãbox2dç©çãã²ãŒã ã«åã蟌ãããã«äœ¿çšãããã¢ããã¿ãŒã¯ã©ã¹ãšããŠäœ¿çšãããŸããRigidbodyComponentã¯ãç©ççã«ã·ãã¥ã¬ãŒããããããã£ïŒbox2dãææïŒã®å€æãšãšã³ãã£ãã£ã®TransformComponentïŒã²ãŒã ãææïŒã®åæã«äœ¿çšããããããéåžžã«éèŠã§ãããã®åæããã»ã¹ã¯PhysicsSystemã«ãã£ãŠå®è¡ãããŸãã
// PhysicsEngine.h class PhysicsSystem : public ECS::System<PhysicsSystem>, public b2ContactListener { public: PhysicsSystem(); virtual ~PhysicsSystem(); virtual void PreUpdate(float dt) override; virtual void Update(float dt) override; virtual void PostUpdate(float dt) override; // box2d virtual void BeginContact(b2Contact* contact) override; virtual void EndContact(b2Contact* contact) override; }; // class PhysicsSystem
// PhysicsEngine.cpp void PhysicsSystem::PreUpdate(float dt) { // TransformComponent for (auto RB = ECS::ECS_Engine->GetComponentManager()->begin<RigidbodyComponent>(); RB != ECS::ECS_Engine->GetComponentManager()->end<RigidbodyComponent>(); ++RB) { if ((RB->m_Box2DBody->IsAwake() == true) && (RB->m_Box2DBody->IsActive() == true)) { TransformComponent* TFC = ECS::ECS_Engine->GetComponentManager()->GetComponent<TransformComponent>(RB->GetOwner()); const b2Vec2& pos = RB->m_Box2DBody->GetPosition(); const float rot = RB->m_Box2DBody->GetAngle(); TFC->SetTransform(glm::translate(glm::mat4(1.0f), Position(pos.x, pos.y, 0.0f)) * glm::yawPitchRoll(0.0f, 0.0f, rot) * glm::scale(TFC->AsTransform()->GetScale())); } } } // ...
äžèšã®å®è£ ããã3ã€ã®ç°ãªãæŽæ°é¢æ°ã«æ°ä»ãããšãã§ããŸããã·ã¹ãã ãæŽæ°ããå Žåããã¹ãŠã®ã·ã¹ãã ã®ãã¹ãŠã®PreUpdateã¡ãœãããæåã«åŒã³åºããã次ã«UpdateãåŒã³åºããããã®åŸPostUpdateã¡ãœãããåŒã³åºãããŸããPhysicsSystemã¯ã·ã¹ãã ã«é¢é£ãããã¹ãŠã®TransformComponentã®åã«åŒã³åºããããããäžèšã®ã³ãŒãã¯å€æã®åæãæäŸããŸããããã§ãComponentIteratorã®åäœã確èªã§ããŸãããããããããããã©ãããäžçã«åãšã³ãã£ãã£ãèŠæ±ããããããRigidbodyComponentãæã ãæ±ããComponentManagerãç§éæäŸComponentIteratorã®ã¿ã€ãRigidbodyComponentããRigidbodyComponentãåãåã£ããããšã³ãã£ãã£èå¥åãç°¡åã«ååŸããããäžåºŠComponentManagerã«ãã®èå¥åã®TransformComponentãæäŸããããã«äŸé Œã§ããŸãã
ç§ãçŽæããããã«ã2çªç®ã®äŸãèŠãŠã¿ãŸããããRespawnComponentã¯ãæ»åŸã«çãŸãå€ããå¿ èŠããããšã³ãã£ãã£ã«äœ¿çšãããŸãããã®ã³ã³ããŒãã³ãã«ã¯ããšã³ãã£ãã£ã®åçæã®åäœãã«ã¹ã¿ãã€ãºããããã«äœ¿çšã§ãã5ã€ã®ããããã£ããããŸããæ»åŸã®ãšã³ãã£ãã£ã®èªåãªãã€ãã«ãéžæãããªãã€ãã«ã®äœçœ®ãšæ¹åã ãã§ãªããåçæããããŸã§ã®æéãèšå®ã§ããŸãããªãã€ãã«ããžãã¯èªäœã¯RespawnSystemã«å®è£ ãããŠããŸãã
// RespawnSystem.h class RespawnSystem : public ECS::System<RespawnSystem>, protected ECS::Event::IEventListener { private: // ... Spawns m_Spawns; RespawnQueue m_RespawnQueue; // void OnGameObjectKilled(const GameObjectKilled* event); public: RespawnSystem(); virtual ~RespawnSystem(); virtual void Update(float dt) override; // ... }; // class RespawnSystem
// RespawnSystem.cpp // : ! voidRespawnSystem::OnGameObjectKilled(const GameObjectKilled * event) { // , RespawnComponent* entityRespawnComponent = ECS::ECS_Engine->GetComponentManager()->GetComponent<RespawnComponent>(event->m_EntityID); if(entityRespawnComponent == nullptr || (entityRespawnComponent->IsActive() == false) || (entityRespawnComponent->m_AutoRespawn == false)) return; AddToRespawnQeueue(event->m_EntityID, entityRespawnComponent); } void RespawnSystem::Update(float dt) { foreach(spawnable in this->m_RespawnQueue) { spawnable.m_RemainingDeathTime -= dt; if(spawnable.m_RemainingDeathTime <= 0.0f) { DoSpawn(spawnable); RemoveFromSpawnQueue(spawnable); } } }
äžèšã®ã³ãŒãã¯äžå®å šã§ãããã³ãŒãã®éèŠãªè¡ã®ã¢ã€ãã¢ãæäŸããŸããRespawnSystemã¯å«ãŸããŠããããã¹ãŠã®æŽæ°å®äœèå¥åãèªåã§RespawnComponentãã·ã¹ãã ãGameObjectKilledã€ãã³ããåä¿¡ãããšãæ°ãããšã³ãã£ãã£ããã¥ãŒã«å ¥ããããŸããã·ã¹ãã ã¯ã殺ããããšã³ãã£ãã£ãåçæããèœåãæã£ãŠãããã©ãããã€ãŸãRespawnComponentãã¢ã¿ãããããŠãããã©ããããã§ãã¯ããŸããããã§ããå Žåããšã³ãã£ãã£ã¯åçã®ããã«ãã¥ãŒã«å ¥ããããããã§ãªãå Žåã¯ç¡èŠãããŸãããã¬ãŒã ããšã«åŒã³åºãããRespawnSystemæŽæ°ã¡ãœããã§ã¯ãã·ã¹ãã ã¯åæRespawnComponentã®åã¹ããŒã³æéãççž®ããŸããã¥ãŒã«å ¥ãããããšã³ãã£ãã£ãã¹ããŒã³æéããŒãã«ççž®ããããšããšã³ãã£ãã£ã¯çãŸãå€ãããã¹ããŒã³ãã¥ãŒããåé€ãããŸãã
ãã®èšäºã¯ããªãçããã®ã§ããããããã圌女ãECSã®äžçã§ãã¹ãŠãã©ã®ããã«æ©èœãããã«ã€ããŠå€§ãŸããªèããäžããŠããããšæããŸããæçš¿ãçµããåã«ãç§èªèº«ã®çµéšãçãããšå ±æããããšæããŸãã ECSã§ã®äœæ¥ã¯å€§ããªåã³ã§ãããµãŒãããŒãã£ã®ã©ã€ãã©ãªã®å©ããåããŠããã²ãŒã ã«æ°ããæ©èœãè¿œå ããã®ã¯é©ãã»ã©ç°¡åã§ããæ°ããæ©èœãã²ãŒã ã«æ¥ç¶ããæ°ããã³ã³ããŒãã³ããšã·ã¹ãã ãè¿œå ããã°ããã§ãåæ¢ãããšããæèŠã¯ãŸã£ãããããŸããã§ãããã²ãŒã ããžãã¯å šäœãè€æ°ã®ã·ã¹ãã ã«åå²ããããšã¯çŽæçã§ãããECSã䜿çšããéã«åé¡ãåŒãèµ·ããããšã¯ãããŸããããã€ã³ã¿ãŒã®ãã¹ãŠã®ãã¹ãã²ããã£äŸåé¢ä¿ããåãé€ãããããã³ãŒãã¯ã¯ããã«ç解ããããããµããŒããããããªããŸãããã€ãã³ããœãŒã·ã³ã°ã¯ãã·ã¹ãã /ãšã³ãã£ãã£éã§ããŒã¿ã亀æããããã®éåžžã«åŒ·åã§äŸ¿å©ãªææ³ã§ãããäž¡åã®ãã¬ãŒãã§ãããæéã®çµéãšãšãã«åé¡ãåŒãèµ·ããå¯èœæ§ããããŸããã€ãã³ããããªã¬ãŒããããã®æ¡ä»¶ã«ã€ããŠè©±ããŠããã UnityãŸãã¯Unreal Engineãšãã£ã¿ãŒã䜿çšããããšãããå Žåã¯ããã®ãããªãšãã£ã¿ãŒã®å®è£ ã«æºè¶³ããã§ãããããããã®ãšãã£ã¿ãŒã¯ããããã®ãã¹ãŠã®ã³ãŒãè¡ãæåã§èšè¿°ããããããæ°ããECSãªããžã§ã¯ããäœæããæéãã¯ããã«çããããçç£æ§ãå€§å¹ ã«åäžããŸãããããããšã³ãã£ãã£ãã³ã³ããŒãã³ããã·ã¹ãã ãããã³ã€ãã³ãã®ãªããžã§ã¯ãã®åŒ·åãªåºç€ãäœæããå Žåãããããçµã¿åãããŠããããã«åºã¥ããŠå®æ§çãªãã®ãäœæããã®ã¯ç°¡åãªäœæ¥ã«ãªããŸãããããã®ã³ãŒãè¡ããã¹ãŠæåã§èšè¿°ãããããããããããšã³ãã£ãã£ãã³ã³ããŒãã³ããã·ã¹ãã ãããã³ã€ãã³ãã®ãªããžã§ã¯ãã®åŒ·åãªåºç€ãäœæããå Žåãããããçµã¿åãããŠããããã«åºã¥ããŠå®æ§çãªãã®ãäœæããã®ã¯ç°¡åãªäœæ¥ã«ãªããŸãããããã®ã³ãŒãè¡ããã¹ãŠæåã§èšè¿°ãããããããããããšã³ãã£ãã£ãã³ã³ããŒãã³ããã·ã¹ãã ãã€ãã³ãã®ãªããžã§ã¯ãã®åŒ·åãªåºç€ãäœæããå Žåãããããçµã¿åãããŠããããã«åºã¥ããŠå®æ§çãªãã®ãäœæããã®ã¯ç°¡åãªäœæ¥ã«ãªããŸãã