DXライブラリでギミックを...

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

DXライブラリでギミックを...

#1

投稿記事 by fey » 13年前

コード:

 
#include "DxLib.h"

#define SCREEN_WIDTH	 (640)                         // 画面の横幅
#define SCREEN_HEIGHT    (480)                          // 画面の縦幅
#define MAP_PIXEL_WIDTH (1280)
#define MAP_PIXEL_HEIGHT (480)
#define CHIP_SIZE        (32)                           // 一つのチップのサイズ
#define MAP_WIDTH        ( MAP_PIXEL_WIDTH / CHIP_SIZE)     // マップの横幅
#define MAP_HEIGHT       (MAP_PIXEL_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, 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,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, 1,1,1,0,0, 0,0,0,0,0, 0,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,0, 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,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,0, 0,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1,
 
    1,0,0,0,0, 0,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,0,0, 1,1,1,1,1,
    1,0,0,0,0, 0,0,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,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,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, 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, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 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, 1,1,1,1,1, 0,0,0,0,1,
 
    1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,1, 1,0,0,0,0, 2,2,2,2,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,1, 0,0,0,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,1,1, 1,0,0,0,0, 0,0,0,0,0, 1,1,1,1,1, 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,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, 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 camerax = 0;//カメラの左上座標
int charx;//自キャラ位置
int view_charx;//自キャラの表示位置。この座標にdrawする。

 
// マップチップの値を取得する関数
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 = 48.0F ;
	PlY = 0.0F ;
 
    // プレイヤーの落下速度を初期化
    PlDownSp = 0.0F ;
 
    // ジャンプ中フラグを倒す
    PlJumpFlag = FALSE ;
 
    // 入力状態の初期化
    Input = 0 ;
    EdgeInput = 0 ;
 
    // 60FPS固定用、時間保存用変数を現在のカウント値にセット
    FrameStartTime = GetNowCount() ;
 
    // メインループ開始、ESCキーで外に出る
    while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
    {
        // 画面のクリア
        ClsDrawScreen() ;
 
        // 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 ) ;
        }

		//自キャラの座標の代入
		charx = PlX;
		//カメラ位置を計算
		camerax = PlX - SCREEN_WIDTH/2;
		//左右の補正
		if( camerax < 0 ) camerax = 0;
		if( camerax > (MAP_PIXEL_WIDTH-SCREEN_WIDTH) ) camerax = (MAP_PIXEL_WIDTH-SCREEN_WIDTH);
		//画面内の位置を求める。
		view_charx = charx - camerax;

        // マップの描画
        {
            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 - camerax,                i * CHIP_SIZE,
                                 j * CHIP_SIZE + CHIP_SIZE - camerax,    i * CHIP_SIZE + CHIP_SIZE,
                                 GetColor( 255, 255, 255 ), TRUE ) ;
                    }
                    if( MapData[i][j] == 2 )
                    {
                        DrawBox( j * CHIP_SIZE - camerax,                i * CHIP_SIZE,
                                 j * CHIP_SIZE + CHIP_SIZE - camerax,    i * CHIP_SIZE + CHIP_SIZE,
                                 GetColor( 255, 0, 255 ), TRUE ) ;
                    }
                }
            }
        }
 
        // キャラクタの描画
        DrawBox( ( int )(view_charx - CHAR_SIZE * 0.5F),     ( int )( PlY - CHAR_SIZE * 0.5F ),
                 ( int )( view_charx + 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 ) != 0 )
    {
        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(GetChipParam(afX, afY) == 1){
			// 上辺に当たっていた場合
			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 ;
			}
		}

		else if(GetChipParam(afX, afY) == 2){
			if( *MoveY > 0.0F )
			{
				// 移動量を補正する
				*MoveY = bty - Y - 1.0F  ;
				// 上辺に当たったと返す
				return 3 ;
			}
		}
 
        // ここに来たら適当な値を返す
        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 ] ;
}
このコードでマップチップに2が入っているところのブロックを下からジャンプしたら透けて上に乗るようにしたいのですが、
真下からならうまくいくのですが端からや、横に当たるとおかしくなってしまいます。
どこが間違えているのでしょうか?

※DXライブラリを使用しています。

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#2

投稿記事 by kimuchi » 13年前

>>369行目

このreturnの値が問題かもしれません。
見ると4は下辺判定のようなので、
適当な値にこれを返すのはまずい気がします。

fey

Re: DXライブラリでギミックを...

#3

投稿記事 by fey » 13年前

return4をなくすと端からジャンプして、上れるようになりましたが、
やはり横からあたると可笑しくなってしまいます。

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#4

投稿記事 by kimuchi » 13年前

ブロックに左右の当たり判定が無いからではないでしょうか?

追記
左右に当たり判定があると駄目ですね。失礼しました。
こちらではそのような現象は起こりませんでした。
具体的にどの様なことが起こるのでしょうか?

fey

Re: DXライブラリでギミックを...

#5

投稿記事 by fey » 13年前

マップチップ2台の上からジャンプして横から当たるとその台の中に入ってしまいます。
同化する、と言ったほうが正しいかもしれません。

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#6

投稿記事 by kimuchi » 13年前

現象確認できました。
此方の見る限りは、
キャラが降下中(MoveY>0)のときに横から当たると起こっているように思われます。
すり抜け床ということで、キャラが部分的にブロックの中にめり込み、
左下もしくは、右下判定が誤作動しているのだと思います。

追記:
よくよくデバッグしてみると、バグを引き起こしていたのは左上、右上判定でした。

fey

Re: DXライブラリでギミックを...

#7

投稿記事 by fey » 13年前

では、どこをどう直せばよいのでしょうか?

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#8

投稿記事 by kimuchi » 13年前

コード:

//プロトタイプ
int MapHitCheck( int flag, float X, float Y, float *MoveX, float *MoveY ) ;

コード:

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

コード:

int MapHitCheck( int flag, float X, float Y,
                    float *MoveX, float *MoveY )
{
<略>
        else if(GetChipParam(afX, afY) == 2){
            if( *MoveY > 0.0F && flag < 3 && Y < bty ){
                // 移動量を補正する
                *MoveY = bty - Y - 1.0F  ;
                // 上辺に当たったと返す
                return 3 ;
            }
        }
    }
 
    // どこにも当たらなかったと返す
    return 0 ;
}
かなり安直ですが、左上、右上、左下、右下それぞれにフラグを振ってやって、
左下、右下判定以外を掃いたうえで、移動前のY座標が、ブロックの上辺より上(数値的には下)の場合のみ
当たり判定を返しています。
一応お望みの動作にはなったと思うのですが、コード的にはイマイチかもしれません。

fey

Re: DXライブラリでギミックを...

#9

投稿記事 by fey » 13年前

なるほど...できました!
ありがとうございます!

もうひとつ聞きたいことがあるのですが、良いでしょうか?
よければ教えていただけると助かります。

透ける床のほかに、ハシゴ(十字キーの上下で移動、途中で左右の入力も検知)を作りたいのですが、
どのように条件を書けばよいのでしょうか?

※ハシゴ = マリオワールドのツタの様な物 (外見は箱で大丈夫です)

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#10

投稿記事 by kimuchi » 13年前

とりあえず動けばいい、というかなり個人的な思考で書きます。
また、お望みのものとは異なる可能性もあります。ご了承下さい。

まず、ハシゴを登るという動作をアクションとして考えます。

コード:

//テンキーによるアクションフラグ
int DirAction = 0;
ハシゴは上下のキー入力で登ると思います。

コード:

// 上下の移動を見る
if( ( Input & PAD_INPUT_UP ) != 0 ) DirAction = 1 ;
if( ( Input & PAD_INPUT_DOWN ) != 0 ) DirAction = -1 ;
上下キーが入力されたら、キーに応じたフラグを入れます。
ハシゴもマップを構成する一つのチップとしておきます。

コード:

// マップデータ
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, 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,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, 1,1,1,0,0, 0,0,0,0,0, 0,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,0, 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,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,0, 0,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1,
 
    1,0,0,0,0, 0,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,0,0, 1,1,1,1,1,
    1,0,0,0,0, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 1,1,1,1,1, 0,0,0,0,1,
 
    1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,1, 1,0,0,0,0, 2,2,2,2,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,1,1,1,1, 0,0,0,1,1, 1,0,0,0,0, 0,0,0,0,3, 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,1,1, 1,0,0,0,0, 0,0,0,0,3, 1,1,1,1,1, 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,3, 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, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1,
} ;
//*3番がハシゴチップです。
あとは、他のブロックと同じように当たり判定時にアクションを実行します。

コード:

//引数の変更
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, float Size, char *JumpFlag, int DirAction ) ;
int MapHitCheck( int flag, float X, float Y, float *MoveX, float *MoveY, int DirAction ) ;

コード:

    // 先ず上下移動成分だけでチェック
    {
        // 左下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( 1, *X - hsize, *Y + hsize, &Dummy, &MoveY, DirAction ) == 3 ) *DownSP = 0.0F ;
 
        // 右下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( 2, *X + hsize, *Y + hsize, &Dummy, &MoveY, DirAction ) == 3 ) *DownSP = 0.0F ;
 
        // 左上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( 3, *X - hsize, *Y - hsize, &Dummy, &MoveY, DirAction ) == 4 ) *DownSP *= -1.0F ;
 
        // 右上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( 4, *X + hsize, *Y - hsize, &Dummy, &MoveY, DirAction ) == 4 ) *DownSP *= -1.0F ;
 
        // 上下移動成分を加算
        *Y += MoveY ;
    }
 
    // 後に左右移動成分だけでチェック
    {
        // 左下のチェック
        MapHitCheck( 1, *X - hsize, *Y + hsize, &MoveX, &Dummy, DirAction ) ;
 
        // 右下のチェック
        MapHitCheck( 2, *X + hsize, *Y + hsize, &MoveX, &Dummy, DirAction ) ;
 
        // 左上のチェック
        MapHitCheck( 3, *X - hsize, *Y - hsize, &MoveX, &Dummy, DirAction ) ;
 
        // 右上のチェック
        MapHitCheck( 4, *X + hsize, *Y - hsize, &MoveX, &Dummy, DirAction ) ;
 
        // 左右移動成分を加算
        *X += MoveX ;
    }
以下が、当たり判定とハシゴを登るアクションを設定している部分です。

コード:

int MapHitCheck( int flag, float X, float Y,
                    float *MoveX, float *MoveY, int DirAction )
{
    float afX, afY ;
//追加部分
    static int Action=0;

<略>

    else if(GetChipParam(afX, afY) == 3){
        if( DirAction ) Action = DirAction;
        if( (int)*MoveX ) Action = 0;
        if( Action ){
            // 移動量を補正する
            *MoveY = -3.0f*DirAction  ;
            // 上辺に当たったと返す
            return 3 ;
        }
    }
    // どこにも当たらなかったと返す
    return 0 ;
}
DirActionは±1の値を持っているので、上下動が可能になっています。
静的変数ActionにDirActionを保存しているのは、上下キーを押さない時もぶら下がっているイメージで
その場にとどまるためです。また、左右キー入力時に梯子から手を離すような動作も可能です。

↓念のため実行確認したコードです。
► スポイラーを表示

fey

Re: DXライブラリでギミックを...

#11

投稿記事 by fey » 13年前

できました!ありがとうございます!

あまり気にはならないのですがはしごの上か下にマップチップで言う1のブロックがあるとめりこみますねw

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#12

投稿記事 by kimuchi » 13年前

う、これはヒドイですね。
ちょっと他にもいろいろ書換えてしまいましたが修正コードです。

コード:

//引数float Sizeを削除 <理由:CHAR_SIZEが定義で決まっていたので。
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, char *JumpFlag, int DirAction ) ;
//引数int flagを削除 <理由:関数の書き換えで必要なくなりました。
//代わりにfloat *DownSPを追加
int MapHitCheck( float X, float Y, float *DownSP, float *MoveX, float *MoveY, int DirAction ) ;

*メインループ内のCharMove関数の引数、CHAR_SIZEも削除して下さい。

コード:

// キャラクタをマップとの当たり判定を考慮しながら移動する
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, char *JumpFlag, int DirAction )
{
    float Dummy = 0.0F ;
  
	// 上下当たり判定
	MapHitCheck( *X, *Y, DownSP, &Dummy, &MoveY, DirAction );
  
    // 上下移動成分を加算
    *Y += MoveY ; 
 
	// 左右当たり判定
	MapHitCheck( *X, *Y, DownSP, &MoveX, &Dummy, DirAction );

	// 左右移動成分を加算
	*X += MoveX ;
 
    // 接地判定
    {
        // キャラクタの左下と右下の下に地面があるか調べる
        if( GetChipParam( *X - CHAR_SIZE * 0.5F, *Y + CHAR_SIZE * 0.5F + 1.0F ) == 0 && 
            GetChipParam( *X + CHAR_SIZE * 0.5F, *Y + CHAR_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 *DownSP,
                    float *MoveX, float *MoveY, int DirAction )
{
	static int Action=0;
    float afX, afY, beX, beY ;
    float blx, bty, brx, bby ;
    float hsize = float(CHAR_SIZE) * 0.5F ;
	int i;

	//左上、右上、左下、右下の判定
	for(i=0; i<4; i++){

		// 移動量を足す
		beX = X + hsize*(i%2?1.0F:-1.0F);
		beY = Y + hsize*(i/2?-1.0F:1.0F);
		afX = beX + *MoveX;
		afY = beY + *MoveY;
  
		// ブロックの上下左右の座標を算出
		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 座標

		// 当たり判定のあるブロックに当たっているかチェック
		switch( GetChipParam( afX, afY ) )
		{
			case 1:{
				// 上辺に当たっていた場合
				if( *MoveY > 0.0F )
				{
					*MoveY = bty - beY - 1.0F;
					*DownSP = 0.0F;
				}
				// 下辺に当たっていた場合
				else if( *MoveY < 0.0F )
				{
					*MoveY = bby - beY + 1.0F;
					if(*DownSP<0)
						*DownSP *= -1.0F;
				}
				// 左辺に当たっていた場合
				if( *MoveX > 0.0F )
				{
					*MoveX = blx - beX - 1.0F ;
				}
				// 右辺に当たっていた場合
				else if( *MoveX < 0.0F )
				{
					*MoveX = brx - beX + 1.0F ;
				}
				break;
			}
			case 2:{
				if( *MoveY > 0.0F && Y+hsize < bty ){
					*MoveY = bty - beY - 1.0F ;
					*DownSP = 0.0F;
				}
				break;
			}
			case 3:{
				if( DirAction ) Action = DirAction;
				if( (int)*MoveX ) Action = 0;
				if( Action ){
					if( DirAction>0 && GetChipParam( afX, Y-hsize-1.0f )==3 )
						*MoveY = -3.0f;
					else if( DirAction<0 && GetChipParam( afX, Y+hsize+1.0f )==3 )
						*MoveY = 3.0f;
					else *MoveY = 0.0f;
					*DownSP = 0.0F;
				}
				break;
			}
			default: break;
		}
	}
 
    return 0 ;
}

コードについて疑問点などありましたらお気軽にどうぞ。
ところで、一つだけ意見を申しますと、キャラクターの情報、
例えば、X,Y座標や、MoveX,MoveYの移動方向成分などを構造体、
もしくはクラスとして定義してはいかがでしょうか?
関数でも頻繁にこれらの値のポインタを引数として利用されているので、
グローバル宣言で、これらの構造体・クラスを定義しておけば、
関数の引数を少なくでき、かつ変数の役割がパッと見て分かるので、
処理が分かりやすくなる効果もあると思います。

fey

Re: DXライブラリでギミックを...

#13

投稿記事 by fey » 13年前

この場合、はしごに少しでも触れている状態だとジャンプできてしまうのですが
これは僕のソースのせいなのでしょうか?

実験お願いします。

fey

Re: DXライブラリでギミックを...

#14

投稿記事 by fey » 13年前

はしごに触れていると、と言うより

判定自体がおかしくなってしまっているようです。
やはり、僕のソース自身がおかしくなっているのでしょうか...

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: DXライブラリでギミックを...

#15

投稿記事 by kimuchi » 13年前

こちらが実行確認したコードです。
上げた以外にも変更した場所があったかもしれませんね。(汗)

コード:

 
#include "DxLib.h"
 
#define SCREEN_WIDTH     (640)                         // 画面の横幅
#define SCREEN_HEIGHT    (480)                          // 画面の縦幅
#define MAP_PIXEL_WIDTH (1280)
#define MAP_PIXEL_HEIGHT (480)
#define CHIP_SIZE        (32)                           // 一つのチップのサイズ
#define MAP_WIDTH        ( MAP_PIXEL_WIDTH / CHIP_SIZE)     // マップの横幅
#define MAP_HEIGHT       (MAP_PIXEL_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, 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,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, 1,1,1,0,0, 0,0,0,0,0, 0,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,0, 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,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,0, 0,1,1,1,1, 0,0,0,0,0, 0,0,0,0,1,
 
    1,0,0,0,0, 0,1,1,1,1, 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, 1,1,1,1,1,
    1,0,0,0,0, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,3, 0,0,0,0,0, 1,1,1,1,1, 0,0,0,0,1,
 
    1,0,0,0,0, 1,1,1,1,0, 0,0,0,0,1, 1,0,0,0,0, 2,2,2,2,3, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 1,1,1,1,1, 0,0,0,1,1, 1,0,0,0,0, 0,0,0,0,3, 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,1,1, 1,0,0,0,0, 0,0,0,0,3, 1,1,1,1,1, 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,3, 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, 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 camerax = 0;//カメラの左上座標
int charx;//自キャラ位置
int view_charx;//自キャラの表示位置。この座標にdrawする。
 
 
// マップチップの値を取得する関数
int GetChipParam( float X, float Y ) ;
 
// キャラクタをマップとの当たり判定を考慮しながら移動する関数
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, char *JumpFlag, int DirAction ) ;
 
// アクションサンプルプログラムメイン関数
int ActMain( void ) ;
 
// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
int MapHitCheck( float X, float Y, float *DownSP, float *MoveX, float *MoveY, int DirAction ) ;
 
 
 
 
// 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 = 48.0F ;
    PlY = 0.0F ;
 
    // プレイヤーの落下速度を初期化
    PlDownSp = 0.0F ;
 
    // ジャンプ中フラグを倒す
    PlJumpFlag = FALSE ;
 
    // 入力状態の初期化
    Input = 0 ;
    EdgeInput = 0 ;
 
    // 60FPS固定用、時間保存用変数を現在のカウント値にセット
    FrameStartTime = GetNowCount() ;
 
    // メインループ開始、ESCキーで外に出る
    while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
    {
        // 画面のクリア
        ClsDrawScreen() ;
 
        // 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 ;
			int DirAction = 0;
 
            // 移動量の初期化
            MoveX = 0.0F ;
            MoveY = 0.0F ;
 
            // 左右の移動を見る
            if( ( Input & PAD_INPUT_LEFT ) != 0 ) MoveX -= SPEED ;
            if( ( Input & PAD_INPUT_RIGHT ) != 0 ) MoveX += SPEED ;

            // 上下の移動を見る
            if( ( Input & PAD_INPUT_UP ) != 0 ) DirAction = 1 ;
            if( ( Input & PAD_INPUT_DOWN ) != 0 ) DirAction = -1 ;

            // 地に足が着いている場合のみジャンプボタン(ボタン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, &PlJumpFlag, DirAction ) ;
        }
 
        //自キャラの座標の代入
        charx = PlX;
        //カメラ位置を計算
        camerax = PlX - SCREEN_WIDTH/2;
        //左右の補正
        if( camerax < 0 ) camerax = 0;
        if( camerax > (MAP_PIXEL_WIDTH-SCREEN_WIDTH) ) camerax = (MAP_PIXEL_WIDTH-SCREEN_WIDTH);
        //画面内の位置を求める。
        view_charx = charx - camerax;
 
        // マップの描画
        {
            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 - camerax,                i * CHIP_SIZE,
                                 j * CHIP_SIZE + CHIP_SIZE - camerax,    i * CHIP_SIZE + CHIP_SIZE,
                                 GetColor( 255, 255, 255 ), TRUE ) ;
                    }
                    if( MapData[i][j] == 2 )
                    {
                        DrawBox( j * CHIP_SIZE - camerax,                i * CHIP_SIZE,
                                 j * CHIP_SIZE + CHIP_SIZE - camerax,    i * CHIP_SIZE + CHIP_SIZE,
                                 GetColor( 255, 0, 255 ), TRUE ) ;
                    }
                    if( MapData[i][j] == 3 )
                    {
                        DrawBox( j * CHIP_SIZE - camerax,                i * CHIP_SIZE,
                                 j * CHIP_SIZE + CHIP_SIZE - camerax,    i * CHIP_SIZE + CHIP_SIZE,
                                 GetColor( 255, 255, 0 ), TRUE ) ;
                    }
                }
            }
        }
 
        // キャラクタの描画
        DrawBox( ( int )(view_charx - CHAR_SIZE * 0.5F),     ( int )( PlY - CHAR_SIZE * 0.5F ),
                 ( int )( view_charx + 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, char *JumpFlag, int DirAction )
{
    float Dummy = 0.0F ;
  
	// 上下当たり判定
	MapHitCheck( *X, *Y, DownSP, &Dummy, &MoveY, DirAction );
  
    // 上下移動成分を加算
    *Y += MoveY ; 
 
	// 左右当たり判定
	MapHitCheck( *X, *Y, DownSP, &MoveX, &Dummy, DirAction );

	// 左右移動成分を加算
	*X += MoveX ;
 
    // 接地判定
    {
        // キャラクタの左下と右下の下に地面があるか調べる
        if( GetChipParam( *X - CHAR_SIZE * 0.5F, *Y + CHAR_SIZE * 0.5F + 1.0F ) == 0 && 
            GetChipParam( *X + CHAR_SIZE * 0.5F, *Y + CHAR_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 *DownSP,
                    float *MoveX, float *MoveY, int DirAction )
{
	static int Action=0;
    float afX, afY, beX, beY ;
    float blx, bty, brx, bby ;
    float hsize = float(CHAR_SIZE) * 0.5F ;
	int i;

	//左上、右上、左下、右下の判定
	for(i=0; i<4; i++){

		// 移動量を足す
		beX = X + hsize*(i%2?1.0F:-1.0F);
		beY = Y + hsize*(i/2?-1.0F:1.0F);
		afX = beX + *MoveX;
		afY = beY + *MoveY;
  
		// ブロックの上下左右の座標を算出
		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 座標

		// 当たり判定のあるブロックに当たっているかチェック
		switch( GetChipParam( afX, afY ) )
		{
			case 1:{
				// 上辺に当たっていた場合
				if( *MoveY > 0.0F )
				{
					*MoveY = bty - beY - 1.0F;
					*DownSP = 0.0F;
				}
				// 下辺に当たっていた場合
				else if( *MoveY < 0.0F )
				{
					*MoveY = bby - beY + 1.0F;
					if(*DownSP<0)
						*DownSP *= -1.0F;
				}
				// 左辺に当たっていた場合
				if( *MoveX > 0.0F )
				{
					*MoveX = blx - beX - 1.0F ;
				}
				// 右辺に当たっていた場合
				else if( *MoveX < 0.0F )
				{
					*MoveX = brx - beX + 1.0F ;
				}
				break;
			}
			case 2:{
				if( *MoveY > 0.0F && Y+hsize < bty ){
					*MoveY = bty - beY - 1.0F ;
					*DownSP = 0.0F;
				}
				break;
			}
			case 3:{
				if( DirAction ) Action = DirAction;
				if( (int)*MoveX ) Action = 0;
				if( Action ){
					if( DirAction>0 && GetChipParam( afX, Y-hsize-1.0f )==3 )
						*MoveY = -3.0f;
					else if( DirAction<0 && GetChipParam( afX, Y+hsize+1.0f )==3 )
						*MoveY = 3.0f;
					else *MoveY = 0.0f;
					*DownSP = 0.0F;
				}
				break;
			}
			default: break;
		}
	}
 
    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 ] ;
}

fey

Re: DXライブラリでギミックを...

#16

投稿記事 by fey » 13年前

できました!

色々試してみた結果やっぱり僕のソースがおかしかったみたいですw

どうもお騒がせしました。

本当にありがとうございました。

閉鎖

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