HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0902
f(感冒中)えふすてやま 2合目18解決


f(感冒中)

リンク

2009/9/2(Wed) 13:13:06|NO.27498

夏休みも終わりだが、HSPコンテストはまだ締め切りまで2ヶ月ある。
しっかり計画してまともな設計が出来て真面目にスケジュールを守るなら、
まだ間に合うだろう。

それだけ出来る奴なら既に提出完了している気もするが。

今日はこれからHSPでゲームを作りたいと言うちみっこ達(謎)の為に、
試みにシューティングゲームを作ってみようと思う。


命令の意味なんかは説明しないので、f1ヘルプを駆使して貰いたい。
なお、毎回毎回、ソース丸ごと一式投稿するので、覚悟せよ。(俺が、いきなり消されても泣かないように。



この記事に返信する


f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

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



f(感冒中)

リンク

2009/9/2(Wed) 13:19:23|NO.27508

とりあえず、これくらい説明しておけば後は応用だと分かるだろう。
シューティングはドレもコレも、これと同じになっている訳ではないが。

1つの参考として。



check

リンク

2009/9/2(Wed) 15:04:05|NO.27509

こうやってHSPでまじめにプログラムを組もうとすると、
つくづくHSPの使いにくさが分か(ry



f(感冒中)

リンク

2009/9/2(Wed) 16:24:28|NO.27510

   / ̄ ̄\
 /   _ノ  \
 |   ( ●)(●)  ……………………。
. |     (__人__)____
  |     ` ⌒/ ─' 'ー\
.  |       /( ○)  (○)\
.  ヽ     /  ⌒(n_人__)⌒ \
   ヽ   |、    (  ヨ    |
   /    `ー─−  厂   /
   |   、 _   __,,/     \



f(感冒中)

リンク

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



f(感冒中)

リンク

2009/9/2(Wed) 16:46:00|NO.27512

「敵の種類」を管理する項目等を増やして、
敵の移動時にそれに応じた動きをさせるとかするだけで、
大きな改造無しに敵の種類を増やす処理が作れるだろう。



Ve

リンク

2009/9/2(Wed) 18:41:27|NO.27515

次は横スクロールアクションでお願いします。



KA

リンク

2009/9/2(Wed) 21:03:55|NO.27517

おつかれさま、ごくろうでした。

苦労が報われる事を祈ります。



shinkun

リンク

2009/9/3(Thu) 07:00:45|NO.27520

他の人の作り方を見ると勉強になりますね。
こういう企画があっても面白そうです。



panda

リンク

2009/9/3(Thu) 16:39:28|NO.27521

f さん、本出せますよ〜 ^^



ONION software Copyright 1997-2023(c) All rights reserved.