コードは以下のとおりです。
//衝突のテストプログラム
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//Create 2017/02/10
#include "DxLib.h"
#define SCREEN_WIDTH (320) //画面の横幅
#define SCREEN_HEIGHT (240) //画面の縦幅
#define STAGE_WIDTH (336)
#define STAGE_HEIGHT (480)
#define CHIP_SIZE (16) //チップのサイズ
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_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,
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,0, 1,
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,0, 1,
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,0, 1,
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,0, 1,
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,0, 1,
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,0, 1,
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,0, 1,
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 CameraX = 0;
int CameraY = 0;
int CharX, CharY, View_CharX, View_CharY;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int 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, int 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(afX, afY) == 1) {
if (*MoveY > 0.0F) {
printf("\n下に当たりました。");
//移動量を補正する
*MoveY = bty - Y - 1.0F;
//上の壁に当たったと判定する
return 3;
}
if (*MoveY < 0.0F) {
printf("\n上に当たりました。");
//移動量を補正する
*MoveY = bby - Y + 1.0F;
//下の壁に当たったと判定する
return 4;
}
//右の当たり判定
if (*MoveX > 0.0F) {
printf("\n右に当たりました。");
//移動量を補正する
*MoveX = blx - X - 1.0F;
//右の壁に当たったと判定する
return 1;
}
//左の当たり判定
if (*MoveX < 0.0F) {
printf("\n左に当たりました。");
//移動量を補正する
*MoveX = brx - X + 1.0F;
//左の壁に当たったと判定する
return 2;
}
//ここに来たら適当な値を返す
return 4;
}
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;
//直前フレーム
float PrevX = *X + MoveX;
float PrevY = *Y + MoveY;
//ベクトルのバックアップ
float SaveMoveX = MoveX;
float SaveMoveY = MoveY;
hsize = Size * 0.5F;
//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
{
//左下
if (MapHitCheck(*X - hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::左下");
//右下
if (MapHitCheck(*X + hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::右下");
//左上
if (MapHitCheck(*X - hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::左上");
//右上
if (MapHitCheck(*X + hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::右上");
//問題ないのなら移動させる
PrevY = *Y + MoveY;
*Y = PrevY;
}
//左右の当たり判定チェック
{
//左下
if (MapHitCheck(*X - hsize + 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左下");
//右上
if (MapHitCheck(*X + hsize - 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右下");
//左上
if (MapHitCheck(*X - hsize + 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左上");
//右上
if (MapHitCheck(*X + hsize - 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右上");
//問題ないのなら移動させる
PrevX = *X + MoveX;
*X = PrevX;
}
//着地判定
{
if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
*Jump = TRUE;
*G = 0.5F;
}
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 = 120.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("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
printf("\nCharX=%d,CharY=%dCameraX=%d,CameraY=%d,ViewX=%d,ViewY=%d", CharX, CharY, CameraX, CameraY, View_CharX, View_CharY);
{
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);
}
//カメラのチェック
CharX = PlayerX;
CharY = PlayerY;
//カメラの位置を計算する
CameraX = CharX - SCREEN_WIDTH / 2;
CameraY = CharY - SCREEN_HEIGHT / 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);
//画面上の位置
View_CharX = CharX - CameraX;
View_CharY = CharY - CameraY;
//マップの描画
{
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 - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
}
}
}
}
//キャラの描画
DrawBox((int)(View_CharX), (int)(View_CharY), (int)(View_CharX-CHIP_SIZE) + 1, (int)(View_CharY-CHIP_SIZE) + 1, 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;
}