# プログラミング授業二日目 プログラム作成補足テキスト
[toc]
イラスト利用 [てがきですの!β](https://regeld.com/desi/)
![image](https://hackmd.io/_uploads/SyirDbh2R.png =200x)
プログラミングでは、目的のものをいきなり作ろうとせずに少しずつ完成に近づけていくというやり方をすることがあります。
そのほうが常に動いているものを作っているんだなというイメージが湧いてやる気にもなりませんか?
というわけで少しずつプログラムをここから作成していきます。
## 手順1:円を描こう
![image](https://hackmd.io/_uploads/HJ_g3-2hR.png =200x)
JavaScriptではインターネットのページを表現するHTMLの中の要素部品として取り出して操作することができます。まずはHTML上に書いたCanvasオブジェクトをに丸を書くという操作をしてみましょう。
### HTML
```html=
<canvas id="myCanvas" width="400" height="400"></canvas>
```
### CSS
```css=
canvas{border:1px solid black;}
```
### Javascript
```javascript=
// Canvas要素と2Dコンテキストの取得
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// 円の初期位置と速度
let x = canvas.width / 2;
let y = canvas.height / 2;
let radius = 30;
// 円を描画する
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fillStyle = "blue";
context.fill();
context.closePath();
```
## 手順2:関数にしてみよう
![image](https://hackmd.io/_uploads/H1KhR-23A.png =200x)
円を描画するように**実際に何かする**処理は、関数化しておくことが多いです。今回は円を描画する処理を関数化してみましょう。
```javascript=
// Canvas要素と2Dコンテキストの取得
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// 円の初期位置と速度
let x = canvas.width / 2;
let y = canvas.height / 2;
let radius = 30;
let dx = 2;
let dy = -2;
// 円を描画する関数
function drawCircle(x, y, radius) {
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fillStyle = "blue";
context.fill();
context.closePath();
}
drawCircle(x, y, radius);
```
## 手順3:アニメーションさせてみよう
![image](https://hackmd.io/_uploads/B1MDxz3h0.png =200x)
プログラムまでアニメーションを実現する場合、直前の絵を削除して、少しずらした場所に新しい絵を描くという動作をさせます。
パラパラ漫画のようなかたちです。
ずらす方向を決めるための変数と、そのために描画をやり直す(再描画といいます)処理を付け足しましょう。
```javascript=
// Canvas要素と2Dコンテキストの取得
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// 円の初期位置と速度
let x = canvas.width / 2;
let y = canvas.height / 2;
let radius = 30;
let dx = 2;
let dy = -2;
// 円を描画する関数
function drawCircle(x, y, radius) {
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fillStyle = "blue";
context.fill();
context.closePath();
}
// Canvasをクリアする関数
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
// アニメーションを実行する関数
function animate() {
clearCanvas();
drawCircle(x, y, radius);
x += dx;
y += dy;
// 次のフレームをリクエスト
window.requestAnimationFrame(animate);
}
// アニメーションの開始
animate();
```
## 手順4:画面端についたら跳ね返る処理を書く
![image](https://hackmd.io/_uploads/HyLB-G32A.png =200x)
ボールが画面端に着いたら跳ね返るという処理を作成します。
ボールが画面端に着いたことを確認するには以下の4つの確認処理をすることになります。
* ボールのX(横)座標+半径がキャンバスの横幅より大きくなった
* ボールのX座標-半径が0未満になった
* ボールのY(縦)座標+半径がキャンバスの縦幅より大きくなった
* ボールのY座標-半径が0未満になった
```javascript=
// Canvas要素と2Dコンテキストの取得
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// 円の初期位置と速度
let x = canvas.width / 2;
let y = canvas.height / 2;
let radius = 30;
let dx = 2;
let dy = -2;
// 円を描画する関数
function drawCircle(x, y, radius) {
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fillStyle = "blue";
context.fill();
context.closePath();
}
// Canvasをクリアする関数
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
// アニメーションを実行する関数
function animate() {
clearCanvas();
drawCircle(x, y, radius);
x += dx;
y += dy;
// 壁に当たったら反転
if (x + radius > canvas.width || x - radius < 0) {
dx = -dx;
}
if (y + radius > canvas.height || y - radius < 0) {
dy = -dy;
}
// 次のフレームをリクエスト
window.requestAnimationFrame(animate);
}
// アニメーションの開始
animate();
```
## 手順5:クリックしたら方向を変えてみよう
![image](https://hackmd.io/_uploads/By0zQzh2R.png =200x)
最後にCanvasをクリックしたら方向転換をするという処理を実現してみましょう。
HTML上の部品はイベントハンドラというものを持っています。
これはページを見ている人が何らかの操作を行ったときに、JavaScriptのプログラムを動作させることができる仕組みです。
```javascript=
// Canvas要素と2Dコンテキストの取得
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// 円の初期位置と速度
let x = canvas.width / 2;
let y = canvas.height / 2;
let radius = 30;
let dx = 2;
let dy = -2;
// 円を描画する関数
function drawCircle(x, y, radius) {
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fillStyle = "blue";
context.fill();
context.closePath();
}
// Canvasをクリアする関数
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
// アニメーションを実行する関数
function animate() {
clearCanvas();
drawCircle(x, y, radius);
x += dx;
y += dy;
// 壁に当たったら反転
if (x + radius > canvas.width || x - radius < 0) {
dx = -dx;
}
if (y + radius > canvas.height || y - radius < 0) {
dy = -dy;
}
// 次のフレームをリクエスト
window.requestAnimationFrame(animate);
}
// クリックイベントのリスナー
canvas.addEventListener('click', () => {
dx = -dx; // 横方向の速度を反転させる
});
// アニメーションの開始
animate();
```