自機に弾を撃たせたいです。

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

自機に弾を撃たせたいです。

#1

投稿記事 by 崎島 » 10年前

初めまして、崎島といいます。
今回、自分の趣味ということで、初めてのゲームを作りたいなと思い、東方二次創作でのゲームを作っています。物語等は考え済みです。
事前に、c言語の入門書は読み、DXライブラリの使い方も、見ながらではありますが何とかできます。


本題ですが、今、http://akaguro.jp/stg/stg_index.shtmlを参 ... て消してしまいました

とりあえず、書いたコードはそのまま載せます。

code
#include "DxLib.h"
//プロトタイプ宣言//

void init_back_img(void);

void to_center(void);

void draw_back(void);

void draw_variable(void);

int get_key(void);

void init_player(void);
void move_player(void);
void draw_player(void);
struct PLAYER{
double x, y;
double draw_x, draw_y;
};

struct PLAYER p1;

int key[256];

int counter;

double back_img_y;
int back_img1;
int back_img2;

int gamecount;

int Color_White;

//こっから本文//

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
ChangeWindowMode(TRUE);
DxLib_Init();
SetDrawScreen(DX_SCREEN_BACK);

init_player();
init_back_img();

while (ScreenFlip() == 0 && ProcessMessage() == 0
&& ClearDrawScreen() == 0 && get_key() == 0){

/*ここにプログラムを書く。主に関数呼び出し*/


to_center();
draw_back();
draw_player();

draw_variable();
move_player();
gamecount++;
back_img_y++;

}
DxLib_End();
return 0;
}

//以下、関数//



void init_back_img(){
back_img1 = LoadGraph("test.png");
back_img2 = LoadGraph("test.png");
back_img_y = 0;
Color_White = GetColor(255, 255, 255);
}


void init_player(){
p1.x = 0;
p1.y = -200;
p1.draw_x = 0;
p1.draw_y = 0;
}

void move_player(){
if (key[KEY_INPUT_RIGHT] >= 1){
p1.x = p1.x + 3;
if (p1.x < 0 && key[KEY_INPUT_A]) p1.x = 0;//瞬間移動っぽいもの
if (p1.x > 305)p1.x = 305;
}
if (key[KEY_INPUT_DOWN] >= 1){
p1.y = p1.y - 3;
if (p1.y < -220)p1.y = -220;
}
if (key[KEY_INPUT_LEFT] >= 1){
p1.x = p1.x - 3;
if (p1.x > 0 && key[KEY_INPUT_A])p1.x = 0;//瞬間移動っぽいもの
if (p1.x < -330)p1.x = -330;

}
if (key[KEY_INPUT_UP] >= 1){
p1.y = p1.y + 3;
if (p1.y > 240)p1.y = 240;
}

}

void draw_player(){

int Handle1;
int Handle2;
int Handle3;
Handle1 = LoadGraph("player_reimu1.png");
Handle2 = LoadGraph("player_reimu2.png");
Handle3 = LoadGraph("player_reimu3.png");
if (CheckHitKey(KEY_INPUT_LEFT) == 0 && CheckHitKey(KEY_INPUT_RIGHT) == 0)
{
// 右と左が押されていない(通常グラ表示)//
DrawGraph(p1.draw_x, p1.draw_y, Handle1, TRUE);
}
else if (CheckHitKey(KEY_INPUT_LEFT) == 1 && CheckHitKey(KEY_INPUT_RIGHT) == 1){
// 右と左が押されている(通常グラ表示)//
DrawGraph(p1.draw_x, p1.draw_y, Handle1, TRUE);
}
else{
// 右か左が押されている(通常グラ非表示)//
}

if (key[KEY_INPUT_RIGHT] >= 1 && key[KEY_INPUT_LEFT] == 0){
DrawGraph(p1.draw_x, p1.draw_y, Handle2, TRUE);
}//左靡きグラ表示//

if (key[KEY_INPUT_LEFT] >= 1 && key[KEY_INPUT_RIGHT] == 0){
DrawGraph(p1.draw_x, p1.draw_y, Handle3, TRUE);
}//右靡きグラ表示//
}



void to_center(){
p1.draw_x = p1.x + 320;
p1.draw_y = ((-1)*p1.y) + 240;
}

void draw_back(){
DrawGraph(0, back_img_y, back_img1, TRUE);
DrawGraph(0, back_img_y - 480, back_img2, TRUE);
DrawLine(0, 240, 640, 240, Color_White);
DrawLine(320, 0, 320, 480, Color_White);
DrawFormatString(320, 240, Color_White, "(0,0)");
if (back_img_y > 480){
back_img_y = 0;
}
}





void draw_variable(){
DrawFormatString(440, 440, Color_White, "gamecount=%d", gamecount);
}

int get_key(){
char keys[256];
GetHitKeyStateAll(keys);
for (int i = 0; i < 256; i++){
if (keys != 0){
key++;
}
else{
key = 0;
}
}
return 0;
}
/code

使用している環境は、
os:windows 8.1
コンパイラ名:Visual Studio 2013

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 自機に弾を撃たせたいです。

#2

投稿記事 by みけCAT » 10年前

崎島 さんが書きました:どうしても自機からの弾幕を打つことが出来ません。恥ずかしい話ではあるのですが、キレて消してしまいました。

とりあえず、書いたコードはそのまま載せます。
とりあえず、自機から弾幕を打つ条件(あるボタンが押されているなど)が成立していたら画面に「弾幕を打つ」と表示するプログラムを作れますか?
また、弾幕を打つには弾の位置の情報を格納する場所が必要だと思います。
崎島 さんが書きました:

コード:

void draw_player(){

	int Handle1; 
	int Handle2;
	int Handle3;
	Handle1 = LoadGraph("player_reimu1.png");
	Handle2 = LoadGraph("player_reimu2.png");
	Handle3 = LoadGraph("player_reimu3.png");
このように毎フレーム画像のロードを行ってはいけません。
ロードは比較的重い上、リソース(ここでは画像ハンドル数)の枯渇を招いてしまいます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 自機に弾を撃たせたいです。

#3

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

当サイトのゲームプログラミングの館
http://dixq.net/g/

に似た様なコードを紹介しています。
http://dixq.net/g/29.html

参考になりますか?

崎島
記事: 7
登録日時: 10年前

Re: 自機に弾を撃たせたいです。

#4

投稿記事 by 崎島 » 10年前

みけCATさん、返信ありがとうございます。

コード:

if(CheckHitKey(KEY_INPUT_Z)>=0){
}
else{
printf("弾幕を打つ");
}
とても簡単に書きましたが、こういうことでしょうか?もうしわけありませんが、ご教授お願いします。


そして昨晩、自分でも新たに弾発射のコードを書いてみましたが、自機の下に弾が現れ消えるだけになってしまいました。

コード:

void draw_shot(){
	for (int i = 0; i < 20; ++i){
		if (tama[i].flag){
			DrawGraph(p1.draw_x, p1.draw_y+1 , Handle4, TRUE);
		}
	}
}

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.x;
				tama[e].yy = p1.y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){
			tama[e].yy = 14;

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}
参考、引用元はhttp://bituse.info/game/shot/# プログラミング入門サイト bituse です。


画像のロードは、他にもやり方があるようなので、配布するまではこのままでいこうと思います。

なかなかわかりにくい質問になっているかもしれませんが、よろしくお願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 自機に弾を撃たせたいです。

#5

投稿記事 by みけCAT » 10年前

崎島 さんが書きました:

コード:

if(CheckHitKey(KEY_INPUT_Z)>=0){
}
else{
printf("弾幕を打つ");
}
とても簡単に書きましたが、こういうことでしょうか?
DXライブラリのCheckHitKey関数は(多分)0以上の値しか返さないので、条件式が不適切です。
また、わざわざ条件が成立した時の処理を空にして、else以降に処理を書く意味もわかりません。
素直に!演算子などを用いて条件の真偽をひっくり返せばいいでしょう。
また、printf関数でも悪くないかもしれませんが、DrawString関数を使うことを想定していました。
崎島 さんが書きました:そして昨晩、自分でも新たに弾発射のコードを書いてみましたが、自機の下に弾が現れ消えるだけになってしまいました。
  • draw_shot関数において、せっかくtamaに弾の位置の情報があるはずなのに、それを使わずにp1にアクセスするのは不自然です。
  • 弾を移動させる処理が提示されたコードの中には無いようです。
  • init_shot関数において、せっかくtama.yyを上のfor文の中で設定しているのに、下のfor文の中ですぐに固定値に上書きしてしまうのは不自然です。
  • 消える原因はよくわかりません。コード全体はどうなっていますか?

崎島 さんが書きました:画像のロードは、他にもやり方があるようなので、配布するまではこのままでいこうと思います。

どうしてですか?
背景のロードはまともなのに、なぜ統一しないのですか?
「配布するまではこのままでいこうと思います」とのことですが、もしかして配布してからもこのままでいくつもりですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

崎島
記事: 7
登録日時: 10年前

Re: 自機に弾を撃たせたいです。

#6

投稿記事 by 崎島 » 10年前

みけCATさん、返信ありがとうございます。

コード:


A=GetColor(255,255,255);

if(CheckHitKey(KEY_INPUT_Z)==1){
DrawString(200,200,"弾幕を打つ",A);
}
Zが押されたときに「弾幕を打つ」と白い文字で表示させるように書いたつもりですが、これでどうでしょうか?


コード全部です

コード:

#include "DxLib.h"
//プロトタイプ宣言//

void init_back_img(void);

void to_center(void);

void draw_back(void);

void draw_variable(void);

void draw_shot(void);

bool life=true;

int get_key(void);

int count;

void init_shot(void);

struct shot{
	double xx, yy;
	int flag = false;
};

struct shot tama[100];

void move_player(void);
void draw_player(void);
struct PLAYER{
	double x, y;
	double draw_x, draw_y;
};

struct PLAYER p1;

int key[256];

int counter;

double back_img_y;
int back_img1;
int back_img2;

int Handle1;
int Handle2;
int Handle3;
int Handle4;

int gamecount;

int Color_White;

//こっから本文//

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	init_back_img();

	back_img1 = LoadGraph("test.png");
	back_img2 = LoadGraph("test.png");
	Handle1 = LoadGraph("player_reimu1.png");
	Handle2 = LoadGraph("player_reimu2.png");
	Handle3 = LoadGraph("player_reimu3.png");
	Handle4 = LoadGraph("danmaku_reimu1.png");


	while (ScreenFlip() == 0 && ProcessMessage() == 0
		&& ClearDrawScreen() == 0 && get_key() == 0){
		
		
		to_center();
		draw_back();
		draw_shot();
		init_shot();
		draw_player();

		draw_variable();
		move_player();
		gamecount++;
		back_img_y++;
		++count;
	}
	DxLib_End();
	return 0;
}

//以下,関数//

void draw_shot(){
	for (int i = 0; i < 20; ++i){
		if (tama[i].flag){
			DrawGraph(p1.draw_x, p1.draw_y+1 , Handle4, TRUE);
		}
	}
}

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.x;
				tama[e].yy = p1.y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){
			tama[e].yy = 14;

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}

void init_back_img(){

	back_img_y = 0;
	Color_White = GetColor(255, 255, 255);
}




void move_player(){
	if (key[KEY_INPUT_RIGHT] >= 1){
		p1.x = p1.x + 3;
		if (p1.x < 0 && key[KEY_INPUT_A]) p1.x = 0;//瞬間移動っぽいやつ
		if (p1.x > 305)p1.x = 305;
	}
	if (key[KEY_INPUT_DOWN] >= 1){
		p1.y = p1.y - 3;
		if (p1.y < -220)p1.y = -220;
	}
	if (key[KEY_INPUT_LEFT] >= 1){
		p1.x = p1.x - 3;
		if (p1.x > 0 && key[KEY_INPUT_A])p1.x = 0;//瞬間移動っぽいやつ
		if (p1.x < -330)p1.x = -330;

	}
	if (key[KEY_INPUT_UP] >= 1){
		p1.y = p1.y + 3;
		if (p1.y > 240)p1.y = 240;
	}

}

void draw_player(){


	if (CheckHitKey(KEY_INPUT_LEFT) == 0 && CheckHitKey(KEY_INPUT_RIGHT) == 0)
	{
		// 右と左が押されていない(通常グラ表示)//
		DrawGraph(p1.draw_x, p1.draw_y, Handle1, TRUE);
	}
	else if (CheckHitKey(KEY_INPUT_LEFT) == 1 && CheckHitKey(KEY_INPUT_RIGHT) == 1){
		// 右と左が押されている(通常グラ表示)//
		DrawGraph(p1.draw_x, p1.draw_y, Handle1, TRUE);
	}
	else{
		// 右か左が押されている(通常グラ非表示)//
	}

	if (key[KEY_INPUT_RIGHT] >= 1 && key[KEY_INPUT_LEFT] == 0){
		DrawGraph(p1.draw_x, p1.draw_y, Handle2, TRUE);
	}//左靡きグラ表示//

	if (key[KEY_INPUT_LEFT] >= 1 && key[KEY_INPUT_RIGHT] == 0){
		DrawGraph(p1.draw_x, p1.draw_y, Handle3, TRUE);
	}//右靡きグラ表示//
}

void to_center(){
	p1.draw_x = p1.x+320;
	p1.draw_y = ((-1)*p1.y) + 240;
}

void draw_back(){
	DrawGraph(0, back_img_y, back_img1, TRUE);
	DrawGraph(0, back_img_y - 480, back_img2, TRUE);
	DrawLine(0, 240, 640, 240, Color_White);
	DrawLine(320, 0, 320, 480, Color_White);
	DrawFormatString(320, 240, Color_White, "(0,0)");
	if (back_img_y > 480){
		back_img_y = 0;
	}
}





void draw_variable(){
	DrawFormatString(440, 440, Color_White, "gamecount=%d", gamecount);
}

int get_key(){
	char keys[256];
	GetHitKeyStateAll(keys);
	for (int i = 0; i < 256; i++){
		if (keys[i] != 0){
			key[i]++;
		}
		else{
			key[i] = 0;
		}
	}
	return 0;
}
tamaに弾の位置の情報があるということなので早速p1のところと入れ替えてみたところ

コード:

void draw_shot(){
	for (int i = 0; i < 20++i){
		if (tama[i].flag){
			DrawGraph(tama[i].xx,tama[i].yy, Handle4, TRUE);
		}
	}
}
左上に弾画像が表示されるだけになりました。訳が分かりません。

弾を移動させる処理が無いとのことですが

コード:

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.x;
				tama[e].yy = p1.y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){
			tama[e].yy = 14;

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}
二つ目のfor文からが弾の移動処理だと「プログラミング入門サイト bituse」というところには書いてあるのですが...

「•init_shot関数において、せっかくtama.yyを上のfor文の中で設定しているのに、下のfor文の中ですぐに固定値に上書きしてしまうのは不自然です。」
とのことで、早速固定値に上書きする部分を消してみました。

コード:

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.x;
				tama[e].yy = p1.y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}
実行結果が変わっていない感じがします。


消える原因は僕もよくわかりません。動かせるときに動かすと消え、左上に出現し動かせないときには消えないようです。

画像のロードですが、

コード:

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	init_back_img();

	back_img1 = LoadGraph("test.png");
	back_img2 = LoadGraph("test.png");
	Handle1 = LoadGraph("player_reimu1.png"); // 画像をロード
	Handle2 = LoadGraph("player_reimu2.png");
	Handle3 = LoadGraph("player_reimu3.png");
	Handle4 = LoadGraph("danmaku_reimu1.png");


	while (ScreenFlip() == 0 && ProcessMessage() == 0
		&& ClearDrawScreen() == 0 && get_key() == 0){
		
		
		to_center();
		draw_back();
		draw_shot();
		init_shot();
		draw_player();

		draw_variable();
		move_player();
		gamecount++;
		back_img_y++;
		++count;
	}
	DxLib_End();
	return 0;
}
先ほども出しましたが、こんな風に全部一か所にまとめてみました。どうでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 自機に弾を撃たせたいです。

#7

投稿記事 by みけCAT » 10年前

崎島 さんが書きました:

コード:


A=GetColor(255,255,255);

if(CheckHitKey(KEY_INPUT_Z)==1){
DrawString(200,200,"弾幕を打つ",A);
}
Zが押されたときに「弾幕を打つ」と白い文字で表示させるように書いたつもりですが、これでどうでしょうか?
これ自体は悪くないと思います。
あとはどこに書くかですね。
崎島 さんが書きました:tamaに弾の位置の情報があるということなので早速p1のところと入れ替えてみたところ

コード:

void draw_shot(){
	for (int i = 0; i < 20++i){
		if (tama[i].flag){
			DrawGraph(tama[i].xx,tama[i].yy, Handle4, TRUE);
		}
	}
}
左上に弾画像が表示されるだけになりました。訳が分かりません。
自機の座標は変換されたdrawを用いているのに対し、弾の座標は生の座標を使用してしまっているので、
弾の座標も自機と同様に描画用に変換するべきです。
崎島 さんが書きました:弾を移動させる処理が無いとのことですが

コード:

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.x;
				tama[e].yy = p1.y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){
			tama[e].yy = 14;

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}
二つ目のfor文からが弾の移動処理だと「プログラミング入門サイト bituse」というところには書いてあるのですが...
具体的にどこに書いてありますか?
少なくとも
操作キャラから弾を発射してみよう | シューティングゲーム作成入門~bituse~
には、似たfor文でyyを減算する処理はありますが、このような固定値を代入する処理は書かれていないようです。
崎島 さんが書きました:「•init_shot関数において、せっかくtama.yyを上のfor文の中で設定しているのに、下のfor文の中ですぐに固定値に上書きしてしまうのは不自然です。」
とのことで、早速固定値に上書きする部分を消してみました。

コード:

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.x;
				tama[e].yy = p1.y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}
実行結果が変わっていない感じがします。
draw_shot関数を変更していない場合、tama.yyは描画に反映されないため、実行結果は変わらないはずです。
修正後のdraw_shot関数を使用した場合、きちんと弾のy位置が打った時の自機の位置を反映するようになりました。

崎島 さんが書きました:画像のロードですが、

コード:

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	init_back_img();

	back_img1 = LoadGraph("test.png");
	back_img2 = LoadGraph("test.png");
	Handle1 = LoadGraph("player_reimu1.png"); // 画像をロード
	Handle2 = LoadGraph("player_reimu2.png");
	Handle3 = LoadGraph("player_reimu3.png");
	Handle4 = LoadGraph("danmaku_reimu1.png");


	while (ScreenFlip() == 0 && ProcessMessage() == 0
		&& ClearDrawScreen() == 0 && get_key() == 0){
		
		
		to_center();
		draw_back();
		draw_shot();
		init_shot();
		draw_player();

		draw_variable();
		move_player();
		gamecount++;
		back_img_y++;
		++count;
	}
	DxLib_End();
	return 0;
}
先ほども出しましたが、こんな風に全部一か所にまとめてみました。どうでしょうか?
悪くないと思います。
添付ファイル
gazou.zip
テスト用仮素材
(6.49 KiB) ダウンロード数: 126 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

崎島
記事: 7
登録日時: 10年前

Re: 自機に弾を撃たせたいです。

#8

投稿記事 by 崎島 » 10年前

みけCATさん、返信ありがとうございます。返信がかなり遅れてしまい、申し訳ございません。

描画用に変換ということは、簡単に言うともう一つ変数を用いるという解釈であっていますでしょうか?

コード:

void init_shot(){
    if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
        for (int e = 0; e < 20; e++){
            if (tama[e].flag == false){
                tama[e].flag = true;
                tama[e].xx = p1.x;
                tama[e].yy = p1.y;
                break;
            }
        }
    }
    for (int e = 0; e < 20; ++e){
        if (tama[e].flag){
            tama[e].yy = 14;
 
            if (tama[e].yy < -240){
                tama[e].flag = false;
            }
        }
    }
}
説明不足でした。http://bituse.info/game/shot/8 ここには、PSHOT_NUMをヘッダーファイルに20と定義しているとあり、わざわざ私も同じように定義せずに20をそのままいれればいいのでは?と思い、20と入れました。やはりいけないことなのでしょうか?


質問が増えるばかりですが、ご教授よろしくお願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 自機に弾を撃たせたいです。

#9

投稿記事 by みけCAT » 10年前

崎島 さんが書きました:描画用に変換ということは、簡単に言うともう一つ変数を用いるという解釈であっていますでしょうか?
自機と同じようにもう二つメンバを追加するか、わざわざ個別に変換しなくてすむように描画関数のラッパを作るといいでしょう。
崎島 さんが書きました:

コード:

void init_shot(){
    if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
        for (int e = 0; e < 20; e++){
            if (tama[e].flag == false){
                tama[e].flag = true;
                tama[e].xx = p1.x;
                tama[e].yy = p1.y;
                break;
            }
        }
    }
    for (int e = 0; e < 20; ++e){
        if (tama[e].flag){
            tama[e].yy = 14;
 
            if (tama[e].yy < -240){
                tama[e].flag = false;
            }
        }
    }
}
説明不足でした。http://bituse.info/game/shot/8 ここには、PSHOT_NUMをヘッダーファイルに20と定義しているとあり、わざわざ私も同じように定義せずに20をそのままいれればいいのでは?と思い、20と入れました。やはりいけないことなのでしょうか?
このような「マジックナンバー」を使うのは褒められたことではないですが、致命的な間違いではありません。
サイトと同じように減算せずに、固定値の14を代入しているところが問題です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 自機に弾を撃たせたいです。

#10

投稿記事 by みけCAT » 10年前

崎島 さんが書きました:描画用に変換ということは、簡単に言うともう一つ変数を用いるという解釈であっていますでしょうか?
描画用に変換は描画用に変換ということです。
「もう一つ変数を用いるという解釈」は、その変数の使い道がわからないため、間違いだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

崎島
記事: 7
登録日時: 10年前

Re: 自機に弾を撃たせたいです。

#11

投稿記事 by 崎島 » 10年前

みけCATさん、返信ありがとうございます。

減算処理のために、以下のように文を追加しました。
それと、p1.xをp1.draw_xに、p1.yをp1.draw_yに、それぞれ変更したところ、自機から弾画像が描画(勿論、飛んでいくように)されるようになりました。

コード:

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.draw_x;
				tama[e].yy = p1.draw_y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){
			tama[e].yy -= 14;//追加した文

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}


最終的に、以下のようなプログラムにしました。

コード:

#include "DxLib.h"
//プロトタイプ宣言//

void init_back_img(void);

void to_center(void);

void draw_back(void);

void draw_variable(void);

void draw_shot(void);

bool life=true;

int get_key(void);

int count;

void init_shot(void);

struct shot{
	double xx, yy;
	int flag = false;
};

struct shot tama[100];

void move_player(void);
void draw_player(void);
struct PLAYER{
	double x, y;
	double draw_x, draw_y;
};

struct PLAYER p1;

int key[256];

int counter;

double back_img_y;
int back_img1;
int back_img2;

int Handle1;
int Handle2;
int Handle3;
int Handle4;

int gamecount;

int Color_White;

//こっから本文//

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	init_back_img();

	back_img1 = LoadGraph("test.png");//画像をロード
	back_img2 = LoadGraph("test.png");
	Handle1 = LoadGraph("player_reimu1.png");
	Handle2 = LoadGraph("player_reimu2.png");
	Handle3 = LoadGraph("player_reimu3.png");
	Handle4 = LoadGraph("danmaku_reimu1.png");


	while (ScreenFlip() == 0 && ProcessMessage() == 0
		&& ClearDrawScreen() == 0 && get_key() == 0){
		
		
		to_center();
		draw_back();
		draw_shot();
		init_shot();
		draw_player();

		draw_variable();
		move_player();
		gamecount++;
		back_img_y;
		++count;
	}
	DxLib_End();
	return 0;
}

//以下,関数//

void draw_shot(){
	for (int i = 0; i < 20; ++i){
		if (tama[i].flag){
			DrawGraph(tama[i].xx,tama[i].yy, Handle4, TRUE);
		}
	}
}

void init_shot(){
	if (CheckHitKey(KEY_INPUT_Z)>=1&&count%3==0){
		for (int e = 0; e < 20; e++){
			if (tama[e].flag == false){
				tama[e].flag = true;
				tama[e].xx = p1.draw_x;
				tama[e].yy = p1.draw_y;
				break;
			}
		}
	}
	for (int e = 0; e < 20; ++e){
		if (tama[e].flag){
			tama[e].yy -= 14;

			if (tama[e].yy < -240){
				tama[e].flag = false;
			}
		}
	}
}

void init_back_img(){

	back_img_y = 0;
	Color_White = GetColor(255, 255, 255);
}




void move_player(){
	if (key[KEY_INPUT_RIGHT] >= 1){
		p1.x = p1.x + 3;
		if (p1.x < 0 && key[KEY_INPUT_A]) p1.x = 0;//瞬間移動っぽいやつ
		if (p1.x > 305)p1.x = 305;
	}
	if (key[KEY_INPUT_DOWN] >= 1){
		p1.y = p1.y - 3;
		if (p1.y < -220)p1.y = -220;
	}
	if (key[KEY_INPUT_LEFT] >= 1){
		p1.x = p1.x - 3;
		if (p1.x > 0 && key[KEY_INPUT_A])p1.x = 0;//瞬間移動っぽいやつ
		if (p1.x < -330)p1.x = -330;

	}
	if (key[KEY_INPUT_UP] >= 1){
		p1.y = p1.y + 3;
		if (p1.y > 240)p1.y = 240;
	}

}

void draw_player(){


	if (CheckHitKey(KEY_INPUT_LEFT) == 0 && CheckHitKey(KEY_INPUT_RIGHT) == 0)
	{
		// 右と左が押されていない(通常グラ表示)//
		DrawGraph(p1.draw_x, p1.draw_y, Handle1, TRUE);
	}
	else if (CheckHitKey(KEY_INPUT_LEFT) == 1 && CheckHitKey(KEY_INPUT_RIGHT) == 1){
		// 右と左が押されている(通常グラ表示)//
		DrawGraph(p1.draw_x, p1.draw_y, Handle1, TRUE);
	}
	else{
		// 右か左が押されている(通常グラ非表示)//
	}

	if (key[KEY_INPUT_RIGHT] >= 1 && key[KEY_INPUT_LEFT] == 0){
		DrawGraph(p1.draw_x, p1.draw_y, Handle2, TRUE);
	}//左靡きグラ表示//

	if (key[KEY_INPUT_LEFT] >= 1 && key[KEY_INPUT_RIGHT] == 0){
		DrawGraph(p1.draw_x, p1.draw_y, Handle3, TRUE);
	}//右靡きグラ表示//
}

void to_center(){
	p1.draw_x = p1.x+320;
	p1.draw_y = ((-1)*p1.y) + 240;
}

void draw_back(){
	DrawGraph(0, back_img_y, back_img1, TRUE);
	DrawGraph(0, back_img_y - 480, back_img2, TRUE);
	DrawLine(0, 240, 640, 240, Color_White);
	DrawLine(320, 0, 320, 480, Color_White);
	DrawFormatString(320, 240, Color_White, "(0,0)");
	if (back_img_y > 480){
		back_img_y = 0;
	}
}





void draw_variable(){
	DrawFormatString(440, 440, Color_White, "gamecount=%d", gamecount);
}

int get_key(){
	char keys[256];
	GetHitKeyStateAll(keys);
	for (int i = 0; i < 256; i++){
		if (keys[i] != 0){
			key[i]++;
		}
		else{
			key[i] = 0;
		}
	}
	return 0;
}
このようにしたところ、自機画像からの弾画像発射が実現できました。

わざわざさまざまなことをご教授いただき、ありがとうございました。
今後ともつまずくことが多いかと思いますが、ぜひともよろしくおねがいいたします。

閉鎖

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