GPGAのやる気を持続する開発および、研究日記

2011-09-15

[]プライオリティ描画管理 04:21

以前まではスプライト描画用の構造体を作って、その構造体を保存しておき

ソートをかけて描画するという手法をとっていたわけだが、結構メモリを消費するのと

数を増やしづらいというのがあったので、新しい手法として関数単位のソートを書くようにしてみた。

class DrawList
{
public :
	typedef void (*DrawFunc)(void* arg1, void* arg2);

	DrawList(int n) : data_(n){}
	void Clear() {
		for (unsigned int i = 0; i < data_.size(); ++i) {
			data_[i].clear();
		}
	}
	void Set(DrawFunc func, void* arg1, void* arg2, int prt) {
		Data data;
		data.func = func;
		data.arg1 = arg1;
		data.arg2 = arg2;
		data_[prt].push_back(data);
	}
	void Draw() {
		for (unsigned int i = 0; i < data_.size(); ++i) {
			std::list<Data>::iterator it = data_[i].begin();
			for (; it != data_[i].end(); ++it) {
				(it->func)(it->arg1, it->arg2);
			}
		}
	}

private :
	struct Data {
		DrawFunc func;
		void* arg1;
		void* arg2;
	};
	std::vector<std::list<Data> > data_;
};

2009-05-26

[]プログラム容量のお話 13:31

Windowsでゲームを製作するときは、プログラムの容量を考えることなどないが

携帯電話、携帯ゲーム機などでは、メモリが少ないためプログラム容量を考える必要が出てくる。


PSP開発をしているときは、STLは普通に使用しているがBoostは使おうとは思わない。

現在のプログラムであればぎりぎりBoostに耐えられるかもしれないが

これ以上の大規模ゲームとなると、モジュール分割を考える必要が出てきて面倒である。

melponmelpon 2009/05/26 14:17 Boostはバイナリが肥大化するというのは正確じゃないかなぁ。
Boost の中でもバイナリにならないライブラリ(TypeTraits とか MPL)ならいくら使っても大丈夫だろうし、自前で書いたのと同じぐらいの増加しかしないと思われるライブラリ(intrusive_ptr とか optional とか)だってあるし。
まあバイナリサイズが増えるライブラリがいっぱいあるというのは否定しないけど、全部使わないのはもったいない気がするかな。

あとBoostを使った程度でモジュール分割しないといけないようなゲームなら、遅かれ早かれ分割しないといけなくなるんじゃないかなーとか思ってみる。

GPGAGPGA 2009/05/28 14:52 TypeTraitsとかMPLはゲーム内での使いどころがわからんなぁ。
スマートポインタは検討の余地がある。optionalはたぶん使わない。

2009-04-28

[][]とらドラP! 15:25

4/30発売のとらドラP!のメインプログラムを担当しました。

PSP初&コンシューマ初のゲーム製作となります。


この日記は4/30に書こうと思ったのですが、すでにフライングでプレイで来ている人がいるため

今日書いてしまいます。


とらドラP!には様々な要素を入れました。

ゲーム本編ではアドベンチャーパート、モーションポートレート、移動マップ、AIマップ、アイテム探索

おまけ関係では、アクションゲーム、ブロック崩し、神経衰弱、泰子クロック、アルバムルーム、ミュージックルーム

その他では、メディアインストール、UMD読み込みの最適化、カスタムテーマなどなど


上記のうち、サブのプログラマの方に担当していただいたのが

移動マップ、AIマップ、アクションゲーム、神経衰弱、泰子クロックとなります。


今回、特に力を入れたのがUMD読み込みの最適化です。

メディアインストールは当初、できたらやろうという程度で、UMD読み込みでも周回プレイが快適にできるように作りました。

開発期間の1/10をUMDのロード速度向上に費やしているくらいです。

実際にプレイしてみるとわかりますが、各シーンの読み込み時間は、UMDでも1〜2秒程度になっているはずです。

モーションポートレートで2〜4秒ほどです。インストールするとこの時間が約半分になります。


シーン開始時のロードだけで考えたら、インストールする必要がほとんどないのですが

ゲーム中に表示する背景やイベントCGやキャラクターは、表示する直前に読み込みに行くため

どうしても、そこでUMDからの読み込みが発生してしまいます。

インストールをしていないと、ここで1秒前後の読み込みが発生してしまいますが

インストールをていると0.01秒程度で読み込みが完了します。

スキッププレイをすれば、その差がよく分かると思います。


なお、背景、イベントCG、キャラクターの全てが、表示する直前に読み込んでいるわけではありません。

シーンごとにメモリを管理し、シーン内の表示枚数が少ない場合はシーン開始時のロードで

データを読み込んでしまうため、表示時の読み込みは発生せずに快適にプレイすることが可能となっています。


この日記を読んでやってみたいと思った人は、トラどらP!を購入してね。

2008-09-29

[]うがー 19:07

「こんなパターン、スクリプトでやんねぇだろう」って思って

それを作らずゲームを開始したら、1分後にそれをやっている場所見つけて、うがー!

2008-02-12

[]今日から仕事開始だおー 01:13

本日から新しい仕事が始まりました。

とりあえず最初はDSで、その後PSPになるかもしれません。

新しい気持ちで取り組んで意向と思います。


最近見ているDirectXやゲーム製作に関する情報がかなり良質と思われるサイト

http://marupeke296.com/index.html

2006-09-24

[]GPGAが考えてるゲームプログラム構築(5) 18:54

さて、次はタスクの部分に入ります。

タスクベースクラスのヘッダーです。

TaskBase.h
/*!
 * @brief タスクベース
 */
class TaskBase
{
public :
    /*!
     * @brief コンストラクタ
     */
    TaskBase(DWORD ulMode, DWORD ulMaxObject);
    /*!
     * @brief デストラクタ
     */
    virtual ~TaskBase();
    /*!
     * @brief メイン処理
     */
    virtual void Task() = 0;

protected :
    /*!
     * @brief オブジェクトの作成
     *
     * @param ulIndex  オブジェクトのインデックス
     * @param ulIdno   オブジェクトのID
     * @param ulMode   オブジェクトの初期モード
     * @param pSharing 共通領域のポインタ
     *
     * @retval 0 :正常終了
     * @retval -1:異常終了
     */
    virtual long _CreateObject(DWORD ulIndex, DWORD ulIdno, DWORD ulMode, void* pSharing) = 0;
    /*!
     * @brief オブジェクトの開放
     *
     * @param ulIndex オブジェクトのインデックス
     */
    virtual void _ReleaseObject(DWORD ulIndex);
    /*!
     * @brief アクション
     */
    virtual void _Action();
    /*!
     * @brief 描画
     */
    virtual void _Draw();

protected :
    SYSTEM_DATA*    m_pSystem;              //!< システムデータ
    ObjectBase**    m_ppObject;             //!< オブジェクトのポインタ
    DWORD           m_ulMode;               //!< モード
    DWORD           m_ulMaxObject;          //!< 最大オブジェクト数
};

SYSTEM_DATAはグローバルとして使用する構造体です。


次に、タスクベースクラスのヘッダーです。

TaskBase.cpp
/*
 * @brief コンストラクタ
 */
TaskBase::TaskBase(DWORD ulMode, DWORD ulMaxObject)
{
    m_ulMode = ulMode;

    // システムデータの取得
    m_pSystem = MainSharing::GetSystemDat();

    // オブジェクトのセット
    m_ulMaxObject = ulMaxObject;
    m_ppObject = new ObjectBase*[ulMaxObject];
    for (DWORD i = 0 ; i < ulMaxObject ; i++) {
        m_ppObject[i] = NULL;
    }
}
/*
 * @brief デストラクタ
 */
TaskBase::~TaskBase()
{
    // オブジェクトの開放
    if (m_ppObject != NULL) {
        delete m_ppObject;
        m_ppObject = NULL;
    }
}
/*
 * @brief オブジェクトの開放
 */
void TaskBase::_ReleaseObject(DWORD ulIndex)
{
    if (m_ppObject[ulIndex] != NULL) {
        delete m_ppObject[ulIndex];
        m_ppObject[ulIndex] = NULL;
    }
}
/*
 * @brief アクション
 */
void TaskBase::_Action()
{
}
/*
 * @brief 描画
 */
void TaskBase::_Draw()
{
}

これでタスクベースクラスは終了です。

コンストラクタで、そのタスクの最大オブジェクト数を受け取り、その分のオブジェクト配列を生成しています。

デストラクタでは、生成したオブジェクト配列を開放するだけです。

Action関数と_Draw関数ですが、ぶっちゃけますと、無くても良かったりしますが

あると便利なので、仮想関数にしています。

2006-09-23

[]GPGAが考えてるゲームプログラム構築(4) 13:23

以前記述していた、ゲーム製作の考え方の続きです。

タイトルの背景オブジェクトです。

オブジェクトの量にもよりますが、一オブジェクトに付き一ファイルで作成していきます。

ここで言う一ファイルはcppファイルとhファイルを合わせたものを言います。

まずは、ヘッダーファイルです。

TitleBg.h

/*!
 * @brief 背景
 */
class TitleBg : public TitleBase
{
public:
    /*!
     * @brief コンストラクタ
     */
    TitleBg();
    /*!
     * @brief デストラクタ
     */
    virtual ~TitleBg();

    /*!
     * @brief モード
     */
    enum
    {
        MODE_INIT,              //!< 初期化
        MODE_DRAW,              //!< 描画
    };

    /*!
     * @brief アクション
     */
    virtual void Action();
    /*!
     * @brief 描画
     */
    virtual void Draw();
};

次にcppファイルです。

TitleBg.cpp

/*!
 * @brief コンストラクタ
 */
TitleBg::TitleBg()
{
}
/*!
 * @brief デストラクタ
 */
TitleBg::~TitleBg()
{
}
/*!
 * @brief アクション
 */
void TitleBg::Action()
{
    switch (m_ulMode){
        // 初期化処理
        case MODE_INIT :
            m_ulMode = MODE_DRAW;
            m_lXpos = 0;
            m_lYpos = 0;
            m_ulTexIndex = ・・・;
            break;

        // 描画時の処理
        case MODE_DRAW :
            break;
    }
}
/*!
 * @brief 描画
 */
void TitleBg::Draw()
{
    // 描画処理 仮にDrawImageという描画関数があった場合
    DrawImage(m_ulTexIndex, m_lXpos, m_lYpos);
}

これで終了です。

今回、背景はただ表示するだけなので、Action関数や、Draw関数内で特別な処理をしていません。