部分的なソースコードだけでしたね。ごめんなさい。ソースコード全体を上げたいと思います。ちなみに左右の当たり判定がおかしい原因は、左下と左上と当たり判定が同時に出ていることにあるようです。この不具合をどうやって解消するのか教えてください。(原因が特定できるよう、少し変えてあります。)
コード:
//衝突のテストプログラム
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//Create 2017/02/10
#include "DxLib.h"
#define SCREEN_WIDTH (320) //画面の横幅
#define SCREEN_HEIGHT (240) //画面の縦幅
#define CHIP_SIZE (16) //チップのサイズ
#define MAP_WIDTH (SCREEN_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (SCREEN_HEIGHT/CHIP_SIZE)
HANDLE Stdout;
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,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,1, 1,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,
};
float PlayerX, PlayerY;
float SaveX, SaveY;
float MoveX, MoveY;
float DropPower, Grav;
char JumpFlag, Dir;
int Input, EdgeInput;
int FreamStartTime;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, float Size);
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop, float *G, char *Jump, float Size);
int MapChipParam(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, float 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(X, afY - 1.0F) == 1 && *MoveY > 0.0F) {
printf("\n下に当たりました。");
//移動量を補正する
*MoveY = bty - Y - 1.0F;
//上の壁に当たったと判定する
return 3;
}
if (MapChipParam(X, afY + 1.0F) == 1 && *MoveY < 0.0F) {
printf("\n上に当たりました。");
//移動量を補正する
*MoveY = bby - Y + 1.0F;
//下の壁に当たったと判定する
return 4;
}
//右の当たり判定
if (MapChipParam(afX - 1.0F ,Y) == 1 && *MoveX > 0.0F) {
printf("\n右に当たりました。");
//移動量を補正する
*MoveX = blx - X + 1.0F;
//右の壁に当たったと判定する
return 1;
}
//左の当たり判定
if (MapChipParam(afX + 1.0F, Y) == 1 && *MoveX < 0.0F) {
printf("\n左に当たりました。");
//移動量を補正する
*MoveX = brx - X + 1.0F;
//左の壁に当たったと判定する
return 2;
}
return 0;
}
//当たり判定チェック
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop,float *G,char *Jump,float Size){
float Dummy = 0.0F;
float hsize;
hsize = Size * 0.5F;
//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
{
//左下
if (MapHitCheck(*X - hsize, *Y + hsize, &Dummy, &MoveY,Size) == 3) *Drop = 0.0F,printf("\n上下::左下");
//右下
if (MapHitCheck(*X + hsize, *Y + hsize, &Dummy, &MoveY,Size) == 3) *Drop = 0.0F,printf("\n上下::右下");
//左上
if (MapHitCheck(*X - hsize, *Y - hsize, &Dummy, &MoveY,Size) == 4) *Drop = -1.0F,printf("\n上下::左上");
//右上
if (MapHitCheck(*X + hsize, *Y - hsize, &Dummy, &MoveY,Size) == 4) *Drop = -1.0F,printf("\n上下::右上");
//問題ないのなら移動させる
*Y += MoveY;
}
//左右の当たり判定チェック
{
//左下
if(MapHitCheck(*X - hsize, *Y + hsize, &MoveX, &Dummy, Size))printf("\n左右::左下");
//右上
if(MapHitCheck(*X + hsize, *Y + hsize, &MoveX, &Dummy, Size))printf("\n左右::右下");
//左上
if(MapHitCheck(*X - hsize, *Y - hsize, &MoveX, &Dummy, Size))printf("\n左右::左上");
//右上
if(MapHitCheck(*X + hsize, *Y - hsize, &MoveX, &Dummy, Size))printf("\n左右::右上");
//問題ないのなら移動させる
*X += MoveX;
}
//着地判定
{
if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
*Jump = TRUE;
}
else {
*Drop = 0.0F;
*G = 0.0F;
*Jump = FALSE;
}
}
return 0;
}
int init(void) {
ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…");
if (DxLib_Init() == -1) { return -1; }
PlayerX = 160.0F, PlayerY = 214.0F, MoveX = 0.0F, MoveY = 0.0F;
JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
return 0;
}
int main(void) {
FreamStartTime = GetNowCount();
while (GetNowCount() - FreamStartTime < 1000 / 60) { Sleep(1); }
system("cls");
printf("メインループ開始\n");
printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
printf("MoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
{
int i;
i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
EdgeInput = i & ~Input;
Input = i;
}
//移動処理
{
MoveX = 0.0F;
MoveY = 0.0F;
if ((Input&PAD_INPUT_RIGHT) != 0) {
Dir = TRUE;
MoveX += 5.0F;
}
if ((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;
}
//落下処理
DropPower += Grav;
MoveY = DropPower;
//移動量に基づいて移動する。
CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
/*//移動処理
int i = MoveChar(&PlayerX, &PlayerY, &MoveX, &MoveY, Grav, &DropPower, &JumpFlag, CHIP_SIZE);
//どういうわけか、常に上に衝突している。僕の考えでは、iが0なら、移動できるとしたいのだが…
//ようやく、原因が見えてきたぞ。
printf("\n現在衝突している場所(3:上、4:下、1:左、2:右)=%d", i);
if (i != 0) {
PlayerX = SaveX;
PlayerY = SaveY;
}*/
}
{
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, i*CHIP_SIZE, j*CHIP_SIZE + CHIP_SIZE, i*CHIP_SIZE + CHIP_SIZE, GetColor(255, 255, 255), TRUE);
}
}
}
}
DrawBox((int)(PlayerX - CHIP_SIZE*0.5F), (int)(PlayerY - CHIP_SIZE*0.5F), (int)(PlayerX + CHIP_SIZE*0.5F) + 1, (int)(PlayerY + 0.5F*CHIP_SIZE), 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;
}