///////////////////////////////////////////////////////
if ( !window.requestAnimationFrame ) {
window.requestAnimationFrame =
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
}
//乱数の取得
function rand(num) {
return Math.floor(Math.random() * num);
}
$(function(){
//HTML ファイル上の canvas エレメントのインスタンスを取得
//canvas = $('#bg')[0];
var canvas = $('#canvas').get(0);
var ctx = canvas.getContext("2d");
var cvsw = 600; // canvasタグに指定したwidth
var cvsh = 600; // canvasタグに指定したheight
var rad = Math.PI / 180;
var R = 2.0;
var imgCnt = 25;
var OUT_DISTANCE = 60;
//var OUT_DISTANCE = 40;
var imgW = 32;
var imgH = 82;
var sx = 0; //画像positionX
var sy = 0; //画像positionY
var dx = 0; //x方向移動
var dy = 0; //y方向移動
var sw = 0;
var sh = 0;
var dw = 0;
var dh = 0;
var deg = 0; //方向角度
var cx = -imgW/2;
var cy = -imgH/2;
//var fps = 48;
var fps = 60;
var angleAdd = 1; // 画像角度への加算値
//オブジェクト
var medakas = [];
var img = new Image();
img.src = "images/medaka.png"; // 画像の読み込み
//めだかの生成
addMedakas = function() {
for (var i = 0; i < imgCnt; i++) {
addMedakaInScreen();
}
}
//めだかの追加
addMedakaInScreen = function() {
while (true) {
var x = rand(360*R);
var y = rand(360*R);
if (x < 50 && y < 50) continue;
addMedaka(x, y, rand(360*R));
break;
}
}
var Sprite = function(w, h){
this.w = w;
this.h = h;
}
addMedaka = function(x, y, orientation) {
//めだかの生成
var medaka = new Sprite(imgW, imgH);
var idx = rand(10);
if (idx < 6) {
medaka.type = 0;
} else if (idx < 9) {
medaka.type = 1;
} else {
medaka.type = 2;
}
medaka.frameTick = 0;
medaka.curframe = medaka.type*2;
medaka.speedMin = (0.1+rand(10)/10.0)*R;
medaka.speedMax = (medaka.speedMin+0.5+rand(20)/10.0)*R;
medaka.speedDec = 0;
medaka.speed = medaka.speedMin;
medaka.x = x;
medaka.y = y;
medaka.rotationTick = 60;
medaka.rotationTo = orientation;
medaka.rotation = medaka.rotationTo;
medaka.active = true;
//メダカデータのアップデート
medaka.updateMedaka = function(){
if (!this.active) {
this.frameTick++;
if (this.frameTick >= 2) this.frameTick = 0;
this.curFrame = this.type*2+this.frameTick;
return;
}
//フレーム
this.frameTick += 0.08+(this.speed/10.0);
if (this.frameTick >= 3) this.frameTick = this.frameTick%3;
var idx = parseInt(this.frameTick);
if (idx == 0) this.curFrame = this.type*2;
if (idx == 1 || idx == 2) this.curFrame = this.type*2+1;
sx = this.curFrame*imgW;
//向き
this.rotationTick--;
if (this.rotationTick < 0) {
this.rotationTick = 300;
//this.rotationTo = this.rotation+rand(60)-30;
this.rotationTo = this.rotation+rand(10)-6;
}
if (this.rotationTick%2 == 0) {
if (this.rotation < this.rotationTo) {
this.rotation += 1;
} else if (this.rotation > this.rotationTo) {
this.rotation -= 1;
}
}
deg = this.rotationTo*rad;
//スピード調整
this.speed -= this.speedDec;
if (this.speed < this.speedMin) {
this.speed = this.speedMin;
}
//移動
this.x += this.speed*Math.cos((this.rotation-90)/180*Math.PI);
this.y += this.speed*Math.sin((this.rotation-90)/180*Math.PI);
dx = this.x;
dy = this.y;
sw = this.w;
sh = this.h;
dw = this.w;
dh = this.h;
}
//タップによるメダカの移動
medaka.ontap = function(x, y){
var distance = Math.sqrt(
(this.x-x)*(this.x-x)+
(this.y-y)*(this.y-y));
if (distance > 100) return;
//スピード
this.speedDec = (this.speedMax-this.speedMin)/(10.0+rand(100));
this.speed = this.speedMax;
//向き
var radian = Math.atan2(this.y-y, this.x-x);
this.rotationTick = 0;
this.rotationTo = (radian*180/Math.PI)+90;
this.rotation = this.rotationTo;
deg = this.rotationTo*rad;
}
medakas.push(medaka);
medaka = null;
}
//範囲外に描画された画像をcanvasの端に戻す
addMedakaInEdge = function(){
var ms = medakas[i];
if (ms.x < -OUT_DISTANCE*R || (320+OUT_DISTANCE)*R < ms.x ||
ms.y < -OUT_DISTANCE*R || (320+OUT_DISTANCE)*R < ms.y) {
//スクリーンエッジに移動
//var dir = 0;//rand(4);
var dir = rand(4); //rand(4);
var orientation = 0;
if (dir == 0) {
ms.x = (100+rand(360-100))*R;
ms.y = (360+rand(OUT_DISTANCE))*R;
orientation = 0+rand(160)-80;
} else if (dir == 1) {
ms.x = (-OUT_DISTANCE+rand(OUT_DISTANCE))*R;
ms.y = (100+rand(360-100))*R;
orientation = 90+rand(160)-80;
} else if (dir == 2) {
ms.x = rand(360)*R;
ms.y = (-OUT_DISTANCE+rand(OUT_DISTANCE))*R;
orientation = 180+rand(160)-80;
} else if (dir == 3) {
ms.x = (360+rand(OUT_DISTANCE))*R;
ms.y = rand(360)*R;
orientation = 270+rand(160)-80;
}
dx = ms.x;
dy = ms.y;
ms.rotationTo = orientation;
deg = ms.rotationTo*rad;
}
}
function drawMedakaImage(){
ctx.clearRect(0,0,cvsw,cvsh);
for(i = 0; i < imgCnt; i++){
medakas[i].updateMedaka();
// 範囲外に描画された画像をcanvasの端に戻す
addMedakaInEdge();
ctx.save();
ctx.translate(dx, dy);
//ctx.translate(cx, cy);
ctx.rotate(deg);
//ctx.drawImage(img, sx, sy, imgW, imgH, cx, cy, imgW, imgH);
ctx.drawImage(img, sx, sy, sw, sh, cx, cy, dw, dh);
//ctx.drawImage(img, sx, sy, imgW, imgH, dx, dy, imgW, imgH);
ctx.restore();
}
}
//circle波紋画像生成
///////////////////////////////////////////////////////
var VisibleTouch = function() {
this.ripples = [];
this.canvas = $('<canvas>')
.attr({
//width: $(window).width(),
//height: $(window).height()
width: cvsw,
height: cvsh
})
.css({
position: 'absolute',
top: 0,
left: 0,
zIndex: -1000
})
.appendTo('body');
this.ctx = this.canvas[0].getContext('2d');
this.foreground = false;
this.mouse = null;
this.ripple = null;
}
VisibleTouch.prototype.addObject = function(x, y) {
if (this.ripple) {
this.ripples.push(new VisibleTouchRipple(this.ctx, x, y));
}
}
VisibleTouch.prototype.draw = function() {
if (this.ripples.length > 0) {
if (!this.foreground) {
this.canvas.css({zIndex: 1000});
}
this.ctx.clearRect(0, 0, this.canvas[0].width, this.canvas[0].height);
for (var i = 0; i < this.ripples.length; i++) {
this.ripples[i].draw();
}
while ((this.ripples.length > 0) && (this.ripples[0].age >= this.ripples[0].maxAge)) {
this.ripples.shift();
}
if (this.ripples.length === 0) {
this.ctx.clearRect(0, 0, this.canvas[0].width, this.canvas[0].height);
this.canvas.css({zIndex: -1000});
}
}
}
///////////////////////////////////////////////////////
visibletouch = new VisibleTouch();
//visibletouch.option = opt;
//$('body').click(function(e) {
$('#canvas').click(function(e) {
visibletouch.addObject(e.pageX, e.pageY);
if (visibletouch.mouse) {
visibletouch.mouse.mouseup(e.which);
}
});
var timerloop = function() {
visibletouch.draw();
window.requestAnimationFrame(timerloop);
};
////////////////////////////////////////////////////////
var VisibleTouchRipple = function(ctx, x, y) {
this.ctx = ctx;
this.age = 0;
//this.maxAge = 15;
this.maxAge = 25;
this.x = x;
this.y = y;
}
VisibleTouchRipple.prototype.draw = function() {
if (this.age < this.maxAge) {
var r = this.age * 4;
//var r = this.age * 6;
var alpha = (1.0 - this.age / this.maxAge / 1).toFixed(2);
//this.ctx.fillStyle = 'rgba(200, 200, 200, ' + alpha + ')';
//this.ctx.fillStyle = 'rgba(153, 255, 255, ' + alpha + ')';
this.ctx.strokeStyle = 'rgba(153, 255, 255, ' + alpha + ')';
this.ctx.lineWidth = 12;
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, r, 0, Math.PI*2, false);
//this.ctx.fill();
this.ctx.stroke();
this.age++;
}
}
visibletouch.ripple = true;
timerloop();
//クリック(タップ)があった場合
$('#canvas').click(function(e){
var x = e.offsetX;
var y = e.offsetY;
// hamon画像をcanvasに生成
//addHamon(x, y);
//タップによるメダカの移動
for(var i = 0; i < imgCnt; i++){
medakas[i].ontap(x, y);
}
});
function flow_start(){
addMedakas();
setInterval(drawMedakaImage,fps);
}
img.onload = flow_start;
});