3 / 3 非表示の原因調査と描画範囲の確認
画像が表示されないトラブルに直面した際の原因特定手法を身につけます。「画像ファイルの読み込み失敗」と「画面外への描画」を切り分ける方法、および画像全体が画面内に収まる座標の計算式を学びます。
読み込み失敗時の動作検証
プログラムを実行したときに画像が表示されない原因は、大きく分けて2通りあります。
- 画像の読み込み失敗: ファイルが存在しない、またはパスが間違っており、画像データがメモリに読み込まれていない
- 画面外への描画: 画像は正常に読み込めているが、描画位置が画面の外側にはみ出している
存在しないファイルを指定する実験
まず、意図的に読み込みエラーを発生させて、前のステップで記述したエラー処理の挙動を確かめてみましょう。
LoadGraph に渡すファイル名を一時的に Missing.png へ変更します。エラー表示との対応も確かめるため、直後の MessageBoxW のメッセージ内も同じ名前へ変更してください。
int image = LoadGraph(L"Assets/Images/Missing.png"); // 存在しないファイル名を指定
if (image == -1)
{
MessageBoxW(nullptr, L"Assets/Images/Missing.png を読み込めません。", L"画像の確認", MB_OK);
DxLib_End();
return -1;
}エラー表示と終了動作の確認
ビルドして実行すると、「Assets/Images/Missing.png を読み込めません。」というメッセージボックスが表示され、「OK」をクリックすると安全に終了することを確認できます。
このようにエラー処理を正しく組み込んでおくことで、「何が原因で停止したのか」が即座に判明します。動作を確認できたら、LoadGraph と MessageBoxW の両方のファイル名を元の Robot.png に戻してください。
相対パスと作業ディレクトリの関係
画像を探す基準フォルダ
L"Assets/Images/Robot.png" のように、特定の基準フォルダからの道筋を指定した表記を 相対パス(relative path) と呼びます。
プログラムが相対パスを探索する基準位置を 作業ディレクトリ(カレントワーキングディレクトリ) と呼びます。この配布プロジェクトをVisual Studioから実行する場合、設定により「実行ファイル(.exe)が生成されるフォルダ」が作業ディレクトリに設定されています。
ビルドが完了すると、プロジェクトフォルダの x64/Debug/ 内には CppBasics.exe と並んで Assets/ フォルダが自動配置されます。プログラムは自分と同じ階層にある Assets フォルダを起点として、その中にある Images/Robot.png を正しく見つけ出しています。
症状に応じた確認箇所
トラブルが発生した際は、症状に応じて次のポイントを確認します。
| トラブルの症状 | 考えられる原因 | 主な確認箇所 |
|---|---|---|
| 読み込みエラーのダイアログが出る | ファイルが見つからない、または破損 | パスのスペルミス、大文字小文字の違い、Assets/Images/ の配置場所 |
| エラーは出ないが画面に何も映らない | 画面外への描画、または描画サイクルの誤り | 座標変数 x, y の数値、ClearDrawScreen や ScreenFlip の呼び出し順序 |
| 古い画像や変更前のコードのまま動作する | ビルドが最新化されていない | Visual Studioでソリューションのビルド(F7)が正常終了しているか |
画面外描画と画面内収容の座標計算
次に、「画像の読み込みには成功しているが、画面の外側に描いてしまっている」状態を検証します。
画面幅を超える座標での実験
ファイル名は正しい Robot.png のままで、座標の初期値 x を 700 に書き換えて実行してみてください。
int x = 700; // 画面幅(640)を超える値
int y = 120;実行すると、エラーダイアログは一切表示されませんが、画面には何も映りません。ウィンドウの幅が 640 ピクセルであるのに対し、x=700 という右側の画面外領域に描画しているためです。
画像全体を画面内に収める座標の計算式
次に、x = 620 に変更して実行してみましょう。画像の左側20ピクセル分が画面内に入り、残りは画面外にはみ出します。
画像の描画座標 (x, y) は「画像の左上端」を指定します。そのため、幅 48 ピクセルの画像を完全に見切れることなく表示するには、画像の右端(x + 48)が画面の右端(640)以下に収まっていなければなりません。
したがって、画像全体が画面内に完全に収まる左上x座標の有効範囲は次のようになります。
同様に、画面の高さが 480 ピクセル、画像の高さが 48 ピクセルであるため、縦方向(y座標)の有効範囲は次の式で計算できます。
この計算式は、第03回でキャラクターの移動範囲を画面端で制限するロジック(境界判定)を実装する際の基礎となります。
課題:任意座標への配置と考察
画面の右下端ぴったり、または左下寄りなど、あらかじめ計算で求めた座標値を x, y に代入し、意図した通りの位置にロボットが表示されるか実験してみましょう。
- 画面の右下端ぴったりに配置する場合:
x = 592,y = 432 - 画面の左下寄りに配置する場合の例:
x = 30,y = 400
確認を終えたら、次回(第03回)の移動処理の基準位置として、初期値を元の x = 160;, y = 120; に戻してください。
- 「読み込み失敗」と「画面外描画」の症状の違いを理解し、切り分けて調査できる
- 画面サイズ(640×480)と画像サイズ(48×48)から、画像全体が収まる座標範囲(x: 0〜592、y: 0〜432)を計算できる
- 相対パスの探索基準(作業ディレクトリ)について理解している
参考実装
ここまでの手順を終えた main.cpp のコード全体です。
main.cpp の参考実装
#include <DxLib.h>
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
ChangeWindowMode(TRUE);
SetGraphMode(640, 480, 32);
SetMainWindowText(L"C++ Basics");
if (DxLib_Init() == -1)
return -1;
SetDrawScreen(DX_SCREEN_BACK);
SetBackgroundColor(245, 248, 252);
int image = LoadGraph(L"Assets/Images/Robot.png");
if (image == -1)
{
MessageBoxW(nullptr, L"Assets/Images/Robot.png を読み込めません。", L"画像の確認", MB_OK);
DxLib_End();
return -1;
}
int x = 160;
int y = 120;
while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0)
{
ClearDrawScreen();
DrawGraph(x, y, image, TRUE);
ScreenFlip();
WaitTimer(16);
}
DeleteGraph(image);
DxLib_End();
return 0;
}