目次
絵が出ない
ん~
クラスを使ったら
なぜかDXライブラリで
絵が出なくなった…
クラスを使ったら
なぜかDXライブラリで
絵が出なくなった…
絵が出ない?
LoadGraphで指定している絵は、
指定位置に存在していますか?
はい、クラスを使う前までは
出てました。今回は、
以下でクラスを利用したものを
少し改良を加えてます。
出てました。今回は、
以下でクラスを利用したものを
少し改良を加えてます。
利用したソースの元
新規プロジェクトを作成する 今回は機能を落とした「04.Anim」よりコピーして「09.ClassTest」を作成してください。 プロジェクト作成の方法は、「【簡単に新規Classをプロジェクトに追加する】」を参照[…]
以下がこちらで
改造したソースです。
コンストラクタってのを
本で見たので
それ使って初期化しました。
改造したソースです。
コンストラクタってのを
本で見たので
それ使って初期化しました。
Player.h
#pragma once
class Player
{
enum class DIR : int
{
// 使用する絵(chara_act.png)の順番に合わせておく
DOWN = 0,
LEFT,
RIGHT,
UP,
NUM,
};
public:
Player(); //< コンストラクタ(これで初期化できるらしい)
void Init(); //< 初期処理
void Update(); //< 更新処理
void Draw(); //< 描画処理
void Exit(); //< 終了処理
int SetDir( DIR dir ) { act_dir = dir; } //< 方向設定
int GetWidth() { return WIDTH; } //< 横サイズ
int GetHeight() { return HEIGHT; } //< 縦サイズ
float x, y; //< 表示座標
protected:
static const int ACT_DIR_SLIDE = 3;
static const int ACT_DIR_NUM = 4;
static const int ACT_IMG_NUM = ACT_DIR_SLIDE * ACT_DIR_NUM;
static const int WIDTH = 32;
static const int HEIGHT = 32;
static const int ACT_SPEED = 20;
int act_img[ ACT_IMG_NUM ]; //< イメージ
// 0,1,2,1 の4種類 [0~3]までにするために用意
static const int MAX_MOTION_INDEX = 4;
// アニメーション変換テーブル
const int act_motion[ MAX_MOTION_INDEX ] = { 0, 1, 2, 1, };
int act_index = 0;
int act_wait = ACT_SPEED;
DIR act_dir = DIR::DOWN;
void loadData();
void exitData();
};
Player.cpp
#include "DxLib.h"
#include "Player.h"
// コンストラクタ
Player::Player()
{
// ここですべて初期化してみる
Init();
}
// 初期処理
void Player::Init()
{
loadData();
int act_wait = ACT_SPEED;
x = 0;
y = 0;
}
//< 更新処理
void Player::Update()
{
// キー情報を取得する
int input = GetJoypadInputState( DX_INPUT_KEY_PAD1 );
// キーで移動させる
if ( input & PAD_INPUT_RIGHT )
{
x++;
act_dir = DIR::RIGHT;
}
if ( input & PAD_INPUT_LEFT )
{
x--;
act_dir = DIR::LEFT;
}
if ( input & PAD_INPUT_UP )
{
y--;
act_dir = DIR::UP;
}
if ( input & PAD_INPUT_DOWN )
{
y++;
act_dir = DIR::DOWN;
}
// アクション
if ( --act_wait <= 0 )
{
act_index++;
act_index %= MAX_MOTION_INDEX;
act_wait = ACT_SPEED;
}
}
// 描画処理
void Player::Draw()
{
int motion_index = act_motion[ act_index ];
// 自分のキャラを表示する
DrawGraph( x, y, act_img[ motion_index + (int)act_dir * ACT_DIR_SLIDE ], TRUE );
}
// 終了処理
void Player::Exit()
{
exitData();
}
void Player::loadData()
{
LoadDivGraph( "chara_act.png", ACT_IMG_NUM, ACT_DIR_SLIDE, ACT_DIR_NUM, WIDTH, HEIGHT, act_img );
}
void Player::exitData()
{
for ( int i = 0; i < ACT_IMG_NUM; i++ )
{
DeleteGraph( act_img[ i ] );
}
}
test.cpp
#include "DxLib.h"
#include "Player.h"
// プレイヤーをグローバルに配置。
// コンストラクタで自動でロード
Player player;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
//======================================================
// ウインドウ設定とDXライブラリの初期化
//======================================================
const int SCREEN_WIDTH = 800; //< スクリーン横の大きさ
const int SCREEN_HEIGHT = 600; //< スクリーン縦の大きさ
// Windowsモードにする
ChangeWindowMode(TRUE);
// 画面サイズの設定
SetGraphMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32);
// DXライブラリ初期化
if (DxLib_Init() == -1)
{
//初期化に失敗
return -1;
}
// ダブルバッファモード
SetDrawScreen(DX_SCREEN_BACK);
//======================================================
// ゲーム部分
//======================================================
//------------------------------------------------------
// ゲーム初期化部分
//------------------------------------------------------
// プレイヤーの初期処理(これはならないはず)
// player.Init();
player.x = ( SCREEN_WIDTH - player.GetWidth() ) / 2; //< 画面の中心
player.y = ( SCREEN_HEIGHT - player.GetHeight() ) / 2; //< 画面の中心
//------------------------------------------------------
// メインループ部分
//------------------------------------------------------
while (ProcessMessage() == 0)
{
//裏画面消す
ClearDrawScreen();
player.Update();
player.Draw();
//裏画面を表画面を入れ替える
ScreenFlip();
}
// プレイヤー終了
player.Exit();
//======================================================
// DXライブラリ終了とプログラム終了
//======================================================
DxLib_End();
return 0;
}
広告
作成したタイミングでコンストラクタで動くはずなので、
ロードは自動的におこなわれますよね。だからInit()はクラスを作った時に来るはず。でもなぜか表示されません…
ロードは自動的におこなわれますよね。だからInit()はクラスを作った時に来るはず。でもなぜか表示されません…
そういう場合は、
いったんデバッガーで見るのが定石ですデバッガーを使えないと
問題が起こった時に
エラーを修正できません。
いったんデバッガーで見るのが定石ですデバッガーを使えないと
問題が起こった時に
エラーを修正できません。
広告
謎1 LoadDivGraphまでちゃんと来ているのか?
ここに来てない可能性はないか調査します。
ここにきてなければ当然キャラはロードされていません。
こんな場合は、来ているかどうか知りたい位置にカーソルを置き、F9を押すか、下で指定した位置をクリックします
この赤い点はブレークポイントとよばれます。

この状態で「➤ローカルWindowsデバッガー」をクリックして実行してください。
この赤い点はブレークポイントとよばれます。


来ています!
ここで止まってます
ロードされているのに
なぜ表示されないの?
ここで止まってます
ロードされているのに
なぜ表示されないの?
ここには来ていますが、まだその行は実行してない。
進めるにはF10を押してください。
進めるにはF10を押してください。
押すと矢印がひとつ進みました!
その行が実行され
次に進んだということですね。では次に気になるのは、
この時に正しくact_imgに読み込まれているのかですね。
次に進んだということですね。では次に気になるのは、
この時に正しくact_imgに読み込まれているのかですね。
広告
謎2 LoadDivGraphでact_imgを読み込めているのか?
ここが実行されたことを確認し、act_imgにカーソルを合わせてみてください。
act_imgの中身を確認できます。
act_imgの中身を確認できます。
※-1はキャラはロードできなかったことを示します。
なんで?
キャラも存在していますよ!
キャラも存在していますよ!
では、最後にどのようにここが呼ばれたのか、
「呼び出し履歴」(コールスタック)
というものを見てみましょう。
ここから不具合になったヒントや
答えを見つけることができます。
「呼び出し履歴」(コールスタック)
というものを見てみましょう。
ここから不具合になったヒントや
答えを見つけることができます。
広告
謎3 どこから呼ばれているのか?


LoadDivGraphは、
グローバルに配置したPlayer player;
から呼ばれていたことがわかります。
グローバルに配置したPlayer player;
から呼ばれていたことがわかります。
このLoadDivGraphは、
グローバルに配置したPlayer player;
から呼ばれていたことがわかります。
グローバルに配置したPlayer player;
から呼ばれていたことがわかります。
あれ?
ここは変数とかを置くエリアでは?!
ここは変数とかを置くエリアでは?!
そうです。
配置したときに実行されるのがコンストラクタです。
よって、プログラムが走る前に来てしまっているのです。DXライブラリは、DxLib_Init()を行わないと、
LoadDivGraphは使うことができません。絵が出ない原因はここにあります。コンストラクタを
使わないようにするか、
以下の位置で
Playerを作ります。
配置したときに実行されるのがコンストラクタです。
よって、プログラムが走る前に来てしまっているのです。DXライブラリは、DxLib_Init()を行わないと、
LoadDivGraphは使うことができません。絵が出ない原因はここにあります。コンストラクタを
使わないようにするか、
以下の位置で
Playerを作ります。
test.cpp
#include "DxLib.h"
#include "Player.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
//======================================================
// ウインドウ設定とDXライブラリの初期化
//======================================================
const int SCREEN_WIDTH = 800; //< スクリーン横の大きさ
const int SCREEN_HEIGHT = 600; //< スクリーン縦の大きさ
// Windowsモードにする
ChangeWindowMode(TRUE);
// 画面サイズの設定
SetGraphMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32);
// DXライブラリ初期化
if (DxLib_Init() == -1)
{
//初期化に失敗
return -1;
}
// ダブルバッファモード
SetDrawScreen(DX_SCREEN_BACK);
//======================================================
// ゲーム部分
//======================================================
//------------------------------------------------------
// ゲーム初期化部分
//------------------------------------------------------
// プレイヤーをグローバルに配置。
// コンストラクタで自動でロード
Player player;
// プレイヤーの初期処理(これはならないはず)
// player.Init();
player.x = ( SCREEN_WIDTH - player.GetWidth() ) / 2; //< 画面の中心
player.y = ( SCREEN_HEIGHT - player.GetHeight() ) / 2; //< 画面の中心
//------------------------------------------------------
// メインループ部分
//------------------------------------------------------
while (ProcessMessage() == 0)
{
//裏画面消す
ClearDrawScreen();
player.Update();
player.Draw();
//裏画面を表画面を入れ替える
ScreenFlip();
}
// プレイヤー終了
player.Exit();
//======================================================
// DXライブラリ終了とプログラム終了
//======================================================
DxLib_End();
return 0;
}
広告
まとめ
CLASSのコンストラクタでDXライブラリのコマンドは避ける必要がある
- ブレークポイントを置くことで、プログラムが実行されているか確認できる
- ブレークポイントで止めたとき、カーソルホバーで変数の内容を確認できる。
- 呼び出し履歴より、どのようにして呼ばれたのかを確認して、不具合の答えを見つけます
以上はC++を使って「VisualStudio」で不具合を見つける基本的な方法です。
参考にしてください。
広告