1 / 3 2体目の追加と独立した座標管理
プレイヤー操作の青いロボットに加え、2体目のキャラクター(オレンジ色のロボット:Walker)を画面に配置します。リソースの段階的解放、独立した座標変数による状態管理、および描画順序による手前・奥の重なり関係を学びます。
2体目の画像読み込みとエラー処理
第03回までのコードに、2枚目のキャラクター画像 Assets/Images/Walker.png(48×48ピクセルのオレンジ色ロボット画像)を読み込む処理を追加します。
ループの前にある int y = 120; の直後に、次のコードを追加してください。
int y = 120;
int walker = LoadGraph(L"Assets/Images/Walker.png");
if (walker == -1)
{
MessageBoxW(nullptr, L"Assets/Images/Walker.png を読み込めません。", L"画像の確認", MB_OK);
DeleteGraph(image); // 既に読み込み済みの1枚目を解放
DxLib_End();
return -1;
}
int walkerX = 320;
int walkerY = 300;段階的なエラーハンドリング
2枚目の読み込みに失敗した際の if (walker == -1) ブロックに注目してください。
1枚目の画像 image はすでに正常にメモリへ読み込まれているため、プログラムを異常終了する前に DeleteGraph(image); を呼び出して1枚目のメモリを確実に解放しています。このように、複数のリソースを順次確保する場合は、「それまでに確保成功したリソースをすべて解放してから終了する」ことが安全なメモリ管理の基本です。
独立した座標変数の定義
2体目の初期位置として walkerX = 320;, walkerY = 300; を宣言・初期化しています。
プレイヤー操作の青いロボットは変数 x, y を使い、2体目のオレンジ色ロボットは変数 walkerX, walkerY を使います。完全に独立した別のメモリ領域(変数)で管理されているため、キーボード入力によって x や y が変化しても、walkerX と walkerY の値には一切影響しません。
複数画像の描画と重なり順(前後関係)
メインループの描画処理に、2体目を描くコードを追加します。
2体目の描画命令の追加
DrawGraph(x, y, image, TRUE); の直後に、次の1行を追加してください。
DrawGraph(x, y, image, TRUE);
DrawGraph(walkerX, walkerY, walker, TRUE);
ScreenFlip();画面消去と描画の順序
1フレーム内の描画サイクルは、次の順序で実行されます。
ClearDrawScreen(): 画面全体を背景色で消去(1フレームにつき1回のみ)DrawGraph(x, y, image, TRUE): 青いロボットを描画DrawGraph(walkerX, walkerY, walker, TRUE): オレンジ色のロボットを描画ScreenFlip(): 裏画面の完成形を表画面へ転送
画面の消去処理 ClearDrawScreen() は、必ずすべての描画の「前」に1度だけ行います。2体の描画の間に挟んでしまうと、先に描いた青いロボットが消去されてしまいます。
描画順序と重なり関係(ペインターズアルゴリズム)
2Dグラフィックスでは、絵の具をキャンバスに重ね塗りするように「後から描いた画像が手前(前面)」に表示されます。青いロボットをオレンジ色のロボットの位置まで移動させて重ねてみると、後から描かれたオレンジ色のロボットが手前に表示され、青いロボットが奥に隠れることが確認できます。
終了処理への解放命令の追加
メインループ終了後のリソース解放にも、2枚目の解放処理を追加します。ファイル末尾の DeleteGraph(image); の直前に、次の行を追加してください。
DeleteGraph(walker);
DeleteGraph(image);これにより、ゲームが正常終了する際にも両方の画像メモリが確実にOSへ返却されます。
画像リソースとインスタンス座標の分離
2体の位置が独立していることの確認
ビルドして実行し、画面中央やや右下にオレンジ色のロボットが表示されることを確認してください。方向キーで青いロボットを動かしても、オレンジ色のロボットはその場に静止したままです。
同じ画像を別の位置に描く実験
描画の仕組みをより深く理解するために、2体目を描くコードを一時的に次のように書き換えてみましょう。
DrawGraph(walkerX, walkerY, image, TRUE); // 第3引数を image(青ロボット)に変更実行すると、青いロボットが2体表示されます。しかし、方向キーで動くのは左上の1体だけで、(walkerX, walkerY) の位置にいる青いロボットは静止しています。
- 画像リソース(画像ハンドル): 「どのような姿・見た目か」を定義するデータ
- 座標変数(x, y): 「その姿を画面のどこに置くか」という個別の状態データ
1つの画像リソースを複数の異なる座標に使い回して描画することも可能です。「画像そのもの」と「描画位置」がプログラム上で完全に分離されていることを確認できたら、引数を元の walker に戻してください。
- 同一画面に複数の画像を正しい順序で描画できる
- 独立した変数を割り当てることで、片方の移動がもう片方に影響しない仕組みを理解している
- 後から描画した画像が手前に重なる性質(描画順と前後関係)を説明できる