ジャンケンのプログラムを改造したのですが・・・

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

ジャンケンのプログラムを改造したのですが・・・

#1

投稿記事 by 海老天 » 16年前

管理人様のジャンケンのソースコードを元にして全体を弄り戦闘システムを作ったのですが全く動きません
恐らくおかしいのはmenu()関数だと思うのですがいくら書き直してもうまく動かすことができませんでした
どこが悪いのか指摘していただけると助かります

Dixq (管理人)

Re:ジャンケンのプログラムを改造したのですが・・・

#2

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

menu関数のwhile(1)で無限ループになってます。
GetHitKeyStateAll_2が呼ばれていないので、Keyデータは変わる事がありません。
かといって、このwhile文の中からGetHitKeyStateAll_2を呼ぶべきではありません。
このように、ある部分でループさせる書き方はよくないです。
処理は毎回メインループに戻すようにして下さい。

1/60秒以上処理がメインに返ってこないような処理がある場合はアルゴリズムの見直しをしてみて下さい。

//メッセージ処理をして応答不能になったりしないようにする関数
ProcessMessage()

//画面に書いてある内容を消す関数
ClearDrawScreen()

//キーの入力状態を格納する関数
GetHitKeyStateAll_2(Key)

//描画した内容をモニタに反映する関数
ScreenFlip();

これらの4つの処理は大抵の場合、必ず毎回呼ばないといけない4大関数ですが(というと誤解ありますが)、
これは慣れない内はメインループ以外には書かずに出来るようにしてみて下さい。

とりあえずmenu関数のwhile文をコメントアウトすると動きます。
なお、どこで止まっているかは、ブレイクポイントを使う事でわかります。

Dixq (管理人)

Re:ジャンケンのプログラムを改造したのですが・・・

#3

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

選択項目の実装サンプルです。もし参考になればどうぞ。
十字キーの上下で選択移動、Zキーを押すとその項目が選択された旨を2秒間表示して戻ります。

セレクト項目の最大数やその中身が変動する場合は、何かのデータから取ってくるような処理にするといいと思います。

ちょっと長いので、解読が面倒かもしれませんが・・。
#include "DxLib.h"

/* セレクト項目の最大数 */
#define SELECT_ELEMENT_MAX 10

/* セレクト項目の要素 */
typedef struct{
    int iX, iY;
    char cName[128];
}Element_t;

/* セレクト項目要素の親 */
typedef struct{
    int iNum;    //今選択されている番号
    int iMax;        //登録されている数
    Element_t Element[ SELECT_ELEMENT_MAX ];
}Select_t;

/* キー状態格納変数 */
int Key[256];

/* キー入力管理関数 */
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[/url]){
    char GetHitKeyStateAll_Key[256];
    GetHitKeyStateAll( GetHitKeyStateAll_Key );
    for(int i=0;i<256;i++)
    {
        if(GetHitKeyStateAll_Key==1) GetHitKeyStateAll_InputKey++;
        else                            GetHitKeyStateAll_InputKey=0;
    }
    return 0;
}

/* 呼ぶ関数を制御する変数 */
int FunctionState;

/* セレクト要素にメニュー情報を登録する */
void EnterSelectString( Select_t *Sel, int iX, int iY, char cStr[/url] ){
    strcpy( Sel->Element[ Sel->iMax ].cName, cStr );    //文字列格納
    Sel->Element[ Sel->iMax ].iX = iX;                  //座標格納
    Sel->Element[ Sel->iMax ].iY = iY;
    Sel->iMax++;                                        //今いくつ要素が入っているかカウント
}

/* セレクト情報初期化 */
void SelectIni( Select_t *Sel ){
    memset ( Sel, 0, sizeof(Select_t) );                //全て0に
    EnterSelectString( Sel , 100, 100, "メニュー0" );
    EnterSelectString( Sel , 100, 150, "メニュー1" );
    EnterSelectString( Sel , 100, 200, "メニュー2" );
    EnterSelectString( Sel , 100, 250, "メニュー3" );
    EnterSelectString( Sel , 100, 300, "メニュー4" );
    EnterSelectString( Sel , 400, 450, "メニューA" );
    FunctionState=1;                                    //次の関数を呼ぶ
}

/* キー入力などからセレクト状況を計算する */
void SelectCalc( Select_t *Sel){
    /* 上下キーが押されたら現在選択されている番号を表す->iNumを変化させる */
    if( Key[ KEY_INPUT_UP ] == 1 )
    {
        Sel->iNum--;
        if( Sel->iNum < 0 )
        {
            Sel->iNum = Sel->iMax - 1 ;
        }
    }
    if( Key[ KEY_INPUT_DOWN ] == 1 )
    {
        Sel->iNum = (++Sel->iNum) % Sel->iMax ;
    }
}

/* セレクト項目と現在のセレクト状況描画 */
void SelectGraph( Select_t Sel){
    int i, Col = GetColor(255,255,255) ;
    for(i=0; i<Sel.iMax; i++)
    {
        DrawFormatString( Sel.Element[ i ].iX, Sel.Element[ i ].iY, Col, "%s", Sel.Element[ i ].cName );
    }
    DrawCircle( Sel.Element[ Sel.iNum ].iX-20, Sel.Element[ Sel.iNum ].iY+7, 7, Col, TRUE );
}

/* セレクトメイン */
void SelectMain( Select_t *Sel ){
    SelectCalc( Sel );    //計算
    SelectGraph( *Sel );//描画
    if( Key[ KEY_INPUT_Z ] == 1 )
    {
        FunctionState = 2;//けって~
    }
}

//決定されて2秒間その項目を表示する
void Decided( Select_t Sel ){
    int Col = GetColor( 255, 255, 255 );
    static int cnt=0;
    DrawFormatString( 100, 100, Col, "%sが選択されました。", Sel.Element[ Sel.iNum ].cName );
    cnt++;
    if( cnt > 120 )//60FPSのモニタで2秒たったら
    {
        cnt = 0;
        FunctionState = 0;
    }
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    
    Select_t Select;
    
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理        ↑画面をクリア      ↑入力状態を保存       ↑ESCが押されていない
        switch(FunctionState){
            case 0:
                //初期化
                SelectIni( &Select );
                break;
            case 1:
                //メイン計算
                SelectMain( &Select );
                break;
            case 2:
                //決定した瞬間その項目を表示->0に戻る
                Decided( Select );
                break;
        }
        ScreenFlip();
    }

    DxLib_End();
    return 0;
}
 

海老天

Re:ジャンケンのプログラムを改造したのですが・・・

#4

投稿記事 by 海老天 » 16年前

わざわざアドバイスありがとうございます
大変参考になりました!

閉鎖

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