/*
JavaScript&HTML5 ゲーム開発用システム
開発　ワールドワイドソフトウェア有限会社

（使用条件）
・本ソースコードの著作権は開発元にあります。
・利用されたい方はメールにてお問い合わせ下さい。
 th@wwsft.com ワールドワイドソフトウェア 広瀬
*/

// ---------- グローバル変数 ----------
var SYS_VER = "Ver.20181205";
var DEBUG = false;

//端末の種類
var deviceType	= 0;
var PT_PC		= 0;
var PT_iOS		= 1;
var PT_Android	= 2;
var PT_Kindle	= 3;

//処理の進行を管理
//main_idxの値↓
//1: 画像と音声の読み込み
//2: セーブできない警告
//3: メイン処理
var main_idx = 0;
var main_tmr = 0;
var stop_flg = 0;//メイン処理の一時停止

var NUA = navigator.userAgent;//機種判定
var supportTouch = 'ontouchend' in document;//タッチイベントが使えるか？
if( DEBUG ) {//★★★開発中
 console.log(NUA);
 console.log(supportTouch);
}

//キャンバス
var winW, winH;
var bakW, bakH;
var SCALE = 1.0;//スケール値設定＋タップ位置計算用
var cvs = document.getElementById("canvas");
var bg = cvs.getContext("2d");

function initCanvas() {//キャンバス初期設定

	winW = window.innerWidth;
	winH = window.innerHeight;
	bakW = winW;
	bakH = winH;

	if( winH < winW*CHEIGHT/CWIDTH ) {
		winH = toInt(winH*CPAD/100);//画面をやや小さくする場合 CPADを100未満に設定
		winW = toInt(winH*CWIDTH/CHEIGHT);
	}
	else {
		winW = toInt(winW*CPAD/100);//画面をやや小さくする場合 CPADを100未満に設定
		winH = toInt(CHEIGHT*winW/CWIDTH);
	}
	cvs.width = winW;
	cvs.height = winH;
	SCALE = winW / CWIDTH;
	bg.scale(SCALE,SCALE);
	bg.textAlign = "center";   //┬文字列のセンタリング表示用に必要な値を指定
	bg.textBaseline = "middle";//┘
}

// ---------- 加速度センサー ----------
var acX = 0, acY = 0, acZ = 0;

//window.ondevicemotion = deviceMotion;//★★★旧
window.addEventListener( "devicemotion", deviceMotion );

function deviceMotion(event) {
	var aIG = event.accelerationIncludingGravity;
	acX = toInt( aIG.x );
	acY = toInt( aIG.y );
	acZ = toInt( aIG.z );
	if( deviceType == PT_Android ) {//Android と iOS で正負が逆になる
		acX = -acX;
		acY = -acY;
		acZ = -acZ;
	}
}

// ---------- キー入力 ----------
var inkey = 0;
var key = new Array(256);

window.onkeydown = function(event) { inkey = event.keyCode; }
window.onkeyup = function(event) { inkey = 0; }

function clrKey() {
	for( var i = 1; i < 256; i ++ ) key[i] = 0;
	inkey = 0;
}

function getKey() {
	for( var i = 1; i < 256; i ++ ) {
		if( inkey == i )
			key[i] ++;
		else
			key[i] = 0;
	}
}

// ---------- マウス入力 ----------
var tapX = 0;
var tapY = 0;
var tapC = 0;

function mouseDown(event) {
	event.preventDefault();//キャンバスの選択／スクロール等を抑制する
	var rect = event.target.getBoundingClientRect();
	tapX = event.clientX-rect.left;
	tapY = event.clientY-rect.top;
	tapC = 1;
	transformXY();
}

function mouseMove(event) {
	event.preventDefault();
	var rect = event.target.getBoundingClientRect();
	tapX = event.clientX-rect.left;
	tapY = event.clientY-rect.top;
	transformXY();
}

function mouseUp(event) { tapC = 0; }
function mouseOut(event) { tapX = -1; tapY = -1; tapC = 0; }

// ---------- タップ入力 ----------
function touchStart(event) {
	event.preventDefault();//キャンバスの選択／スクロール等を抑制する
	var rect = event.target.getBoundingClientRect();
	tapX = event.touches[0].clientX-rect.left;
	tapY = event.touches[0].clientY-rect.top;
	tapC = 1;
	transformXY();
	//【重要】サウンドのスマートフォン対応
	if( snd_init == 0 ) initSnd();//iOS Android共通 メモリー上にサウンドファイルを読み込む
	if( isBgm == -1 ) playWhenTap();//【Android仮対応】タップのタイミングで強制的にサウンドを流す
}

function touchMove(event) {
	event.preventDefault();
	var rect = event.target.getBoundingClientRect();
	tapX = event.touches[0].clientX-rect.left;
	tapY = event.touches[0].clientY-rect.top;
	transformXY();
}

function touchEnd(event) {
	event.preventDefault();
	tapX = -1; tapY = -1; tapC = 0;//【重要】ヴァーチャルボタンがハイライトにならないように　※マウス操作ではmouseOutがこれになる
	if( isBgm == -1 ) playWhenTap();//【Android仮対応】タップのタイミングで強制的にサウンドを流す
}

function touchCancel(event) { tapX = -1; tapY = -1; tapC = 0; }

function transformXY() {//実座標→仮想座標への変換
	tapX = toInt(tapX/SCALE);
	tapY = toInt(tapY/SCALE);
}

// ---------- 画像読み込み ----------
var IMAGE_ENTRY = IMG_LIST.length;
var img = [];//new Array(IMAGE_ENTRY);
var iOK = [];//new Array(IMAGE_ENTRY);

function loadImg(n) {
	iOK[n] = false;//読み込み開始
	img[n] = new Image();
	img[n].onload = function() { iOK[n] = true; }
	img[n].src = "img/" + IMG_LIST[n];
}

function compImg() {//全ての画像が読み込まれたか
	var i, c = 0;
	for( i = 0; i < IMAGE_ENTRY; i ++ ) if( iOK[i] == true ) c ++;
	if( c == IMAGE_ENTRY ) return true;
	return false;
}

// ---------- サウンド制御 ----------
var snd_init = 0;//サウンドファイルを読み込んだか（スマートフォン対策）
var sefile = [];
var bgmfile = [];
//var SND_TYPE = ".m4a";
//var SND_TYPE = ".mp3";
//var SND_TYPE = ".ogg";
var SND_TYPE = "";

var wait_se = 0;
var bgmNo = 0;
var isBgm = 0;

function initSnd() {//サウンドファイルをメモリー上に読み込む
	var i;
	var audio = new Audio();
//	if( audio.canPlayType("audio/ogg") == "maybe"    ) SND_TYPE = ".ogg";
//	if( audio.canPlayType("audio/ogg") == "probably" ) SND_TYPE = ".ogg";
	for( i = 0; i < SE_LIST.length; i ++ ) {
		sefile[i] = new Audio( "snd/" + SE_LIST[i] + SND_TYPE );
		sefile[i].load();
	}
	for( i = 0; i < BGM_LIST.length; i ++ ) {
		bgmfile[i] = new Audio( "snd/" + BGM_LIST[i] + SND_TYPE );
		bgmfile[i].load();
	}
	snd_init = 1;
}

var seNo = -1;
function playSE(n) {
	if( SOUND_ON == false ) return;
    if( isBgm == 2 ) return;
	if( wait_se == 0 ) {
		seNo = n;
		sefile[n].play();
		wait_se = 3;//ブラウザに負荷をかけないため連続して流さないようにする
	}
}

function playBgm( n ) {
	if( SOUND_ON == false ) return;
	bgmNo = n;
	bgmfile[n].loop = true;
	bgmfile[n].play();
	isBgm = 1;//BGM流れている
}

function pauseBgm() {
	bgmfile[bgmNo].pause();
	isBgm = 0;//BGM停止している
}

function stopBgm() {
	bgmfile[bgmNo].pause();
	bgmfile[bgmNo].currentTime = 0;
	isBgm = 0;//BGM停止している
}

function rateSnd( rate ) {//曲の速度
	bgmfile[bgmNo].playbackRate = rate;
}

//ブラウザを隠した時に音を一時停止する処理
document.addEventListener( "visibilitychange", vcProc );
function vcProc() {
	if( document.visibilityState == "hidden" ) {
		stop_flg = 1;
		if( isBgm == 1 ) {
			pauseBgm();
			isBgm = 2;//BGM再出力待ち
		}
		if( seNo >= 0 ) {//長いSEを考慮し、こちらも停止
			try {
				sefile[seNo].pause();
				sefile[seNo].currentTime = 0;
			} catch(e) {}
		}
	}
	else if( document.visibilityState == "visible" ) {
		stop_flg = 0;
		if( isBgm == 2 ) playBgm(bgmNo);
	}
}

//【Android仮対応】タップのタイミングで強制的にサウンドを流す
function playBgmA( n ) {
	if( SOUND_ON == false ) return;
	bgmNo = n;
	isBgm = -1;
}

function playWhenTap() {
	if( bgmfile[bgmNo] == null ) bgmfile[bgmNo] = new Audio( "snd/" + BGM_LIST[bgmNo] + SND_TYPE );
	bgmfile[bgmNo].loop = true;
	bgmfile[bgmNo].play();
	isBgm = 1;
}

// ---------- ローカルストレージ ----------
//【開発メモ】
//ローカルストレージへのアクセスができない状態（具体的にはSafariでプライベートブラウズになっている時） try catch が入っていないとフリーズする
//7  C:\Users\ユーザ名\AppData\Local\Google\Chrome\User Data\Default\Local Storage
//
function saveLS( kno, val ) {
	try {
		localStorage.setItem( LS_KEYNAME+kno, val );
	}
	catch( e ) {}
}

function loadLS( kno ) {
	var val;
	try {
		val = localStorage.getItem( LS_KEYNAME+kno );
	}
	catch( e ) {
		val = null;
//		alert(e);
	}
	return val;
}

function clrLS( kno ) {
	localStorage.removeItem( LS_KEYNAME+kno );
}

// ---------- 描画関連１　基本描画 ----------
function setAlp( per ) {
	bg.globalAlpha = per/100;//【メモ】HTML5は0.0～1.0の値で指定
}

function col( cr, cg, cb ) {
	cr = toInt(cr);//【開発メモ】少数を渡すとおかしくなるので整数にしておく
	cg = toInt(cg);
	cb = toInt(cb);
	return ( "rgb("+cr+","+cg+","+cb+")" );
}

function lineW( wid ) {//線の太さを指定
	bg.lineWidth = wid;
	bg.lineCap = "round";//線の先端を丸める指定
	bg.lineJoin = "round";//線の接続部分を丸める指定
}

function fRect( x, y, w, h, col ) {//矩形（塗り潰し）
	bg.fillStyle = col;
	bg.fillRect( x, y, w, h );
}

function sRect( x, y, w, h, col ) {//矩形（線）
	bg.strokeStyle = col;
	bg.strokeRect( x, y, w, h );
}

function fCir( x, y, r, col ) {//円（塗り潰し）
	bg.fillStyle = col;
	bg.beginPath();
	bg.arc( x, y, r, 0, Math.PI*2, false );
	bg.closePath();
	bg.fill();
}
function sCir( x, y, r, col ) {//円（線）
	bg.strokeStyle = col;
	bg.beginPath();
	bg.arc( x, y, r, 0, Math.PI*2, false );
	bg.closePath();
	bg.stroke();
}

function fTri( x1, y1, x2, y2, x3, y3, col ) {//三角（塗り潰し）
	bg.fillStyle = col;
	bg.beginPath();
	bg.moveTo( x1, y1 );
	bg.lineTo( x2, y2 );
	bg.lineTo( x3, y3 );
	bg.closePath();
	bg.fill();
}

function sTri( x1, y1, x2, y2, x3, y3, col ) {//三角（線）
	bg.strokeStyle = col;
	bg.beginPath();
	bg.moveTo( x1, y1 );
	bg.lineTo( x2, y2 );
	bg.lineTo( x3, y3 );
	bg.closePath();
	bg.stroke();
}

// ---------- 描画関連２　画像表示 ----------
function drawImg( n, x, y ) {
	if( iOK[n] == true ) bg.drawImage( img[n], x, y );
}

function drawImgS( n, x, y, w, h ) {//拡大縮小
	if( iOK[n] == true ) bg.drawImage( img[n], x, y, w, h );
}

function drawImgTS( n, sx, sy, sw, sh, cx, cy, cw, ch ) {//切り出し＋拡大縮小
	if( iOK[n] == true ) bg.drawImage( img[n], sx, sy, sw, sh, cx, cy, cw, ch );
}

function drawImgR( n, x, y, ang ) {//回転
	if( iOK[n] == true ) {
		var w = img[n].width;
		var h = img[n].height;
		bg.save();
		bg.translate( x+w/2, y+h/2 );
		bg.rotate(Math.PI*ang/180);
		bg.drawImage( img[n], -w/2, -h/2 );
		bg.restore();
	}
}

// ---------- 描画関連２　文字表示 ----------
function fText( str, x, y, siz, col ) {
	bg.font = siz + "px bold monospace";//等幅フォントを指定
	bg.fillStyle = col;
	bg.fillText( str, x, y );
}

function fTextN( str, x, y, h, siz, col ) {
	var i;
	var sn = str.split("\n");//改行を区切り文字とした一次元配列を生成
	bg.font = siz + "px bold monospace";//等幅フォントを指定
	bg.fillStyle = col;
	if( sn.length == 1 ) {
		h = 0;
	}
	else {
		y = y - toInt(h/2);
		h = toInt(h/(sn.length-1));
	}
	for( i = 0; i < sn.length; i ++ ) bg.fillText( sn[i], x, y+h*i );
}

function mTextWidth( str ) {//文字列のキャンバス上の幅を返す
 return bg.measureText(str).width;
}

// ---------- 日時の取得 ----------
var year, month, date, day, hour, min, sec;

function getDate() {
	var D = new Date();
	year	= D.getFullYear();	//西暦を取得
	month	= D.getMonth();		//月を取得　１月は0
	date	= D.getDate();		//日を取得
	day		= D.getDay();		//曜日を取得　日曜は0
	hour	= D.getHours();		//時間を取得
	min		= D.getMinutes();	//分を取得
	sec		= D.getSeconds();	//秒を取得
}

// ---------- 各種の関数 ----------
function eID( id ) {
	return document.getElementById( id );
}

function toInt( val ) {//整数を返す＝小数点以下を切り捨て
//	return Math.floor(val);//マイナスの場合 -0.1 → -1となるので注意
	return parseInt(val);//こちらはプラスもマイナスも小数部分を切り捨てる
}

function rnd( max ) {//乱数
	return toInt( max * Math.random() );
}

function SIN( a ) {//三角関数 最大値1=1000として返す
	return toInt( 1000*Math.sin(Math.PI*2*a/360) );
}

function COS( a ) {
	return toInt( 1000*Math.cos(Math.PI*2*a/360) );
}

function digit0( val, len ) {
	var s = "0000000000" + val;
	return s.substring( s.length-len, s.length );
}

// ---------- リアルタイム処理 ----------
function wwsSysMain() {

	main_tmr ++;
	
	switch( main_idx ) {

	case -1:
	cautionLS(bg);//ローカルストレージが使えない際のメッセージ
	if( tapC != 0 ) {
		main_idx = 0;
		main_tmr = 0;
	}
	break;

	case 0:
	if( main_tmr <= IMAGE_ENTRY ) {//画像読み込み
		loadImg(main_tmr-1);
	}
	else {
		if( deviceType == PT_PC ) initSnd();
		main_idx = 1;//【注記】イメージが完全に読み込まれるまで待つ場合
//		main_idx = 2;
	}
	break;

	case 1:
	fRect( 0, 0, CWIDTH, CHEIGHT, "black" );
	fText( "Please wait.", CWIDTH/2, CHEIGHT/2, (CWIDTH/24), "white" );
	if( compImg() == true ) main_idx = 2;
	break;

	case 2:
	if(	stop_flg == 0 ) {
		getKey();
		mainProc();
		drawProc();
	}
	else {
		main_tmr --;
	}
/*
	if( deviceType > 0 ) {//縦持ち、横持ち時のメッセージ
		var w = window.innerWidth;
		var h = window.innerHeight;
		if( CWIDTH < CHEIGHT ) {
			if( w > h ) cautionSCOR(bg);
		}
		else {
			if( w < h ) cautionSCOR(bg);
		}
	}
*/
	if( wait_se > 0 ) wait_se --;
	break;

	}

if( DEBUG ) {//★★★開発中
	var i, x = 240, y;
	fText( "deviceType="+deviceType, x, 100, 16, "yellow" );
	fText( "isBgm="+isBgm+"("+bgmNo+")", x, 150, 16, "yellow" );
	fText( "winW="+winW+" winH="+winH+" SCALE="+SCALE, x, 200, 16, "yellow" );
	fText( main_idx+":"+main_tmr+"("+tapX+","+tapY+")"+tapC+" inkey="+inkey, x, 250, 16, "cyan" );
	fText( "加速度 "+acX + " : " + acY + " : " + acZ, x, 300, 16, "pink" );
//	for( i = 0; i < 256; i ++ ) {
//		x = i%16;
//		y = toInt(i/16);
//		fText( key[i], 15+30*x, 15+30*y, 12, "white" );
//	}
	y = 400;
	for( i = 0; i < SE_LIST.length; i ++ ) { fText( sefile[i], x, y, 16, "green" ); y += 30; }
	for( i = 0; i < BGM_LIST.length; i ++ ) { fText( bgmfile[i], x, y, 16, "green" ); y += 30; }
}

	setTimeout( "wwsSysMain()", toInt(1000/FPS) );
}

// ---------- 起動処理 ----------
window.onload = function() {

	initCanvas();

	if( NUA.indexOf('Android') > 0 ) {
		deviceType = PT_Android;
	}
	else if( NUA.indexOf('iPhone') > 0 || NUA.indexOf('iPod') > 0 || NUA.indexOf('iPad') > 0 ) {
		deviceType = PT_iOS;
		window.scrollTo(0,1);//iPhoneのURLバーを消す位置に
	}
	else if( NUA.indexOf('Silk') > 0 ) {
		deviceType = PT_Kindle;
	}

	//イベントリスナー（タップ判定）
	if( supportTouch == true ) {
		cvs.addEventListener( "touchstart", touchStart );
		cvs.addEventListener( "touchmove", touchMove );
		cvs.addEventListener( "touchend", touchEnd );
		cvs.addEventListener( "touchcancel", touchCancel );
	}
	else {
		cvs.addEventListener( "mousedown", mouseDown );
		cvs.addEventListener( "mousemove", mouseMove );
		cvs.addEventListener( "mouseup", mouseUp );
		cvs.addEventListener( "mouseout", mouseOut );
	}

	main_idx = 0;
	//iOS Safari プライベートブラウズがON（保存できない）か判定
	if( CHECK_LS == true ) {
		try { localStorage.setItem( "_save_test", "testdata" ); } catch( e ) { main_idx = -1; }
	}
	wwsSysMain();//リアルタイム処理を開始
}
