GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
fps_controller.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 "fps_controller.h"
9
10#include <cmath>
11#include <string>
12
13#include <Dxlib.h>
14
15
16namespace designlab
17{
18
19FpsController::FpsController(const int target_fps) :
20 kTargetFpsValue(target_fps),
21 kOneFrameTime(static_cast<int>(1000.0 / target_fps)),
22 kListMax(target_fps * 2),
23 need_skip_draw_screen_(false)
24{
25}
26
27
29{
30 if (!TargetFpsIsValid())
31 {
32 return;
33 }
34
35 // 待つべき時間を取得して待つ.
36 int wait_time = 0;
37
38 if (CheckNeedSkipDrawScreen(&wait_time))
39 {
40 WaitTimer(wait_time); // 取得した時間分待つ.
41 // Sleep(wait_time); // windows API版.
42
43 RegisterTime(GetNowCount()); // 現在の時刻を記録する.
44 }
45 else
46 {
47 // 時間オーバーしているので,コマ落ちの処理をする.
48
49 // このフレームは理想的な処理をしたものとして,記録する.
50 RegisterTime(time_list_.back() + kOneFrameTime);
51
52 need_skip_draw_screen_ = true; // 描画を飛ばすフラグを立てる.
53 }
54}
55
56
58{
59 if (!TargetFpsIsValid())
60 {
61 return false;
62 }
63
64 // スキップフラグが立っているならば,そのフラグを折り,シーンをスキップする.
65 if (need_skip_draw_screen_)
66 {
67 need_skip_draw_screen_ = false;
68 return true;
69 }
70
71 return false;
72}
73
75{
76 if (!TargetFpsIsValid())
77 {
78 printfDx("FPS:%dは推奨されません.(FPSの調整は行われません.)\n",
79 kTargetFpsValue);
80 return;
81 }
82
83 if (time_list_.size() < 2)
84 {
85 printfDx("計測中です.\n");
86 return;
87 }
88
89 // FPSを計算する.
90 const int duration = (time_list_.back() - time_list_.front()) /
91 static_cast<int>(time_list_.size() - 1);
92
93 printfDx("FPS:%d\n", static_cast<int>(1000.0 / duration));
94}
95
96
97void FpsController::RegisterTime(const int now_time)
98{
99 time_list_.push_back(now_time); // 現在の時刻を記憶.
100
101 if (time_list_.size() > kListMax)
102 {
103 // 器から漏れたら削除する.
104 time_list_.pop_front();
105 }
106}
107
108
109bool FpsController::CheckNeedSkipDrawScreen(int* time) const
110{
111 // 時刻を初期化.
112 (*time) = 0;
113
114 // 時刻リストが空なら,Wait時間は0秒.
115 if (time_list_.empty())
116 {
117 (*time) = 0;
118 return true;
119 }
120
121 // 実際にかかった時間を求める.
122 int actually_took_time = GetNowCount() - time_list_.back();
123
124 // 計算上かかるべき時間 - 実際にかかった時間 はすなわち待つべき時間.
125 int wait_time = kOneFrameTime - actually_took_time;
126
127 if (wait_time >= 0)
128 {
129 // 待ち時間が正の値であるとき,
130 // (つまり,かかるべき時間より実際にかかった時間が小さい時)はそのまま値を返す.
131
132 (*time) = wait_time;
133 return true;
134 }
135 else
136 {
137 // 待ち時間が負の値であるとき.
138
139 if (static_cast<int>(abs(wait_time)) < kOneFrameTime)
140 {
141 // 1フレーム以上遅れていないならば,処理を行う.
142 return false;
143 }
144 }
145
146 // どれにも引っかからなかった場合0を返す.
147 (*time) = 0;
148 return true;
149}
150
151
152bool FpsController::TargetFpsIsValid() const
153{
154 // マイナスの値は許容しない.
155 if (kTargetFpsValue <= 0)
156 {
157 return false;
158 }
159
160 // 1秒間に1フレーム以上は許容しない.
161 if (kTargetFpsValue > 60)
162 {
163 return false;
164 }
165
166 return true;
167}
168
169} // namespace designlab
void Wait()
処理が早すぎる場合,FPSを一定にするために待つ.
bool SkipDrawScene()
60Hz以上のモニター使用時に処理が詰まって画面がちらつかないように, 描画処理をスキップするかどうかを判定する.