<div class="canvas" name="train99">
<div style="display: none;">
<img src="material/center.gif" id="center.gif">
<img src="material/left.gif" id="left.gif">
<img src="material/right.gif" id="right.gif">
<audio src="material/boo.wav" id="boo.wav"></audio>
</div>
<canvas id="train99" width="200" height="200"></canvas>
<script id="loader.js">
function Loader(main, ...files) {
	var n = 0;
	function onload() {if (++n == files.length) main();}

	for (let file of files) {
		var element = document.getElementById(file);
		element.addEventListener('load', onload);
	}
}
</script>
<script id="train99.js">
new Loader(train99, "center.gif", "left.gif", "right.gif");

// http://bee.in.coocan.jp/tk/
function train99() {
	var imgC = document.getElementById("center.gif");
	var imgL = document.getElementById("left.gif");
	var imgR = document.getElementById("right.gif");
	var audD = document.getElementById("boo.wav").load();

	var canvas = document.getElementById("train99");
	var ctx = canvas.getContext("2d");

	var id = 0;
	canvas.tabIndex = 1;
	canvas.onblur = function(){clearInterval(id); id = 0;};
	canvas.onfocus = function(){if (!id) id = setInterval(game_draw, 20)};

	function main() {
		canvas.style.background = "black";
		game_init(canvas.width/2, canvas.height/2);
		game_draw();
		title();
	}

	function title() {
		ctx.font = "12pt Verdena";
		ctx.textAlign = "center";
		ctx.textBaseline = "middle";
		ctx.fillStyle = "orange";
		var w = canvas.width/2;
		var h = canvas.height/2;
		ctx.fillText('click to start.', w, h + 20);
		ctx.fillText('enter to restart.', w, h + 20 + 16);
		ctx.fillText('arrow key to move.', w, h + 20 + 32);
	}

	// fighter
	var r = 2, speed = 2;
	var x = canvas.width / 2, y = canvas.height / 2;
	var xp = 0, xn = 0, yp = 0, yn = 0, dx = 0, dy = 0;
	var life = 1, clock = 0;

	function fighter_init(_x, _y) {
		x = _x; y = _y;
		xp = xn = yp = yn = dx = dy = 0;
		life = 1; clock = 0;
	}

	// fighter control
	canvas.onkeydown = function(event) {
		event = event || window.event;
		event.preventDefault();
		if (event.keyCode == 13) {game_init(canvas.width/2, canvas.height/2); return;}//enter
		if (!life) return;
		switch(event.keyCode) {
		case 37: xn=dx=-1; break;//left
		case 39: xp=dx=+1; break;//right
		case 38: yn=dy=-1; break;//up
		case 40: yp=dy=+1; break;//down
		}
	};
	canvas.onkeyup = function(event) {
		event = event || window.event;
		event.preventDefault();
		if (!life) return;
		switch(event.keyCode) {
		case 37: xn=0; dx=xp; break;//left
		case 39: xp=0; dx=xn; break;//right
		case 38: yn=0; dy=yp; break;//up
		case 40: yp=0; dy=yn; break;//down
		}
	};

	// bullet
	var BN = 30;
	var bx = new Array(BN), by = new Array(BN);
	var bdx = new Array(BN), bdy = new Array(BN);
	var br = new Array(BN);
	var bfill = new Array(BN), bstroke = new Array(BN);
	var border = 10, bspeed = 1, bradius = 2;

	function bullet_init(i) {
		for (var i=0; i<BN; ++i)
			bullet_init_index(i);
	}

	function bullet_init_index(i) {
		var d = Math.floor(Math.random() * 8);
		bdx[i] = Math.ceil(Math.random() * bspeed);
		bdy[i] = Math.ceil(Math.random() * bspeed);
		if (d & 1) {
			bx[i] = Math.round(Math.random() * (canvas.width + border * 2));
			if (d & 2) by[i] = canvas.height + border; else by[i] = -border;
			if (d & 2) bdy[i] = -bdy[i];
			if (d & 4) bdx[i] = -bdx[i];
		} else {
			by[i] = Math.round(Math.random() * (canvas.height + border * 2));
			if (d & 2) bx[i] = canvas.width  + border; else bx[i] = -border;
			if (d & 2) bdx[i] = -bdx[i];
			if (d & 4) bdy[i] = -bdy[i];
		}

		br[i] = bradius;
		if (clock >= 1500) br[i] *= 2;
		if (clock >= 3000) br[i] *= 2;
		if (clock >= 4500) br[i] *= 2;

		var cc = clock % 1500;
		if        (cc < 250) {
			bfill[i] = "green";  bstroke[i] = "yellow";
		} else if (cc < 500) {
			bfill[i] = "red";    bstroke[i] = "yellow";
			bdx[i] *= 2; bdy[i] /= 2;
		} else if (cc < 750) {
			bfill[i] = "navy";   bstroke[i] = "blue";
			bdx[i] /= 2; bdy[i] /= 2;
		} else if (cc < 1250) {
			bfill[i] = "orange"; bstroke[i] = "gold";
			if (d & 3) {bdx[i]*=2; bdy[i]/=2;}
			else {bdx[i]/=2; bdy[i]*=2;}
		} else {
			bfill[i] = "black";  bstroke[i] = "white";
			if (d & 3) bdx[i] *= 2; else bdy[i] *= 2;
		}
	}

	function bullet_reload(i) {
		if (bx[i] >= -border && bx[i] <= canvas.width  + border &&
			by[i] >= -border && by[i] <= canvas.height + border) return;
		bullet_init_index(i);
	}

	function bullet_hit(i, x, y) {
		var _x = bx[i] - x, _y = by[i] - y, _r = r + br[i];
		return _x*_x + _y*_y <= _r*_r;
	}

	function game_init(_x, _y) {
		fighter_init(_x, _y);
		bullet_init();
	}

	function game_draw() {
		ctx.clearRect(0, 0, canvas.width, canvas.height);

		// print bullet
		for (var i=0; i<BN; ++i) {
			bx[i] += bdx[i]; by[i] += bdy[i]; bullet_reload(i);
			ctx.beginPath();
			ctx.arc(bx[i], by[i], br[i], 0, 2.0 * Math.PI);
			ctx.fillStyle = bfill[i]; ctx.strokeStyle = bstroke[i];
			ctx.fill(); ctx.stroke();
		}

		// explode message
		if (life == 0) {
			ctx.font = "50pt Verdena";
			ctx.textAlign = "center";
			ctx.textBaseline = "middle";
			ctx.fillStyle = "red";
			ctx.fillText((clock / 50).toFixed(2), canvas.width/2, canvas.height/2);
			return;
		}
		clock++;

		// fighter moves
		x += dx * speed; y += dy * speed;
		x = Math.min(x, canvas.width - r);  x = Math.max(x, r);
		y = Math.min(y, canvas.height - r); y = Math.max(y, r);

		// fighter hits bullet
		for (var i=0; i<BN; ++i)
			if (bullet_hit(i, x, y)) {
				life = 0;
				audD.play();
				break;
			}

		// print fighter
		if     (dx == -1) ctx.drawImage(imgL, x - imgL.width/2, y - imgL.height/2);
		else if (dx == 0) ctx.drawImage(imgC, x - imgC.width/2, y - imgC.height/2);
		else if (dx == 1) ctx.drawImage(imgR, x - imgR.width/2, y - imgR.height/2);
	}

	main();
};
</script>
</div><div class="canvas" name="accelerator">
<input type="range" id="accelerator">
<div id="out">value = 0</div>
<script id="accelerator.js">
(function(){
	var input = document.getElementById('accelerator');
	var out = document.getElementById('out');

	var value = 0;
	var inc = 1;
	var last = -1;

	input.min = 0;
	input.max = 1000;
	input.valueAsNumber = value;

	input.oninput = function() {
		value = this.valueAsNumber;
		out.innerHTML = 'value = ' + value;
	};

	input.onkeydown = function(e) {
		e.preventDefault();
	};

	window.onkeyup = function(e) {
		inc = 1;
		last = -1;
	};

	window.onkeydown = function(e) {
		last == e.keyCode ? (inc = Math.min(++inc, 50)) : (inc = 1);
		last = e.keyCode;
	
		if      (e.keyCode == 37)	// left
			value = Math.max(0, value -= inc);
		else if (e.keyCode == 39)	// right
			value = Math.min(1000, value += inc);
		else
			return;

		input.valueAsNumber = value;
		out.innerHTML = 'value = ' + value;
	};
})();
</script>
</div><div class="canvas" name="point">
<canvas id="point" width="200" height="200"></canvas>
<script id="point.js">
(function(){
	var canvas = document.getElementById("point");
	var ctx = canvas.getContext("2d");

	var N = 40;
	var tx = 0, ty = 360, t = 0;
	var dx = 2, dy = 3;
	var px = new Array(N), py = new Array(N);
	for (var i=0; i<N; ++i) {px[i] = py[i] = -100;}

	canvas.onclick = function(){
		dx = Math.ceil(Math.random()*6);
		dy = Math.ceil(Math.random()*6);
	};

	var id = 0;
	canvas.tabIndex = 1;
	canvas.onblur = function(){cancelAnimationFrame(id); id = 0;};
	canvas.onfocus = function(){if (!id) id = requestAnimationFrame(frame, canvas);};
	function frame() {id = requestAnimationFrame(frame, canvas); draw();}
	draw();

	function draw() {
		var w = canvas.width >> 1, h = canvas.height >> 1;
		var r = 5, amp = 90;
		var x = Math.sin(tx * Math.PI / 180);
		var y = Math.cos(ty * Math.PI / 180);
		x *= -1; x *= amp; x += (amp + r);
		y *= -1; y *= amp; y += (amp + r);
		px[t] = x; py[t] = y;
		ctx.clearRect(0, 0, canvas.width, canvas.height);
		ctx.fillStyle = "brown"; 
		for (var i=0; i<N; ++i)
			ctx.fillRect(px[i], py[i], 2, 2);
		ctx.beginPath();
		ctx.arc(x, y, r, 0, 2.0 * Math.PI);
		ctx.fillStyle = "red"; ctx.strokeStyle = "black"; ctx.fill(); ctx.stroke();
		tx = (tx + dx) % 720;
		ty = (ty + dy) % 720;
		t = (t + 1) % N;
	}
})();
</script>
</div>