#include"DxLib.h"
#include<stdio.h>

#pragma warning(disable : 4996)//fopen,fscanfでエラーが出るのを防ぐ
//このエラーの原因は「マイクロソフトの余計なおせっかい」です
#define WINDOW_WIDTH 640	//ウィンドウの大きさ(横)
#define WINDOW_HEIGHT 480	//ウィンドウの大きさ(縦)
#define CENTER 288			//主人公の中央座標
#define HERO_SIZE 32		//主人公の大きさ
#define HERO_VX 8			//主人公の移動の速度
#define WIDTH_SIZE 35		//スクロールの幅(横)
#define HEIGHT_SIZE 15		//スクロールの幅(縦)
#define BLOCK 32			//タイルの大きさ[px]
#define PI 3.145

//画像関連の構造体
struct SImg {
	int player;
	int block;
	int goal;
	int enemy;
	int gameover;
	int title;
	int clear;
	int haikei;
	int null;
};

//主人公関連の構造体
struct SPlayer {
	int x, y;		//主人公のX,Y座標
	int vx, vy;		//主人公のX,Y軸方向の速度
	int dire;		//主人公の向いている方向	0:右/1:左/2:上/3:下
	int movingright;
};



//敵関連の構造体
struct SEnemy {
	int x, y;			//敵のX,Y座標
	int vx, vy;			//敵のX,Y軸方向の速度
	int size_x, size_y;	//敵の大きさ
	int count;			//敵の動く際のカウント
	int dire;			//敵の向いている方向	0:右/1:左
};

//ゲームループ管理のフラグ
enum e_flag {
	f_title,
	f_gameplay,
	f_clear,
	f_gameover,
};

//構造体の宣言
struct SImg img;
struct SPlayer player;
struct SEnemy enemy;
enum e_flag flag;
int map[WIDTH_SIZE][HEIGHT_SIZE];
char keyState[256];
int white = GetColor(255, 255, 255);

//マップチップの読み込み
void Map(void) {
	FILE* fp;	//ファイルポインタの宣言

				//fopenでファイルを開く
	if ((fp = fopen("map/map.txt", "r")) == NULL) {
		OutputDebugString("MapData Read Error\n");	//もしマップデータが開くことが出来なかったらデバッグ画面に"Map Data Read Error"と表示
		exit(EXIT_FAILURE);							//エラー終了する
	}
	//開いたファイルをマップ配列に読み込む
	for (int j = 0; j < HEIGHT_SIZE; j++) {
		for (int i = 0; i < WIDTH_SIZE; i++) {
			fscanf(fp, "%d,", &map[i][j]);//カンマに気を付けてください
		}
	}
	fclose(fp);
}

//画像読み込み
void image(void) {
	img.player = LoadGraph("img/player1.png");
	img.block = LoadGraph("img/block.png");
	img.goal = LoadGraph("img/goal.png");
	img.enemy = LoadGraph("img/enemy.png");
	img.gameover = LoadGraph("img/gameover.png");/*6-0*/
	img.title = LoadGraph("img/title.png");
	img.clear = LoadGraph("img/clear.png");
	img.haikei = LoadGraph("img/haikei.png");
	img.null = LoadGraph("img/null.png");

}

//変数の初期化
void init(void) {

	player.x = 32;	//主人公の初期ｘ座標
	player.y = (HEIGHT_SIZE - 1) * BLOCK - HERO_SIZE;	//主人公の初期ｙ座標
	player.vx = 0;
	player.vy = 0;
	player.dire = 0;
	player.movingright = 0;

	enemy.size_x = 32;
	enemy.size_y = 32;
	enemy.x = 300;
	enemy.y = 480 - BLOCK - enemy.size_y;
	enemy.vx = 2;
	enemy.vy = 0;
	enemy.count = 0;
	enemy.dire = 0;
}

void title(void) {
	PlaySound("bgm.mp3", DX_PLAYTYPE_BACK);

	if (keyState[KEY_INPUT_RETURN]) {	//RETURNが押されていたら
							//フラグを変える
		flag = f_gameplay;

		//マップチップ読み込み
		Map();
		//変数の初期化
		init();
		
	}
}

//ゲームオーバー画面の表示＋マップのリロード＋変数の初期化
void clear(void) {
	//StopSound("bgm.mp3",DX_PLAYTYPE_BACK);
	if (keyState[KEY_INPUT_BACK]) {	//BACKが押されていたら
									//フラグを変える
		flag = f_title;
	}
}

//ゲームオーバー画面の表示＋マップのリロード＋変数の初期化
void gameover(void) {

	if (keyState[KEY_INPUT_BACK] || GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_3) {	//BACKが押されていたら
									//フラグを変える
		flag = f_title;
		//マップチップ読み込み
		Map();
		//変数の初期化
		init();
	}
}
//判定
void judge(int blx, int bly) {

	//プレイヤーと壁が重なっている時
	if (blx < (player.x + HERO_SIZE) && player.x < (blx + BLOCK) && bly < (player.y + HERO_SIZE) && player.y < (bly + BLOCK)) {
		//右に進んでいるなら壁の左にずらす
		if (player.dire == 0) {
			player.x = blx - HERO_SIZE;
		}
		//左に動いているなら壁の右にずらす
		else if(player.dire==1) {
			player.x = blx + BLOCK;
		}
		//上に進んでいるなら壁の下にずらす
		if (player.dire == 2) {
			player.y = blx - HERO_SIZE;
		}
		//下に動いているなら壁の上にずらす
		else {
			player.y = blx + BLOCK;
		}
		if (map[blx / BLOCK][bly / BLOCK] == 3) {
			flag = f_clear;
		}
	}
	//画面外に出ないようにする
	if (player.x < 0)
		player.x = 0;
	else if (player.x > WIDTH_SIZE * BLOCK - HERO_SIZE)
		player.x = WIDTH_SIZE * BLOCK - HERO_SIZE;
}
/*
void judge(void) {
	if (player.x<goal.x + 32 && player.x>goal.x && player.y<goal.y + 32 && player.y>goal.y) {
		f_clear;
	}
}*/
//プレイヤーの移動
void move(void) {


	//横移動リセット
	player.vx = 0;
	player.vy = 0;
	int movingright = 0;

	if (keyState[KEY_INPUT_LEFT]) {		//主人公の左向き操作(もし左ボタンが押されていたら)
		player.vx -= HERO_VX;
		//主人公をx方向に移動させる
		player.dire = 1;//主人公は左向き



	}

	if (keyState[KEY_INPUT_RIGHT]) {	//主人公の右向き操作(もし右ボタンが押されていたら)
		player.vx += HERO_VX;
		player.dire = 0;


	//主人公は右向き
	}
	if (keyState[KEY_INPUT_UP]) {
		player.vy -= HERO_VX;
		player.dire = 2;
		 
	}
	if (keyState[KEY_INPUT_DOWN]) {
		player.vy += HERO_VX;
		player.dire = 3;


	}

	player.x += player.vx;
	player.y += player.vy;

	for (int j = 0; j < HEIGHT_SIZE; j++) {
		for (int i = 0; i < WIDTH_SIZE; i++) {
			if (map[i][j] != 0) {
				judge(i * BLOCK, j * BLOCK);

			}
		}
	}

}
void draw(void) {

	//画面クリア
	ClearDrawScreen();

	switch (flag) {
	case f_title:
		DrawGraph(0, 0, img.title, TRUE);			//ゲームオーバー画面を描画
		break;

	case f_gameplay:
		//背景の描画
		for (int j = 0; j < BLOCK; j++) {
			for (int i = 0; i < BLOCK; i++) {
				DrawGraph(j * BLOCK, i*BLOCK, img.haikei, TRUE);
			}
		}

		//マップチップからの描画
		for (int j = 0; j < HEIGHT_SIZE; j++) {
			for (int i = (player.x / BLOCK) - 9; i < (player.x / BLOCK) + 12; i++) {
				if (i >= 0 && i < WIDTH_SIZE) {		//画面内に表示される範囲でマップ判断し描画する
					switch (map[i][j]) {
					case 0:		break;
					case 1:		DrawGraph(i * BLOCK - player.x + CENTER, j * BLOCK, img.block, TRUE); break;	//壁
					case 2:		DrawGraph(i * BLOCK - player.x + CENTER, j * BLOCK, img.block, TRUE); break;	//イベント床
					case 3:		DrawGraph(i * BLOCK - player.x + CENTER, j * BLOCK, img.goal, TRUE);break;	//ゴール旗(触れたらゴール)
					default:	DrawGraph(i * BLOCK - player.x + CENTER, j * BLOCK, img.null, TRUE); break;	//null
					}
				}
				else {	//マップの範囲外は壁を表示する
					DrawGraph(i * BLOCK - player.x + CENTER, j * BLOCK, img.block, TRUE);
				}
				GetHitKeyStateAll(keyState);
				if (keyState[KEY_INPUT_R])
					DrawFormatString(i * BLOCK - player.x + CENTER, j * BLOCK, white, "%d", map[i][j]);//デバッグ用数値表示
			}
		}


		if (player.dire == 0) {	//主人公の描画
			DrawGraph(CENTER, player.y, img.player, TRUE);		//右向き
			if (keyState[KEY_INPUT_RIGHT])
				player.movingright++;
		}
		else if(player.dire==1) {
			DrawRotaGraph(CENTER, player.y,1.0,PI/4, img.player, TRUE);	//左向き

			if (keyState[KEY_INPUT_LEFT])
				player.movingright++;
		}
		else if (player.dire == 2) {
			DrawRotaGraph(CENTER, player.y,1.0,PI/2, img.player, TRUE);	//上向き

			if (keyState[KEY_INPUT_UP])
			{ 
				
		}
		else{
			DrawRotaGraph(CENTER, player.y, 1.0, PI/2, img.player, TRUE);	//下向き

			if (keyState[KEY_INPUT_DOWN])
			{ 
				
		}


		//デバッグ用の変数描画
		DrawFormatString(450, 20, white, "X :%4d", player.x);
		DrawFormatString(550, 20, white, "Y :%4d", player.y);
		DrawFormatString(450, 40, white, "VX:%4d", player.vx);
		DrawFormatString(550, 40, white, "VY:%4d", player.vy);
		if (player.dire)
			DrawString(450, 60, "左向き", white);
		else
			DrawString(450, 60, "右向き", white);
		/*else
		DrawString(550, 60, "着地", white);
		*/
		/*if (player.attack)
			DrawString(450, 80, "攻撃", white);
		else
			DrawString(450, 80, "通常", white);*/
		break;

	case f_clear:
		DrawGraph(0, 0, img.clear, TRUE);			//クリア画面を描画
		break;

	case f_gameover:
		DrawGraph(0, 0, img.gameover, TRUE);			//ゲームオーバー画面を描画
		break;
	}

	ScreenFlip();
}

void update(void){

	//現在のフラグによって異なる処理を行う
	switch (flag) {
	case f_title:
		//タイトル画面の動作
		title();
		break;

	case f_clear:
		//クリア画面の動作
		clear();
		break;

	case f_gameover:
		//ゲームオーバー画面の動作
		gameover();
		break;
	}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ipCmdLine, int nShowCmd) {
	//ウィンドウのタイトルを変更
	SetMainWindowText("ローグライク");

	//ウィンドウモードに変更
	ChangeWindowMode(TRUE);

	//解像度とカラービット数を設定
	SetGraphMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32);

	//ウインドウの端を掴んでサイズを変更できるかどうかを設定
	SetWindowSizeChangeEnableFlag(TRUE);

	//初期化に失敗したらやめる
	if (DxLib_Init() == -1) {
		return -1;
	}

	//画像のロード
	image();

	//裏画面描画を設定
	SetDrawScreen(DX_SCREEN_BACK);

	//flagの初期化をここで行う
	flag = f_title;

	/************************** ゲームループ *****************************/

	while (!ProcessMessage() && !CheckHitKey(KEY_INPUT_ESCAPE)) {

		//キーボードのすべてのキーの状態を取得
		//その状態は変数keyStateに記録される
		GetHitKeyStateAll(keyState);

		//数値的な処理を行う
		update();

		//描画する
		draw();

		move();

		

		
	}

	/************************ ゲームループおわり ************************/
	//DXライブラリ使用の終了処理
	DxLib_End();

	//ソフトの終了
	return 0;
}
