Windowsゲーム「初音ミク冒険記」、遅くなる原因を特定!
ようやく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)】
このエントリーへのリンク
トラックバック
この記事へのトラックバックの一覧です: Windowsゲーム「初音ミク冒険記」、遅くなる原因を特定!:


コメント
このブログの新着コメントをRSSリーダに登録する為のxmlwin版に向けて一歩前進ですね![→◇←]
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)