2018年 6月1日
今回はいただいたコメントに基づいてサブウエポン(複武装、特殊攻撃)要素をつけたいと思います。
その前にコメントいただいた方、発見と返事が送れて済みませんでした。
ブログ開設以来、長い事コメント 0が常態だったので、確認する習慣が無いとか、確認する方法とかよく分からなかったので。
以後は確認するようにします。
コメントありがとうございました。
さてサブウエポンですが、例として折角エクセリオンを挙げてもらったのもあり、とりあえずそれっぽくしてみました。
バルカン、クリックで一定数発射、弾数制限有り。
弾数の増やし方は色々方法はありますが、とりあえず今回はエクセリオン方式で敵を倒したら一定数増えます。
それと前回のソースにバグがありました。
repeat eb ; 敵との当たり判定
if ef(cnt)=0 : break
continue(次を繰り返せ)と書かなくてはいけない所を break(終了しろ)と書いたために、その f(フラグ)の敵が 0なら以降当たり判定がなくなるという。
つまり少し謎のすり抜けがあったかもしれません。
ブログの表記は直しますが、ゲームは HTML編集しなければいけないし、めんどうなのでそのままにします(今回のは直ってます)
今回は問題が発生して、画面がちらつく。
表示の量が多いのか、計算が多いのか、別の理由なのかイマイチ分からないのでその検証は次回以降にする。
ただ自分の意見としては素直に JAVAとか他の言語やった方が良いとは思う、スペック的にもプロで仕事目指すにしても。
HSPは、まあ使い方次第ではあるけど、あくまでも入門だと割り切った方が良いだろうね。
少なくともこれでブラウザ用の STGみたいな動きのあるものを、というのは少し無謀かもしれない。
(スマホでもちらついたので別の原因かもしれない、PCのウインドウ起動なら問題無い
それと普通の HSPと HSPdishの webGL要するにブラウザ版とまた違うので注意
そしてアンドロイドアプリとして作るのとも違う、これはブラウザ版なのだ
どの道総じてブラウザは重い)
まあ、もうちょっとやってみないと何とも言えないかな。
今回はスマホ用にクリック発射を実装したけど、ただボタン押すだけじゃ無くて、放してる常態から一定フレーム内押してもう一度放したら発射。
長押しでは発射されない仕組みになってる。
後はサブウエポンのバルカンは 1フレームに 3発同時発射、最初の位置を 0~2回分後退させておく、という手法をとった。
ただ 1フレームのスピードと計算は前回と同じなので、単に 1フレームに同時3発発射というだけの事になってる。
つまり今回はまだスピード 20 × 3回で計算をしてるが、次は 60 × 1回で、線との当たり判定をしたいとは思ってる。
それと集弾率をランダム座標では無くて、ランダムラジアン(円周率)にした。
ただしメインショットは着弾点の特定が難しかったので、止めにしてそのままにしてる。
それでは今回のソース、バルカンの要素が増えてる、変数とか処理とかはショットや敵とほとんど同じ。
← バルカン
; 企画第一弾 : 1画面防衛シューティングを作ろう ; var.0.005 #include "hsp3dish.as" ; HSPdishの宣言 randomize ; 乱数の初期化 pai=3.141593 pai2=pai*2 rad45=0.7853982 ; ラジアンで45度 rad90=1.5707965 ; ラジアンで90度 wx=640 ; 画面の大きさx wy=360 ; 画面の大きさy gmode 2 jw=1 : jo=20 : jo2=jo/2 ; 自機 celload "jiki_1.png",jw celdiv jw,jo,jo,jo2,jo2 sw=2 : so=6 : so2=so/2 ; ショット celload "shot_1.png",sw celdiv sw,so,so,so2,so2 ew=3 : eo=20 : eo2=eo/2 ; 敵 celload "ene_1.png",ew celdiv ew,eo,eo,eo2,eo2 cw=4 : co=32 : co2=co/2 ; カーソル celload "csr_2.png",cw celdiv cw,co,co,co2,co2 hw=5 : ho=16 : ho2=ho/2 ; ヒット celload "hit_4.png",hw celdiv hw,ho,ho,ho2,ho2 vw=6 : vo=16 : vo2=vo/2 ; バルカン celload "vulcan_1.png",vw celdiv vw,vo,vo,vo2,vo2 ; 自機 ---------- jx=wx/2 ; プレイヤーの座標x jy=wy/2 ; プレイヤーの座標y jx1=jx-jo2 ; 自機左座標 jx2=jx+jo2 ; 自機右座標 jy1=jy-jo2 ; 自機上座標 jy2=jy+jo2 ; 自機下座標 ; SHOT ---------- sb=20 ; ショット最大数 dim sf,sb ; ショット発射フラグ ddim sx,sb ; ショット座標x ddim sy,sb ; ショット座標y ddim sdx,sb ; ショット移動量x ddim sdy,sb ; ショット移動量y ddim sr,sb ; 向き dim sxb,sb ; 終点座標x dim syb,sb ; 終点座標y ddim skn,sb ; 現移動距離 ddim skb,sb ; 最終移動距離 ssp=20.0 ; スピード skc=3 ; 1フレームで移動計算する回数 sc=0 ; 出現カウント scb=0 ; 発射間隔(フレーム) sp=5 ; パワー su=32 ; 揺れ幅(集弾値) ; VULCAN ---------- vb=30 ; バルカン最大数 dim vf,vb ; バルカン発射フラグ ddim vx,vb ; バルカン座標x ddim vy,vb ; バルカン座標y ddim vdx,vb ; バルカン移動量x ddim vdy,vb ; バルカン移動量y ddim vr,vb ; 向き vkc=3 ; 1フレームに出現する数 vsp=20.0 ; スピード vp=3 ; パワー vu=30 ; 揺れ幅(集弾値) vnb=180 ; 1クリックで発射される数 vc=0 ; 残弾数 vcb=20 ; 1つ敵を倒した時に増える数 ; ENEMY ---------- eb=40 ; 敵最大数 dim ef,eb ; 出現フラグ dim ehp,eb ; 耐久度 ddim ex,eb ; 敵座標x ddim ey,eb ; 敵座標y ddim edx,eb ; 敵移動量x ddim edy,eb ; 敵移動量y ddim er,eb ; 向き ehpb=60 ; 耐久度 esp=0.5 ; 敵スピード ec=0 ; 出現カウント ecb=10 ; 出現間隔(フレーム) scr=0 ; スコア hiscr=0 ; ハイスコア kf=0 ; キーを押してるかフラグ kc=0 ; 何フレームキーを押してるか *main mainf=0 ; ゲームフラグ repeat ; メインループ ---------------------------------- switch mainf case 0 ; タイトル ---------- stick k : if k=0 : swbreak ; ボタンでゲーム再開 mainf=1 swbreak ; ---------- case 1 ; ゲーム ---------- ; 自機 ---------- x=mousex : y=mousey ; マウスの座標 stick k,256 ; マウスクリック ; SHOT ---------- repeat 1 ; 発射 if sc>0 : sc- : break ; ウエイト中 repeat sb if sf(cnt)!0 : continue ; 使用中 sf(cnt)=1 ; 使用フラグon sx(cnt)=double(jx) : sy(cnt)=double(jy) ; 初期座標 xx=x-su/2+rnd(su) ; ショットの着弾点x yy=y-su/2+rnd(su) ; ショットの着弾点y xn=double(xx-jx) ; 自機とマウスの距離x yn=double(yy-jy) ; 自機とマウスの距離y rad=atan(xn,yn) ; 距離xyから角度を求める sr(cnt)=-rad+pai ; 向き sdx(cnt)=sin(rad)*ssp ; 角度とスピードから移動量xを求める sdy(cnt)=cos(rad)*ssp ; 角度とスピードから移動量yを求める sxb(cnt)=xx : syb(cnt)=yy ; 終点座標 skn(cnt)=0.0 ; 現移動距離をリセット x2=xx-jx : y2=yy-jy skb(cnt)=sqrt(x2*x2+y2*y2); 最終移動距離 break loop sc=scb ; 発射ウエイト loop repeat sb : scn=cnt ; ショット移動処理 if sf(scn)=0 : continue ; 無し repeat skc : cnt2=cnt ; 1ショットの移動繰り返し ==================== sx(scn)+=sdx(scn) ; xの移動 sy(scn)+=sdy(scn) ; yの移動 skn(scn)+=ssp ; どれだけ距離を進んだか if skn(scn)>=skb(scn) { ; 終点判定 sx(scn)=double(sxb(scn)) sy(scn)=double(syb(scn)) sf(scn)=-1 ; 着弾フラグ } sx1=int(sx(scn))-so2 ; ショット左座標 sx2=int(sx(scn))+so2 ; ショット右座標 sy1=int(sy(scn))-so2 ; ショット上座標 sy2=int(sy(scn))+so2 ; ショット下座標 repeat eb ; 敵との当たり判定 if ef(cnt)=0 : continue ex1=int(ex(cnt))-eo2 ; 敵左座標 ex2=int(ex(cnt))+eo2 ; 敵右座標 ey1=int(ey(cnt))-eo2 ; 敵上座標 ey2=int(ey(cnt))+eo2 ; 敵下座標 if sx1<ex2 and ex1<sx2 and sy1<ey2 and ey1<sy2 { sf(scn)=-1 ehp(cnt)-=sp ; 耐久度- if ehp(cnt)<=0 { ; 倒したか ef(cnt)=0 ; 当たった敵とショットを消す vc+=vcb ; バルカンの残弾数を増やす scr+ ; スコア if hiscr<scr : hiscr=scr ; ハイスコアの更新 break } } loop if sf(scn)=1 : if sx2<0 or wx<sx1 or sy2<0 or wy<sy1 : sf(scn)=0 : break ; 場外でフラグ off if sf(scn)=-1 : break ; 着弾してる loop ; ==================== loop ; VULCAN ---------- repeat 1 ; バルカンの入力判定 if k=256 : kf=1 : kc+ : break ; 押している if kf=0 : break ; 一度も押してない kf=0 ; 押しフラグリセット if kc>2 : kc=0 : break ; 2フレーム以上押していた if vc>0 and vn=0 : vn+=vnb ; 発射要求数 kc=0 loop repeat vkc : cnt2=cnt ; 1フレームに発射される数 if vn=0 or vc=0 : break ; 発射要求数、または残弾が0 repeat vb : vcn=cnt if vf(vcn)!0 : continue ; 使用中 vn- ; 発射要求数- vc- : if vc=0 : vn=0 ; 残弾- vf(vcn)=1 ; 使用フラグon vx(vcn)=double(jx) : vy(vcn)=double(jy) ; 初期座標 xn=double(x-jx) ; 自機とマウスの距離x yn=double(y-jy) ; 自機とマウスの距離y rd=double(-(vu/2)+rnd(vu+1))/100.0 ; 揺れ幅(ラジアン) rad=atan(xn,yn)+rd ; 距離xyから角度を求める vr(vcn)=-rad+pai ; 向き vdx(vcn)=sin(rad)*vsp ; 角度とスピードから移動量xを求める vdy(vcn)=cos(rad)*vsp ; 角度とスピードから移動量yを求める repeat cnt2 vx(vcn)-=vdx(vcn) ; 始点座標をバックさせておくx vy(vcn)-=vdy(vcn) ; 始点座標をバックさせておくy loop break loop loop repeat vkc ; vkc回移動 repeat vb : vcn=cnt ; ショット移動処理 if vf(vcn)=0 : continue ; 無し vx(vcn)+=vdx(vcn) ; xの移動 vy(vcn)+=vdy(vcn) ; yの移動 vx1=int(vx(vcn))-vo2 ; ショット左座標 vx2=int(vx(vcn))+vo2 ; ショット右座標 vy1=int(vy(vcn))-vo2 ; ショット上座標 vy2=int(vy(vcn))+vo2 ; ショット下座標 repeat eb ; 敵との当たり判定 if ef(cnt)=0 : continue ex1=int(ex(cnt))-eo2 ; 敵左座標 ex2=int(ex(cnt))+eo2 ; 敵右座標 ey1=int(ey(cnt))-eo2 ; 敵上座標 ey2=int(ey(cnt))+eo2 ; 敵下座標 if vx1<ex2 and ex1<vx2 and vy1<ey2 and ey1<vy2 { vf(vcn)=-1 ehp(cnt)-=vp ; 耐久度- if ehp(cnt)<=0 { ; 倒したか ef(cnt)=0 ; 敵を消す ;vc+=vcn ; バルカンの残弾数を増やす vcr+ ; スコア if hiscr<scr : hiscr=scr ; ハイスコアの更新 break } } loop if vf(vcn)=1 : if vx2<0 or wx<vx1 or vy2<0 or wy<vy1 : vf(vcn)=0 : continue ; 場外でフラグ off if vf(vcn)=-1 : continue ; 着弾してる loop loop ; ENEMY ---------- repeat 1 ; 敵出現 if ec>0 : ec- : break ; ウエイト中 repeat eb ; フラグ確認 if ef(cnt)>0 : continue ; 使用中 ef(cnt)=1 ; 使用フラグon ehp(cnt)=ehpb r=rnd(4) ; 出現方向 if r=0 : exs=rnd(wx)-eo2 : eys=0-eo2 ; 上 if r=1 : exs=rnd(wx)-eo2 : eys=wy+eo2 ; 下 if r=2 : exs=-eo2 : eys=rnd(wy)-eo2 ; 左 if r=3 : exs=wx+eo2 : eys=rnd(wy)-eo2 ; 右 ex(cnt)=double(exs) ; 初期位置x ey(cnt)=double(eys) ; 初期位置y xn=double(jx-exs) ; 敵と自機の距離x yn=double(jy-eys) ; 敵と自機の距離y rad=atan(xn,yn) ; 距離xyから角度を求める edx(cnt)=sin(rad)*esp ; 角度とスピードから移動量xを求める edy(cnt)=cos(rad)*esp ; 角度とスピードから移動量yを求める er(cnt)=-rad+pai ; 向き ec=ecb ; 出現ウエイト break ; 登録終わり loop loop repeat eb ; 敵移動処理 if ef(cnt)=0 : continue ; 無し ex(cnt)+=edx(cnt) : ey(cnt)+=edy(cnt) ; 移動 ex1=int(ex(cnt))-eo2 ; 敵左座標 ex2=int(ex(cnt))+eo2 ; 敵右座標 ey1=int(ey(cnt))-eo2 ; 敵上座標 ey2=int(ey(cnt))+eo2 ; 敵下座標 if jx1<ex2 and ex1<jx2 and jy1<ey2 and ey1<jy2 { mainf=2 : break ; 自機と当たりで GAME OVER } if ex2<0 or wx<ex1 or ey2<0 or wy<ey1 : ef(cnt)=0 ; 枠外でフラグ off loop swbreak ; ---------- case 2 ; gameover ---------- stick k : if k=0 : swbreak ; ボタンでゲーム再開 repeat sb sf(cnt)=0 ; ショットリセット loop repeat vb vf(cnt)=0 ; バルカンリセット loop vn=0 : vc=0 ; 残弾リセット repeat eb ef(cnt)=0 ; 敵リセット loop scr=0 ; スコアリセット mainf=0 ; ゲーム再開 swbreak ; ---------- swend redraw 0 ; 表示 ==================== color 1,1,1 : boxf : color 255,255,255 ; 画面クリア pos jx,jy : celput jw ; 自機 repeat eb ; 敵 if ef(cnt)=0 : continue ; 無い pos ex(cnt),ey(cnt) : celput ew,,,,er(cnt) ; 敵 loop repeat sb ; ショット if sf(cnt)=0 : continue ; 無い pos sx(cnt),sy(cnt) if sf(cnt)=-1 : celput hw,,,,sr(cnt) : sf(cnt)=0 : continue ; フラグリセット celput sw ; ショット loop repeat vb ; バルカン if vf(cnt)=0 : continue ; 無い pos vx(cnt),vy(cnt) if vf(cnt)=-1 : celput hw,,,,vr(cnt) : vf(cnt)=0 : continue ; フラグリセット celput vw,,,,vr(cnt) ; バルカン loop pos 10,wy-20 : mes vc ; バルカンの残弾表示 repeat vc/10 pos 50+cnt*6,wy-12 : celput vw if cnt=100 : break ; 最大 loop pos x,y : celput cw ; カーソル switch mainf case 0 ; タイトル pos wx/2-120,wy/2-50 : mes "1画面防衛シューティング" pos wx/2-43,wy/2+30 : mes "var.0.005" swbreak case 1 ; ゲーム swbreak case 2 ; gameover pos wx/2-43,wy/2+50 : mes "GAME OVER" swbreak swend pos wx-300,5 : mes "SCORE "+scr pos wx-150,5 : mes "HI SCORE "+hiscr redraw 1 ; ==================== await 1000/15 ; ウエイト、FPS 15 loop ; -------------------------------------------------- return ; 終わり
プログラム解説
入力判定
repeat 1 ; バルカンの入力判定 この前に stick k という命令が実行されていて、kの変数にキー入力の値が入る。 kf=そのキーを押してるか、0=押してない、1=押してる。 kf=1の時、kcを +する、kc=何フレームキーを押してるかのカウント。 再び kf=0になった時、つまりボタンを放した時 kcが 2フレーム以下なら特殊攻撃発動、それ以上押しっ放しなら照準を動かしているものと見る。 要するにポンと押した時だけ発動するようなプログラム。 vc=残弾数、vn=発射数、発射中の変化はしないようにしてる。 |
バルカン
ソースの内容はショットと敵とほとんど同じ。
ショットのソースをコピペして sを vに書き換え、改造して作った。 結局今回はまだ 1フレームに3回動かしている。 |