GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
graphic_system.cpp
[詳解]
1
3
4// Copyright(c) 2023-2025 Design Engineering Laboratory, Saitama University
5// Released under the MIT license
6// https://opensource.org/licenses/mit-license.php
7
8#include "graphic_system.h"
9
10#include <utility>
11
12#include <Dxlib.h>
13
14#include "cassert_define.h"
15#include "dxlib_util.h"
16#include "graphic_const.h"
17#include "keyboard.h"
18
19
20namespace designlab
21{
22
24 const std::shared_ptr<const ApplicationSettingRecord> setting_ptr) :
25 setting_ptr_(setting_ptr),
26 fps_controller_{ setting_ptr != nullptr ? setting_ptr->window_fps : 60 }
27{
28 assert(setting_ptr_ != nullptr);
29}
30
31
33{
34 // そもそも描画処理を使わないならば即終了.
35 if (!setting_ptr_->do_gui_display)
36 {
37 return;
38 }
39
40 // Dxlib の関数は複数スレッドで呼ぶことを考慮されていないので,
41 // 複数のスレッドから呼ぶと必ず問題が起きる.
42 // そのため,初期化処理,描画,終了処理の全てをこの関数の中で呼ぶ必要がある.
43
44 if (!MyDxlibInit())
45 {
46 return;
47 }
48
49 // ProcessMessage関数はウィンドウの×ボタンがおされると失敗の値を返す.
50 // また,ウィンドウを維持するためには定期的に呼び出し続ける必要があるので,
51 // ループで呼び続けている.
52 // ProcessMessage は成功で 0 ( C++における false),
53 // 失敗で -1 ( C++における true は0以外の値)を返す,
54 // そのため,失敗するまでループする場合は以下のように記述する.
55 while (ProcessMessage() >= 0)
56 {
57 // メインループ,false が帰った場合,ループを抜ける.
58 if (!Loop())
59 {
60 break;
61 }
62 }
63
64 // 終了処理を行う.
65 MyDxlibFinalize();
66}
67
69 std::unique_ptr<IGraphicMain>&& graphic_main_ptr)
70{
71 // mutexで排他制御を行う.GraphicMainを切り替える際に,
72 // Main を呼んでしまうとエラーが発生する可能性があるため,それを抑制する.
73 boost::mutex::scoped_lock lock(mutex_);
74
75 // もともと持っていたIGraphicMainクラスのインスタンスを破棄する.
76 if (graphic_main_ptr_)
77 {
78 graphic_main_ptr_.reset();
79 }
80
81 graphic_main_ptr_ = std::move(graphic_main_ptr);
82}
83
84
85bool GraphicSystem::MyDxlibInit()
86{
87 // 1部の初期化用関数はDxlib_Initを呼ぶ前に実行する必要があるのでここで実行する.
88
89 // ログ出力無しに変更.これをしないとLog.txtという邪魔なファイルが出力される.
90 SetOutApplicationLogValidFlag(FALSE);
91
92 // タイトルを変更.ウィンドウの左上に表示されるもの.
93 SetMainWindowText(GraphicConst::kWindowName);
94
95 // ウィンドウサイズを自由に変更できないようにする.
96 SetWindowSizeChangeEnableFlag(FALSE);
97
98 // ウインドウがアクティブではない状態でも処理を続行するように変更する.
99 SetAlwaysRunFlag(TRUE);
100
101 // 垂直同期信号を待たないように変更.これをしないとFPSが60固定になる.
102 SetWaitVSyncFlag(FALSE);
103
104 // ウインドウモードに変更.これをしないとフルスクリーンで表示される.
105 ChangeWindowMode(TRUE);
106
107 // DirectInputを使用するように変更.
108 // これをしないとマウス入力でサイドボタンが受け付けられない.
109 SetUseDirectInputFlag(TRUE);
110
111 // ウィンドウの横幅,縦幅,カラーを設定する.
112 SetGraphMode(setting_ptr_->window_size_x, setting_ptr_->window_size_y, GraphicConst::kColorBit);
113
114 // DX ライブラリ初期化処理.
115 if (DxLib_Init() < 0)
116 {
117 return false;
118 }
119
120 // 描画先を裏画面にする.説明が難しいが,画面のちらつきを押えてくれる効果があり,
121 // Dxlibを使う以上必須の項目.
122 SetDrawScreen(DX_SCREEN_BACK);
123
124 // 背景色の設定
126
127 // 3D関連の初期化を行う.
128 if (setting_ptr_ != nullptr && setting_ptr_->gui_display_quality == DisplayQuality::kHigh)
129 {
131 }
132 else
133 {
135 }
136
137 return true;
138}
139
140
141bool GraphicSystem::Loop()
142{
143 // [描画の処理について]
144 // ScreenFlip関数とClearDrawScreen関数の詳細:
145 // ウィンドウの画像表示はパラパラ漫画の様に画面を素早く切り替えることで,
146 // アニメーションを再現している.
147 // しかし,単に画面を切り替えた場合,本物のパラパラ漫画の様にウィンドウにちらつきがでてしまう.
148 // そこで GraphicSystem クラスの MyDxlibInit 関数の中で呼ばれている.
149 // SetDrawScreen(DX_SCREEN_BACK) によっていったん裏画面に絵を描画してから,
150 // ScreenFlip関数でウィンドウに絵を戻すことで画面のちらつきをなくしている.
151 // なお,ClearDrawScreen も ScreenFlip も ProcessMessageと返す値が同じなので,
152 // Loop関数の様な書き方となる.
153
154
155 // mutexで排他制御を行う.Main を呼ぶと同時に,
156 // GraphicMain を切り替えるとエラーが発生する可能性があるため,それを抑制する.
157 boost::mutex::scoped_lock lock(mutex_);
158
159 // GUI画面への標準出力をリセットする.
160 clsDx();
161
162 // 処理を行う.graphic_main_ptr_が false ならば,
163 // ( nullであるならば),処理を行わない.
164 if (graphic_main_ptr_ != nullptr)
165 {
166 if (!graphic_main_ptr_->Update()) { return false; }
167 }
168
169 // 描画する.
170 if (!fps_controller_.SkipDrawScene())
171 {
172 // 裏画面に描画した絵を消す.
173 if (ClearDrawScreen() < 0) { return false; }
174
175 // 描画処理を行う.graphic_main_ptr_ が false ならば( nullであるならば),
176 // 処理を行わない.
177 if (graphic_main_ptr_ != nullptr)
178 {
179 graphic_main_ptr_->Draw();
180 }
181
182 // fps_controller_.DrawFps();
183
184 // スクリーンに裏画面に描画した内容を移す.
185 if (ScreenFlip() < 0)
186 {
187 return false;
188 }
189 }
190
191 // FPS を一定に保つために待つ.
192 fps_controller_.Wait();
193
194 return true;
195}
196
197void GraphicSystem::MyDxlibFinalize() const
198{
199 // DXライブラリの終了処理を呼ぶ.
200 DxLib_End();
201
202 // ほかにも処理があればここに追記する.
203}
204
205} // namespace designlab
void Wait()
処理が早すぎる場合,FPSを一定にするために待つ.
bool SkipDrawScene()
60Hz以上のモニター使用時に処理が詰まって画面がちらつかないように, 描画処理をスキップするかどうかを判定する.
static const int kBackColorBlue
ウィンドウ背景色. 青色成分.0~255の範囲で指定.
static const int kBackColorGreen
ウィンドウ背景色. 緑色成分.0~255の範囲で指定.
static const char kWindowName[]
ウィンドウの名前.
static const int kBackColorRed
ウィンドウ背景色. 赤色成分.0~255の範囲で指定.
static const int kColorBit
色を表現するビット数.通常32で良いが軽くするなら16にする.
GraphicSystem(const std::shared_ptr< const ApplicationSettingRecord > setting_ptr)
void ChangeGraphicMain(std::unique_ptr< IGraphicMain > &&graphic_main_ptr)
グラフィックの表示を行うクラスを変更する.
void Main()
ウィンドウの表示を行う関数. boost::thread にこの関数を渡して並列処理を行う. メンバ関数の MyDxlibInit 関数に失敗した場合,終了する.
void InitDxlib3DSetting(const bool high_quality)
3D処理を行う上で必要な初期化処理をまとめたもの.