2012年7月16日月曜日

[ドリトル] 跳ね返り (円)

前の記事で跳ね返りをやったので、もう少し続けてみる。 今度は円。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -100 100 moveto pendown.
t1 ! 100 circle.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.
t1:collision = t1:bounce. 

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

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

あれ、全部まっすぐ跳ね返ってきた。
円を少し回転させてみる。ついでにタートルのサイズも少し小さくしてみよう。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -100 100 moveto pendown 0.5 scale.
t1 ! 100 circle.
t1 ! penup 0 direction movetocenter.
shape1 = t1 ! makefigure.
shape1 ! 30 rightturn.
shape1 ! (-100+50*cos(30/2)) (100 - 50*sin(30/2)) moveto. 
t1:collision = t1:bounce. 

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

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

回転した分だけ跳ね返り角度が変わっているような気がする。circle 命令で描いた円だときれいには反射してくれないようだ。
ちなみに、図形の回転は書き始めの点を始点に回転するようなので、move で動いた分を補正してある。

今度は forward 命令で円を描いてどうなるか見てみる。ドリトルの円命令は36角形だそうなので それに合わせて円を描く。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -100 100 moveto pendown 0.5 scale .
POLY = 36.
[
    t1 ! (100*cos( (180-(360/(POLY))) /2 )*2 ) forward (360/(POLY)) rightturn.
] ! (POLY) repeat.
shape1 = t1 ! makefigure.

t1 ! penup 0 direction movetocenter.

t1:collision = t1:bounce. 

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

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

やっぱりまっすぐに跳ね返ってくる。なぜだろう?
前回、「く」の字を作ったときにはうまくいったのに。

「く」の字の角度を少し変えてみよう。

t1 = Turtle ! create.

// ターゲット作成
DEG = 60.
t1 ! penup -200 100 moveto pendown (DEG) rightturn.
t1 ! (100 / sin((DEG))) forward (180-(DEG)*2) rightturn (100 / sin((DEG))) 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.
...
DEG = 30.
...

なんとなくわかった気がする。
反射する方向は、入射角と最初に引いた線の角度で決まって、その線上のどちら側に反射するかだけが実際に反射する面との相互作用で決まるということのようだ。
マニュアルに書いてある「衝突する相手が図形オブジェクトの場合、図形オブジェクトを描き始めたときの 方向が衝突する際の壁の角度として扱われます」ってこういうことだったのか。前回の「く」の字の時にうまくいったので油断したのだがたまたまだったわけだ。

ならば36角形の各辺をそれぞれ独立した図形にしてしまえばよいわけだ。

t1 = Turtle ! create.

// ターゲット作成
t1 ! penup -100 100 moveto pendown 0.5 scale .
POLY = 36.
[
    t1 ! (100*cos( (180-(360/(POLY))) /2 )*2 ) forward (360/(POLY)) rightturn.
    t1 ! makefigure.
] ! (POLY) repeat.
t1 ! penup 0 direction movetocenter.
t1:collision = t1:bounce. 

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

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

うまくいった。動かしたり色塗ったりするのは超大変だろうけど。
角に当たったりしたのかたまに微妙な跳ね返りをしているが辺の数を増やせばよいまでのこと。

...
POLY = 360.
...

360角形。これでパーフェクト。



0 件のコメント:

コメントを投稿