|
|
2009/9/2(Wed) 13:13:06|NO.27498
夏休みも終わりだが、HSPコンテストはまだ締め切りまで2ヶ月ある。
しっかり計画してまともな設計が出来て真面目にスケジュールを守るなら、
まだ間に合うだろう。
それだけ出来る奴なら既に提出完了している気もするが。
今日はこれからHSPでゲームを作りたいと言うちみっこ達(謎)の為に、
試みにシューティングゲームを作ってみようと思う。
命令の意味なんかは説明しないので、f1ヘルプを駆使して貰いたい。
なお、毎回毎回、ソース丸ごと一式投稿するので、覚悟せよ。(俺が、いきなり消されても泣かないように。
|
|
2009/9/2(Wed) 13:13:26|NO.27499
まず、大枠を作る。「初期化」、「主処理」、「終了処理」を順番に実行して終了する。
「初期化」で、「主処理」が終了する為の条件になるフラグを作り、
「主処理」はそのフラグが変化しない限りループする。
これは俺の書き方。
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
|
|
2009/9/2(Wed) 13:14:08|NO.27500
キャラクタを表示する前準備を行う。
まず、最大幾つのキャラクタを管理するか決める。
そして、そのキャラクタに必要なパラメタを考える。
管理するために、管理番号がを使う事にする。
その管理番号のデータは有効なのかを判断する必要がある。
その管理番号のデータは何のデータなのか区別する必要がある。
その管理番号のデータの表示位置を保持しなければならない。
これらを1つの2次元配列変数cparamで管理する事にする。
番号では分かり難いので、#defineで適当な名前で定数にしておく。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
dim cparm , MAXCHR , ID_MAX
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
|
|
2009/9/2(Wed) 13:14:33|NO.27501
補助的な作業を行う処理を加えてゆく。
まず、「空きの管理番号」を探すサブルーチンを作る。
二次元配列変数cparmのどこが空いているかを確認し、
空いている場所を変数cnoに入れて返事する。
次に、自分の初期化を行うサブルーチン。
自分はとりあえず、2次元配列変数の一番最初にでも登録する。
自分自身だけはmycnoと言う変数で、管理番号を覚えておく。
あとで参照し易いように。
次に、「空き管理番号」を取得して、「自分の位置と同じ位置」に「弾」を配置するサブルーチンを作る。
ココを呼び出せば自動的に弾が管理に追加される様にしてしまう。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
dim cparm , MAXCHR , ID_MAX
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
| |
|
2009/9/2(Wed) 13:15:02|NO.27502
そろそろ、表示部分を作ろうと思う。
主処理の中から、キャラクタを表示するサブルーチンへ飛ぶgosub命令を入れる。
そして、その先で
・有効な管理番号で、自分なら大きな四角、弾なら小さな四角を描画
させる
ここまで来て、ようやく実行画面が表示できるようになった。
しかし、まだ操作は出来ない。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
dim cparm , MAXCHR , ID_MAX
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *view // キャラクタ表示処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( 0 , ID_ALIVE ) = 1 // 存在有効
cparm( 0 , ID_TYPE ) = 0 // 種類->自分
cparm( 0 , ID_X ) = 320
cparm( 0 , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-表示-----------------------------------------------------------------------
*view
redraw 0
color 0,0,0
boxf 0,0,640,480
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
swbreak
case 1 // 弾処理
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
swbreak
swend
}
next
redraw 1
return
| |
|
2009/9/2(Wed) 13:15:30|NO.27503
移動処理を考える。
とりあえず、自分の移動速度をMYSPEEDで、弾の移動速度をBLLETSPEEDで、移動速度を定数にしておく。
まず、主処理に、移動処理専用のサブルーチンへ飛ぶgosubを追加する。
移動処理専用サブルーチンでは、
・有効な管理番号で、自分なら自分操作ルーチンへ、弾なら弾移動ルーチンへ振り分け
を行う。
自分操作ルーチンはキー入力を受付、移動。必要なら新規弾生成。
弾移動ルーチンは弾の移動と、画面から外に出た場合の管理終了フラグセットを行う。
移動と、画面表示のルーチンの構造が良く似ているので、後で1つにまとめるのも良いかも知れない。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
#define MYSPEED 10 // 自分移動速度
#define BLLETSPEED 20 // 自分の弾移動速度
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
dim cparm , MAXCHR , ID_MAX
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *move // キャラクタ移動処理
gosub *view // キャラクタ表示処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-表示-----------------------------------------------------------------------
*view
redraw 0
color 0,0,0
boxf 0,0,640,480
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
swbreak
case 1 // 弾処理
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
swbreak
swend
}
next
redraw 1
return
//-移動-----------------------------------------------------------------------
*move
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
gosub *move_MyChr
swbreak
case 1 // 弾処理
gosub *move_Bllet
swbreak
swend
}
next
return
//-自分処理-------------------------------------------------------------------
*move_MyChr
mx = 0
my = 0
mw = 5
stick st , 0xf
if ( st & 1 ) != 0 : mx=-MYSPEED // カーソル左
if ( st & 4 ) != 0 : mx= MYSPEED // 右
if ( st & 2 ) != 0 : my=-MYSPEED // 上
if ( st & 8 ) != 0 : my= MYSPEED // 下
if ( st & 16 ) != 0 : gosub *set_MyBllet // スペース:弾発射
cparm( mycno , ID_X ) += mx // 実際に位置を移動
cparm( mycno , ID_Y ) += my
return
//-弾処理---------------------------------------------------------------------
*move_Bllet
cparm( index , ID_Y ) -= BLLETSPEED // 上へ移動
if cparm( index , ID_Y ) < 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
| |
|
2009/9/2(Wed) 13:16:13|NO.27504
移動と表示のサブルーチンを、1つにまとめた。
続いて、敵を表示する準備を始める。
基本部分は出来ているので、
・呼び出せば敵が追加されるサブルーチン
・呼び出せば敵を移動させるサブルーチン
を追加すればよい。
最初に管理部分を作っておけば後がこんな感じで楽だ。
この再、表示部分もサブルーチン化して、まとめてみる。
敵が追加されるルーチンでは、出現位置を画面一番上の左右はランダムとするので、
初期化部分にrandomizeを追加しておく。
これで敵の出現、移動、表示は出来た。
次は「どのタイミングで敵を出すのか」だ。
とりあえず、乱数振ってみて、1/30くらいの確立で敵追加にしてみた。
敵登場タイミングーチンを作成し、メインの処理ループに入れ込む。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾 2:敵
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
#define MYSPEED 10 // 自分移動速度
#define BLLETSPEED 20 // 自分の弾移動速度
#define ENEMYSPEED 10 // 敵移動速度
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
randomize
dim cparm , MAXCHR , ID_MAX
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *newEnemy // 新規敵追加
gosub *controll // キャラクタ移動表示処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-新規敵追加-------------------------------------------------------------------
*newEnemy
if rnd( 30 ) = 0 : gosub *set_Enemy
return
//-実行制御-------------------------------------------------------------------
*controll
redraw 0
color 0,0,0
boxf 0,0,640,480
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
gosub *move_MyChr // 移動処理
gosub *write_MyChr // 描画処理
swbreak
case 1 // 弾処理
gosub *move_MyBllet // 移動処理
gosub *write_MyBllet // 描画処理
swbreak
case 2 // 敵処理
gosub *move_Enemy // 移動処理
gosub *write_Enemy // 描画処理
swbreak
swend
}
next
redraw 1
return
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-敵を加える-----------------------------------------------------------------
*set_Enemy
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 2 // 種類->敵
cparm( cno , ID_X ) = rnd(640)
cparm( cno , ID_Y ) = 0 // 画面1番上
return
//-自分処理-------------------------------------------------------------------
*move_MyChr
mx = 0
my = 0
mw = 5
stick st , 0xf
if ( st & 1 ) != 0 : mx =-MYSPEED // カーソル:左
if ( st & 4 ) != 0 : mx = MYSPEED // カーソル:右
if ( st & 2 ) != 0 : my =-MYSPEED // カーソル:上
if ( st & 8 ) != 0 : my = MYSPEED // カーソル:下
if ( st & 16 ) != 0 : gosub *set_MyBllet // スペース:弾発射
if ( st & 128 ) != 0 : game_eof = 1 // ESC :終了フラグを立てる
cparm( mycno , ID_X ) += mx // 実際に位置を移動
cparm( mycno , ID_Y ) += my
return
//-弾処理---------------------------------------------------------------------
*move_MyBllet
cparm( index , ID_Y ) -= BLLETSPEED // 上へ移動
if cparm( index , ID_Y ) < 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-敵処理---------------------------------------------------------------------
*move_Enemy
cparm( index , ID_Y ) += ENEMYSPEED // 下へ移動
if cparm( index , ID_Y ) >480 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-自分描画処理---------------------------------------------------------------------
*write_MyChr
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-自分弾描画処理---------------------------------------------------------------------
*write_MyBllet
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
return
//-敵描画処理---------------------------------------------------------------------
*write_Enemy
color 255,0,0
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
| |
|
2009/9/2(Wed) 13:16:38|NO.27505
当り判定を行おう。
まず、何と何が当った時に何をするのか考える。
・敵と自分が当ったら、自分を消す
・敵と弾が当ったら、敵と弾を消す
こうだ。
処理をするには・・・
・敵移動完了したら、自分と当ってないか位置関係を調べる
これで敵と自分は判断できそうだ。なので、とりあえず後回しにする。
敵と弾はどうしようか?
判定の為に全部の管理番号について、敵か弾か調べていくのは、処理は簡単でも処理時間がかかりそうだ。
なので、予め、敵は何番で管理している、弾は何番で管理している、というのを調べたい。
そこで、全管理情報を全部チェックしている*controllのサブルーチンの中で、
「今の管理番号は敵だった」「今の管理番号は弾だった」と、情報を収集し、
最後にそれらだけを判断するようにする。
弾だった管理番号を覚えておく為に、cblletと言う配列を、
敵だった管理番号を覚えておく為に、cenemyと言う配列を作る。
これを*controll内で更新して行く。
そして、最後に、集まった情報を元に当り判定を行うサブルーチン*blletHitを作成する。
これで敵と自分の弾との判定はOKだ。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾 2:敵
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
#define MYSPEED 10 // 自分移動速度
#define BLLETSPEED 20 // 自分の弾移動速度
#define ENEMYSPEED 10 // 敵移動速度
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
randomize
dim cparm , MAXCHR , ID_MAX
dim cbllet , MAXCHR
dim cenemy , MAXCHR
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *newEnemy // 新規敵追加
gosub *controll // キャラクタ移動表示処理
gosub *blletHit // 自分の弾と敵の当り判定処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-新規敵追加-------------------------------------------------------------------
*newEnemy
if rnd( 30 ) = 0 : gosub *set_Enemy
return
//-実行制御-------------------------------------------------------------------
*controll
redraw 0
color 0,0,0
boxf 0,0,640,480
bcount = 0 // 管理している自分の弾の数を集計する変数
ecount = 0 // 管理している敵の数を集計する変数
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
gosub *move_MyChr // 移動処理
gosub *write_MyChr // 描画処理
swbreak
case 1 // 弾処理
gosub *move_MyBllet // 移動処理
gosub *write_MyBllet // 描画処理
if cparm( index , ID_ALIVE ) != 0 {
cbllet( bcount ) = index // 管理中の弾だった管理番号を覚えておく
bcount++ // 弾集計数を増やす
}
swbreak
case 2 // 敵処理
gosub *move_Enemy // 移動処理
gosub *write_Enemy // 描画処理
if cparm( index , ID_ALIVE ) != 0 {
cenemy( ecount ) = index // 管理中の敵だった管理番号を覚えておく
ecount++ // 敵集計数を増やす
}
swbreak
swend
}
next
redraw 1
return
//-当り判定-------------------------------------------------------------------
*blletHit
if bcount = 0 : return // 自分の弾が無いなら判定不要
if ecount = 0 : return // 敵が無いなら判定不要
// 弾1つ1つに付き、敵と衝突していないか判定
for bindex , 0 , bcount
// 実際に処理する弾管理番号を、覚えておいた配列変数から取得
bno = cbllet( bindex )
for eindex , 0 , ecount
// 実際に処理する敵管理番号を、覚えておいた配列変数から取得
eno = cenemy( eindex )
// その敵はまだ管理しているか確認
if cparm( eno , ID_ALIVE ) != 0 {
// 当り判定部分
// 直線距離を求めているが色々方法あるので好きにして欲しい
dist_x = cparm( bno , ID_X ) - cparm( eno , ID_X )
dist_y = cparm( bno , ID_Y ) - cparm( eno , ID_Y )
dist = sqrt( (dist_x * dist_x) + ( dist_y * dist_y) )
// 中心距離が32以下なら、命中とする
if dist < 30.0 {
cparm( bno , ID_ALIVE ) = 0 // 弾管理終了
cparm( eno , ID_ALIVE ) = 0 // 敵管理終了
_break :// これ以上、この弾について判定する必要は無いので抜ける
}
}
next
next
return
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-敵を加える-----------------------------------------------------------------
*set_Enemy
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 2 // 種類->敵
cparm( cno , ID_X ) = rnd(640)
cparm( cno , ID_Y ) = 0 // 画面1番上
return
//-自分処理-------------------------------------------------------------------
*move_MyChr
mx = 0
my = 0
mw = 5
stick st , 0xf
if ( st & 1 ) != 0 : mx =-MYSPEED // カーソル:左
if ( st & 4 ) != 0 : mx = MYSPEED // カーソル:右
if ( st & 2 ) != 0 : my =-MYSPEED // カーソル:上
if ( st & 8 ) != 0 : my = MYSPEED // カーソル:下
if ( st & 16 ) != 0 : gosub *set_MyBllet // スペース:弾発射
if ( st & 128 ) != 0 : game_eof = 1 // ESC :終了フラグを立てる
cparm( mycno , ID_X ) += mx // 実際に位置を移動
cparm( mycno , ID_Y ) += my
return
//-弾処理---------------------------------------------------------------------
*move_MyBllet
cparm( index , ID_Y ) -= BLLETSPEED // 上へ移動
if cparm( index , ID_Y ) < 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-敵処理---------------------------------------------------------------------
*move_Enemy
cparm( index , ID_Y ) += ENEMYSPEED // 下へ移動
if cparm( index , ID_Y ) >480 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-自分描画処理---------------------------------------------------------------------
*write_MyChr
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-自分弾描画処理---------------------------------------------------------------------
*write_MyBllet
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
return
//-敵描画処理---------------------------------------------------------------------
*write_Enemy
color 255,0,0
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
| |
|
2009/9/2(Wed) 13:17:11|NO.27506
命中判定部分を、別にサブルーチンにしてしまい、敵と弾の命中判定意外にも使えるようにする。
cno1と、cno2に、判定したい二つの管理番号を入れ、distに判定の距離をいれて*hitCheckに飛ぶと、
命中していればhitが1になる。
これを、敵キャラの移動の時に判定をはさみ、命中していたらゲーム終了の為のフラグを立ててしまう。
とりあえずは、これでゲームとしての体裁が整ったようだ。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 4 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾 2:敵
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
#define MYSPEED 10 // 自分移動速度
#define BLLETSPEED 20 // 自分の弾移動速度
#define ENEMYSPEED 10 // 敵移動速度
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
randomize
dim cparm , MAXCHR , ID_MAX
dim cbllet , MAXCHR
dim cenemy , MAXCHR
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *newEnemy // 新規敵追加
gosub *controll // キャラクタ移動表示処理
gosub *blletHit // 自分の弾と敵の当り判定処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-新規敵追加-------------------------------------------------------------------
*newEnemy
if rnd( 30 ) = 0 : gosub *set_Enemy
return
//-実行制御-------------------------------------------------------------------
*controll
redraw 0
color 0,0,0
boxf 0,0,640,480
bcount = 0 // 管理している自分の弾の数を集計する変数
ecount = 0 // 管理している敵の数を集計する変数
cno1 = mycno // 命中判定用。片方に自分を指定
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
gosub *move_MyChr // 移動処理
gosub *write_MyChr // 描画処理
swbreak
case 1 // 弾処理
gosub *move_MyBllet // 移動処理
gosub *write_MyBllet // 描画処理
if cparm( index , ID_ALIVE ) != 0 {
cbllet( bcount ) = index // 管理中の弾だった管理番号を覚えておく
bcount++ // 弾集計数を増やす
}
swbreak
case 2 // 敵処理
gosub *move_Enemy // 移動処理
gosub *write_Enemy // 描画処理
// 敵と自分の命中判定
cno2 = index
dist = 32.0
gosub *hitCheck
if hit = 1 : game_eof = 1 // 当っていたらゲーム終了
if cparm( index , ID_ALIVE ) != 0 {
cenemy( ecount ) = index // 管理中の敵だった管理番号を覚えておく
ecount++ // 敵集計数を増やす
}
swbreak
swend
}
next
redraw 1
return
//-当り判定-------------------------------------------------------------------
*blletHit
if bcount = 0 : return // 自分の弾が無いなら判定不要
if ecount = 0 : return // 敵が無いなら判定不要
// 弾1つ1つに付き、敵と衝突していないか判定
for bindex , 0 , bcount
// 実際に処理する弾管理番号を、覚えておいた配列変数から取得
bno = cbllet( bindex )
for eindex , 0 , ecount
// 実際に処理する敵管理番号を、覚えておいた配列変数から取得
eno = cenemy( eindex )
// その敵はまだ管理しているか確認
if cparm( eno , ID_ALIVE ) != 0 {
cno1 = bno
cno2 = eno
dist = 32.0
gosub *hitCheck
if hit = 1 {
cparm( bno , ID_ALIVE ) = 0 // 弾管理終了
cparm( eno , ID_ALIVE ) = 0 // 敵管理終了
_break :// これ以上、この弾について判定する必要は無いので抜ける
}
}
next
next
return
//-指定管理番号同士の距離-----------------------------------------------------
*hitCheck
// 当り判定部分
// 直線距離を求めているが色々方法あるので好きにして欲しい
hit = 0 // 指定距離以下なら命中とし、1になる
dist_x = cparm( cno1 , ID_X ) - cparm( cno2 , ID_X )
dist_y = cparm( cno1 , ID_Y ) - cparm( cno2 , ID_Y )
dist_w = sqrt( (dist_x * dist_x) + ( dist_y * dist_y) )
if double(dist) >= dist_w : hit = 1
return
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-敵を加える-----------------------------------------------------------------
*set_Enemy
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 2 // 種類->敵
cparm( cno , ID_X ) = rnd(640)
cparm( cno , ID_Y ) = 0 // 画面1番上
return
//-自分処理-------------------------------------------------------------------
*move_MyChr
mx = 0
my = 0
mw = 5
stick st , 0xf
if ( st & 1 ) != 0 : mx =-MYSPEED // カーソル:左
if ( st & 4 ) != 0 : mx = MYSPEED // カーソル:右
if ( st & 2 ) != 0 : my =-MYSPEED // カーソル:上
if ( st & 8 ) != 0 : my = MYSPEED // カーソル:下
if ( st & 16 ) != 0 : gosub *set_MyBllet // スペース:弾発射
if ( st & 128 ) != 0 : game_eof = 1 // ESC :終了フラグを立てる
cparm( mycno , ID_X ) += mx // 実際に位置を移動
cparm( mycno , ID_Y ) += my
return
//-弾処理---------------------------------------------------------------------
*move_MyBllet
cparm( index , ID_Y ) -= BLLETSPEED // 上へ移動
if cparm( index , ID_Y ) < 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-敵処理---------------------------------------------------------------------
*move_Enemy
cparm( index , ID_Y ) += ENEMYSPEED // 下へ移動
if cparm( index , ID_Y ) >480 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-自分描画処理---------------------------------------------------------------------
*write_MyChr
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-自分弾描画処理---------------------------------------------------------------------
*write_MyBllet
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
return
//-敵描画処理---------------------------------------------------------------------
*write_Enemy
color 255,0,0
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
| |
|
2009/9/2(Wed) 13:17:44|NO.27507
管理データのパラメタを増やし、爆発を表現する。
まず、cparmの配列の規模を大きくする
ここらへんは、定数をいじれば済む様にしてある。
あらたにID_PARM1と、ID_PARM2の定数を増やしておく。
ここで、爆発の現在の大きさや、広がっているのか小さくなっているのかを表現する。
追加するサブルーチンも、いままでどおり。
・呼び出すと、自動で爆発を管理開始するサブルーチン
・呼び出すと、自動で爆発の動作を制御するサブルーチン
・呼び出すと、現在の情報から爆発を描画するサブルーチン
を普通に追加する。
開始のルーチンには、爆発の広がる方向や今の大きさなどのパラメタをセットさせる。
最後に、主の処理から、管理番号のタイプから爆発処理へ行くようにするのと
自分の弾が敵に当ったら、爆発管理開始を呼び出すようにすれば良い。
かんたんかんたん。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 6 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾 2:敵
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
#define ID_PARM1 4 // 汎用1
#define ID_PARM2 5 // 汎用2
#define MYSPEED 10 // 自分移動速度
#define BLLETSPEED 20 // 自分の弾移動速度
#define ENEMYSPEED 10 // 敵移動速度
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
randomize
dim cparm , MAXCHR , ID_MAX
dim cbllet , MAXCHR
dim cenemy , MAXCHR
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *newEnemy // 新規敵追加
gosub *controll // キャラクタ移動表示処理
gosub *blletHit // 自分の弾と敵の当り判定処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-新規敵追加-------------------------------------------------------------------
*newEnemy
if rnd( 30 ) = 0 : gosub *set_Enemy
return
//-実行制御-------------------------------------------------------------------
*controll
redraw 0
color 0,0,0
boxf 0,0,640,480
bcount = 0 // 管理している自分の弾の数を集計する変数
ecount = 0 // 管理している敵の数を集計する変数
cno1 = mycno // 命中判定用。片方に自分を指定
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
gosub *move_MyChr // 移動処理
gosub *write_MyChr // 描画処理
swbreak
case 1 // 弾処理
gosub *move_MyBllet // 移動処理
gosub *write_MyBllet // 描画処理
if cparm( index , ID_ALIVE ) != 0 {
cbllet( bcount ) = index // 管理中の弾だった管理番号を覚えておく
bcount++ // 弾集計数を増やす
}
swbreak
case 2 // 敵処理
gosub *move_Enemy // 移動処理
gosub *write_Enemy // 描画処理
// 敵と自分の命中判定
cno2 = index
dist = 32.0
gosub *hitCheck
if hit = 1 : game_eof = 1 // 当っていたらゲーム終了
if cparm( index , ID_ALIVE ) != 0 {
cenemy( ecount ) = index // 管理中の敵だった管理番号を覚えておく
ecount++ // 敵集計数を増やす
}
swbreak
case 3 // 爆発処理
gosub *move_Explode // 移動処理
gosub *write_Explode // 描画処理
swbreak
swend
}
next
redraw 1
return
//-当り判定-------------------------------------------------------------------
*blletHit
if bcount = 0 : return // 自分の弾が無いなら判定不要
if ecount = 0 : return // 敵が無いなら判定不要
// 弾1つ1つに付き、敵と衝突していないか判定
for bindex , 0 , bcount
// 実際に処理する弾管理番号を、覚えておいた配列変数から取得
bno = cbllet( bindex )
for eindex , 0 , ecount
// 実際に処理する敵管理番号を、覚えておいた配列変数から取得
eno = cenemy( eindex )
// その敵はまだ管理しているか確認
if cparm( eno , ID_ALIVE ) != 0 {
cno1 = bno
cno2 = eno
dist = 32.0
gosub *hitCheck
if hit = 1 {
cparm( bno , ID_ALIVE ) = 0 // 弾管理終了
cparm( eno , ID_ALIVE ) = 0 // 敵管理終了
cno1 = eno
gosub *set_explode // 爆発をセット
_break :// これ以上、この弾について判定する必要は無いので抜ける
}
}
next
next
return
//-指定管理番号同士の距離-----------------------------------------------------
*hitCheck
// 当り判定部分
// 直線距離を求めているが色々方法あるので好きにして欲しい
hit = 0 // 指定距離以下なら命中とし、1になる
dist_x = cparm( cno1 , ID_X ) - cparm( cno2 , ID_X )
dist_y = cparm( cno1 , ID_Y ) - cparm( cno2 , ID_Y )
dist_w = sqrt( (dist_x * dist_x) + ( dist_y * dist_y) )
if double(dist) >= dist_w : hit = 1
return
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-敵を加える-----------------------------------------------------------------
*set_Enemy
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 2 // 種類->敵
cparm( cno , ID_X ) = rnd(640)
cparm( cno , ID_Y ) = 0 // 画面1番上
return
//-爆発を加える---------------------------------------------------------------
*set_Explode
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 3 // 種類->敵
cparm( cno , ID_X ) = cparm( cno1 , ID_X ) // cno1で指定する管理番号データ位置が出発点
cparm( cno , ID_Y ) = cparm( cno1 , ID_Y )
cparm( cno , ID_PARM1 ) = 5 // 爆発の広がる早さ
cparm( cno , ID_PARM2 ) = 0 // 現在の爆発広さ
return
//-自分処理-------------------------------------------------------------------
*move_MyChr
mx = 0
my = 0
mw = 5
stick st , 0xf
if ( st & 1 ) != 0 : mx =-MYSPEED // カーソル:左
if ( st & 4 ) != 0 : mx = MYSPEED // カーソル:右
if ( st & 2 ) != 0 : my =-MYSPEED // カーソル:上
if ( st & 8 ) != 0 : my = MYSPEED // カーソル:下
if ( st & 16 ) != 0 : gosub *set_MyBllet // スペース:弾発射
if ( st & 128 ) != 0 : game_eof = 1 // ESC :終了フラグを立てる
cparm( mycno , ID_X ) += mx // 実際に位置を移動
cparm( mycno , ID_Y ) += my
return
//-弾処理---------------------------------------------------------------------
*move_MyBllet
cparm( index , ID_Y ) -= BLLETSPEED // 上へ移動
if cparm( index , ID_Y ) < 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-敵処理---------------------------------------------------------------------
*move_Enemy
cparm( index , ID_Y ) += ENEMYSPEED // 下へ移動
if cparm( index , ID_Y ) >480 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-爆発処理-------------------------------------------------------------------
*move_Explode
// 大きさが60になるまで5づつ大きくなり、
// それ以降は3づつ小さくなる。
// 大きさが0以下になったら、爆発終了
if cparm( index , ID_PARM2 ) >= 60 : cparm( index , ID_PARM1 ) = -3
cparm( index , ID_PARM2 ) += cparm( index , ID_PARM1 )
if cparm( index , ID_PARM2 ) <= 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-自分描画処理---------------------------------------------------------------------
*write_MyChr
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-自分弾描画処理---------------------------------------------------------------------
*write_MyBllet
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
return
//-敵描画処理---------------------------------------------------------------------
*write_Enemy
color 255,0,0
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-爆発描画処理---------------------------------------------------------------------
*write_Explode
color 255,0,0
csx = cparm( index , ID_X ) - cparm( index , ID_PARM2 )
cex = cparm( index , ID_X ) + cparm( index , ID_PARM2 )
csy = cparm( index , ID_Y ) - cparm( index , ID_PARM2 )
cey = cparm( index , ID_Y ) + cparm( index , ID_PARM2 )
circle csx,csy,cex,cey , 1
return
| |
|
2009/9/2(Wed) 13:19:23|NO.27508
とりあえず、これくらい説明しておけば後は応用だと分かるだろう。
シューティングはドレもコレも、これと同じになっている訳ではないが。
1つの参考として。
|
|
2009/9/2(Wed) 15:04:05|NO.27509
こうやってHSPでまじめにプログラムを組もうとすると、
つくづくHSPの使いにくさが分か(ry
|
|
2009/9/2(Wed) 16:24:28|NO.27510
/ ̄ ̄\
/ _ノ \
| ( ●)(●) ……………………。
. | (__人__)____
| ` ⌒/ ─' 'ー\
. | /( ○) (○)\
. ヽ / ⌒(n_人__)⌒ \
ヽ |、 ( ヨ |
/ `ー─− 厂 /
| 、 _ __,,/ \
|
|
2009/9/2(Wed) 16:32:29|NO.27511
管理できるパラメタが増えたので、ソレを使って敵の動きを付ける。
修正箇所は2箇所。
新規敵出現時に、新しい管理情報であるID_PARM1にX軸移動量、ID_PARM2のほうにY軸移動量になる数字を格納しておく
そして、実際の敵移動時に、敵座標にそれぞれを加える。
それだけだ。
#define MAXCHR 100 // 管理する最大キャラクタ
#define ID_MAX 6 // 以下の項目の数
#define ID_ALIVE 0 // 存在を確認するフラグ
#define ID_TYPE 1 // 種類別フラグ 0:自分 1:自分の弾 2:敵
#define ID_X 2 // X座標
#define ID_Y 3 // Y座標
#define ID_PARM1 4 // 汎用1
#define ID_PARM2 5 // 汎用2
#define MYSPEED 10 // 自分移動速度
#define BLLETSPEED 20 // 自分の弾移動速度
#define ENEMYSPEED 10 // 敵移動速度
//-全体制御-------------------------------------------------------------------
gosub *game_init
gosub *game_main
gosub *game_term
stop
//-初期化---------------------------------------------------------------------
*game_init
randomize
dim cparm , MAXCHR , ID_MAX
dim cbllet , MAXCHR
dim cenemy , MAXCHR
gosub *set_MyChr // 自分を初期化
game_eof = 0 // 終了フラグを初期化
return
//-主処理---------------------------------------------------------------------
*game_main
gosub *newEnemy // 新規敵追加
gosub *controll // キャラクタ移動表示処理
gosub *blletHit // 自分の弾と敵の当り判定処理
await 10
if game_eof = 0 : goto *game_main
return
//-終了処理-------------------------------------------------------------------
*game_term
return
//-サブ-----------------------------------------------------------------------
//-新規敵追加-------------------------------------------------------------------
*newEnemy
if rnd( 30 ) = 0 : gosub *set_Enemy
return
//-実行制御-------------------------------------------------------------------
*controll
redraw 0
color 0,0,0
boxf 0,0,640,480
bcount = 0 // 管理している自分の弾の数を集計する変数
ecount = 0 // 管理している敵の数を集計する変数
cno1 = mycno // 命中判定用。片方に自分を指定
for index , 0 , MAXCHR
// 管理されているデータのみ処理を行う
if cparm( index , ID_ALIVE ) = 1 {
switch cparm( index , ID_TYPE )
case 0 // 自分処理
gosub *move_MyChr // 移動処理
gosub *write_MyChr // 描画処理
swbreak
case 1 // 弾処理
gosub *move_MyBllet // 移動処理
gosub *write_MyBllet // 描画処理
if cparm( index , ID_ALIVE ) != 0 {
cbllet( bcount ) = index // 管理中の弾だった管理番号を覚えておく
bcount++ // 弾集計数を増やす
}
swbreak
case 2 // 敵処理
gosub *move_Enemy // 移動処理
gosub *write_Enemy // 描画処理
// 敵と自分の命中判定
cno2 = index
dist = 32.0
gosub *hitCheck
if hit = 1 : game_eof = 1 // 当っていたらゲーム終了
if cparm( index , ID_ALIVE ) != 0 {
cenemy( ecount ) = index // 管理中の敵だった管理番号を覚えておく
ecount++ // 敵集計数を増やす
}
swbreak
case 3 // 爆発処理
gosub *move_Explode // 移動処理
gosub *write_Explode // 描画処理
swbreak
swend
}
next
redraw 1
return
//-当り判定-------------------------------------------------------------------
*blletHit
if bcount = 0 : return // 自分の弾が無いなら判定不要
if ecount = 0 : return // 敵が無いなら判定不要
// 弾1つ1つに付き、敵と衝突していないか判定
for bindex , 0 , bcount
// 実際に処理する弾管理番号を、覚えておいた配列変数から取得
bno = cbllet( bindex )
for eindex , 0 , ecount
// 実際に処理する敵管理番号を、覚えておいた配列変数から取得
eno = cenemy( eindex )
// その敵はまだ管理しているか確認
if cparm( eno , ID_ALIVE ) != 0 {
cno1 = bno
cno2 = eno
dist = 32.0
gosub *hitCheck
if hit = 1 {
cparm( bno , ID_ALIVE ) = 0 // 弾管理終了
cparm( eno , ID_ALIVE ) = 0 // 敵管理終了
cno1 = eno
gosub *set_explode // 爆発をセット
_break :// これ以上、この弾について判定する必要は無いので抜ける
}
}
next
next
return
//-指定管理番号同士の距離-----------------------------------------------------
*hitCheck
// 当り判定部分
// 直線距離を求めているが色々方法あるので好きにして欲しい
hit = 0 // 指定距離以下なら命中とし、1になる
dist_x = cparm( cno1 , ID_X ) - cparm( cno2 , ID_X )
dist_y = cparm( cno1 , ID_Y ) - cparm( cno2 , ID_Y )
dist_w = sqrt( (dist_x * dist_x) + ( dist_y * dist_y) )
if double(dist) >= dist_w : hit = 1
return
//-空いている管理番号を変数cnoに入れて返す------------------------------------
*getNewCno
cno = -1 // 空きが無かった時はこの値を返す
for i , 0 , MAXCHR
if cparm( i , ID_ALIVE ) = 0 {
cno = i
_break
}
next
return
//-自分を初期化する-----------------------------------------------------------
*set_MyChr
mycno = 0
cparm( mycno , ID_ALIVE ) = 1 // 存在有効
cparm( mycno , ID_TYPE ) = 0 // 種類->自分
cparm( mycno , ID_X ) = 320
cparm( mycno , ID_Y ) = 240
return
//-自分の弾を加える-----------------------------------------------------------
*set_MyBllet
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 1 // 種類->自分の弾
cparm( cno , ID_X ) = cparm( mycno , ID_X ) // 自分の位置が出発点
cparm( cno , ID_Y ) = cparm( mycno , ID_Y )
return
//-敵を加える-----------------------------------------------------------------
*set_Enemy
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 2 // 種類->敵
cparm( cno , ID_X ) = rnd(640)
cparm( cno , ID_Y ) = 0 // 画面1番上
cparm( cno , ID_PARM1 ) = rnd( ENEMYSPEED * 2 + 1) - ENEMYSPEED // X軸移動量
cparm( cno , ID_PARM2 ) = rnd( ENEMYSPEED ) + 1 // Y軸移動量
return
//-爆発を加える---------------------------------------------------------------
*set_Explode
gosub *getNewCno // 新規管理番号取得
if cno < 0 : return // 管理番号に空きがなければ終了
cparm( cno , ID_ALIVE ) = 1 // 存在有効
cparm( cno , ID_TYPE ) = 3 // 種類->敵
cparm( cno , ID_X ) = cparm( cno1 , ID_X ) // cno1で指定する管理番号データ位置が出発点
cparm( cno , ID_Y ) = cparm( cno1 , ID_Y )
cparm( cno , ID_PARM1 ) = 5 // 爆発の広がる早さ
cparm( cno , ID_PARM2 ) = 15 // 現在の爆発広さ
return
//-自分処理-------------------------------------------------------------------
*move_MyChr
mx = 0
my = 0
mw = 5
stick st , 0xf
if ( st & 1 ) != 0 : mx =-MYSPEED // カーソル:左
if ( st & 4 ) != 0 : mx = MYSPEED // カーソル:右
if ( st & 2 ) != 0 : my =-MYSPEED // カーソル:上
if ( st & 8 ) != 0 : my = MYSPEED // カーソル:下
if ( st & 16 ) != 0 : gosub *set_MyBllet // スペース:弾発射
if ( st & 128 ) != 0 : game_eof = 1 // ESC :終了フラグを立てる
cparm( mycno , ID_X ) += mx // 実際に位置を移動
cparm( mycno , ID_Y ) += my
return
//-弾処理---------------------------------------------------------------------
*move_MyBllet
cparm( index , ID_Y ) -= BLLETSPEED // 上へ移動
if cparm( index , ID_Y ) < 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-敵処理---------------------------------------------------------------------
*move_Enemy
cparm( index , ID_X ) += cparm( index , ID_PARM1 ) // X移動
cparm( index , ID_Y ) += cparm( index , ID_PARM2 ) // Y移動
if cparm( index , ID_Y ) >480 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-爆発処理-------------------------------------------------------------------
*move_Explode
// 大きさが60になるまで5づつ大きくなり、
// それ以降は3づつ小さくなる。
// 大きさが0以下になったら、爆発終了
if cparm( index , ID_PARM2 ) >= 60 : cparm( index , ID_PARM1 ) = -3
cparm( index , ID_PARM2 ) += cparm( index , ID_PARM1 )
if cparm( index , ID_PARM2 ) <= 0 : cparm( index , ID_ALIVE ) = 0 // 画面からはみ出たら管理終了
return
//-自分描画処理---------------------------------------------------------------------
*write_MyChr
color 255,255,255
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-自分弾描画処理---------------------------------------------------------------------
*write_MyBllet
color 255,128,128
csx = cparm( index , ID_X ) - 10
cex = cparm( index , ID_X ) + 10
csy = cparm( index , ID_Y ) - 10
cey = cparm( index , ID_Y ) + 10
boxf csx,csy,cex,cey
return
//-敵描画処理---------------------------------------------------------------------
*write_Enemy
color 255,0,0
csx = cparm( index , ID_X ) - 32
cex = cparm( index , ID_X ) + 32
csy = cparm( index , ID_Y ) - 32
cey = cparm( index , ID_Y ) + 32
boxf csx,csy,cex,cey
return
//-爆発描画処理---------------------------------------------------------------------
*write_Explode
color 255,0,0
csx = cparm( index , ID_X ) - cparm( index , ID_PARM2 )
cex = cparm( index , ID_X ) + cparm( index , ID_PARM2 )
csy = cparm( index , ID_Y ) - cparm( index , ID_PARM2 )
cey = cparm( index , ID_Y ) + cparm( index , ID_PARM2 )
circle csx,csy,cex,cey , 1
return
| |
|
2009/9/2(Wed) 16:46:00|NO.27512
「敵の種類」を管理する項目等を増やして、
敵の移動時にそれに応じた動きをさせるとかするだけで、
大きな改造無しに敵の種類を増やす処理が作れるだろう。
|
|
2009/9/2(Wed) 18:41:27|NO.27515
次は横スクロールアクションでお願いします。
|
|
2009/9/2(Wed) 21:03:55|NO.27517
おつかれさま、ごくろうでした。
苦労が報われる事を祈ります。
|
|
2009/9/3(Thu) 07:00:45|NO.27520
他の人の作り方を見ると勉強になりますね。
こういう企画があっても面白そうです。
|
|
2009/9/3(Thu) 16:39:28|NO.27521
f さん、本出せますよ〜 ^^
|
|