JavaScriptでシンプルに始めるクリエイティブコーディングその1

# クリエイティブコーディングとは
アートやデザインなど可視化表現のためのコーディング技法のことです。
巷に存在するコーディング環境としてはWebGLやProcessing, openFrameworksまたはArduino等が挙げられます。

これらは、現在メディアアートを始め、広告やエンターテイメントといった様々な形で人々の目に触れるようになってきています。

# この記事で何をやるか

かなり原始的なところから始めようと思います。ですので、複数回に渡って、技法を紹介していこうと考えています。
表現を実現するためにHTML5で追加された、2Dのグラフィックスを描く`<canvas>`要素を利用します。


# 「円を描いて、それを移動させる」
初回はシンプルで、円の移動のみやります。

## 円の描画
canvasをつかって円を描画するのは、以下のコードで実現できます。（最初はコピペでも動くように、html全体を記載します。以後JavaScriptのうち必要なコードのみを記載することにします。）

```html:javascript
<!DOCTYPE html>
<html>
<head>
<title>直線移動</title>
<meta charset="utf-8">
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <canvas id="canvas"></canvas>
</body>
</html>
<style type="text/css">
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  background: white;
  display: block;
  overflow: hidden;
}
</style>
<script type="text/javascript">
var canvas;

// 画面全体をcanvasにする。
(function(){
  canvas = document.getElementById('canvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
})();
var context = canvas.getContext("2d");

// 座標(100, 200)に半径10の黒色の円の描画を行う
context.beginPath();
context.arc(100, 200, 10, 0, Math.PI*2,true);
context.fillStyle = "black";
context.fill();

</script>
```

## 円を移動させるとは？
上記でまず円を描画することができたと思います。次に円を移動させたいと思います。どうやってやればいいのでしょうか。実際に、円を移動させるというよりは、円が移動しているように「見える」ように描画し続けるのです。
つまり、

円を描画する-> 消す -> 円をちょっとずらして描画する -> 消す ->....

を繰り返すことで円の移動を表現します。

## 円を移動させてみる！

コードは以下のようになります。
円の最初の位置を定義し、それを一定間隔で更新する、というコードです。

```js:JavaScript部分
// 描画される最初の位置を定義
var x = 100;
var y = 100;

var animation = function(){
  // 画面を消す
  context.clearRect(0, 0, canvas.width, canvas.height);

  // 座標(x, y)に円を描画する。
  context.beginPath();
  context.arc(x, y, 10, 0, Math.PI*2,true);
  context.fillStyle = "black";
  context.fill();

  // 実行させるたびに、座標となる変数x, yを更新する。
  x+=1;
  y+=1;
}

// animation関数を10mm secondごとに繰り返す
setInterval(animation,10);

```

上記のコードで、円が左上から右下へと移動していると思います。一定時間たつと画面外に円が出て行ってしまうので、画面端にくると跳ね返るように修正しましょう。

# 画面外にでそうになると跳ね返るように変更
まずソースコードを示します。
やってることとしては、画面の端に来たら、それまで足していた1を-1にする。そしてまた逆の画面端にきたらそれまで足していた-1を1にする。ということを行ってます。
上記説明をコードに落とし込むと、xSpeed, ySpeedという変数を用意し、変数に-１をかけるだけで済みます。

```js:JavaScript部分

var x = 100;
var y = 100;
var xSpeed = 1;
var ySpeed = 1;

var animation = function(){
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.beginPath();
  context.arc(x, y, 10, 0, Math.PI*2,true);
  context.fillStyle = "black";
  context.fill();
  x+=xSpeed;
  y+=ySpeed;

  // 画面左端、右端にくると、xSpeedの向きを入れ替える。
  if(x < 0 || x > canvas.width){
    xSpeed = xSpeed * -1;
  }

  // 画面上端、下端にくると、xSpeedの向きを入れ替える。
  if(y < 0 || y > canvas.height){
    ySpeed = ySpeed * -1;
  }
}

setInterval(animation,1);
```

ひとまず、画面を縦横無尽に移動する円が出来ました。

ただ、上記コードの場合、汎用性がないです（たとえば、100個円を作り、別々のスピードで移動させようなるとどうしようか？）。
そこでプログラミング技法であるオブジェクト指向でコードを書き直します。
ここではオブジェクト指向の詳細な説明はしません。

# （発展）オブジェクト指向で作り直してみる
上記と同じような挙動をするコードを書きました。さてちゃんと動くでしょうか？
下記コードは
Particleクラスに

- 円を移動させるメソッド
- 円の描画メソッド
- 円の画面端判定メソッド

を実装しています。

```js:JavaScript部分
// コンストラクタ
var Particle = function(x, y){
  this.x = x;
  this.y = y;
  this.vx = 1;
  this.vy = 1;
  this.size = 10;
}

// 円の移動
Particle.prototype.move = function(){
  this.x += this.vx;
  this.y += this.vy;
}

// 円の描画
Particle.prototype.draw = function(){
  context.beginPath();
  context.arc(this.x, this.y, this.size, 0, Math.PI*2,true);
  context.fillStyle = "black";
  context.fill();
}

// 円が画面端に来た時の処理
Particle.prototype.checkEdge = function(){
  // 画面外に円の一部が飛び出ないようにthis.sizeを利用
  if(this.x < this.size || this.x > canvas.width - this.size){
    this.vx = this.vx * -1;
  }

  if(this.y < this.size || this.y > canvas.height - this.size){
    this.vy = this.vy * -1;
  }
}

// 円を作る
var particle = new Particle(10,10);

var animation = function(){
  context.clearRect(0, 0, canvas.width, canvas.height);
  particle.move(); 
  particle.draw();
  particle.checkEdge();
}

setInterval(animation,1);

```

# （おまけ）100個の円を移動

説明はしませんが、コードを動かしてみてください。非常に楽しいですね。

```js:JavaScript部分
// コンストラクタ
var Particle = function(x, y){
  this.x = x;
  this.y = y;
  this.vx = Math.random() * 2 -1;
  this.vy = Math.random() * 2 -1;
  this.size = 10;
}

// 円の移動
Particle.prototype.move = function(){
  this.x += this.vx;
  this.y += this.vy;
}

// 円の描画
Particle.prototype.draw = function(){
  context.beginPath();
  context.arc(this.x, this.y, this.size, 0, Math.PI*2,true);
  context.fillStyle = "black";
  context.fill();
}

// 円が画面端に来た時の処理
Particle.prototype.checkEdge = function(){
  if(this.x < this.size || this.x > canvas.width - this.size){
    this.vx = this.vx * -1;
  }

  if(this.y < this.size || this.y > canvas.height - this.size){
    this.vy = this.vy * -1;
  }
}

// 円を作る
var particle = new Particle(10,10);

var particles = [];
for(var i=0; i < 100; i++){
  particles.push(new Particle(10,10))
}

var animation = function(){
  context.clearRect(0, 0, canvas.width, canvas.height);
  for(var i=0; i < 100; i++){
    particles[i].move(); 
    particles[i].draw();
    particles[i].checkEdge();
  }
}

setInterval(animation,1);

```

# 次回
加速度のある円の移動です。