"use strict";

var	Resource =
{
	Tilemap	: [
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
		[ 0, 0, 0, 0, 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, 1 ],
		[ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ],
		[ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ],
	],
}



let	WIDTH  = 23;
let	HEIGHT = 23;
let	TILE   = 8;
let	CHRSIZE = 32;


var DL =
{
	SCALE	: 3,
	TILE	: 8,
	mTile8	: [],
	mTile32	: [],

	DrawString : function( x, y, s, color )
	{
		TUGames.GX.DrawString( s, x, y, 0, color );	//	座標XYZへ、ABGR形式で指定した色で文字列を描画
	},

	DrawTexture : function( x0, y0, x1, y1, gh )
	{
		TUGames.GX.DrawTexture( gh, x0, y0, 0, x1 - x0, y1 - y0 );
	},

	DrawTextureR : function( pos, atr, gh )
	{
		let		h =   atr & 1;
		let		v = ( atr & 2 ) >> 1;
		this.DrawTexture(
		 pos.mX + pos.mWidth *  h   , pos.mY + pos.mHeight *  v   ,
		 pos.mX + pos.mWidth * (h^1), pos.mY + pos.mHeight * (v^1),
		 gh );
	},

	DrawTilemap : function()
	{
		if( DL.sPriTilemap == null ){
			DL.sPriTilemap = TUGames.Primitive.CreateMap( TUGames.GU.Format.T2F_V3F, WIDTH, HEIGHT, TILE, TILE, DL.mTex8, Resource.Tilemap );
		}
		DL.sPriTilemap.draw();
	},

	FillRect : function( x1, y1, x2, y2, color )
	{
		TUGames.GX.FillRect( x1, y1, 0, x2 - x1, y2 - y1, color );
	},
}

class Rectangle
{
	constructor( x, y, width, height )
	{
		this.mX = x;
		this.mY = y;
		this.mWidth = width;
		this.mHeight = height;
	}

	intersectsWith( rect )
	{
//console.log( "this.mX=" + this.mX + " this.mY=" + this.mY + " this.mWidth=" + this.mWidth + " this.mHeight=" + this.mHeight );
//console.log( "rect.mX=" + rect.mX + " rect.mY=" + rect.mY + " rect.mWidth=" + rect.mWidth + " rect.mHeight=" + rect.mHeight );
		let	sw = this.mWidth / 2;
		let	sh = this.mHeight / 2;
		let	rw = rect.mWidth / 2;
		let	rh = rect.mHeight / 2;
		return( Math.abs( ( this.mX + sw ) - ( rect.mX + rw ) ) < ( sw + rw ) &&
		        Math.abs( ( this.mY + sh ) - ( rect.mY + rh ) ) < ( sh + rh ) );
	}
}

class Size
{
	constructor( width, height )
	{
		this.mWidth = width;
		this.mHeight = height;
	}
}

class Sprite
{
	constructor( gh, pos )
	{
		this.mGH = gh;
		this.mPos = pos;
		this.mAtr = 0;
	}

	add( width, height )
	{
		this.mPos.mX += width;
		this.mPos.mY += height;
	}

	draw( idx )
	{
		DL.DrawTextureR( this.mPos, this.mAtr, this.mGH[ idx ] );
	}

	intersectsWith( rect )
	{
		return( this.mPos.intersectsWith( rect ) );
	}
}

class Character extends Sprite
{
	constructor( gh, pos, col )
	{
//console.log( "Character#constructor pos=" + pos );
		super( gh, pos );
		this.mCol = col;
		this.mColIdx = 0;
		this.addCol( pos.mX, pos.mY );
	}

	add( dx, dy )
	{
		super.add( dx, dy );
		this.addCol( dx, dy );
	}

	addCol( dx, dy )
	{
		for( let i = 0; i < this.mCol.length; i++ ){
			this.mCol[ i ].mX += dx;
			this.mCol[ i ].mY += dy;
		}
	}

	collision( c )
	{
//console.log( "collision this.mCol[ this.mColIdx ]=" + this.mCol[ this.mColIdx ] + " c.mCol[ c.mColIdx ]=" + c.mCol[ c.mColIdx ] );
		return( this.mCol[ this.mColIdx ].intersectsWith( c.mCol[ c.mColIdx ] ) );
	}

}

let	mGameOver = false;
let	mScore = 0;
let	mHiScore = 0;
let	mPlayer = [];
let	mEnemy = [];
let	mFire = [];
let	mScreen = new Rectangle( 0, 0, WIDTH * TILE, ( HEIGHT - 2 ) * TILE );

class Enemy extends Character
{
	constructor( gh, pos, col, vec )
	{
//console.log( "Enemy#constructor pos=" + pos );
		super( gh, pos, col );
		this.mVec = vec;
	}

	draw()
	{
		super.draw( ( this.mPos.mX + this.mPos.mY ) >> 2 & 1 );
	}

	move()
	{
		super.add( this.mVec.mWidth, this.mVec.mHeight );
	}
}

class Fire extends Character
{
	constructor( gh, pos, col, vec )
	{
//console.log( "Fire#constructor pos.mX=" + pos.mX + " pos.mY=" + pos.mY );
		super( gh, pos, col );
		this.mVec = vec;
	}

	draw()
	{
//console.log( "Fire#draw " + this.mPos.mX + " " + this.mPos.mY );
		super.draw( ( this.mPos.mX + this.mPos.mY ) >> 2 & 1 );
	}

	move()
	{
		super.add( this.mVec.mWidth, this.mVec.mHeight );
	}
}

class Player extends Character
{
	constructor( gh, pos, col )
	{
//console.log( "Player#constructor pos=" + pos );
		super( gh, pos, col );
		this.mCrou = false;
		this.mDX = 0;
		this.mDY = 0;
		this.mHP = 112;
		this.mWait = 0;
	}

	get KeyStateLeft(){		return( Math.max( TUGames.PF.GetKey( 37 ), TUGames.PF.GetKey( 65 ) ) );	}
	get KeyStateUp(){		return( Math.max( TUGames.PF.GetKey( 38 ), TUGames.PF.GetKey( 87 ) ) );	}
	get KeyStateRight(){	return( Math.max( TUGames.PF.GetKey( 39 ), TUGames.PF.GetKey( 68 ) ) );	}
	get KeyStateDown(){		return( Math.max( TUGames.PF.GetKey( 40 ), TUGames.PF.GetKey( 83 ) ) );	}
	get KeyStateB(){		return( Math.max( TUGames.PF.GetKey( 78 ), TUGames.PF.GetKey( 88 ) ) );	}

	damage()
	{
		this.mHP -= 2;
		return( this.mHP <= 0 );
	}

	diffGround()
	{
		return( 20 * TILE - this.mPos.mHeight - this.mPos.mY );
	}

	draw()
	{
		if( this.mCrou ){
			super.draw( 2 );
		}else{
			super.draw( this.mPos.mX >> 3 & 1 );
		}

		DL.FillRect( 16, 32, 128, 48, 0xff0000ff );
		DL.FillRect( 128 - this.mHP, 32, 128, 48, 0xff00ff00 );
	}

	update()
	{
		if( this.mWait > 0 ){
			this.mWait--;
			return;
		}

		let	d = this.diffGround();

		this.mCrou = this.KeyStateDown > 0 && d == 0;
		if( this.mCrou ){
			this.mColIdx = 1;
		}else{
			this.mColIdx = 0;
		}

		if( d == 0 ){
			if( this.KeyStateB == 1 && this.mWait == 0 ){
				this.mWait = 30;
				mFire.push( new Fire( [ DL.mTile8[ 4 ], DL.mTile8[ 5 ] ],
				                      new Rectangle( this.mPos.mX + 20 - this.mAtr * 16, this.mPos.mY + this.mColIdx * 12 + 8, TILE, TILE ),
				                      [ new Rectangle( 0, 0, 8, 8 ) ],
				                      new Size( 1 - ( this.mAtr << 1 ), 0 ) ) );
			}
		}

		if( this.mCrou ){
			return;
		}

		if( d == 0 ){
			if( this.KeyStateLeft > 0 ){
				this.mDX = -1;
				this.mAtr = 1;
			}else if( this.KeyStateRight > 0 && this.mPos.mX + this.mPos.mWidth < WIDTH * TILE ){
				this.mDX = 1;
				this.mAtr = 0;
			}else{
				this.mDX = 0;
			}
		}

		if( this.mDX == -1 && this.mPos.mX > 0 ){
			this.add( -1, 0 );
		}

		if( this.mDX == 1 && this.mPos.mX + this.mPos.mWidth < WIDTH * TILE ){
			this.add( 1, 0 );
		}

		if( d > 0 ){
			this.mDY++;
		}

		if( this.KeyStateUp > 0 && this.diffGround() <= 0 ){
			this.mDY = -24;
		}

		this.add( 0, this.mDY >> 3 );

		d = this.diffGround();

		if( d <= 0 ){
			this.mDY = 0;
			this.add( 0, d );
		}
	}
}

function AddEnemy( type )
{
	let		x, y, dx, dy;
	if( type == 0 ){
		x = WIDTH * TILE - 1;
		y = Rnd( TILE * 5 ) + TILE * 14;
		dx = -Rnd( 2 ) - 1;
		dy = 0;
	}else if( type == 1 ){
		x = -7;
		y = Rnd( TILE * 5 ) + TILE * 14;
		dx = Rnd( 2 ) + 1;
		dy = 0;
	}else{
		x = Rnd( WIDTH * TILE );
		y = -7;
		dx = Rnd( 3 ) - 1;
		dy = Rnd( 2 ) + 1;
	}
	mEnemy.push( new Enemy( [ DL.mTile8[ 2 ], DL.mTile8[ 3 ] ],
	                        new Rectangle( x, y, TILE, TILE ),
	                        [ new Rectangle( 2, 1, 4, 6 ) ],
	                        new Size( dx, dy ) ) );
}

function Rnd( m )
{
	return( Math.floor( Math.random() * m ) );
}

function UpdateFrame()
{
	if( mGameOver ){
		if( TUGames.PF.GetKey( 13 ) <= 0 ){
			return;
		}
		Start();
	}

	mHiScore = Math.max( mHiScore, ++mScore );

//	if( mEnemy.length == 0 || Rnd( 200000 / ( mScore + 1000 ) ) == 0 ){
	if( mEnemy.length == 0 || Rnd( 5000 / ( mScore + 1000 ) ) == 0 ){
		AddEnemy( Rnd( mEnemy.length ) );
	}

	mPlayer[ 0 ].update();
	for( let i = mEnemy.length - 1; i >= 0; i-- ){
		let	e = mEnemy[ i ];
		e.move();
		if( !e.intersectsWith( mScreen ) ){
			mEnemy.splice( i, 1 );
		}
		if( mPlayer[ 0 ].collision( e ) ){
//			mGameOver = mPlayer[ 0 ].damage();
		}
	}
	for( let i = mFire.length - 1; i >= 0; i-- ){
		let	f = mFire[ i ];
		f.move();
		if( !f.intersectsWith( mScreen ) ){
			mFire.splice( i, 1 );
			continue;
		}
		for( let j = mEnemy.length - 1; j >= 0; j-- ){
			if( f.collision( mEnemy[ j ] ) ){
				mFire.splice( i, 1 );
				mEnemy.splice( j, 1 );
				break;
			}
		}
	}
}

function Start()
{
	mGameOver = false;
	mScore = 0;
	mPlayer = [];
	mPlayer.push( new Player( [ DL.mTile32[ 0 ], DL.mTile32[ 1 ], DL.mTile32[ 2 ] ],
	                          new Rectangle( WIDTH / 2 * TILE, 20 * TILE - CHRSIZE, CHRSIZE, CHRSIZE ),
	                          [ new Rectangle( 13, 5, 6, 26 ), new Rectangle( 13, 18, 6, 13 ) ] ) );

	mEnemy = [];
	mFire = [];
	TUGames.PF.StartLoop( 60, UpdateFrame, Draw );	//	fpsを指定してループを開始し、更新処理と描画処理を登録
}

function Draw()
{
	TUGames.GX.Clear();	//	設定された背景色で画面初期化

	DL.DrawTilemap();

	let	el = mEnemy.length;
	DL.sPri8.setCount( el );
	for( let i = 0; i < el; i++ ){
		let		e = mEnemy[ i ];
		let		p = e.mPos;
		let		u = ( ( p.mX + p.mY ) >> 2 & 1 ) / 2;
		DL.sPri8.setTexCoord( i, u, 0.25, 0.5, 0.25 );
		DL.sPri8.setPosition( i, p.mX, p.mY, p.mWidth, p.mHeight );
		DL.sPri8.setIndices( i );
	}
	DL.sPri8.draw_main( el * 6 );


/*
	for( let i = mPlayer.length - 1; i >= 0; i-- ){
		mPlayer[ i ].draw();
	}
	for( let i = mEnemy.length - 1; i >= 0; i-- ){
		mEnemy[ i ].draw();
	}
	for( let i = mFire.length - 1; i >= 0; i-- ){
		mFire[ i ].draw();
	}

	DL.DrawString(  4, 4, "SCORE " + mScore, 0xffffffff );
	DL.DrawString( 76, 4, "HI-SCORE " + mHiScore, 0xffffffff );
	if( mGameOver ){
		DL.DrawString( 48, 64, "GAME OVER", 0xffffffff );
	}
*/

	GL.flush();	//	描画内容を画面に反映
}

function LoadImage( imf, imp )
{
	DL.mTile8  = TUGames.GX.LoadTextureDiv( imf, TILE, TILE );	//	指定されたファイルをテクスチャ画像として分割して読み込む
	DL.mTile32 = TUGames.GX.LoadTextureDiv( imp, CHRSIZE, CHRSIZE );	//	指定されたファイルをテクスチャ画像として分割して読み込む
	DL.mTex8   = TUGames.Texture.Create2p( imf );

	DL.sPri8 = new TUGames.PriRects( TUGames.GU.Format.T2F_V3F );
	DL.sPri8.mTexture = TUGames.Texture.Create2p( imf );

	Start();
}

window.onload = function()
{
	document.addEventListener( 'keydown', ( ev ) =>{	ev.preventDefault();	} );
	document.addEventListener( 'keyup'  , ( ev ) =>{	ev.preventDefault();	} );

	TUGames.GX.Init( "main", 180, 180 );	//	キャンバスIDと描画領域を指定してライブラリ初期化
	TUGames.GX.ClearColor( 0xff111111 );

	let		imf = new Image();
	imf.onload = function()
	{
		let		imp = new Image();
		imp.onload = function()
		{
			LoadImage( imf, imp );
		}
		imp.src = "../assets/tile32.png";
	}
	imf.src = "../assets/tile8.png";
}



戻る戻る back