1MAP-STG 敵種類を複数化しよう


2018年 6月22日
 
 
 ver.0.007


 
 今回はまとめたものを zipファイルにしました。

 表示の 0.006を 0.007にし忘れてますが、最後に気づいてもうめんどくさいのでそのままです。

 プログラムやった事のある人なら分かってもらえると思いますけど、バグは必ずある(笑)
 
 
 今回は敵の種類を 3種類にした。

 バギーまたはバイクのイメージ

 戦車のイメージ

 要塞のイメージ

 今回はまだアルゴリズム(挙動のプログラム)自体は全部自機に向かう直線運動だけで変化は無い。
 
 
 合わせてソースが長くなったので、この辺でいつものフォーマット(プログラム構造)を使う事にした。


 
 
 こんな感じでソースファイルを分割する


 
 
 main.hspがメインソースで、ここに put.hsp、shot.hsp、ene.hsp、syoki.hspを #inculude(インクルード、取り込み、この場所にそのファイルのソースを置き換える)する。

 put=表示関係全部
 shot=ショット、サブウエポン
 ene=敵
 syoki=初期設定、及びゲームリセット

 と言うような感じで分割してる。
 
 
 ザックリ表にするとこんな感じ

 .hspはファイル、赤矢印は呼び出し。

 put、shot、eneのソースはラベルを使わず、全部 #deffuncで書かれている。

 なので前回やったが、HSPでは呼び出される #deffuncソースが呼び出し箇所の前に書かれなければいけないので、このような配置になってる。
 
 
 main.hspのソースはこんな感じ

 
 
 while文(繰り返し)と switch文(値分岐)による mainf値分岐で、タイトルとメインゲームとゲームオーバーのモードを切り替えている。

 今回は表示関係を putに分離して、それぞれのモード事に表示プログラムを呼び出しで表示している。
 
 
 putのソース

 
 
 syokiのソース

 
 
 shotのソース

 
 
 eneのソース

 
 
 こんな感じで分割すると、敵とかショットの種類が増えても管理が分かりやすくなる。

 この構造論(フォーマット)を使えば、どんなゲームでも大体これで作れてしまう。

 自分は goto文は使わない、goto文は Javaとか Cではたぶん使われなくて、全部呼び出し returnで構成されてると思う、たぶん。
 
 

プログラム解説

メイン

while ; ———- メインルーチン ———-
 switch mainf
  case 0 : gosub *titl : swbreak ; タイトル
  case 1 : gosub *game_main : swbreak ; ゲーム
  case 2 : gosub *game_over : swbreak ; ゲームオーバー
 swend
 if mainf=3 : _break ; end
wend

 mainfの値を切り替える事により、モードを切り替える。

 OP、EDとか、ストーリーの挿入とか、戦闘前のパワーアップや面セレクトの待機画面とかの切り替えも考えられる。

 もう少し複雑なソースの場合、例えば RPGなんかだとゲームルーチン内にもう一つルーチンを作って、フィールド移動、町探索、戦闘なんかを切り替えたりする。
 
 
 キー入力について、今回はちょんと押すとバルカン発射だが、基本的に押した時点でカーソル位置がその場所にセットされるようにし、合わせてその場所から近い標的を再セットするようにした。

 前回そうしたつもりだったが、そうでもなかったみたい。


; 出現 ———-
 s_set ; ショット出現
 v_set ; バルカン出現
 e1_set ; 敵1出現
 e2_set ; 敵2出現
 e3_set ; 敵3出現
; 移動処理 ———-
 s_syo ; ショット処理
 v_syo ; バルカン処理
 e_syo ; 敵処理テーブル

 ショットと敵の出現と移動処理を、全部呼び出しで行う。


redraw 0 ; 表示 ———-
 clr ; 画面クリア
 e_put ; 敵表示
 j_put ; 自機表示
 s_put ; ショット表示
 v_put ; バルカン表示
 c_put ; 照準表示
 scr_put ; スコア表示
redraw 1

 表示関係も全て呼び出しで行う。

 
 
ene.hsp 敵

#deffunc e_syo ; 敵移動処理テーブル
 repeat eb : en=cnt ; 敵No,
  if ef(en)=0 : continue ; 無し
  switch ef(en)
   case 1 : e1_syo : swbreak ; 敵1移動処理
   case 2 : e2_syo : swbreak ; 敵2移動処理
   case 3 : e3_syo : swbreak ; 敵3移動処理
  swend
 loop

 ef(en)のフラグが 1なら敵 1、2なら敵 2、3なら敵 3の移動処理を実行する。

 要するに efとか ex,eyのような変数は、全部の敵で使いまわし。

つまり ef(n)=敵フラグ

 0=無し
 1=敵1
 2=敵2
 3=敵3

 と言う風になってる。

 移動処理を分けるのは今回は設定してないが、それぞれの敵でアルゴリズムが異なる場合を想定している。

 例えば小型は蛇行するとか、要塞から小型が吐き出されるとか、戦車からミサイルが放たれるとか、そういう要素(アルゴリズム)をそれぞれの処理ルーチンで作る。

 
 
syoki.hsp 初期

e1hpb=24 ; 耐久度
e1sp=1.0 ; 敵1スピード
e1c=0 ; 出現カウント
e1cb=10 ; 出現間隔(フレーム)
escr(1)=10 ; スコア
 
e2hpb=300 ; 耐久度
e2sp=0.5 ; 敵2スピード
e2c=50 ; 出現カウント
e2cb=70 ; 出現間隔(フレーム)
escr(2)=100 ; スコア
 
e3hpb=5000 ; 耐久度
e3sp=0.1 ; 敵2スピード
e3c=400 ; 出現カウント
e3cb=2000 ; 出現間隔(フレーム)
escr(3)=2000 ; スコア

 敵によってそれぞれ違うステータスを、ここで定義している。

 スコアについて、escrの配列変数に定義しおき、scr+=escr(ef(en))のように書けば、倒した敵のソースを分けずにスコア加算が出来る。

 escr(1)=10,100,2000 のような書き方でも良い。
 
 
#deffunc reset ; ゲーム再初期化
 
 cx=double(jx) ; 照準座標xリセット
 cy=double(jy) ; 照準座標yリセット
 
 repeat sb : sf(cnt)=0 : loop ; ショットリセット
 repeat vb : vf(cnt)=0 : loop ; バルカンリセット
  vcn=0 : vc=0 ; 残弾リセット
 repeat eb : ef(cnt)=0 : loop ; 敵リセット
 
 scr=0 ; スコアリセット
 esn=0 ; 標的リセット
 
 return

 再ゲームするにあたって、必要な初期化をするルーチン。

コメントを残す

メールアドレスが公開されることはありません。