#include <GConsoleLib.h>
#include <stdio.h>

//マップデータ
#define MAXWIDTH 10
#define MAXHEIGHT 7
int g_mapdata[MAXHEIGHT][MAXWIDTH] = {
	// 0  1  2  3  4  5  6  7  8  9
	{  1, 0, 1, 1, 1, 1, 1, 1, 1, 1},	//0
	{  1, 0, 0, 1, 2, 0, 0, 1, 3, 1},	//1
	{  1, 1, 0, 1, 1, 1, 0, 1, 0, 1},	//2
	{  1, 0, 0, 0, 0, 0, 0, 1, 0, 1},	//3
	{  1, 0, 1, 1, 1, 1, 1, 1, 0, 1},	//4
	{  1, 0, 0, 0, 0, 0, 0, 0, 0, 1},	//5
	{  1, 1, 1, 1, 1, 1, 1, 1, 1, 1}	//6
};

//マップの部品の画像
char *g_images[] = {
	"C:\\GConsole追加ファイル\\sampleimg\\chap5-1-field.png",
	"C:\\GConsole追加ファイル\\sampleimg\\chap5-1-wall.png",
	"C:\\GConsole追加ファイル\\sampleimg\\chap5-1-goal.png",
	"C:\\GConsole追加ファイル\\sampleimg\\chap5-1-key.png",
	"C:\\GConsole追加ファイル\\sampleimg\\chap5-1-man.png"
};

//主人公の位置
int g_x = 1, g_y = 0;
int g_keyflag = 0;	//鍵を拾ったフラグ

//画面座標
int g_scx=0, g_scy=0;
#define SCROLLWIDTH 5
#define SCROLLHEIGHT 5
#define CORNERX 165
#define CORNERY 62

//関数プロトタイプ宣言
void DrawMap();
void RedrawMap(int, int, int, int);
int ScrollCheck(int, int);

int main(){
	gcls();
	gfront();

	DrawMap();	//マップ全体を表示

	while(1){
		glocate(0,19); gcolor(128,0,0);
		gprintf("コマンド（左A、上W、下S、右D）？　　");
		glocate(32,19);
		char ch = ggetchar();
		int newx=g_x, newy=g_y;
		switch(ch){
			case 'W':
			case 'w':
				newy--;
				break;
			case 'S':
			case 's':
				newy++;
				break;
			case 'A':
			case 'a':
				newx--;
				break;
			case 'D':
			case 'd':
				newx++;
				break;
		}
		//移動チェック
		if(newx >=0 && newx < MAXWIDTH && newy >=0 && newy < MAXHEIGHT){
			//壁かどうかチェック
			if(g_mapdata[newy][newx]!=1){
				//ゴールと鍵の処理
				switch(g_mapdata[newy][newx]){
					case 3:	//鍵
						g_keyflag = 1;				//鍵フラグオン
						g_mapdata[newy][newx] = 0;	//鍵を消す
						break;
					case 2: //ゴール
						if(g_keyflag) goto GAMECLEAR;
						break;
				}
				int oldx = g_x;
				int oldy = g_y;
				g_x = newx;
				g_y = newy;
				//ScrollCheck関数はスクロールの必要があれば1、
				//不要なら0を返す
				if(ScrollCheck(newx, newy)){
					DrawMap();	//全画面書き換え
				} else {
					RedrawMap(oldx, oldy, newx, newy);	//一部書き換え
				}
			}
		}
	}
	//ゲーム終了
GAMECLEAR:
	char *ending[] = {
		"君はついにゴールにたどり着いた",
		"しかし本当に冒険は終わったのだろうか……？",
		"",
		"　　　　　　　　　END?"
	};
	gcls();
	gcolor(0,0,0);
	gbox(0,0,640,480);
	gcolor(255,255,255);
	for(int i=0; i<4; i++){
		glocate(12,16 + i);
		gprintf(ending[i]);
	}
	//スクロール
	for(int i=0; i<90; i++){
		gprintf("　　　");
	}
}
//マップ再描画（一部のみ）
void RedrawMap(int oldx, int oldy, int newx, int newy){
	int mapd = g_mapdata[oldy][oldx];
	gimage(g_images[mapd], 
		(oldx-g_scx)*62 + CORNERX, (oldy-g_scy)*62 + CORNERY);
	gimage(g_images[4],
		(newx-g_scx)*62 + CORNERX, (newy-g_scy)*62 + CORNERY);
}

//マップ表示
void DrawMap(){
	for(int y=0; y<SCROLLHEIGHT; y++){
		for(int x=0; x<SCROLLWIDTH; x++){
			if(x+g_scx == g_x && y+g_scy == g_y){
				//主人公表示
				gimage(g_images[4], 
					(g_x-g_scx)*62 + CORNERX, (g_y-g_scy)*62 + CORNERY);
			} else {
				int mapd = g_mapdata[y+g_scy][x+g_scx];
				gimage(g_images[mapd], 
					x*62 + CORNERX, y*62 + CORNERY);
			}
		}
	}
}

//スクロールが必要かチェックする関数
//引数には移動先の座標を指定
int ScrollCheck(int newx, int newy){
	//現在の表示範囲から飛び出しているかをチェック
	//注座標がg_mapdataの範囲内にあることはチェック済み
	if( newx < g_scx || newy < g_scy || 
		newx > g_scx + SCROLLWIDTH - 1 ||
		newy > g_scy + SCROLLHEIGHT -1)
	{
		g_scx = newx / SCROLLWIDTH * SCROLLWIDTH;
		if(g_scx + SCROLLWIDTH > MAXWIDTH) {
			g_scx = MAXWIDTH - SCROLLWIDTH;
		}
		g_scy = newy / SCROLLWIDTH * SCROLLWIDTH;
		if(g_scy + SCROLLHEIGHT > MAXHEIGHT) {
			g_scy = MAXHEIGHT - SCROLLHEIGHT;
		}
		return 1;	//真
	}
	return 0;	//偽
}