ブログ

勉強に役立つかもしれないゲームプログラミングPart4

work-731198_1920

 

皆さんこんにちは!武田塾垂水校の講師Iです。
前回は画像の変更点と画像を表示させるサンプルコード、そしてif文と関数について教えました。
(なんかやんわり教えるつもりだったのに結構ガッツリになっちゃってるんだよなあ…)
そして今回はBitBltの応用的な使い方について教えていきます!
前回のコードだとウィンドウの左上に表示するだけで終わっていたのですが、今回はこの画像を別の場所に移動させたりとか半分にしたりとか出来るようになります。
その上で前回のサンプルコードのもう少し詳しい解説も出来ればやろうかなと考えています。
では早速やっていきましょう!

プログラミングにおける鉄則とは?

ではまず前回のコードを見てみる前にプログラミングコードにおける鉄則を幾つか書いておきます。
この鉄則というのはプログラミングをするにあたって絶対守らなければいけないルールです。これを破ると勿論エラーを吐き出します。
いやそういうのは一番最初に教えろよ!と思われるかもしれませんが、すみませんすっかり忘れてました
まあ全部言っていくと何が何だか…ってなると思うのでとりあえず必要なところだけ書いていきます。

鉄則その1.データの形は揃えるべし!

いやもう早速何を言ってるのか分からん…と思っている方も多いと思いますが、データ(変数とか)にはいろんな種類があります
例えば数の中にも整数だったり小数だったり分数だったり…といろんな種類がありますよね?
そんな感じでデータにもいろんな種類があるのでデータを入れる場所にはそれ専用のスペースを空けているんです
例えば整数を1つ入れるところを作りたい、ってなったら整数を入れる変数(英語のintegerからint型と言います)を作ってそこに入れたい整数を入れる訳ですね。
でもそこに小数をぶち込んでみたとしましょう。結果どうなるかというと小数点以下が全て切り捨てられた状態で整数型に入れられます
まあこの場合は逆にそれを利用してプログラムを組むことがあったりするのですが…(エラーを吐いて止まったりはしないので)場合によってはエラーを吐いたりするので狙ってやらない限りは変数の形は揃えるようにしましょう。

鉄則その2.処理を1つ書いたらセミコロン(;のこと)を打つ!

サンプルコードを見てみると結構この記号を見かけると思いますが、これは日本語でいう「。」みたいなものです。これを付けることによって「ここまででやる処理は一旦終わりだよ」と言ってる訳ですね
これはちゃんと付けないとエラーが出ます。なので自分で作った場合セミコロンが抜けてないか気を付けましょう。
逆に一番最後なのに付けなくていいところもあるのでそれも気を付けましょう。例えばif文に付ける{}の後ろとかは付けなくていいです。

鉄則その3.順番をちゃんと守るべし!

前にも言ったことはあるかと思いますが、プログラミングには処理する順番があります。行う処理によっては少し複雑な順番になる場合もありますが、基本的には上から順番に処理を行っていきます
もし順番を逆に書いたりすると勿論思うように動かなかったりエラーが出たりします。なので順番をちゃんと守って処理を書いていきましょう。

プログラミングにおける鉄則は大体こんな感じですね。(もしかすると書き忘れているものもあるかもしれませんが…)
自分で工夫してプログラミングを書いてみる場合はこの鉄則は必ず意識しましょう。

BitBlt関数の仕組みについて

ではやっと前回のサンプルコードにあったBitBlt関数の解説をします。
前回はこんな感じに書いてましたね。

hPause = (HBITMAP)LoadImage(
NULL,
"Resource\\pause.bmp",
IMAGE_BITMAP,
0, 0,
LR_LOADFROMFILE
);

if (hPause == NULL) {
MessageBox(NULL, "画像が読み込めませんでした", "エラー", MB_OK);
return 0;
}

hMemDC = CreateCompatibleDC(NULL);

hdc = BeginPaint(hWnd, &ps);

SelectObject(hMemDC, hPause);

BitBlt(
hdc,
0, 0,
CLIENT_W, CLIENT_H,
hMemDC,
0, 0,
SRCCOPY
);

一応解説に使いそうな他の部分も書いておきました。
では早速BitBlt関数についてみていきましょう。

BitBlt(
hdc,
0, 0,
CLIENT_W, CLIENT_H,
hMemDC,
0, 0,
SRCCOPY
);

ここで関数の見方ですが、前回の記事で解説した関数の構造について少し復習しましょう。
関数には返り値と引数(ひきすう)というものを持っている関数と持ってない関数があるんでしたね?ではこのBitBlt関数を見てみましょう。
まずこのBitBlt関数に返り値はあるのでしょうか?前回の内容と照らし合わせながら見てみましょう。
前回の記事で返り値について、「返り値がないとその関数単体で使用していて、返り値があるとその関数と他のものを組み合わせる必要がある」と説明しましたね?そこでこのBitBlt関数の処理を見ていきましょう。
BitBlt関数の右に()が付いてその中に引数がごちゃごちゃ書いていますね。で、引数を入れる()の右には…セミコロン、つまり処理の終わりです。
ということは…BitBlt関数はこの関数単体で使っているので引数を持っているが返り値はない関数です。
なのでこの関数は引数だけちゃんとしたものを渡せばちゃんと動きます。お利口さんですね。

そしてついに本題!このBitBlt関数とはなんなのか!

…ググりましょう。

は?と思った方が大半だと思いますが、関数の詳細はググった方が圧倒的に早いです。それこそ定義を見て理解するとかほぼ不可能でしょうし(てか自分も出来ませんし)名前から推測する程度しかできません。
なのでググって先達がまとめている情報を見てその関数がどんな処理をしているのか見ましょう。(この記事で教える分にはここで書きますが)

ちなみにBitBlt関数とは読み込んだ画像の一部をウィンドウの中に描画する関数です。まあBit(ビット。画素のこと。)Blt(ビルト。組み立てるって感じ。)なので分かる人には何となく分かったと思います。
そこで関数の各引数の役割を重要なとこだけざっくりと見ていきましょう。

BitBlt(
hdc,         ←コピペ先
int x, int y,      ←貼り付ける範囲の左上端
int dx, int dy,     ←貼り付ける範囲の幅と高さ
hdc,         ←コピペ元
int x2, int y2,     ←コピペ元のコピーする範囲の左上端
SRCCOPY      ←追加のコマンド。これは「そのまんま貼り付ける」の意。
)

各引数の役割はこんな感じです。こうやって必要な情報を受け取って描画をしているんですね。
これを見ていろんな疑問が湧くと思いますので、ありがちな疑問について解説していきます。

なんで左上端なの?

これについては完全に予測ですが恐らく描画を始める点が左上からだからでしょうね。ペイント等で画素の座標とか見ても左上が基準ですし。
あと幅と高さを指定しているのは処理が面倒だからでしょうか。描画をするには幅と高さを出す必要があるのですが、(左上の座標-右下の座標)と計算を1つ挟むよりかは幅と高さを純粋に書き込む方が良いでしょうし。
まあこれにはいろんな予測を立てることが出来ますが1番の理由は「前からそうだったから統一した」でしょうね。
なぜそのように開発したのかは開発者に聞かないと分かりませんし自分はお手上げですね。興味があれば調べてみてください(丸投げ)

コピペ元は幅と高さはないの?

良い質問ですね。ないです
これがBitBlt関数の使いにくいところです。コピペ元の範囲は読み取りの始点のみしか指定できません。
しかも自動的に伸び縮みしたりもしません。ゴミカスですね。

SRCCOPYって何?

オプションみたいなものです。色を組み合わせたり画像を反転したりできます。
まあ基本的にSRCCOPYでいいです。興味ある人は調べてやってみてどうぞ。

とまあ大体こんな感じですね。ついでにですがBitBlt関数内にあるint型のデータ(数値を入れてるとこ)は数値をいじることが出来ます
なので範囲が狭くて画像が切れてる場合は範囲の幅と高さに入ってる数値をもっと大きくするといいです。
こんな感じで関数の引数と意味を見て自分でいろいろいじってみて使い方を学んでいくわけですね。
皆さんも是非他の数値を一通り(1個ずつ)いじってみてください。
BitBlt関数に関してはこれで以上とします。

他の関数に関して

ちょっとBitBlt関数について解説を入れたので他の関数もざっくり解説します。
他の関数にはどういうものがあるのかというと、大体名前の通りです
LoadImageは画像を読み込む処理、MessageBoxは何かのメッセージを入れておくところ(ここではエラーメッセージを表示している)、CreateCompatibleDCはフリーなDC(デバイスコンテキストってやつ。絵を描いておくとこってくらいの理解度でいい。)を作成する処理、BeginPaintは描画を始める準備、SelectObjectは描くものを選ぶ処理、みたいな感じで名前を見れば何がしたいのかざっくり分かるように先達の方々が名前を付けてくれてます。良かったですね。

これらからサンプルプログラミングコードを上から順番に読み解いていくと、画像を読み取り(読み取れなかったらエラーを吐く)空のDCを作り、描画状態に移行して空のDCに読み取った画像を入れてそれをコピペ先に貼り付ける、と言った感じの処理になります。
何が何やら…となる人もいると思いますがざっくり「コピペしてるんだなー」くらいで大丈夫です。むしろ結構な割合で細かく理解していないプログラマーもいると思います。自分とか自分とか自分とか。

関数を扱う上で大事なことは大体の処理内容と引数の内容を理解して紐づけていくことです。これと読み方をマスター出来たらもう一人前と言っても過言ではありません。読み方も今後解説していきますので頑張りましょう。

最後に

今回はBitBlt関数の細かいところを解説していきました。
本当はもっと書き込みたいことがあったのですがそれは今度似たような内容をやった時にやりたいと思います。
ここまで読んでくださりありがとうございました。

あなたに合った勉強法を教えます!

無料受験相談に行ってみる