マリオ風の加減速付きジャンプができない。

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

マリオ風の加減速付きジャンプができない。

#1

投稿記事 by keito940 » 8年前

毎度のことながらすいません。スクロールの件は一応解決としましたが、今度は、マリオ風の加減速を実装しようとしてます。
ですが、何故か、垂直ジャンプしかできません。どうすればいいのでしょうか?コードは以下のとおりです。(僕なりにどうやって対策したのかはコメントに書かれてます。)

コード:

//衝突のテストプログラム(だった)
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//(完成しました)
//でも現在はアクションゲーム全般のテストプログラムになりつつある…。
//現在マリオで使われるジャンプの加減速で悪戦苦闘中…。
//Create 2017/02/10
#include "DxLib.h"

#define SCREEN_WIDTH (320)		//画面の横幅
#define SCREEN_HEIGHT (240)		//画面の縦幅
#define STAGE_WIDTH  (400)
#define STAGE_HEIGHT (320)
#define CHIP_SIZE (16)			//チップのサイズ
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_HEIGHT/CHIP_SIZE)
HANDLE Stdout;

//テスト用のマップデータ。実際の開発では、Tiled(フリーのマップエディタ)を使う予定。
//このテストプログラムがある程度の段階に達したら、本格的な開発に移ります。
//TinyXML2は便利だ
char MapData[MAP_HEIGHT][MAP_WIDTH]
{
	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,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,1,0,1, 1,1,1,1,1, 1,1,1,1,1, 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,
};

float PlayerX, PlayerY;
float SaveX, SaveY;
float MoveX, MoveY;
float DropPower, Grav;
char JumpFlag, Dir, AirFlag, NonVertJump;

int Input, EdgeInput;
int FreamStartTime;
int CameraX = 0;
int CameraY = 0;
float CharX, CharY, ViewCharX, ViewCharY;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size);
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop, float *G, char *Jump, char *Air, char *Vert, float Size);
int MapChipParam(float X, float Y);
int CameraCheck(float X, float Y);

int MapChipParam(float X, float Y) {
	int x, y;

	x = (int)X / CHIP_SIZE;
	y = (int)Y / CHIP_SIZE;

	if (x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0) return 0;

	return MapData[y][x];
}
//衝突判定
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size) {
	float afX, afY;
	afX = X + *MoveX;
	afY = Y + *MoveY;
	float blx, brx, bby, bty;
	blx = (float)((int)afX / Size)*Size;
	brx = (float)((int)afX / Size + 1)*Size;
	bty = (float)((int)afY / Size)*Size;
	bby = (float)((int)afY / Size + 1)*Size;
	if (MapChipParam(afX, afY) == 1) {
		if (*MoveY > 0.0F) {
			printf("\n下に当たりました。");
			//移動量を補正する
			*MoveY = bty - Y - 1.0F;
			//上の壁に当たったと判定する
			return 3;
		}
		if (*MoveY < 0.0F) {
			printf("\n上に当たりました。");
			//移動量を補正する
			*MoveY = bby - Y + 1.0F;
			//下の壁に当たったと判定する
			return 4;
		}
		//右の当たり判定
		if (*MoveX > 0.0F) {
			printf("\n右に当たりました。");
			//移動量を補正する
			*MoveX = blx - X - 1.0F;
			//右の壁に当たったと判定する
			return 1;
		}
		//左の当たり判定
		if (*MoveX < 0.0F) {
			printf("\n左に当たりました。");
			//移動量を補正する
			*MoveX = brx - X + 1.0F;
			//左の壁に当たったと判定する
			return 2;
		}
		//ここに来たら適当な値を返す
		return 4;
	}
	return 0;
}
//当たり判定チェック
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop,float *G,char *Jump,char *Air,char *Vert,float Size){
	float Dummy = 0.0F;
	float hsize;
	//直前フレーム
	float PrevX = *X + MoveX;
	float PrevY = *Y + MoveY;
	//ベクトルのバックアップ
	float SaveMoveX = MoveX;
	float SaveMoveY = MoveY;

	hsize = Size * 0.5F; 
	//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
	{
		//左下
		if (MapHitCheck(*X - hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::左下");
		//右下
		if (MapHitCheck(*X + hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::右下");
		//左上
		if (MapHitCheck(*X - hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::左上");
		//右上
		if (MapHitCheck(*X + hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::右上");
		//問題ないのなら移動させる
		PrevY = *Y + MoveY;
		*Y = PrevY;
	}
	//左右の当たり判定チェック
	{
		//左下
		if (MapHitCheck(*X - hsize + 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左下");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右下");
		//左上
		if (MapHitCheck(*X - hsize + 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左上");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右上");
		//問題ないのなら移動させる
		PrevX = *X + MoveX;
		*X = PrevX;
	}
	//着地判定
	{
		if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
			*Air = TRUE;
			*G = 0.5F;
		}
		else {
			*Drop = 0.0F;
			*G = 0.0F;
			*Air = FALSE;
			*Vert = FALSE;
			*Jump = FALSE;
		}
	}
	return 0;
}

//カメラの位置計算
int CameraCheck(float X, float Y) {
	//カメラのチェック
	CharX = X;
	CharY = Y;
	//カメラの位置を計算する
	CameraX = (int)CharX - SCREEN_WIDTH / 2;
	CameraY = (int)CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX >(STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY >(STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	ViewCharX = CharX - CameraX;
	ViewCharY = CharY - CameraY;
	return 0;
}

int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 240.0F, PlayerY = 200.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
	NonVertJump = FALSE;
	return 0;
}

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d", Dir,NonVertJump);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		int DashTimer = 8;
		//ベクトルを初期化
		MoveX = 0.0F;
		MoveY = 0.0F;
		//右へ移動
		if (JumpFlag == FALSE || MoveX > 0.0F && (Input&PAD_INPUT_RIGHT) != 0) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		//左に移動
		if (JumpFlag == FALSE || MoveX < 0.0F && (Input&PAD_INPUT_LEFT) != 0) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		//垂直ジャンプ
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) != 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//左右に入れるとその方向へジャンプする。EdgeInputがチョン押しだとするなら、と思って以下の通りにしたのだが…。
		//右へジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_RIGHT) != 0 && (EdgeInput&PAD_INPUT_1) != 0 ) {
			Grav = 0.5F;
			MoveX += 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//左へジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_LEFT) != 0 && (EdgeInput&PAD_INPUT_1) != 0 ) {
			Grav = 0.5F;
			MoveX -= 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && JumpFlag == TRUE && MoveX > 0.0F && (Input&PAD_INPUT_LEFT) != 0) {
			MoveX += 0.5F;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && JumpFlag == TRUE && MoveX < 0.0F && (Input&PAD_INPUT_RIGHT) != 0) {
			MoveX -= 0.5F;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	AllocConsole(); FILE* out = 0; freopen_s(&out, "CON", "w", stdout); Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
	init();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		main();
	}
	DxLib_End(); fclose(out); FreeConsole();
	return 0;
}

Math

Re: マリオ風の加減速付きジャンプができない。

#2

投稿記事 by Math » 8年前

これは何とか動いている様です。ZキーでJump.参考まで。

コード:

#include "DxLib.h"

#define SCREEN_WIDTH     (640)                          // 画面の横幅
#define SCREEN_HEIGHT    (480)                          // 画面の縦幅
#define CHIP_SIZE        (32)                           // 一つのチップのサイズ
#define MAP_WIDTH        (SCREEN_WIDTH / CHIP_SIZE)     // マップの横幅
#define MAP_HEIGHT       (SCREEN_HEIGHT / CHIP_SIZE)    // マップの縦幅

#define G                (0.3F)                         // キャラに掛かる重力加速度
#define JUMP_POWER       (9.0F)                         // キャラのジャンプ力
#define SPEED            (5.0F)                         // キャラの移動スピード
#define CHAR_SIZE        (30)                           // プレイヤーのサイズ

// マップデータ
char MapData[MAP_HEIGHT][MAP_WIDTH] =
{
    0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,1,0,1,

    1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,1,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 0,0,1,1,0, 0,0,0,0,0, 1,0,0,0,1,

    1,0,0,0,0, 1,1,1,1,1, 0,0,0,0,1, 1,0,0,0,1,
    1,0,0,0,0, 1,1,1,1,1, 0,0,0,1,1, 1,0,0,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,1,1, 1,0,0,0,1,
    1,0,0,0,0, 0,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,
} ;

float PlX, PlY ;            // プレイヤーの座標(中心座標)
float PlDownSp ;            // プレイヤーの落下速度
char PlJumpFlag ;           // プレイヤーがジャンプ中か、のフラグ

int Input, EdgeInput ;      // 入力状態
int FrameStartTime ;        // 60FPS固定用、時間保存用変数

// マップチップの値を取得する関数
int GetChipParam( float X, float Y ) ;

// キャラクタをマップとの当たり判定を考慮しながら移動する関数
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, float Size, char *JumpFlag ) ;

// アクションサンプルプログラムメイン関数
int ActMain( void ) ;

// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
int MapHitCheck( float X, float Y, float *MoveX, float *MoveY ) ;

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode( TRUE ) ;

    // DXライブラリの初期化
    if( DxLib_Init() == -1 ) return -1 ;

    // アクションゲームのメイン関数を呼ぶ
    ActMain() ;

    // DXライブラリの後始末
    DxLib_End() ;

    // 終了
    return 0 ;
}

// アクションサンプルプログラムメイン
int ActMain( void )
{
    // 描画先を裏画面にセット
    SetDrawScreen( DX_SCREEN_BACK ) ;

    // 垂直同期信号を待たない
    SetWaitVSyncFlag( FALSE ) ;

    // プレイヤーの座標を初期化
    PlX = 320.0F ;        PlY = 240.0F ;

    // プレイヤーの落下速度を初期化
    PlDownSp = 0.0F ;

    // ジャンプ中フラグを倒す
    PlJumpFlag = FALSE ;

    // 入力状態の初期化
    Input = 0 ;
    EdgeInput = 0 ;

    // 60FPS固定用、時間保存用変数を現在のカウント値にセット
    FrameStartTime = GetNowCount() ;

    // メインループ開始、ESCキーで外に出る
    while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
    {
        // 画面のクリア
        ClearDrawScreen() ;

        // 1/60秒立つまで待つ
        while( GetNowCount() - FrameStartTime < 1000 / 60 ){}

        // 現在のカウント値を保存
        FrameStartTime = GetNowCount() ;

        // 入力状態を更新
        {
            int i ;

            // パッド1とキーボードから入力を得る
            i = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;

            // エッジを取った入力をセット
            EdgeInput = i & ~Input ;

            // 入力状態の保存
            Input = i ;
        }

        // プレイヤーの移動処理
        {
            float MoveX, MoveY ;

            // 移動量の初期化
            MoveX = 0.0F ;
            MoveY = 0.0F ;

            // 左右の移動を見る
            if( ( Input & PAD_INPUT_LEFT ) != 0 ) MoveX -= SPEED ;
            if( ( Input & PAD_INPUT_RIGHT ) != 0 ) MoveX += SPEED ;

            // 地に足が着いている場合のみジャンプボタン(ボタン1 or Zキー)を見る
            if( PlJumpFlag == FALSE && ( EdgeInput & PAD_INPUT_A ) != 0 )
            {
                PlDownSp = -JUMP_POWER ;
                PlJumpFlag = TRUE ;
            }

            // 落下処理
            PlDownSp += G ;

            // 落下速度を移動量に加える
            MoveY = PlDownSp ;

            // 移動量に基づいてキャラクタの座標を移動
            CharMove( &PlX, &PlY, &PlDownSp, MoveX, MoveY, CHAR_SIZE, &PlJumpFlag ) ;
        }

        // マップの描画
        {
            int i, j ;

            for( i = 0 ; i < MAP_HEIGHT ; i ++ )
            {
                for( j = 0 ; j < MAP_WIDTH ; j ++ )
                {
                    // 1は当たり判定チップを表しているので1のところだけ描画
                    if( MapData[i][j] == 1 )
                    {
                        DrawBox( j * CHIP_SIZE,                i * CHIP_SIZE,
                                 j * CHIP_SIZE + CHIP_SIZE,    i * CHIP_SIZE + CHIP_SIZE,
                                 GetColor( 255, 255, 255 ), TRUE ) ;
                    }
                }
            }
        }

        // キャラクタの描画
        DrawBox( ( int )( PlX - CHAR_SIZE * 0.5F ),     ( int )( PlY - CHAR_SIZE * 0.5F ),
                 ( int )( PlX + CHAR_SIZE * 0.5F ) + 1, ( int )( PlY + CHAR_SIZE * 0.5F ) + 1,
                    GetColor( 255, 0, 0 ), TRUE ) ;

        // 画面の更新
        ScreenFlip() ;
    }

    // 終了
    return 0 ;
}

// キャラクタをマップとの当たり判定を考慮しながら移動する
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, float Size, char *JumpFlag )
{
    float Dummy = 0.0F ;
    float hsize ;

    // キャラクタの左上、右上、左下、右下部分が当たり判定のある
    // マップに衝突しているか調べ、衝突していたら補正する

    // 半分のサイズを算出
    hsize = Size * 0.5F ;

    // 先ず上下移動成分だけでチェック
    {
        // 左下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( *X - hsize, *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 右下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( *X + hsize, *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 左上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( *X - hsize, *Y - hsize, &Dummy, &MoveY ) == 4 ) *DownSP *= -1.0F ;

        // 右上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( *X + hsize, *Y - hsize, &Dummy, &MoveY ) == 4 ) *DownSP *= -1.0F ;

        // 上下移動成分を加算
        *Y += MoveY ;
    }

    // 後に左右移動成分だけでチェック
    {
        // 左下のチェック
        MapHitCheck( *X - hsize, *Y + hsize, &MoveX, &Dummy ) ;

        // 右下のチェック
        MapHitCheck( *X + hsize, *Y + hsize, &MoveX, &Dummy ) ;

        // 左上のチェック
        MapHitCheck( *X - hsize, *Y - hsize, &MoveX, &Dummy ) ;

        // 右上のチェック
        MapHitCheck( *X + hsize, *Y - hsize, &MoveX, &Dummy ) ;

        // 左右移動成分を加算
        *X += MoveX ;
    }

    // 接地判定
    {
        // キャラクタの左下と右下の下に地面があるか調べる
        if( GetChipParam( *X - Size * 0.5F, *Y + Size * 0.5F + 1.0F ) == 0 && 
            GetChipParam( *X + Size * 0.5F, *Y + Size * 0.5F + 1.0F ) == 0 )
        {
            // 足場が無かったらジャンプ中にする
            *JumpFlag = TRUE ;
        }
        else
        {
            // 足場が在ったら接地中にする
            *JumpFlag = FALSE ;
        }
    }

    // 終了
    return 0 ;
}

// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
int MapHitCheck( float X, float Y,
                    float *MoveX, float *MoveY )
{
    float afX, afY ;

    // 移動量を足す
    afX = X + *MoveX ;
    afY = Y + *MoveY ;

    // 当たり判定のあるブロックに当たっているかチェック
    if( GetChipParam( afX, afY ) == 1 )
    {
        float blx, bty, brx, bby ;

        // 当たっていたら壁から離す処理を行う

        // ブロックの上下左右の座標を算出
        blx = (float)( (int)afX / CHIP_SIZE ) * CHIP_SIZE ;        // 左辺の X 座標
        brx = (float)( (int)afX / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 右辺の X 座標

        bty = (float)( (int)afY / CHIP_SIZE ) * CHIP_SIZE ;        // 上辺の Y 座標
        bby = (float)( (int)afY / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 下辺の Y 座標

        // 上辺に当たっていた場合
        if( *MoveY > 0.0F )
        {
            // 移動量を補正する
            *MoveY = bty - Y - 1.0F  ;

            // 上辺に当たったと返す
            return 3 ;
        }

        // 下辺に当たっていた場合
        if( *MoveY < 0.0F )
        {
            // 移動量を補正する
            *MoveY = bby - Y + 1.0F ;

            // 下辺に当たったと返す
            return 4 ;
        }

        // 左辺に当たっていた場合
        if( *MoveX > 0.0F )
        {
            // 移動量を補正する
            *MoveX = blx - X - 1.0F ;

            // 左辺に当たったと返す
            return 1 ;
        }

        // 右辺に当たっていた場合
        if( *MoveX < 0.0F )
        {
            // 移動量を補正する
            *MoveX = brx - X + 1.0F ;

            // 右辺に当たったと返す
            return 2 ;
        }

        // ここに来たら適当な値を返す
        return 4 ;
    }

    // どこにも当たらなかったと返す
    return 0 ;
}

// マップチップの値を取得する関数
int GetChipParam( float X, float Y )
{
    int x, y ;

    // 整数値へ変換
    x = (int)X / CHIP_SIZE ;
    y = (int)Y / CHIP_SIZE ;

    // マップからはみ出ていたら 0 を返す
    if( x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0 ) return 0 ;

    // 指定の座標に該当するマップの情報を返す
    return MapData[ y ][ x ] ;
}

Math

Re: マリオ風の加減速付きジャンプができない。

#3

投稿記事 by Math » 8年前

[参考に]..imo...[but only in my opinion.私の意見でしかありませんが。]

コード:

	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);
	DrawKnife(key);
	float mv = 200.0f * g_frametime; //移動量計算
	float hx = g_stagedata.hero.x;
	float hy = g_stagedata.hero.y;

	//ジャンプ処理
	if (g_stagedata.hero.jumping == TRUE){
		mv = 0;	//ジャンプ中は自力で移動させない
		g_stagedata.hero.jumppower -= GRAVITY;
		hy -= (g_stagedata.hero.jumppower * g_frametime);
		hx += (g_stagedata.hero.jumpforward * g_frametime);
	}
	if (key & PAD_INPUT_LEFT)	{
		hx -= mv;
		g_stagedata.hero.turn = TRUE;
	}
	if (key & PAD_INPUT_RIGHT)	{
		hx += mv;
		g_stagedata.hero.turn = FALSE;
	}

	//マップ当たり判定
	AtariInfo atari = CheckBlock(hx, hy, g_stagedata.hero.x);
	if (g_stagedata.hero.turn == FALSE){
		if (atari.DR == TRUE || atari.UR == TRUE){
			hx = g_stagedata.hero.x;
		}
	}
	else {
		if (atari.DL == TRUE || atari.UL == TRUE){
			hx = g_stagedata.hero.x;
		}
	}
	//接地チェック
	if (atari.GL == TRUE || atari.GR == TRUE) {
		g_stagedata.hero.noground = FALSE;
		g_stagedata.hero.jumping = FALSE;
		g_stagedata.hero.jumppower = 0;
		g_stagedata.hero.jumpforward = 0;
		//ジャンプ後に地面に埋まらないよう補正
		hy = (float)((int)(hy / IMG_CHIPSIZE) * IMG_CHIPSIZE);
	}
	else {
		g_stagedata.hero.noground = TRUE;
		//重力で落下
		g_stagedata.hero.jumping = TRUE;
	}
	//天井チェック

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#4

投稿記事 by keito940 » 8年前

そういえば、サンプルコードのジョイパッドは一つのボタンしか読み出せないことに気づいて、
ゲームプログラミングの館を参考に複数のボタンを獲得するコードを書いてみましたが、ジョイパッドが反応しません。
どうしたらジョイパッドが反応するんですか?教えてください。

コード:

int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 240.0F, PlayerY = 200.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, Pad = 0, FreamStartTime = GetNowCount();
	NonVertJump = FALSE;
	return 0;
}

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d", Dir,NonVertJump);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//ジョイパッドの確認
	{
		for (int i = 0; i < JOYPAD_BUTTON_MAX; i++) {
			Pad = GetJoypadInputState(DX_INPUT_KEY_PAD1);
			if (Pad & (1 << i)) {
				EdgeInput = Pad & ~Input;
				Input = Pad;
			}
		}
	}
	//移動処理
	{
		int DashTimer = 8;
		//ベクトルを初期化
		MoveX = 0.0F;
		MoveY = 0.0F;
		//右へ移動
		if (JumpFlag == FALSE || MoveX > 0.0F && (Input&PAD_INPUT_RIGHT)==PAD_INPUT_ON) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		//左に移動
		if (JumpFlag == FALSE || MoveX < 0.0F && (Input&PAD_INPUT_LEFT)==PAD_INPUT_ON) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		//垂直ジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_1)==PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//左右に入れるとその方向へジャンプする。EdgeInputがチョン押しだとするなら、と思って以下の通りにしたのだが…。
		//右へジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_RIGHT) != 0 && (EdgeInput&PAD_INPUT_1) != 0 ) {
			Grav = 0.5F;
			MoveX += 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//左へジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_LEFT) != 0 && (EdgeInput&PAD_INPUT_1) != 0 ) {
			Grav = 0.5F;
			MoveX -= 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && JumpFlag == TRUE && MoveX > 0.0F && (Input&PAD_INPUT_LEFT) != 0) {
			MoveX += 0.5F;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && JumpFlag == TRUE && MoveX < 0.0F && (Input&PAD_INPUT_RIGHT) != 0) {
			MoveX -= 0.5F;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#5

投稿記事 by keito940 » 8年前

失礼しました。一部のコードだけじゃわかりにくかったですね。

コード:

//衝突のテストプログラム(だった)
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//(完成しました)
//でも現在はアクションゲーム全般のテストプログラムになりつつある…。
//現在マリオで使われるジャンプの加減速で悪戦苦闘中…。
//サンプルコードのジョイパッドのやつは欠陥だらけらしいことに気づき、ちょっと書き直し中…。
//Create 2017/02/10
#include "DxLib.h"

#define SCREEN_WIDTH (320)		//画面の横幅
#define SCREEN_HEIGHT (240)		//画面の縦幅
#define STAGE_WIDTH  (400)
#define STAGE_HEIGHT (320)
#define CHIP_SIZE (16)			//チップのサイズ
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_HEIGHT/CHIP_SIZE)
#define JOYPAD_BUTTON_MAX (28)
#define PAD_INPUT_ON 1
#define PAD_INPUT_OFF 0
HANDLE Stdout;

//テスト用のマップデータ。実際の開発では、Tiled(フリーのマップエディタ)を使う予定。
//このテストプログラムがある程度の段階に達したら、本格的な開発に移ります。
//TinyXML2は便利だ
char MapData[MAP_HEIGHT][MAP_WIDTH]
{
	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,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,1,0,1, 1,1,1,1,1, 1,1,1,1,1, 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,
};

float PlayerX, PlayerY;
float SaveX, SaveY;
float MoveX, MoveY;
float DropPower, Grav;
char JumpFlag, Dir, AirFlag, NonVertJump;

int Input, EdgeInput, Pad;
int FreamStartTime;
int CameraX = 0;
int CameraY = 0;
float CharX, CharY, ViewCharX, ViewCharY;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size);
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop, float *G, char *Jump, char *Air, char *Vert, float Size);
int MapChipParam(float X, float Y);
int CameraCheck(float X, float Y);
bool IsPush(int PadHandle);
bool IsFree(int PadHandle);
bool IsHold(int PadHandle);
bool IsPull(int PadHandle);

//将来の開発で使う予定の関数。
//押されたか?
bool IsPush(int PadHandle) {
	if ((EdgeInput&(1 << PadHandle) == PAD_INPUT_ON)) {
		return true;
	}
	return false;
}

//押されていないか?
bool IsFree (int PadHandle) {
	if ((Input&(1 << PadHandle) == PAD_INPUT_OFF)) {
		return true;
	}
	return false;
}

//押されているか?
bool IsPull(int PadHandle) {
	if ((EdgeInput&(1 << PadHandle) == PAD_INPUT_OFF)) {
		return true;
	}
	return false;
}

 //離されたか?
bool IsHold (int PadHandle) {
	if ((Input&(1 << PadHandle)) == PAD_INPUT_ON) {
		return true;
	}
	return false;
}
//マップチップのデータ獲得
int MapChipParam(float X, float Y) {
	int x, y;

	x = (int)X / CHIP_SIZE;
	y = (int)Y / CHIP_SIZE;

	if (x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0) return 0;

	return MapData[y][x];
}

//衝突判定
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size) {
	float afX, afY;
	afX = X + *MoveX;
	afY = Y + *MoveY;
	float blx, brx, bby, bty;
	blx = (float)((int)afX / Size)*Size;
	brx = (float)((int)afX / Size + 1)*Size;
	bty = (float)((int)afY / Size)*Size;
	bby = (float)((int)afY / Size + 1)*Size;
	if (MapChipParam(afX, afY) == 1) {
		if (*MoveY > 0.0F) {
			printf("\n下に当たりました。");
			//移動量を補正する
			*MoveY = bty - Y - 1.0F;
			//上の壁に当たったと判定する
			return 3;
		}
		if (*MoveY < 0.0F) {
			printf("\n上に当たりました。");
			//移動量を補正する
			*MoveY = bby - Y + 1.0F;
			//下の壁に当たったと判定する
			return 4;
		}
		//右の当たり判定
		if (*MoveX > 0.0F) {
			printf("\n右に当たりました。");
			//移動量を補正する
			*MoveX = blx - X - 1.0F;
			//右の壁に当たったと判定する
			return 1;
		}
		//左の当たり判定
		if (*MoveX < 0.0F) {
			printf("\n左に当たりました。");
			//移動量を補正する
			*MoveX = brx - X + 1.0F;
			//左の壁に当たったと判定する
			return 2;
		}
		//ここに来たら適当な値を返す
		return 4;
	}
	return 0;
}

//当たり判定チェック
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop,float *G,char *Jump,char *Air,char *Vert,float Size){
	float Dummy = 0.0F;
	float hsize;
	//直前フレーム
	float PrevX = *X + MoveX;
	float PrevY = *Y + MoveY;
	//ベクトルのバックアップ
	float SaveMoveX = MoveX;
	float SaveMoveY = MoveY;

	hsize = Size * 0.5F; 
	//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
	{
		//左下
		if (MapHitCheck(*X - hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::左下");
		//右下
		if (MapHitCheck(*X + hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::右下");
		//左上
		if (MapHitCheck(*X - hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::左上");
		//右上
		if (MapHitCheck(*X + hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::右上");
		//問題ないのなら移動させる
		PrevY = *Y + MoveY;
		*Y = PrevY;
	}
	//左右の当たり判定チェック
	{
		//左下
		if (MapHitCheck(*X - hsize + 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左下");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右下");
		//左上
		if (MapHitCheck(*X - hsize + 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左上");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右上");
		//問題ないのなら移動させる
		PrevX = *X + MoveX;
		*X = PrevX;
	}
	//着地判定
	{
		if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
			*Air = TRUE;
			*G = 0.5F;
		}
		else {
			*Drop = 0.0F;
			*G = 0.0F;
			*Air = FALSE;
			*Vert = FALSE;
			*Jump = FALSE;
		}
	}
	return 0;
}

//カメラの位置計算
int CameraCheck(float X, float Y) {
	//カメラのチェック
	CharX = X;
	CharY = Y;
	//カメラの位置を計算する
	CameraX = (int)CharX - SCREEN_WIDTH / 2;
	CameraY = (int)CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX >(STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY >(STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	ViewCharX = CharX - CameraX;
	ViewCharY = CharY - CameraY;
	return 0;
}

int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 240.0F, PlayerY = 200.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
	NonVertJump = FALSE;
	return 0;
}

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d", Dir,NonVertJump);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//ジョイパッドの確認
	{
		Pad = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		for (int i = 0; i < JOYPAD_BUTTON_MAX; i++) {
			if (Pad & (1 << i)) {
				EdgeInput = i & ~Input;
				Input = i;
			}
		}
	}
	//移動処理
	{
		int DashTimer = 8;
		//ベクトルを初期化
		MoveX = 0.0F;
		MoveY = 0.0F;
		//右へ移動
		if (JumpFlag == FALSE || MoveX > 0.0F && (Input&PAD_INPUT_RIGHT)==PAD_INPUT_ON) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		//左に移動
		if (JumpFlag == FALSE || MoveX < 0.0F && (Input&PAD_INPUT_LEFT)==PAD_INPUT_ON) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		//垂直ジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_1)==PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//左右に入れるとその方向へジャンプする。EdgeInputがチョン押しだとするなら、と思って以下の通りにしたのだが…。
		//右へジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_RIGHT) == PAD_INPUT_ON && (EdgeInput&PAD_INPUT_1) == PAD_INPUT_ON ) {
			Grav = 0.5F;
			MoveX += 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//左へジャンプ
		if (JumpFlag == FALSE && (Input&PAD_INPUT_LEFT) == PAD_INPUT_ON && (EdgeInput&PAD_INPUT_1) == PAD_INPUT_ON ) {
			Grav = 0.5F;
			MoveX -= 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && JumpFlag == TRUE && MoveX > 0.0F && (Input&PAD_INPUT_LEFT) == PAD_INPUT_ON) {
			MoveX += 0.5F;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && JumpFlag == TRUE && MoveX < 0.0F && (Input&PAD_INPUT_RIGHT) == PAD_INPUT_ON) {
			MoveX -= 0.5F;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	AllocConsole(); FILE* out = 0; freopen_s(&out, "CON", "w", stdout); Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
	init();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		main();
	}
	DxLib_End(); fclose(out); FreeConsole();
	return 0;
}

Math

Re: マリオ風の加減速付きジャンプができない。

#6

投稿記事 by Math » 8年前

コンパイルに次のようなワーニングがでるので")"の使い方がおかしいと思われます。..imo..(just in my opinion)

コード:

       cl /c /TP /EHsc /D "_MBCS" /MT  /I"d:\DxLib_VC\プロジェクトに追加すべきファイル_VC用" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /W3 g1.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

g1.cpp
g1.cpp(76): warning C4554: '&': 演算子の優先順位に問題があります。かっこを使用して優先順位を明確に してください
g1.cpp(84): warning C4554: '&': 演算子の優先順位に問題があります。かっこを使用して優先順位を明確に してください
g1.cpp(92): warning C4554: '&': 演算子の優先順位に問題があります。かっこを使用して優先順位を明確に してください
[/size]

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

Re: マリオ風の加減速付きジャンプができない。

#7

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

Math さんが書きました:コンパイルに次のようなワーニングがでるので")"の使い方がおかしいと思われます。..imo..(just in my opinion)

コード:

       cl /c /TP /EHsc /D "_MBCS" /MT  /I"d:\DxLib_VC\プロジェクトに追加すべきファイル_VC用" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /W3 g1.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

g1.cpp
g1.cpp(76): warning C4554: '&': 演算子の優先順位に問題があります。かっこを使用して優先順位を明確に してください
g1.cpp(84): warning C4554: '&': 演算子の優先順位に問題があります。かっこを使用して優先順位を明確に してください
g1.cpp(92): warning C4554: '&': 演算子の優先順位に問題があります。かっこを使用して優先順位を明確に してください
[/size]
なるほど、A & B == Cと書くと、(A & B) == CではなくA & (B == C)、すなわちA & (BとCが同じならば1、そうでなければ0)という意味になる罠にかかっているようですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: マリオ風の加減速付きジャンプができない。

#8

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

よく考えたら、1を左シフトした値とビットANDをとったもの(1ビット以上のシフトなら最下位ビットは確実に0)とPAD_INPUT_ON(1と定義されている)を比較するのもおかしく思えますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#9

投稿記事 by keito940 » 8年前

皆様のおかげさまで、ちゃんと横にジャンプできるようになりました。ですが、加減速が反応しないようです。

コード:

//衝突のテストプログラム(だった)
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//(完成しました)
//でも現在はアクションゲーム全般のテストプログラムになりつつある…。
//現在マリオで使われるジャンプの加減速で悪戦苦闘中…。
//サンプルコードのジョイパッドのやつは欠陥だらけらしいことに気づき、ちょっと書き直し中…。
//(やっぱり、これでよかったのか…。)
//しかし、どうしたら加減速ができるんだ?
//Create 2017/02/10
#include "DxLib.h"

#define SCREEN_WIDTH (320)		//画面の横幅
#define SCREEN_HEIGHT (240)		//画面の縦幅
#define STAGE_WIDTH  (400)
#define STAGE_HEIGHT (320)
#define CHIP_SIZE (16)			//チップのサイズ
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_HEIGHT/CHIP_SIZE)
#define JOYPAD_BUTTON_MAX (28)
#define PAD_INPUT_ON 1
#define PAD_INPUT_OFF 0
HANDLE Stdout;

//テスト用のマップデータ。実際の開発では、Tiled(フリーのマップエディタ)を使う予定。
//このテストプログラムがある程度の段階に達したら、本格的な開発に移ります。
//TinyXML2は便利だ
char MapData[MAP_HEIGHT][MAP_WIDTH]
{
	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,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,1,0,1, 1,1,1,1,1, 1,1,1,1,1, 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,
};

float PlayerX, PlayerY;
float SaveX, SaveY;
float MoveX, MoveY;
float DropPower, Grav;
char JumpFlag, Dir, AirFlag, NonVertJump;

int Input, EdgeInput, Pad;
int FreamStartTime;
int CameraX = 0;
int CameraY = 0;
float CharX, CharY, ViewCharX, ViewCharY;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size);
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop, float *G, char *Jump, char *Air, char *Vert, float Size);
int MapChipParam(float X, float Y);
int CameraCheck(float X, float Y);
bool IsPush(int PadHandle);
bool IsFree(int PadHandle);
bool IsHold(int PadHandle);
bool IsPull(int PadHandle);

//将来の開発で使う予定の関数。
//押されたか?
bool IsPush(int PadHandle) {
	if (((EdgeInput&PadHandle) > PAD_INPUT_ON)) {
		return true;
	}
	return false;
}

//押されていないか?
bool IsFree (int PadHandle) {
	if ((Input&PadHandle) > PAD_INPUT_OFF) {
		return true;
	}
	return false;
}

//押されているか?
bool IsPull(int PadHandle) {
	if ((EdgeInput&PadHandle) > PAD_INPUT_OFF) {
		return true;
	}
	return false;
}

 //離されたか?
bool IsHold (int PadHandle) {
	if ((Input&PadHandle) > PAD_INPUT_ON) {
		return true;
	}
	return false;
}
//マップチップのデータ獲得
int MapChipParam(float X, float Y) {
	int x, y;

	x = (int)X / CHIP_SIZE;
	y = (int)Y / CHIP_SIZE;

	if (x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0) return 0;

	return MapData[y][x];
}

//衝突判定
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size) {
	float afX, afY;
	afX = X + *MoveX;
	afY = Y + *MoveY;
	float blx, brx, bby, bty;
	blx = (float)((int)afX / Size)*Size;
	brx = (float)((int)afX / Size + 1)*Size;
	bty = (float)((int)afY / Size)*Size;
	bby = (float)((int)afY / Size + 1)*Size;
	if (MapChipParam(afX, afY) == 1) {
		if (*MoveY > 0.0F) {
			printf("\n下に当たりました。");
			//移動量を補正する
			*MoveY = bty - Y - 1.0F;
			//上の壁に当たったと判定する
			return 3;
		}
		if (*MoveY < 0.0F) {
			printf("\n上に当たりました。");
			//移動量を補正する
			*MoveY = bby - Y + 1.0F;
			//下の壁に当たったと判定する
			return 4;
		}
		//右の当たり判定
		if (*MoveX > 0.0F) {
			printf("\n右に当たりました。");
			//移動量を補正する
			*MoveX = blx - X - 1.0F;
			//右の壁に当たったと判定する
			return 1;
		}
		//左の当たり判定
		if (*MoveX < 0.0F) {
			printf("\n左に当たりました。");
			//移動量を補正する
			*MoveX = brx - X + 1.0F;
			//左の壁に当たったと判定する
			return 2;
		}
		//ここに来たら適当な値を返す
		return 4;
	}
	return 0;
}

//当たり判定チェック
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop,float *G,char *Jump,char *Air,char *Vert,float Size){
	float Dummy = 0.0F;
	float hsize;
	//直前フレーム
	float PrevX = *X + MoveX;
	float PrevY = *Y + MoveY;
	//ベクトルのバックアップ
	float SaveMoveX = MoveX;
	float SaveMoveY = MoveY;

	hsize = Size * 0.5F; 
	//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
	{
		//左下
		if (MapHitCheck(*X - hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::左下");
		//右下
		if (MapHitCheck(*X + hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::右下");
		//左上
		if (MapHitCheck(*X - hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::左上");
		//右上
		if (MapHitCheck(*X + hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::右上");
		//問題ないのなら移動させる
		PrevY = *Y + MoveY;
		*Y = PrevY;
	}
	//左右の当たり判定チェック
	{
		//左下
		if (MapHitCheck(*X - hsize + 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左下");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右下");
		//左上
		if (MapHitCheck(*X - hsize + 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左上");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右上");
		//問題ないのなら移動させる
		PrevX = *X + MoveX;
		*X = PrevX;
	}
	//着地判定
	{
		if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
			*Air = TRUE;
			*G = 0.5F;
		}
		else {
			*Drop = 0.0F;
			*G = 0.0F;
			*Air = FALSE;
			*Vert = FALSE;
			*Jump = FALSE;
		}
	}
	return 0;
}

//カメラの位置計算
int CameraCheck(float X, float Y) {
	//カメラのチェック
	CharX = X;
	CharY = Y;
	//カメラの位置を計算する
	CameraX = (int)CharX - SCREEN_WIDTH / 2;
	CameraY = (int)CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX >(STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY >(STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	ViewCharX = CharX - CameraX;
	ViewCharY = CharY - CameraY;
	return 0;
}

int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 240.0F, PlayerY = 200.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
	NonVertJump = FALSE;
	return 0;
}

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d", Dir,NonVertJump);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//入力状態を更新
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		int DashTimer = 8;
		//ベクトルを初期化
		MoveX = 0.0F;
		MoveY = 0.0F;
		char RunButton;
		if ((Input&PAD_INPUT_2) > PAD_INPUT_ON) {
			RunButton = TRUE;
		}
		else {
			RunButton = FALSE;
		}
		//右へ移動
		if ((Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			Dir = TRUE;
			if (RunButton == TRUE) {
				MoveX = 8.0F;
			}
			else {
				MoveX = 5.0F;
			}
		}
		//左に移動
		if ((Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			Dir = FALSE;
			if (RunButton == TRUE) {
				MoveX = -8.0F;
			}
			else {
				MoveX = -5.0F;
			}
		}
		//垂直ジャンプ
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			Grav = 0.5F;
			MoveX = 0.0F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//右へジャンプ
		if (JumpFlag == FALSE && MoveX > 0.0F && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON ) {
			Grav = 0.5F;
			MoveX += 0.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//左へジャンプ
		if (JumpFlag == FALSE && MoveX < 0.0F && (EdgeInput&PAD_INPUT_1) == PAD_INPUT_ON ) {
			Grav = 0.5F;
			MoveX -= 5.0F;
			DropPower = -9.5F;
			NonVertJump = TRUE;
			JumpFlag = TRUE;
		}
		//右へジャンプしているときに左で減速
		if (JumpFlag == TRUE && MoveX > 0.0F && (Input&PAD_INPUT_LEFT) == PAD_INPUT_ON) {
			MoveX += 0.5F;
		}
		//左へジャンプしているときに右で減速
		if (JumpFlag == TRUE && MoveX < 0.0F && (Input&PAD_INPUT_RIGHT) == PAD_INPUT_ON) {
			MoveX -= 0.5F;
		}
		MoveX = MoveX;
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	AllocConsole(); FILE* out = 0; freopen_s(&out, "CON", "w", stdout); Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
	init();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		main();
	}
	DxLib_End(); fclose(out); FreeConsole();
	return 0;
}
ちなみに、僕の考えでは、ジャンプフラグが立っている時に、横に移動していれば加減速が可能になります。

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#10

投稿記事 by keito940 » 8年前

マリオみたいなジャンプがうまくいかない…。
どうすればいいんだ?

コード:

//衝突のテストプログラム(だった)
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//(完成しました)
//でも現在はアクションゲーム全般のテストプログラムになりつつある…。
//現在マリオで使われるジャンプの加減速で悪戦苦闘中…。
//サンプルコードのジョイパッドのやつは欠陥だらけらしいことに気づき、ちょっと書き直し中…。
//(やっぱり、これでよかったのか…。)
//しかしどうしたら加減速ができるんだ?
//そうか!スピードを保存して、移動している方向を決めればいいんだ!
//Create 2017/02/10
#include "DxLib.h"

#define SCREEN_WIDTH (320)		//画面の横幅
#define SCREEN_HEIGHT (240)		//画面の縦幅
#define STAGE_WIDTH  (400)
#define STAGE_HEIGHT (320)
#define CHIP_SIZE (16)			//チップのサイズ
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_HEIGHT/CHIP_SIZE)
#define JOYPAD_BUTTON_MAX (28)
#define PAD_INPUT_ON 1
#define PAD_INPUT_OFF 0
HANDLE Stdout;

//テスト用のマップデータ。実際の開発では、Tiled(フリーのマップエディタ)を使う予定。
//このテストプログラムがある程度の段階に達したら、本格的な開発に移ります。
//TinyXML2は便利だ
char MapData[MAP_HEIGHT][MAP_WIDTH]
{
	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,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,1, 1,1,1,1,1, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	1,0,0,0,0, 0,0,1,0,1, 1,1,1,1,1, 1,1,1,1,1, 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,
};

float PlayerX, PlayerY;
float SaveX, SaveY;
float MoveX, MoveY;
float VectX;
float DropPower, Grav;
char JumpFlag, Dir, AirFlag, NonVertJump;

int Input, EdgeInput, Pad;
int FreamStartTime;
int CameraX = 0;
int CameraY = 0;
float CharX, CharY, ViewCharX, ViewCharY;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size);
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop, float *G, char *Jump, char *Air, char *Vert,float *Vect, float Size);
int MapChipParam(float X, float Y);
int CameraCheck(float X, float Y);
bool IsPush(int PadHandle);
bool IsFree(int PadHandle);
bool IsHold(int PadHandle);
bool IsPull(int PadHandle);

//将来の開発で使う予定の関数。
//押されたか?
bool IsPush(int PadHandle) {
	if (((EdgeInput&PadHandle) > PAD_INPUT_ON)) {
		return true;
	}
	return false;
}

//押されていないか?
bool IsFree (int PadHandle) {
	if ((Input&PadHandle) > PAD_INPUT_OFF) {
		return true;
	}
	return false;
}

//押されているか?
bool IsPull(int PadHandle) {
	if ((EdgeInput&PadHandle) > PAD_INPUT_OFF) {
		return true;
	}
	return false;
}

 //離されたか?
bool IsHold (int PadHandle) {
	if ((Input&PadHandle) > PAD_INPUT_ON) {
		return true;
	}
	return false;
}
//マップチップのデータ獲得
int MapChipParam(float X, float Y) {
	int x, y;

	x = (int)X / CHIP_SIZE;
	y = (int)Y / CHIP_SIZE;

	if (x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0) return 0;

	return MapData[y][x];
}

//衝突判定
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size) {
	float afX, afY;
	afX = X + *MoveX;
	afY = Y + *MoveY;
	float blx, brx, bby, bty;
	blx = (float)((int)afX / Size)*Size;
	brx = (float)((int)afX / Size + 1)*Size;
	bty = (float)((int)afY / Size)*Size;
	bby = (float)((int)afY / Size + 1)*Size;
	if (MapChipParam(afX, afY) == 1) {
		if (*MoveY > 0.0F) {
			printf("\n下に当たりました。");
			//移動量を補正する
			*MoveY = bty - Y - 1.0F;
			//上の壁に当たったと判定する
			return 3;
		}
		if (*MoveY < 0.0F) {
			printf("\n上に当たりました。");
			//移動量を補正する
			*MoveY = bby - Y + 1.0F;
			//下の壁に当たったと判定する
			return 4;
		}
		//右の当たり判定
		if (*MoveX > 0.0F) {
			printf("\n右に当たりました。");
			//移動量を補正する
			*MoveX = blx - X - 1.0F;
			//右の壁に当たったと判定する
			return 1;
		}
		//左の当たり判定
		if (*MoveX < 0.0F) {
			printf("\n左に当たりました。");
			//移動量を補正する
			*MoveX = brx - X + 1.0F;
			//左の壁に当たったと判定する
			return 2;
		}
		//ここに来たら適当な値を返す
		return 4;
	}
	return 0;
}

//当たり判定チェック
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop,float *G,char *Jump,char *Air,char *Vert,float *Vect,float Size){
	float Dummy = 0.0F;
	float hsize;
	//直前フレーム
	float PrevX = *X + MoveX;
	float PrevY = *Y + MoveY;
	//ベクトルのバックアップ
	float SaveMoveX = MoveX;
	float SaveMoveY = MoveY;

	hsize = Size * 0.5F; 
	//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
	{
		//左下
		if (MapHitCheck(*X - hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::左下");
		//右下
		if (MapHitCheck(*X + hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::右下");
		//左上
		if (MapHitCheck(*X - hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::左上");
		//右上
		if (MapHitCheck(*X + hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::右上");
		//問題ないのなら移動させる
		PrevY = *Y + MoveY;
		*Y = PrevY;
	}
	//左右の当たり判定チェック
	{
		//左下
		if (MapHitCheck(*X - hsize + 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))*Vect = 0.0F, MoveX += 1.0F, printf("\n左右::左下");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))*Vect = 0.0F, MoveX -= 1.0F, printf("\n左右::右下");
		//左上
		if (MapHitCheck(*X - hsize + 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))*Vect = 0.0F, MoveX += 1.0F, printf("\n左右::左上");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))*Vect = 0.0F, MoveX -= 1.0F, printf("\n左右::右上");
		//問題ないのなら移動させる
		PrevX = *X + MoveX;
		*X = PrevX;
	}
	//着地判定
	{
		if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
			*Air = TRUE;
			*G = 0.5F;
		}
		else {
			*Drop = 0.0F;
			*G = 0.0F;
			*Air = FALSE;
			*Vert = FALSE;
			*Jump = FALSE;
		}
	}
	return 0;
}

//カメラの位置計算
int CameraCheck(float X, float Y) {
	//カメラのチェック
	CharX = X;
	CharY = Y;
	//カメラの位置を計算する
	CameraX = (int)CharX - SCREEN_WIDTH / 2;
	CameraY = (int)CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX >(STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY >(STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	ViewCharX = CharX - CameraX;
	ViewCharY = CharY - CameraY;
	return 0;
}

int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 240.0F, PlayerY = 200.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
	NonVertJump = FALSE;
	return 0;
}

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d,VectX = %8.1f", Dir, NonVertJump, VectX);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//入力状態を更新
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		int DashTimer = 8;
		int ContTimer = 8;
		int DashCnt = 0;
		int ContCnt = 0;
		//ベクトルを初期化
		MoveX = 0.0F;
		MoveY = 0.0F;
		if (NonVertJump == FALSE) {
			VectX = 0.0F;
		}
		char RunButton;
		//0なら移動していない、1なら右へ移動中、2なら左へ移動中
		char NonVertJumpFlag = 0;
		if ((Input&PAD_INPUT_2) > PAD_INPUT_ON) {
			RunButton = TRUE;
		}
		else {
			RunButton = FALSE;
		}
		//右へ移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			Dir = TRUE;
			NonVertJumpFlag = 1;
			if (RunButton == TRUE) {
				MoveX = 8.0F;
			}
			else {
				MoveX = 5.0F;
			}
		}
		//左に移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			Dir = FALSE;
			NonVertJumpFlag = 2;
			if (RunButton == TRUE) {
				MoveX = -8.0F;
			}
			else {
				MoveX = -5.0F;
			}
		}
		//垂直ジャンプ
		if (JumpFlag == FALSE && NonVertJumpFlag == 0 &&(EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//斜めへジャンプ
		if (JumpFlag == FALSE && NonVertJumpFlag == 1 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON ) {
			Grav = 0.5F;
			DropPower = -9.5F;
			if (RunButton == TRUE) {
				VectX = 8.0F;
			}
			else {
				VectX = 5.0F;
			}
			//斜めに飛んでいることを確認
			NonVertJump = TRUE;
			JumpFlag = TRUE;
			//コントロールカウントをリセット
			ContCnt = 0;
		}
		if (JumpFlag == FALSE && NonVertJumpFlag == 2 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			if (RunButton == TRUE) {
				VectX = -8.0F;
			}
			else {
				VectX = -5.0F;
			}
			//斜めに飛んでいることを確認
			NonVertJump = TRUE;
			JumpFlag = TRUE;
			//コントロールカウントをリセット
			ContCnt = 0;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && VectX > 0 && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			VectX -= 0.1F;
			DropPower -= 0.1F;
			MoveX = VectX;
		}
		if (NonVertJump == TRUE && VectX > 0 && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			DropPower += 0.3F;
			MoveX = VectX;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && VectX < 0 && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			VectX += 0.1F;
			DropPower -= 0.1F;
			MoveX = VectX;
		}
		if (NonVertJump == TRUE && VectX < 0 && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			DropPower += 0.3F;
			MoveX = VectX;
		}
		ContCnt++;
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, &VectX, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	AllocConsole(); FILE* out = 0; freopen_s(&out, "CON", "w", stdout); Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
	init();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		main();
	}
	DxLib_End(); fclose(out); FreeConsole();
	return 0;
}

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#11

投稿記事 by keito940 » 8年前

要は、移動しながらジャンプしたときに、その距離を保存して、前に行くときは落下力を追加して、後ろに行くときは保存した距離と落下力を下げるわけですね?
(本コードでは保存した距離はVectXとよんでいます。)
でも、時折めり込んでしまいます。なので解決したとは言い切れません。次の課題はめり込み防止のアルゴリズムの組み方を教えて下さい。

コード:

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d,VectX = %8.1f", Dir, NonVertJump, VectX);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//入力状態を更新
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		int DashTimer = 8;
		int ContTimer = 8;
		int DashCnt = 0;
		int ContCnt = 0;
		//ベクトルを初期化
		MoveX = 0.0F;
		MoveY = 0.0F;
		if (NonVertJump == FALSE) {
			VectX = 0.0F;
		}
		char RunButton;
		//0なら移動していない、1なら右へ移動中、2なら左へ移動中
		char NonVertJumpFlag = 0;
		if ((Input&PAD_INPUT_2) > PAD_INPUT_ON) {
			RunButton = TRUE;
		}
		else {
			RunButton = FALSE;
		}
		//右へ移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			Dir = TRUE;
			NonVertJumpFlag = 1;
			if (RunButton == TRUE && JumpFlag == FALSE) {
				MoveX = 8.0F;
			}
			else if(RunButton == FALSE && JumpFlag == FALSE){
				MoveX = 5.0F;
			}
			else {
				MoveX = 3.0F;
			}
		}
		//左に移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			Dir = FALSE;
			NonVertJumpFlag = 2;
			if (RunButton == TRUE) {
				MoveX = -8.0F;
			}
			else if(RunButton == FALSE && JumpFlag == FALSE){
				MoveX = -5.0F;
			}
			else {
				MoveX = -3.0F;
			}
		}
		//垂直ジャンプ
		if (JumpFlag == FALSE && NonVertJumpFlag == 0 &&(EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//斜めへジャンプ
		if (JumpFlag == FALSE && NonVertJumpFlag == 1 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON ) {
			Grav = 0.5F;
			DropPower = -9.5F;
			if (RunButton == TRUE) {
				VectX = 8.0F;
			}
			else {
				VectX = 5.0F;
			}
			//斜めに飛んでいることを確認
			NonVertJump = TRUE;
			JumpFlag = TRUE;
			//コントロールカウントをリセット
			ContCnt = 0;
		}
		if (JumpFlag == FALSE && NonVertJumpFlag == 2 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			if (RunButton == TRUE) {
				VectX = -8.0F;
			}
			else {
				VectX = -5.0F;
			}
			//斜めに飛んでいることを確認
			NonVertJump = TRUE;
			JumpFlag = TRUE;
			//コントロールカウントをリセット
			ContCnt = 0;
		}
		if (NonVertJump == TRUE && VectX == 0) {
			NonVertJump = FALSE;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && VectX > 0 && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			VectX -= 0.5F;
			DropPower -= 0.1F;
			MoveX = VectX;
		}
		if (NonVertJump == TRUE && VectX > 0 && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			DropPower += 0.3F;
			MoveX = VectX;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && VectX < 0 && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			VectX += 0.5F;
			DropPower -= 0.1F;
			MoveX = VectX;
		}
		if (NonVertJump == TRUE && VectX < 0 && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			DropPower += 0.3F;
			MoveX = VectX;
		}
		ContCnt++;
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, &VectX, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#12

投稿記事 by keito940 » 8年前

更に改造を加えるついでに http://dixq.net/forum/viewtopic.php?f=3&t=11328 を参考にして、マリオ同様にジャンプの量を調整できるようにしてみました。
…ですが、長く押しているつもりなのに短く押したとみなされてしまいます。デバッグ用コンソールさんによると、ジャンプ時間の変数に長く押しているはずなのに1しか代入されていません。

コード:

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d,VectX = %8.1f,JumpTimer = %d", Dir, NonVertJump, VectX,JumpTimer);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//入力状態を更新
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		float MaxVect;
		int DashTimer = 8;
		int ContTimer = 8;
		DashCnt = 0;
		ContCnt = 0;
		//ベクトルを初期化し、加減速処理を行う。
		if (NonVertJump == FALSE) {
			MoveX = 0.0F;
			VectX = 0.0F;
			MaxVect = 0.0F;
		}
		else {
			MoveX = VectX;
		}
		MoveY = 0.0F;
		char RunButton;
		//0なら移動していない、1なら右へ移動中、2なら左へ移動中
		char NonVertJumpFlag = 0;
		if ((Input&PAD_INPUT_2) > PAD_INPUT_ON) {
			RunButton = TRUE;
		}
		else {
			RunButton = FALSE;
		}
		//右へ移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			Dir = TRUE;
			NonVertJumpFlag = 1;
			if (RunButton == TRUE && JumpFlag == FALSE) {
				MoveX = 8.0F;
			}
			else if(RunButton == FALSE && JumpFlag == FALSE){
				MoveX = 5.0F;
			}
			else {
				MoveX = 3.0F;
			}
		}
		//左に移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			Dir = FALSE;
			NonVertJumpFlag = 2;
			if (RunButton == TRUE) {
				MoveX = -8.0F;
			}
			else if(RunButton == FALSE && JumpFlag == FALSE){
				MoveX = -5.0F;
			}
			else {
				MoveX = -3.0F;
			}
		}
		if (JumpTimer == 0 && JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			if (JumpTimer > 0 && (Input&PAD_INPUT_1) > PAD_INPUT_ON) {
				JumpTimer++;
			}
			if (JumpTimer < 10 && NonVertJumpFlag == 0) {
				Grav = 0.5F;
				DropPower = -5.0F;
				JumpFlag = TRUE;
			}
			//垂直大ジャンプ
			if (JumpTimer == 10 && NonVertJumpFlag == 0) {
				Grav = 0.5F;
				DropPower = -9.5F;
				JumpFlag = TRUE;
			}
			//斜めへジャンプ
			if (JumpFlag == FALSE && NonVertJumpFlag == 1 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
				Grav = 0.5F;
				DropPower = -9.5F;
				if (RunButton == TRUE) {
					VectX = 8.0F;
					MaxVect = 8.0F;
				}
				else {
					VectX = 5.0F;
					MaxVect = 5.0F;
				}
				//斜めに飛んでいることを確認
				NonVertJump = TRUE;
				JumpFlag = TRUE;
				//コントロールカウントをリセット
				ContCnt = 0;
			}
			if (JumpFlag == FALSE && NonVertJumpFlag == 2 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
				Grav = 0.5F;
				DropPower = -9.5F;
				if (RunButton == TRUE) {
					VectX = -8.0F;
				}
				else {
					VectX = -5.0F;
				}
				//斜めに飛んでいることを確認
				NonVertJump = TRUE;
				JumpFlag = TRUE;
				//コントロールカウントをリセット
				ContCnt = 0;
			}
		}
		if (NonVertJump == TRUE && VectX == 0) {
			NonVertJump = FALSE;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && VectX > 0 &&(Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			VectX -= 0.5F;
			if (DropPower < 0) {
				DropPower += 0.1F;
			}
			else {
				DropPower -= 0.1F;
			}
			MoveX = VectX;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && VectX < 0 &&(Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			VectX += 0.5F;
			if (DropPower < 0) {
				DropPower += 0.1F;
			}
			else {
				DropPower -= 0.1F;
			}
			MoveX = VectX;
		}
		ContCnt++;
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, &JumpTimer ,&VectX, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}

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

Re: マリオ風の加減速付きジャンプができない。

#13

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

keito940 さんが書きました:

コード:

		if (JumpTimer == 0 && JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			if (JumpTimer > 0 && (Input&PAD_INPUT_1) > PAD_INPUT_ON) {
				JumpTimer++;
			}
			if (JumpTimer < 10 && NonVertJumpFlag == 0) {
				Grav = 0.5F;
				DropPower = -5.0F;
				JumpFlag = TRUE;
			}
			//垂直大ジャンプ
			if (JumpTimer == 10 && NonVertJumpFlag == 0) {
				Grav = 0.5F;
				DropPower = -9.5F;
				JumpFlag = TRUE;
			}
1が代入されるというのはわかりませんが、「JumpTimerが0」のときしか実行されないはずの場所に「JumpTimerが0より大きい」や「JumpTimerが10」という条件による分岐があるのは怪しいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#14

投稿記事 by keito940 » 8年前

もしかしてこういうことかなって思ったんですけど、今度はジャンプができなくなってしまいました。

コード:

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	printf("\n現在の向き=%d\t右は1、左は0,NonVert = %d,VectX = %8.1f,JumpTimer = %d", Dir, NonVertJump, VectX,JumpTimer);
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//入力状態を更新
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		float MaxVect;
		int DashTimer = 8;
		int ContTimer = 8;
		DashCnt = 0;
		ContCnt = 0;
		//ベクトルを初期化し、加減速処理を行う。
		if (NonVertJump == FALSE) {
			MoveX = 0.0F;
			VectX = 0.0F;
			MaxVect = 0.0F;
		}
		else {
			MoveX = VectX;
		}
		MoveY = 0.0F;
		char RunButton;
		//0なら移動していない、1なら右へ移動中、2なら左へ移動中
		char NonVertJumpFlag = 0;
		if ((Input&PAD_INPUT_2) > PAD_INPUT_ON) {
			RunButton = TRUE;
		}
		else {
			RunButton = FALSE;
		}
		//右へ移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			Dir = TRUE;
			NonVertJumpFlag = 1;
			if (RunButton == TRUE && JumpFlag == FALSE) {
				MoveX = 8.0F;
			}
			else if (RunButton == FALSE && JumpFlag == FALSE) {
				MoveX = 5.0F;
			}
			else {
				MoveX = 3.0F;
			}
		}
		//左に移動
		if (NonVertJump == FALSE && (Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			Dir = FALSE;
			NonVertJumpFlag = 2;
			if (RunButton == TRUE) {
				MoveX = -8.0F;
			}
			else if (RunButton == FALSE && JumpFlag == FALSE) {
				MoveX = -5.0F;
			}
			else {
				MoveX = -3.0F;
			}
		}
		if (JumpTimer <= 0) {
			if ((Input&PAD_INPUT_1) > PAD_INPUT_ON) {
				JumpTimer++;
			}
		}
		else {
			if (JumpTimer < 10 && NonVertJumpFlag == 0) {
				Grav = 0.5F;
				DropPower = -5.0F;
				JumpFlag = TRUE;
			}
			//垂直大ジャンプ
			if (JumpTimer == 10 && NonVertJumpFlag == 0) {
				Grav = 0.5F;
				DropPower = -9.5F;
				JumpFlag = TRUE;
			}
			//斜めへジャンプ
			if (JumpFlag == FALSE && NonVertJumpFlag == 1 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
				Grav = 0.5F;
				DropPower = -9.5F;
				if (RunButton == TRUE) {
					VectX = 8.0F;
					MaxVect = 8.0F;
				}
				else {
					VectX = 5.0F;
					MaxVect = 5.0F;
				}
				//斜めに飛んでいることを確認
				NonVertJump = TRUE;
				JumpFlag = TRUE;
				//コントロールカウントをリセット
				ContCnt = 0;
			}
			if (JumpFlag == FALSE && NonVertJumpFlag == 2 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
					Grav = 0.5F;
					DropPower = -9.5F;
					if (RunButton == TRUE) {
						VectX = -8.0F;
					}
					else {
						VectX = -5.0F;
					}
					//斜めに飛んでいることを確認
					NonVertJump = TRUE;
					JumpFlag = TRUE;
					//コントロールカウントをリセット
					ContCnt = 0;
					}
			}
		}
		if (NonVertJump == TRUE && VectX == 0) {
			NonVertJump = FALSE;
		}
		//右へジャンプしているときに左で減速
		if (NonVertJump == TRUE && VectX > 0 &&(Input&PAD_INPUT_LEFT) > PAD_INPUT_ON) {
			VectX -= 0.5F;
			if (DropPower < 0) {
				DropPower += 0.1F;
			}
			else {
				DropPower -= 0.1F;
			}
			MoveX = VectX;
		}
		//左へジャンプしているときに右で減速
		if (NonVertJump == TRUE && VectX < 0 &&(Input&PAD_INPUT_RIGHT) > PAD_INPUT_ON) {
			VectX += 0.5F;
			if (DropPower < 0) {
				DropPower += 0.1F;
			}
			else {
				DropPower -= 0.1F;
			}
			MoveX = VectX;
		}
		ContCnt++;
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, &AirFlag, &NonVertJump, &JumpTimer ,&VectX, CHIP_SIZE);
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}


keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#15

投稿記事 by keito940 » 8年前

コードを以下のようにしたら、移動したときに落下して、何もしていないときにジャンプしてしまいます。
どうすれば治るのでしょうか?みけCATさん、1が代入されるじゃ不適切でしたね。正しくは長く押しているつもりなのにジャンプ時間用の変数が1しか増えないでした。こうすれば原因がわかるでしょう。

コード:

if (JumpTimer < 0) {
		if ((Input&PAD_INPUT_1) > PAD_INPUT_ON) {
			JumpTimer++;
		}
	}
	else {
		if (JumpTimer < 10 && NonVertJumpFlag == 0) {
			Grav = 0.5F;
			DropPower = -5.0F;
			JumpFlag = TRUE;
		}
		//垂直大ジャンプ
		if (JumpTimer == 10 && NonVertJumpFlag == 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//斜めへジャンプ
		if (JumpFlag == FALSE && NonVertJumpFlag == 1 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
			Grav = 0.5F;
			DropPower = -9.5F;
			if (RunButton == TRUE) {
				VectX = 8.0F;
				MaxVect = 8.0F;
			}
			else {
				VectX = 5.0F;
				MaxVect = 5.0F;
			}
			//斜めに飛んでいることを確認
			NonVertJump = TRUE;
			JumpFlag = TRUE;
			//コントロールカウントをリセット
			ContCnt = 0;
		}
		if (JumpFlag == FALSE && NonVertJumpFlag == 2 && (EdgeInput&PAD_INPUT_1) > PAD_INPUT_ON) {
				Grav = 0.5F;
				DropPower = -9.5F;
				if (RunButton == TRUE) {
					VectX = -8.0F;
				}
				else {
					VectX = -5.0F;
				}
				//斜めに飛んでいることを確認
				NonVertJump = TRUE;
				JumpFlag = TRUE;
				//コントロールカウントをリセット
				ContCnt = 0;
			}
		}
	}

keito940
記事: 105
登録日時: 8年前

Re: マリオ風の加減速付きジャンプができない。

#16

投稿記事 by keito940 » 8年前

すいません。一応解決らしいので、ここで閉めさせて頂きます。
さっきの質問の件は、 http://dixq.net/forum/viewtopic.php?f=3&t=18931 でお願いします。

返信

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