2018年 5月12日
キャラをグラフィックにする。
座標と当たり判定をすっきりさせ、さらにグラを回転させて向きを表現する。
それからスマホ向けにマウスカーソルでは無くて「照準」のグラを用意する。
スマホではカーソル表示は無いため。
自機
ショット
敵
照準
使用する場合は「名前をつけて画像を保存」でダウンロードして下さい。
ソース
; 企画第一弾 : 1画面防衛シューティングを作ろう ; var.0.003 #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=24 : co2=co/2 ; カーソル celload "csr_1.png",cw celdiv cw,co,co,co2,co2 ; 自機 ---------- 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 ssp=20.0 ; スピード sc=0 ; 出現カウント scb=1 ; 発射間隔(フレーム) ; ENEMY ---------- eb=40 ; 敵最大数 dim ef,eb ; 出現フラグ ddim ex,eb ; 敵座標x ddim ey,eb ; 敵座標y ddim edx,eb ; 敵移動量x ddim edy,eb ; 敵移動量y ddim er,eb ; 向き esp=3.0 ; 敵スピード ec=0 ; 出現カウント ecb=4 ; 出現間隔(フレーム) scr=0 ; スコア hiscr=0 ; ハイスコア *main mainf=0 ; ゲームフラグ repeat ; メインループ ---------------------------------- switch mainf case 0 ; タイトル ---------- stick k : if k=0 : swbreak ; ボタンでゲーム再開 mainf=1 swbreak ; ---------- case 1 ; ゲーム ---------- ; 自機 ---------- x=mousex : y=mousey ; マウスの座標 ; 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) ; 初期座標 xn=double(x-jx) ; 自機とマウスの距離x yn=double(y-jy) ; 自機とマウスの距離y rad=atan(xn,yn) ; 距離xyから角度を求める sdx(cnt)=sin(rad)*ssp ; 角度とスピードから移動量xを求める sdy(cnt)=cos(rad)*ssp ; 角度とスピードから移動量yを求める break loop sc=scb ; 発射ウエイト loop repeat sb : scn=cnt ; ショット移動処理 if sf(scn)=0 : continue ; 無し sx(scn)+=sdx(scn) ; xの移動 sy(scn)+=sdy(scn) ; yの移動 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 { ef(cnt)=0 : sf(scn)=0 ; 当たった敵とショットを消す 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 ; 場外でフラグ off loop ; ENEMY ---------- repeat 1 ; 敵出現 if ec>0 : ec- : break ; ウエイト中 repeat eb ; フラグ確認 if ef(cnt)>0 : continue ; 使用中 ef(cnt)=1 ; 使用フラグon 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 eb ef(cnt)=0 ; 敵リセット loop repeat sb sf(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 sb ; ショット if sf(cnt)=0 : continue ; 無い pos sx(cnt),sy(cnt) : celput sw ; ショット loop repeat eb ; 敵 if ef(cnt)=0 : continue ; 無い pos ex(cnt),ey(cnt) : celput ew,,,,er(cnt) ; 敵 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.003" 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 ; -------------------------------------------------- end ; 終わり
プログラム解説
初期設定
pai=3.141593 pai2=pai*2 rad45=0.7853982 ; ラジアンで45度 円周率。 ゲームプログラムの時は大体書いてる。 jw=1 : 自機のグラフィックバッファNo. celload “jiki_1.png”,jw celdiv jw,jo,jo,jo2,jo2 それから今回はグラの回転表示を行うが、その再の中心点になる。 当たり判定用の 4辺端座標。 たぶんこの程度のプログラムなら速度に影響は無い。 |
メインルーチン
sx1,sx2,sy1,sy2、ex1,ex2,ey1,ey2 今回はこれらショットや敵の当たり判定用の 4辺座標をあらかじめ用意しておく事で、見た目にもスッキリしたと思う。 合わせて場外判定のソースも分かりやすくなった。 そもそも celput(グラ表示)のラジアンの値も独自のような気もするし つまりプログラム的には真上が 0で、時計周り(右回り)に真下までが π(パイ(3,141593))で、そこから真上が 2π(6.28・・・)という仕様らしい。 これはグラフィックが普通上向きだから 0が正位置なら合理的なんだと思う。 今回用意した敵のグラも正位置で上向きだし。 |
表示
pos ex(cnt),ey(cnt) : celput ew,,,,er(cnt) ; 敵 celput が HSPdish用のグラフィック表示命令になります。 先に設定した posの座標に表示します。 ew=グラのバッファNo. er=回転表示角度。 間の,,,,には、その画像バッファの何番目の画像を表示するか(celdivで区切った)と、xとyの拡大縮小表示率が設定できます。 |
今回ショットの大きさを 6ドットにし、当たり判定もその大きさで計算してるので、前回よりエイム(狙う)要素が増したと思います。