合計 昨日 今日

Hiragi(GKUTH)の日常
理系大学生の日記
アバター
Hiragi(GKUTH)
 
記事: 166
登録日時: 2010年10月16日(土) 20:10
お住まい: 大阪府
日記: 日記を見る (102)
日記
- 1月 2018
龍神録2の館の機能追加その1 (10)
   2018年1月16日(火) 22:20
あけましておめでとうございました (0)
   2018年1月14日(日) 18:12

+ 7月 2017
+ 5月 2017
+ 4月 2017
+ 3月 2017
+ 1月 2017
+ 10月 2016
+ 6月 2016
+ 5月 2016
+ 3月 2016
+ 2月 2016
+ 11月 2015
+ 10月 2015
+ 9月 2015
+ 8月 2015
+ 7月 2015
+ 5月 2015
+ 4月 2015
+ 3月 2015
+ 2月 2015
+ 1月 2015
+ 11月 2014
+ 10月 2014
+ 9月 2014
+ 8月 2014
+ 7月 2014
+ 6月 2014
+ 4月 2014
+ 3月 2014
+ 2月 2014
+ 1月 2014
+ 12月 2013
+ 9月 2013
+ 8月 2013
+ 7月 2013
+ 6月 2013
+ 5月 2013
+ 4月 2013
+ 3月 2013
+ 10月 2012
+ 8月 2012
+ 7月 2012
+ 6月 2012
+ 5月 2012
+ 4月 2012
+ 11月 2010
+ 10月 2010
カテゴリー
日常
2 記事
勉強
1 記事

龍神録2の館の機能追加その1

パーマリンクby Hiragi(GKUTH) on 2018年1月16日(火) 22:20

 新しい章が出るまでちょくちょく機能追加などしていこうかと思います。
今回はゲーム内の処理時間がどのぐらいかと言うのを計測してグラフを描画してやろうというお話です。
Profilerクラスを新たに作り、開始と終了時にメンバ関数を呼ぶと任意フレーム間の平均値を取って
平均フレーム時間を棒グラフで描画してくれるというものです。Fpsクラスを参考にしました。いずれFpsクラスの機能をProfilerに内包したい...
相変わらず美しいとはいい難いソースですが...

Profiler.h
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pragma once
 
#include <list>
#include <DxLib.h>
 
class Profiler {
public:
    Profiler() : _begin(0), _end(0), _enableFlag(false) {}
    void update();
    bool draw() const;
    void begin() { _begin = GetNowHiPerformanceCount(); }
    void end() { _end = GetNowHiPerformanceCount(); }
    void setMode(bool enableFlag) { _enableFlag = enableFlag; };
 
private:
 
    std::list<double> _list;
    std::list<double> _ave;
    LONGLONG _begin, _end;
    int _counter;
    bool _enableFlag;
    const int SAMPLE_LEN = 240;
    const int AVE_LEN = 10;
 
};


Profiler.cpp
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "Profiler.h"
#include <vector>
 
void Profiler::update() {
    double differ = (double)(_end-_begin)/1000;
    int listLen = _list.size();
    int aveLen = _ave.size();
 
    _counter++;
    _ave.push_back(differ);
    if (aveLen > AVE_LEN) { //サンプル数を超えたらポップ
        _ave.pop_front();
    }
 
        //平均の長さフレーム毎に平均をとる
    if (_counter%AVE_LEN == 0) {
        double sum = 0;
        for (auto itr = _ave.begin(); itr != _ave.end(); itr++) {
            sum += *itr;
        }
        sum = sum / AVE_LEN;
 
        _list.push_back(sum);
        if (listLen > SAMPLE_LEN) { //サンプル数を超えたらポップ
            _list.pop_front();
        }
    }
}
 
 
bool Profiler::draw() const {
    if (_enableFlag != true) {
        return false;
    }
 
    int i = 0;
    int red = GetColor(255, 64, 64);
        //グラフの表示位置の設定
    const int START_X = 64, START_Y = 64;
    const int SIZE_X = SAMPLE_LEN, SIZE_Y = 128;
 
        //枠を描画
    DrawBox(START_X,START_Y,START_X + SIZE_X,START_Y + SIZE_Y, red, false);
 
        //棒グラフを描画
    for (auto itr = _list.begin(); itr != _list.end(); itr++,i++) {
        double current = *itr * 20;
        double x = START_X + SIZE_X - i;
        double y_1 = START_Y + SIZE_Y - current;
        double y_2 = START_Y + SIZE_Y;
 
        DrawLine(x, y_1, x, y_2, red);
    }
    DrawFormatString(START_X, START_Y, red, "%.2f ms", _list.back());
    return true;
}

コメント数: 10 閲覧数: 687
コメント

Re: 龍神録2の館の機能追加その1

パーマリンクby Dixq (管理人) on 2018年1月16日(火) 22:54

次章を早く作らなければ・・・ツイッターでもまだかなーってつぶやいてる人いるし・・。

変数名にFlagはおすすめしないっす。
職場でもこういう変数名が出てきたら真っ先に指摘されます。
結局Flagって何をするのか忘れたときに見返してもよくわからないのです。

setModeというメソッド名ではなく
enable();
disable();
というメソッド名にした方がより分かりやすいでしょう。
アバター
Dixq (管理人)
管理人
 
記事: 1596
登録日時: 2010年10月12日(火) 20:16
お住まい: 北海道札幌市
日記: 日記を見る (581)

Re: 龍神録2の館の機能追加その1

パーマリンクby usao on 2018年1月17日(水) 16:34

名前の付け方で気になるのは Flag 側よりもむしろ enable の側.
何の有効無効を表すフラグなのかわからない.
アバター
usao
 
記事: 1352
登録日時: 2013年5月16日(木) 11:36
日記: 日記を見る (140)

Re: 龍神録2の館の機能追加その1

パーマリンクby Dixq (管理人) on 2018年1月17日(水) 18:21

drawableかどうかを表しているようなのでそこがわかるようにしたいですね
アバター
Dixq (管理人)
管理人
 
記事: 1596
登録日時: 2010年10月12日(火) 20:16
お住まい: 北海道札幌市
日記: 日記を見る (581)

Re: 龍神録2の館の機能追加その1

パーマリンクby usao on 2018年1月17日(水) 18:36

描画したくないなら単にdraw()を呼ばなければ良いのであって
描画したいかどうかはこのクラスを使う側の都合なのだから
そもそもそんなフラグをこのクラスに持たせるのが,なんか違う感.
アバター
usao
 
記事: 1352
登録日時: 2013年5月16日(木) 11:36
日記: 日記を見る (140)

Re: 龍神録2の館の機能追加その1

パーマリンクby へにっくす on 2018年1月17日(水) 19:39

有効か無効かで色が変わるとかならわかる気がする。
無効だったら描画しないとは手抜きですな。(笑)
written by へにっくす
アバター
へにっくす
 
記事: 612
登録日時: 2012年7月01日(日) 17:32
お住まい: 埼玉県
日記: 日記を見る (170)

RE: 龍神録2の館の機能追加その1

パーマリンクby Dixq (管理人) on 2018年1月17日(水) 20:13

いや、インスタンスの所持元は一律
update
draw
は必ずやるとしてその中のステータスにより描画をdisableするのはありですよ。
むしろゲームプログラムの基本であるupdateとdrawの呼び出しを呼び出しもとが理解して管理するのはさけるべきです。
さもないとポリモーフィズムを利用した一括管理ができなくなります。
アバター
Dixq (管理人)
管理人
 
記事: 1596
登録日時: 2010年10月12日(火) 20:16
お住まい: 北海道札幌市
日記: 日記を見る (581)

Re: 龍神録2の館の機能追加その1

パーマリンクby usao on 2018年1月17日(水) 21:08

そういう共通インタフェースなのだとして…
draw()を一括コールする側にはProfilerを描画disableできるやつに包んだ状態で渡しとくとか,
あるいは,単に一旦一括コールリストから除外するとかいう方法を考えたりするんだけど,
そういうのだと無駄に面倒なのかな.
アバター
usao
 
記事: 1352
登録日時: 2013年5月16日(木) 11:36
日記: 日記を見る (140)

Re: 龍神録2の館の機能追加その1

パーマリンクby Hiragi(GKUTH) on 2018年1月18日(木) 12:06

色々指摘がありましたが、とりあえずすぐできそうな事をしてみました。
Profilerは一つ上のLooperが持ってるので、シーンと同じ深さでDrawなりUpdateなり書いてます。デバッグモード時だけ有効とか
幾つかの機能を全て内包してProfilerにするならばLooperからProfilerの各機能の有効無効を切り替えるメソッドを呼ぶことになるのでしょうか、
今後更に機能追加して、例えば計算部、描画部や、音声やエフェクト、弾など細かい所での計測を考えるのならばそれはそれでまた大幅な設計の変更が必要な気がします。
やったこと無いのでどういう風に実装するのかパッとは思いつかんのですが...

Profiler.h
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#pragma once
 
#include <list>
#include <DxLib.h>
 
class Profiler {
public:
    Profiler() : _begin(0), _end(0), _isDrawable(false) {}
    void update();
    bool draw() const;
    void begin() { _begin = GetNowHiPerformanceCount(); }
    void end() { _end = GetNowHiPerformanceCount(); }
    void disable() { _isDrawable = false; }
    void enable() { _isDrawable = true; }
 
private:
 
    std::list<double> _list;
    std::list<double> _ave;
    LONGLONG _begin, _end;
    int _counter;
    bool _isDrawable;
    const int SAMPLE_LEN = 240;
    const int AVE_LEN = 10;
 
};


Profiler.cpp
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "Profiler.h"
#include <vector>
 
void Profiler::update() {
    double differ = (double)(_end-_begin)/1000;
    int listLen = _list.size();
    int aveLen = _ave.size();
 
    _counter++;
    _ave.push_back(differ);
    if (aveLen > AVE_LEN) { //サンプル数を超えたらポップ
        _ave.pop_front();
    }
 
        //平均の長さフレーム毎に平均をとる
    if (_counter%AVE_LEN == 0) {
        double sum = 0;
        for (auto itr = _ave.begin(); itr != _ave.end(); itr++) {
            sum += *itr;
        }
        sum = sum / AVE_LEN;
 
        _list.push_back(sum);
        if (listLen > SAMPLE_LEN) { //サンプル数を超えたらポップ
            _list.pop_front();
        }
    }
}
 
 
bool Profiler::draw() const {
    if (this->_isDrawable == false) {
        return false;
    }
 
    int i = 0;
    int red = GetColor(255, 64, 64);
        //グラフの表示位置の設定
    const int START_X = 64, START_Y = 64;
    const int SIZE_X = SAMPLE_LEN, SIZE_Y = 128;
 
        //枠を描画
    DrawBox(START_X,START_Y,START_X + SIZE_X,START_Y + SIZE_Y, red, false);
 
        //棒グラフを描画
    for (auto itr = _list.begin(); itr != _list.end(); itr++,i++) {
        double current = *itr * 20;
        double x = START_X + SIZE_X - i;
        double y_1 = START_Y + SIZE_Y - current;
        double y_2 = START_Y + SIZE_Y;
 
        DrawLine(x, y_1, x, y_2, red);
    }
    DrawFormatString(START_X, START_Y, red, "%.2f ms", _list.back());
    return true;
}


Looper.cpp
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Looper::Looper() {
    Image::getIns()->load();
    Parameter parameter;
    _profiler.enable();
    _sceneStack.push(make_shared<TitleScene>(this, parameter)); //タイトルのシーンを作ってpush
}
 
/*!
@brief スタックのトップのシーンの処理をする
*/
bool Looper::loop() {
    _profiler.begin();
    Keyboard::getIns()->update();
    Pad::getIns()->update();
    _sceneStack.top()->update();    //トップスタックの更新
    _sceneStack.top()->draw();      //トップスタックの描画
    _profiler.end();
    _profiler.update();
    _profiler.draw();
    _fps.draw();
    _fps.wait();
    return true;
}
アバター
Hiragi(GKUTH)
 
記事: 166
登録日時: 2010年10月16日(土) 20:10
お住まい: 大阪府
日記: 日記を見る (102)

Re: 龍神録2の館の機能追加その1

パーマリンクby Rittai_3D on 2018年1月18日(木) 17:28

draw()がboolを返す必要ってありますかね?
return ; で十分な気がします。現時点で、戻り値を使っている訳でもなさそうですし。
何か意図があるならば申し訳ないです。

あと、update()内のfor文はrange based for を使うか、std::accumulate() を使うとシンプルに書けますよ。
初心者です
アバター
Rittai_3D
 
記事: 514
登録日時: 2012年11月24日(土) 11:40
日記: 日記を見る (68)

Re: 龍神録2の館の機能追加その1

パーマリンクby Hiragi(GKUTH) on 2018年1月18日(木) 23:13

>>Rittai_3D
なんとなく返してます。特に意図はないのですが、今後使われる可能性もないと思いますがとりあえず無いよりゃある方がいいだろとか言う脳死判断でつけました
range-based forすごい使いやすいですね、Pythonのinみたいでよい。しかしインデックスの取得に別変数が必要なのがウーンと言った感じですが
std::accumulate()もコレはコレで素晴らしい、知ってるのと知らないのでは全然違いますね...
アバター
Hiragi(GKUTH)
 
記事: 166
登録日時: 2010年10月16日(土) 20:10
お住まい: 大阪府
日記: 日記を見る (102)

オンラインデータ

登録ユーザー: みけCAT