DXライブラリの横スクロールについてお聞きしたいのですが...

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

DXライブラリの横スクロールについてお聞きしたいのですが...

#1

投稿記事 by fey » 14年前

http://homepage2.nifty.com/natupaji/DxL ... Sample.cpp

ここのサンプルに横スクロールをつけるにはどうしたらよいのでしょうか?

自分なりに横スクロールをつけると画像は動いても当たり判定が残ってしまったりします。

http://homepage2.nifty.com/natupaji/DxL ... am.html#N4

これを参考にしてもこっちは移動が1ドット生制御じゃないのでうまくいきません。

誰か教えていただけないでしょうか?

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#2

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

マップ全体の座標と表示用の座標は分けることで解決します。
マップ全体のうちの一部が見える窓=ウィンドウ(カメラ)があると考えてみてください。
その窓はキャラの移動に合わせて移動します。

・キャラはマップ全体におけるピクセル座標を持ちます。
・表示窓の左上の座標をキャラの位置からピクセル位置で計算します。
・表示窓の座標をキャラの座標から引くと窓内の相対位置が出ますので、その座標で描画します。
・他の処理は全てマップ全体の座標で処理します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

fey

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#3

投稿記事 by fey » 14年前

行っていることは理解できるのですが、
それをどうやってこのプログラムに組み込むか
スクロール用にマップを大きくした、このサンプルを例に教えていただけないでしょうか?
ご迷惑お掛けします。

コード:

#include "DxLib.h"

#define SCREEN_WIDTH     (1280)                          // 画面の横幅
#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, 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, 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, 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, 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, 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, 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, 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, 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, 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,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,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 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 )
    {
        // 画面のクリア
        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 ) ;
        }

        // マップの描画
        {
            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 ] ;
}
必ずcodeタグで囲ってください。詳しくはフォーラムルールを。
by softya(ソフト屋)

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#4

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

仮想コードで書きますので移植してください。

コード:

#define SCREEN_WIDTH 640
#define MAP_WIDH 1280
int camerax = 0;//カメラの左上座標
int charx;//自キャラ位置
int view_charx;//自キャラの表示位置。この座標にdrawする。

//カメラ位置を計算
camerax = charx - SCREEN_WIDTH/2;
//左右の補正
if( camerax < 0 ) camerax = 0;
if( camerax > (MAP_WIDH-SCREEN_WIDTH) )  camerax = (MAP_WIDH-SCREEN_WIDTH);
//画面内の位置を求める。
view_charx = charx - camerax;
[追記]
マップチップも同様に。

コード:

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

fey(別PC)

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#5

投稿記事 by fey(別PC) » 14年前

何度もスイマセン;

どこにどんな感じで組み込めば良いのでしょうか?

物分りが悪くて申し訳ありません;;

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#6

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

fey(別PC) さんが書きました:何度もスイマセン;
どこにどんな感じで組み込めば良いのでしょうか?
物分りが悪くて申し訳ありません;;
ここでズバリ回答を書いても勉強になりませんので、よく考えてみてください。
charx は自キャラの位置です。これに該当するfeyさんのコードの変数は何でしょうか?
あとview_charxは自キャラを表示するときに使います。表示しているところはどこの部分ですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

fey(別PC)

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#7

投稿記事 by fey(別PC) » 14年前

// キャラクタの描画
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 ) ;

ここのPlXの位置をview_charxにすればよいのでしょうか?

後、MAPの描写はそのままでいけるのでしょうか?

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#8

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

fey(別PC) さんが書きました:// キャラクタの描画
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 ) ;

ここのPlXの位置をview_charxにすればよいのでしょうか?

後、MAPの描写はそのままでいけるのでしょうか?
feyさんのコードと
#define SCREEN_WIDTH 640
#define MAP_WIDH 1280
の値が違うので注意してください。

SCREEN_WIDTHは、現実の画面サイズである640の方が良いと私は思います。
また、MAP_WIDH はピクセルサイズとマップチップサイズを分けたほうが良いと思います。

コード:

#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)    // マップの縦幅
とすることをお勧めします。

これに合わせて

コード:

int camerax = 0;//カメラの左上座標
int charx;//自キャラ位置
int view_charx;//自キャラの表示位置。この座標にdrawする。
 
//カメラ位置を計算
camerax = charx - 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;
として下さい。

それと、MAPの描画は、このままだとダメですね。
int view_chipx = map_chipx - camerax;
と書きましたが、無駄が多いけど単純にマップチップのdrawでX座表示にcameraxを足したほうが簡単ですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

fey(別PC)

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#9

投稿記事 by fey(別PC) » 14年前

描画のところにいれてみたのですがエラーは出ないのですがうまくいきません;
入れ方が間違っているのでしょうか?

//自キャラの座標の代入
charx = PlX;
//カメラ位置を計算
camerax = charx - 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[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 ) ;
}
}
}
}

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

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#10

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

コードはcodeタグで囲ってくださいと、ソースコード全体をお願いします。

で、コードを見る前に聞きますが、どううまく行かないのでしょうか?
的確に問題把握が出来ているかをまずお聞きしたいです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

fey(別PC)

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#11

投稿記事 by fey(別PC) » 14年前

ステージを動かしてスクロールしているようには見えるのですが、操作が逆になっているのと
一定の位置まで動くとキャラの操作になるところまではいいのですが、操作も元に戻り、
マップの当たり判定が動いていないみたいなんです。


code
#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, 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,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,0,0,0,0, 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, 0,0,0,0,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, 0,0,0,0,0, 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, 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,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 = 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 )
{
// 画面のクリア
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 = charx - 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[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 ) ;
}
}
}
}

// キャラクタの描画
DrawBox( ( int )(view_charx), ( int )( PlY - CHAR_SIZE * 0.5F ),
( int )( view_charx + CHAR_SIZE ) + 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 ] ;
}
/code

fey(別PC)

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#12

投稿記事 by fey(別PC) » 14年前

スイマセン

コード:

 でのくくり方を間違えてしまいました。
もう一度コードだけ貼らせていただきます。

[code=Cpp] 
#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, 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,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,0,0,0,0, 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, 0,0,0,0,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, 0,0,0,0,0, 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, 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,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 = 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 )
    {
        // 画面のクリア
        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 = charx - 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 ) ;
                    }
                }
            }
        }
 
        // キャラクタの描画
        DrawBox( ( int )(view_charx),     ( int )( PlY - CHAR_SIZE * 0.5F ),
                 ( int )( view_charx + CHAR_SIZE ) + 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 ] ;
}

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#13

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

返事が遅くなってすいません。
マップのcameraxは足すではなく引くですね。申し訳ありません。

当たり判定が変なのは、元とキャラクタの描画のコードが微妙に違うからだと思います。
元と見比べてみてください。

ゲームを作れるようになる事が目標だと思いますので、私の言うとおり改造するのではなく理解して改造するようにして欲しいです。
私も考えて欲しくて、わざと曖昧に答えてますので。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

fey(別PC)

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#14

投稿記事 by fey(別PC) » 14年前

できました!この度は、本当にありがとうございました!


考えたいのは山々なんですが、
今回ばっかりは他にもしなければいけないことが多くて
時間があまりないんです;すいません;

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

Re: DXライブラリの横スクロールについてお聞きしたいのですが...

#15

投稿記事 by ISLe » 14年前

いまさらですが、画面座標とマップ座標を関数やマクロにしてしまうと見た目がスッキリすると思います。

#最近同じことを書いた気がする。

閉鎖

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