ページ

2012年7月15日日曜日

[ドリトル] 跳ね返り

Turtle には bounce (跳ね返る)命令があり、跳ね返り動作を簡単に記述することができる。 面白そうなので早速使ってみよう。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -200 100 moveto pendown 45 rightturn.
t1 ! (100 * sqrt(2)) forward 90 rightturn (100 * sqrt(2)) forward.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.

// Collision 動作を bounce動作に置き換える。
t1:collision = t1:bounce. 

// 一歩づつ進める。
t1:go = [ | length | 
  [ ! 1 forward ] ! (length) repeat.
].

// 初期位置を下にずらしながらターゲットに当てる。
t1 ! 1 linewidth (red) linecolor.
[ | count | 
  y = 100 - (count * 10).
  t1 ! penup 100 (y) moveto 180 direction pendown.
  t1 ! 600 go.
] ! 20 repeat.

初期位置を下にずらしながら右からタートルを当てている。ぶつかったところできれいに進行方向が変わっている。手前で跳ね返っているのはタートルの大きさによるマージン分。
「 t1:collision = t1:bounce. 」としているところは衝突時に自動的に跳ね返り動作をするようにしている。

今度は、タートルの入射位置を一定にしてターゲットを回転させる。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -200 100 moveto pendown 135 rightturn.
t1 ! (200 * sqrt(2)) forward.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.
shape1 ! create (blue) paint.  // 初期位置表示用

// Collision 動作を bounce動作に置き換える。
t1:collision = t1:bounce. 

// 一歩づつ進める。
t1:go = [ | length | 
  [ ! 1 forward ] ! (length) repeat.
].

// ターゲットを回転させながら右からターゲットに当てる。
t1 ! 1 linewidth (red) linecolor.
[ y = 0.
  t1 ! penup 200 (y) moveto 180 direction pendown.
  t1 ! 600 go.
  shape1 ! 2 leftturn. 
] ! 46 repeat.

これは楽しい。
ターゲットを青い初期位置から黒い最終位置まで90度回転させながら右からタートルを入射している。

今までは単純に跳ね返り動作をしていたが、跳ね返り前後の中間の角度に進むようにすると反射面に沿って進むようになるはず。

t1 = Turtle ! create.
t1 ! 0.1 scale.

// ターゲット作成
t1 ! penup -200 160 moveto pendown 60 rightturn.
t1 ! 300 forward.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.

// 反射方向は反射前後の中間
t1:collision = [ | what moveSelf ; preBounce  newDirection |
    preBounce = !direction?.
    ! (what) (moveSelf) bounce. 
    newDirection = ((!direction?) + preBounce) / 2.
    ! (newDirection) direction.
].

// 一歩づつ進める。
t1:go = [ | length | 
  [ ! 1 forward ] ! (length) repeat.
].

// 入射角度を変えながら右からターゲットに当てる。
t1 ! 1 linewidth (red) linecolor.
[ | count |
  y = 0.
  t1 ! penup 100 (y) moveto 180 direction pendown.
  t1 ! ((count-10)*3) leftturn.
  t1 ! 600 go.
] ! 20 repeat.

うまくいった。
右から入射角を変えながらターゲットに当てている。これなら別に衝突後に一定値を進行角度としてセットしてもよさそうだが、衝突先の向きを気にしないで済むのでこれはこれで便利だと思う。
タートルが大きいとマージンの関係で多少反射後の線がぶれるので小さくしている。

0 件のコメント:

コメントを投稿