#include "DxLib.h" #define SCREEN_WIDTH (640) // 画面の横幅 #define SCREEN_HEIGHT (480) // 画面の縦幅 #define CHIP_SIZE (32) // 一つのチップのサイズ #define MAP_WIDTH (40) // マップの横幅 #define MAP_HEIGHT (20) // マップの縦幅 #define G (0.3F) // キャラに掛かる重力加速度 #define JUMP_POWER (9.0F) // キャラのジャンプ力 #define SPEED (5.0F) // キャラの移動スピード #define CHAR_SIZE (30) // プレイヤーのサイズ // マップデータ 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,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,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,0, 0,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,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,1, 0,0,0,0,1, 1,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,0,1, 1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, 0,1,0,0,0, 1,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,1,1,0, 0,0,1,0,0, 0,1,0,0,0, 1,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,1,0,0, 0,1,1,1,1, 1,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,1,1,0, 0,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,1, 1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, 0,1,0,0,0, 1,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,1,1,0, 0,0,1,0,0, 0,1,0,0,0, 1,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,1,0,0, 0,1,1,1,1, 1,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,1,1,0, 0,0,0,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,1,1,1,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,1,1,1,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,1,1,1, 1,1,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,1, 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,1, 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 PlayerGraphHandle ; // プレイヤーのグラフィックハンドル int WallGraphHandle ; // 壁のグラフィックハンドル // マップチップの値を取得する関数 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 ) { // プレイヤーの画像を読み込む PlayerGraphHandle = LoadGraph( "Player.bmp" ) ; // 壁の画像を読み込む WallGraphHandle = LoadGraph( "Wall.bmp" ) ; // 描画先を裏画面にセット 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 DrawBaseX ; int DrawBaseY ; // 描画基準座標の決定 { DrawBaseX = PlX - SCREEN_WIDTH / 2 ; DrawBaseY = PlY - SCREEN_HEIGHT / 2 ; // マップの左端より左側は画面に映らないようにする if( DrawBaseX < 0 ) { DrawBaseX = 0 ; } // マップの右端より右側は画面に映らないようにする if( DrawBaseX + SCREEN_WIDTH > MAP_WIDTH * CHIP_SIZE ) { DrawBaseX = MAP_WIDTH * CHIP_SIZE - SCREEN_WIDTH ; } // マップの上端より上側は画面に映らないようにする if( DrawBaseY < 0 ) { DrawBaseY = 0 ; } // マップの下端より下側は画面に映らないようにする if( DrawBaseY + SCREEN_HEIGHT > MAP_HEIGHT * CHIP_SIZE ) { DrawBaseY = MAP_HEIGHT * CHIP_SIZE - SCREEN_HEIGHT ; } } // マップの描画 { int i, j ; for( i = 0 ; i < MAP_HEIGHT ; i ++ ) { for( j = 0 ; j < MAP_WIDTH ; j ++ ) { // 1は当たり判定チップを表しているので1のところだけ描画 if( MapData[i][j] == 1 ) { DrawGraph( ( int )( j * CHIP_SIZE - DrawBaseX ), ( int )( i * CHIP_SIZE - DrawBaseY ), WallGraphHandle, TRUE ) ; } } } } // キャラクタの描画 DrawGraph( ( int )( PlX - CHAR_SIZE * 0.5F - DrawBaseX ), ( int )( PlY - CHAR_SIZE * 0.5F - DrawBaseY ), PlayerGraphHandle, 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 ] ; }