キャラクターから弾が出るようなプログラム

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

キャラクターから弾が出るようなプログラム

#1

投稿記事 by Marin » 15年前

こんにちは。
前回、非常に丁寧に質問に答えて下さいまして、本当にありがとうございます。
キャラクターが歩くプログラムを作ることができました。

今回は、その歩いているキャラクターから弾を出すようなプログラムを作りたいのですが、
思ったように上手くいきません><

----------------------------------------------------------------------

#include "DxLib.h"

typedef struct{
int x,y,img,muki,aruki;
}ch_t;

struct shot{
int x,y;
int flag;
};

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

int image[16];
char Key[256];
ch_t ch;

int i,counter=0; //counter=発射してからのカウントをする変数。

struct shot tama[10]; //tamaを10個作る。

for(i=0;i<10;i++){ //初期化処理
tama.x=640/2; tama.y=480; //座標代入
tama.flag=0; //飛んでいない事を示すフラグ=0
}

while(1){
ClearDrawScreen(); //裏画面のデータを全て削除
GetHitKeyStateAll( Key ) ; // すべてのキーの状態を得る

if( ProcessMessage() == -1 ) break ; //異常がおきたら終了

if(counter<5) //前にエンターを押してから5カウント未満なら
counter++; //カウントアップ

else if( Key[ KEY_INPUT_RETURN ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(i=0;i<10;i++){
if(tama.flag==0){ //発射していない玉を探し、
tama.flag=1; //発射フラグを立てる
break;
}
}
}
for(i=0;i<10;i++){
if(tama.flag==1){ //発射している玉なら
tama.y-=8; //座標を8減らす
LoadGraphScreen( tama.x , tama.y , "shot.bmp" , TRUE );//玉を描画
if(tama.y < -32){ //もし画面外まで来たら
tama[i].y=480; //初期値に戻し、
tama[i].flag=0; //発射フラグを戻す
}
}
}
if( Key[ KEY_INPUT_ESCAPE ] == 1 ) break;//Escボタンが押されたらブレイク

ScreenFlip() ;//裏画面データを表画面へ反映
}



if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理

ch.x =288;
ch.y =448;
ch.muki=0;
ch.aruki=0;

SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了



if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
ch.x=ch.x-6,ch.muki=1,ch.aruki=1;
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
ch.x=ch.x+6,ch.muki=3,ch.aruki=1;
else
ch.muki=0,ch.aruki=0;
if(ch.x<(-6)) //もし、キャラのX座標が-6以下になった場合
ch.x=(-6); //ch.xは0にする。
if(ch.x>614) //もし、キャラのX座標が614以上になった場合
ch.x=614; //ch.xは608にする


if( Key[ KEY_INPUT_UP ] == 1 )
ch.x=320;

int cnt;


cnt = (cnt+1)&0x07;
if(ch.aruki==1)
ch.img=image[ch.muki*4+(cnt/2)]; //画像をセット
else
ch.img=image[ch.muki*4];

DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画

ScreenFlip();//裏画面を表画面に反映
}

DxLib_End();
return 0;
}

---------------------------------------------------------------------------------

サンプルプログラムでは「image[1]」というデータを表示する訳なんですが、
それとは別に、「shot.bmp」と言う名前のファイルを表示させたいのです

エラーは無いのですが、なぜかコンパイルしても起動しません><
どこが悪いのかがわかりません;;

そして、多分このプログラムだとキャラクターから弾が出ないと思うのですが…
キャラクターから弾が出るようにするには


tama[i].x=640/2; tama[i].y=480; //座標代入



の部分を、
tama[i].x=ch.x; tama[i].y=ch.y;
に変えればいいのでしょうか?

あと、
DrawGraph と
LoadGraphScreen の
違いってなんでしょうか><

回答よろしくお願いします><

ひよこ

Re:キャラクターから弾が出るようなプログラム

#2

投稿記事 by ひよこ » 15年前

あれ、最終的な自分のプログラムの形がないですけど、それは置いておいて、
while(1)が
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Ke[KEY_INPUT_ESCAPE])
の前にあってそしてDxLib_Init()が使われていないのでwhile文の中は動けません。

一度、ゲームプログラミングの館を見てきたほうがいいかもしれません。

Marin

Re:キャラクターから弾が出るようなプログラム

#3

投稿記事 by Marin » 15年前

はい、いろいろプログラムをつぎこんだらわけがわからなくなってしまって><
言われた通り、プログラミングの館を見て確認してみました。

-------------------------------------------------------

#include "DxLib.h"

typedef struct{
int x,y,img,muki,aruki;
}ch_t;

struct shot{
int x,y;
int flag;
};




int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

int image[16],i,counter=0;
char Key[256];
struct shot tama[10];
ch_t ch;

if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理

ch.x =288;
ch.y =448;
ch.muki=0;
ch.aruki=0;

SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

for(i=0;i<10;i++){ //初期化処理
★1 tama.x=ch.x; tama.y=ch.y; //座標代入
tama.flag=0; //飛んでいない事を示すフラグ=0
}




while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了

★★★

if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
ch.x=ch.x-6,ch.muki=1,ch.aruki=1;
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
ch.x=ch.x+6,ch.muki=3,ch.aruki=1;
else
ch.muki=0,ch.aruki=0;
if(ch.x<(-6)) //もし、キャラのX座標が-6以下になった場合
ch.x=(-6); //ch.xは0にする。
if(ch.x>614) //もし、キャラのX座標が614以上になった場合
ch.x=614; //ch.xは608にする


if( Key[ KEY_INPUT_UP ] == 1 )
ch.x=320;

int cnt;


cnt = (cnt+1)&0x07;
if(ch.aruki==1)
ch.img=image[ch.muki*4+(cnt/2)]; //画像をセット
else
ch.img=image[ch.muki*4];

DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画

★2 if(KEY_INPUT_Z ==1){

if(counter<5) //前にエンターを押してから5カウント未満なら
counter++; //カウントアップ

else if( Key[ KEY_INPUT_RETURN ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(i=0;i<10;i++){
if(tama.flag==0){ //発射していない玉を探し、
tama.flag=1; //発射フラグを立てる
break;
}
}
}
for(i=0;i<10;i++){
if(tama.flag==1){ //発射している玉なら
tama.y-=8; //座標を8減らす
LoadGraphScreen( tama.x , tama.y , "shot.bmp" , TRUE );//玉を描画
if(tama.y < -32){ //もし画面外まで来たら
tama[i].y=480; //初期値に戻し、
tama[i].flag=0; //発射フラグを戻す
}
}
}
}





ScreenFlip();//裏画面を表画面に反映
}

DxLib_End();
return 0;
}


---------------------------------------------------------

★1の部分、

tama[i].x=ch.x; tama[i].y=ch.y; //弾が出てくところ

tama[i].x=640/2 を tama[i].x=ch.x に変更し、
キャラクターから弾が出てくるようにします。

★2の部分、
ゲームプログラミングの館「26. シューティング基本」で
必要だろうと思う場所をコピーペーストして
Zキーが入力されている時、この処理を行うようにしているのですが・・・

キャラクターは動くのですが、
Zキーを入力しても弾が発射されません><

★★★の部分に、
LoadGraphScreen( 0 , 0 , "back.bmp" , FALSE ) ;
を入力して、背景を設定してみたのですが、
これだと重くなってキャラの動作が鈍くなってしまいました;



質問多くてすみません><

1.弾が発射されない
2.背景「back.bmp」を表示すると重くなってしまう

これらの対処法を教えて頂ければ幸いです><

ひよこ

Re:キャラクターから弾が出るようなプログラム

#4

投稿記事 by ひよこ » 15年前

LoadGraphScreenはメモリに読み込まず、何度も読み込み続けているので重くなります。
LoadGraphとDrawGraphを使うといいでしょう、これもゲームプログラミングの館に書いてあります。
★2 if(KEY_INPUT_Z ==1)と書いてありますが、中にif( Key[ KEY_INPUT_RETURN ] == 1 )があります。
Zは★2ではなくRETURNをZに書き変えればいいです。

Marin

Re:キャラクターから弾が出るようなプログラム

#5

投稿記事 by Marin » 15年前

おお!画像は

tamagazou = LoadGraph( "shot.bmp" ) ;

などのように一度メモリに読みこんで、「shot.bmp」をintとして表すやり方を知ることが出来ました!
結果、とても軽く動作するようになりました!

本当にいつもありがとうございます!

ところで、

弾のプログラムは弾のプログラムで、
歩くプログラムは歩くプログラムで、のように
それぞれのプログラムをcppファイルごとに分けたいのですが、
サンプルプログラム(12章)を見てみると、

main.cppには

case 100://通常処理
calc_ch(); //キャラクタ計算
ch_move(); //キャラクタの移動制御
enemy_main();//敵処理メイン
graph_main();//描画メイン
stage_count++;
break;

と入力されている部分がありますが、
例えばcalc_ch()なんですが、
case 100の場合calc_chの処理を行う、次にch_moveの…と
続いていくことだと思います。

char.cppファイルに
void calc_ch(){

と入力されている部分がありますが、
この{}の中の処理を行うと言う意味ですよね?

弾の部分だけのプログラムをshot.cppとして保存したいのですが、
とりあえず、今出来ているプログラムがこれです。

[color=red>---------------------------------------------------------[/color]

#include "DxLib.h"

typedef struct{
int x,y,img,muki,aruki;
}ch_t;

struct shot{
int x,y;
int flag;
};




int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

int image[16],i,counter=0;
char Key[256];
struct shot tama[10];
ch_t ch;
int tamagazou;




if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理



ch.x =288;
ch.y =448;
ch.muki=0;
ch.aruki=0;



SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了

tamagazou = LoadGraph( "shot.bmp" ) ;

if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
ch.x=ch.x-6,ch.muki=1,ch.aruki=1;
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
ch.x=ch.x+6,ch.muki=3,ch.aruki=1;
else
ch.muki=0,ch.aruki=0;
if(ch.x<(-6)) //もし、キャラのX座標が-6以下になった場合
ch.x=(-6); //ch.xは0にする。
if(ch.x>614) //もし、キャラのX座標が614以上になった場合
ch.x=614; //ch.xは608にする


if( Key[ KEY_INPUT_UP ] == 1 )
ch.x=320;

int cnt;


cnt = (cnt+1)&0x07;
if(ch.aruki==1)
ch.img=image[ch.muki*4+(cnt/2)]; //画像をセット
else
ch.img=image[ch.muki*4];

DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画

for(i=0;i<10;i++){ //初期化処理
tama.x=ch.x+6; tama.y=ch.y; //座標代入
tama.flag=0; //飛んでいない事を示すフラグ=0
}

if(ch.aruki==0){

//★-----------------------------------------------------------------------★

if(counter<5) //前にエンターを押してから5カウント未満なら
counter++; //カウントアップ

else if( Key[ KEY_INPUT_Z ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(i=0;i<10;i++){
if(tama.flag==0){ //発射していない玉を探し、
tama.flag=1; //発射フラグを立てる
break;
}
}
}
}

for(i=0;i<10;i++){
if(tama.flag==1){ //発射している玉なら
tama.y-=14; //座標を8減らす
DrawGraph( tama.x , tama.y , tamagazou , TRUE );//玉を描画
if(tama.y < 0){ //もし画面外まで来たら
tama[i].y=480; //初期値に戻し、
tama[i].flag=0; //発射フラグを戻す
}
}

//★-----------------------------------------------------------------------★

}


ScreenFlip();//裏画面を表画面に反映
}

DxLib_End();
return 0;
}

[color=red>--------------------------------------------------------------------------[/color]

Marin

Re:キャラクターから弾が出るようなプログラム

#6

投稿記事 by Marin » 15年前

長いと言われたので、2つにわけさせていただきます><


★---★の間のプログラムをshot_tama(); にして、

別のcppファイル、「shot.cpp」には

----------------------------------------------------------

#include "DXlib.h"

void shot_tama(){
struct shot{
int x,y;
int flag;
};
char Key[256];
struct shot tama[10];
int tamagazou;
tamagazou = LoadGraph( "shot.bmp" ) ;
int i,counter=0;
for(i=0;i<10;i++){ //初期化処理
tama.x=288; tama.y=480; //座標代入
tama.flag=0; //飛んでいない事を示すフラグ=0
}
if(counter<5) //前にエンターを押してから5カウント未満なら
counter++; //カウントアップ

else if( Key[ KEY_INPUT_Z ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(i=0;i<10;i++){
if(tama.flag==0){ //発射していない玉を探し、
tama.flag=1; //発射フラグを立てる
break;
}
}
}


for(i=0;i<10;i++){
if(tama.flag==1){ //発射している玉なら
tama.y-=14; //座標を8減らす
DrawGraph( tama.x , tama.y , tamagazou , TRUE );//玉を描画
if(tama.y < 0){ //もし画面外まで来たら
tama[i].y=480; //初期値に戻し、
tama[i].flag=0; //発射フラグを戻す
}
}
}
}

----------------------------------------------------------

色々めちゃくちゃではありますが・・・

ここでのエラーは、

「'shot_tama': 識別子が見つかりませんでした」
と出ました。これはshot_tama以外に、
ヘッダーファイルなどで何か準備するべきところがあるのでしょうか?

あと、赤字で囲ってあるプログラムについて、

-----------------------------------------------

for(i=0;i<10;i++){ //初期化処理
★1 tama[i].x=ch.x; tama[i].y=ch.y; //座標代入
tama[i].flag=0; //飛んでいない事を示すフラグ=0
}

------------------------------------------------

このプログラムの位置についてなんですが、
前回の書き込みのプログラムの位置だと
これの前に

ch.x =288;
ch.y =448;

などの宣言があるので、
tama[i].xやtama[i].yなどが
288、448と代入されてしまい、
(288,448)の部分からしか弾が出ませんでした><

なので、今回は位置を変えてみたのですが、
この位置だとキャラクターの頭上には表示されますが、
飛ばずにすぐに消えてしまうようになりました><

いったいこのプログラムをどこに置けば
キャラクターの位置、すなわち(ch.x,ch.y)の座標から弾が出るように出来るのでしょうか><

ひよこ

Re:キャラクターから弾が出るようなプログラム

#7

投稿記事 by ひよこ » 15年前

ファイルを分けるなら、extern 宣言がいります。
シューティングゲームの館を参考にしましょう。
これで実行は出来ますが、初期化、読み込み、描くなのでうまくいきません。
一回文法を勉強したほうがいいかもしれません。昔、私もすごい処理をしていました。

Marin

Re:キャラクターから弾が出るようなプログラム

#8

投稿記事 by Marin » 15年前

サンプルプログラムを見て、色々処理の整理の仕方を学んでいきたいと思います。

あの、

for(i=0;i<10;i++){ //初期化処理
tama.x=ch.x+8; tama.y=ch.y; //座標代入
tama.flag=0; //飛んでいない事を示すフラグ=0
}

の位置を色々変えてはみたのですが、

Whileの{}の外に置くと弾はちゃんと動くのですが、
ch.x =288;
ch.y =448;
と宣言してしまっているので、弾が出てくる座標は常に(288.448)となってしまいます。

Whileの{}の中に入れると、
画像はきちんとキャラクターの上に表示されるのですが、
一瞬表示されるだけですぐに消えてしまいます。
これはどういうことでしょうか?

ひよこ

Re:キャラクターから弾が出るようなプログラム

#9

投稿記事 by ひよこ » 15年前

これが原因ですね。tama.x=288; tama.y=480; //座標代入
少し説明をします。
for(i=0;i<10;i++){ //初期化処理
tama.x=288; tama.y=480; //座標代入
tama.flag=0; //飛んでいない事を示すフラグ=0
}
はすべての玉を初期化します。それをwhile文の中に置くと玉が飛んでいても、ループの度に消えます。
for(i=0;i<10;i++){
if(tama.flag==1){ //発射している玉なら
発射している玉を探して
tama.y-=14; //座標を8減らす
DrawGraph( tama.x , tama.y , tamagazou , TRUE );//玉を描画
描画します。
int tamagazou;
tamagazou = LoadGraph( "shot.bmp" ) ;
変数tamagazouを作りそこにshot.bmpをいれています。これは
Winmainのcppで宣言し読み込みましょう。
毎回読むとどんどん重くなります。
externを使って直しましょう。

閉鎖

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