マリオ風のジャンプについて

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

マリオ風のジャンプについて

#1

投稿記事 by ボラ天神 » 11年前

私は今DxライブラリとC言語を使ってマリオ風のアクションゲームを作っています。
作成手順として背景の表示、移動、加速、減速、ジャンプ、とやってきたのですが、マリオみたく長くボタンを押すと大きくジャンプするみたいなことができません。
色々なサイトのコードを参考にさせてもらっていて頑張ってみたのですが、そのジャンプの処理は実装することができませんでした。
C言語は少し前から授業で触った程度です。Dxライブラリも同時期に使い始めました。

どのようにしたら私が望んでいるようにできるのか教えていただけると助かります。

コード:

#include "DxLib.h"

int count=0;
char Key[256];

void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);

struct Chara {
	double x;
	double y;
	int g;
	double spdX;
	double spdY;
};
    

struct Chara mario;


int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1) return(-1);

	SetDrawScreen(DX_SCREEN_BACK);
	mario.x = (double)0;
	mario.y = (double)32;//480 - 32 * 2;
	mario.g = LoadGraph("media\\test001.png");
	mario.spdX = (double)0;
	mario.spdY = (double)0;

	while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		ClsDrawScreen();
		int Bg_flag = 0;
		int count_flag = 0;
		int  grav = 10;
		int Buf[256];
		GetKeyInput(Buf);

		if(Bg_flag == 0){
			DrawBox(0,0,640,480,GetColor(105,122,243),TRUE);	//背景を水色に1 - 1
			Bg_flag = 1;
		}
		fps();
		count++;
		//-------------------------------------------------------------------------



		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
		if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
			mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
		if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;		
		}




		mario.y -= mario.spdY;
		mario.spdY -= 1;

		if(mario.x < 0)	mario.x = 0;
		//if(mario.x > 640 - 32) mario.x = 640 - 32;
		if((CheckHitKey(KEY_INPUT_Z))) {
			if(mario.spdX > 8.0) mario.spdX = 8.0;
			if(mario.spdX < -8.0) mario.spdX = -8.0;
		}else {
			if(mario.spdX > 5.0) mario.spdX = 5.0;
			if(mario.spdX < -5.0) mario.spdX = -5.0;
		}
		if(count_flag > 1)	{count_flag = 0;	mario.spdX = 0;}
		if(mario.y > 480 - 32) {mario.y = 480 - 32;	mario.spdY = 0;}
		if(mario.spdY > 30.0) mario.spdY = 30.0;


		if(((CheckHitKey(KEY_INPUT_C)) == TRUE && mario.y == 480 -32) && (Buf[KEY_INPUT_C] > 0 && Buf[KEY_INPUT_C] < 10)) {
			mario.spdY = 15;
		}else if((CheckHitKey(KEY_INPUT_C)) == TRUE && mario.y == 480 -32 && (Buf[KEY_INPUT_C] >= 10)) {
			mario.spdY = 20;
		}

		DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);


		//-------------------------------------------------------------------------
		ScreenFlip();
		wait_fanc();
	}
	DxLib_End();
	return(0);
}



void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}

void fps(){
    int i;
    static int t=0,ave=0,f[60];
 
    f[count%60]=GetNowCount()-t;
    t=GetNowCount();
    if(count%60==59){
        ave=0;
        for(i=0;i<60;i++)
            ave+=f[i];
        ave/=60;
    }
    if(ave!=0){
        DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
        DrawFormatString(0,20,GetColor(0,0,0),"%dms"  ,ave);
    }
    return;
}

void GetKeyInput( int *KeyBuf ){
	char damy[256];
	GetHitKeyStateAll( damy ) ;
	for( int i=0 ; i<256 ; i++ ){
		if( damy[i] == 1 )
			KeyBuf[i]++;
		else
			KeyBuf[i] = 0;
	}

}
コード汚くて本当にすみません。

ボラ天神

Re: マリオ風のジャンプについて

#2

投稿記事 by ボラ天神 » 11年前

追伸:キーボードの右と左を同時に押すとおかしな挙動をするのも気になるので教えていただけると助かります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#3

投稿記事 by softya(ソフト屋) » 11年前

ジャンプに関しては完全に検証してませんが、構造体にJumpCountを追加して初期化。
そのあとの処理は、こんな感じです。

コード:

        if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
        if(mario.spdY > 30.0) mario.spdY = 30.0;
 
		if( mario.JumpCount == 0 ) {
			if( Buf[KEY_INPUT_C] > 0  ) {
				mario.JumpCount++;
			}
		} else {
			if( Buf[KEY_INPUT_C] > mario.JumpCount  ) {
				if( mario.JumpCount == 10 ) {
					mario.spdY = 20;
				} else if( mario.JumpCount < 10 ) {
					mario.spdY = 15;
				}
			}
			mario.JumpCount++;
		}
左右キーの同時押しは、同時に押され倒されていない時のみの右キーとキー左の処理を書いてください。同時に押されたら押されていないと同じ扱いに成るようにします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ボラ天神

Re: マリオ風のジャンプについて

#4

投稿記事 by ボラ天神 » 11年前

>> softya(ソフト屋) さん
ありがとうございます!!
今組み込んでみたいと思います!!

ボラ天神

Re: マリオ風のジャンプについて

#5

投稿記事 by ボラ天神 » 11年前

ジャンプは一応成功しましたがやはりプログラムの順番的に

コード:

if( Buf[KEY_INPUT_C] > mario.JumpCount) {
	if(mario.JumpCount == 10) {
		mario.spdY = 15;
	}else if(mario.JumpCount < 10) {
		mario.spdY = 10;
	}
}
Cボタンを押し続けると10を代入してから15を代入する形になるので長押しした場合スムーズにジャンプせずにグイン・グインと二段階に分かれてジャンプしてしまいます。
これはどうしようもないことなのでしょうか?

それと左右の挙動についてですが変更してみたのですがもちろん動きませんでしたw
自分でもおかしいと思いながら直したのですがどこが間違ってるのでしょうか?

コード:

if(CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0){
	if(CheckHitKey(KEY_INPUT_LEFT) == 1){
		if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
			mario.spdX -= 1.0;
		}else {
			mario.spdX -= 0.3;
		}
		mario.x += mario.spdX;
	}
	if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
		mario.spdX -= 0.3;
		mario.x += mario.spdX;
		count_flag += 1;
	}
}
if(CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0){
	if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
		if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
			mario.spdX += 1.0;
		}else {
			mario.spdX += 0.3;
		}
		mario.x += mario.spdX;			
	}
	if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
		mario.spdX += 0.3;
		mario.x += mario.spdX;
		count_flag += 1;		
	}
}

ボラ天神

Re: マリオ風のジャンプについて

#6

投稿記事 by ボラ天神 » 11年前

すみません/コードで閉じるの忘れてました!!

nil
記事: 428
登録日時: 12年前

Re: マリオ風のジャンプについて

#7

投稿記事 by nil » 11年前

10か15に統一すればいいです

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#8

投稿記事 by softya(ソフト屋) » 11年前

涼雅 さんが書きました:10か15に統一すればいいです
10から15の間を計算で求めて多段階に分解するって方法もありますね。
【追記】気持ちよくなるポイントを色々調整する必要があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#9

投稿記事 by softya(ソフト屋) » 11年前

左右の問題について

if(CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0){
だとif条件がRIGHTがOFFでかつLEFTがOFFの時にしか成立しないので、この中のif文でRIGHTがONか聞いても無駄です。

私が書いたのは、「左右が同時に押されたら押されていないと同じ扱いに成るようにします。」なので、
CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0

CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1
の時は何もしない様に素直に書くだけです。elseをうまく使ってください。

あとキーが押されていなくても動作する必要のある処理をCheckHitKeyのあるif文の中に書いてはいけません。
キーが押された時だけする処理とキーが押された後で起こる反応はかき分けてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: マリオ風のジャンプについて

#10

投稿記事 by ISLe » 11年前

マリオジャンプは、跳び上がる初速は同じで、ボタンを押していないとき落下加速度が大きくなるようにするのだったかと。

ボラ天神

Re: マリオ風のジャンプについて

#11

投稿記事 by ボラ天神 » 11年前

涼雅 さんが書きました:10か15に統一すればいいです
実際のマリオにできるだけ近づけたいのでISLeさんの意見を採用してみたいと思います。しかし、返信はとても為になりますし、本物のマリオに近づくための一歩だと思うのでどしどし書いていただけると本当に嬉しく思います。

あと左右の件なのですが、説明していただいていることはよくわかるのですが、経験が足りないためか、どこにその処理をいれたらいいかわかりません。試しに色々変えてみたのですがうまくいかないのでもう少し教えていただけると幸いです。
ISLe さんが書きました:マリオジャンプは、跳び上がる初速は同じで、ボタンを押していないとき落下加速度が大きくなるようにするのだったかと。
このような本物のマリオの動作について返信していただけるととてもありがたいと思います。具体的にはジャンプボタンを押したら上限は決まっていて、そこまで飛び、私たちが高く飛んでいるように見えるのは落下速度が遅くなるからなのですか?
実際に高く飛んでいるように見えたのは目の錯覚なのでしょうかww

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#12

投稿記事 by softya(ソフト屋) » 11年前

ボラ天神 さんが書きました: あと左右の件なのですが、説明していただいていることはよくわかるのですが、経験が足りないためか、どこにその処理をいれたらいいかわかりません。試しに色々変えてみたのですがうまくいかないのでもう少し教えていただけると幸いです。
こんな感じでしょうか?
条件は素直に書くのが一番です。

コード:

	//	左右を押していないか同時押しは押していないのと同じ。
	if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) ||
		(CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1)		) {
		//	左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
			:
			:
		
		
	} else {
		//	右キーの処理。移動・ダッシュ。
			:
			:
		
		//	左キーの処理。移動・ダッシュ。
			:
			:
	}
ボラ天神 さんが書きました:
ISLe さんが書きました:マリオジャンプは、跳び上がる初速は同じで、ボタンを押していないとき落下加速度が大きくなるようにするのだったかと。
このような本物のマリオの動作について返信していただけるととてもありがたいと思います。具体的にはジャンプボタンを押したら上限は決まっていて、そこまで飛び、私たちが高く飛んでいるように見えるのは落下速度が遅くなるからなのですか?
実際に高く飛んでいるように見えたのは目の錯覚なのでしょうかww
ISLeさんの方式だと上方向の速度は同じでも下方向の加速度を減らすので当然ながらジャンプ頂点は高くなります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ボラ天神

Re: マリオ風のジャンプについて

#13

投稿記事 by ボラ天神 » 11年前

コード:

#include "DxLib.h"

/*        if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
        if(mario.spdY > 30.0) mario.spdY = 30.0;
 
        if( mario.JumpCount == 0 ) {
            if( Buf[KEY_INPUT_C] > 0  ) {
                mario.JumpCount++;
            }
        } else {
            if( Buf[KEY_INPUT_C] > mario.JumpCount  ) {
                if( mario.JumpCount == 10 ) {
                    mario.spdY = 20;
                } else if( mario.JumpCount < 10 ) {
                    mario.spdY = 15;
                }
            }
            mario.JumpCount++;
        }
		*/

int count=0;
char Key[256];

void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);

struct Chara {
	double x;
	double y;
	int g;
	double spdX;
	double spdY;
	int JumpCount;
};
    

struct Chara mario;


int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1) return(-1);

	SetDrawScreen(DX_SCREEN_BACK);
	mario.x = (double)0;
	mario.y = (double)32;//480 - 32 * 2;
	mario.g = LoadGraph("media\\test001.png");
	mario.spdX = (double)0;
	mario.spdY = (double)0;

	while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		ClsDrawScreen();
		int Bg_flag = 0;
		int count_flag = 0;
		int  grav = 10;
		int Buf[256];
		GetKeyInput(Buf);

		if(Bg_flag == 0){
			DrawBox(0,0,640,480,GetColor(105,122,243),TRUE);	//背景を水色に1 - 1
			Bg_flag = 1;
		}
		fps();
		count++;
		//-------------------------------------------------------------------------

		/*

		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
		if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
			mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
	

		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
		if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;		
		}

		*/
		
	 if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) || (CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1)     ) {
        //  左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
		if(mario.spdX > 0) {
            mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
		if(mario.spdX < 0){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;	
		 }
        
    } else {
        //  右キーの処理。移動・ダッシュ。
		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
        //  左キーの処理。移動・ダッシュ。
		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
    }



		mario.y -= mario.spdY;
		mario.spdY -= 1;

		if(mario.x < 0)	mario.x = 0;
		//if(mario.x > 640 - 32) mario.x = 640 - 32;
		if((CheckHitKey(KEY_INPUT_Z))) {
			if(mario.spdX > 8.0) mario.spdX = 8.0;
			if(mario.spdX < -8.0) mario.spdX = -8.0;
		}else {
			if(mario.spdX > 5.0) mario.spdX = 5.0;
			if(mario.spdX < -5.0) mario.spdX = -5.0;
		}
		if(count_flag > 1)	{count_flag = 0;	mario.spdX = 0;}
		if(mario.y > 480 - 32) {mario.y = 480 - 32;	mario.spdY = 0; mario.JumpCount = 0;}
		if(mario.spdY > 30.0 ) mario.spdY = 30.0;

		if( mario.JumpCount == 0) {
			if( Buf[KEY_INPUT_C] > 0) {
				mario.JumpCount++;
			}
		}else{
			if( Buf[KEY_INPUT_C] > mario.JumpCount) {
				if(mario.JumpCount < 10) {
					mario.spdY = 10;
				}else if(mario.JumpCount == 10) {
					mario.spdY = 15;
				}
			}
			mario.JumpCount++;
		}





		DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);


		//-------------------------------------------------------------------------
		ScreenFlip();
		wait_fanc();
	}
	DxLib_End();
	return(0);
}



void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}

void fps(){
    int i;
    static int t=0,ave=0,f[60];
 
    f[count%60]=GetNowCount()-t;
    t=GetNowCount();
    if(count%60==59){
        ave=0;
        for(i=0;i<60;i++)
            ave+=f[i];
        ave/=60;
    }
    if(ave!=0){
        DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
        DrawFormatString(0,20,GetColor(0,0,0),"%dms"  ,ave);
    }
    return;
}

void GetKeyInput( int *KeyBuf ){
	char damy[256];
	GetHitKeyStateAll( damy ) ;
	for( int i=0 ; i<256 ; i++ ){
		if( damy[i] == 1 )
			KeyBuf[i]++;
		else
			KeyBuf[i] = 0;
	}

}
これで左右の変な挙動は治りました!!!
さすがですねww
コードを素直にかつ単純に綺麗に書く事が大切ということをまた思い知らされましたw

それとジャンプについてですが、上方向にジャンプしているがジャンプした瞬間から下方向への力も働いているということですか?

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: マリオ風のジャンプについて

#14

投稿記事 by ISLe » 11年前

ボラ天神 さんが書きました:このような本物のマリオの動作について返信していただけるととてもありがたいと思います。具体的にはジャンプボタンを押したら上限は決まっていて、そこまで飛び、私たちが高く飛んでいるように見えるのは落下速度が遅くなるからなのですか?
実際に高く飛んでいるように見えたのは目の錯覚なのでしょうかww
高さの上限ではなくて、跳び上がる強さといいましょうか。
例えば、月の重力は地球の6分の1しかないので、月面では地球よりも高く飛べるわけです。

簡単なサンプルコードを書いてみました。
アルゴリズムはとてもシンプルです。

コード:

#include "DxLib.h"
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	ChangeWindowMode(TRUE);
	if (DxLib_Init() != 0) return 0;
	SetDrawScreen(DX_SCREEN_BACK);

	const int SCREEN_W = 640;
	const int SCREEN_H = 480;
	const int CHARA_W = 64;
	const int CHARA_H = 64;

	int x, y;
	bool jumping = false;
	float vy, ga;
	x = (SCREEN_W-CHARA_W)/2;
	y = SCREEN_H-CHARA_H;

	while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
		if (CheckHitKey(KEY_INPUT_C) != 0) {
			if (!jumping) {
				vy = -16.0f; // 初速
				jumping = true;
			}
			ga = 0.5f; // ジャンプボタンを押しているときの落下加速度
		}
		else {
			ga = 3.0f; // ジャンプボタンを離しているときの落下加速度
		}
		y += vy;
		vy += ga;
		if (y > SCREEN_H-CHARA_H) {
			y = SCREEN_H-CHARA_H;
			vy = ga = 0.0f;
			jumping = false;
		}
		DrawBox(x, y, x+CHARA_W, y+CHARA_H, GetColor(255,255,255), TRUE);
	}
 
	DxLib_End();
	return 0;
}
Cキーで白い箱がジャンプします。
ジャンプ中にキーを離しているあいだ落下速度が速くなります。
見た目にはボタンを離したところでストンと落下するように見えます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#15

投稿記事 by softya(ソフト屋) » 11年前

ボラ天神 さんが書きました:それとジャンプについてですが、上方向にジャンプしているがジャンプした瞬間から下方向への力も働いているということですか?
ご自分で毎フレーム
mario.spdY -= 1;
されてますよね?これが下方向の加速度です。
つまり、マイナスなので下方向に速度が毎フレーム1づつ増える(加速度)処理です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: マリオ風のジャンプについて

#16

投稿記事 by ISLe » 11年前

落下加速度をもっと小さくすると、水中ステージでマリオが手で掻いたあとゆっくり下降するのを表現できます。
つまり、ジャンプと水中の動きはパラメータが違うだけだということです。

ボラ天神

Re: マリオ風のジャンプについて

#17

投稿記事 by ボラ天神 » 11年前

お二人方が言っていることが分かりました!!
しかし何故かサンプルプログラムが私の環境で動きませんでした。しかしサンプルプログラムを上げていただいたおかげで更に理解を深めることができました!

内容は理解できたと思うのですが、実際に組み込んでないので今から頑張ってみたいと思います!
できたらまたあげたいと思います。

ボラ天神

Re: マリオ風のジャンプについて

#18

投稿記事 by ボラ天神 » 11年前

本当に申し訳ありません。私はわかったつもりだったのかもしれませんww

今まで組み込んでみていたのですが、やってみると難しく成功しません。
ISLeさんのサンプルコードを参考に作ってみたのですがどうもうまくいきません。
ゲームプログラミングではなく基礎C言語でつまづいている可能性もありますが、どのように組み込めばよいでしょうか?

教えていただけるととても助かります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#19

投稿記事 by softya(ソフト屋) » 11年前

ボラ天神 さんが書きました:本当に申し訳ありません。私はわかったつもりだったのかもしれませんww

今まで組み込んでみていたのですが、やってみると難しく成功しません。
ISLeさんのサンプルコードを参考に作ってみたのですがどうもうまくいきません。
ゲームプログラミングではなく基礎C言語でつまづいている可能性もありますが、どのように組み込めばよいでしょうか?

教えていただけるととても助かります。
現状のコードを提示してください。
その方が自分で考えたものですから問題点を指摘された時の理解度が高いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ボラ天神

Re: マリオ風のジャンプについて

#20

投稿記事 by ボラ天神 » 11年前

コード:

#include "DxLib.h"

/*        if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
        if(mario.spdY > 30.0) mario.spdY = 30.0;
 
        if( mario.JumpCount == 0 ) {
            if( Buf[KEY_INPUT_C] > 0  ) {
                mario.JumpCount++;
            }
        } else {
            if( Buf[KEY_INPUT_C] > mario.JumpCount  ) {
                if( mario.JumpCount == 10 ) {
                    mario.spdY = 20;
                } else if( mario.JumpCount < 10 ) {
                    mario.spdY = 15;
                }
            }
            mario.JumpCount++;
        }
		*/

int count=0;
char Key[256];

void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);

struct Chara {
	double x;
	double y;
	int g;
	double spdX;
	double spdY;
	int JumpCount;
};
    

struct Chara mario;


int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1) return(-1);

	SetDrawScreen(DX_SCREEN_BACK);
	mario.x = (double)0;
	mario.y = (double)32;//480 - 32 * 2;
	mario.g = LoadGraph("media\\test001.png");
	mario.spdX = (double)0;
	mario.spdY = (double)0;

	while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		ClsDrawScreen();
		int Bg_flag = 0;
		int count_flag = 0;
		int  grav = 10;
		int Buf[256];
		bool jumpflag = false;
		double oti;
		GetKeyInput(Buf);

		if(Bg_flag == 0){
			DrawBox(0,0,640,480,GetColor(105,122,243),TRUE);	//背景を水色に1 - 1
			Bg_flag = 1;
		}
		fps();
		count++;
		//-------------------------------------------------------------------------

		/*

		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
		if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
			mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
	

		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
		if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;		
		}

		*/
		
	 if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) || (CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1)     ) {
        //  左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
		if(mario.spdX > 0) {
            mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
		if(mario.spdX < 0){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;	
		 }
        
    } else {
        //  右キーの処理。移動・ダッシュ。
		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
        //  左キーの処理。移動・ダッシュ。
		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
    }





		if(mario.x < 0)	mario.x = 0;
		//if(mario.x > 640 - 32) mario.x = 640 - 32;
		if((CheckHitKey(KEY_INPUT_Z))) {
			if(mario.spdX > 8.0) mario.spdX = 8.0;
			if(mario.spdX < -8.0) mario.spdX = -8.0;
		}else {
			if(mario.spdX > 5.0) mario.spdX = 5.0;
			if(mario.spdX < -5.0) mario.spdX = -5.0;
		}
		if(count_flag > 1)	{count_flag = 0;	mario.spdX = 0;}
		if(mario.y > 480 - 32) {mario.y = 480 - 32;	mario.spdY = 0; mario.JumpCount = 0;}
		if(mario.spdY > 30.0 ) mario.spdY = 30.0;

		/*xxx:if( mario.JumpCount == 0) {
			if( Buf[KEY_INPUT_C] > 0) {
				mario.JumpCount++;
			}
		}else{
			if( Buf[KEY_INPUT_C] > mario.JumpCount) {
				if(mario.JumpCount < 10) {
					mario.spdY = 10;
				}else if(mario.JumpCount == 10) {
					mario.spdY = 15;
				}
			}
			mario.JumpCount++;
		}
		xxx:*/
		if(KEY_INPUT_C == 1) {
			if(!jumpflag) {
				mario.spdY = 15;
				jumpflag = true;
			}
			oti = 0.5; 
		}else{
			if(!jumpflag){
				oti = 3.0;
			}
		}


		mario.y -= mario.spdY;
		mario.spdY -= oti;

		DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);


		//-------------------------------------------------------------------------
		ScreenFlip();
		wait_fanc();
	}
	DxLib_End();
	return(0);
}



void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}

void fps(){
    int i;
    static int t=0,ave=0,f[60];
 
    f[count%60]=GetNowCount()-t;
    t=GetNowCount();
    if(count%60==59){
        ave=0;
        for(i=0;i<60;i++)
            ave+=f[i];
        ave/=60;
    }
    if(ave!=0){
        DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
        DrawFormatString(0,20,GetColor(0,0,0),"%dms"  ,ave);
    }
    return;
}

void GetKeyInput( int *KeyBuf ){
	char damy[256];
	GetHitKeyStateAll( damy ) ;
	for( int i=0 ; i<256 ; i++ ){
		if( damy[i] == 1 )
			KeyBuf[i]++;
		else
			KeyBuf[i] = 0;
	}

}
です。
さっき消してしまって作り直したのですが、更に別な挙動になってしまいましたが、結果的におかしいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#21

投稿記事 by softya(ソフト屋) » 11年前

分析力を身につけるためにも、おかしい状態を出来るだけ正確・具体的に説明してくださいね。
それと、自分でで調べたほうが良いと思いますので方法を教えます。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2

まず、自分で調べてみて何処が悪かったか報告をお待ちしています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ボラ天神

Re: マリオ風のジャンプについて

#22

投稿記事 by ボラ天神 » 11年前

コード:

#include "DxLib.h"

/*        if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount=0; }
        if(mario.spdY > 30.0) mario.spdY = 30.0;
 
        if( mario.JumpCount == 0 ) {
            if( Buf[KEY_INPUT_C] > 0  ) {
                mario.JumpCount++;
            }
        } else {
            if( Buf[KEY_INPUT_C] > mario.JumpCount  ) {
                if( mario.JumpCount == 10 ) {
                    mario.spdY = 20;
                } else if( mario.JumpCount < 10 ) {
                    mario.spdY = 15;
                }
            }
            mario.JumpCount++;
        }
		*/

int count=0;
char Key[256];

void wait_fanc();
void fps();
void GetKeyInput(int *KeyBuf);

struct Chara {
	double x;
	double y;
	int g;
	double spdX;
	double spdY;
	int JumpCount;
};
    

struct Chara mario;


int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	AllocConsole();
	freopen("CONOUT$", "w",stdout);
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1) return(-1);

	SetDrawScreen(DX_SCREEN_BACK);
	mario.x = (double)0;
	mario.y = (double)32;//480 - 32 * 2;
	mario.g = LoadGraph("media\\test001.png");
	mario.spdX = (double)0;
	mario.spdY = (double)0;
	bool jumpflag = false;
	while(ProcessMessage() == 0&& CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		ClsDrawScreen();
		int Bg_flag = 0;
		int count_flag = 0;
		int  grav = 10;
		int Buf[256];
		
		double oti;
		GetKeyInput(Buf);

		if(Bg_flag == 0){
			DrawBox(0,0,640,480,GetColor(105,122,243),TRUE);	//背景を水色に1 - 1
			Bg_flag = 1;
		}
		fps();
		count++;
		//-------------------------------------------------------------------------

		/*

		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
		if(((CheckHitKey(KEY_INPUT_RIGHT)) == false) &&(CheckHitKey(KEY_INPUT_LEFT) == false) && (mario.spdX > 0)){
			mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
	

		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
		if((CheckHitKey(KEY_INPUT_LEFT) == false) && ((CheckHitKey(KEY_INPUT_RIGHT)) == false) && (mario.spdX < 0)){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;		
		}

		*/
		
	 if( (CheckHitKey(KEY_INPUT_RIGHT) == 0 && CheckHitKey(KEY_INPUT_LEFT) == 0) || (CheckHitKey(KEY_INPUT_RIGHT) == 1 && CheckHitKey(KEY_INPUT_LEFT) == 1)     ) {
        //  左右のスピードの摩擦・慣性処理。キーを離すとしばらくして停止。
		if(mario.spdX > 0) {
            mario.spdX -= 0.3;
			mario.x += mario.spdX;
			count_flag += 1;
		}
		if(mario.spdX < 0){
			mario.spdX += 0.3;
			mario.x += mario.spdX;
			count_flag += 1;	
		 }
        
    } else {
        //  右キーの処理。移動・ダッシュ。
		if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX += 1.0;
			}else {
				mario.spdX += 0.3;
			}
			mario.x += mario.spdX;			
		}
        //  左キーの処理。移動・ダッシュ。
		if(CheckHitKey(KEY_INPUT_LEFT) == 1){
			if(CheckHitKey(KEY_INPUT_Z) == TRUE) {
				mario.spdX -= 1.0;
			}else {
				mario.spdX -= 0.3;
			}
			mario.x += mario.spdX;
		}
    }

	 	if(Buf[KEY_INPUT_C] > 0) {
			if(!jumpflag) {
				mario.spdY = 16;
				jumpflag = true;
			}else{
				oti = 0.7; 
			}
		}else{
			
			oti = 1.2;
			
		}
		printf("%d",jumpflag);


		mario.y -= mario.spdY;
		mario.spdY -= oti;



		if(mario.x < 0)	mario.x = 0;
		//if(mario.x > 640 - 32) mario.x = 640 - 32;
		if((CheckHitKey(KEY_INPUT_Z))) {
			if(mario.spdX > 8.0) mario.spdX = 8.0;
			if(mario.spdX < -8.0) mario.spdX = -8.0;
		}else {
			if(mario.spdX > 5.0) mario.spdX = 5.0;
			if(mario.spdX < -5.0) mario.spdX = -5.0;
		}
		if(count_flag > 1)	{count_flag = 0;	mario.spdX = 0;}
		if(mario.y > 480 - 32) {mario.y = 480 - 32;	mario.spdY = 0; mario.JumpCount = 0; jumpflag = false;}
		if(mario.spdY > 30.0 ) mario.spdY = 30.0;

		/*xxx:
		mario.y += mario.spdY;
		mario.spdY += oti;

		if( mario.JumpCount == 0) {
			if( Buf[KEY_INPUT_C] > 0) {
				mario.JumpCount++;
			}
		}else{
			if( Buf[KEY_INPUT_C] > mario.JumpCount) {
				if(mario.JumpCount < 10) {
					mario.spdY = 10;
				}else if(mario.JumpCount == 10) {
					mario.spdY = 15;
				}
			}
			mario.JumpCount++;
		}
		xxx:*/

		DrawFormatString(300,0,GetColor(0,0,0),"X : %f"  ,mario.x);
		DrawFormatString(300,20,GetColor(0,0,0),"Y : %f"  ,mario.y);

		DrawGraph((int)mario.x, (int)mario.y, mario.g, TRUE);


		//-------------------------------------------------------------------------
		ScreenFlip();
		wait_fanc();
	}
	DxLib_End();
	return(0);
}



void wait_fanc(){
    int term;
    static int t=0;
    term = GetNowCount()-t;
    if(16-term>0)
            Sleep(16-term);
    t=GetNowCount();
    return;
}

void fps(){
    int i;
    static int t=0,ave=0,f[60];
 
    f[count%60]=GetNowCount()-t;
    t=GetNowCount();
    if(count%60==59){
        ave=0;
        for(i=0;i<60;i++)
            ave+=f[i];
        ave/=60;
    }
    if(ave!=0){
        DrawFormatString(0, 0,GetColor(0,0,0),"%.1fFPS",1000.0/(double)ave);
        DrawFormatString(0,20,GetColor(0,0,0),"%dms"  ,ave);
    }
    return;
}

void GetKeyInput( int *KeyBuf ){
	char damy[256];
	GetHitKeyStateAll( damy ) ;
	for( int i=0 ; i<256 ; i++ ){
		if( damy[i] == 1 )
			KeyBuf[i]++;
		else
			KeyBuf[i] = 0;
	}

}
一応出来ました!!
悪かった点が確かなのかわからないので変えたところを書きたいと思います。
まず、if(mario.y > 480 - 32) {mario.y = 480 - 32; mario.spdY = 0; mario.JumpCount = 0; jumpflag = false;}
を書いたあとにジャンプの処理をしていたので、その前にジャンプの処理を書きました。
これにより、カクカクする動作が消えました。

次に地面についた時にjumpflagをfalseにしていなかったので追加しました。

コード:

if(Buf[KEY_INPUT_C] > 0) {
	if(!jumpflag) {
		mario.spdY = 16;
		jumpflag = true;
	}else{
		oti = 0.7; 
	}
}else{			
	oti = 1.2;		
}
これですが、直した点は、まずKEY_INPUT_C == 1を上記のに変えました。これはなぜできなかったのかわかないです。
次にCkeyを押している時にjumpflagがtrueのときだけoti = 0.7を実行するようにしました。最初はprintfデバッグで確認したらここにプログラムの流れがこなかったので色々試したら簡単にまとまってしまいました。
次はCkeyが押されていない時にjumpflagがfalseの場合のみ oti = 1.2を実行していたので、それを取り除きました。これにより地面より上にいる場合はキーに触れていなくても必ず下に落ちてくるようになりました。

おそらく以上のことを変えました。
久しぶりに昔のマリオをやってみたのですが、なかなかジャンプの綺麗さが違って驚きましたww
意外とジャンプが低く、大きいジャンプと低いジャンプの差がキャラ1つ分位ありました。
色々数値をいじってみたのですがなかなか本物に近づけません。
これ以外にも何らかの処理があるのでしょうか?
謎ですww

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#23

投稿記事 by softya(ソフト屋) » 11年前

KEY_INPUT_C == 1がうまくいかない理由はKEY_INPUT_CとBuf[KEY_INPUT_C]をprintfして比べてみると分かると思います。

問題のジャンプですが、調べてみると面白い方法で計算しているみたいです。
「マリオのジャンプ実装法とVerlet積分 - Gemmaの日記」
http://d.hatena.ne.jp/Gemma/20080517/1211010942

出てくる言葉はややこしく見えますが、やっていることは簡単ですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ボラ天神

Re: マリオ風のジャンプについて

#24

投稿記事 by ボラ天神 » 11年前

出てくる言葉が難しくてわからない今日この頃ですねwww

一体どういうふうになっているのですかね

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: マリオ風のジャンプについて

#25

投稿記事 by softya(ソフト屋) » 11年前

ボラ天神 さんが書きました:出てくる言葉が難しくてわからない今日この頃ですねwww

一体どういうふうになっているのですかね
「マリオのジャンプ実装法とVerlet積分(実践編) - Gemmaの日記」
http://d.hatena.ne.jp/Gemma/20080801/1217559803

まぁ、やって見たほうが早いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: マリオ風のジャンプについて

#26

投稿記事 by ISLe » 11年前

ボラ天神 さんが書きました:久しぶりに昔のマリオをやってみたのですが、なかなかジャンプの綺麗さが違って驚きましたww
意外とジャンプが低く、大きいジャンプと低いジャンプの差がキャラ1つ分位ありました。
色々数値をいじってみたのですがなかなか本物に近づけません。
これ以外にも何らかの処理があるのでしょうか?
謎ですww
スーパーマリオブラザーズのジャンプは大小の2種類ではないですよね。
#まさか最近のスーパーマリオは違うとか?

小マリオと大マリオで背の高さが違うので、足元を基準にします。
  • 一瞬ボタンを押してすぐに離しても最低1ブロック(小マリオの高さ)分はジャンプする。
  • ボタン押しっぱなしで垂直に飛ぶと4ブロック分ジャンプする。
  • 移動しながらだとジャンプの高さは上がる。Bダッシュ最高速で5ブロック分に到達
実際の映像では押しっぱなしで上半分は等速に見えますね。

ボラ天神

Re: マリオ風のジャンプについて

#27

投稿記事 by ボラ天神 » 11年前

皆さん返信遅れてすみませんでした。

softya(ソフト屋) さん
URLありがとうございます!!
早速試してみたいと思います!!

ISLe さん
めっちゃ参考になりますww
実際のプログラムはどうなのでしょうかねww
頑張って試してみたいと思います。

ジャンプは一応これで解決としますが、今後もマリオ関係の質問をするかもしれませんのでよろしくお願いします。

閉鎖

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