画像の重なり?について教えて下さい。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ムンバ

画像の重なり?について教えて下さい。

#1

投稿記事 by ムンバ » 16年前

こんばんは。お世話になります。<_ _>

---ここから雑談---

C言語の基礎の勉強はしたのですが、なかなか全部は覚えられませんでした。(涙
ですがっ!けどC言語でゲームを作りたいので、おとといからゲームにも挑戦してしまいました。^^;
これからはゲームを作りながら参考書や、こちらのサイトやその他の参考サイトを参考に
頭の足りない所を、できるだけ埋めて行きたいと思います。

以前、質問させて頂いた時に、とある方にご指導頂いた(ご指導ありがとうございました。)

・じゃんけんゲームのような簡単な遊びをするゲーム
・簡単なアクションゲーム
・チャットをするソフト

私が作りたいゲームの勉強方法を、上記の様にご指導頂きました。
もちろん私の作りたいゲームができなくても、自爆なのでお気にされないで下さい。
自分が作りたいゲームに向かって、勉強してみます。<俺の、青春かい?w

---ここまで雑談(謝---

パソコンと、じゃんけんをするゲームを作ってます。
勝ち負けの判定は、まだです。

キーボードの「1」を押すと、自分は「グー」
キーボードの「2」を押すと、自分は「チョキ」
キーボードの「3」を押すと、自分は「パー」

1~3のキーを押すと
PCはランダムに「グー・チョキ・パー」の何れかを表示します。
#include "DxLib.h"

#define HAIKEI "img/haikei001.jpg" //背景画像
#define JYANxITI 315

/* 自分側のじゃんけん画像 */
#define MYGOO   "img/goo.png"
#define MYTYOKI "img/tyoki.png"
#define MYPAA   "img/paa.png"

/* PC側のじゃんけん画像 */
#define PCGOO   "img/goo2.png"
#define PCTYOKI "img/tyoki2.png"
#define PCPAA   "img/paa2.png"

char keybuf[256];
int mynum, pc_rand, pcnum; //mynum pcnum は勝ち負けの判定に使う予定

void myjyan();
void pcjyan();

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	ChangeWindowMode(TRUE); //ウィンドウモードに変更する関数
	if (DxLib_Init() == -1) //初期化処理する関数
		return -1;

	LoadGraphScreen(0, 0, HAIKEI, FALSE); //#define HAIKEI 背景画像
	DrawFormatString(520, 463, GetColor(100, 100, 255), "%s", "ムンじゃんけん"); //タイトル表示

	while (1){
		GetHitKeyStateAll(keybuf); //すべてのキーの状態を得る
		if (keybuf[KEY_INPUT_ESCAPE] == 1) //Escキー押すと終了
			break;
		if (ProcessMessage() == -1) //エラーが起きたら終了
			break;

		myjyan(); //自分じゃんけん関数

		pcjyan(); //PCじゃんけん関数
	}

	DxLib_End(); //終了処理をする関数
	return 0;
}

void myjyan() //自分じゃんけん関数
{
	if (keybuf[KEY_INPUT_1] == 1){
		LoadGraphScreen(JYANxITI, 390, MYGOO, TRUE); //数字1で自分グー画像
		DrawFormatString(JYANxITI, 463, GetColor(100, 100, 255), "%s", "グー"); //自分グー表示
		mynum = 1; //勝ち負け判定予定の変数

	} else if (keybuf[KEY_INPUT_2] == 1){
		LoadGraphScreen(JYANxITI, 390, MYTYOKI, TRUE); //数字2で自分チョキ画像
		DrawFormatString((JYANxITI - 10), 463, GetColor(100, 100, 255), "%s", "チョキ"); //自分チョキ表示
		mynum = 2; //勝ち負け判定予定の変数

	} else if (keybuf[KEY_INPUT_3] == 1){
		LoadGraphScreen(JYANxITI, 390, MYPAA, TRUE); //数字3で自分パー画像
		DrawFormatString(JYANxITI, 463, GetColor(100, 100, 255), "%s", "パー"); //自分パー表示
		mynum = 3; //勝ち負け判定予定の変数
	}
}

void pcjyan() //PCじゃんけん関数
{
	if (keybuf[KEY_INPUT_1] == 1 || keybuf[KEY_INPUT_2] == 1 || keybuf[KEY_INPUT_3] == 1){

		pc_rand = GetRand(2); //PCじゃんけんランダム
		Sleep(300); //押しっぱなし対策(1/600秒間)

		if (pc_rand == 0){
			LoadGraphScreen(JYANxITI, 250, PCGOO, TRUE); //PCグー画像
			pcnum = 1; //勝ち負け判定予定の変数

		}else if (pc_rand == 1){
			LoadGraphScreen(JYANxITI, 250, PCTYOKI, TRUE); //PCチョキ画像
			pcnum = 2; //勝ち負け判定予定の変数

		}else if (pc_rand == 2){
			LoadGraphScreen(JYANxITI, 250, PCPAA, TRUE); //PCパー画像
			pcnum = 3; //勝ち負け判定予定の変数
		}
	}
}
このプログラムを実行して、「1」「2」「3」の何れかの数字をキーボードから入力して
じゃんけんをするのですが、じゃんけんを繰り返すと
自分側の画像も、PC側の画像も重なって表示されてしまいます。
「グー」「チョキ」「パー」の文字も重なります。

2回目以降に、じゃんけんをした時に、画像が重ならない様にしたいのです。
どの様に対処したらいいでしょうか?
ご指導の程お願い致します。

修正・追加<_ _>
 ライブラリ:DXライブラリ
 PC:Windows VISTA
 開発環境:VC++ 2008

木霊

Re:画像の重なり?について教えて下さい。

#2

投稿記事 by 木霊 » 16年前

 ScreenFlip ()とClearDrawScreen ()の2つを呼んでいないからではないですか?
 ループ内でこの2つを呼ぶようにしてください。
 詳しい使い方はDXライブラリのリファレンスを見てくださいね。

 あとは、グローバル変数を使わないようにしてください。
 各関数をvoidではなくintにして返り値で「どの手を出したか」を返せばできると思います。
 

ムンバ

Re:画像の重なり?について教えて下さい。

#3

投稿記事 by ムンバ » 16年前

木霊さん、早速のご解説どうもありがとうございます。

>ScreenFlip ()とClearDrawScreen ()の2つ
「ゲームプログラミングの館」の 13a. 裏画面処理をして画像を動かす
もう一度、読み直してみます。

>DXライブラリのリファレンス
 ありがとうございます。見てみます。

>あとは、グローバル変数を使わないようにしてください。
 関数に void を使ったのは・・・。(汗
 
ごめんなさい。
今日は寝てしまいますが、明日の夜に勉強再開します。
すみません。(謝

SCI

Re:画像の重なり?について教えて下さい。

#4

投稿記事 by SCI » 16年前

>>あとは、グローバル変数を使わないようにしてください。
> 関数に void を使ったのは・・・。(汗

ん、気になりますね。何か重大な秘密があるのでしょうか。

SCI

Re:画像の重なり?について教えて下さい。

#5

投稿記事 by SCI » 16年前

あぁ、それから。
LoadGraphScreenをループ毎に実行するのは高負荷なので、LoadGraphを使って予め画像を読み込んでおくと良いでしょう。

Dixq (管理人)

Re:画像の重なり?について教えて下さい。

#6

投稿記事 by Dixq (管理人) » 16年前

木霊さんが仰っている事に加え、ちょっと考え方で良くない所があります。
コードをザっと見ただけですが、「今押した瞬間」を考えるため、
途中で

Sleep(300); //押しっぱなし対策(1/600秒間)

していますよね。
こうすると、0.3秒画面が止まってしまいます。
メッセージ処理も出来ませんし、動きも止まってしまうのはよくないです。
0.3秒待機させるときは、カウンタなどによって0.3秒は特定の関数を呼ばないようにするなどの
方法が必要です。
またキーが今押された瞬間かどうかはゲームプログラミングの館の40a章などを参考にして下さい。

最低限呼ばないといけない関数はwhile関数の条件式の中に突っ込んでしまうと便利です。
また、常に読み込みながら描画するLoadGraphScreenはほとんど使う機会の無い関数です。
LoadGraph関数で一度読み込んでから描画して下さい。
詳しくは13c章までよく読んでみて下さい。
まとめると

・メッセージ処理をすること
・裏画面処理をすること
・画像は一回ロードしてから使うこと
・Sleep関数はFPS制御以外に使わないこと
・今押されたかどうかは前のキーボードの状態と今のキーボードの状態を比較して行うこと

この辺に注意してみて下さい。それとSleep(300)は1/600秒ではないですが、その辺はOKですか?

lbfuvab

Re:画像の重なり?について教えて下さい。

#7

投稿記事 by lbfuvab » 16年前

キーの押しっぱなし対策としては、bKeyDowningみたいな名前のフラグをつくり、押したらフラグをtrueにし、離したらfalseにします。そしてtrueの間は新しくゲームを始めないようにすれば良いですよ。

SCI

Re:画像の重なり?について教えて下さい。

#8

投稿記事 by SCI » 16年前

もしくは、GetHitKeyStateAll(keybuf)のkeybufをそのまま使うのではなく、
if (keybuf[コード]) key[コード]++;
else key[コード] = 0;
というようにすれば、「押された瞬間」と「押され続けている」をすべてのキーに対して判定できますね。
龍神録3章ではこの実装になっているようです。
もちろん、押された瞬間は「値が1」、押され続けているときは「値が正」ですね。

lbfuvab

Re:画像の重なり?について教えて下さい。

#9

投稿記事 by lbfuvab » 16年前

>>SCIさん

おお、それは良い方法ですね。
今度から使わして頂きます。

ムンバ

Re:画像の重なり?について教えて下さい。

#10

投稿記事 by ムンバ » 16年前

こんにちは。
仕事が思ったより早く終わったので勉強再開できました。w

木霊さん、SCIさん、管理人さん、lbfuvabさん
ご丁寧なご解説ありがとうございます。

皆さんに、ご意見頂いた内、まだ部分的にですが^^;修正してみました。

#include "DxLib.h"

#define JYANxITI 315

char keybuf[256];
int mynum, pc_rand, pcnum; //mynum pcnum は勝ち負けの判定に使う予定
int img[7];

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	ChangeWindowMode(TRUE); //ウィンドウモードに変更する関数
	if (DxLib_Init() == -1) //初期化処理する関数
		return -1;

	img[0]=LoadGraph("img/haikei001.jpg");
	img[1]=LoadGraph("img/goo.png");
	img[2]=LoadGraph("img/tyoki.png");
	img[3]=LoadGraph("img/paa.png");
	img[4]=LoadGraph("img/goo2.png");
	img[5]=LoadGraph("img/tyoki2.png");
	img[6]=LoadGraph("img/paa2.png");

	while (1){
		ClearDrawScreen();
		
		DrawGraph(0, 0, img[0], TRUE);
		DrawFormatString(520, 463, GetColor(100, 100, 255), "%s", "ムンじゃんけん"); //タイトル表示
		
		GetHitKeyStateAll(keybuf); //すべてのキーの状態を得る
		if (keybuf[KEY_INPUT_ESCAPE] == 1) //Escキー押すと終了
			break;
		if (ProcessMessage() == -1) //エラーが起きたら終了
			break;

		if (keybuf[KEY_INPUT_1] == 1){
			DrawGraph(JYANxITI, 390, img[1], TRUE); //数字1で自分グー画像
			DrawFormatString(JYANxITI, 463, GetColor(100, 100, 255), "%s", "グー"); //自分グー表示
			mynum = 1; //勝ち負け判定予定の変数

		} else if (keybuf[KEY_INPUT_2] == 1){
			DrawGraph(JYANxITI, 390, img[2], TRUE); //数字2で自分チョキ画像
			DrawFormatString((JYANxITI - 10), 463, GetColor(100, 100, 255), "%s", "チョキ"); //自分チョキ表示
			mynum = 2; //勝ち負け判定予定の変数

		} else if (keybuf[KEY_INPUT_3] == 1){
			DrawGraph(JYANxITI, 390, img[3], TRUE); //数字3で自分パー画像
			DrawFormatString(JYANxITI, 463, GetColor(100, 100, 255), "%s", "パー"); //自分パー表示
			mynum = 3; //勝ち負け判定予定の変数
		}

		if (keybuf[KEY_INPUT_1] == 1 || keybuf[KEY_INPUT_2] == 1 || keybuf[KEY_INPUT_3] == 1){
			pc_rand = GetRand(2); //PCじゃんけんランダム
			Sleep(300); //押しっぱなし対策(ミリ秒)
			
			if (pc_rand == 0){
				DrawGraph(JYANxITI, 250, img[4], TRUE); //PCグー画像
				pcnum = 1; //勝ち負け判定予定の変数

			} else if (pc_rand == 1){
				DrawGraph(JYANxITI, 250, img[5], TRUE); //PCグー画像
				pcnum = 2; //勝ち負け判定予定の変数

			}else if (pc_rand == 2){
				DrawGraph(JYANxITI, 250, img[6], TRUE); //PCパー画像
				pcnum = 3; //勝ち負け判定予定の変数
			}
		}
		
		ScreenFlip();
	}
       
	DxLib_End(); //終了処理をする関数
	return 0;
}
>木霊さん
 自作関数は、もう少し勉強してから、もう1度試してみます。(謝
 ScreenFlip ()とClearDrawScreen ()を入れてみたらできました。
 じゃんけん画像が、その都度消えるのは今後、対処したいと思います。
 ご指導ありがとうございました。<_ _>

>SCIさん
 >ん、気になりますね。何か重大な秘密があるのでしょうか。
 実はですね~^^;
 自作関数は、こちらの「サンプルプログラミングの館」の「ジャンケン」
 のソース内の自作関数を真似してみたのです。ごめんなさい。(涙

 LoadGraph関数に変更しました。
 GetHitKeyStateAll_2関数は、管理人さんのご指導も含めまして
 これから勉強して取り入れてみたと思います。
 ご指導ありがとうございました。<_ _>

>管理人さん
 いつもありがとうございます。^^
 >Sleep(300)は1/600秒ではないですが、その辺はOKですか?
 ううっ・・・単位はミリ秒ですよね。<全然OKじゃないですね。^^;

 おっしゃる通り、Sleep関数は使わないで
 GetHitKeyStateAll_2関数でやってみたいと思います。
 
・メッセージ処理をすること
・Sleep関数はFPS制御以外に使わないこと
・今押されたかどうかは前のキーボードの状態と今のキーボードの状態を比較して行うこと

 今から引き続き「館」を参考にさせて頂き、やってみます。w
 ご指導ありがとうございました。<_ _>

>lbfuvabさん
 参考にさせて頂きます。
 ご指導ありがとうございました。<_ _>


皆さん本当にありがとうございました。
また何かありましたらご指導の程宜しくお願い致します。(謝

閉鎖

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