« Windowsゲーム「初音ミク冒険記」、GameBoosterで起動してみたが | トップページ | Windowsゲーム「初音ミク冒険記」、フォントハンドル対応 »

2012.03.10

Windowsゲーム「初音ミク冒険記」、遅くなる原因を特定!

| |コメント (10)|トラックバック (0)

 このエントリーをはてなブックマークに追加

ようやくPSP版より遅くなる原因を特定できた!

Windows版の最初のバージョンは
3月9日ミクの日に公開できたらイイな
と思っていたのだが
この遅い原因が分からなかったりなど
いろんな問題があって実現出来なかった。

さて、本題の遅くなる原因だが
SetFontSizeとChangeFontTypeが遅いことが分かった。

具体的には、上記2つの関数は実行するだけで
それぞれ3~5ミリ秒持っていくみたいだ。

「初音ミク冒険記」の文字表示では
タイトル画面のHIT ANY BUTTONを除き
一つも画像文字を使わず
全てDrawString系で描画している。

つまり画面内でフォントサイズが異なる文字
エッジがあったり、なかったりが混ざると
フォントを切り替える時に、
必ず上記の2つの命令を実行しているのだ。

タイトル画面だけ1ループにかかる時間が
PSP版と同じだったのは、画像文字を使っているためだ。

メニュー系の場合、右上の「メニュー名称の文字」
「メニュー項目の文字」、「メニュー説明の吹き出しの文字」
と3種類のフォントを使っている。

これがゲーム本編だと
左上のミクのステータスや発動スキル名、
ダメージ数字の文字、シナリオ関係の文字など
文字のフォントサイズやエッジが異なるものが
メニュー系と比べて多くなる。

多いということは、それだけ何度も先の2関数を
セットで呼び出す内部関数setFontSizeAndTypeを
呼びまくっているわけで・・・そりゃあ遅くなるよね。

試しにsetFontSizeAndTypeに書かれている
SetFontSizeとChangeFontTypeをコメントアウトして
実行してみたところ、1ループにかかる時間は
PSP版と同じくらいになった。

かげさんが思いついた対処方法は
画像文字にすることくらいだったのだが
新・C言語~ゲームプログラミングの館」の
55. 文字のサイズや太さを変更する
によると
・CreateFontToHandle
・DrawStringToHandle
・DrawStringToHandle
を使うと回避できるっぽい。

シナリオ部分とか、アイテムやスキルの説明とかは
画像文字を作るのは現実的じゃないし
数字やゲームオーバーとかの固定文字列以外は
画像文字を作るのも大変なので
回避方法があるのはありがたい。

サンプルソースにはDeleteFontToHandleが
書かれていない。
たぶん、終了処理でDeleteFontToHandleを使わないと
メモリリークすると思うので注意することにしよう。

ちなみにCreateFontToHandleだけ
文字コードの引数があるため
本家互換じゃないけど
DXライブラリPortableにも関連関数があったみたいだ。
気づかなかったぜぃ。


 このエントリーをはてなブックマークに追加

| |コメント (10)|トラックバック (0)

このエントリーへのリンク

このエントリーのリンクを入れるHTML:

トラックバック

この記事へのトラックバックの一覧です: Windowsゲーム「初音ミク冒険記」、遅くなる原因を特定!:

コメント

このブログの新着コメントをRSSリーダに登録する為のxml

win版に向けて一歩前進ですね![→◇←]


win版の大きさってどれくらいのサイズなんでしょうか?
1.5Mの貧弱回線なので・・・

投稿者: satoshifukusima (2012/03/10 18:05:58)

To:satoshifukusimaさん
> win版に向けて一歩前進ですね![→◇←]

ええ、少しずつ進んでますよぉ[・_←]

> win版の大きさってどれくらいのサイズなんでしょうか?
> 1.5Mの貧弱回線なので・・・

現時点で圧縮して24.1メガくらいです。
2章を作り始めるとBGMが増えるので
もっと容量は増えると思いますが。

投稿者: かげさん (2012/03/10 18:57:12)

おおー解決しましたか!おめでとうございます。
意外にフォントの処理は重いんですねえ。
GameBooster、使っていただけたようですね。
スペックの問題でなくてよかったです[汗]

僕は思うように処理が書けなさすぎて
行き詰っています[冷や汗]
もう一度基礎を読み直そうと思いました[→_←]

投稿者: ななしあ (2012/03/10 19:32:38)

To:ななしあさん
> おおー解決しましたか!おめでとうございます。

解決できそうで良かったです![・_←]

> 意外にフォントの処理は重いんですねえ。

そのようです。
PSP版の時は影響なかったんですけどねぇ。

> GameBooster、使っていただけたようですね。
> スペックの問題でなくてよかったです[汗]

GameBooster、効果がありましたよ。
パソコンゲームをする時に使おうと思います。

PSPよりスペックの良いはずのパソコンで
遅いというのは納得できなかったのですが
何とか解決できそうです。

> 僕は思うように処理が書けなさすぎて
> 行き詰っています[冷や汗]
> もう一度基礎を読み直そうと思いました[→_←]

実際に動くソースを少しずつ改造しながら
どの処理が何をやっているのか
つかんでいくと覚えが早いかもしれません。

基礎からというのであれば
かげさんも全部見たわけじゃないですけど
C言語だと「ミクと学ぶC言語」という
25回ものの動画がありましたよ。
http://www.nicovideo.jp/mylist/11224473

Hello Worldからポインタまで扱っているみたいです。

環境はBCCみたいですが、C言語なので
Visual Studio 2008 C++ Express Edition
でも問題なく学習できると思いますよ。

投稿者: かげさん (2012/03/10 23:55:08)

>実際に動くソースを少しずつ改造しながら
どの処理が何をやっているのか
つかんでいくと覚えが早いかもしれません。

正しいソース(ゲームプログラミングの館さんの)
を見て少しずつ試していきます!

>基礎からというのであれば
かげさんも全部見たわけじゃないですけど
C言語だと「ミクと学ぶC言語」という
25回ものの動画がありましたよ。

その動画、前に見ました!
第5回くらいで挫折した覚えが[冷や汗]
(確か中2で見て訳が分からなかった)

とりあえず第1回からもう一回入門してきます[→◇←]

投稿者: ななしあ (2012/03/11 23:56:38)

To:ななしあさん
> 正しいソース(ゲームプログラミングの館さんの)
> を見て少しずつ試していきます!

実は、かげさんもゲームプログラミングの館で
勉強していたりします。
全部をガッチリ見たわけじゃないのですが
とりあえず流れが分かれば、なんとかなるかと。

> 第5回くらいで挫折した覚えが[冷や汗]

第5回というとifのところですか。
基本的にifとforあたりが分かれば
結構いろいろなことが書けると思う。

構造化プログラミングの基本要素
・順次(プログラムは上から下に流れるよ)
・反復(同じ事をするなら繰り返す良いよね)
・選択(条件によって動作を切り分けよう)
というのがあるんですが
ifは選択(switchも選択です)、
forは反復(whileも反復です)
になります。

ifは
もしもxxだったらyyする
そうでなかったらzzする
ということをする時に使います。
そうでなかったらというのがelseです。

初音ミク冒険記だと
もしミクのHPが0以下だったらゲームオーバー
if(hp <= 0){
 ゲームオーバー
}
みたいな感じですね。

複雑なのだと音符がゆらゆら揺れるところの
if(noteAnime < 12){
noteRotate = PIE/6;
}else if(noteAnime < 24){
noteRotate = 0;
}else if(noteAnime < 36){
noteRotate = 0 - PIE/6;
}else if(noteAnime < 48){
noteRotate = 0;
}else if(noteAnime < 60){
noteRotate = PIE/6;
}
なんてのがあったりして。

> とりあえず第1回からもう一回入門してきます[→◇←]

ミクのC言語のやつだと
10回くらいまで分かるとプログラムの流れが
理解しやすくなりますよ。

投稿者: かげさん (2012/03/12 22:50:47)

理解できてるかテストです。

>複雑なのだと音符がゆらゆら揺れるところの
if(noteAnime < 12){
noteRotate = PIE/6;
}else if(noteAnime < 24){
noteRotate = 0;
}else if(noteAnime < 36){
noteRotate = 0 - PIE/6;
}else if(noteAnime < 48){
noteRotate = 0;
}else if(noteAnime < 60){
noteRotate = PIE/6;
}

最初はnoteAnimeが12未満の時,
24未満,36未満,48未満,60未満の順になっていて、
noteRotateにPIE/6や0を代入をしている…って感じですかね?

多分ソースの続きではnoteRotateという変数の値に応じて傾きを制御しているはずです。

if文は何とか理解ができているような状態にまで来られました。
while文はたしか
while () で、この()←内に処理を書く、であってますよね?

投稿者: ななしあ (2012/03/12 23:47:44)

To:ななしあさん
> 理解できてるかテストです。
<中略>
> 最初はnoteAnimeが12未満の時,
> 24未満,36未満,48未満,60未満の順になっていて、
> noteRotateにPIE/6や0を代入をしている…って感じですかね?
> 多分ソースの続きではnoteRotateという変数の
> 値に応じて傾きを制御しているはずです。

そうです。[・_←]

> if文は何とか理解ができているような状態にまで来られました。

一歩前進ですね![→◇←]

> while文はたしか
> while () で、この()←内に処理を書く、であってますよね?

()でなく{}であればその通りです。

繰り返しにはfor文のように
指定回数繰り返すタイプと
ある条件を満たすまで繰り返すwihleみたいなタイプがあります。

条件の書き方はwihleの場合
「○○の間中」という感じの繰り返しです。
C言語系の文法は共通なのでC++とかJavaとかでも同じ考え方です。

VBなど言語によってはuntil(○○になるまで)というのもありますが。

ゲームのメインループにある
while(ProcessMessage() != -1)
を例にすると
ProcessMessageはゲームを終了すべき時に-1を返すので
-1じゃない間中、繰り返すとなります。

初音ミク冒険記だと
他にはファイルの読み込み処理(myTxtLoad)で
whileを使っています。

ファイルを読み込める間中繰り返す
という使い方をしていますよ[・_←]

投稿者: かげさん (2012/03/13 20:05:23)

動画少しずつ見て勉強しています!
前回書いた中にちょっと間違って
書いたところがありました。

while()のカッコ内にループを抜ける条件を書く
ということでしたね。(処理を書くのは{}ないでした)

キー入力処理を理解しようとしています。
char型とかなんぞ!とか思ってます[汗]
頑張ります!

投稿者: ななしあ (2012/03/14 0:06:48)

To:ななしあさん
> 動画少しずつ見て勉強しています!

少しずつ覚えていきましょう![・_←]

> 前回書いた中にちょっと間違って
> 書いたところがありました。
> while()のカッコ内にループを抜ける条件を書く
> いうことでしたね。(処理を書くのは{}ないでした)

処理を書くのは{}ブロックで
()はループを続ける条件です。

VBだと「○○まで」という終了条件ですが、
C言語だと「○○の間中」繰り返すになります。

> キー入力処理を理解しようとしています。

入力ができると楽しくなってきますし
良いのではないでしょうか。

> char型とかなんぞ!とか思ってます[汗]

char型は、1バイトの文字を格納できる型です。
通常、文字列(複数の文字)を格納する時は
char型の配列(連続した領域)を使います。
日本語の1文字を入れる場合、全角文字ですので
最低でも2バイト必要になります。

SJISという文字コードだと日本語文字は2バイト、
UTF-8という文字コードだと日本語文字は3バイト
と文字コードによって格納に必要な配列サイズは変わってきます。[ ̄∀ ̄]

> 頑張ります!

少しずつ頑張って覚えていきましょう![・_←]

投稿者: かげさん (2012/03/14 22:15:32)




←名前とメールアドレスは必須です。
URLも記入すれば、URLのみが公開されます。
メールアドレスのみですと、メールアドレスが公開されてしまいますので、御注意ください。

↓コメント本文では、「a href」「b」「i」「br/」「p」「strong」「em」「ul」「ol」「li」「blockquote」「pre」のタグが使えます。絵文字をクリックすると、本文にタグを挿入できます。