Created
January 31, 2015 09:37
-
-
Save khirayama/ba28a96d4103e9156e56 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id='world' width="465" height="465"></canvas> | |
<div id="fps"></div> | |
<style> | |
body { | |
margin:0; | |
padding:0; | |
overflow:hidden; | |
background:#666; | |
} | |
canvas{ | |
background:#000; | |
position:absolute; | |
top:0; | |
left:0; | |
} | |
#fps{ | |
background:black; | |
color:white; | |
padding:.5em; | |
display:inline-block; | |
font-size:80%; | |
width:5em; | |
text-align:center; | |
border-radius:5px; | |
position:absolute; | |
top:5px; | |
left:5px; | |
} | |
</style> | |
<script> | |
// forked from os0x's "Particle 40000" http://jsdo.it/os0x/ezL2 | |
// forked from os0x's "Particle 10000" http://jsdo.it/os0x/30Pg | |
// forked from clockmaker's "Particle 3000" http://jsdo.it/clockmaker/particle | |
/* | |
* Opera10.60 Betaならいける気がする 10まん | |
*/ | |
/* | |
* いろいろ弄ってみたけど、パフォーマンス自体はほとんど変わってない… | |
* 単にFPS落として40000パーティクル | |
* Opera10.60 Betaが最適 | |
*/ | |
/* | |
* Canvas での擬似lock/unlockとか使って無理やり 10000 パーティクル | |
* 参考: http://ss-o.net/game2d/tech.html#C12 | |
*/ | |
/** | |
* みんな大好きパーティクル | |
* (JavaSript, HTML5バージョン) | |
* | |
* @author clockmaker | |
* @see http://clockmaker.jp/blog/ | |
* | |
* wonderflのパーティクル祭りを参考 | |
* http://wonderfl.net/c/436W/ | |
*/ | |
// ----------------------------------------- | |
// 定数 | |
// ----------------------------------------- | |
var MAX_NUM = 100000; // パーティクルの個数 | |
var FPS = 20; | |
var FRAMERATE = FPS / 1000 >> 0; // フレームレート | |
// ----------------------------------------- | |
// クラス定義 | |
// ----------------------------------------- | |
/** | |
* パーティクル | |
*/ | |
function Particle(x,y) { | |
this.x = x; | |
this.y = y; | |
this.vx = 0; | |
this.vy = 0; | |
} | |
// ----------------------------------------- | |
// 初期化 | |
// ----------------------------------------- | |
// 変数の初期化 | |
var mouseX = 0; | |
var mouseY = 0; | |
// キャンバスの初期化 | |
var canvas = document.getElementById("world"); | |
var ctx = canvas.getContext("2d"); | |
var width = canvas.width; | |
var height = canvas.height; | |
ctx.fillStyle = "rgb(200, 200, 255)"; | |
ctx.fillRect(0, 0, width, height); | |
// ピクセルを取得 | |
var pixels = ctx.getImageData(0, 0, width, height); | |
var data = pixels.data; | |
for (var i = 3, l = data.length;i < l;i+=4){ | |
data[i] = 0; | |
} | |
// setPixel を定義(色は固定) | |
var setPixel = (function(){ | |
var data = pixels.data; | |
function _setPixel(x, y){ | |
var idx = ((x|0) + (y|0) * width)*4; | |
data[idx+3] = 255; | |
} | |
return _setPixel; | |
})(); | |
var delPixel = (function(){ | |
var data = pixels.data; | |
function _setPixel(x, y){ | |
var idx = ((x|0) + (y|0) * width)*4; | |
data[idx+3] = 0; | |
} | |
return _setPixel; | |
})(); | |
var particles = []; | |
// パーティクルの初期化 | |
for(var i=0; i<MAX_NUM; i++) { | |
var p = new Particle( | |
Math.random() * width, | |
Math.random() * height | |
); | |
particles.push(p); | |
} | |
// FPS の表示 | |
var fps_view = document.getElementById('fps'); | |
var Counter = 0, last = +new Date(); | |
// イベントハンドラの登録 | |
canvas.onmousemove = mouseMoveHandler; | |
setInterval(enterFrameHandler, FRAMERATE); | |
// ----------------------------------------- | |
// イベントハンドラ | |
// ----------------------------------------- | |
/** | |
* マウスが動いたとき | |
*/ | |
function mouseMoveHandler(e) { | |
// var rect = e.target.getBoundingClientRect(); | |
// マウス座標の更新(もっとスマートな方法ある?) | |
// → スマートではないけどoffsetで | |
mouseX = e.clientX - canvas.offsetLeft; | |
mouseY = e.clientY - canvas.offsetTop; | |
} | |
/** | |
* タイマー | |
*/ | |
function enterFrameHandler() { | |
var gravityX = mouseX; | |
var gravityY = mouseY; | |
var n; | |
var l = particles.length; | |
while(l--){ | |
n = particles[l]; | |
delPixel(n.x,n.y); | |
var diffX = gravityX - n.x; | |
var diffY = gravityY - n.y; | |
var acc = 50 / (diffX * diffX + diffY * diffY); | |
var accX = acc * diffX; | |
var accY = acc * diffY; | |
n.vx += accX; | |
n.vy += accY; | |
n.x += n.vx; | |
n.y += n.vy; | |
n.vx *= 0.96; | |
n.vy *= 0.96; | |
if (n.x > width) | |
n.x = 0; | |
else if (n.x < 0) | |
n.x = width; | |
if (n.y > height) | |
n.y = 0; | |
else if (n.y < 0) | |
n.y = height; | |
// 点描 | |
setPixel(n.x, n.y); | |
} | |
ctx.putImageData(pixels, 0, 0); | |
if (++Counter > FPS){ | |
var now = +new Date(); | |
var _f = 1000 / ((now - last) / Counter); | |
last = now; | |
Counter = 0; | |
fps_view.innerHTML = 'FPS '+_f.toFixed(2); | |
} | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment