【解説編】プログラミング講座 :: Pong ゲームを作ろう！

[【越境学習】プログラミング講座 :: Pong ゲームを作ろう！](http://qiita.com/yulii/items/6a9417807951413c255c) の解説編です。

# 越境学習とは？

自分の所属する組織の枠を自発的に __"越境"__ し、新しい学びを求めることです :raising_hand: 
このテキストは周りの方々に __"越境"__ してもらい、エンジニアの仕事を知ってもらおうと作成したモノです。 :books:

# 演習課題の解答例

- [Pong ゲーム - Scratch Project](https://scratch.mit.edu/projects/96496621/)

## 解答：ボールの動き（スコアボード含む）

![image](https://qiita-image-store.s3.amazonaws.com/0/257/ce635c11-12a0-c2ca-e01e-87165821e90f.png)

### ボールの動きの説明

ボールの反射をボールが落ちてくる向きに合わせて変える必要があります。実現したいことは単純で、

- ボールが右下に動いている場合（ボールが左から右に落ちてきた時）
    - ボールを右上に跳ね返す
- ボールが左下に動いている場合（ボールが右から左に落ちてきた時）
    - ボールを左上に跳ね返す

です。

右下、左上などの向きを数値で表現し直すと、

- ボールの向きが135の場合
    - ボールの向きを45にする
- ボールの向きが-135の場合
    - ボールの向きを-45にする

ということになります。

今回のプログラムでは、 `ボールが右下に動いている = ボールの向きがプラス`, `ボールが左下に動いている = ボールの向きがマイナス` としています。

### スコアボードの動き説明

`ボールが地面につく` の判定をここではボールの座標を使って判別しています。ボールの座標はボールの中心の座標になります。

`地面 = y座標の最小値 (-180)` なので、`ボールが地面につく = -180 + ボールの半径` となります。ただ、ボールの半径がわからなかったので、ゲームを動かして調整しながら適切な数値を見つけました。

ボールがパドルより下に落ちれば、自然とボールが地面につくので、 `ボールが地面につく = ボールの中心のy座標が -150 よりも小さくなったとき` という条件にしました。

## 解答：パドルの動き

![image](https://qiita-image-store.s3.amazonaws.com/0/257/65b873a2-06d6-00bd-4f98-bda0582c022b.png)

### パドルの動きの説明

`上下の動き = y座標` になります。

1. マウスのポインターを動かした場所に、パドルのx座標とy座標を移動する
2. パドルのy座標を `-120` に移動する

という処理を繰り返すことで、パドルの上下の動きを固定できます。

# 解説：どうやって組み立てるのか？

@yulii が自分でやってみた時の思考をそのまま垂れ流しにしておきます。

答えは複数あるので、実際に自分でやってみた時の思考順序で説明するのが良いと思います。プログラミングができるようになってもらうことは目的ではないので、思考順序を共有することで「プログラミング」という作業を体感してもらうことが大切です。

> ## プログラミング講座のゴール
> 
> プログラミングをやったことがない人に、
> 
> - プログラミングは地道な作業である
> - プログラムは思った通りに動かない（書いた通りに動く）
> - 作業は予測以上に時間がかかるものだ（ホフスタッターの法則）
> 
> ということを知ってもらう、体感してもらうこと。

## Level 1 : パドルの動きを上下固定する

![image](https://qiita-image-store.s3.amazonaws.com/0/257/b9beb868-5ec9-d8c2-8d41-8fda53e8cbab.png)

画面を見渡すと、位置を表す座標がそこかしこに見つかります。どうやら、マウスのポインターやボール、パドルには座標で位置を決めることが出来そうです。

実現したい動きは、

- マウスのポインターの動きに合わせてパドルが左右に動く
- マウスのポインターが動いても、パドルは上下に固定されている状態

です。1つ目はすでに実現しているので、2つ目をどうやって作るか？

`パドルが上下に固定されている` という表現があいまいなので、座標を使って表現すると `パドルのy座標が固定されている` です。より具体化すると `パドルのy座標がtである`（tの値はこれから調べます）。

![image](https://qiita-image-store.s3.amazonaws.com/0/257/d4673e6f-7d54-a1d4-138f-53fc10dc2a0e.png)

さて、固定したい場所の座標をどうにかして探しましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/257/7fd22bfa-dbc1-96fe-369d-2cdc921c9d84.png)

パドルをドラッグして、この辺に固定したいなーと思ったところに置きます。画面の右側に座標が表示されるので、表示されているy座標を使います。今回はキリの良い数字を見つけて `-120` を使うことにしました。

パドルの `y座標を-120にする` という動きを追加すれば出来そう。

![image](https://qiita-image-store.s3.amazonaws.com/0/257/88ac1e05-b936-00f7-4945-8730d853f4a5.png)

こんな感じ？

早速、実際に動かしてみると・・・パドルがマウスに合わせて動く！上下固定になっていない :fearful: 

順番が悪いのかしら？

![image](https://qiita-image-store.s3.amazonaws.com/0/257/6efb0618-daaf-bf5f-2c43-80d947a77208.png)

動いた！よくわからんけど、とりあえず動いた！ :flushed: 

どっちでも良さそうに見えますが、プログラムは思った通りに動かず、書いた通りに動くのです。

### 参考：このコードがなんで動いているのか分からない

実際のサービスを作ると複雑な処理も多くなり、理由はわからないけど動かなくなったり、いじっている内に何故か分からないが直ったりします。案外そんなプログラムがサービスの中で動いていたりします。

本来であれば、エンジニアとして「なぜ？」と原因や理由を調べたりするのが仕事なのですが、急いでいると細かく調べている余裕がなくて「とりあえず動いたから・・・」と原因調べるのを後回しにしちゃうこともあります。結果、それが後にバグを引き起こす原因となったりします。

そんな訳で、何かトラブルがあってもエンジニアを急かしたところで良い結果は生まないのです。
「何か進展あったら教えて」「16時になったら進展がなくても一度連絡して」など報告だけお願いして、そっとしておきましょう。

## Level 2 : ボールが地面（画面下部）についたら、スコアを0点に戻す

Level 1 を参考に、ボールのy座標を判定に使ったらうまく出来そう。
地面（画面下部）のy座標は `-180` だから、

![image](https://qiita-image-store.s3.amazonaws.com/0/257/0c96042a-ed08-e02e-e9a2-3d2ff2eae407.png)

と設定してみると・・・動かない。 :disappointed: 

思った通りに動かない時は、「なぜ動かないのか？」を想像することが大切です。ただ、実際のプログラムの状態を確認しないと、コンピューターの中でどのように解釈されているのかわからないので中身を調べてみましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/257/965d327d-98b4-08b6-b80b-7c6502378e83.png)

これがいわゆるデバッグ作業です。ゲームを動かしながら、画面に表示されたy座標を見ながら、どうすればうまく動くのか考えます。

ボールが地面についた時のy座標を正確に確認するのが出来なかったのですが、目を凝らしてy座標データを見るとおおよそ `-150` くらいになってそうです。 :eyes: 

![image](https://qiita-image-store.s3.amazonaws.com/0/257/27123658-93b7-bd3e-7c3b-0d9ba735c0ed.png)

値を変更して、再度ゲームを実行してみると・・・やっぱり動きません。 :cold_sweat: 

改めて、目を凝らしてy座標データを見ると・・・。何やら小数点らしい数字がチカチカ動いてます。どうやら、 `-150` ぴったりにはならないようです。

ボールのy座標が `-150` よりも下なら、パドルの下なので必然的に地面についてしまいます。そこで、

![image](https://qiita-image-store.s3.amazonaws.com/0/257/1f1dc0f1-3ae5-9a7d-22a7-7b05f1f12ec0.png)

と変更すると、動きました！ :blush: 

### 参考：「あと少しで出来る」と言った "あと" の道のりがとても長い

頭のなかで構想が出来上がり、「あーして、こーしたら、できるなー」と考えたものの、実際にプログラムを書き始めるとうまくいかないのです。エンジニアが「あと少し」「ほぼ終わり」と言ってたら言葉通りに受け取らず、察してください。

作業時間はなかなか読みづらいので「いつ出来ますか？」と質問するよりは「これくらいまでに出来ていると嬉しいなー。」と希望を伝えるほうが得策です。

_cf. [プログラマの嫁が知るべき97のこと](http://d.hatena.ne.jp/tt_clown/20101218/1292609206)_

## Level 3 : ボールの反射を良い感じする

Level 2 ができたら、ほぼ同じ手順で作成できるはず。まずは、ボールの向きが実際どうなっているのかを確認してみます。

![image](https://qiita-image-store.s3.amazonaws.com/0/257/55f6531a-f660-da5c-53df-0abcff229172.png)

ボールの動きを見ながら「向き」を確認すると、

- ボールが右上に動くとき、向きは `45`
- ボールが右下に動くとき、向きは `135`
- ボールが左下に動くとき、向きは `-135`
- ボールが左上に動くとき、向きは `-45`

です。

![image](https://qiita-image-store.s3.amazonaws.com/0/257/65084b3b-8905-9d8e-2bd5-275f646ebcf2.png)

今回は45度の向きでボールが動いているので、適切な方向に90度回すことで反射を実現しました。

### 参考：ちょっとした仕様変更

「ボールがパドルで反射した時の角度をちょっと変えたいんだよね？」って言われたらどうしましょう？

「ボールの軌道が予測しづらくなるとゲーム難易度が上がって楽しいと思うんだ。」とか言ってます。どうしましょう？ :fearful: 

_cf. [エンジニアの「できない」という言葉の裏側](http://konifar.hatenablog.com/entry/2015/06/07/105035)_

# おわり

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">感情表現 <a href="https://twitter.com/hashtag/illust?src=hash">#illust</a> <a href="http://t.co/vJsUyoh1nu">pic.twitter.com/vJsUyoh1nu</a></p>&mdash; シェゴ (@syego) <a href="https://twitter.com/syego/status/533927273024323585">November 16, 2014</a></blockquote>