プチコン3号 21日目 SmileBASICでOOP(4)サンプル

pc21-1.jpg

前回までで、オブジェクト指向(風)プログラミングに必要な関数は一通りそろいましたので、使い方をサンプルでお見せします。
例題は

・スライドパッドで自機移動
・Aボタンで弾発射

という、作りかけのシューティングゲームみたいなものです。

プチコン3号本体の命令としては、3日目で書いたボタン入力、15日目で書いたスプライトのアニメーション(移動)を使います。
今回は特に説明はしませんので、上記の記事を参照してください。

おさらいになりますが、オブジェクト指向用の関数・命令として以下のものがあります。
詳細は以前の記事を参照してください。

・クラス作成
SP_NEWCLASS(“クラス名称”,インスタンスの最大数)
返り値:クラスオブジェクト(作成失敗時は_S_NULL)

・オブジェクト生成
SP_NEWOBJECT(クラスオブジェクト)
返り値:インスタンスオブジェクト(作成失敗時は_S_NULL)

・オブジェクト廃棄
SP_FREE インスタンスオブジェクト

・オブジェクトの状態チェック
SP_ISACTIVE(オブジェクト)
返り値:アクティブ(表示等更新要)ならTRUE、非アクティブならFALSE

・オブジェクトの表示等更新処理
UPDATE_クラス名称 オブジェクト
(SP_UPDATEから呼び出される)

今回のサンプルでは、「自機」「弾」の2つのクラスを作成します。

自機のインスタンスは、プログラム開始時に1つ生成します。
自機はスライドパッドで移動し、Aボタンで弾を発射します。

弾のインスタンスは、自機が生成します。
弾はアニメーションで勝手に画面外へ向かって飛んでいきます。
弾オブジェクトは、毎回座標をチェックし、画面外へ出ていたら自らを廃棄します。

pc21-2.jpg

メインプログラムは以下のようになります。

VAR _MY,_SHOT

_MY     =SP_NEWCLASS("MY",    1)
_SHOT   =SP_NEWCLASS("SHOT",  5)

VAR I

MY_NEWSHIP
WHILE TRUE
FOR I=0 TO __MAXOBJ-1
IF SP_ISACTIVE(I) THEN SP_UPDATE I
NEXT
VSYNC 1
WEND

まず自機のクラス”MY”と弾のクラス”SHOT”を生成し、それぞれクラスオブジェクトを_MYと_CLASSに代入しています。
自機のインスタンスは最大1、弾のインスタンスは最大5つのリソースを確保しています。
(本来ここで_MYや_SHOTが_S_NULLになっていないかチェックが必要ですが、今回は省略します。)

MY_NEWSHIPは_MYのインスタンスを生成する命令ですが、後で説明します。

ループの中ではアクティブな全てのオブジェクトの更新を行っています。
この部分は作成した全てのクラスで有効です。
クラス固有の処理はUPDATE_クラス名のほうで記述します。

自機のクラス_MYに関連する処理は以下のようになります。

DEF MY_NEWSHIP
VAR SP
SP=SP_NEWOBJECT(_MY)
IF SP != _S_NULL THEN
SPCHR SP,3311
SPOFS SP,_SCW>>1,200
ENDIF
END

DEF UPDATE_MY SELF
VAR SX,SY,X,Y,B
STICK OUT SX,SY
SPOFS SELF OUT X,Y
X=MIN(_SCW-8,MAX(X+SX*8,8))
Y=MIN(_SCH-8,MAX(Y-SY*8,100))
SPOFS SELF,X,Y,1

B=BUTTON(1)
IF B AND 16 THEN
NEW_SHOT X,Y,60
ENDIF
END

MY_NEWSHIPで_MYの新しいインスタンスを生成しています。
オブジェクトは実際にはスプライト管理番号ですので、生成したオブジェクトをそのままスプライト管理番号として、キャラクタと座標を設定しています。
_SCWは掲載していない部分で定義しており、スクリーンの横方向ピクセル数-1(399)です。

メインプログラムのSP_UPDATEを介して、UPDATE_MYが呼び出されます。
UPDATE_MYは、クラス_MYのインスタンスメソッドの位置づけです。

インスタンスメソッドの引数SELFにはオブジェクト自身が入っています。
このオブジェクトがクラス_MYのインスタンスであることは保証されています。
オブジェクト指向言語では、SELFはパラメータではなく主体なので、SELF.SP_UPDATEというような書き方をしますが、BASICではパラメータにせざるを得ません。

UPDATE_MYの処理はスライドパッドによる自機の移動と、Aボタンを押したときの弾の発射です。
弾オブジェクトの生成はNEW_SHOTで行っています。
NEW_SHOTのパラメータは初期座標とY軸方向の移動速度の逆数(240ピクセル移動するのに要する時間を1/60秒単位で示した数。60なら1秒で240ピクセル移動)です。

弾のクラス_SHOTに関するコードを以下に示します。

DEF NEW_SHOT X,Y,SPEED
VAR SP
SP=SP_NEWOBJECT(_SHOT)
IF SP != _S_NULL THEN
SPCHR SP,3353
SPOFS SP,X,Y
SPANIM SP,"XY+",-SPEED,0,-240,1
ENDIF
END

DEF UPDATE_SHOT SELF
VAR X,Y
SPOFS SELF OUT X,Y
IF Y < 0 THEN SP_FREE SELF
END

NEW_SHOTで弾のクラス_SHOTの新しいインスタンスを生成しています。
そして、座標とアニメーションの設定を行っています。

メインプログラムのSP_UPDATEを介して、UPDATE_SHOTが呼び出されます。
UPDATE_MYはクラス_SHOTのインスタンスメソッドです。

弾オブジェクトはSPANIMで移動させていますので、移動処理は不要です。
現在の座標を取得して、Yが負(画面上端に到達)ならばオブジェクトを廃棄しています。

クラス_SHOTの生成時に、インスタンス数を最大5に指定していますので、弾は5発まで連射可能です。
5発とも画面内に存在している間は、NEW_SHOTからSP_NEWOBJECTを呼び出したときに_SP_NULLが返りますので、新しい弾オブジェクトを生成できません。

「OOP風」プログラムのサンプルは以上です。
「BASICで無理やりOOPをやろうとしている」という雰囲気は感じていただけたでしょうか。

コメント