ちなみに、前回での質問における2ドット浮くという現象は解決済みです。また、地上の衝突判定自体は完成しています。
#include "dxlib.h"
#define SCREEN_WIDTH (320)
#define SCREEN_HEIGHT (240)
#define STAGE_WIDTH (320)
#define STAGE_HEIGHT (240)
#define CHIP_SIZE (16)
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_HEIGHT/CHIP_SIZE)
float PlayerX = 24.0F, PlayerY = 215.0F, DropPower = 0.0F, Gravity;
char dir, JumpFlag, DashFlag, AirFlag, DashTrigger, HitFlagX, HitFlagY;
int GetChipParam(float X, float Y);
int MoveChecker(float *X, float *Y, float *DropPower, float MoveX, float MoveY, float Size, char *JumpFlag, char *AirFlag, char *HitFlagX, char *HitFlagY);
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY);
int PlayerHandle, MapChipHandle[2], JumpCount, Time, Input, EdgeInput, charX, charY, cameraX = 0, cameraY = 0, viewx, viewy;
int Key[256];
int gpUpdateKey() {
char tmpKey[256];
GetHitKeyStateAll(tmpKey);
for (int i = 0; i < 256; i++) {
if (tmpKey[i] != 0) {
Key[i]++;
}
else {
Key[i] = 0;
}
}
return 0;
}
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,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,
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,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,
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,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,
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,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,
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,
};
//マップチップ確認
int GetChipParam(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) {
float afX, afY;
afX = X + *MoveX;
afY = Y + *MoveY;
if (GetChipParam(X, Y) == 1) {
float blx, bty, brx, bby;
//壁衝突確認
blx = (float)((int)afX / CHIP_SIZE)*CHIP_SIZE;//左辺の当たり判定
brx = (float)((int)afX / CHIP_SIZE + 1)*CHIP_SIZE;//右辺の当たり判定
bty = (float)((int)afY / CHIP_SIZE)*CHIP_SIZE;//上辺の当たり判定
bby = (float)((int)afY / CHIP_SIZE + 1)*CHIP_SIZE;//下辺の当たり判定
//上辺に当たったら3を返す
if (*MoveY > 0.0F) {
*MoveX = 0.0F;
*MoveY = bty - Y - 1.0F;
return 3;
}
//下辺に当たっていたら4を返す
if (*MoveY < 0.0F) {
*MoveX = 0.0F;
*MoveY = bby - Y + 1.0F;
return 4;
}
if (*MoveX > 0.0F) {
*MoveY = 0.0F;
*MoveX = blx - X - 1.0F;
return 1;
}
if (*MoveX < 0.0F) {
*MoveY = 0.0F;
*MoveX = brx - X + 1.0F;
return 2;
}
return 4;
}
return 0;
}
//当たり判定チェック
int MoveChecker(float *X, float *Y, float *DropPower, float MoveX, float MoveY, float Size, char *JumpFlag, char *AirFlag, char *HitFlagX, char *HitFlagY) {
float Dummy = 0.0F;
float hsize;
hsize = Size*0.5F;
//上下移動成分をチェック
{
//左下
if (MapHitCheck(*X - hsize, *Y + hsize, &Dummy, &MoveY) == 3) *DropPower = 0.0F; *HitFlagY = TRUE;
//右下
if (MapHitCheck(*X + hsize, *Y + hsize, &Dummy, &MoveY) == 3) *DropPower = 0.0F; *HitFlagY = TRUE;
//左上
if (MapHitCheck(*X - hsize, *Y - hsize, &Dummy, &MoveY) == 4) *DropPower = -1.0F;
//右上
if (MapHitCheck(*X + hsize, *Y - hsize, &Dummy, &MoveY) == 4) *DropPower = -1.0F;
//問題がないのなら移動成分を加算する
*Y += MoveY;
}
//左右移動成分、以下同順
{
if (MapHitCheck(*X - hsize, *Y + hsize, &MoveX, &Dummy) == 1) *HitFlagX = TRUE;
if (MapHitCheck(*X + hsize, *Y + hsize, &MoveX, &Dummy) == 2) *HitFlagX = TRUE;
if (MapHitCheck(*X - hsize, *Y - hsize, &MoveX, &Dummy) == 1) *HitFlagX = TRUE;
if (MapHitCheck(*X + hsize, *Y - hsize, &MoveX, &Dummy) == 2) *HitFlagX = TRUE;
*X += MoveX;
}
//ヒットフラグが付いたら、壁にハマるのを防止してからフラグをオフにする。
if (*HitFlagX == TRUE) {
//左の場合
if (MoveX<0 && MapHitCheck(*X - hsize, *Y + hsize, &MoveX, &Dummy) == 1 && MapHitCheck(*X - hsize, *Y - hsize, &MoveX, &Dummy) == 1) {
*X += 1.0F;
HitFlagX = FALSE;
}
//右の場合
else if (MoveX>0 && MapHitCheck(*X + hsize, *Y - hsize, &MoveX, &Dummy) == 2 && MapHitCheck(*X + hsize, *Y + hsize, &MoveX, &Dummy) == 2) {
*X -= 1.0F;
HitFlagX = FALSE;
}
}
{
//空中にいるなら、空中にいるとみなす
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) {
*AirFlag = TRUE;
}
//もし足場に着地したら埋まりこみを防止してからジャンプ回数をリセットする
else if (*HitFlagY = TRUE) {
*Y -= 1.0F;
*HitFlagY = FALSE;
*AirFlag = FALSE;
JumpCount = 0;
Gravity = 0;
*JumpFlag = FALSE;
}
return 0;
}
}
int DrawChar() {
if (dir == TRUE) {
DrawRotaGraph((int)PlayerX, (int)PlayerY + 2, 1.0, 0.0, PlayerHandle, TRUE, FALSE);
}
else {
DrawRotaGraph((int)PlayerX, (int)PlayerY + 2, 1.0, 0, PlayerHandle, TRUE, TRUE);
}
return 0;
}
//マップの描画
int DrawMap() {
{
int i, j;
for (i = 0; i < MAP_HEIGHT; i++) {
for (j = 0; j < MAP_WIDTH; j++) {
if (MapData[i][j] == 1) {
DrawGraph(j * CHIP_SIZE, i*CHIP_SIZE, MapChipHandle[1], TRUE);
}
}
}
} return 0;
}
//カメラの確認
int CameraCheck() {
//プレイヤーの位置チェック
charX = (int)PlayerX, charY = (int)PlayerY;
//カメラの位置チェック
cameraX = charX - SCREEN_WIDTH / 2, cameraY = charY - SCREEN_WIDTH / 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);
return 0;
}
int init(void) {
ChangeWindowMode(TRUE), SetGraphMode(320, 240, 32);
if (DxLib_Init() == -1) { return -1; };
SetDrawScreen(DX_SCREEN_BACK), Input = 0, Time = GetNowCount();//カウント値を更新する
PlayerHandle = LoadGraph("テスト用.png"), LoadDivGraph("マップチップ.bmp", 2, 2, 1, 16, 16, MapChipHandle);
dir = TRUE, DashFlag = FALSE, HitFlagX = TRUE, HitFlagY = FALSE;
return 0;
}
int main(void) {
//マップの描画
DrawMap();
//カウント値を更新する
Time = GetNowCount();
//フレームを管理する
while (GetNowCount() - Time < 1000 / 60) { Sleep(1); }
//入力状態を更新する
{
int i;
i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
//チョン押しを確認する
EdgeInput = i & ~Input;
Input = i;
}
//ダッシュトリガー確認
if ((Input&PAD_INPUT_1) == 0) {
DashFlag = FALSE;
}
if (JumpCount >= 2) {
JumpFlag = TRUE;
}
//移動処理
{
float MoveX, MoveY;
MoveX = 0.0F;
MoveY = 0.0F;
//左に移動
if ((Input&PAD_INPUT_LEFT) != 0) {
dir = FALSE;
MoveX -= 5.0F;
}
//右に移動
if ((Input&PAD_INPUT_RIGHT) != 0) {
dir = TRUE;
MoveX += 5.0F;
}
//左ラン
if ((Input&PAD_INPUT_LEFT) != 0 && (Input&PAD_INPUT_1) != 0 && JumpFlag == FALSE) {
dir = FALSE;
DashFlag = TRUE;
MoveX -= 5.25F;
}
//右ラン
if ((Input&PAD_INPUT_RIGHT) != 0 && (Input&PAD_INPUT_1) != 0 && JumpFlag == FALSE) {
dir = TRUE;
DashFlag = TRUE;
MoveX += 5.25F;
}
//ダッシュボタン
if ((EdgeInput&PAD_INPUT_3) != 0) {
int DashTimer = GetNowCount();
}
//ジャンプ処理
if ((EdgeInput&PAD_INPUT_2) != 0 && JumpFlag == FALSE) {
//ジャンプできる状態にする
DropPower = 0;
//ジャンプ回数を増やす
JumpCount += 1;
//ジャンプする
DropPower -= 9.5F;
//ジャンプするときの重力を決める
Gravity = 0.5F;
}
if ((EdgeInput&PAD_INPUT_2) != 0 && DashFlag == TRUE && JumpFlag == FALSE) {
DashFlag = TRUE;
DropPower = 0;
JumpCount += 1;
DropPower -= 12.0F;
Gravity = 0.5F;
}
//カメラのチェック
CameraCheck();
//落下処理
DropPower += Gravity;
//落下速度を移動量に追加する
MoveY = DropPower;
//当たり判定に基づく移動を行う
MoveChecker(&PlayerX, &PlayerY, &DropPower, MoveX, MoveY, CHIP_SIZE, &JumpFlag, &AirFlag, &HitFlagX, &HitFlagY);
}
DrawChar();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
init();//初期化処理
//メインプログラム
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0) {
main();
}
//DXライブラリを終了する
DxLib_End();
return 0;
}