[CreateJS] 紙吹雪 (2)

CreateJSを使って、紙吹雪の動きを作ったよ。 :boy:

createjs_confetti2

ConfettiクラスPaperクラスを作ってみたよ。 :bouzu:
紙が回転する動きは、SpriteクラスSpriteSheetクラスを使ってるよ。 :girl:

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/tweenjs-0.6.1.min.js"></script>
<script src="js/movieclip-0.8.1.min.js"></script>
<script src="js/preloadjs-0.6.1.min.js"></script>
<script src="js/Confetti.js"></script>
<script src="js/Paper.js"></script>
<script src="js/stats.min.js"></script>
<style type="text/css">
  #canvas{
    display:block;
    width:800px;
    margin-top:20px;
    margin-left:auto;
    margin-right:auto;
    padding-left:0;
    padding-right:0;
  }
</style>
<script>

var canvas, stage, stats;
var images;
var confetti;

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);

  background();

  images = images||{};
  var loader = new createjs.LoadQueue(false);
  loader.addEventListener("fileload", fileload);
  loader.addEventListener("complete", complete);
  loader.loadFile({src: "assets/papers.png", id: "papers"});

  createjs.Ticker.setFPS(30);
  createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED;
  if (createjs.Touch.isSupported()) {
    createjs.Touch.enable(stage);
  }
  stage.enableMouseOver(10);
  stage.update();
  createjs.Ticker.addEventListener("tick", update);
}
function fileload(event) {
  if (event.item.type == "image") {
    images[event.item.id] = event.result;
  }
}
function complete(event) {
  event.target.removeEventListener("fileload", fileload);
  event.target.removeEventListener("complete", complete);

  initialize();
}
function initialize() {
  confetti = new Confetti(800, 600, 60, [0.8, 0.6, 0.4], 3);
  stage.addChild(confetti);
  confetti.x = 400;
  confetti.start();
}
function update(event) {
  stage.update();

  stats.update();
}

function background() {
  var sky = new createjs.Shape();
  stage.addChild(sky);
  sky.graphics.beginLinearGradientFill(["#0069A0", "#00AAE4"], [0, 1], 0, 0, 0, 540);
  sky.graphics.drawRect(0, 0, 800, 540);

  var ground = new createjs.Shape();
  stage.addChild(ground);
  ground.graphics.beginLinearGradientFill(["#99CC33", "#7EB133"], [0, 1], 0, 540, 0, 60);
  ground.graphics.drawRect(0, 540, 800, 60);

  var basic = new createjs.Text("HTML5 / CreateJS [0.8.1]", "14px Myriad Pro", "#FFFFFF");
  stage.addChild(basic);
  basic.textAlign = "left";
  basic.textBaseline = "bottom";
  basic.x = 10;
  basic.y = canvas.width - 3;
  basic.alpha = 0.6;
  var title = new createjs.Text("confetti", "24px Myriad Pro", "#FFFFFF");
  stage.addChild(title);
  title.textAlign = "center";
  title.textBaseline = "top";
  title.x = canvas.width/2;
  title.y = 65;
  title.alpha = 0.6;
  var subtitle = new createjs.Text("CreateJS [0.8.1]", "20px Myriad Pro", "#FFFFFF");
  stage.addChild(subtitle);
  subtitle.textAlign = "center";
  subtitle.textBaseline = "top";
  subtitle.x = canvas.width/2;
  subtitle.y = 110;
  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 = canvas.width - 3;
  publish.alpha = 0.6;
}
</script>
</head>
<body onload="init();" style="background-color:#EEEEEE">
  <canvas id="canvas" width="800" height="600" style="background-color:#FFFFFF"></canvas>
</body>
</html>

Confetti.js
(function() {

function Confetti(w, h, o, s, u) {
  this.Container_constructor();

  this.init(w, h, o, s, u);
}
var p = createjs.extend(Confetti, createjs.Container);

p.bw = 800;
p.bh = 600;
p.offset = 60;
p.scales = [1];
p.unit;
p.sprites;
p.ids;

p.init = function(w, h, o, s, u) {
  this.bw = w;
  this.bh = h;
  this.offset = o;
  if (s) this.scales = s;
  this.unit = u;

  var data = {
    "images": ["assets/papers.png"],
    "frames": [
      [98, 354, 30, 30], [194, 322, 30, 30], [162, 322, 30, 30], [130, 322, 30, 30], [98, 322, 30, 30], [66, 450, 30, 30], [66, 418, 30, 30], [66, 386, 30, 30], [66, 354, 30, 30], [66, 322, 30, 30], [66, 354, 30, 30], [66, 386, 30, 30], [66, 418, 30, 30], [66, 450, 30, 30], [98, 322, 30, 30], [130, 322, 30, 30], [162, 322, 30, 30], [194, 322, 30, 30],
      [194, 290, 30, 30], [162, 290, 30, 30], [130, 290, 30, 30], [98, 290, 30, 30], [66, 290, 30, 30], [34, 450, 30, 30], [34, 418, 30, 30], [34, 386, 30, 30], [34, 354, 30, 30], [34, 322, 30, 30], [34, 354, 30, 30], [34, 386, 30, 30], [34, 418, 30, 30], [34, 450, 30, 30], [66, 290, 30, 30], [98, 290, 30, 30], [130, 290, 30, 30], [162, 290, 30, 30],
      [34, 290, 30, 30], [194, 258, 30, 30], [162, 258, 30, 30], [130, 258, 30, 30], [98, 258, 30, 30], [66, 258, 30, 30], [34, 258, 30, 30], [2, 450, 30, 30], [2, 418, 30, 30], [2, 386, 30, 30], [2, 418, 30, 30], [2, 450, 30, 30], [34, 258, 30, 30], [66, 258, 30, 30], [98, 258, 30, 30], [130, 258, 30, 30], [162, 258, 30, 30], [194, 258, 30, 30],
      [2, 354, 30, 30], [2, 322, 30, 30], [2, 290, 30, 30], [2, 258, 30, 30], [194, 226, 30, 30], [162, 226, 30, 30], [130, 226, 30, 30], [98, 226, 30, 30], [66, 226, 30, 30], [34, 226, 30, 30], [66, 226, 30, 30], [98, 226, 30, 30], [130, 226, 30, 30], [162, 226, 30, 30], [194, 226, 30, 30], [2, 258, 30, 30], [2, 290, 30, 30], [2, 322, 30, 30],
      [2, 226, 30, 30], [194, 194, 30, 30], [162, 194, 30, 30], [130, 194, 30, 30], [98, 194, 30, 30], [66, 194, 30, 30], [34, 194, 30, 30], [2, 194, 30, 30], [194, 162, 30, 30], [162, 162, 30, 30], [194, 162, 30, 30], [2, 194, 30, 30], [34, 194, 30, 30], [66, 194, 30, 30], [98, 194, 30, 30], [130, 194, 30, 30], [162, 194, 30, 30], [194, 194, 30, 30],
      [130, 162, 30, 30], [98, 162, 30, 30], [66, 162, 30, 30], [34, 162, 30, 30], [2, 162, 30, 30], [194, 130, 30, 30], [162, 130, 30, 30], [130, 130, 30, 30], [98, 130, 30, 30], [66, 130, 30, 30], [98, 130, 30, 30], [130, 130, 30, 30], [162, 130, 30, 30], [194, 130, 30, 30], [2, 162, 30, 30], [34, 162, 30, 30], [66, 162, 30, 30], [98, 162, 30, 30],
      [34, 130, 30, 30], [2, 130, 30, 30], [194, 98, 30, 30], [162, 98, 30, 30], [130, 98, 30, 30], [98, 98, 30, 30], [66, 98, 30, 30], [34, 98, 30, 30], [2, 98, 30, 30], [194, 66, 30, 30], [2, 98, 30, 30], [34, 98, 30, 30], [66, 98, 30, 30], [98, 98, 30, 30], [130, 98, 30, 30], [162, 98, 30, 30], [194, 98, 30, 30], [2, 130, 30, 30],
      [162, 66, 30, 30], [130, 66, 30, 30], [98, 66, 30, 30], [66, 66, 30, 30], [34, 66, 30, 30], [2, 66, 30, 30], [194, 34, 30, 30], [162, 34, 30, 30], [130, 34, 30, 30], [98, 34, 30, 30], [130, 34, 30, 30], [162, 34, 30, 30], [194, 34, 30, 30], [2, 66, 30, 30], [34, 66, 30, 30], [66, 66, 30, 30], [98, 66, 30, 30], [130, 66, 30, 30],
      [66, 34, 30, 30], [34, 34, 30, 30], [2, 34, 30, 30], [194, 2, 30, 30], [162, 2, 30, 30], [130, 2, 30, 30], [98, 2, 30, 30], [66, 2, 30, 30], [34, 2, 30, 30], [2, 2, 30, 30], [34, 2, 30, 30], [66, 2, 30, 30], [98, 2, 30, 30], [130, 2, 30, 30], [162, 2, 30, 30], [194, 2, 30, 30], [2, 34, 30, 30], [34, 34, 30, 30]
    ],
    "animations": {
      "paper0":[0, 17], "paper1":[18, 35], "paper2":[36, 53], "paper3":[54, 71], "paper4":[72, 89],
      "paper5":[90, 107], "paper6":[108, 125], "paper7":[126, 143], "paper8":[144, 161]
    }
  };
  var spritesheet = new createjs.SpriteSheet(data);
  this.sprites = [];
  for (var n = 0; n < 9; n++) {
    var sprite = new createjs.Sprite(spritesheet, "paper" + n);
    sprite.regX = 10;
    sprite.regY = 10;
    this.sprites.push(sprite);
  }
  this.ids = [0, 0, 1, 2, 3, 4, 5, 6, 7, 8];

  this.mouseChildren = false;
};

p.timer;
p.interval = 30;
p.time = 300;
p.duration = 2400;

p.start = function() {
  this.timer = setInterval(createjs.proxy(this.create, this), this.interval);
}
p.stop = function() {
  if (this.timer) {
    clearInterval(this.timer);
  }
}
p.create = function() {
  for (var n = 0; n < this.unit; n++) {
    var id = this.ids[Math.random()*this.ids.length >> 0];
    var sprite = this.sprites[id].clone();
    var scale = this.scales[Math.random()*this.scales.length >> 0];
    var paper = new Paper(sprite, scale);
    this.fall(paper);
  }
}
p.fall = function(paper) {
  var px = (Math.random() - 0.5)*this.bw;
  var a = Math.random()*360;
  if (Math.random() < 0.5) {
    ta = a - 360;
  } else {
    ta = a + 360;
  }

  paper.x = px;
  paper.y = - 25;
  paper.rotation = a;
  this.addChild(paper);

  createjs.Tween.get(paper, {override: false})
    .to({y: this.bh - 25}, this.duration, createjs.Ease.sineIn)
    .call(createjs.proxy(this.remove, this), [paper]);
  createjs.Tween.get(paper, {override: false})
    .wait(this.time*7)
    .to({alpha: 0}, this.time, createjs.Ease.linear);
  createjs.Tween.get(paper, {override: false})
    .to({rotation: ta}, this.duration, createjs.Ease.quadOut);
}
p.remove = function(paper) {
  this.removeChild(paper);
  paper = null;
}

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

}());

Paper.js
(function() {

function Paper(sprite, scale) {
  this.Container_constructor();

  this.init(sprite, scale);
}
var p = createjs.extend(Paper, createjs.Container);

p.container;
p.content;

p.init = function(sprite, scale) {
  this.container = new createjs.Container();
  this.addChild(this.container);
  this.container.scaleX = this.container.scaleY = scale;

  this.content = sprite;
  this.content.currentAnimationFrame = Math.random()*18 >> 0;
  this.container.addChild(this.content);

  this.mouseChildren = false;
};

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

}());

スプライトシートは「TexturePacker」というツールで作成。 :doki:
データ形式は「EaselJS」でパブリッシュ。(トリムモード: None)
:check: 「TexturePacker - Sprite sheet maker, image packer and optimizer | TexturePacker | Sprite sheet creation and image optimization

papers.png (縮小なし)

createjs_confetti2_papers


[修正] (15/09/20 Sun 23:56)
CreateJS 0.8.1 にバージョンアップ。