ã¬ã¬ã·ãŒç¬¬12ç« ïŒã¬ã¬ã·ãŒã²ãŒã ãšã³ãžã³çµ±åã¢ãŒããã¯ãã£
ã¡ã€ã³ã«ãŒãã»ã¬ã³ãã©ã»ç©çã»ãµãŠã³ãã®ççµåãªãŒã±ã¹ãã¬ãŒã·ã§ã³
ãããŸã§ã®ç¬¬1ç« ã第11ç« ã§ãç§ãã¡ã¯ã«ãã»ã«åãåç寿åœãããªã¢ãŒãã£ãºã ãState/Observerãã¿ãŒã³ãæŒç®åãªãŒããŒããŒãããã€ã³ã¿æŒç®ãã³ãŒã«ããã¯ãå€éç¶æ¿ã®åé¿ãCRTPããããŠç¬èªã¡ã¢ãªããŒã«ãŸã§ãC++ã®åŒ·åãªèšèšææ³ã1ã€ãã€ç¿åŸããŠããŸãããããããå®éã®åçšã²ãŒã ãå®åã®å€§èŠæš¡ã·ã¹ãã ã§ã¯ããåã
ã®éšåãåããã ãã§ã¯éçšããŸãããæç»ãç©çæŒç®ãå
¥åããµãŠã³ããã·ãŒã³é·ç§»ãšãã£ã巚倧ãªãµãã·ã¹ãã 矀ããã©ã®ãããªé åºã§åæåããã©ã®ãããªæéè»žã§æŽæ°ããå®å
šã«çµäºãããã®ããšããããšã³ãžã³éªšæ ŒïŒãªãŒã±ã¹ãã¬ãŒã·ã§ã³ïŒãã®èšèšãäžå¯æ¬ ã§ããæ¬ç« ã§ã¯ãåžè²©ã®2D/3Dã²ãŒã ãšã³ãžã³ïŒUnreal EngineãUnityã®å
éšã³ã¢ïŒã§ãæ¡çšãããŠããäŒèª¬ã®ãåºå®ãã«ã¿ã¿ã€ã ïŒFixed TimestepïŒã²ãŒã ã«ãŒãããšããµãã·ã¹ãã ã®çµååºŠãæ¥µéãŸã§äžãããIEngineSubsystem ã©ã€ããµã€ã¯ã«ç®¡çãã培åºè§£èª¬ãPCã¹ããã¯ããã¬ãŒã ã¬ãŒãã«äžåå·Šå³ãããªããæ±ºå®è«çã§å
ç¢ãªã²ãŒã ãšã³ãžã³ã¢ãŒããã¯ãã£ã宿ãããŸãã
L12.1 ã²ãŒã ã«ãŒãã®ç©çæ³åïŒå¯å€ãã«ã¿ã¿ã€ã ã®çœ ãšãåºå®ãã«ã¿ã¿ã€ã ã
åãã¬ãŒã ã®çµéæéïŒdtïŒããã®ãŸãŸæããçŽ æŽãªææ³ãããªãã匟ã®ããæãããããã¬ãŒã ã¬ãŒãäŸåãã°ããåŒãèµ·ããã®ããè§£æããŸãã
ð§ ãã³ã®ã³å
茩
ãã³å
çïŒå€§å€ã§ãïŒãã€ã¹ããã¯ãªã²ãŒãã³ã°PCïŒ240HzïŒã§åãããšæµã®åããè¶
ã¹ããŒã«ãªããéã«äœã¹ããã¯ãªããŒãPCã§éãåŠçãèµ°ããšãèªæ©ã®åŒŸãæµã®äœãã¯ãŒãããŠããæããŠããŸããŸãâŠâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ãµãã£ãµãã£ãµãïŒãããããã²ãŒã ããã°ã©ãã®èª°ããäžåºŠã¯éãæŽç€Œããå¯å€ãã«ã¿ã¿ã€ã ã®çœ ããããªïŒ
ð§ ãã³ã®ã³å
茩
åãã¬ãŒã ããã®çµéæé dt ãæž¬ã£ãŠãx += velocity * dt; ãšèšç®ããŠããŸããçŸå®äžçã®ç©çå
¬åŒãšåãã¯ããªã®ã«ããªãå£ãããã§ããïŒ
ð»ââïž ã·ãã¯ãå
ç
çŸå®äžçã®æéã¯é£ç¶ããŠããããã³ã³ãã¥ãŒã¿ã®ã·ãã¥ã¬ãŒã·ã§ã³ã¯ã颿£çïŒé£ã³é£ã³ïŒãããããããïŒäžç¬ã¬ã¯ããšãã¬ãŒã èœã¡ã㊠dt = 0.2ç§ ã«è·³ãäžãã£ãç¬éã匟ã¯1ãã¬ãŒã ã§20ãã¯ã»ã«ããžã£ã³ãããéã«æãŸããèãæµã®åœããå€å®ãé£ã³è¶ããŠããŸãïŒãã³ããªã³ã°çŸè±¡ïŒãç©çã·ãã¥ã¬ãŒã·ã§ã³ã¯çµ¶å¯Ÿã«ãåºå®æéïŒFixed TimestepïŒãã§åããã°ãªããã®ããïŒ
ð FixedTimestepLoop.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <algorithm>
class FixedTimestepEngine {
private:
static constexpr double FIXED_DT = 1.0 / 60.0; // 60Hzåºå®ç©çã¹ããã (çŽ0.01666ç§)
static constexpr double MAX_FRAME_TIME = 0.25; // 1ãã¬ãŒã ã®æå€§èš±å®¹æéïŒ250msïŒ
double simulatedTime_ = 0.0;
int physicsTickCount_ = 0;
int renderFrameCount_ = 0;
public:
// ç©çã»ããžãã¯æŽæ°ïŒåžžã«äžå®ã®åºå®å»ã¿ã§åŒã°ããïŒ
void updatePhysics(double dt) {
simulatedTime_ += dt;
physicsTickCount_++;
// ããã§å³å¯ãªè¡çªå€å®ã匟移åãAIæèãè¡ã
}
// æç»åŠçïŒãã£ã¹ãã¬ã€ã®æç»ã¿ã€ãã³ã°ã«åãããŠåŒã°ããïŒ
// alpha 㯠[0.0, 1.0) ã®ç¯å²ïŒåãã¬ãŒã ãšçŸãã¬ãŒã ã®éã®è£éä¿æ°
void render(double alpha) {
renderFrameCount_++;
(void)alpha; // è£éæç»ã«äœ¿çš
}
// 1ãã¬ãŒã åã®æéé²è¡ãåŠçããã³ã¢é¢æ°
void advanceTime(double frameTime, double& accumulator) {
// â ïž ã¹ãã€ã©ã«ã»ãªãã»ãã¹ïŒSpiral of DeathïŒé²æ¢ã¬ãŒãïŒ
// åŠçèœã¡æã«ç©çæŽæ°ãç¡é墿®ããŠå®å
šããªãŒãºããã®ãé²ã
if (frameTime > MAX_FRAME_TIME) {
frameTime = MAX_FRAME_TIME;
}
accumulator += frameTime;
// èç©ãããæéãåºå®å»ã¿ FIXED_DT 以äžããéããäœåã§ãç©çæŽæ°ãåãïŒ
while (accumulator >= FIXED_DT) {
updatePhysics(FIXED_DT);
accumulator -= FIXED_DT;
}
// æ®äœæéãç©çå»ã¿ã§æ£èŠåïŒ0.0 ã 0.999...ïŒããŠæç»è£éãžæž¡ã
double alpha = accumulator / FIXED_DT;
render(alpha);
}
void printStats() const {
std::cout << "[Engine Stats] ç©çTickåæ°: " << physicsTickCount_
<< ", æç»Frameåæ°: " << renderFrameCount_
<< ", ç©çã·ãã¥ã¬ãŒã·ã§ã³æé: " << simulatedTime_ << "s\n";
}
};
int main() {
FixedTimestepEngine engine;
double accumulator = 0.0;
std::cout << "--- 1. éåžžãã¬ãŒã (16.6ms çµé / 60FPS) ---\n";
for (int i = 0; i < 3; ++i) {
engine.advanceTime(1.0 / 60.0, accumulator);
}
engine.printStats();
std::cout << "\n--- 2. æ¿ããåŠçèœã¡çºçïŒ (1ãã¬ãŒã ã§ 100ms çµé) ---\n";
// 100ms = 0.1ç§ -> çŽ6ååã®ç©çæŽæ°ãäžæ°ã«è¿œãã€ãåŠçãããïŒ
engine.advanceTime(0.100, accumulator);
engine.printStats();
return 0;
}
L12.2 ãµãã·ã¹ãã ã®ã©ã€ããµã€ã¯ã«ïŒIEngineSubsystem ãšãªãŒã±ã¹ãã¬ãŒã·ã§ã³
æç»ã»ç©çã»é³å£°ã»å
¥åã»ã¢ã»ããã®åãããŒãžã£ãŒãæ±ãããåæåé åºãšçµäºé åºã®äŸåå°çããçµ±äžã¢ãŒããã¯ãã£ã§æ ¹çµ¶ããŸãã
ð§ ãã³ã®ã³å
茩
ãã³å
çãã²ãŒã çµäºæã«ããŸã«ã¢ã¯ã»ã¹éåã§èœã¡ãŸãâŠâŠããããã¬ã§èŠããããµãŠã³ãã·ã¹ãã ããã§ã«è§£æŸãããåŸã«ããã¬ã€ã€ãŒã®ãã¹ãã©ã¯ã¿ããæ»äº¡æå¹æé³ãã鳎ããããšããŠãã«ãã€ã³ã¿ãèžãã§ããŸããâŠâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ãããŸãçŸå Žã®å
žåçãªçœ ãããªïŒãåæåïŒStartupïŒããšãçµäºïŒShutdownïŒãã®é åºã管çãããŠãããããããã
ð§ ãã³ã®ã³å
茩
åãããŒãžã£ãŒããã©ãã©ã«ã°ããŒãã«å€æ°ãšããŠååšããŠããã®ãåé¡ãªãã§ããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãã®éãããïŒC++ã§ã¯ç°ãªã翻蚳åäœã®ã°ããŒãã«å€æ°ã®åæåé ã¯ãæªèŠå®ïŒUnspecifiedïŒãããããã¹ãŠã®ãµãã·ã¹ãã ããIEngineSubsystemããšããå
±éã€ã³ã¿ãŒãã§ãŒã¹ã§çµ±äžããã«ãŒãã«ããåæåããé åºã®å®å
šãªéé ïŒLIFO: ã¹ã¿ãã¯é ïŒãã§çµäºãããèŠåŸãäœããã°ãªããã®ããïŒ
ð SubsystemLifecycle.cpp
#include <iostream>
#include <vector>
#include <memory>
#include <string>
// ãµãã·ã¹ãã ã®æšæºã€ã³ã¿ãŒãã§ãŒã¹
class IEngineSubsystem {
public:
virtual ~IEngineSubsystem() = default;
virtual const char* getName() const = 0;
virtual bool startup() = 0;
virtual void update(double dt) = 0;
virtual void shutdown() = 0;
};
// 1. å
¥åãµãã·ã¹ãã
class InputSubsystem : public IEngineSubsystem {
public:
const char* getName() const override { return "InputSubsystem"; }
bool startup() override {
std::cout << " [OK] InputSubsystem èµ·å (ããŒããŒã/ããŠã¹åæå)\n";
return true;
}
void update(double dt) override { (void)dt; }
void shutdown() override {
std::cout << " [SHUTDOWN] InputSubsystem çµäº\n";
}
};
// 2. ãµãŠã³ããµãã·ã¹ãã
class AudioSubsystem : public IEngineSubsystem {
public:
const char* getName() const override { return "AudioSubsystem"; }
bool startup() override {
std::cout << " [OK] AudioSubsystem èµ·å (ãªãŒãã£ãªããã€ã¹ã»ãããã¡ç¢ºä¿)\n";
return true;
}
void update(double dt) override { (void)dt; }
void shutdown() override {
std::cout << " [SHUTDOWN] AudioSubsystem çµäº (åç忢ã»ãã©ã€ãè§£æŸ)\n";
}
};
// 3. ã¬ã³ããªã³ã°ãµãã·ã¹ãã
class RenderSubsystem : public IEngineSubsystem {
public:
const char* getName() const override { return "RenderSubsystem"; }
bool startup() override {
std::cout << " [OK] RenderSubsystem èµ·å (GPUã³ã³ããã¹ãã»ã¹ã¯ãããã§ãŒã³çæ)\n";
return true;
}
void update(double dt) override { (void)dt; }
void shutdown() override {
std::cout << " [SHUTDOWN] RenderSubsystem çµäº (GPUãªãœãŒã¹è§£æŸã»ãŠã£ã³ããŠç Žæ£)\n";
}
};
// ãšã³ãžã³ã«ãŒãã«ïŒãµãã·ã¹ãã ã®ãªãŒã±ã¹ãã¬ãŒã·ã§ã³ãæ
åœ
class EngineKernel {
private:
std::vector<std::unique_ptr<IEngineSubsystem>> subsystems_;
bool isRunning_ = false;
public:
template <typename T, typename... Args>
void registerSubsystem(Args&&... args) {
subsystems_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
}
bool startup() {
std::cout << "=== ãšã³ãžã³èµ·åã·ãŒã¯ãšã³ã¹éå§ ===\n";
for (auto& sys : subsystems_) {
if (!sys->startup()) {
std::cerr << "èŽåœçãšã©ãŒ: " << sys->getName() << " ã®èµ·åã«å€±æïŒ\n";
shutdown();
return false;
}
}
isRunning_ = true;
std::cout << "=== å
šãµãã·ã¹ãã èµ·åå®äº (ã²ãŒã 皌åå¯èœ) ===\n\n";
return true;
}
void update(double dt) {
if (!isRunning_) return;
for (auto& sys : subsystems_) {
sys->update(dt);
}
}
// çµäºæã¯ç»é²ã®ãå®å
šãªéé ïŒLIFOïŒãã§è§£æŸããïŒ
void shutdown() {
std::cout << "\n=== ãšã³ãžã³çµäºã·ãŒã¯ãšã³ã¹éå§ (éé ã·ã£ããããŠã³) ===\n";
for (auto it = subsystems_.rbegin(); it != subsystems_.rend(); ++it) {
(*it)->shutdown();
}
subsystems_.clear();
isRunning_ = false;
std::cout << "=== å
šãµãã·ã¹ãã å®å
šç Žæ£å®äº ===\n";
}
~EngineKernel() {
if (isRunning_) {
shutdown();
}
}
};
int main() {
EngineKernel engine;
// äŸåé¢ä¿ã«åŸã£ãŠç»é²é ãæ±ºå®ïŒInput -> Audio -> RenderïŒ
engine.registerSubsystem<InputSubsystem>();
engine.registerSubsystem<AudioSubsystem>();
engine.registerSubsystem<RenderSubsystem>();
if (engine.startup()) {
engine.update(1.0 / 60.0);
}
// çµäºæã¯èªåçã« Render -> Audio -> Input ã®éé ã§å®å
šçµäºãããïŒ
return 0;
}
L12.3 ãã©ãããã©ãŒã ççµååãšãããã¬ã¹èšèšïŒCIèªåãã¹ã察å¿ïŒ
ã²ãŒã ããžãã¯ããã°ã©ãã£ãã¯ã¹APIäŸåãå®å
šæé€ãããŠã£ã³ããŠãªãã»ç§éã§åãããããã¬ã¹ã¢ãŒãããæ§ç¯ããŸãã
ð§ ãã³ã®ã³å
茩
ãã³å
çãCIïŒç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ïŒã®ãµãŒããŒäžã§ã²ãŒã ã®èªåãã¹ããèµ°ããããã®ã§ãããGitHub Actions ã®LinuxãµãŒããŒã«ã¯ãã£ã¹ãã¬ã€ãç¹ãã£ãŠããªãã®ã§ DirectX ããŠã£ã³ããŠåæåã§ãšã©ãŒã«ãªã£ãŠããŸããŸãïŒ
ð»ââïž ã·ãã¯ãå
ç
ããïŒãŸãã«ã¢ãã³éçºã®çŸå Žã§æéèŠããã課é¡ããïŒåçšãšã³ãžã³ïŒUnreal Engineãªã©ïŒãããã«ããã·ã³ãå°çšã²ãŒã ãµãŒããŒã§ã¯ç»é¢ãäžååºããªãããããã¬ã¹ã¢ãŒãïŒHeadless Mode / Dedicated ServerïŒãã§åãããã«èšèšãããŠããã®ããã
ð§ ãã³ã®ã³å
茩
ãšããããšã¯ããæç»ïŒIRendererïŒããã€ã³ã¿ãŒãã§ãŒã¹ã«ããŠãæ¬çªã§ã¯OpenGLãDirectXã®ã¬ã³ãã©ã䜿ãããã¹ãããµãŒããŒã§ã¯ãäœãããªãNullRendererããå·®ãæ¿ããããããã«ããã°ãããã§ããïŒ
ð HeadlessRenderer.cpp
#include <iostream>
#include <memory>
#include <string>
// æç»æœè±¡ã€ã³ã¿ãŒãã§ãŒã¹
class IRenderer {
public:
virtual ~IRenderer() = default;
virtual void clearScreen() = 0;
virtual void drawSprite(int id, float x, float y) = 0;
virtual void present() = 0;
};
// 1. æ¬çªçšïŒã³ã³ãœãŒã«/ã°ã©ãã£ãã¯ã¹æç»
class ConsoleRenderer : public IRenderer {
public:
void clearScreen() override { /* ç»é¢æ¶å» */ }
void drawSprite(int id, float x, float y) override {
std::cout << "[Draw] ã¹ãã©ã€ãID=" << id << " ã (" << x << ", " << y << ") ã«æç»\n";
}
void present() override {
std::cout << "[Screen] ç»é¢ãããã¡ãããªãã衚瀺\n";
}
};
// 2. CI/ãã¹ãçšïŒãããã¬ã¹ã»ãã«ã¬ã³ãã©ïŒç»é¢åºåãŒãã»è¶
é«éïŒ
class NullRenderer : public IRenderer {
public:
void clearScreen() override {}
void drawSprite(int id, float x, float y) override { (void)id; (void)x; (void)y; }
void present() override {}
};
// ã²ãŒã ã¯ãŒã«ãïŒã¬ã³ãã©ã«çŽæ¥äŸåãããæœè±¡ã€ã³ã¿ãŒãã§ãŒã¹ã«äŸå
class GameWorld {
private:
IRenderer& renderer_;
float playerX_ = 100.0f;
float playerY_ = 200.0f;
public:
GameWorld(IRenderer& renderer) : renderer_(renderer) {}
void render() {
renderer_.clearScreen();
renderer_.drawSprite(1, playerX_, playerY_); // èªæ©
renderer_.present();
}
void movePlayer(float dx, float dy) {
playerX_ += dx;
playerY_ += dy;
}
float getPlayerX() const { return playerX_; }
};
int main() {
std::cout << "--- A. æ¬çªã°ã©ãã£ãã¯ã¹å®è¡ ---\n";
ConsoleRenderer realRenderer;
GameWorld game(realRenderer);
game.render();
std::cout << "\n--- B. CIãµãŒããŒçšãããã¬ã¹èªåãã¹ã (ç»é¢ãªãã»è¶
é«é) ---\n";
NullRenderer nullRenderer;
GameWorld testWorld(nullRenderer);
// ç»é¢ãåºããã«1000åç§»åããžãã¯ãåããŠã¢ãµãŒã·ã§ã³æ€èšŒïŒ
for (int i = 0; i < 1000; ++i) {
testWorld.movePlayer(1.0f, 0.0f);
}
std::cout << "ãã¹ãå®äº: æçµèªæ©Xåº§æš = " << testWorld.getPlayerX() << " (æåŸ
å€: 1100)\n";
return 0;
}
L12.4 ã€ã³ããŒããŒã²ãŒã çµ±åïŒ60FPSå®å
šåæã®å®æ
ãããŸã§äœã£ãŠããå
šã¢ãžã¥ãŒã«ïŒã¡ã¢ãªããŒã«ãCRTPãStateãã·ã³ã空éããžãã¯ïŒã1ã€ã®ã²ãŒã ãšã³ãžã³ãžçµ±åããŸãã
ð»ââïž ã·ãã¯ãå
ç
èŠããã³ã®ã³åïŒç¬¬1ç« ã®ãã®500è¡ã¹ãã²ãã£ã³ãŒãã ã£ãã€ã³ããŒããŒã²ãŒã ããä»ãããæ°Žæºã®ã²ãŒã ãšã³ãžã³ã¢ãŒããã¯ãã£ã®å
ã§çµ±å¶ãããŠãããïŒ
ð§ ãã³ã®ã³å
茩
æåã§ãâŠâŠïŒã¡ã€ã³ã«ãŒãã¯åºå®ãã«ã¿ã¿ã€ã ã§1ãã¯ã»ã«ã®ãã¬ããªãåãããµãã·ã¹ãã ã¯å®å
šãªé åºã§èµ·åã»çµäºãããã¹ãããããã¬ã¹ã§ç¬æã«å®äºããŸãããããåçšã²ãŒã ãšã³ãžã³ã®éªšæ Œãªãã§ããïŒ
ð ShirokumaGameEngine.cpp
// Shirokuma 2D Game Engine Core Loop
class ShirokumaGameEngine {
public:
void run() {
kernel_.startup();
while (isRunning_) {
// 1. OSã€ãã³ãã»å
¥åããŒãªã³ã°
input_.pollEvents();
if (input_.isQuitRequested()) break;
// 2. åºå®ãã«ã¿ã¿ã€ã ã«ããæ±ºå®è«çç©çã»ããžãã¯æŽæ°
double frameTime = timer_.getElapsedSeconds();
accumulator_ += std::min(frameTime, MAX_FRAME_TIME);
while (accumulator_ >= FIXED_DT) {
world_.update(FIXED_DT);
audio_.update(FIXED_DT);
accumulator_ -= FIXED_DT;
}
// 3. æ®äœæé alpha ã«ããæ»ãããªè£éæç»
double alpha = accumulator_ / FIXED_DT;
renderer_.beginFrame();
world_.render(renderer_, alpha);
renderer_.endFrame();
}
kernel_.shutdown(); // ç»é²ã®å®å
šéé ã§å®å
šç Žæ£ïŒ
}
};
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
- èœãšã穎1ïŒã¹ãã€ã©ã«ã»ãªãã»ãã¹ïŒåŠçèœã¡ã®æ»ã®é£éïŒ: 1ãã¬ãŒã ã®åŠçãéããŠ0.5ç§ããã£ãå Žåãæ¬¡ã®ãã¬ãŒã ã§0.5ç§åïŒçŽ30ååïŒã®ç©çæŒç®ãäžæ°ã«åãããšããŠããã«åŠçèœã¡ãã²ãŒã ãåçµããŸããå¿
ã frameTime = std::min(frameTime, 0.25); ã®ããã«æå€§äžéã¯ã©ã³ããèšããŸãã
- èœãšã穎2ïŒãµãã·ã¹ãã å士ã®çžäºåç
§ïŒåŸªç°äŸåïŒ: AudioSubsystem ãš RenderSubsystem ãçŽæ¥äºããåç
§ãããšåæåé åºãç Žç¶»ããŸããObserver ãã¿ãŒã³ãã€ãã³ããã¹ãä»ããŠççµåã«éä¿¡ããŸãã
- èœãšã穎3ïŒãµãã·ã¹ãã ã®ã·ã³ã°ã«ãã³ä¹±çš: ã©ãããã§ãåŒã¹ãã°ããŒãã« Singleton ãä¹±çšãããšã䞊è¡ãã¹ããDIãäžå¯èœã«ãªããŸãããµãã·ã¹ãã 㯠EngineKernel ãäžæ¬ææãåç
§ãæž¡ãã®ãã¯ãªãŒã³ã§ãã
ð ç解床ãã§ãã¯ã¯ã€ãº
Q1. ç©çã·ãã¥ã¬ãŒã·ã§ã³ã«ãããŠãå¯å€ãã«ã¿ã¿ã€ã ïŒdt = now - lastTimeïŒãçŽæ¥äœ¿ãããšã®æå€§ã®æ¬ ç¹ã¯ã©ãã§ããïŒ
- 1. C++ã³ã³ãã€ã©ãã€ã³ã©ã€ã³å±éã§ããªããªããããã³ã³ãã€ã«æéãé·ããªã
- 2. ãã¬ãŒã èœã¡ããç¬éã« dt ã巚倧åãã匟ãå£ãæµã®åœããå€å®ãé£ã³è¶ããããã³ããªã³ã°çŸè±¡ããèµ·ãã
- 3. CPUã®L1ãã£ãã·ã¥ããã©ã°ã¡ã³ããŒã·ã§ã³ãèµ·ãããŠããŒããŠã§ã¢ã忢ãã
- 4. ä»®æ³é¢æ°ããŒãã«ïŒvtableïŒã®ãµã€ãºããã¬ãŒã ããšã«åçæ¡åŒµãããŠããŸã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒãã¬ãŒã èœã¡ããç¬éã« dt ã巚倧åãã匟ãå£ãæµã®åœããå€å®ãé£ã³è¶ããããã³ããªã³ã°çŸè±¡ããèµ·ãã
ãã¬ãŒã èœã¡çã§ dt ãè·³ãäžãããšã1ãã¬ãŒã ã®ç§»åéãåœããå€å®ã®åã¿ãè¶
ããŠããŸããéã«é害ç©ããã£ãŠãããæããŠããŸãããã³ããªã³ã°çŸè±¡ããçºçããŸããåºå®ãã«ã¿ã¿ã€ã ã«ããããšã§ãã©ããªã«åŠçèœã¡ããŠãå°å»ã¿ãªã·ãã¥ã¬ãŒã·ã§ã³ãé æ¬¡å®è¡ããã匟æãã確å®ã«é²ãããšãã§ããŸãã
Q2. è€æ°ã®ãšã³ãžã³ãµãã·ã¹ãã ïŒInput, Audio, Physics, RenderïŒãçµäºïŒShutdownïŒãããéãäžè¬çã«æšå¥šãããé åºã®ååã¯ã©ãã§ããïŒ
- 1. ååã®ã¢ã«ãã¡ãããæé ïŒAããZã®é ïŒã§çµäºããã
- 2. ã©ã³ãã ãªé åºã§çµäºãããæ®ã£ãã¡ã¢ãªã¯OSã®èªåååã«ä»»ãã
- 3. åæåïŒStartupïŒããé åºã®ãå®å
šãªéé ïŒLIFOïŒã¹ã¿ãã¯é ïŒãã§çµäºããã
- 4. ãã¹ãŠã®ãµãã·ã¹ãã ãåæã«äžŠåã¹ã¬ããã§äžæã«ç Žæ£ãã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒåæåïŒStartupïŒããé åºã®ãå®å
šãªéé ïŒLIFOïŒã¹ã¿ãã¯é ïŒãã§çµäºããã
åŸããåæåããããµãã·ã¹ãã ã¯ãå
ã«åæåããããµãã·ã¹ãã ã«äŸåããŠããïŒäŸ: Render ã GameWorld 㯠Audio ã MemoryPool ã«äŸåããïŒããšãäžè¬çã§ãããã®ãããåæåãšå®å
šãªéé ïŒLIFOïŒã§ã·ã£ããããŠã³ããããšã§ãäŸåå
ã®ãµãã·ã¹ãã ãå
ã«æ¶ããŠæªå®çŸ©åäœãã¢ã¯ã»ã¹éåã¯ã©ãã·ã¥ãèµ·ããäºæ
ã確å®ã«é²ãããšãã§ããŸãã
Q3. æç»åŠçãæœè±¡ã€ã³ã¿ãŒãã§ãŒã¹ïŒIRendererïŒã§èšèšãããNullRendererïŒäœãããªãæç»ïŒããå·®ãæ¿ããããããã«ããããããã¬ã¹èšèšãã®æå€§ã®ã¡ãªããã¯äœã§ããïŒ
- 1. C++ã³ãŒããèªåçã«ã¢ã»ã³ããªèšèªã«å€æãããŠFPSã100åã«ãªã
- 2. GPUããã£ã¹ãã¬ã€ã®ååšããªãCIãµãŒããŒãLinuxãã¹ãç°å¢ã§ããã²ãŒã ããžãã¯ã®åäœãã¹ããè¶
é«éã«èªåå®è¡ã§ãã
- 3. ãã¹ãŠã®å€æ°ãã³ã³ãã€ã«æã« constexpr è©äŸ¡ãããŠãã€ããªãµã€ãºãååã«ãªã
- 4. ãã«ãã¹ã¬ããã«ããããããããã¯ãç©ççã«äžåçºçããªããªã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒGPUããã£ã¹ãã¬ã€ã®ååšããªãCIãµãŒããŒãLinuxãã¹ãç°å¢ã§ããã²ãŒã ããžãã¯ã®åäœãã¹ããè¶
é«éã«èªåå®è¡ã§ãã
ãããã¬ã¹èšèšã«ããããšã§ãGPUãŠã£ã³ããŠã®ç«ã¡äžããã§ããªãCI/CDç°å¢ïŒGitHub ActionsçïŒããã«ããã¬ã€ã€ãŒçšå°çšãµãŒããŒïŒDedicated ServerïŒã§ããã²ãŒã ã«ãŒããšã²ãŒã ããžãã¯ã ããæ¯ç§æ°åãæ°äžãã¬ãŒã ã®çéã§å®è¡ã»èªåæ€èšŒã§ããããã«ãªããŸãã
ð»ââïž ã·ãã¯ãC++ã©ã ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ã·ã¹ãã
ãã©ãŠã¶ã§JavaScriptãæå¹ã«ãããšããã©ãŠã¶å
ã€ã³ããŒããŒã²ãŒã ãšãã¥ã¬ãŒã¿ãã¡ã¢ãªãããå¯èŠåãUMLã¯ã©ã¹å³ã察話å解説ãç解床ã¯ã€ãºãèµ·åããŸãã
ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ãéå§ãã â