ARPGのようなものを作っています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kei_sasaki2
記事: 17
登録日時: 5年前
住所: 北海道

ARPGのようなものを作っています。

#1

投稿記事 by kei_sasaki2 » 5年前

はじめまして、KEIといいます。
C++についてはほとんど初学者でロベール本を300ページ読み終えた程度です。
もしよかったら質問させて下さい。

ARPGのようなものをDxLibraryを用いて作ろうとしています。
マップ表示は何とかできてキャラクター表示も何とかできたのですが、
自プレイヤーに関する処理をクラス化しようとしたところでキャラが表示されなくなり困りました。
どの部分に問題があるのかわからないという次第です。

本当に汚くて無駄の多いコードですがもしよければお願いいたします・・・。

コード:


#include "DxLib.h"

//初期化
int Key[256]; // 全キーの押されているフレーム数を格納
int Map_Image[2]; // マップイメージ
int map[15][20] = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

// プレイヤーキャラ
class Player {
public:
	int x, y; // 座標
	int Image[16]; // イメージ
	Player();
	Player(int xx, int yy);
	void Draw();
	void Calc();
};
Player::Player()	{ int x = 320, y = 240; } // 引数なしならこの座標
Player::Player(int xx, int yy) { int x = xx, y = yy; }

void Player::Draw() {
	DrawGraph(x, y, Image[0], TRUE); //主人公の描画
}
void Player::Calc() { //計算フェーズ
	//キャラクターアップデート
	if (Key[KEY_INPUT_RIGHT] >= 1){
	x += 2;
	}
	if (Key[KEY_INPUT_DOWN] >= 1){
	y += 2;
	}
	if (Key[KEY_INPUT_LEFT] >= 1){
	x -= 2;
	}
	if (Key[KEY_INPUT_UP] >= 1){
	y -= 2;
	}
}

// キーの入力状態を更新する
int gpUpdateKey(){
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i<256; i++){
		if (tmpKey[i] != 0){ // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

void gpDraw(){ //描画フェーズ
	int i, j;
	//マップの描画
	for (i = 0; i < 20; i++) {
		for (j = 0; j < 15; j++){
			DrawGraph(i*32, j*32, Map_Image[map[j][i]], TRUE); //マップの描画
		}
	}
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	//初期化
	SetGraphMode(640, 480, 16);
	SetMainWindowText("test");
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);
	
	Player myself;
	LoadDivGraph("img/actor00.png", 12, 3, 4, 32, 32, myself.Image);
	LoadDivGraph("img/map00.png", 2, 2, 1, 32, 32, Map_Image);

	// メインループ
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0){
		myself.Calc();
		gpDraw();
		myself.Draw();
	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
}


Rittai_3D
記事: 525
登録日時: 7年前

Re: ARPGのようなものを作っています。

#2

投稿記事 by Rittai_3D » 5年前

変数の寿命についての理解はされていますか?
一度確認してみてください。 http://www7b.biglobe.ne.jp/~robe/cpphtm ... 01068.html

コンストラクタ内で行っている

コード:

Player::Player()    { int x = 320, y = 240; } // 引数なしならこの座標
Player::Player(int xx, int yy) { int x = xx, y = yy; }
は無意味です。 int x = 320, y = 240; の変数x,yはそのブロックで有効です。メンバ変数のx,yとは一切無関係です。
また、プレイヤーの描画を行っている部分に初期化されていないメンバ変数のx,yが使用されているので表示されないのは当然です。

コンストラクタ内の変数を this->x = 320, this->y = 240; とするか、http://wisdom.sakura.ne.jp/programming/cpp/cpp15.html
x = 320, y = 240; と何も付けないか、
初期化リストを使用しましょう。http://www.geocities.jp/bleis_tift/cpp/init.html
オフトピック
せっかくクラス化するのならばメンバ変数はprivateにした方がカプセル化が進んで良いと思います。
初心者です

kei_sasaki2
記事: 17
登録日時: 5年前
住所: 北海道

Re: ARPGのようなものを作っています。

#3

投稿記事 by kei_sasaki2 » 5年前

>Rittai 3Dさん
早いお返事、本当にありがとうございます。
お陰様でコンストラクタの中でintをつけなければthis->と同等だと知ることが出来ました。
intをつけてもthis->と同じ処理になるのだと思っていましたので、本当に助かりました。
善意で回答して頂けるありがたみをとても感じている次第でございます・・。。

無事に動作しまして、次はキャラ画像の向きや当たり判定などを頑張ってみようと思っています。

ところで、例えばキャラを複数、オブジェクトで生成して移動処理や描画処理等を行う場合、
オブジェクトを配列にして処理をする方法を思いついたのですが(このサイトのSTG講座でも似たような処理をしていますが、)、
これよりも一般的に良いとされている方法があったりしますでしょうか。


一応、解決後のコードも貼り付けさせて頂きます。

コード:

#include "DxLib.h"

//初期化
int Key[256]; // 全キーの押されているフレーム数を格納
int Map_Image[2]; // マップイメージ
int map[15][20] = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

// プレイヤーキャラ
class Player {
private:
	int x, y; // 座標
	char* img_src = "img/actor00.png"; // イメージのファイル
	int Image[16]; // イメージ
public:
	Player();
	void Draw();
	void Calc();
};

//コンストラクタ
Player::Player() {
	x = 320, y = 240;
	LoadDivGraph(img_src, 12, 3, 4, 32, 32, Image);
}

void Player::Draw() {
	DrawGraph(x, y, Image[0], TRUE); //主人公の描画
}
void Player::Calc() { //計算フェーズ
	//キャラクターアップデート
	if (Key[KEY_INPUT_RIGHT] >= 1){
	x += 2;
	}
	if (Key[KEY_INPUT_DOWN] >= 1){
	y += 2;
	}
	if (Key[KEY_INPUT_LEFT] >= 1){
	x -= 2;
	}
	if (Key[KEY_INPUT_UP] >= 1){
	y -= 2;
	}
}

// キーの入力状態を更新する
int gpUpdateKey(){
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i<256; i++){
		if (tmpKey[i] != 0){ // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

void gpDraw(){ //描画フェーズ
	int i, j;
	//マップの描画
	for (i = 0; i < 20; i++) {
		for (j = 0; j < 15; j++){
			DrawGraph(i*32, j*32, Map_Image[map[j][i]], TRUE); //マップの描画
		}
	}
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	//初期化
	SetGraphMode(640, 480, 16);
	SetMainWindowText("test");
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);
	
	Player myself;
	LoadDivGraph("img/map00.png", 2, 2, 1, 32, 32, Map_Image);

	// メインループ
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0){
		myself.Calc();
		gpDraw();
		myself.Draw();
	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
}


Rittai_3D
記事: 525
登録日時: 7年前

Re: ARPGのようなものを作っています。

#4

投稿記事 by Rittai_3D » 5年前

一般的かどうかは分かりませんが、配列で良いと思います。
ただ、配列ですと、思わぬミス(範囲外アクセスなど)を起こす場合がありますので、STLのstd::list<>,std::vector<>などを使用したほうが安全です。

また、このコードはコンパイルが通らないと思いますが、本当に解決されたのでしょうか?
#追記 すいません。ideoneで実験したところコンパイルが通りました。勘違いしておりました。
適当なことを言ってしまい、申し訳ありませんでした。
https://ideone.com/1geiYO実験用のコード。
オフトピック
あまり関係ないのですが、マップの配列はconstをつけて変更できなくした方がよいと思います。
また、マジックナンバーがあちこちにあってコードが分かりづらいです。参考→http://itpro.nikkeibp.co.jp/article/COL ... 20/279836/
さらに、gpDraw()が何をするのかがぱっと見で分かりづらいです。Drawがついているから描画だろうという部分は分かりますが、gpがいまいち分からないです。マップの描画ならMapDraw()などと分かりやすい名前をつけましょう。
初心者です

kei_sasaki2
記事: 17
登録日時: 5年前
住所: 北海道

Re: ARPGのようなものを作っています。

#5

投稿記事 by kei_sasaki2 » 5年前

>Rittai 3Dさん
お返事ありがとうございます。

なるほど、双方向リストクラスというものがあるんですね。
まだ学習していない範囲でしたので、学習して試してみようと思います。

>コンパイルが通らない
コンパイルが出来て予想通りの挙動でしたので気に留めていませんでしたが、
何かコードにまだ重大な問題があったでしょうか。
もしよければ教えて頂けると幸いです。

マジックナンバー、関数名などにつきましても、訂正していこうと思います。

ありがとうございますm(_ _)m

Rittai_3D
記事: 525
登録日時: 7年前

Re: ARPGのようなものを作っています。

#6

投稿記事 by Rittai_3D » 5年前

いえ、コンパイルが通らないはわたしの勘違いでした。ideoneでコンパイルが通るのを確認しました。

コード:

class C
{
   char* str = "sample";
};
のように宣言と同時に代入を行って怒られた記憶がありましたので、コンパイルが通らないと勘違いしました。

コード:

 LoadDivGraph(img_src, 12, 3, 4, 32, 32, Image);
の部分ですが、ファイル名が変わらないのなら、メンバ変数である必要はないと思います。
初心者です

kei_sasaki2
記事: 17
登録日時: 5年前
住所: 北海道

Re: ARPGのようなものを作っています。

#7

投稿記事 by kei_sasaki2 » 5年前

>Rittai 3Dさん
お返事ありがとうございます。

成程、そういうことでしたか。
いえ、細かい部分までご丁寧に指摘して頂き嬉しい限りです。

>ファイル名が変わらないのなら~
このコードですとファイル名固定になっていますが、
のちのちプレイヤーキャラが増えたときのために、メンバ変数としてみている感じでした。

閉鎖

“C言語何でも質問掲示板” へ戻る