ICSメディアの記事でCreateJSを勉強してみた


```javascript:雛形
const stage = new createjs.Stage("myCanvas");
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
stage.canvas.width = WIDTH;
stage.canvas.height = HEIGHT;

// 処理

createjs.Ticker.addEventListener("tick", handleTick);
function handleTick() {
  stage.update();
}
createjs.Ticker.timingMode = createjs.Ticker.RAF;
```

## ドラッグ＆ドロップ

デモ：https://codepen.io/mo4_9/pen/apvgvR

引用：https://ics.media/tutorial-createjs/mouse_drag.html

```javascript
// ドラッグした場所を保存する変数
let dragPointX;
let dragPointY;

target.addEventListener("mousedown", handleDown);
target.addEventListener("pressmove", handleMove);
function handleDown(event) {
    // ドラッグを開始した座標を覚えておく
    dragPointX = stage.mouseX - target.x;
    dragPointY = stage.mouseY - target.y;
}
function handleMove(event) {
    // 表示オブジェクトはマウス座標に追随する
    // ただしドラッグ開始地点との補正をいれておく
    target.x = stage.mouseX - dragPointX;
    target.y = stage.mouseY - dragPointY;
}
```



## キーボード制御

デモ：http://codepen.io/mo4_9/pen/VPeXWo

引用：https://ics.media/tutorial-createjs/keyboard_ship.html

```
let angle = 0;
let speed = 0;

window.addEventListener("keydown", handleKeyDown);
function handleKeyDown(evt) {
  evt.preventDefault();
  const keyCode = evt.keyCode;
  console.log(evt.keyCode, angle, speed);
  switch (keyCode){
    case 39: angle += 5; break; // 右
    case 37: angle -= 5; break; // 左
    case 40: speed -= 1; break; // 下
    case 38: speed += 1; break; // 上
  }
}

createjs.Ticker.addEventListener("tick", handleTick);
function handleTick() {
  ship.rotation = angle;

  // 回転しても前後を保つ
  const radian = angle * Math.PI/180;
  const vx = speed * Math.cos(radian);
  const vy = speed * Math.sin(radian);
  ship.x += vx;
  ship.y += vy;

  // 摩擦（これがないと止まらない）
  speed *= 0.90;

  // 画面端の処理
  if (ship.x < 0) { ship.x = 0; }
  if (ship.x > stage.canvas.width) { ship.x = stage.canvas.width; }
  if (ship.y < 0) { ship.y = 0; }
  if (ship.y > stage.canvas.height) { ship.y = stage.canvas.height; }

  stage.update();
}
```

## 当たり判定

デモ：http://codepen.io/mo4_9/pen/RKryYj

引用：https://ics.media/tutorial-createjs/hittest.html

```
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick() {

  （省略）
  
  // 当たり判定
  for (let i = 0; i < starList.length; i++) {
    const star = starList[i];
    const point = ship.localToLocal(0,0,star);
    const isHit = star.hitTest(point.x, point.y);
    if(isHit) alert("game over!");
  }

  stage.update();
}
```

## 画像表示、マスク

デモ：http://codepen.io/mo4_9/pen/qRNBNK
↑八の字サーチライトにしてみた

引用：
https://ics.media/tutorial-createjs/bitmap.html
https://ics.media/tutorial-createjs/slideshow.html

```javascript
const maskShape = new createjs.Shape();
maskShape.set({
    x        : 20,
    y        : 20,
    graphics : new createjs.Graphics().beginFill("#FFF").drawEllipse(0,0,300,200)
})
bitmap.set({
    mask : maskShape
});
```

## アナログ時計

デモ：http://codepen.io/mo4_9/pen/OWMExG

引用：https://ics.media/tutorial-createjs/clock.html

```javascript
// 目盛り
// 極座標:半径と角度の2つのパラメーターでXY座標を決定できる数学上の計算方法
const STEPS = 60;
for(let i = 0; i < STEPS; i++) {
  const radian = getRadian(STEPS, i);
  const startX = (RADIUS-10) * Math.cos(radian);
  const startY = (RADIUS-10) * Math.sin(radian);
  const endX = RADIUS * Math.cos(radian);
  const endY = RADIUS * Math.sin(radian);
  bg.graphics
    .setStrokeStyle(1)
    .beginStroke("#666")
    .moveTo(startX, startY)
    .lineTo(endX, endY);
}

function getRadian(steps, index, diff = 0) {
  const angle = index * (360/steps) - diff; // diff:開始座標をずらす
  const radian = angle * Math.PI / 180;
  return radian;
}

```

## Tween

デモ：http://codepen.io/mo4_9/pen/KaVBGQ

引用：https://ics.media/tutorial-createjs/tween_api.html

`loop`, `to`, `wait`, `call`を抑える

```javascript
createjs.Tween.get(circle, {loop: true})
  .to({x: WIDTH/2, y: HEIGHT, alpha: 0.5}, 1000, createjs.Ease.bounceOut)
  .wait(1000)
  .call(step1)
  .to({x: 0, y: HEIGHT/2, alpha: 0.9}, 500, createjs.Ease.cubicOut)
  .to({x: WIDTH, y: 0, alpha: 0}, 500);

function step1(){
  circle.graphics.clear().beginFill("blue").drawCircle(0, 0, 50);
}
```

> 参考
http://createjs.com/docs/tweenjs/classes/Tween.html

## 三角関数

デモ：http://codepen.io/mo4_9/pen/MJKqGM

引用：https://ics.media/tutorial-createjs/math_basic.html

### 向きを変える

差分 = 向かせたい方向 - 向かせたい対象
ラジアン = Math.atan2(差分.y, 差分.x);
向かせたい対象の角度をラジアンで更新する

### 距離を測る

三平方の定理：斜辺の長さ（ここでは距離） = 三角形の底辺と高さをそれぞれ二乗したものを足し算した平方根

```math:三平方の定理
c = \sqrt{a^2+b^2}
```


```javascript
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick() {
  stage.update();
  // arrowとmouseの差分
  const dx = stage.mouseX - arrow.x;
  const dy = stage.mouseY - arrow.y;
  // 距離（三平方の定理）
  const distance = Math.sqrt(dx * dx + dy * dy);
  label.text = distance + "px";
  // 差分をもとに方向を計算
  const radians = Math.atan2(dy, dx);
  const degrees = radians * 180 / Math.PI;
  // 線を引く
  shape.graphics.clear()
    .setStrokeStyle(1).beginStroke("#f00")
    .moveTo(arrow.x, arrow.y)
    .lineTo(stage.mouseX, stage.mouseY)
  
  arrow.rotation = degrees;
}
```

### sin波

デモ：http://codepen.io/mo4_9/pen/egZBoW
↑色も変えてみた

引用：
https://ics.media/tutorial-createjs/math_trigonometry.html
https://ics.media/tutorial-createjs/color_hsl.html



```javascript
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick() {
  px += speedX;
  // centerY=150, range=75のとき
  // 75 ~ 225をなめらかに返す
  const py = centerY + Math.sin(angleY) * range;
  angleY += speedY; // 角度更新
  shape.graphics.lineTo(px, py);
  stage.update();
}
createjs.Ticker.timingMode = createjs.Ticker.RAF;
```

## サウンド

引用：https://ics.media/tutorial-createjs/sound.html

```javascript
createjs.Sound.registerSound("sound/sound01.mp3", "clickSound01");
createjs.Sound.registerSound("sound/sound02.mp3", "clickSound02");
createjs.Sound.registerSound("sound/sound03.mp3", "clickSound03");

function playSound01() { createjs.Sound.play("clickSound01"); }
function playSound02() { createjs.Sound.play("clickSound02"); }
function playSound03() { createjs.Sound.play("clickSound03"); }

document.getElementById("sound01").addEventListener("click", playSound01, false);
document.getElementById("sound02").addEventListener("click", playSound02, false);
document.getElementById("sound03").addEventListener("click", playSound03, false);
```

## 物理演算

ドラッグしている間は、物理演算を無効
ドラッグしていない間に、物理演算（重力と摩擦）を適用

デモ：http://codepen.io/mo4_9/pen/QdNvGX

引用：https://ics.media/tutorial-createjs/ball.html

## フラクタル図形

デモ：
シェルピンスキーのギャスケット：http://codepen.io/mo4_9/pen/PWzoOo
２進木アニメーション：http://codepen.io/mo4_9/pen/rjLaVZ

> 参考
[フラクタル図形とは（JavaScript版）](http://k-ichikawa.blog.enjoy.jp/etc/HP/js/fractal/fra0.html)


続く・・・