こんにちは!武田塾垂水校の講師Iです。
一度自分が書いた記事を読み直して「なんか趣旨変わってきてないか…?」と思いました。
元々は勉強ってこういうことに役立つんだぞ、という分かりやすい例を挙げる為に書き始めたのですが…いつの間にか結構ガチな解説になっております(笑)
ブログを書くって…難しい…!
まあそんなこんなで今回も解説していくのですが…前回の記事でBitBlt関数の詳しい解説をした際にこんなことを言いました。
BitBlt関数の弱点としてコピペ元から特定の範囲だけを切り取って表示するなんてことは(条件によるが基本的に)出来ない、と書きました。ゲームプログラミングにおいてはこの性質はかなり使えません。
ですが!そんな弱点をちゃんと克服し、おまけに特定の色を透過することが出来るTransparentBlt関数という超有能関数があるのでそれの解説をします。
解説をする際に今までの復習も兼ねてやっていきますので今までの記事と照らし合わせてこの記事を見ると分かりやすいかもしれません。
では早速やっていきましょう!
今回実装する処理
今回は今までと違って出来るだけ皆にやって貰おうと思います。
なので最初に前のサンプルコードに書き足してほしい処理を書いておきます。その処理を何処にどの形で書けばいいのかを考えてみてください。
因みに今回追加するTransparentBlt以外は全てこれ以前の記事でまとめた内容を使っているのでそれらを見ながらでも構いません。
では、ここから実装してほしい処理を書きます。
・前に用意した画像とは別の画像を拡張子「.bmp」で用意すること。
・今回用意した画像を読み込む場所(HBITMAP)を作成し、前にやった方法と同じ方法で読み込むこと。
この2つの処理を自分でやってみてください。やってみてからこの記事の続きを見てください。
因みに2個目の処理を実装して実行しても結果は前回までのと何も変わらないはずなのでエラーが出なかったら多分出来てます。
答え合わせ
これを見ている人達は恐らくプログラミングの難しさに
嘆き苦しんだことだろう…(なんかの遺書風)
とまあ冗談はさておき、ここまで大分詰め込んできたので結構難しかったと思います。逆に今までの自分の記事見ただけでこれ出来た人はすごいです。もう天才です。是非プログラマーになりましょう。
では早速例の処理の解説をしていくのですが、1つ目に関しては前の記事を見たら出来ると思います。
なのでBitBlt関数の導入部分の記事(たしかPart3)を見てください。
出来るのなら画像変換が出来なかった人のために自分が画像提供出来ればよかったのですが…1分クオリティな上にここbmp貼れないんですよね(泣)
もし画像変換が出来ない場合は最悪ペイントソフトで簡単な画像(背景塗りつぶして文字書くだけとか)を作ってbmpで保存すれば簡単にbmp画像を使えます。自分もここで教える際はそうしています。(著作権とか怖いので)
では今回用意したものを読み込ませる処理を書く…というかコピペするのですが、画像を読み込む処理をしている部分はどこだったでしょう?
今までの記事を読み漁ると分かると思いますが、画像を読み込む処理をしているのはLoadImage関数です。
ですが!ここで1つ落とし穴が!というより解説入れてなかっただけですスミマセン…
誰だよ!LoadImage関数の中身はどうでもいいとか言った奴はぁ!
(Part3より)
はい私でした\(^o^)/オワタ
それはともかく。勿論落とし穴があるのでそのままコピペするだけではちゃんと動いてくれません。
ではその落とし穴は何なのか?それを今から説明していきましょう。
例えばあなたはおつかいを頼まれました。頼まれたものが覚えられないくらいの量あったのでメモをすることにしました。
ですが、メモするものがなかったらどうなりますか?当然あなたはおつかいの内容を覚えられません。
今回の落とし穴とはそういう感じのものです。データを読み込んでも、そのデータを保存しておく場所がないのです。
なので保存できるところを作ってあげる必要があるんですね。では、その保存できる場所はどうやって作るのでしょうか?
ここでLoadImage関数をもう一度見直してみましょう。
hPause = (HBITMAP)LoadImage(
NULL,
"Resource\\pause.bmp",
IMAGE_BITMAP,
0, 0,
LR_LOADFROMFILE
);
これがLoadImage関数を使ってるコードです。ここで一番最初に注目してください。
hPause = (HBITMAP)LoadImage(…);
「hPause=」という等式から始まっています。これはどういうことかというと、
「hPause=LoadImage関数の返り値」ということです。
もう答えを言ってしまいますがつまり「hPauseにLoadImageで読み込んだ画像を入れる」ということなんです。
ならhPauseに画像を入れている→hPauseが画像を保存する場所だということが分かります。
では次にhPauseはどういうものなのかを見てみましょう。
定義がLoadImage関数の少し上に書かれています。
static HBITMAP hPause;
これはstaticなHBITMAP型のhPauseという名前のデータを定義しているコードです。
ここで「staticなHBITMAP型のデータ」って何?ってなるかと思いますがここに関してはちゃんとプログラミングを学んでからで良いと思うので、これからするざっくりとした説明で分からなかったら思考放棄してください。
staticに関してはほんとにどうでもいいので先にHBITMAP型の説明をします。
HBITMAP型のデータというのは「ビットマップ画像を入れることが出来る形のデータ」ということです。そのままですね。
このシリーズの記事でも解説したとは思いますが、データには形があって(intやfloat等)その形に対応したデータしか基本的に入れることが出来ません。
なのでHBITMAP型のデータにはビットマップ画像を入れることが出来る、ってことですね。ここはまだ理解できると思います。
さあ続いてstaticの説明に入る前に少しプログラミングの仕様についてのお話をば…。(これ理解出来たら結構強いかも)
プログラミングの仕様と言うのはコード内で作ったデータは基本的に残らないというものです。
プログラミングというのはデータというおもちゃを使った遊びです。遊ぶためには様々なおもちゃをおもちゃ箱から取り出す必要があります。(まあ正確にはコピーなんですが)
鉛筆と紙を取り出して絵を描いたり戦隊モノの人形を取り出してヒーローごっこをするわけですが、みなさんも幼少期によく言われたと思います。「遊んだらおもちゃは元の場所に片付けましょう」と。
プログラミングでは遊び終わるどころか別の遊びを始める時にも今まで遊んでたおもちゃ(データのコピー)は片付け(削除し)てしまいます。結構綺麗好きなんですね。
ですがstaticなおもちゃ(データ)を使って遊んでいるとそのstaticなおもちゃだけは別の遊びを始めても残していてくれます。
まあそれでも遊び終えたら(プログラムが終了したら)staticでも消えてしまうはずですがね。
ここまでの説明を理解できた人にはこう思う人もいるんじゃないでしょうか?「ゲームだったらセーブ機能でデータを保存できるよね?」
勿論データを保存することも出来ます。データのコピーは削除されるので削除されないところにデータの内容を書けばいいだけです。
詳しいやり方に関してはここでは多分やらないと思いますが、調べてみればプログラムからテキストファイルの書き換えをする方法くらいは見つかると思うので興味がある人は是非調べてみてください。
また説明が長くなってしまいましたがHBITMAPの保存先を作るコードの続きから…
とりあえず
static HBITMAP hPause;
とHBITMAP型のデータを宣言しているので、このコードが画像の保存先を作っているコードになります。
これと画像読み込み(LoadImage関数)とエラー表示(画像読み込み直後のif文)がもう1つ必要なのでこれをコピペしましょう。
場所は元々あったコードのすぐ下くらいで大丈夫です。
そして落とし穴である名前の変更をやっていきましょう。
まず画像の保存先の作成ですが同じ名前の保存先を作ったらエラーを吐いていると思います。
なのでコピペしたコードの中にある画像の保存先の名前を変えましょう。
次にLoadImage関数の中身ですが、保存先の名前を変えるのは勿論読み込む画像の名前も変えないといけません。
ここ変えないと同じ画像が読み込まれますからね、注意してください。
そして最後にエラー文ですね。ここは別に変えなくても大丈夫なのですが、代わりに画像読み込みで何か間違えていた時に何もエラーを吐きません。訳の分からないエラーを吐かれても初心者さんが困るだけなので変えましょう。
変える部分は2ヵ所です。1つ目は保存先の名前ですね。そして2つ目は何気に困るエラーメッセージです。
今のままだと「画像が読み込めませんでした」と表示されますが、どっちの画像でエラーが出ても同じエラーメッセージが出ます。
これではどっちが間違っているのか分からないので画像の名前を詳細に書くなり適当に番号を振っておくなりしましょう。
これでやっとTransparentBlt関数を使うところまでこぎつけることが出来ましたが…
今回はここまでとします。
今までTransparentBlt関数に期待しながらながったるい答え合わせに付き合ってくれた皆さんほんとに申し訳ないです…。
ですが今からTransparentBlt関数の引数、内容、何が出来るのかを全て説明していくと文字数が5桁に到達しそうなので流石に分けることにしました。
なんならTransparentBlt関数の説明も2回くらいに分けそうですけどね…。
最後に
今回は実際に言われたとおりのコードを書くことが出来るのか、というのを試させてもらいました。
今回のコードが問題なく書けたならこの少なくてぐだぐだな説明の中しっかり理解が出来て且つ応用的な部分も予測することが出来ているので正直独学でもやっていける方だと思います。
そして解けなかった方なんですが…自分の説明不足が原因だと思うので気にしないでください。それにやはりゲーム作りのルートに沿って解説していくとやはり物事の順序がごっちゃになってしまって理解が及ばない部分も出てくると思ったので…
C言語解説シリーズ作ります!
(いやもうガチで教える気やんけ…)
C言語解説シリーズとはどういったものか軽く説明しますと、基本的に自分がCやC++、C#等を学んだ時のメモ書きみたいな内容だと思ってください。
この記事を見て分からないところがあれば解説記事を見て理解する、という流れを作れたらプログラミングの勉強も捗るかなと思ったのでこれから頑張って作ってみようと思います。
またこれから作っていくものなのでこの記事に含まれた内容が入っているとは限りませんのであしからず…。
(余程マニアックなことでもない限り書く予定ではありますが)
その他にも学生に役立ちそうなコラム系記事もちょっと書いてみようかなと思っているので(他の学生と差をつけるショートカットキー紹介、0から始めるブラインドタッチとか考えてます)そういう記事も上がっていたら是非見ていってくれると幸いです。
それではこれで終わりにしようと思います。
最後まで見ていただきありがとうございました!