今回から GraphicsWindow を使ったゲームを扱っていきます。
以前このブログでも紹介した垂直スクロールゲームをゲームプログラミング解説のために少し書き換えました。プログラムID QZN342-4 として公開しました。
メイン
4つのサブルーチンを呼んでいます。タイトルは毎回バージョンを変更するので、Init() の外に出しました。デバッグ時のみ呼び出す処理を有効にするには debug = “True” を指定します。
‘ Turtle Dodger 0.6b
‘ Copyright (c) 2014 Nonki Takahashi. The MIT License.
‘
‘ History:
‘ 0.6b 2014-07-30 Changed image and sorted subroutines. (QZN342-4)
‘ 0.5b 2014-04-17 Changed to detect collision. (QZN342-3)
‘ 0.4a 2014-04-17 Added opening. (QZN342-2)
‘ 0.3a 2014-04-02 Avoided to hold while Turtle moving. (QZN342-1)
‘ 0.2a 2014-04-02 Changed for Silverlight. (QZN342-0)
‘ 0.1a 2014-04-02 Created. (QZN342)
‘
title = “Turtle Dodger 0.6b”
GraphicsWindow.Title = title
debug = “False”
Init()
Opening()
Game()
Closing()
障害物の追加
今回サブルーチンをアルファベット順に並び替えました。プログラムが長くなってくるとプログラム編集時にサブルーチンを探すのに手間取るので並び替えをしています。A で始まるこのサブルーチンから紹介します。AddObject() では上から降ってくる障害物を1つ Shapes.AddRectangle() で作成します。このサブルーチンでは Math.GetRandomNumber() を3回呼んでいます。色と位置と角度を変えるためです。
Sub AddObject
iMax = obj[“iMax”] + 1
obj[“iMax”] = iMax
GraphicsWindow.PenWidth = 1
type = Math.GetRandomNumber(3)
obj[iMax][“type”] = type
GraphicsWindow.BrushColor = color[type]
sz = size[type]
obj[iMax][“obj”] = Shapes.AddRectangle(sz, sz)
x = Math.GetRandomNumber(gw – 20) + 10
y = -20
obj[iMax][“x”] = x
obj[iMax][“y”] = y
Shapes.Move(obj[iMax][“obj”], x, y)
Shapes.Rotate(obj[iMax][“obj”], Math.GetRandomNumber(360))
EndSub
終了時の処理
カメを3回転させて、”GAME OVER” と表示します。この文字列は左右の中央にくるように計算されています。詳細についてはこちら(英語)をご覧ください。
Sub Closing
Timer.Pause()
Turtle.Turn(720)
GraphicsWindow.BrushColor = “White”
GraphicsWindow.FontName = “Trebuchet MS”
GraphicsWindow.FontSize = 40
x = (gw – 217) / 2
y = 100
GraphicsWindow.DrawText(x, y, “GAME OVER”)
Program.Delay(3000)
EndSub
ゲーム本体
ゲームの主人公はカメ (Turtle) にしました。一般的には Shapes.AddImage() などを使うことが多いと思いますが、Turtle のほうがより操作が簡単になると考えました。メインのキャラクターと降ってくる障害物を同時に動かす必要があります。メインキャラクターはマウスやキーボードのイベントで、障害物はタイマーのイベントで動かすと全体をイベント駆動型のプログラムにできます。ただイベント処理が重くなり過ぎると同時の動作に影響が出ます。また、今回は Turtle を使っているのですが、Small Basic v1.0 の問題(英語)のために、イベント処理の中で Turtle を動かすことを断念しました。
障害物との衝突がない限り While ループを回り続けます。
Sub Game
Turtle.Speed = 7
Turtle.PenUp()
x = gw / 2
y = gh – 40
GraphicsWindow.BrushColor = “White”
GraphicsWindow.FontSize = 18
score = Shapes.AddText(“0”)
Shapes.Move(score, 20, 20)
If debug Then
GraphicsWindow.BrushColor = “White”
GraphicsWindow.FontSize = 12
pos = Shapes.AddText(“(” + x + “,” + y + “)”)
GraphicsWindow.PenWidth = 1
cross1 = Shapes.AddLine(0, -8, 0, 8)
cross2 = Shapes.AddLine(-8, 0, 8, 0)
Shapes.Move(cross1, x, y)
Shapes.Move(cross2, x, y)
Shapes.Move(pos, gw – 100, 20)
EndIf
Turtle.MoveTo(x, y)
Turtle.Angle = 0
Not = “False=True;True=False;”
moving = “False”
scrolling = “False”
Ready()
GraphicsWindow.KeyDown = OnKeyDown
tick = “False”
Timer.Interval = 1000 / 24
Timer.Tick = OnTick
lastems = Clock.ElapsedMilliseconds
obj[“iMin”] = 1
While Not[cd]
If moving Then
If key = “Left” Then
Turtle.TurnLeft()
Turtle.Move(30)
Turtle.TurnRight()
ElseIf key = “Right” Then
Turtle.TurnRight()
Turtle.Move(30)
Turtle.TurnLeft()
EndIf
moving = “False”
Else
Program.Delay(100)
EndIf
EndWhile
EndSub
初期化
ウィンドウのサイズや使用する変数を初期化しています。
Sub Init
gw = 598
gh = 428
GraphicsWindow.BackgroundColor = “DodgerBlue”
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
color = “1=Orange;2=Cyan;3=Lime;”
size = “1=20;2=16;3=12;”
passed = 0
cd = “False” ’ collision detected
EndSub
(つづく)