[CreateJS] ドットの光 (2) ~BitmapData, ColorHSV~

CreateJSを使って、光るドットの表現に挑戦してみるよ。 :boy:

createjs_dotlight2

BitmaData for EaselJS を使ってみちゃうよ。 :boy:
DotLight, EmitLight, Dotクラスでつくってみたよ。 :bouzu:
ColorHSVクラスなんてのもつくったよ。 :cake:

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ドットの光 (2) | CreateJS</title>
<script src="js/easeljs-0.8.1.min.js"></script>
<script src="js/libs/bitmapdata-1.1.2.min.js"></script>
<script src="js/DotLight.js"></script>
<script src="js/EmitLight.js"></script>
<script src="js/Dot.js"></script>
<script src="js/ColorHSV.js"></script>
<script src="js/stats.min.js"></script>

<style type="text/css">
  #canvas {
  display:block;
    width: 480px;
    height: 320px;
    margin-top: 40px;
    margin-left:auto;
    margin-right:auto;
    padding-left:0;
    padding-right:0;
  }
</style>

<script>
var canvas, stage, stats;
var light;

function init() {
  stats = new Stats();
  stats.setMode(0);
  stats.domElement.style.position = "fixed";
  stats.domElement.style.right = "0px";
  stats.domElement.style.top = "0px";
  document.body.appendChild(stats.domElement);

  canvas = document.getElementById("canvas");

  stage = new createjs.Stage(canvas);

  initialize();
  background();

  stage.update();

  createjs.Ticker.setFPS(30);
  createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED;
  createjs.Ticker.addEventListener("tick", update);
}
function initialize() {
  light = new DotLight(new createjs.Rectangle(0, 0, 480, 320));
  stage.addChild(light);
}
function update(event) {
  light.update();
  stage.update();

  stats.update();
}
function background() {
  var title = new createjs.Text("CreateJS", "24px Myriad Pro", "#FFFFFF");
  stage.addChild(title);
  title.textAlign = "left";
  title.textBaseline = "bottom";
  title.x = 10;
  title.y = 30;
  title.alpha = 0.6;
  var version = new createjs.Text("[0.8.1]", "14px Myriad Pro", "#FFFFFF");
  stage.addChild(version);
  version.textAlign = "left";
  version.textBaseline = "bottom";
  version.x = 105;
  version.y = 26;
  version.alpha = 0.6;
  var subtitle = new createjs.Text("DotLight", "20px Myriad Pro", "#FFFFFF");
  stage.addChild(subtitle);
  subtitle.textAlign = "left";
  subtitle.textBaseline = "bottom";
  subtitle.x = 160;
  subtitle.y = 28;
  subtitle.alpha = 0.6;
  var publish = new createjs.Text("authoring: Sublime Text 2 + Flash CC", "14px Myriad Pro", "#FFFFFF");
  stage.addChild(publish);
  publish.textAlign = "right";
  publish.textBaseline = "bottom";
  publish.x = canvas.width - 10;
  publish.y = 318;
  publish.alpha = 0.6;
}
</script>
</head>
<body onload="init();" style="background-color:#333333">
  <canvas id="canvas" width="480" height="320" style="background-color:#000000"></canvas>
</body>
</html>

DotLight.js
(function() {

function DotLight(rect) {
  this.Container_constructor();

  this.init(rect);
}
var p = createjs.extend(DotLight, createjs.Container);

var scale = 4;

p.rect;
p.bitmapData;
p.sparkle;
p.matrix;
p.light;

p.init = function(rect) {
  this.rect = rect;

  this.bitmapData = new createjs.BitmapData(null, this.rect.width, this.rect.height, 0xFF000000);
  var bitmap = new createjs.Bitmap(this.bitmapData.canvas);
  this.addChild(bitmap);

  this.sparkle = new createjs.BitmapData(null, this.rect.width/scale, this.rect.height/scale, 0xFF000000);
  var sbitmap = new createjs.Bitmap(this.sparkle.canvas);
  this.addChild(sbitmap);
  sbitmap.scaleX = sbitmap.scaleY = scale;
  sbitmap.compositeOperation = "lighter";
  this.matrix = new createjs.Matrix2D();
  this.matrix.scale(1/scale, 1/scale);

  this.light = new EmitLight(this.bitmapData);
};
p.update = function() {
  this.light.create(10);
  this.bitmapData.fillRect(this.rect, 0x00000000);
  this.light.emit();
  this.bitmapData.updateContext();

  this.sparkle.draw(this.bitmapData, this.matrix);
  this.sparkle.updateImageData();
};

window.DotLight = createjs.promote(DotLight, "Container");

}());

EmitLight.js
(function() {

function EmitLight(bd) {
  this.init(bd);
}
var p = EmitLight.prototype;

var gravity = 0.02;

p.bitmapData;
p.rect;
p.dots = [];

p.init = function(bd) {
  this.bitmapData = bd;
  this.rect = bd.rect;
};
p.create = function(max) {
  for (var n = 0; n < max; n++) {
    var px = Math.random()*this.rect.width;
    var py = this.rect.height;
    var power = Math.random() + 0.5;
    var dot = new Dot(px, py, power);
    var hue = Math.random()*360;
    color = new ColorHSV(hue, 0.4, 1);
    dot.rgb = color.value();
    this.dots.push(dot);
  }
};
p.emit = function() {
  var max = this.dots.length;
  for (var n = 0; n < max; n++) {
    var dot = this.dots[n];
    dot.vy += gravity*dot.power;
    dot.vy *= 0.99;
    dot.y -= dot.vy;
    this.bitmapData.setPixel(dot.x, dot.y, dot.rgb);
    if (dot.y > this.rect.bottom) {
      this.dots.splice(n, 1);
      dot = null;
    }
  }
};

window.EmitLight = EmitLight;

}());

Dot.js
(function() {

function Dot(x, y, p) {
  this.init(x, y, p);
}
var p = Dot.prototype;

p.x = 0;
p.y = 0;
p.vx = 0;
p.vy = 0;
p.power = 1;
p.rgb = 0xFFFFFF;

p.init = function(x, y, p) {
  this.x = x;
  this.y = y;
  this.power = p;
};

window.Dot = Dot;

}());

ColorHSV.js
(function() {

function ColorHSV(h, s, v) {
  this.init(h, s, v);
}
var p = ColorHSV.prototype;

p.rgb = 0xFFFFFF;

p.init = function(h, s, v) {
  var r, g, b, i, f, p, q, t;
  if (h && s === undefined && v === undefined) {
    s = h.s, v = h.v, h = h.h;
  }
  i = (h * 6) >> 0;
  f = h * 6 - i;
  p = v * (1 - s);
  q = v * (1 - f * s);
  t = v * (1 - (1 - f) * s);
  switch (i % 6) {
    case 0: r = v, g = t, b = p; break;
    case 1: r = q, g = v, b = p; break;
    case 2: r = p, g = v, b = t; break;
    case 3: r = p, g = q, b = v; break;
    case 4: r = t, g = p, b = v; break;
    case 5: r = v, g = p, b = q; break;
  }
  this.rgb = (((r*0xFF) << 16) >> 0) | (((g*0xFF) << 8) >> 0) | ((b*0xFF) >> 0);
};
p.value = function() {
  return this.rgb;
};

window.ColorHSV = ColorHSV;

}());


参考資料「BitmapData for EaselJS」(リファレンス)


[修正] (15/09/21 Mon 01:00)
CreateJS 0.8.1 にバージョンアップ。