また課題が出てしまいました・・・・・・

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

また課題が出てしまいました・・・・・・

#1

投稿記事 by manako » 17年前

今回はキー入力によって処理を変える事に挑戦中なのですが・・・・・・
先にやりたい事を言っておきますね。

・スペースキーを押されたらch.2のフラグを立てる
・↑が押されたらch.1の画像を2分割した2番目を壁画したい。

今できていないのはch1のキーフラグでスペースを押すとch2のフラグが立てられない。
壁画の変更のしかたがわからない。
この二つです。

ソースは
#include "DxLib.h"


typedef struct{
	int x,y,img,zahyou,san_flag;
}ch_t;


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
    int image[2];
    char Key[256];
    ch_t ch1,ch2;
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
    ch1.x  =0;
	ch1.y  =0;
    ch2.x  =0;
	ch2.y  =0;
    ch1.san_flag=0;
    ch1.zahyou=4;
	ch2.san_flag=0;
    ch2.zahyou=4;

    SetDrawScreen( DX_SCREEN_BACK ) ;  //描画先を裏画面に設定

        {
                ClearDrawScreen();                            // 裏画面のデータを全て削除
	LoadDivGraph( "abcd.png" , 2 , 2 , 1 , 32 , 32 , image );//画像を分割してimage配列に保存
                ScreenFlip() ;                                // 裏画面データを表\u30011 画面へ反映
        }



    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            //↑メッセージ処理       ↑画面をクリア         ↑キーボード入力状態取得      ↑ESCが押されると終了
     if(ch1.x%32==0 && ch1.y%32==0){   
            ch1.san_flag=1;         //歩くフラグを立てる。
            if     ( Key[ KEY_INPUT_UP   ]  == 1 )  //上ボタンが押されたら
                    ch1.zahyou=0;         //上向きフラグを立てる
            else if( Key[ KEY_INPUT_LEFT ]  == 1 )  //左ボタンが押されたら
                    ch1.zahyou=1;         //左向きフラグを立てる
            else if( Key[ KEY_INPUT_DOWN ]  == 1 )  //下ボタンが押されたら
                    ch1.zahyou=2;         //下向きフラグを立てる
            else if( Key[ KEY_INPUT_RIGHT]  == 1 )  //右ボタンが押されたら
                    ch1.zahyou=3;//右向きフラグを立てる

			else if( Key[ KEY_INPUT_SPACE]  == 1 )// スペースキー
                     ch1.zahyou=4;

			else                                    //何のボタンも押されてなかったら
                    ch1.san_flag=0; //向かないフラグを立てる
		}


if(ch1.san_flag==1){
	 if    (ch1.zahyou==0)
		    ch1.y--;
else if    (ch1.zahyou==1)
            ch1.x--;
else if    (ch1.zahyou==2)
            ch1.y++;
else if    (ch1.zahyou==3)
            ch1.x++;
else if    (ch1.zahyou==4)
           if(ch2.x%32==0 && ch2.y%32==0){   
            ch1.san_flag=1;         //歩くフラグを立てる。
            if     ( Key[ KEY_INPUT_UP   ]  == 1 )  //上ボタンが押されたら
                    ch2.zahyou=0;         //上向きフラグを立てる
            else if( Key[ KEY_INPUT_LEFT ]  == 1 )  //左ボタンが押されたら
                    ch2.zahyou=1;         //左向きフラグを立てる
            else if( Key[ KEY_INPUT_DOWN ]  == 1 )  //下ボタンが押されたら
                    ch2.zahyou=2;         //下向きフラグを立てる
            else if( Key[ KEY_INPUT_RIGHT]  == 1 )  //右ボタンが押されたら
                    ch2.zahyou=3;//右向きフラグを立てる
			else                                    //何のボタンも押されてなかったら
                    ch1.san_flag=0; //向かないフラグを立てる
}
}
if(ch2.san_flag==1){
	 if    (ch2.zahyou==0)
		    ch2.y--;
else if    (ch2.zahyou==1)
            ch2.x--;
else if    (ch2.zahyou==2)
            ch2.y++;
else if    (ch2.zahyou==3)
            ch2.x++;
}

	    ch1.img=image[(ch1.x%32+ch1.y%32)/32 + ch1.zahyou*0];
	    ch2.img=image[(ch2.x%32+ch2.y%32)/32 + ch2.zahyou*0];
		LoadGraphScreen( 0 , 0 , "000.bmp" , FALSE ) ;
        DrawGraph( ch1.x , ch1.y , ch1.img , TRUE  ) ;
        DrawGraph( ch2.x , ch2.y , ch1.img , TRUE  ) ;
                ScreenFlip();
    }

    DxLib_End();
    return 0;
}
考え方やヒントだけでもいいので教えてください。
よろしくお願いします。

kazuoni

Re:また課題が出てしまいました・・・・・・

#2

投稿記事 by kazuoni » 17年前

・・・またということは以前質問されている方でしょうか^^;コードは<pre>と</pre>タグで挟んで投稿して下さいって↑に思いっきり管理人さんが強調してらっしゃるのですが(笑)次回からは気をつけてくださいね。あと題名は過去ログになる際では大切になってくるので、質問の内容が分かるものがいいと思います。

突っ込みどころがありすぎてよく分からないんですが・・・

ch2.san_flagはとりあえずずっとゼロのままです。ゆえに
if(ch2.san_flag==1)
は実行されることはありません。これでは自分の目的とは異なるのではないのですか?

通りすがり

Re:また課題が出てしまいました・・・・・・

#3

投稿記事 by 通りすがり » 17年前

まず、前回質問したトピは「解決」にしておきましょう。
質問した内容管理人さんに返事もらってるのそのままにして新しいトピを立てるのはやめましょう。
規約をよく読んで投稿しましょう。

木霊

Re:また課題が出てしまいました・・・・・・

#4

投稿記事 by 木霊 » 17年前

とりあえず

> ch1.san_flag=0; //向かないフラグを立てる

向かないフラグが立っている時、このキャラはどこを向いているんでしょう?


> ch1.img=image[(ch1.x%32+ch1.y%32)/32 + ch1.zahyou*0];
> ch2.img=image[(ch2.x%32+ch2.y%32)/32 + ch2.zahyou*0];

0を掛けるとその答えは0になるので最後の部分は要りません

木霊

Re:また課題が出てしまいました・・・・・・

#5

投稿記事 by 木霊 » 17年前

変数の意味がわかりづらいと前回か前々回のトピで指摘されてた気がするのですが・・・

構造体 ch_t はキャラクターに関する構造体で合っていますか?
ch1、ch2 はそれぞれどんなキャラクターですか?


> ch1.san_flag=1; //歩くフラグを立てる。
> ch1.san_flag=0; //向かないフラグを立てる

今見つけたのですが構造体のメンバ san_flag は何のフラグですか?
多分「歩く歩かない」のフラグだと思いますが、変数の名前からはその意味が分かりません
分かるように訂正しておくことをお勧めします


> ch1.zahyou=0; //上向きフラグを立てる

構造体のメンバ zahyou は「座標」ではなく「向き」のようですが、変数の意味と名前が不一致です
一致させておくことをお勧めします


> LoadGraphScreen ( 0, 0, "000.bmp", FALSE );

毎ループ毎に画像を読み込んでいるので処理速度がかなり落ちていると思います
素直に LoadGraph , DrawGraph を使った方がいいと思います


> ・↑が押されたらch.1の画像を2分割した2番目を壁画したい。

×壁画(へきが)
○描画(びょうが)

manako

Re:また課題が出てしまいました・・・・・・

#6

投稿記事 by manako » 17年前

頭が混乱して表記ミスが多かったようです。訂正します。
今、やりたいのはch1のフラグを立てて十字移動させ、決定=スペースキーで
ch2のフラグを立てたいのがひとつ。

もうひとつはスペースキーが押されたら2分割した画像の2番目を描画したい。(ch1の)

今、出ている問題はch1は動くのに、スペースキーを押してもch2の
画像が動かない。ch1の画像描画の変更のやり方がわからない。の二点です。
この、あるキーを押されたら別のフラグを立ててその処理をする方法がわかれば
パズルゲームでも作れるように思うのです。
(正確に言うとchは枠の描画の画像と移動のためでキャラクターとは関係ないです)

簡単に言うとif文である事をされると別のフラグを立てて
そちらの処理に移動したいと言うことです




> ch1.san_flag=1; //歩くフラグを立てる。
> ch1.san_flag=0; //向かないフラグを立てる

>今見つけたのですが構造体のメンバ san_flag は何のフラグですか?

とありますが、枠のx.y座標の増減のためのフラグです。




> ch1.san_flag=0; //向かないフラグを立てる

>向かないフラグが立っている時、このキャラはどこを向いているんでしょう?

そこの部分は行動処理を一区間ずつ毎回行うために必要みたいです。
書かないと座標の増減が一区間では終わらずに延々と続いてしまい、一区間歩かず
同じ方向にずっと動き続けます。

木霊

Re:また課題が出てしまいました・・・・・・

#7

投稿記事 by 木霊 » 17年前

私なりの解釈ですが・・・

最初は「枠1」(ch1)だけを動かす
スペースキーが押されると「枠1」(ch1)は固定し、「枠2」(ch2)だけを動かす
「枠2」を動かしてる間「枠1」は通常とは違う画像を表示する
「枠1・2」の移動は1マス単位(1ドット単位ではない)

と言う事で合ってますか?

木霊

Re:また課題が出てしまいました・・・・・・

#8

投稿記事 by 木霊 » 17年前

「枠」の移動は1ドット単位で、1回の移動が1マス(32ドット)ですね

木霊

Re:また課題が出てしまいました・・・・・・

#9

投稿記事 by 木霊 » 17年前

眠たいのでかなり力技ですがこんな感じでしょうか?

木霊

Re:また課題が出てしまいました・・・・・・

#10

投稿記事 by 木霊 » 17年前

すみません
BCCで作成しましたが画像は御自分で用意して下さい

Frame.bmpは32×64の縦長
BackGround.bmpは640×480の横長です

C++です

manako

Re:また課題が出てしまいました・・・・・・

#11

投稿記事 by manako » 17年前

木霊さん、ありがとうございました。
結局私のプログラムのどこが間違っていたのかぜんぜんわかりませんでしたが
一応考えてるように行動にはなりました。

でも、できるだけあの形で書ける方法はないものでしょうか?
できるだけ今の形を崩さないで書けたほうがこれから先かきやすいんです。
なぜかと言うとパズルゲームはマスの入れ替えがあると思います。

#include "DxLib.h"


typedef struct{
	int x,y,img,zahyou,san_flag;
}ch_t;

int hantei[15][20] = {
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};

int can_or_cannot(int x,int y,int muki){//進めるかを判定する
        if(muki==0)//上向きなら
                if(hantei[y/32-1][x/32]==1)//進めるか判定
                        return 1;//エラー
        if(muki==1)//左向きなら
                if(hantei[y/32][x/32-1]==1)
                        return 1;
        if(muki==2)//下向きなら
                if(hantei[y/32+1][x/32]==1)
                        return 1;
        if(muki==3)//右向きなら
                if(hantei[y/32][x/32+1]==1)
                        return 1;
        return 0;//正常
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
    int image[16],i,j;
    char Key[256];
    ch_t ch1 ch2;

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

    ch1.x    =0;
    ch1.y    =0;
    ch2.x    =0
    ch2.y    =0
    ch1.san_flag=0;
    ch2.san_flag=0;
    ch1.zahyou=3
    ch2.zahyou=3;
.
.
.
.
.
そのときにch1とch2の座標を入れ替えるにはint A とでもしておいて
A = hantei[ch1.x][ch1.y];

hantei[ch1.x][ch1.y] = hantei[ch2.x][ch2.y];

hantei[ch2.x][ch2.y] =A;

のような感じになるとおもいます。
この処理を行うには、ch2の移動フラグのところでEnterを押すとこの処理に
移行させる。

こんなプログラムにする場合、一番最初に書いたソースのように書かないと自分で
もわけがわからなくなりそうなので何かいい方法があれば教えてください。


わがままとわかっていてのお願いですが、よろしくお願いします。

木霊

Re:また課題が出てしまいました・・・・・・

#12

投稿記事 by 木霊 » 17年前

最初のソースだと、ループの最初でch1の判定をしています
そこで方向キーの入力があればzahyouが0~3になり、4にはなりません
スペースキーの判定の前にif~else文を抜けるからです

一方ch2の判定はch1.zahyouが4の時のみ行われますが、キー入力はループの最初で判定されたものを
そのまま使っているのでch1の判定の時に方向キーが押されてなく、かつスペースキーが押されていた時しか
ch2の移動判定は行われないことになります
その時には方向キーが押されていないので、当然ch2は動きません

つまり、方向キーが押されている時は常にch1が動き、ch2は動かないソースになっています

> else if( Key[ KEY_INPUT_SPACE] == 1 )// スペースキー
> ch1.zahyou=4;

の部分をelseを外して直前のif~else文の後ろに出してやればch1からch2への移り変わりだけはうまくいきます

自分のソースも大筋はmanakoさんのものと変わらないと思います
大きく違うのはch1、ch2を配列にして管理しているぐらいでしょうか?

manako

Re:また課題が出てしまいました・・・・・・

#13

投稿記事 by manako » 17年前

なるほど~。
ループの外にスペースキーの判定があるからいけないのですね。

> else if( Key[ KEY_INPUT_SPACE] == 1 )// スペースキー
> ch1.zahyou=4;

>の部分をelseを外して直前のif~else文の後ろに出してやればch1からch2への移り変わりだけはうまくいま


とありますが
	else if( Key[ KEY_INPUT_SPACE]  == 1 )// スペースキー
                     ch1.zahyou=4;

			else                                    //何のボタンも押されてなかったら
                    ch1.san_flag=0; //向かないフラグを立てる
		}
この部分を
			else                                    //何のボタンも押されてなかったら
                    ch1.san_flag=0; //向かないフラグを立てる
		}

			if( Key[ KEY_INPUT_SPACE]  == 1 )// スペースキー
                     ch1.zahyou=4;

と言うことでしょうか?
あと、木霊さんのソースの配列とは私のように座標とキー入力と
増減を別々にせずに一緒にしていると言うことでしょうか?

木霊

Re:また課題が出てしまいました・・・・・・

#14

投稿記事 by 木霊 » 17年前

はい、そういうことです
ですが、このままだとch1が移動中にスペースキーが押された時、ch1の座標(具体的にはX、Yの両方が
共に32で割り切れない時)によってはch2しか動かせないようになってしまいます

ch1が移動中にスペースキーが押されてもch1が32で割り切れる座標まで動きつつ、ch2を操作できるように
するのか、それともch1が移動中はスペースキーを無効にするのか、最初は後者の方が作りやすいと思います


> あと、木霊さんのソースの配列とは私のように座標とキー入力と
> 増減を別々にせずに一緒にしていると言うことでしょうか?

ch1とch2を、自分のソースではFrameとしてまとめています
Frame [ 0 ]がch1、Frame [ 1 ]がch2に対応しています
また、zahyou = 4の代わりに別の変数Choose_Frameを作って、
ch1とch2の切り替え(今見たらch1からch2への一方通行だったorz)を管理しています

同じソースを変数だけ変えて打ち直す(コピペ)なら、関数化やfor、while文を使えるようにした方がミスも
少ないでしょう(現に最初のソースではch2の処理のはずなのにch1のフラグを立てている)

あと、移動時の座標の増減を一度別のメンバ変数X_Move、Y_Moveに渡しておき、毎ループごとにX += X_Moveとさせています(移動していない時はX_Moveは0で計算している)ので「枠1」が移動中に「枠2」に
操作を切り替えても座標が32で割り切れるところまでは勝手に動きます

> LoadGraphScreen( 0 , 0 , "000.bmp" , FALSE ) ;

ループの中で毎回画像を読み込んでいたら重過ぎます
ループ外でint Gr_Handle = LoadGraph ( "000.bmp" );
ループ内ではDrawGraph ( 0, 0, Gr_Handle, FALSE );
としてください

添付ファイルは変更を最小限にしたソースです

木霊

Re:また課題が出てしまいました・・・・・・

#15

投稿記事 by 木霊 » 17年前

> こんなプログラムにする場合、一番最初に書いたソースのように書かないと自分で
> もわけがわからなくなりそうなので何かいい方法があれば教えてください。

今回の場合、動かす「枠」の数だけ移動判定の処理を書くということですね?

とりあえず、メンバ変数zahyouを見直しましょう
zahyou = 0 上方向への移動フラグ
zahyou = 1 左方向への移動フラグ
zahyou = 2 下方向への移動フラグ
zahyou = 3 右方向への移動フラグ
zahyou = 4 別の枠を動かす為のフラグ

と0~3と4で2種類のフラグが混在しています
これは分けた方が後々の為にもいいでしょう

自分ならzahyou = 4の状態を管理する別の変数(先のソースではChoose_Frame)を作り
Choose_Frame = 0 「枠1」を動かす スペースキーでChoose_Frame = 1にする
Choose_Frame = 1 「枠2」を動かす エンターキーでChoose_Frame = 2にする
Choose_Frame = 2 「枠1」と「枠2」の座標を入れ替える 入れ替え終わったらChoose_Frame = 0にする
という感じにします

で、それぞれの移動判定を
if ( Choose_Frame == 0 ) {
// 移動判定の処理
if ( key [ KEY_INPUT_SPACE ] == 1 ) { Choose_Frame = 1; }
}
・・・
if ( Choose_Frame == 1 ) {
// 移動判定の処理
if ( key [ KEY_INPUT_ENTER ] == 1 ) { Choose_Frame = 2; }
}
・・・
if ( Choose_Frame == 2 ) {
// 座標の入れ替え処理
Choose_Frame = 0;
}
とします

やそ

Re:また課題が出てしまいました・・・・・・

#16

投稿記事 by やそ » 17年前

こんにちわ。
別トピのsousiさんの「勉強してきました!」
でもほぼ同じ事をやろうとしていて、やそがいろいろ回答をつけたトピックがあります。

一度ご覧になってみてはどうでしょう。
(ま、最終的には木霊さんと同じような考え方になるんじゃないかと思いますが(笑))

manako

Re:また課題が出てしまいました・・・・・・

#17

投稿記事 by manako » 17年前

やそ様

言われた通りに読んでみます。いま、ちょっと見てみたのですが疑問に思う事、
あるいは、勉強したい事などを検索してみると以外に出てきて勉強になりますね^^


木霊様
初心者の疑問に長々と付き合ってくださり、ありがとうございました。とてもわかりやすかったです。
ですが、後に作っていただいたソースを実行してみるとなぜかスペースキーを押しているときにしか
ch2の画面が動きません。なぜでしょう?<!--1

<kor

extern宣言とグローバル変数の意味について...

#18

投稿記事 by <kor » 17年前

本格的にシューティングゲームの開発をしようと思い、シューティングゲームの館を見ながら、
コピーペーストでどんどん進むより意味を理解しながら自分で手を加えていって進めようと1から見て行くと、
『先ほどのプログラムを分割する』のところに出てきた、extern宣言とグローバル変数の意味が良くわかりませんでした。
ウィキペディアで調べてみましたが(自分の勉強不足で)よく意味が理解できませんでした。
どなたか、extern宣言をしたりグローバル変数を使うとどのような効果や利点があるのか、具体的に教えてくださらないでしょうか?


<kor

Re:extern宣言とグローバル変数の意味について...

#20

投稿記事 by <kor » 17年前

ありがとうございます。よくわかりました。
かなりわかりやすかったです。

たかぎ

Re:extern宣言とグローバル変数の意味について...

#21

投稿記事 by たかぎ » 17年前

DXライブラリを使うのであればC++でしょうが...

基本的には、グローバル変数やそれを利用するためのexternは使わないようにしましょう。
他に実現方法が無い場合や、他の実現方法よりグローバル変数を使う方法の方が有利なことが明らかな場合に限って使うべきです。
つまり、効果や利点が分からないのであれば、使うのは避けたほうが無難です。

閉鎖

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