ページ 11

画像が表示されない……

Posted: 2014年10月22日(水) 18:36
by しろうと!
 C++でSTGのプログラムを組んでいたら分からない事が出来たので質問させていただきます
 現在、ゲームプログラムの館のメニュー画面の作り方(C++)のプログラムとソースコードが公開されているSTGを合わせてゲームの基本部分を作ろうとしているのですが、二つのプログラムを掛け合わせて実行してみたところ、敵機、自機ともにちゃんと動き、当たり判定も存在しているのですが、肝心の自機、敵機、弾の画像が表示されずに困っています。
 このプログラムはPlayer,Enemy,Bulletのクラスにおける初期化、描画、更新を行ってくれるUnitAdminというクラスを導入しており、そのに画像を情報を書き込んでいます。
 なんとなく画像関係の初期化がうまくされていないせいだとは分かるのですが、どこにどうプログラムを追加すれば良いのでしょうか?
 ご助力の程お願いします
(なおC++に関しては未だ勉強中で、ポインタや継承などに関してなんとなくは分かるが1から組むのは苦手という状態です)

コード:

/*Unit.h*/
#ifndef DEF_Unit
#define DEF_Unit

#include "Object.h"
#include "Define.h"
class Bullet;

class Unit : public Object{
protected:

	Bullet* bullet[BULLET_MAX];

	int hit_point;

	int rapid;

public:
	virtual void Spawn(int,int,double)=0; //ユニットの出現場所を指定

	virtual void Update()=0;

	void Hit(Bullet*);

	Bullet* GetBullet(int);

	void Draw();

	void DrawHitPoint();
};

#endif

コード:

/*UnitAdmin.h*/
#ifndef DEF_UnitAdmin
#define DEF_UnitAdmin

class Unit;
class Object;
#include "define.h"

class UnitAdmin{
private:
	Unit* unit[UNIT_MAX];

	bool game_set_flag;

	int score;

	int player_graphic_handle;
	int enemy_graphic_handle;
	int bullet_graphic_handle;

public:

	UnitAdmin(char*);
	~UnitAdmin();

	bool GetGameSetFlag();

	int GetScore();

	void Game_Initialize();

	void Update();

	void Draw();

	void DrawHitPoint();

	void Judge();

	Unit* NearUnit(Object*);

};

#endif

コード:

/*Unit.cpp*/
#include "Unit.h"
#include "DxLib.h"
#include "Define.h"
#include "Bullet.h"


void Unit::Hit(Bullet* m_bullet){
	hit_point -= m_bullet->GetDamage();

	if(hit_point<0){
		exist=false;
	}
}

Bullet* Unit::GetBullet(int i){
	return bullet[i];
}

void Unit::Draw(){
	if(exist){
		DrawRotaGraph(x,y,1.0,angle+PI/2,graphic_handle,1,0);

		for(int i=0;i<BULLET_MAX;i++){
			bullet[i]->Draw();
		}
	}
}

void Unit::DrawHitPoint(){
	if(exist){
		int color;

		if(hostility_flag){
			color=GetColor(255,0,0);
		}else{
			color=GetColor(0,255,0);
		}

		DrawBox(x-10,y-20,x+10            ,y-17,GetColor(0,0,255),0);
		DrawBox(x-10,y-20,x-10+hit_point/5,y-17,color,1);
	}

コード:

/*UnitAdmin.cpp*/
#include "UnitAdmin.h"


#include <iostream>
using namespace std;

#include "DxLib.h"
#include "Player.h"
#include "Enemy.h"

#include "Bullet.h"

int handle;

UnitAdmin::UnitAdmin(char* m_key):game_set_flag(false),score(0){

	int player_graphic_handle = LoadGraph("img/p2.png",0);
	enemy_graphic_handle = LoadGraph("img/e.png",0);
	bullet_graphic_handle = LoadGraph("img/b.png",0);

	unit[0]=new Player(player_graphic_handle,bullet_graphic_handle,m_key,this);
	for(int i=1; i < UNIT_MAX;i++){
		unit[i]=new Enemy(enemy_graphic_handle,bullet_graphic_handle,this);
	}
}

UnitAdmin::~UnitAdmin(){
	for(int i=0; i < UNIT_MAX;i++){
		delete unit[i];
	}		
}

bool UnitAdmin::GetGameSetFlag(){
	return game_set_flag;
}

int UnitAdmin::GetScore(){
	return score;
}

void UnitAdmin::Game_Initialize(){
	unit[0]->Spawn(320,240,-PI/2);
}

void UnitAdmin::Update(){
	for(int i=0;i<UNIT_MAX;i++){
		unit[i]->Update();
	}

	int spawn = GetRand(UNIT_MAX-2)+1;
	int dice = GetRand(10);

	if(dice==1){
		if(!unit[spawn]->GetExist()){
			unit[spawn]->Spawn(GetRand(640),20,PI/2);
		}
	}

	if(!unit[0]->GetExist()){
		game_set_flag=true;
	}
}

void UnitAdmin::Draw(){
	for(int i=0;i<UNIT_MAX;i++){
		unit[i]->Draw();
	}
	DrawFormatString(50,50,GetColor(20,20,20),"Score:%d",score);
}

void UnitAdmin::DrawHitPoint(){
	for(int i=0;i<UNIT_MAX;i++){
		unit[i]->DrawHitPoint();
	}
}

void UnitAdmin::Judge(){
	for(int i=0;i<UNIT_MAX;i++){
		if(unit[i]->GetExist()){
			for(int b=0;b<BULLET_MAX;b++){
				if(unit[i]->GetBullet(b)->GetExist()){

					for(int t=0;t<UNIT_MAX;t++){
						if(unit[t]->GetExist()){
							
							if(unit[i]->GetHostility() != unit[t]->GetHostility()){
								
								int bullet_x = unit[i]->GetBullet(b)->GetX();
								int bullet_y = unit[i]->GetBullet(b)->GetY();
								double bullet_area = unit[i]->GetBullet(b)->GetHitArea();

								int target_x = unit[t]->GetX();
								int target_y = unit[t]->GetY();
								double target_area = unit[t]->GetHitArea();

								if((bullet_x - target_x)*(bullet_x - target_x)+(bullet_y - target_y)*(bullet_y - target_y) < (bullet_area+target_area)*(bullet_area+target_area)){
									unit[t]->Hit(unit[i]->GetBullet(b));
									unit[i]->GetBullet(b)->Hit();
									score+=20;
								}
							}

						}
					}

				}
			}
		}
	}
}

Unit* UnitAdmin::NearUnit(Object* request_object){
	Unit* return_unit = NULL;
	int range = -1;

	int request_x=request_object->GetX();
	int request_y=request_object->GetY();

	for(int i=0;i<UNIT_MAX;i++){
		if(unit[i]->GetExist()){
			if(request_object->GetHostility()!=unit[i]->GetHostility()){

				int target_x = unit[i]->GetX();
				int target_y = unit[i]->GetY();

				int tmp_range = (target_x-request_x)*(target_x-request_x) + (target_y-request_y)*(target_y-request_y);

				if(range!=-1){

					if(tmp_range<range){
						range= tmp_range;
						return_unit=unit[i];
					}

				}else{
					range=tmp_range;
					return_unit =unit[i];
				}
			}
		}
	}

	return return_unit;
}

コード:

/*Player.h*/
#ifndef DEF_PLAYER_H //二重include防止
#define DEF_PLAYER_H

#include "Unit.h"
class UnitAdmin;

class Player : public Unit{
private:
	char* key;

public:

	Player(int,int,char*,UnitAdmin*);
	
	~Player();

	void Spawn(int,int,double);

	void Update();

};
#endif 

コード:

/*Player.cpp*/
#include "DxLib.h"
#include "Player.h"
#include "Keyboard.h"
#include "UnitAdmin.h"
#include "Define.h"
#include "Bullet.h"

Player::Player( int m_unit_graphic_handle,int m_bullet_graphic_handle,char m_key[256],UnitAdmin* m_unit_admin){
	key=m_key;
	graphic_handle=m_unit_graphic_handle;
	unit_admin=m_unit_admin;

	hit_area=HIT_AREA;
	hostility_flag=false;

	for(int i=0;i<BULLET_MAX;i++){
		bullet[i]= new Bullet(m_bullet_graphic_handle,hostility_flag);
	}
}

Player::~Player(){
	for(int i=0;i<BULLET_MAX;i++){
		delete bullet[i];
	}
}

void Player::Spawn(int m_x,int m_y,double m_angle){
	x=m_x;
	y=m_y;
	angle=m_angle;

	exist=true;
	hit_point=PLAYERHITPOINT_MAX;
}
 
// 動きを計算する
void Player::Update(){

	for(int i=0;i<BULLET_MAX;i++){
		bullet[i]->Update();
	}

	if(Keyboard_Get(KEY_INPUT_UP)!=0){
		if(y>0){
			y-=5;
		}
	}
	if(Keyboard_Get(KEY_INPUT_DOWN)!=0){
		if(y<480){
			y+=5;
		}
	}
	if(Keyboard_Get(KEY_INPUT_LEFT)!=0){
		if(x>0){
			x-=5;
		}
	}
	if(Keyboard_Get(KEY_INPUT_RIGHT)!=0){
		if(x<640){
			x+=5;
		}
	}
	if (Keyboard_Get(KEY_INPUT_Z)!=0){
		rapid++;
		rapid%=RAPID_SPEED;
		if(rapid==1){
			for(int i=0;i<BULLET_MAX;i++){
				if(!bullet[i]->GetExist()){
					bullet[i]->Shot(x,y,angle);
					break;
				}
			}
		}
	}
}

コード:

/*Game.cpp*/
#include "Game.h"
#include "DxLib.h"
#include "Keyboard.h"
#include "UnitAdmin.h"

char key[256];
UnitAdmin* unit_admin = new UnitAdmin(key);
Game::Game(ISceneChanger* changer) : BaseScene(changer) {
}

//初期化
void Game::Initialize(){
	unit_admin->Game_Initialize();
	
	 mImageHandle = LoadGraph("img/bg2.png");    //画像のロード
}
   
	

//更新
void Game::Update(){
	unit_admin->Update();
	unit_admin->Judge();
    if(CheckHitKey(KEY_INPUT_ESCAPE)!=0){ //Escキーが押されていたら
        mSceneChanger->ChangeScene(eScene_Menu);//シーンをメニューに変更
    }
	
}

//描画
void Game::Draw(){
    BaseScene::Draw();//親クラスの描画メソッドを呼ぶ
	unit_admin->Draw();
	unit_admin->DrawHitPoint();
    DrawString(0, 0,"ゲーム画面です。",GetColor(255,255,255));
    DrawString(0,20,"Escキーを押すとメニュー画面に戻ります。",GetColor(255,255,255));

}

Re: 画像が表示されない……

Posted: 2014年10月22日(水) 19:56
by softya(ソフト屋)
DXLIBは初期化後でないとロードが出来ません。
インスタンスの生成が先に発生して画像がロードできていない可能性があります。

Re: 画像が表示されない……

Posted: 2014年10月23日(木) 11:56
by しろうと!
お早い対応ありがとうございます。
ということはGame.cpp内にある

コード:

UnitAdmin* unit_admin = new UnitAdmin(key);
を別の場所に移すという感じなのでしょうか?

Re: 画像が表示されない……

Posted: 2014年10月23日(木) 12:01
by softya(ソフト屋)
コンストラクタでの読み込みは全てやめて、タイミングがコントロール可能な読み込み初期化メソッドを用意すべきかと思います。

Re: 画像が表示されない……

Posted: 2014年10月23日(木) 13:46
by LL
これは私自身、だいぶ過去の経験なのであやふやな部分がありますが一つお話しを。
過去にDirectX9で簡単な物を作っていた時に初期化を司る自作メソッド
Init(){}
と言うものを作るのを省略してちょっぴりだけ楽しようかなと思い,
コンストラクタで画像などの各種読み込みをしようとして、大量のエラーに悩まされた事がありました。
学校の先生と悩み抜いた挙句たどり着いた答えが、
「コンストラクタを通っている時点でデバイスが生成されていない」
という結論でした。
コンストラクタでは何かしらの読み込みという行為はソフト屋さんのおっしゃる通り避けて、任意のタイミングで読み込みなどの初期化を行えるメソッドを用意するべきです。

流れてきにはこんな感じですかね?
例:プレイヤー

コード:

class Player{
private:
    D3DXVECTOR3 m_Pos;    //自機の座標
    int m_Hp;    //ライフとか
    //あと目的に合わせたメンバ変数
public:
    Player();    //コンストラクタ。場合によっては値の初期化ぐらいならコンストラクタで行ってもいいかもしれない(あくまで方法の一つ)
    void init();    //初期化
    void load();    //読み込み(人によってはinitに統合するのかな?今回は一メソッド一処理を意識して見たので分けてみました);
    void work();    //座標更新
    void upDate();    //座標以外の更新
    void draw();    //描画
};


Re: 画像が表示されない……

Posted: 2014年10月24日(金) 16:59
by しろうと!
なるほど……場所を変えるとかの問題ではなくてクラスを作り変える必要があるんですね
助言ありがとうございます!