まったくのプログラミング素人の筆者がC++/HSPを使用してSTG(シューティングゲーム)を作っていく過程を書くブログでしたが最近は脱線気味。プログラミング以外にも、ゲーム関連の記事、日々の戯言など。
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
敵の種類を増やそうと思って、一つ作ってみました。
敵攻撃を多彩にする為には、同時に色んな種類の弾を撃たせなければなりませんが、ここでちょっとつまづきました。
敵弾の座標変数は1種類しかありません。(と言うか弾の種類だけ変数を別で用意したら、当り判定なんかが大変)
どうするんだ?と思って色々試した所、gcopyの値を配列変数で換えれば出来ました。
ついでに自機弾も3方向に撃てるようにし、Zボタンを押した時はスピードダウン&連射速度アップ出来るようにした。

スプリクトはコチラ↓雑魚以上中ボス以下のちょっと強い敵をイメージしてみました。
*************************************
;初期設定
#include "CK_JOYFORCE.AS"
dialog "fullscreenで起動しますか?「はい」を選択した場合、画面解像度を640×480に変更します。",2
if stat=6:fullscreen=0
if stat=7:fullscreen=1
if fullscreen=0 : chgdisp 1,640,480 : mouse -1 ;ディスプレイ解像度を640×480に。マウスを表示しない
*start
buffer 3 ;ウィンドウ3をバッファ画面として用意
picload "stg10.gif";画像をバッファ3に読み込み
buffer 4 ; ウィンドウ4をバッファ画面として用意
picload "s396.jpg" ;背景画像をバッファ4に読み込み
buffer 5 ; ウィンドウ4をバッファ画面として用意
picload "bomb.gif" ;ボム画像をバッファ5に読み込み
ssp=482 ;スクロール速度
wxs=320 :wys=480 ;ゲーム画面の座標設定
screen 2,640,480,1;メイン画面(ウィンドウ2を480*640で用意)
bgscr 2,640,480,2 : gsel 2,1 ;メイン画面を初期化して枠のないウィンドウを作成。メイン画面をアクティブに
gtime=0 ;フレーム数
px=304:py=448;自機の初期位置
tmx=40 ;自機弾の数
dim tx,tmx ;自機弾のX座標の配列変数
dim ty,tmx ;自機弾のY座標の配列変数
dim tf,tmx ;自機弾が画面にあるか無いかを調べる配列変数
dim txv,tmx;自機弾のx軸移動量
dim tyv,tmx;自機弾のy軸移動量
emx=50;敵の数
dim ex,emx : dim ey,emx;敵の初期位置
dim dx,emx : dim dy,emx;敵の移動量
dim ef,emx;敵のフラグ
dim em,emx;敵の種類
dim et,emx;敵出現からの時間
dim bbmx,emx;ボムで爆破時の爆発のx座標
dim bbmy,emx;ボムで爆破時の爆発のy座標
dim bbmc,emx;ボムカウント
emt=2000;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt; etxv 敵弾x方向運動量
dim etyv,emt; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ
dim etxp,emt;敵弾画像のx軸の座標
dim etyp,emt;敵弾画像のy軸の座標
dim etxs,emt;敵弾画像のx軸の大きさ
dim etys,emt;敵弾画像のy軸の大きさ
sc=0;スコア
gend=0;ゲームオーバー処理の為の変数
bombcnt=-1;ボム処理の為の変数(-1でボムを撃っていない)
nbomb=30;ボムの数
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
;スクロール処理
gmode 1 ; ノーマルコピーモード
scr=(scr+ssp)¥wys ; コピー元座標を算出
pos 160,scr :gcopy 4,0,0,wxs,wys-scr ;
if scr!0 { pos 160,0 ; 背景画像をコピー
gcopy 4,0,wys-scr,wxs,scr ;
} ;
;面データ読み込み
gosub *men ;*men(タイムテーブル)へ移動
;自機移動処理
pk=0 ;自機の傾きの為の変数
ck_joystick ky,15;キーボードのチェック
if ky&1 :px-=move :pk=32 :if px<160 :px=160;カーソルキー左(←)を押した時pxよりmoveを引く:画面からはみ出さないようにpxが0以下にならないようにする
if ky&4 :px+=move :pk=64 :if px>448 :px=448
if ky&2 :py-=move :if py<0 :py=0
if ky&8 :py+=move :if py>448 :py=448
gmode 2 ;透明化処理の為の命令
pos px,py;自機の座標指定
gcopy 3,pk,0,32,32;バッファ画面(ウィンドウ3)より自機画像をコピー
;自機弾発射処理
shottime-- ;連射為の処理
if shottime<0: st=1 ;shottimeが0以下の時、stに1を代入
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)=0 : if st=1{ ;tf(cnt)が0の時=画面に弾がない時、かつstが1の時(shottimeが0以下の時){}内の命令を行う
th=th+1;一回で撃てる弾数の為の変数
tf(cnt)=1 ;tf(cnt)に1を代入。画面に弾があると言う事
st=0 ;連射の為の処理
shottime=2 ;連射の為の処理
ts=10 ;自機弾の速さ
if th=1 :tx(cnt)=px : ty(cnt)=py-12 : r=double(4.712) : txv(cnt)=cos(r)*ts : tyv(cnt)=sin(r)*ts;直進弾
if th=2 :tx(cnt)=px-6 : ty(cnt)=py-12 : r=double(4.61) : txv(cnt)=cos(r)*ts : tyv(cnt)=sin(r)*ts;左弾
if th=3 :tx(cnt)=px+6 : ty(cnt)=py-12 : r=double(4.813) : txv(cnt)=cos(r)*ts : tyv(cnt)=sin(r)*ts : th=0;右弾
}
if tf(cnt)=1{ ;画面に弾があるとき、{}内の命令を行う
tx(cnt)=tx(cnt)+txv(cnt) : ty(cnt)=ty(cnt)+tyv(cnt) ;自機弾の移動量
pos tx(cnt),ty(cnt) ;自機弾の座標指定
gcopy 3,96,0,32,32 ;バッファ画面(ウィンドウ3)より自機弾画像をコピー
if ty(cnt)<-32 : tf(cnt)=0 : st=0 ;画面から自機弾が消えたら弾を消す
}
loop
ck_joystick ky,2048 ;Zキーのチェック
if ky&2048 { ;Zキーが押されていた時はmove(自機移動速度)を2にして連射速度を上げる。そうでなければmoveを4にする
move=2 : shottime=0 }else{
move=4
}
;ボム処理
ck_joystick ky,4096 ;Xキーのチェック
if ky&4096 { ;Xキーが押された時は{}内の命令を行う
if (bombcnt=-1)&(nbomb>0) { ;ボムが画面に出てなく、ボム数が0以上の時
nbomb=nbomb-1 ;ボム数を1減らす
bombcnt=0:bombp=17 ;ボムの存在を有にする。ボムアニメの為に変数を用意。
bpx=px-152 : bpy=py-400;ボムの座標指定
}
}
if bombcnt!-1 { ;ボムが画面に有る時。!は-1以外の時という事
repeat emt ;弾の存在を調べ画面に弾がある時は、弾の存在を消す(etf(cnt)=0)
if etf(cnt)<1 : continue
etf(cnt)=0
loop
bombcnt=bombcnt+1 ;ボムの効いている時間処理
if bombcnt=20 { bombcnt=-1 } ;20フレーム過ぎたらボムが効かなくなる
}
;敵移動処理
repeat emx ;repeat〜loop間をemx回繰り返す
ent=cnt
et(cnt)++ ;敵出現時間を+
if ef(cnt)<1 : continue ;ef(cnt)が1以下(敵が画面にいない)ならばrepeatに戻る
if enm(cnt)=4 : gosub *em04 ;敵の名前が4の時*em04へ移動
loop
;敵弾発射処理
repeat emt ;repeat〜loop間をemt回繰り返す
if etf(cnt)=1 { ;etf(cnt)が1(敵弾が画面にあるなら){}内の命令を行う
etx(cnt)=etx(cnt)+etxv(cnt) ;敵弾x座標に敵弾移動速度をプラス
ety(cnt)=ety(cnt)+etyv(cnt) ;敵弾y座標に敵弾移動速度をプラス
pos etx(cnt),ety(cnt) ;敵弾の座標指定
gcopy 3,etxp(cnt),etyp(cnt),etxs(cnt),etys(cnt) ;バッファ画面(ウィンドウ3)より敵弾画像をコピー
if etx(cnt)>480 : etf(cnt)=0 ;敵弾x座標が480以上になったら弾の存在を消す
if etx(cnt)<152 : etf(cnt)=0
if ety(cnt)>480 : etf(cnt)=0
if ety(cnt)<-16 : etf(cnt)=0
}
loop
;敵弾当り判定
repeat emt ;emt回繰り返す
if etf(cnt)=0 : continue
if etxs(cnt)=16 : ddx=(etx(cnt)+8)-(px+16) : if ddx<0 : ddx=-ddx ;自機と弾の中心座標の差の絶対値を求める
if etys(cnt)=16 : ddy=(ety(cnt)+8)-(py+16) : if ddy<0 : ddy=-ddy
if etxs(cnt)=8 : ddx=(etx(cnt)+4)-(px+16) : if ddx<0 : ddx=-ddx
if etys(cnt)=8 : ddy=(ety(cnt)+4)-(py+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<3))&(abs(ddy<3)) { ;x軸とy軸の差が3以下の時、ゲームオーバー
gend=1 ;1にするとゲームオーバー
}
loop
;爆風とボムのアニメ処理
if bombp>0 { ;ボムのアニメ処理変数が0以上の時{}内の命令を行う
bombp- : pos bpx,bpy
gcopy 5,320*(16-bombp),0,320,480
}
repeat emx ;敵のアニメ処理変数が0以上の時{}内の命令を行う
if bbmc(cnt)>0 {
bbmc(cnt)- : pos bbmx(cnt),bbmy(cnt)
gcopy 3,128+48*(16-bbmc(cnt)),0,48,48
}
loop
color 0,0,0 ;色に黒を指定
boxf 0,0,160,480 ;画面右側を黒で塗りつぶす
boxf 480,0,640,480 ;画面左側を黒で塗りつぶす
;スコア表示
font msmincho,18,3 ;フォントをMS明朝に、大きさを18に、イタリック体太字に指定
color 255,255,255 ;色に白を指定
pos 0,0
mes"Escで終了"
pos 496,0
mes"SCORE-"+sc+"-"
pos 496,462
mes"BOMB-"+nbomb+"-"
;fps表示
fp++
time=gettime(6)
if time!=time2{
fpc=fp
fp=0}
pos 0,462
mes " Fps "+fpc
time2=time
if gend=1 : gosub *gameover ;gendが1(ゲームオーバーの時)*gameoverに移動
redraw 1 ;メイン画面を更新
await 16 ;これを入れないとパソコンが固まる
gtime=gtime+1 ;タイムテーブルの為の変数
getkey syuryo,27:if syuryo=1:end ;Escキーのチェック。押されたら終了
goto *main ;*mainに戻る
;サブルーチン
*men ;タイムテーブル
if gtime=1 : bx=240 : by=-64 : gosub *eb04
if gtime=500 : gtime=0
return
*eb04;敵発生処理
repeat emx
if ef(cnt)>0 : continue ;画面に敵がいなければrepeatに戻る
enm(cnt)=4 ;敵の名前
ef(cnt)=100 ;敵の体力
ex(cnt)=bx : ey(cnt)=by ;敵生成位置決定
dx(cnt)=0 : dy(cnt)=1 ;移動方向
et(cnt)=0 ;敵弾生成時間をリセット
break ;repeat〜loop間のループから、強制的に抜け出す
loop
return
*em04;敵移動処理
if (et(cnt)>60)&(et(cnt)<250) : if gtime¥20=0 : gosub *tekitama4 ;敵生成時間が60以上250以下の時かつgtimeを20で割った余りが0の時*tekitama4へ移動
if (et(cnt)>60)&(et(cnt)<250) : if gtime¥20=0 : gosub *tekitama5
if (et(cnt)>30)&(et(cnt)<300) : if gtime¥5=0 : gosub *tekitama6
ex(cnt)=ex(cnt)+dx(cnt) ;敵の移動量決定
ey(cnt)=ey(cnt)+dy(cnt) ;敵の移動量決定
if et(cnt)<20 : dy(cnt)=5
if et(cnt)>21 : dy(cnt)=0
if et(cnt)>300 : dy(cnt)=3
if ey(cnt)>480 : ef(cnt)=0 ;画面から消えたら敵の存在を無しにする
pos ex(cnt),ey(cnt) : gmode 2 : gcopy 3,256,80,160,80 ;敵4の表示
;敵と自機との当り判定
ddx=(ex(cnt)+80)-(px+16) : if ddx<0 : ddx=-ddx
ddy=(ey(cnt)+40)-(py+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<70))&(abs(ddy<30)) {
gend=1
}
;自機弾と敵との当り判定
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)<1 : continue ;tf(cnt)が1以下(弾が画面にいない)ならばrepeatに戻る
ddx=(ex(ent)+80)-(tx(cnt)+16) : if ddx<0 : ddx=-ddx
ddy=(ey(ent)+40)-(ty(cnt)+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<70))&(abs(ddy<30)) { ;自機弾と敵のx軸とy軸の座標差を求め(敵と自機弾全て)、どちらも32以下であれば{}}内の命令を行う
tf(cnt)=0 ;弾が当った時は弾の存在を消す
ef(ent)- ;弾が当った時は敵の存在を消す
pos ex(ent),ey(ent)
gcopy 3,416,80,160,80
if ef(ent)=0 : sc+10000 : gosub *bomb2
}
loop
;ボム処理
if bombcnt!-1 {
ef(cnt)-
pos ex(cnt),ey(cnt)
gcopy 3,416,80,160,80
if ef(cnt)=0 : gosub *bomb2
}
return
*tekitama4;敵左側3方向弾
repeat emt
if etf(cnt)>0 : continue ;etfが0以上の時repeatに戻る
eh=eh+1 : etf(cnt)=1 ;弾数の為の処理。弾の存在を有にする
etx(cnt)=double(ex(ent)+37) : ety(cnt)=double(ey(ent)+80) ;弾の初期座標
etxp(cnt)=96 : etyp(cnt)=40;弾画像の場所指定
etxs(cnt)=8 : etys(cnt)=8;弾画像の大きさ指定
if eh=1 :ds=2 :r=atan(py-ey(ent), px-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=2 :ds=2 : r=atan(py-ey(ent), px+90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=3 :ds=2 : r=atan(py-ey(ent), px-90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=4 :ds=2.5 : r=atan(py-ey(ent), px-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=5 :ds=2.5 : r=atan(py-ey(ent), px+90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=6 :ds=2.5 : r=atan(py-ey(ent), px-90-ex(ent)): etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=7 :ds=3 : r=atan(py-ey(ent), px-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=8 :ds=3 : r=atan(py-ey(ent), px+90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=9 :ds=3 : r=atan(py-ey(ent), px-90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds:eh=0 :break
loop
return
*tekitama5;敵右側3方向弾
repeat emt
if etf(cnt)>0 : continue
eh=eh+1 : etf(cnt)=1
etx(cnt)=double(ex(ent)+115) : ety(cnt)=double(ey(ent)+80)
etxp(cnt)=96 : etyp(cnt)=40
etxs(cnt)=8 : etys(cnt)=8
if eh=1 :ds=2 :r=atan(py-ey(ent), px-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=2 :ds=2 : r=atan(py-ey(ent), px+90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=3 :ds=2 : r=atan(py-ey(ent), px-90-(ex(ent)+100)): etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=4 :ds=2.5 : r=atan(py-ey(ent), px-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=5 :ds=2.5 : r=atan(py-ey(ent), px+90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=6 :ds=2.5 : r=atan(py-ey(ent), px-90-(ex(ent)+100)): etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=7 :ds=3 : r=atan(py-ey(ent), px-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=8 :ds=3 : r=atan(py-ey(ent), px+90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=9 :ds=3 : r=atan(py-ey(ent), px-90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds:eh=0 :break
loop
return
*tekitama6;敵5方向弾
repeat emt
if etf(cnt)>0 : continue
eh=eh+1 : etf(cnt)=1
etx(cnt)=double(ex(ent)+72) : ety(cnt)=double(ey(ent)+60)
ds=6 ;敵弾の速さ
etxp(cnt)=96 : etyp(cnt)=48
etxs(cnt)=16 : etys(cnt)=16
if eh=1 : r=double(1.57) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=2 : r=double(1.97) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=3 : r=double(2.57) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=4 : r=double(1.17) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=5 : r=double(0.57) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds : eh=0 :break
loop
return
*bomb2;敵爆破処理
bbmx(ent)=ex(ent)+60 : bbmy(ent)=ey(ent)+20 ;爆風の座標指定
bbmc(ent)=17 ;爆風アニメの為の変数
return
*gameover
color rnd(255),rnd(255),rnd(255) ;色指定
pos 280,228
mes "Game Over"
pos 230,248
mes"Press X to Continue"
redraw 1
wait 1
ck_joystick ky ;Xキーのチェック。押されたら*startに戻る
if ky=4096 :goto *start
getkey syuryo,27:if syuryo=1:end
goto *gameover
*************************************
HSP3.0使用 CK_JOYFORCE.DLL使用 画像は↓を使用

これを実行すると5方向に青い弾を撃ちつつ、弾速の違う3方向自機狙い弾を左右の砲座から撃ってきます。
こんな感じで敵を増やしていけば、そこそこの物が出来そうな感じです^^
でも音楽もまだだし、完成までは程遠いと言った感じですが・・・
敵攻撃を多彩にする為には、同時に色んな種類の弾を撃たせなければなりませんが、ここでちょっとつまづきました。
敵弾の座標変数は1種類しかありません。(と言うか弾の種類だけ変数を別で用意したら、当り判定なんかが大変)
どうするんだ?と思って色々試した所、gcopyの値を配列変数で換えれば出来ました。
ついでに自機弾も3方向に撃てるようにし、Zボタンを押した時はスピードダウン&連射速度アップ出来るようにした。
スプリクトはコチラ↓雑魚以上中ボス以下のちょっと強い敵をイメージしてみました。
*************************************
;初期設定
#include "CK_JOYFORCE.AS"
dialog "fullscreenで起動しますか?「はい」を選択した場合、画面解像度を640×480に変更します。",2
if stat=6:fullscreen=0
if stat=7:fullscreen=1
if fullscreen=0 : chgdisp 1,640,480 : mouse -1 ;ディスプレイ解像度を640×480に。マウスを表示しない
*start
buffer 3 ;ウィンドウ3をバッファ画面として用意
picload "stg10.gif";画像をバッファ3に読み込み
buffer 4 ; ウィンドウ4をバッファ画面として用意
picload "s396.jpg" ;背景画像をバッファ4に読み込み
buffer 5 ; ウィンドウ4をバッファ画面として用意
picload "bomb.gif" ;ボム画像をバッファ5に読み込み
ssp=482 ;スクロール速度
wxs=320 :wys=480 ;ゲーム画面の座標設定
screen 2,640,480,1;メイン画面(ウィンドウ2を480*640で用意)
bgscr 2,640,480,2 : gsel 2,1 ;メイン画面を初期化して枠のないウィンドウを作成。メイン画面をアクティブに
gtime=0 ;フレーム数
px=304:py=448;自機の初期位置
tmx=40 ;自機弾の数
dim tx,tmx ;自機弾のX座標の配列変数
dim ty,tmx ;自機弾のY座標の配列変数
dim tf,tmx ;自機弾が画面にあるか無いかを調べる配列変数
dim txv,tmx;自機弾のx軸移動量
dim tyv,tmx;自機弾のy軸移動量
emx=50;敵の数
dim ex,emx : dim ey,emx;敵の初期位置
dim dx,emx : dim dy,emx;敵の移動量
dim ef,emx;敵のフラグ
dim em,emx;敵の種類
dim et,emx;敵出現からの時間
dim bbmx,emx;ボムで爆破時の爆発のx座標
dim bbmy,emx;ボムで爆破時の爆発のy座標
dim bbmc,emx;ボムカウント
emt=2000;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt; etxv 敵弾x方向運動量
dim etyv,emt; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ
dim etxp,emt;敵弾画像のx軸の座標
dim etyp,emt;敵弾画像のy軸の座標
dim etxs,emt;敵弾画像のx軸の大きさ
dim etys,emt;敵弾画像のy軸の大きさ
sc=0;スコア
gend=0;ゲームオーバー処理の為の変数
bombcnt=-1;ボム処理の為の変数(-1でボムを撃っていない)
nbomb=30;ボムの数
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
;スクロール処理
gmode 1 ; ノーマルコピーモード
scr=(scr+ssp)¥wys ; コピー元座標を算出
pos 160,scr :gcopy 4,0,0,wxs,wys-scr ;
if scr!0 { pos 160,0 ; 背景画像をコピー
gcopy 4,0,wys-scr,wxs,scr ;
} ;
;面データ読み込み
gosub *men ;*men(タイムテーブル)へ移動
;自機移動処理
pk=0 ;自機の傾きの為の変数
ck_joystick ky,15;キーボードのチェック
if ky&1 :px-=move :pk=32 :if px<160 :px=160;カーソルキー左(←)を押した時pxよりmoveを引く:画面からはみ出さないようにpxが0以下にならないようにする
if ky&4 :px+=move :pk=64 :if px>448 :px=448
if ky&2 :py-=move :if py<0 :py=0
if ky&8 :py+=move :if py>448 :py=448
gmode 2 ;透明化処理の為の命令
pos px,py;自機の座標指定
gcopy 3,pk,0,32,32;バッファ画面(ウィンドウ3)より自機画像をコピー
;自機弾発射処理
shottime-- ;連射為の処理
if shottime<0: st=1 ;shottimeが0以下の時、stに1を代入
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)=0 : if st=1{ ;tf(cnt)が0の時=画面に弾がない時、かつstが1の時(shottimeが0以下の時){}内の命令を行う
th=th+1;一回で撃てる弾数の為の変数
tf(cnt)=1 ;tf(cnt)に1を代入。画面に弾があると言う事
st=0 ;連射の為の処理
shottime=2 ;連射の為の処理
ts=10 ;自機弾の速さ
if th=1 :tx(cnt)=px : ty(cnt)=py-12 : r=double(4.712) : txv(cnt)=cos(r)*ts : tyv(cnt)=sin(r)*ts;直進弾
if th=2 :tx(cnt)=px-6 : ty(cnt)=py-12 : r=double(4.61) : txv(cnt)=cos(r)*ts : tyv(cnt)=sin(r)*ts;左弾
if th=3 :tx(cnt)=px+6 : ty(cnt)=py-12 : r=double(4.813) : txv(cnt)=cos(r)*ts : tyv(cnt)=sin(r)*ts : th=0;右弾
}
if tf(cnt)=1{ ;画面に弾があるとき、{}内の命令を行う
tx(cnt)=tx(cnt)+txv(cnt) : ty(cnt)=ty(cnt)+tyv(cnt) ;自機弾の移動量
pos tx(cnt),ty(cnt) ;自機弾の座標指定
gcopy 3,96,0,32,32 ;バッファ画面(ウィンドウ3)より自機弾画像をコピー
if ty(cnt)<-32 : tf(cnt)=0 : st=0 ;画面から自機弾が消えたら弾を消す
}
loop
ck_joystick ky,2048 ;Zキーのチェック
if ky&2048 { ;Zキーが押されていた時はmove(自機移動速度)を2にして連射速度を上げる。そうでなければmoveを4にする
move=2 : shottime=0 }else{
move=4
}
;ボム処理
ck_joystick ky,4096 ;Xキーのチェック
if ky&4096 { ;Xキーが押された時は{}内の命令を行う
if (bombcnt=-1)&(nbomb>0) { ;ボムが画面に出てなく、ボム数が0以上の時
nbomb=nbomb-1 ;ボム数を1減らす
bombcnt=0:bombp=17 ;ボムの存在を有にする。ボムアニメの為に変数を用意。
bpx=px-152 : bpy=py-400;ボムの座標指定
}
}
if bombcnt!-1 { ;ボムが画面に有る時。!は-1以外の時という事
repeat emt ;弾の存在を調べ画面に弾がある時は、弾の存在を消す(etf(cnt)=0)
if etf(cnt)<1 : continue
etf(cnt)=0
loop
bombcnt=bombcnt+1 ;ボムの効いている時間処理
if bombcnt=20 { bombcnt=-1 } ;20フレーム過ぎたらボムが効かなくなる
}
;敵移動処理
repeat emx ;repeat〜loop間をemx回繰り返す
ent=cnt
et(cnt)++ ;敵出現時間を+
if ef(cnt)<1 : continue ;ef(cnt)が1以下(敵が画面にいない)ならばrepeatに戻る
if enm(cnt)=4 : gosub *em04 ;敵の名前が4の時*em04へ移動
loop
;敵弾発射処理
repeat emt ;repeat〜loop間をemt回繰り返す
if etf(cnt)=1 { ;etf(cnt)が1(敵弾が画面にあるなら){}内の命令を行う
etx(cnt)=etx(cnt)+etxv(cnt) ;敵弾x座標に敵弾移動速度をプラス
ety(cnt)=ety(cnt)+etyv(cnt) ;敵弾y座標に敵弾移動速度をプラス
pos etx(cnt),ety(cnt) ;敵弾の座標指定
gcopy 3,etxp(cnt),etyp(cnt),etxs(cnt),etys(cnt) ;バッファ画面(ウィンドウ3)より敵弾画像をコピー
if etx(cnt)>480 : etf(cnt)=0 ;敵弾x座標が480以上になったら弾の存在を消す
if etx(cnt)<152 : etf(cnt)=0
if ety(cnt)>480 : etf(cnt)=0
if ety(cnt)<-16 : etf(cnt)=0
}
loop
;敵弾当り判定
repeat emt ;emt回繰り返す
if etf(cnt)=0 : continue
if etxs(cnt)=16 : ddx=(etx(cnt)+8)-(px+16) : if ddx<0 : ddx=-ddx ;自機と弾の中心座標の差の絶対値を求める
if etys(cnt)=16 : ddy=(ety(cnt)+8)-(py+16) : if ddy<0 : ddy=-ddy
if etxs(cnt)=8 : ddx=(etx(cnt)+4)-(px+16) : if ddx<0 : ddx=-ddx
if etys(cnt)=8 : ddy=(ety(cnt)+4)-(py+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<3))&(abs(ddy<3)) { ;x軸とy軸の差が3以下の時、ゲームオーバー
gend=1 ;1にするとゲームオーバー
}
loop
;爆風とボムのアニメ処理
if bombp>0 { ;ボムのアニメ処理変数が0以上の時{}内の命令を行う
bombp- : pos bpx,bpy
gcopy 5,320*(16-bombp),0,320,480
}
repeat emx ;敵のアニメ処理変数が0以上の時{}内の命令を行う
if bbmc(cnt)>0 {
bbmc(cnt)- : pos bbmx(cnt),bbmy(cnt)
gcopy 3,128+48*(16-bbmc(cnt)),0,48,48
}
loop
color 0,0,0 ;色に黒を指定
boxf 0,0,160,480 ;画面右側を黒で塗りつぶす
boxf 480,0,640,480 ;画面左側を黒で塗りつぶす
;スコア表示
font msmincho,18,3 ;フォントをMS明朝に、大きさを18に、イタリック体太字に指定
color 255,255,255 ;色に白を指定
pos 0,0
mes"Escで終了"
pos 496,0
mes"SCORE-"+sc+"-"
pos 496,462
mes"BOMB-"+nbomb+"-"
;fps表示
fp++
time=gettime(6)
if time!=time2{
fpc=fp
fp=0}
pos 0,462
mes " Fps "+fpc
time2=time
if gend=1 : gosub *gameover ;gendが1(ゲームオーバーの時)*gameoverに移動
redraw 1 ;メイン画面を更新
await 16 ;これを入れないとパソコンが固まる
gtime=gtime+1 ;タイムテーブルの為の変数
getkey syuryo,27:if syuryo=1:end ;Escキーのチェック。押されたら終了
goto *main ;*mainに戻る
;サブルーチン
*men ;タイムテーブル
if gtime=1 : bx=240 : by=-64 : gosub *eb04
if gtime=500 : gtime=0
return
*eb04;敵発生処理
repeat emx
if ef(cnt)>0 : continue ;画面に敵がいなければrepeatに戻る
enm(cnt)=4 ;敵の名前
ef(cnt)=100 ;敵の体力
ex(cnt)=bx : ey(cnt)=by ;敵生成位置決定
dx(cnt)=0 : dy(cnt)=1 ;移動方向
et(cnt)=0 ;敵弾生成時間をリセット
break ;repeat〜loop間のループから、強制的に抜け出す
loop
return
*em04;敵移動処理
if (et(cnt)>60)&(et(cnt)<250) : if gtime¥20=0 : gosub *tekitama4 ;敵生成時間が60以上250以下の時かつgtimeを20で割った余りが0の時*tekitama4へ移動
if (et(cnt)>60)&(et(cnt)<250) : if gtime¥20=0 : gosub *tekitama5
if (et(cnt)>30)&(et(cnt)<300) : if gtime¥5=0 : gosub *tekitama6
ex(cnt)=ex(cnt)+dx(cnt) ;敵の移動量決定
ey(cnt)=ey(cnt)+dy(cnt) ;敵の移動量決定
if et(cnt)<20 : dy(cnt)=5
if et(cnt)>21 : dy(cnt)=0
if et(cnt)>300 : dy(cnt)=3
if ey(cnt)>480 : ef(cnt)=0 ;画面から消えたら敵の存在を無しにする
pos ex(cnt),ey(cnt) : gmode 2 : gcopy 3,256,80,160,80 ;敵4の表示
;敵と自機との当り判定
ddx=(ex(cnt)+80)-(px+16) : if ddx<0 : ddx=-ddx
ddy=(ey(cnt)+40)-(py+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<70))&(abs(ddy<30)) {
gend=1
}
;自機弾と敵との当り判定
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)<1 : continue ;tf(cnt)が1以下(弾が画面にいない)ならばrepeatに戻る
ddx=(ex(ent)+80)-(tx(cnt)+16) : if ddx<0 : ddx=-ddx
ddy=(ey(ent)+40)-(ty(cnt)+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<70))&(abs(ddy<30)) { ;自機弾と敵のx軸とy軸の座標差を求め(敵と自機弾全て)、どちらも32以下であれば{}}内の命令を行う
tf(cnt)=0 ;弾が当った時は弾の存在を消す
ef(ent)- ;弾が当った時は敵の存在を消す
pos ex(ent),ey(ent)
gcopy 3,416,80,160,80
if ef(ent)=0 : sc+10000 : gosub *bomb2
}
loop
;ボム処理
if bombcnt!-1 {
ef(cnt)-
pos ex(cnt),ey(cnt)
gcopy 3,416,80,160,80
if ef(cnt)=0 : gosub *bomb2
}
return
*tekitama4;敵左側3方向弾
repeat emt
if etf(cnt)>0 : continue ;etfが0以上の時repeatに戻る
eh=eh+1 : etf(cnt)=1 ;弾数の為の処理。弾の存在を有にする
etx(cnt)=double(ex(ent)+37) : ety(cnt)=double(ey(ent)+80) ;弾の初期座標
etxp(cnt)=96 : etyp(cnt)=40;弾画像の場所指定
etxs(cnt)=8 : etys(cnt)=8;弾画像の大きさ指定
if eh=1 :ds=2 :r=atan(py-ey(ent), px-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=2 :ds=2 : r=atan(py-ey(ent), px+90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=3 :ds=2 : r=atan(py-ey(ent), px-90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=4 :ds=2.5 : r=atan(py-ey(ent), px-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=5 :ds=2.5 : r=atan(py-ey(ent), px+90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=6 :ds=2.5 : r=atan(py-ey(ent), px-90-ex(ent)): etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=7 :ds=3 : r=atan(py-ey(ent), px-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=8 :ds=3 : r=atan(py-ey(ent), px+90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=9 :ds=3 : r=atan(py-ey(ent), px-90-ex(ent)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds:eh=0 :break
loop
return
*tekitama5;敵右側3方向弾
repeat emt
if etf(cnt)>0 : continue
eh=eh+1 : etf(cnt)=1
etx(cnt)=double(ex(ent)+115) : ety(cnt)=double(ey(ent)+80)
etxp(cnt)=96 : etyp(cnt)=40
etxs(cnt)=8 : etys(cnt)=8
if eh=1 :ds=2 :r=atan(py-ey(ent), px-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=2 :ds=2 : r=atan(py-ey(ent), px+90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=3 :ds=2 : r=atan(py-ey(ent), px-90-(ex(ent)+100)): etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=4 :ds=2.5 : r=atan(py-ey(ent), px-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=5 :ds=2.5 : r=atan(py-ey(ent), px+90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=6 :ds=2.5 : r=atan(py-ey(ent), px-90-(ex(ent)+100)): etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=7 :ds=3 : r=atan(py-ey(ent), px-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=8 :ds=3 : r=atan(py-ey(ent), px+90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=9 :ds=3 : r=atan(py-ey(ent), px-90-(ex(ent)+100)) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds:eh=0 :break
loop
return
*tekitama6;敵5方向弾
repeat emt
if etf(cnt)>0 : continue
eh=eh+1 : etf(cnt)=1
etx(cnt)=double(ex(ent)+72) : ety(cnt)=double(ey(ent)+60)
ds=6 ;敵弾の速さ
etxp(cnt)=96 : etyp(cnt)=48
etxs(cnt)=16 : etys(cnt)=16
if eh=1 : r=double(1.57) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=2 : r=double(1.97) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=3 : r=double(2.57) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=4 : r=double(1.17) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds
if eh=5 : r=double(0.57) : etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds : eh=0 :break
loop
return
*bomb2;敵爆破処理
bbmx(ent)=ex(ent)+60 : bbmy(ent)=ey(ent)+20 ;爆風の座標指定
bbmc(ent)=17 ;爆風アニメの為の変数
return
*gameover
color rnd(255),rnd(255),rnd(255) ;色指定
pos 280,228
mes "Game Over"
pos 230,248
mes"Press X to Continue"
redraw 1
wait 1
ck_joystick ky ;Xキーのチェック。押されたら*startに戻る
if ky=4096 :goto *start
getkey syuryo,27:if syuryo=1:end
goto *gameover
*************************************
HSP3.0使用 CK_JOYFORCE.DLL使用 画像は↓を使用
これを実行すると5方向に青い弾を撃ちつつ、弾速の違う3方向自機狙い弾を左右の砲座から撃ってきます。
こんな感じで敵を増やしていけば、そこそこの物が出来そうな感じです^^
でも音楽もまだだし、完成までは程遠いと言った感じですが・・・
PR
fpsを表示させようと思って、表示のさせ方を色々と調べてみた。
fpsってのは1秒間に何回画面を書き換えたか?っていうのがわかる表示で、処理落ちした時なんかに
どれくらい処理落ちしてるのか目安になるので、表示させたかったんですよね。
どうやるのかと言うと、何回書き換えたかを変数で覚えておいて、その変数が1秒間に増えた数をFpsとして表示するみたい。
HSPの掲示板なんかを参考に簡単なfps測定スプリクトを作ってみました。(写したとも言う(汗))
*************************************
*main
fp++ ;フレーム数を覚えておく変数
time=gettime(6) ;timeに現在の秒数を代入
if time!=time2 { ;timeとtime2が等しくなければ{}内の命令を行う
cls 0 ;ウィンドウ内を白色でクリア
fpc=fp ;fpc(表示するFps数)にfp(現在のフレーム数)を代入
fp=0 } ;フレーム数をクリア
pos 0,0
mes " Fps "+fpc ;フレーム数の表示
time2=time ;time2に現在の秒数を代入(1秒ごとに比べる為)
await 16 ;16ミリ秒待つ
goto *main
*************************************
hsp3.0使用
これを表示すると、Fps 50位を表示します。でも、await 16なので60位を表示しそうなもんなのですが。
(await 16は16ミリ秒待つと言う事なので、1秒は1000ミリ秒ですので16×60で960(大体1000)になるので)
で、更に調べてみるとgettime自体の精度があまり良くないみたいで、このような結果になるみたいです・・・多分。
ひょっとしたら、スプリクトが悪いのかもしれませんが(汗)
どなたか60fpsで表示出来る方法を知っていらしたら教えて下さい。
肝心のゲームの方ですが、エラー表示に悩まされてたんですが敵の弾処理を、全部サイン、コサインで処理したら
上手く動くようになりました。
しかも、動作もそこそこ軽くなってくれるという嬉しい誤算^^
DirectX使おうかと思ってましたが、とりあえず標準命令だけで作ってみます。
現在はこんな感じ↓

今日で作り初めて1ヶ月になるんですが、思ったより順調に出来てきています。
大体のゲーム進行のイメージは出来てきたので、もっと敵の種類やボスなんかを作っていけば
当初の目的の、簡単な敵が出てきて敵をすべて倒すとボスが出てきてボスを倒して終了みたいなのは出来そうな感じです。
fpsってのは1秒間に何回画面を書き換えたか?っていうのがわかる表示で、処理落ちした時なんかに
どれくらい処理落ちしてるのか目安になるので、表示させたかったんですよね。
どうやるのかと言うと、何回書き換えたかを変数で覚えておいて、その変数が1秒間に増えた数をFpsとして表示するみたい。
HSPの掲示板なんかを参考に簡単なfps測定スプリクトを作ってみました。(写したとも言う(汗))
*************************************
*main
fp++ ;フレーム数を覚えておく変数
time=gettime(6) ;timeに現在の秒数を代入
if time!=time2 { ;timeとtime2が等しくなければ{}内の命令を行う
cls 0 ;ウィンドウ内を白色でクリア
fpc=fp ;fpc(表示するFps数)にfp(現在のフレーム数)を代入
fp=0 } ;フレーム数をクリア
pos 0,0
mes " Fps "+fpc ;フレーム数の表示
time2=time ;time2に現在の秒数を代入(1秒ごとに比べる為)
await 16 ;16ミリ秒待つ
goto *main
*************************************
hsp3.0使用
これを表示すると、Fps 50位を表示します。でも、await 16なので60位を表示しそうなもんなのですが。
(await 16は16ミリ秒待つと言う事なので、1秒は1000ミリ秒ですので16×60で960(大体1000)になるので)
で、更に調べてみるとgettime自体の精度があまり良くないみたいで、このような結果になるみたいです・・・多分。
ひょっとしたら、スプリクトが悪いのかもしれませんが(汗)
どなたか60fpsで表示出来る方法を知っていらしたら教えて下さい。
肝心のゲームの方ですが、エラー表示に悩まされてたんですが敵の弾処理を、全部サイン、コサインで処理したら
上手く動くようになりました。
しかも、動作もそこそこ軽くなってくれるという嬉しい誤算^^
DirectX使おうかと思ってましたが、とりあえず標準命令だけで作ってみます。
現在はこんな感じ↓
今日で作り初めて1ヶ月になるんですが、思ったより順調に出来てきています。
大体のゲーム進行のイメージは出来てきたので、もっと敵の種類やボスなんかを作っていけば
当初の目的の、簡単な敵が出てきて敵をすべて倒すとボスが出てきてボスを倒して終了みたいなのは出来そうな感じです。
先日作った弾幕サンプルを利用して、ゲームっぽく弾幕を撃たせてみた。

こんな感じなんですが、まぁゲームとしては殆ど成り立ってませんが弾幕ゲーっぽくて良い感じです^^
ついでに、開始時のフルスクリーン選択、ボム処理、Zボタンを押している時の自機のスピードダウンなんかを追加
フルスクリーンはchgdisp命令で解像度を変更してbgscrとgsel命令で一番手前に画面を持ってくれば出来ました。
スプリクトはコチラ↓
*************************************
;初期設定
#include "CK_JOYFORCE.AS"
dialog "fullscreenで起動しますか?「はい」を選択した場合、画面解像度を640×480に変更します。",2
if stat=6:fullscreen=0
if stat=7:fullscreen=1
if fullscreen=0 : chgdisp 1,640,480 : mouse -1 ;ディスプレイ解像度を640×480に。マウスを表示しない
*start
buffer 3 ;ウィンドウ3をバッファ画面として用意
picload "stg8.gif";画像をバッファ3に読み込み
buffer 4 ; ウィンドウ4をバッファ画面として用意
picload "s399.jpg" ;背景画像をバッファ4に読み込み
buffer 5 ; ウィンドウ4をバッファ画面として用意
picload "bomb.gif" ;ボム画像をバッファ5に読み込み
ssp=482 ;スクロール速度
wxs=320 :wys=480 ;ゲーム画面の座標設定
screen 2,640,480,1;メイン画面(ウィンドウ2を480*640で用意)
bgscr 2,640,480,2 : gsel 2,1 ;メイン画面を初期化して枠のないウィンドウを作成。メイン画面をアクティブに
gtime=0 ;フレーム数
px=304:py=448;自機の初期位置
tmx=10 ;自機弾の数
dim tx,tmx ;自機弾のX座標の配列変数
dim ty,tmx ;自機弾のY座標の配列変数
dim tf,tmx ;自機弾が画面にあるか無いかを調べる配列変数
emx=50;敵の数
dim ex,emx : dim ey,emx;敵の初期位置
dim dx,emx : dim dy,emx;敵の移動量
dim ef,emx;敵のフラグ
dim em,emx;敵の種類
dim et,emx;敵出現からの時間
dim bbmx,emx;ボムで爆破時の爆発のx座標
dim bbmy,emx;ボムで爆破時の爆発のy座標
dim bbmc,emx;ボムカウント
emt=2000;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt; etxv 敵弾x方向運動量
dim etyv,emt; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ
sc=0;スコア
gend=0;ゲームオーバー処理の為の変数
bombcnt=-1;ボム処理の為の変数(-1でボムを撃っていない)
nbomb=30;ボムの数
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
;スクロール処理
gmode 1 ; ノーマルコピーモード
scr=(scr+ssp)¥wys ; コピー元座標を算出
pos 160,scr :gcopy 4,0,0,wxs,wys-scr ;
if scr!0 { pos 160,0 ; 背景画像をコピー
gcopy 4,0,wys-scr,wxs,scr ;
} ;
;面データ読み込み
gosub *men ;*men(タイムテーブル)へ移動
;自機移動処理
pk=0 ;自機の傾きの為の変数
ck_joystick ky,15;キーボードのチェック
if ky&1 :px-=move :pk=32 :if px<160 :px=160;カーソルキー左(←)を押した時pxよりmoveを引く:画面からはみ出さないようにpxが0以下にならないようにする
if ky&4 :px+=move :pk=64 :if px>448 :px=448
if ky&2 :py-=move :if py<0 :py=0
if ky&8 :py+=move :if py>448 :py=448
gmode 2 ;透明化処理の為の命令
pos px,py;自機の座標指定
gcopy 3,pk,0,32,32;バッファ画面(ウィンドウ1)より自機画像をコピー
;自機弾発射処理
shottime-- ;連射為の処理
if shottime<0: st=1 ;shottimeが0以下の時、stに1を代入
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)=0 : if st=1{ ;tf(cnt)が0の時=画面に弾がない時、かつstが1の時(shottimeが0以下の時){}内の命令を行う
tx(cnt)=px ;tx(cnt)(弾のx座標)にpx(自機のx座標)の値を代入
ty(cnt)=py-20 ;ty(cnt)(弾のy座標)にpy(自機のy座標)より20引いた値を代入。(弾と自機が重ならないようにする為)
tf(cnt)=1 ;tf(cnt)に1を代入。画面に弾があると言う事
st=0 ;連射の為の処理
shottime=3 ;連射の為の処理
}
ty(cnt)-=12 : if ty(cnt)<-32 : tf(cnt)=0 :ty(cnt)=-32: st=0;弾を進めて画面から出たら弾を消す
if tf(cnt)=1{ ;画面に弾があるとき、{}内の命令を行う
pos tx(cnt),ty(cnt) ;自機弾の座標指定
gcopy 3,96,0,32,32 ;バッファ画面(ウィンドウ1)より自機弾画像をコピー
}
loop
ck_joystick ky,2048 ;Zキーのチェック
if ky&2048 { ;Zキーが押されていた時はmove(自機移動速度)を1にする。そうでなければmoveを3にする
move=1 }else{
move=3
}
;ボム処理
ck_joystick ky,4096 ;Xキーのチェック
if ky&4096 { ;Xキーが押された時は{}内の命令を行う
if (bombcnt=-1)&(nbomb>0) { ;ボムが画面に出てなく、ボム数が0以上の時
nbomb=nbomb-1 ;ボム数を1減らす
bombcnt=0:bombp=17 ;ボムの存在を有にする。ボムアニメの為に変数を用意。
bpx=px-152 : bpy=py-400;ボムの座標指定
}
}
if bombcnt!-1 { ;ボムが画面に有る時。!は-1以外の時という事
repeat emt ;弾の存在を調べ画面に弾がある時は、弾の存在を消す(etf(cnt)=0)
if etf(cnt)<1 : continue
etf(cnt)=0
loop
bombcnt=bombcnt+1 ;ボムの効いている時間処理
if bombcnt=20 { bombcnt=-1 } ;20フレーム過ぎたらボムが効かなくなる
}
if bombcnt!-1 {
repeat emx ;敵の存在を調べ、敵がいる時は敵体力から1を引く(ef(cnt)-)
if ef(cnt)<1 : continue
ef(cnt)-
if ef(cnt)=0 : bbmx(cnt)=ex(cnt)+8 : bbmy(cnt)=ey(cnt)+8 :bbmc(cnt)=17
;敵体力が0になったら爆発させる
loop
}
;敵移動処理
repeat emx ;repeat〜loop間をemx回繰り返す
ent=cnt
et(cnt)++ ;敵出現時間を+
if ef(cnt)<1 : continue ;ef(cnt)が1以下(敵が画面にいない)ならばrepeatに戻る
if enm(cnt)=3 : gosub *em03 ;敵の名前が3の時*em03へ移動
loop
;敵弾発射処理
repeat emt ;repeat〜loop間をemt回繰り返す
if etf(cnt)=1 { ;etf(cnt)が1(敵弾が画面にあるなら){}内の命令を行う
etx(cnt)=etx(cnt)+etxv(cnt) ;敵弾x座標に敵弾移動速度をプラス
ety(cnt)=ety(cnt)+etyv(cnt) ;敵弾y座標に敵弾移動速度をプラス
pos etx(cnt),ety(cnt) ;敵弾の座標指定
gcopy 3,96,48,16,16 ;バッファ画面(ウィンドウ1)より敵弾画像をコピー
if etx(cnt)>480 : etf(cnt)=0 ;敵弾x座標が480以上になったら弾の存在を消す
if etx(cnt)<152 : etf(cnt)=0
if ety(cnt)>480 : etf(cnt)=0
if ety(cnt)<-16 : etf(cnt)=0
}
loop
;敵弾当り判定
repeat emt ;emt回繰り返す
if etf(cnt)=0 : continue
ddx=(etx(cnt)+8)-(px+16) : if ddx<0 : ddx=-ddx ;自機と弾の中心座標の差の絶対値を求める
ddy=(ety(cnt)+8)-(py+16) : if ddy<0 : ddy=-ddy
if (ddx<2)&(ddy<2) { ;x軸とy軸の差が2以下の時、ゲームオーバー
gend=1 ;1にするとゲームオーバー
}
loop
;爆風とボムのアニメ処理
if bombp>0 { ;ボムのアニメ処理変数が0以上の時{}内の命令を行う
bombp- : pos bpx,bpy
gcopy 5,320*(16-bombp),0,320,480
}
repeat emx ;敵のアニメ処理変数が0以上の時{}内の命令を行う
if bbmc(cnt)>0 {
bbmc(cnt)- : pos bbmx(cnt),bbmy(cnt)
gcopy 3,128+48*(16-bbmc(cnt)),0,48,48
}
loop
color 0,0,0 ;色に黒を指定
boxf 0,0,160,480 ;画面右側を黒で塗りつぶす
boxf 480,0,640,480 ;画面左側を黒で塗りつぶす
;スコア表示
font msmincho,18,3 ;フォントをMS明朝に、大きさを18に、イタリック体太字に指定
color 255,255,255 ;色に白を指定
pos 0,0
mes"Escで終了"
pos 496,0
mes"SCORE-"+sc+"-"
pos 496,462
mes"BOMB-"+nbomb+"-"
if gend=1 : gosub *gameover ;gendが1(ゲームオーバーの時)*gameoverに移動
redraw 1 ;メイン画面を更新
await 16 ;これを入れないとパソコンが固まる
gtime=gtime+1 ;タイムテーブルの為の変数
getkey syuryo,27:if syuryo=1:end ;Escキーのチェック。押されたら終了
goto *main ;*mainに戻る
;サブルーチン
*men ;タイムテーブル
if gtime=1 : bx=170 : by=-64 : gosub *eb03
if gtime=126 : bx=406 : by=-64 : gosub *eb03
if gtime=376 : bx=170 : by=-64 : gosub *eb03
if gtime=500 : bx=406 : by=-64 : gosub *eb03
if gtime=1000 : gtime=0
return
*eb03;敵発生処理
repeat emx
if ef(cnt)>0 : continue ;画面に敵がいなければrepeatに戻る
enm(cnt)=3 ;敵の名前
ef(cnt)=30 ;敵の体力
ex(cnt)=bx : ey(cnt)=by ;敵生成位置決定
dx(cnt)=0 : dy(cnt)=1 ;移動方向
et(cnt)=0 ;敵弾生成時間をリセット
break ;repeat〜loop間のループから、強制的に抜け出す
loop
return
*em03;敵移動処理
if et(cnt)>200 : if gtime¥20=0 : gosub *tekitama3 ;敵生成時間が200以上の時かつgtimeを20で割った余りが0の時*tekitama3へ移動
ex(cnt)=ex(cnt)+dx(cnt) ;敵の移動量決定
ey(cnt)=ey(cnt)+dy(cnt) ;敵の移動量決定
if et(cnt)>180 : dy(cnt)=0
if et(cnt)>500 : dy(cnt)=1
if ey(cnt)>480 : ef(cnt)=0 ;画面から消えたら敵の存在を無しにする
pos ex(cnt),ey(cnt) : gmode 2 : gcopy 3,0,96,64,64 ;敵3の表示
;敵と自機との当り判定
ddx=(ex(cnt)+32)-(px+16) : if ddx<0 : ddx=-ddx
ddy=(ey(cnt)+32)-(py+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<32))&(abs(ddy<32)) {
gend=1
}
;自機弾と敵との当り判定
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)<1 : continue ;tf(cnt)が1以下(弾が画面にいない)ならばrepeatに戻る
ddx=(ex(ent)+32)-(tx(cnt)+16) : if ddx<0 : ddx=-ddx
ddy=(ey(ent)+32)-(ty(cnt)+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<32))&(abs(ddy<32)) { ;自機弾と敵のx軸とy軸の座標差を求め(敵と自機弾全て)、どちらも32以下であれば{}}内の命令を行う
tf(cnt)=0 ;弾が当った時は弾の存在を消す
ef(ent)- ;弾が当った時は敵の存在を消す
sc+1000
pos ex(ent),ey(ent)
gcopy 3,192,96,64,64
if ef(ent)=0 : gosub *bomb1
}
loop
return
*tekitama3;敵弾発生処理
edx=ex(ent)+28 : edy=ey(ent)+32
repeat emt
if etf(cnt)>0 : continue ;etfが0(敵弾が画面に無い時)、emn(cnt)が1(敵の名前が1の時)の場合if{}内の命令を行う
eh=eh+1 : etf(cnt)=1 ;弾数の為の処理。弾の存在を有にする
etx(cnt)=double(edx) : ety(cnt)=double(edy) ;弾の初期座標
ds=3 ;敵弾の速さ
r=double(r+0.1) ;弾の角度を実数で計算
etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds ;弾の移動量を角度より計算
if eh>62 : eh=0 :break ;63発弾を撃った時点でrepeatを抜ける
loop
return
*bomb1;敵爆破処理
bbmx(ent)=ex(ent)+8 : bbmy(ent)=ey(ent)+8 ;爆風の座標指定
bbmc(ent)=17 ;爆風アニメの為の変数
return
*gameover
color rnd(255),rnd(255),rnd(255) ;色指定
pos 280,228
mes "Game Over"
pos 230,248
mes"Press X to Continue"
redraw 1
wait 1
ck_joystick ky ;Xキーのチェック。押されたら*startに戻る
if ky=4096 :goto *start
getkey syuryo,27:if syuryo=1:end
goto *gameover
*************************************
HSP3.0使用、CK_JOYFORCE.DLL使用、画像は↓を使用

このスプリクトでは、Zキーを押していないときに弾を発射させて、Zボタンを押した時は自機のスピードを遅くしています。
CAVEシューっぽいですね(汗)
Xキーでボム発射。ボム処理はまだまだですね・・・もっと派手派手にしたいんですが研究中です。
ちなみに、敵移動処理のif gtime¥20=0の20や、敵弾発生処理のr=double(r+0.1)やif eh>62の0.1、62などの数字を弄ると色んな弾幕が撃てます。

こんな事も出来ますよ^^
しかし、筆者の開発マシンはP4/1.7Gのノートなのですが、全体的に処理が重いです。
色んなHSPサイトを見てみてもDirectXを使った方が速度は速くなるようなので、DirectXを使うようにしようか迷ってます。
こんな感じなんですが、まぁゲームとしては殆ど成り立ってませんが弾幕ゲーっぽくて良い感じです^^
ついでに、開始時のフルスクリーン選択、ボム処理、Zボタンを押している時の自機のスピードダウンなんかを追加
フルスクリーンはchgdisp命令で解像度を変更してbgscrとgsel命令で一番手前に画面を持ってくれば出来ました。
スプリクトはコチラ↓
*************************************
;初期設定
#include "CK_JOYFORCE.AS"
dialog "fullscreenで起動しますか?「はい」を選択した場合、画面解像度を640×480に変更します。",2
if stat=6:fullscreen=0
if stat=7:fullscreen=1
if fullscreen=0 : chgdisp 1,640,480 : mouse -1 ;ディスプレイ解像度を640×480に。マウスを表示しない
*start
buffer 3 ;ウィンドウ3をバッファ画面として用意
picload "stg8.gif";画像をバッファ3に読み込み
buffer 4 ; ウィンドウ4をバッファ画面として用意
picload "s399.jpg" ;背景画像をバッファ4に読み込み
buffer 5 ; ウィンドウ4をバッファ画面として用意
picload "bomb.gif" ;ボム画像をバッファ5に読み込み
ssp=482 ;スクロール速度
wxs=320 :wys=480 ;ゲーム画面の座標設定
screen 2,640,480,1;メイン画面(ウィンドウ2を480*640で用意)
bgscr 2,640,480,2 : gsel 2,1 ;メイン画面を初期化して枠のないウィンドウを作成。メイン画面をアクティブに
gtime=0 ;フレーム数
px=304:py=448;自機の初期位置
tmx=10 ;自機弾の数
dim tx,tmx ;自機弾のX座標の配列変数
dim ty,tmx ;自機弾のY座標の配列変数
dim tf,tmx ;自機弾が画面にあるか無いかを調べる配列変数
emx=50;敵の数
dim ex,emx : dim ey,emx;敵の初期位置
dim dx,emx : dim dy,emx;敵の移動量
dim ef,emx;敵のフラグ
dim em,emx;敵の種類
dim et,emx;敵出現からの時間
dim bbmx,emx;ボムで爆破時の爆発のx座標
dim bbmy,emx;ボムで爆破時の爆発のy座標
dim bbmc,emx;ボムカウント
emt=2000;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt; etxv 敵弾x方向運動量
dim etyv,emt; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ
sc=0;スコア
gend=0;ゲームオーバー処理の為の変数
bombcnt=-1;ボム処理の為の変数(-1でボムを撃っていない)
nbomb=30;ボムの数
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
;スクロール処理
gmode 1 ; ノーマルコピーモード
scr=(scr+ssp)¥wys ; コピー元座標を算出
pos 160,scr :gcopy 4,0,0,wxs,wys-scr ;
if scr!0 { pos 160,0 ; 背景画像をコピー
gcopy 4,0,wys-scr,wxs,scr ;
} ;
;面データ読み込み
gosub *men ;*men(タイムテーブル)へ移動
;自機移動処理
pk=0 ;自機の傾きの為の変数
ck_joystick ky,15;キーボードのチェック
if ky&1 :px-=move :pk=32 :if px<160 :px=160;カーソルキー左(←)を押した時pxよりmoveを引く:画面からはみ出さないようにpxが0以下にならないようにする
if ky&4 :px+=move :pk=64 :if px>448 :px=448
if ky&2 :py-=move :if py<0 :py=0
if ky&8 :py+=move :if py>448 :py=448
gmode 2 ;透明化処理の為の命令
pos px,py;自機の座標指定
gcopy 3,pk,0,32,32;バッファ画面(ウィンドウ1)より自機画像をコピー
;自機弾発射処理
shottime-- ;連射為の処理
if shottime<0: st=1 ;shottimeが0以下の時、stに1を代入
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)=0 : if st=1{ ;tf(cnt)が0の時=画面に弾がない時、かつstが1の時(shottimeが0以下の時){}内の命令を行う
tx(cnt)=px ;tx(cnt)(弾のx座標)にpx(自機のx座標)の値を代入
ty(cnt)=py-20 ;ty(cnt)(弾のy座標)にpy(自機のy座標)より20引いた値を代入。(弾と自機が重ならないようにする為)
tf(cnt)=1 ;tf(cnt)に1を代入。画面に弾があると言う事
st=0 ;連射の為の処理
shottime=3 ;連射の為の処理
}
ty(cnt)-=12 : if ty(cnt)<-32 : tf(cnt)=0 :ty(cnt)=-32: st=0;弾を進めて画面から出たら弾を消す
if tf(cnt)=1{ ;画面に弾があるとき、{}内の命令を行う
pos tx(cnt),ty(cnt) ;自機弾の座標指定
gcopy 3,96,0,32,32 ;バッファ画面(ウィンドウ1)より自機弾画像をコピー
}
loop
ck_joystick ky,2048 ;Zキーのチェック
if ky&2048 { ;Zキーが押されていた時はmove(自機移動速度)を1にする。そうでなければmoveを3にする
move=1 }else{
move=3
}
;ボム処理
ck_joystick ky,4096 ;Xキーのチェック
if ky&4096 { ;Xキーが押された時は{}内の命令を行う
if (bombcnt=-1)&(nbomb>0) { ;ボムが画面に出てなく、ボム数が0以上の時
nbomb=nbomb-1 ;ボム数を1減らす
bombcnt=0:bombp=17 ;ボムの存在を有にする。ボムアニメの為に変数を用意。
bpx=px-152 : bpy=py-400;ボムの座標指定
}
}
if bombcnt!-1 { ;ボムが画面に有る時。!は-1以外の時という事
repeat emt ;弾の存在を調べ画面に弾がある時は、弾の存在を消す(etf(cnt)=0)
if etf(cnt)<1 : continue
etf(cnt)=0
loop
bombcnt=bombcnt+1 ;ボムの効いている時間処理
if bombcnt=20 { bombcnt=-1 } ;20フレーム過ぎたらボムが効かなくなる
}
if bombcnt!-1 {
repeat emx ;敵の存在を調べ、敵がいる時は敵体力から1を引く(ef(cnt)-)
if ef(cnt)<1 : continue
ef(cnt)-
if ef(cnt)=0 : bbmx(cnt)=ex(cnt)+8 : bbmy(cnt)=ey(cnt)+8 :bbmc(cnt)=17
;敵体力が0になったら爆発させる
loop
}
;敵移動処理
repeat emx ;repeat〜loop間をemx回繰り返す
ent=cnt
et(cnt)++ ;敵出現時間を+
if ef(cnt)<1 : continue ;ef(cnt)が1以下(敵が画面にいない)ならばrepeatに戻る
if enm(cnt)=3 : gosub *em03 ;敵の名前が3の時*em03へ移動
loop
;敵弾発射処理
repeat emt ;repeat〜loop間をemt回繰り返す
if etf(cnt)=1 { ;etf(cnt)が1(敵弾が画面にあるなら){}内の命令を行う
etx(cnt)=etx(cnt)+etxv(cnt) ;敵弾x座標に敵弾移動速度をプラス
ety(cnt)=ety(cnt)+etyv(cnt) ;敵弾y座標に敵弾移動速度をプラス
pos etx(cnt),ety(cnt) ;敵弾の座標指定
gcopy 3,96,48,16,16 ;バッファ画面(ウィンドウ1)より敵弾画像をコピー
if etx(cnt)>480 : etf(cnt)=0 ;敵弾x座標が480以上になったら弾の存在を消す
if etx(cnt)<152 : etf(cnt)=0
if ety(cnt)>480 : etf(cnt)=0
if ety(cnt)<-16 : etf(cnt)=0
}
loop
;敵弾当り判定
repeat emt ;emt回繰り返す
if etf(cnt)=0 : continue
ddx=(etx(cnt)+8)-(px+16) : if ddx<0 : ddx=-ddx ;自機と弾の中心座標の差の絶対値を求める
ddy=(ety(cnt)+8)-(py+16) : if ddy<0 : ddy=-ddy
if (ddx<2)&(ddy<2) { ;x軸とy軸の差が2以下の時、ゲームオーバー
gend=1 ;1にするとゲームオーバー
}
loop
;爆風とボムのアニメ処理
if bombp>0 { ;ボムのアニメ処理変数が0以上の時{}内の命令を行う
bombp- : pos bpx,bpy
gcopy 5,320*(16-bombp),0,320,480
}
repeat emx ;敵のアニメ処理変数が0以上の時{}内の命令を行う
if bbmc(cnt)>0 {
bbmc(cnt)- : pos bbmx(cnt),bbmy(cnt)
gcopy 3,128+48*(16-bbmc(cnt)),0,48,48
}
loop
color 0,0,0 ;色に黒を指定
boxf 0,0,160,480 ;画面右側を黒で塗りつぶす
boxf 480,0,640,480 ;画面左側を黒で塗りつぶす
;スコア表示
font msmincho,18,3 ;フォントをMS明朝に、大きさを18に、イタリック体太字に指定
color 255,255,255 ;色に白を指定
pos 0,0
mes"Escで終了"
pos 496,0
mes"SCORE-"+sc+"-"
pos 496,462
mes"BOMB-"+nbomb+"-"
if gend=1 : gosub *gameover ;gendが1(ゲームオーバーの時)*gameoverに移動
redraw 1 ;メイン画面を更新
await 16 ;これを入れないとパソコンが固まる
gtime=gtime+1 ;タイムテーブルの為の変数
getkey syuryo,27:if syuryo=1:end ;Escキーのチェック。押されたら終了
goto *main ;*mainに戻る
;サブルーチン
*men ;タイムテーブル
if gtime=1 : bx=170 : by=-64 : gosub *eb03
if gtime=126 : bx=406 : by=-64 : gosub *eb03
if gtime=376 : bx=170 : by=-64 : gosub *eb03
if gtime=500 : bx=406 : by=-64 : gosub *eb03
if gtime=1000 : gtime=0
return
*eb03;敵発生処理
repeat emx
if ef(cnt)>0 : continue ;画面に敵がいなければrepeatに戻る
enm(cnt)=3 ;敵の名前
ef(cnt)=30 ;敵の体力
ex(cnt)=bx : ey(cnt)=by ;敵生成位置決定
dx(cnt)=0 : dy(cnt)=1 ;移動方向
et(cnt)=0 ;敵弾生成時間をリセット
break ;repeat〜loop間のループから、強制的に抜け出す
loop
return
*em03;敵移動処理
if et(cnt)>200 : if gtime¥20=0 : gosub *tekitama3 ;敵生成時間が200以上の時かつgtimeを20で割った余りが0の時*tekitama3へ移動
ex(cnt)=ex(cnt)+dx(cnt) ;敵の移動量決定
ey(cnt)=ey(cnt)+dy(cnt) ;敵の移動量決定
if et(cnt)>180 : dy(cnt)=0
if et(cnt)>500 : dy(cnt)=1
if ey(cnt)>480 : ef(cnt)=0 ;画面から消えたら敵の存在を無しにする
pos ex(cnt),ey(cnt) : gmode 2 : gcopy 3,0,96,64,64 ;敵3の表示
;敵と自機との当り判定
ddx=(ex(cnt)+32)-(px+16) : if ddx<0 : ddx=-ddx
ddy=(ey(cnt)+32)-(py+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<32))&(abs(ddy<32)) {
gend=1
}
;自機弾と敵との当り判定
repeat tmx ;repeat〜loop間をtmx回繰り返す
if tf(cnt)<1 : continue ;tf(cnt)が1以下(弾が画面にいない)ならばrepeatに戻る
ddx=(ex(ent)+32)-(tx(cnt)+16) : if ddx<0 : ddx=-ddx
ddy=(ey(ent)+32)-(ty(cnt)+16) : if ddy<0 : ddy=-ddy
if (abs(ddx<32))&(abs(ddy<32)) { ;自機弾と敵のx軸とy軸の座標差を求め(敵と自機弾全て)、どちらも32以下であれば{}}内の命令を行う
tf(cnt)=0 ;弾が当った時は弾の存在を消す
ef(ent)- ;弾が当った時は敵の存在を消す
sc+1000
pos ex(ent),ey(ent)
gcopy 3,192,96,64,64
if ef(ent)=0 : gosub *bomb1
}
loop
return
*tekitama3;敵弾発生処理
edx=ex(ent)+28 : edy=ey(ent)+32
repeat emt
if etf(cnt)>0 : continue ;etfが0(敵弾が画面に無い時)、emn(cnt)が1(敵の名前が1の時)の場合if{}内の命令を行う
eh=eh+1 : etf(cnt)=1 ;弾数の為の処理。弾の存在を有にする
etx(cnt)=double(edx) : ety(cnt)=double(edy) ;弾の初期座標
ds=3 ;敵弾の速さ
r=double(r+0.1) ;弾の角度を実数で計算
etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds ;弾の移動量を角度より計算
if eh>62 : eh=0 :break ;63発弾を撃った時点でrepeatを抜ける
loop
return
*bomb1;敵爆破処理
bbmx(ent)=ex(ent)+8 : bbmy(ent)=ey(ent)+8 ;爆風の座標指定
bbmc(ent)=17 ;爆風アニメの為の変数
return
*gameover
color rnd(255),rnd(255),rnd(255) ;色指定
pos 280,228
mes "Game Over"
pos 230,248
mes"Press X to Continue"
redraw 1
wait 1
ck_joystick ky ;Xキーのチェック。押されたら*startに戻る
if ky=4096 :goto *start
getkey syuryo,27:if syuryo=1:end
goto *gameover
*************************************
HSP3.0使用、CK_JOYFORCE.DLL使用、画像は↓を使用
このスプリクトでは、Zキーを押していないときに弾を発射させて、Zボタンを押した時は自機のスピードを遅くしています。
CAVEシューっぽいですね(汗)
Xキーでボム発射。ボム処理はまだまだですね・・・もっと派手派手にしたいんですが研究中です。
ちなみに、敵移動処理のif gtime¥20=0の20や、敵弾発生処理のr=double(r+0.1)やif eh>62の0.1、62などの数字を弄ると色んな弾幕が撃てます。
こんな事も出来ますよ^^
しかし、筆者の開発マシンはP4/1.7Gのノートなのですが、全体的に処理が重いです。
色んなHSPサイトを見てみてもDirectXを使った方が速度は速くなるようなので、DirectXを使うようにしようか迷ってます。
サイン、コサインを使って自機狙い弾を作る事が出来るようになったんですが、そもそもサイン、コサインを使おうと思った
きっかけは弾幕を作りたいと思ったからです。
サイン、コサインを使う前まではx軸とy軸の移動量を足したり引いたりして弾を撃たせようと思って色々試したのですが
この方法だと、角度もあまり変えられず、弾速もまばらで、綺麗な円状に弾を撃つ事が不可能でした。
それこそ扇状に弾を撃つなんて夢のまた夢って感じです。
ところが、サイン、コサインを使えば比較的簡単に弾幕を撃つ事が出来ます。
試しにスプリクトを書いてみました↓
*************************************
screen 0,240,320,0,0,0 ;メインウインドウ0を240×320で用意
px=112:py=304 ;自機の初期位置
ex=112:ey=100 ;敵の初期位置
dx=8:dy=8 ;敵の移動量
dx=1:dy=1 ;敵弾の移動量
emt=1000;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt ; etxv 敵弾x方向運動量
dim etyv,emt ; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ
gtime=0 ;フレーム数
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
boxf 0,0,240,320 ;指定色で画面を塗りつぶす
;自機移動処理
stick ky,15 ;キーボードのチェック
if ky&1 :px-=4 :if px<0 :px=0
if ky&4 :px+=4 :if px>224 :px=224
if ky&2 :py-=4 :if py<0 :py=0
if ky&8 :py+=4 :if py>304 :py=304
pos px,py ;自機の座標指定
color 0,255,255 : mes "▲" ;青で▲を表示
;敵表示処理
pos ex,ey
color 255,0,0 : mes "■"
;敵弾処理
if gtime¥6=0 : gosub *tama ;gtime÷6の余りが0の時*tamaに移動
repeat emt ;emt回繰り返す
if etf(cnt)=1 { ;敵弾が画面に有る時{}内の命令を行う
etx(cnt)=etxv(cnt)+etx(cnt) ;敵弾のx軸の座標指定
ety(cnt)=etyv(cnt)+ety(cnt) ;敵弾のx軸の座標指定
pos etx(cnt),ety(cnt) ;敵弾の座標指定
color 255,255,0 : mes "*"
if etx(cnt)>240 : etf(cnt)=0 ;敵弾が画面から消えたら存在をなしにする
if etx(cnt)<-16 : etf(cnt)=0
if ety(cnt)>320 : etf(cnt)=0
if ety(cnt)<-16 : etf(cnt)=0
}
loop
gtime+ ;フレーム数をプラス
redraw 1 ;画面を更新
await 16
goto *main ;*mainに戻る
*tama
repeat emt ;emt回繰り返す
if etf(cnt)>0 : continue ;画面に弾がある時はrepeatに戻る
eh=eh+1 ;弾の数の為の計算
etf(cnt)=1 ;弾の存在を有にする
etx(cnt)=double(ex+2) : ety(cnt)=double(ey+2) ;弾の座標を実数で設定
ds=2 ;敵弾の速さ
r=double(r+0.1) ;弾の角度を実数で計算
etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds ;弾の移動量を角度より計算
if eh>62 : eh=0 :break ;63発弾を撃った時点でrepeatを抜ける
loop
return
*************************************
HSP3.0使用
コレを実行すると、円弾幕を角度をちょっとづつ変えながら撃ってきます。
まさに弾幕って感じですね^^

当初、このスプリクトを作っている時に、エラー31 "異なる型を持つ配列変数に代入しました"
が、ずっと出てしまい上手くいかなかったのですが、double命令を使う事により上手く動くようになったので
多分、整数と実数の使い分けが上手くいってなかったんだろうと思っています。
でも、このサンプルでは上手く行くのですが、今作っているSTGに反映させようとすると、エラー31が出てしまうんですよね・・・
悩み中です(涙)
きっかけは弾幕を作りたいと思ったからです。
サイン、コサインを使う前まではx軸とy軸の移動量を足したり引いたりして弾を撃たせようと思って色々試したのですが
この方法だと、角度もあまり変えられず、弾速もまばらで、綺麗な円状に弾を撃つ事が不可能でした。
それこそ扇状に弾を撃つなんて夢のまた夢って感じです。
ところが、サイン、コサインを使えば比較的簡単に弾幕を撃つ事が出来ます。
試しにスプリクトを書いてみました↓
*************************************
screen 0,240,320,0,0,0 ;メインウインドウ0を240×320で用意
px=112:py=304 ;自機の初期位置
ex=112:ey=100 ;敵の初期位置
dx=8:dy=8 ;敵の移動量
dx=1:dy=1 ;敵弾の移動量
emt=1000;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt ; etxv 敵弾x方向運動量
dim etyv,emt ; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ
gtime=0 ;フレーム数
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
boxf 0,0,240,320 ;指定色で画面を塗りつぶす
;自機移動処理
stick ky,15 ;キーボードのチェック
if ky&1 :px-=4 :if px<0 :px=0
if ky&4 :px+=4 :if px>224 :px=224
if ky&2 :py-=4 :if py<0 :py=0
if ky&8 :py+=4 :if py>304 :py=304
pos px,py ;自機の座標指定
color 0,255,255 : mes "▲" ;青で▲を表示
;敵表示処理
pos ex,ey
color 255,0,0 : mes "■"
;敵弾処理
if gtime¥6=0 : gosub *tama ;gtime÷6の余りが0の時*tamaに移動
repeat emt ;emt回繰り返す
if etf(cnt)=1 { ;敵弾が画面に有る時{}内の命令を行う
etx(cnt)=etxv(cnt)+etx(cnt) ;敵弾のx軸の座標指定
ety(cnt)=etyv(cnt)+ety(cnt) ;敵弾のx軸の座標指定
pos etx(cnt),ety(cnt) ;敵弾の座標指定
color 255,255,0 : mes "*"
if etx(cnt)>240 : etf(cnt)=0 ;敵弾が画面から消えたら存在をなしにする
if etx(cnt)<-16 : etf(cnt)=0
if ety(cnt)>320 : etf(cnt)=0
if ety(cnt)<-16 : etf(cnt)=0
}
loop
gtime+ ;フレーム数をプラス
redraw 1 ;画面を更新
await 16
goto *main ;*mainに戻る
*tama
repeat emt ;emt回繰り返す
if etf(cnt)>0 : continue ;画面に弾がある時はrepeatに戻る
eh=eh+1 ;弾の数の為の計算
etf(cnt)=1 ;弾の存在を有にする
etx(cnt)=double(ex+2) : ety(cnt)=double(ey+2) ;弾の座標を実数で設定
ds=2 ;敵弾の速さ
r=double(r+0.1) ;弾の角度を実数で計算
etxv(cnt)=cos(r)*ds : etyv(cnt)=sin(r)*ds ;弾の移動量を角度より計算
if eh>62 : eh=0 :break ;63発弾を撃った時点でrepeatを抜ける
loop
return
*************************************
HSP3.0使用
コレを実行すると、円弾幕を角度をちょっとづつ変えながら撃ってきます。
まさに弾幕って感じですね^^
当初、このスプリクトを作っている時に、エラー31 "異なる型を持つ配列変数に代入しました"
が、ずっと出てしまい上手くいかなかったのですが、double命令を使う事により上手く動くようになったので
多分、整数と実数の使い分けが上手くいってなかったんだろうと思っています。
でも、このサンプルでは上手く行くのですが、今作っているSTGに反映させようとすると、エラー31が出てしまうんですよね・・・
悩み中です(涙)
自機狙い弾を作ろうと思って調べた所、サイン、コサイン、アークタンジェントを使用すれば簡単に作れると言う事がわかりました。
ただ、HSPでは標準でサイン、コサイン、タンジェントを扱う命令がないと思っていたので、5月7日書いたような平方根を利用してのスプリクトを作りました。
しかし、実はHSP3.0からは標準でサイン、コサイン、アークタンジェントを扱う命令が追加されていたようで
先日書いたようなややこしいスプリクトを書かなくても自機狙い弾を作れる事がわかりました。
とりあえず簡単な自機狙いスプリクトを作ってみました。
*************************************
screen 0,240,320,0,0,0 ;メインウインドウ0を240×320で用意
px=112:py=304 ;自機の初期位置
ex=0:ey=10 ;敵の初期位置
dx=8:dy=8 ;敵の移動量
dx=1:dy=1 ;敵弾の移動量
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
boxf 0,0,240,320 ;指定色で画面を塗りつぶす
;自機移動処理
stick ky,15 ;キーボードのチェック
if ky&1 :px-=4 :if px<0 :px=0
if ky&4 :px+=4 :if px>224 :px=224
if ky&2 :py-=4 :if py<0 :py=0
if ky&8 :py+=4 :if py>304 :py=304
pos px,py ;自機の座標指定
color 0,0,255 : mes "▲" ;青で▲を表示
;敵移動処理
ex=ex+dx ;敵座標に移動量をプラス
if(ex<0)|(ex>224) :dx=-dx ;画面端で反転
ey=ey+dy
if(ey<0)|(ey>304) :dy=-dy
pos ex,ey
color 255,0,0 : mes "■"
;敵弾処理
if etf=0 { ;敵弾が画面にない時{}内の処理を行う
ds=5 ;敵弾の速さ
r=atan(py-ey, px-ex) ;敵と自機との角度を求める
etxv = cos(r)*ds ;敵弾のx軸方向の移動量
etyv = sin(r)*ds ;敵弾のy軸方向の移動量
etf=1 ;弾の存在を有にする
etx=ex : ety=ey ;敵弾の初期座標
}
if etf=1 { ;敵弾が画面に有る時{}内の命令を行う
etx=etxv+etx ;敵弾のx軸の座標指定
ety=etyv+ety ;敵弾のx軸の座標指定
pos etx,ety ;敵弾の座標指定
color 255,255,0 : mes "●"
if etx>240 : etf=0 ;敵弾が画面から消えたら存在をなしにする
if etx<0 : etf=0
if ety>320 : etf=0
if ety<0 : etf=0
}
redraw 1 ;画面を更新
await 1
goto *main ;*mainに戻る
*************************************
HSP3.0使用
コレを実行すると敵「■」が弾「●」を自機「▲」に向かって撃ってきます。
簡単に説明すると、まずアークタンジェントを使用して敵と自機との角度を求め、その角度を元に弾の移動量を決めて移動させています。
ただ、筆者自身まだサイン、コサイン、タンジェントについての理解が浅く、コレを応用して今作ってるSTGに使う事が出来ていません。
(なぜが、命中精度が落ちてしまうんですよね・・・)
かれこれ3〜4日考えてるんですが、イマイチ上手く動いてくれません。でもコレが上手く動けば弾幕なんかも作りやすくなると思うので
もうちょっと頑張ってみよう。
上記スプリクトを実行するとこんな感じ↓

どこに動いても自機を狙ってきます^^
しかし学生の頃、もう二度とサイン、コサイン、タンジェントを使う日はこないだろうと思っていたのですが
まさか登場するとは(笑)
ただ、HSPでは標準でサイン、コサイン、タンジェントを扱う命令がないと思っていたので、5月7日書いたような平方根を利用してのスプリクトを作りました。
しかし、実はHSP3.0からは標準でサイン、コサイン、アークタンジェントを扱う命令が追加されていたようで
先日書いたようなややこしいスプリクトを書かなくても自機狙い弾を作れる事がわかりました。
とりあえず簡単な自機狙いスプリクトを作ってみました。
*************************************
screen 0,240,320,0,0,0 ;メインウインドウ0を240×320で用意
px=112:py=304 ;自機の初期位置
ex=0:ey=10 ;敵の初期位置
dx=8:dy=8 ;敵の移動量
dx=1:dy=1 ;敵弾の移動量
*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
boxf 0,0,240,320 ;指定色で画面を塗りつぶす
;自機移動処理
stick ky,15 ;キーボードのチェック
if ky&1 :px-=4 :if px<0 :px=0
if ky&4 :px+=4 :if px>224 :px=224
if ky&2 :py-=4 :if py<0 :py=0
if ky&8 :py+=4 :if py>304 :py=304
pos px,py ;自機の座標指定
color 0,0,255 : mes "▲" ;青で▲を表示
;敵移動処理
ex=ex+dx ;敵座標に移動量をプラス
if(ex<0)|(ex>224) :dx=-dx ;画面端で反転
ey=ey+dy
if(ey<0)|(ey>304) :dy=-dy
pos ex,ey
color 255,0,0 : mes "■"
;敵弾処理
if etf=0 { ;敵弾が画面にない時{}内の処理を行う
ds=5 ;敵弾の速さ
r=atan(py-ey, px-ex) ;敵と自機との角度を求める
etxv = cos(r)*ds ;敵弾のx軸方向の移動量
etyv = sin(r)*ds ;敵弾のy軸方向の移動量
etf=1 ;弾の存在を有にする
etx=ex : ety=ey ;敵弾の初期座標
}
if etf=1 { ;敵弾が画面に有る時{}内の命令を行う
etx=etxv+etx ;敵弾のx軸の座標指定
ety=etyv+ety ;敵弾のx軸の座標指定
pos etx,ety ;敵弾の座標指定
color 255,255,0 : mes "●"
if etx>240 : etf=0 ;敵弾が画面から消えたら存在をなしにする
if etx<0 : etf=0
if ety>320 : etf=0
if ety<0 : etf=0
}
redraw 1 ;画面を更新
await 1
goto *main ;*mainに戻る
*************************************
HSP3.0使用
コレを実行すると敵「■」が弾「●」を自機「▲」に向かって撃ってきます。
簡単に説明すると、まずアークタンジェントを使用して敵と自機との角度を求め、その角度を元に弾の移動量を決めて移動させています。
ただ、筆者自身まだサイン、コサイン、タンジェントについての理解が浅く、コレを応用して今作ってるSTGに使う事が出来ていません。
(なぜが、命中精度が落ちてしまうんですよね・・・)
かれこれ3〜4日考えてるんですが、イマイチ上手く動いてくれません。でもコレが上手く動けば弾幕なんかも作りやすくなると思うので
もうちょっと頑張ってみよう。
上記スプリクトを実行するとこんな感じ↓
どこに動いても自機を狙ってきます^^
しかし学生の頃、もう二度とサイン、コサイン、タンジェントを使う日はこないだろうと思っていたのですが
まさか登場するとは(笑)
カレンダー
| 02 | 2026/03 | 04 |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
リンク
カテゴリー
最新記事
(04/04)
(12/26)
(12/25)
(11/17)
(10/11)
プロフィール
HN:
kt.
性別:
男性
自己紹介:
プログラミング経験は昔ファミリーベーシックでちょっとさわったくらい。
好きなSTGは、怒首領蜂大往生、エスプガルーダ(2)等の弾幕STGやら雷電シリーズなんかの非弾幕、バトルガレッガ、グラディウスシリーズ、R-TYPE等、STGなら何でも好きです。
音楽がカッコイイSTGが特に好きで、並木学氏は最高!
好きなSTGは、怒首領蜂大往生、エスプガルーダ(2)等の弾幕STGやら雷電シリーズなんかの非弾幕、バトルガレッガ、グラディウスシリーズ、R-TYPE等、STGなら何でも好きです。
音楽がカッコイイSTGが特に好きで、並木学氏は最高!
ブログ内検索
最古記事