Small BASICで簡単ブロック崩しを作ったよ

2010/3/11 48310hit

窓の杜を見てたらSmallBASICって言語が紹介されていた。
ということで、早速ブロック崩しを作ってみたんだけど、
インストールから作成までが一日で出来るほどの簡単ぷりだったので作り方を紹介してみる。

完成図 SmallBASICはさっぱり知らない状態から数時間でブロック崩しが出来ちゃった。
ブロック崩しを作ってみました


Windows用Basicと言えばVisualBasicを思い出すけれど、実際にブロック崩しを作ってみるとVisualBasicより、もっとシンプルなN88 Basicやファミリーベーシックに近い感じがした。

※N88 Basicはかつてパソコン入門書とかにも載ってた超簡単プログラム言語)
 ファミリーベーシックはファミコンで動くBasic

VisualBasicで初心者が躓きやすい部分が隠されて、かなり取っつき易くなっている。

コンピュータを趣味程度に何か作ってみたいとか
初めてコンピューターゲームを作ってみたいと思う小学生たち、あるいはRPGツクールのような簡易ゲームエディタから次のステップとしても良さそう。

SmallBASICのインストール方法とブロック崩しの作り方

Small BASICの入手方法
Small BASICは無料で公開されている。
http://msdn.microsoft.com/en-us/ff384126.aspxでDownload Small BASICをクリック

ダウンロードしたインストーラを実行する。
Welcome to the Microsoft Small Basic v0.8 Setup Wizardが表示されたら
Nextをクリック

License Agreementが表示され承認するなら
I AgreeにチェックしNextをクリック

Select Installation Folderが表示されたら
インストール先を選択して
全ユーザが使用するならEveryone
インストールしたユーザーのみが使用するならJust meにチェックを入れてNextをクリック
途中でUACの確認画面が出たらOKを選択。
Installation Completeが表示されたらCloseをクリックでインストール完了

プログラムの実行
言語毎にショートカットが作られるので実行時は注意が必要
Small BASICを日本語で起動するにはスタートメニューから
「Small Basic」-「Localized」-「Microsoft Small Basic(Japanese)」を実行する。
(次回からは「Small Basic」-「Microsoft Small Basic」を直接実行してもOK)


動作画面はこんな感じで、VisualBasicと比べると随分とグラフィカルになってる。
特にトグル風に入力候補が表示されるのが目を引いた
SmallBASIC実行画面

ボタンの少なさも特筆的で
ファイルとクリップボードを除くSmall Basic特有のボタンは
インポート、発行、実行、等級をつけるの4つだけ

それぞれ、
インポートはMicrosoft Small Basic Program Listing上にあるプログラムをインポートする。
発行は逆にプログラムをMicrosoft Small Basic Program Listing上にアップロードする。
パフォーマンスは落ちるけれどSilverlightが入っていればブラウザ上で実行できる。
実行はプログラムをローカルで実行する Webで実行するのと違ってexeで実行されるのでパフォーマンスが良い
等級をつける(誤訳と思われる)はVisualBasicに出力できる

プログラムがWebでも実行できるあたりもScrachっぽい

言語はVisualBasicに近いけれど削られている部分もあって、
関数に引数を持たせられないとか、Functionが定義出来ないとかはビックリした。(方法を見つけられてないだけか?)

文法上の簡素さを保つために、Goto文とかグローバル変数だとか普通の言語だと汚いとされている方法が推奨されている感じがする。

逆に描画したオブジェクトがそのままクラスになって後から変更可能とかは素敵な仕様だと思う。
おかげで今回作ったブロック崩しでも関数すら使っていないのにソースコードが凄く少ないし、自然とオブジェクト指向になってる。

と言うことでブロック崩しのソースコードを解説

もっと簡単なプログラム HelloWorld!についての紹介も書きました。
初めてプログラムを作る人はHelloWorld!から見ることをオススメします。


GraphicsWindow.MouseMove = OnMouseMove
GraphicsWindow.MouseUp = OnMouseUp

マウス移動時とマウスクリック時のイベントハンドラを設定。
イベント = 処理する関数
と設定するだけ シンプル


width = 640
height = 480
padSize = 120
BOX_WIDTH = 64
BOX_HEIGHT = 24
halfPadSize = padSize/2

変数のセット。Basic同様変数を定義する必要はないけれど、
初期値が設定されていない変数を読み込もうとするとコンパイル時にエラーになる。
Const(定数)は使えないぽい


start:

Goto文で飛ばすためのラベル。
VBではエラーハンドリングぐらいにしか使われないGotoだけど、
マニュアルにはループにGotoを使っていたりしてN88っぽい
GotoでパスタになるようなプログラムはSmall BASICの出番じゃないんだろうな


GraphicsWindow.Clear()
GraphicsWindow.BrushColor = "White"
GraphicsWindow.DrawText(2,420,"Click to end")
GraphicsWindow.BackgroundColor = "Black"
GraphicsWindow.BrushColor = "Orange"
GraphicsWindow.PenWidth = 0

画面を描画するためにはGraphicsWindowオブジェクトを使う。
Clear()で画面を消し
BrushColor = "White"で描画色を白にセット
DrawText(2,420,"Click to end")で画面上 横2 縦420の位置にClick to endと出力
BackgroundColor = "Black"で画面の背景色を黒にする。
BrushColor = "Orange" 打ち返すパッドを作るために塗りつぶし色をオレンジにする
PenWidth = 0 枠線の幅を0にして枠を描画しない


pad = Shapes.AddRectangle(padSize, 12)

幅padSize、高さ12pxの長方形を変数padに設定する。
単に長方形が描画されるだけじゃなくて、padに長方形のインスタンスが格納される。
一回作っちゃえばpadのプロパティをいじって位置を変更したりも出来る

ブロックを作る。

GraphicsWindow.BrushColor = "Red"
boxCount = 0
For r = 0 to 9
 繰り返す処理
EndFor

Forでの繰り返しはBasic同様
For 変数名 = 初期値 To 終了値 [Step 増分値]
 繰り返し処理


box[r][c] = Shapes.AddRectangle(BOX_WIDTH-2,BOX_HEIGHT-2)

配列は添え字を[]でつけるのに注意
ここでは、作ったブロックを2次元配列に格納している
添え字を並べれば多次元配列もいけるし、初期化する必要もない

boxEnable[r][c] = "True"

ブロックが存在するかのチェックをBooleanで登録する。
Trueをダブルクオーテーションでくくるのに要注意


Shapes.Move(box[r][c],r*BOX_WIDTH+1,c*BOX_HEIGHT+1)

作成したブロックを並べる。
Shapes.Move(オブジェクト、横位置、縦位置)とするだけでオブジェクトを好きな位置に移動できる。
消去や再描画を考える必要がない


GraphicsWindow.Width = width
GraphicsWindow.Height = height

画面サイズを設定している。


runState = "True"
While(runState)
 繰り返す処理
EndWhile

While(条件)での繰り返し処理も可能。
今回は繰り返しの終了時はGoToで飛ばすようにしてみた



ySpeed = ySpeed + g
If ySpeed > maxYSpeed Then
ySpeed = maxYSpeed
EndIf
If ySpeed < -maxYSpeed Then
ySpeed = -maxYSpeed
EndIf
If xSpeed > maxXSpeed Then
xSpeed = maxXSpeed
EndIf
If xSpeed < -maxXSpeed Then
xSpeed = -maxXSpeed
EndIf
x = x + xSpeed
y = y + ySpeed

ボールの座標に速度を足してボールを移動している。
最高速度をセットすることで速くなりすぎないようにしている

If (x+SIZE+xSpeed >= width or x <= 0) Then
Sound.PlayClick()
xSpeed = -xSpeed
If x<=0 Then
x=1
Else
x=width-SIZE -1
EndIf
EndIf
If (y <= 0) Then
Sound.PlayClick()
ySpeed = -ySpeed
y=1
EndIf

壁に当たってボールが跳ね返る処理
Sound.PlayClick()は組み込みのクリック風の音を再生する。
もちろんPC内の音声ファイルを再生することもできる。


padY = Shapes.GetTop (pad)
padX = Shapes.GetLeft(pad)

パッドの座標を取得する。
特にプログラムしたわけでもないのに、あっさり好きな位置の座標が取得できるのが凄い


If (y+SIZE > padY and x+SIZE >= padX and x <= padX + padSize) Then
Sound.PlayClick()
padPoint = ((x + HALF_SIZE )-(padX+halfPadSize))
ySpeed = -(ySpeed*0.50 + (halfPadSize+SIZE-Math.Abs(padPoint))/30)
xSpeed = xSpeed + padPoint/20
y = padY-SIZE
EndIf

パッドとボールの衝突判定
座標を元に、パッドの中間位置に近いほど高く、
端に近いほど横に飛ぶように設定する。

Shapes.Move(ball, x, y)

新しい座標を指定するだけでボールが移動する。


xIndex1 = Math.Floor(x / BOX_WIDTH)
yIndex1 = Math.Floor(y / BOX_HEIGHT)
xIndex2 = Math.Floor((x+SIZE) / BOX_WIDTH)
yIndex2 = Math.Floor((y+SIZE) / BOX_HEIGHT)
xCrash = 0
yCrash = 0
If boxEnable[xIndex1][yIndex1] Then
xCrash = 1
yCrash = 1
EndIf
If boxEnable[xIndex2][yIndex1] Then
xCrash = xCrash-1
yCrash = yCrash+1
EndIf
If boxEnable[xIndex1][yIndex2] Then
xCrash = xCrash+1
yCrash = yCrash-1
EndIf
If boxEnable[xIndex2][yIndex2] Then
xCrash = xCrash-1
yCrash = yCrash-1
EndIf
If boxEnable[xIndex1][yIndex1] Then
Sound.PlayClick()
boxEnable[xIndex1][yIndex1]="False"
Shapes.Remove(box[xIndex1][yIndex1])
boxCount = boxCount -1
EndIf
If boxEnable[xIndex2][yIndex1] Then
Sound.PlayClick()
boxEnable[xIndex2][yIndex1]="False"
Shapes.Remove(box[xIndex2][yIndex1])
boxCount = boxCount -1
EndIf
If boxEnable[xIndex1][yIndex2] Then
Sound.PlayClick()
boxEnable[xIndex1][yIndex2]="False"
Shapes.Remove(box[xIndex1][yIndex2])
boxCount = boxCount -1
EndIf
If boxEnable[xIndex2][yIndex2] Then
Sound.PlayClick()
boxEnable[xIndex2][yIndex2]="False"
Shapes.Remove(box[xIndex2][yIndex2])
boxCount = boxCount -1
EndIf
If boxCount = 0 Then
Goto GameClear
EndIf
If xCrash <> 0 Then
xSpeed = -xSpeed * 0.9
EndIf
If yCrash <> 0 Then
ySpeed = -ySpeed * 0.9
EndIf

ブロックとボールの衝突判定
ボールの当たり具合でどのようにはじくのかを設定している。
※詳しく知りたい場合はAndroidでブロック崩しを見てね

If boxCount = 0 Then
Goto GameClear
EndIf

でボールの数が0個になったらクリア処理を行う


Program.Delay(7)

ボールの速度を調整するためにプログラムを一瞬停止している。

If (y > height) Then
Goto GameOVer
EndIf

ボールが奈落に落ちたらゲームオーバー処理を行う。


GameOver:
Sound.PlayBellRing()
GraphicsWindow.ShowMessage("You Lose", "GAME OVER")
Goto start

ゲームオーバーのメッセージを表示してスタートへ

GameClear:
Sound.PlayChime()
GraphicsWindow.ShowMessage("You Win", "CLEAR")
Goto start

ゲームクリアのメッセージを表示してスタートへ


Sub OnMouseMove
paddleX = Mouse.MouseX
Shapes.Move(pad, paddleX - padsize/2, GraphicsWindow.Height - 12)
EndSub

冒頭で設定したマウスが移動したときに呼ばれる処理。
マウスの座標を元にパッドを移動する。


Sub OnMouseUp
Program.End()
EndSub

マウスがクリックしたときに呼ばれる処理
プログラムを終了させる。


ソースコード全文は以下

GraphicsWindow.MouseMove = OnMouseMove
GraphicsWindow.MouseUp = OnMouseUp
width = 640
height = 480
padSize = 120
BOX_WIDTH = 64
BOX_HEIGHT = 24
halfPadSize = padSize/2
start:
GraphicsWindow.Clear()
GraphicsWindow.BrushColor = "White"
GraphicsWindow.DrawText(2,420,"Click to end")
GraphicsWindow.BackgroundColor = "Black"
GraphicsWindow.BrushColor = "Orange"
GraphicsWindow.PenWidth = 0
pad = Shapes.AddRectangle(padSize, 12)

GraphicsWindow.BrushColor = "Red"
boxCount = 0
For r = 0 to 9
For c = 0 To 8
box[r][c] = Shapes.AddRectangle(BOX_WIDTH-2,BOX_HEIGHT-2)
boxEnable[r][c] = "True"
Shapes.Move(box[r][c],r*BOX_WIDTH+1,c*BOX_HEIGHT+1)
boxCount = boxCount + 1
EndFor
Endfor

GraphicsWindow.Width = width
GraphicsWindow.Height = height
x = width /2
y = height /2
xSpeed = 0
ySpeed = 0

SIZE = 16
HALF_SIZE = SIZE / 2
maxYSpeed = 6
maxXSpeed = 2
x = width/2
y = width/2
g = 0.015
GraphicsWindow.BrushColor = "White"
GraphicsWindow.PenColor="White"
ball = Shapes.AddEllipse(SIZE, SIZE)

runState = "True"
while(runState)
ySpeed = ySpeed + g
If ySpeed > maxYSpeed Then
ySpeed = maxYSpeed
EndIf
If ySpeed < -maxYSpeed Then
ySpeed = -maxYSpeed
EndIf
If xSpeed > maxXSpeed Then
xSpeed = maxXSpeed
EndIf
If xSpeed < -maxXSpeed Then
xSpeed = -maxXSpeed
EndIf
x = x + xSpeed
y = y + ySpeed
If (x+SIZE+xSpeed >= width or x <= 0) Then
Sound.PlayClick()
xSpeed = -xSpeed
If x<=0 Then
x=1
Else
x=width-SIZE -1
EndIf
EndIf
If (y <= 0) Then
Sound.PlayClick()
ySpeed = -ySpeed
y=1
EndIf
padY = Shapes.GetTop (pad)
padX = Shapes.GetLeft(pad)

If (y+SIZE > padY and x+SIZE >= padX and x <= padX + padSize) Then
Sound.PlayClick()
padPoint = ((x + HALF_SIZE )-(padX+halfPadSize))
ySpeed = -(ySpeed*0.50 + (halfPadSize+SIZE-Math.Abs(padPoint))/30)
xSpeed = xSpeed + padPoint/20
y = padY-SIZE
EndIf
Shapes.Move(ball, x, y)
xIndex1 = Math.Floor(x / BOX_WIDTH)
yIndex1 = Math.Floor(y / BOX_HEIGHT)
xIndex2 = Math.Floor((x+SIZE) / BOX_WIDTH)
yIndex2 = Math.Floor((y+SIZE) / BOX_HEIGHT)
xCrash = 0
yCrash = 0
If boxEnable[xIndex1][yIndex1] Then
xCrash = 1
yCrash = 1
EndIf
If boxEnable[xIndex2][yIndex1] Then
xCrash = xCrash-1
yCrash = yCrash+1
EndIf
If boxEnable[xIndex1][yIndex2] Then
xCrash = xCrash+1
yCrash = yCrash-1
EndIf
If boxEnable[xIndex2][yIndex2] Then
xCrash = xCrash-1
yCrash = yCrash-1
EndIf
If boxEnable[xIndex1][yIndex1] Then
Sound.PlayClick()
boxEnable[xIndex1][yIndex1]="False"
Shapes.Remove(box[xIndex1][yIndex1])
boxCount = boxCount -1
EndIf
If boxEnable[xIndex2][yIndex1] Then
Sound.PlayClick()
boxEnable[xIndex2][yIndex1]="False"
Shapes.Remove(box[xIndex2][yIndex1])
boxCount = boxCount -1
EndIf
If boxEnable[xIndex1][yIndex2] Then
Sound.PlayClick()
boxEnable[xIndex1][yIndex2]="False"
Shapes.Remove(box[xIndex1][yIndex2])
boxCount = boxCount -1
EndIf
If boxEnable[xIndex2][yIndex2] Then
Sound.PlayClick()
boxEnable[xIndex2][yIndex2]="False"
Shapes.Remove(box[xIndex2][yIndex2])
boxCount = boxCount -1
EndIf
If boxCount = 0 Then
Goto GameClear
EndIf
If xCrash <> 0 Then
xSpeed = -xSpeed * 0.9
EndIf
If yCrash <> 0 Then
ySpeed = -ySpeed * 0.9
EndIf
Program.Delay(7)
If (y > height) Then
Goto GameOVer
EndIf
EndWhile

GameOver:
Sound.PlayBellRing()
GraphicsWindow.ShowMessage("You Lose", "GAME OVER")
Goto start

GameClear:
Sound.PlayChime()
GraphicsWindow.ShowMessage("You Win", "CLEAR")
Goto start

Sub OnMouseMove
paddleX = Mouse.MouseX
Shapes.Move(pad, paddleX - padsize/2, GraphicsWindow.Height - 12)
EndSub
Sub OnMouseUp
Program.End()
EndSub


Exe版の実行イメージ
SmallBasicでブロック崩し

ブラウザ上でプログラムを実行する
要Silverlight ※音が鳴ります


ソースコードを保存したフォルダにExeも出来るのでExeを実行も可能です。
Exe版ダウンロード
要SmallBasicLibrary.DLL



最近はプログラム言語が複雑になって初心者が取っつきづらくなっているから、こういう掴みやすくて結果が出やすい言語って凄く素敵だと思う。

「ネットやメール」しかしないなんてもったいないよ

前:テルマエ・ロマエ 一巻 次:初めてのプログラム 1日目 SmallBASICでHelloWorld

関連キーワード

[簡易言語][SmallBasic]

コメント

名前:名無しさん|投稿日:2011/11/04 11:54

ダウンロードしたものを実行したら、”Welcome to the Microsoft Small Basic v0.8 Setup Wizard”の「v0.8」の部分が「v1.0」になっているのですが、この場合はどうすればいいのでしょうか?

名前:falcon|投稿日:2012/04/11 21:48

すごいですね僕にわできないですよ
良ければおしえてください
たくさん遊びました
楽しかったです
以上

名前:名無しさん|投稿日:2012/04/23 09:46

環境によりマウスとパドルの位置関係がおかしくなるようです。
パドルが左端までいかないorそもそも表示されない。
タスクバーのが一つの要因みたいですが、それだけではないようで。

名前:名無しさん|投稿日:2013/10/01 14:30

俺(小学生だけど)はアクションの基本部分(地面・着地、操作)に挑戦中。
いやあ実に面倒くさい。
配列やスタックはつか・・ってスタック要るかね

名前:名無しさん|投稿日:2013/10/01 14:34

っていうか二次元配列なんてものがあるのか
ただ一次元でほぼ十分な気がする・・

名前:Kenz|投稿日:2013/10/09 19:58

二次元配列はX座標とY座標を保持するなど座標系の取り扱いとかで便利ですが
慣れると一次元配列で事足りることが多いですね

名前:名無しさん|投稿日:2013/11/14 14:32

作ってみた。
JPZ021
タートルムーバー。まだ完成版の半分程度(コードによるセーブ・ロード機能も作る予定)ですが。
がんばる。

名前:名無しさん|投稿日:2013/11/14 14:34

アップしたけど重いからインポートしてやった方がいいかもしれない。

名前:kenz|投稿日:2013/11/16 09:52

おぉ すごい!

名前:名無しさん|投稿日:2017/04/11 19:53

ループしてますよ。

名前:kenz|投稿日:2017/04/14 08:13

はいループさせています

コメントを投稿する

名前URI
コメント