Shapesの利用とアニメーション
Small Basic のグラフィックスにはShapesと呼ばれる面白い機能があります。グラフィックスウィンドーに例えばGraphicsWindow.DrawEllipse() やGraphicsWindow.DrawRectangle()等で描かれた円や長方形は一旦グラフィックスウィンドーに描かれると移動させたりサイズを変えたりといったことはできません。スケッチブックに色鉛筆で絵を描いてしまったようなものですね。
でも例えばゲームをプログラミングしようと思うとそういうグラフィックスを移動させたりしたくなってきますよね。疑似的に動いているように見せることはできます。どうするかと言うと、要は描いたグラフィックスを一旦消して、少し移動した場所に描きなおせばいいのです。例えば下の例で、太陽のマークのグラフィックスを右に移動させたいとします。
まずは、最初の位置の太陽を消すように背景色で塗りつぶします。黒い枠で囲ったあたりを背景色で塗りつぶせばよいですよね。
次に移動したい場所に太陽のグラフィックスを描画します。
これをくりかええばあたかも太陽のグラフィックスが左から右へ移動しているように見えるでしょう。ちなみに離れた位置に再描画すれば素早く、近い位置に再描画すればゆっくりと移動したように見えるでしょう。
では、この仕組みをつかってサンプルプログラムを作ってみました。ちょっと長いですが簡単なゲームになっています。
GraphicsWindow.Width = 800 GraphicsWindow.Height = 800 GraphicsWindow.BackgroundColor = "Black" cx = 400 cy = 400 earthR=2000 altitude = 400 ground = 600 G = 0.05 speed = 0.0 GraphicsWindow.Show() DrawStars() GraphicsWindow.BrushColor = "Blue" GraphicsWindow.FillEllipse(cx-earthR, ground, earthR*2, earthR*2) GraphicsWindow.PenColor = "Black" GraphicsWindow.MouseDown = OnMouseDown loop: GraphicsWindow.BrushColor = "Black" GraphicsWindow.FillRectangle(cx-10, ground - altitude, 20, 20) If altitude <= 0 Then If speed < 2 then GraphicsWindow.ShowMessage("無事に着地", "成功") else GraphicsWindow.ShowMessage("地面に激突", "失敗") endif Program.End() EndIf speed = speed + G altitude = altitude - speed GraphicsWindow.BrushColor = "White" GraphicsWindow.FillRectangle(cx-10, ground - altitude, 20, 20) Program.Delay(33) Goto loop Sub OnMouseDown speed = speed - 1.0 EndSub Sub DrawStars For I=0 To 4000 GraphicsWindow.SetPixel(Math.GetRandomNumber(800), Math.GetRandomNumber(800), GraphicsWindow.GetRandomColor()) EndFor EndSub
このゲームはロケットの着陸船を無事に着陸させるゲームです。そのまま放っておくと重力に引かれて次第に落下し、地面に激突してしまいます。ですので、マウスをクリックして着陸ロケットを噴射し、降下速度を落として着陸させる必要があります。まぁ、着陸船は単なる白い正方形だし、もっと凝った作りにもできるかもしれませんが、サンプルなどのこの程度で許してください。
理科で「速度と加速度」や「重力加速度」を習っていれば内容を理解しやすいかもしれませんが、そうでない場合はまぁ、色々計算している部分は適当に流し読みしてしまいましょう。
着陸船の移動ですが、(1)の箇所でブラシの色を背景の黒にして正方形を描いていますが、要はここと次の行(2)で以前に書いた白色の着陸船を消しているのです。(3)の箇所で着陸船の色である白にブラシを選択し、(4)で着陸船を描画しています。これを繰り返すことによりまるでアニメーションのように着陸船が移動しているように見えるのです。
でも、あれ?よく見てみると、着陸船が通った後、背景にあった星が消えて真っ黒になってしまっていますね。これは、当たり前と言えば当たり前で、着陸船を移動する際に単純に黒い正方形で塗りつぶしているからです。このように背景のグラフィックが消えてしまう事を防ぐテクニックももちろんあります。要は着陸船を描画する前に、そこに描画されていたグラフィックスをどこかに記憶しておいて、着陸船を消す代わりに記憶しておいたグラフィックスをつかって描画しなおしてやればよいのです。
でも、なんだか面倒だよね。
Shapesの利用
Small Basicにはこのような場面で利用できるとても便利な機能があります。それが、Shapesです。Shapes は単純な図形を格納する変数のようなものです。Shapesに図形を格納し、そのShapesをグラフィックスウィンドーの好きな位置に移動させたり拡大させたり透明度を変えたりすることができます。ちょうど、スケッチブックにシールを張るようなものです。シールをはがして別の場所に移動させれば、そのシールに描かれた図形は移動するし、スケッチブックのシールが貼ってあった箇所の図形もそのまま残っているはずです。まぁ、シールの糊がそれほど強力でなければね。
Shapesに例えば矩形(長方形)を登録するには、次のようにします。
lander = Shapes.AddRectangle(20,20)
これは、幅20、高さ20の長方形(つまり正方形)をShapesに追加し、これを"lander"という変数に格納しています。別の言い方をすると幅高さそれぞれ20の正方形をShapesとして登録し、それに"lander"という名前を付けているともいえます。
この"lander"という名前の正方形を移動するには次のようにします。
Shapes.Move(lander, x, y)
"lander"はもちろん今回作成したshapesの名前で、あとのxとyはこのShapesを移動するグラフィックスウィンドー上の座標です。
では、このShapesを使って先ほどの着陸ゲームを作り直してみましょう。
GraphicsWindow.Width = 800 GraphicsWindow.Height = 800 GraphicsWindow.BackgroundColor = "Black" cx = 400 cy = 400 earthR=2000 altitude = 400 ground = 600 G = 0.05 speed = 0.0 GraphicsWindow.Show() DrawStars() GraphicsWindow.BrushColor = "Blue" GraphicsWindow.FillEllipse(cx-earthR, ground, earthR*2, earthR*2) GraphicsWindow.PenColor = "Black" GraphicsWindow.BrushColor = "White" lander = Shapes.AddRectangle(20,20) GraphicsWindow.MouseDown = OnMouseDown loop: Shapes.Move(lander, cx-10, ground - altitude) If altitude <= 0 Then If speed < 2 then GraphicsWindow.ShowMessage("無事に着地", "成功") else GraphicsWindow.ShowMessage("地面に激突", "失敗") endif Program.End() EndIf speed = speed + G altitude = altitude - speed Program.Delay(33) Goto loop Sub OnMouseDown speed = speed - 1.0 EndSub Sub DrawStars For I=0 To 4000 GraphicsWindow.SetPixel(Math.GetRandomNumber(800), Math.GetRandomNumber(800), GraphicsWindow.GetRandomColor()) EndFor EndSub
ちょっとだけすっきりとしたかな?実際に動かしてみると分かりますが、着陸船が移動しても背景の星々は消えることはありません。
さてこのゲームですが、アイディア次第で色々と改造できると思います。例えば燃料の残量の概念を導入して着陸ロケットの噴射回数、つまりマウスをクリックできる回数を制限してみたり、時間制限を導入してみたり、等など。
試してみるといいでしょう。
Shapesにはもちろん長方形以外の図形も登録できます。工夫してみてください。