忍者ブログ
まったくのプログラミング素人の筆者がC++/HSPを使用してSTG(シューティングゲーム)を作っていく過程を書くブログでしたが最近は脱線気味。プログラミング以外にも、ゲーム関連の記事、日々の戯言など。
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

最初に画面の解像度を考えた時に240×320では画面が小さいので嫌やなーと思い、480×640で作っていたのですが
弾処理やら当り判定やら爆発処理やらを加えていくと目に見えて重たーくなってきました。
CPU占有率もずっと100パーセントのままです。んで最終的にずっと処理落ちしてしまう始末・・・
ゲーム作り始める前に、色んな人のゲームを遊んでいたのですが何でみなさん画面が小さいのだろう?と思ってたんですが納得です。
面倒くさがらずに、画面の解像度をかえるかフルスクリーンにしろって事ですね。

という事で、画面の解像度を下げる事にしました。フルスクリーンの時の表示を640×480で考えて、縦を448×横320で作る事にしました。
なんとなく8で割れる数が良いのかなーと思って、この数字になってます。根拠はありません(汗)

最初に作った画面はこんな感じ↓
jiki.jpg

今回、縮小した画面がコチラ↓
syukusyou1.jpg
かなり小さくなってますが、フルスクリーンにすれば画面いっぱいに表示される(はず)
と言ってもフルスクリーンにする方法は知りません^^;

とりあえず現在の所、当り判定、敵の爆発処理なんかも出来て来て、かなりゲームっぽくなってきました。
スプリクトは、また別の機会に。
PR
ずっとなやんでた自機狙い弾がなんとか上手く動くようになってくれました^^
ただ単に配列変数を二重で使ってしまっていた為に動かなかっただけでした。敵一体一体に弾一個づつ処理しようと思って
二重にしてたんですが、そんな事する必要なかった。敵一体に対し弾全部の処理をすれば良かったんですね。

で、自機狙い弾なのですがこれも敵と自機の方向を計算して、その結果に弾の速さを掛けて距離で割ればよいみたい。
じゃ昨日の使ったMIAさんのスプリクトを使えば良いかな?と思ったら、それでは若干弾の速さが変わるみたい。(計算が正確ではないので)
遊々窓々さんのHSP講座を見てみると、距離を求めるためには・・・
heihoukon.jpgc2=a2+b2
この式で求めるらしい。ちなみにこの式が三平方の定理。遠い昔に習った記憶が・・・今更、役に立つとは思ってもみませんでした。
つまり、自機と敵とのx軸とy軸を足した物の平方根を求めれば距離がわかる訳です。
ただここで問題があるようで、HSPには平方根を扱う命令がないようで、本当に正確な計算が必要な場合は外部プラグインが必要との事。
でも、筆者はとりあえず最初は基本命令だけで作って行こうと思っているので、遊々窓々さんのスプリクトを参考にさせてもらいました。

その平方根の計算方法ですが、まず平方根の計算の答えを沢山用意しておき
自機と敵とのx軸とy軸を足して2乗した物と比べるって方法です。
これだと、メチャクチャ正確には計算出来ませんが、ほぼ正確な計算が出来るのでシューティングでは問題ありません。

そのスプリクトがコレ↓
*************************************
;敵2スプリクト
buffer 1 ;ウィンドウ1をバッファ画面として用意
picload "stg3.gif";画像をバッファ1に読み込み
wxs=480 :wys=640 ;メイン画面の座標指定
screen 0,wxs,wys,0,0,0;メイン画面(ウィンドウ0を480*640で用意)

px=208:py=576;自機の初期位置
tmx=10 ;自機弾の数
dim tx,tmx ;自機弾のX座標の配列変数
dim ty,tmx ;自機弾のY座標の配列変数
dim tf,tmx ;自機弾が画面にあるか無いかを調べる配列変数

emx=120;敵の数
dim ex,emx : dim ey,emx;敵の初期位置
dim dx,emx : dim dy,emx;敵の移動量
dim ef,emx;敵のフラグ
dim em,emx;敵の種類
dim et,emx;敵出現からの時間

emt=100;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt ; etxv 敵弾x方向運動量
dim etyv,emt ; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ

;■ 平方根の準備
dim calc,900 ;平方根の為の配列変数
repeat 900 ;900回繰り返す。640x480の斜めの長さは約832なので
temp=cnt : calc(cnt)=temp*temp ;calc(cnt)にtempの2乗の値を入れておく
loop

*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
boxf 0,0,480,640 ;仮想画面を黒で塗りつぶす

;面データ読み込み
gosub *men ;*men(タイムテーブル)へ移動

;自機移動処理
pk=0 ;自機の傾きの為の変数
stick ky,15;キーボードのチェック
if ky&1 :px-=8 :pk=64 :if px<0 :px=0;カーソルキー左(←)を押した時pxより-8を引く:画面からはみ出さないようにpxが0以下にならないようにする
if ky&4 :px+=8 :pk=128 :if px>416 :px=416
if ky&2 :py-=8 :if py<0 :py=0
if ky&8 :py+=8 :if py>576 :py=576
gmode 2 ;透明化処理の為の命令
pos px,py;自機の座標指定
gcopy 1,pk,0,64,64;バッファ画面(ウィンドウ1)より自機画像をコピー

;敵移動処理
repeat emx ;repeat〜loop間をemx回繰り返す
et(cnt)++ ;敵出現時間を+
if ef(cnt)<1 : continue ;ef(cnt)が1以下(敵が画面にいない)ならばrepeatに戻る
if enm(cnt)=2 : gosub *em02
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 1,192,64,16,16 ;バッファ画面(ウィンドウ1)より敵弾画像をコピー
if etx(cnt)>480 : etf(cnt)=0 ;敵弾x座標が480以上になったら弾の存在を消す
if etx(cnt)<0 : etf(cnt)=0
if ety(cnt)>640 : etf(cnt)=0
if ety(cnt)<0 : etf(cnt)=0
}
loop

redraw 1 ;メイン画面を更新
await 1 ;これを入れないとパソコンが固まる
gtime=gtime+1 ;タイムテーブルの為の変数
goto *main ;*mainに戻る

;サブルーチン
*men ;タイムテーブル
if gtime=150 : bx=0 : by=-64 : gosub *eb02
if gtime=151 : bx=415 : by=-64 : gosub *eb02
if gtime=200 : bx=0 : by=-64 : gosub *eb02
if gtime=201 : bx=415 : by=-64 : gosub *eb02
if gtime=250 : bx=0 : by=-64 : gosub *eb02
if gtime=251 : bx=415 : by=-64 : gosub *eb02

if gtime=252 : gtime=0
return

*eb02
repeat emx
if ef(cnt)>0 : continue
enm(cnt)=2 ;敵の名前
ef(cnt)=1 ;敵の有無(1=有)
ex(cnt)=bx : ey(cnt)=by ;敵生成位置決定
dx(cnt)=3 : dy(cnt)=1 ;移動方向
et(cnt)=0 ;敵弾生成時間をリセット
break ;repeat〜loop間のループから、強制的に抜け出す
loop
return

*em02
ex(cnt)=ex(cnt)+dx(cnt) ;敵の移動量決定
if(ex(cnt)<1)|(ex(cnt)>415) :dx(cnt)=-dx(cnt) ;画面の端まで行ったら反転させる
ey(cnt)=ey(cnt)+dy(cnt) ;敵の移動量決定
if ey(cnt)>640 : ef(cnt)=0 ;画面から消えたら敵の存在を無しにする
pos ex(cnt),ey(cnt) : gmode 2 : gcopy 1,0,128,64,64 ;敵2の表示

;敵弾移動速度&方向決定
dxh=px-ex(cnt) : mx=dxh : if dxh<0 : dxh=0-dxh ;dxhの絶対値の計算
dyh=py-ey(cnt) : my=dyh : if dyh<0 : dyh=0-dyh ;dyhの絶対値の計算
dst=(dxh*dxh)+(dyh*dyh) ;平方根計算の為の変数dst

repeat 900
if dst loop

;敵弾発生処理
sx=px-ex(cnt) ;自機と敵とのx軸の差
sy=py-ey(cnt) ;自機と敵とのy軸の差
txv=sx : tyv=sy ;txv,tyvにそれぞれ代入

if sx<0 : sx=0-sx ;sxの絶対値の計算
if sy<0 : sy=0-sy ;syの絶対値の計算
su=sx : if su;suは自機と敵との大体の距離となる

if su>250 { ;suが250以上の場合if{}内の命令を行う

if ef(cnt)=1 { ;ef(cnt)が1(敵が画面にいる時){}内の命令を行う
if etf(cnt)=0 : if enm(cnt)=2 { ;etf(cnt)が0(画面に敵弾が無い)enm(cnt)が2(敵の名前が2の時){}内の命令を行う
etf(cnt)=1 ;画面に敵弾が存在する
etx(cnt)=ex(cnt)+24 : ety(cnt)=ey(cnt)+55 ;敵弾の初期座標指定。少しずらしておかないと敵と重なって発射される為
ds=7 ;敵弾の速度
etxv(cnt)=mx*ds/dst ;敵弾のx軸の移動量計算
etyv(cnt)=my*ds/dst ;敵弾のy軸の移動量計算
}
}
}
return
************************************
hsp3.0使用 画像は5月6日の画像を使用

これを実行すると、敵が左右にうごきつつ自機狙い弾を撃ってきます。
ずっと悩んでいたので動いた時は感動的でした^^
teki2.jpg
自機狙い弾の処理はあいかわらず上手くいかないので、とりあえず普通にまっすぐ弾を撃つ敵のスプリクトを考える事にした。
解らない事で後回しに出来る事は後回しにしとかないと、挫折してしまいそうなので。
んで弾の画像を書いてみた。
stg3.gif
まだ回転はしないけど回転するアニメーションも書いておいた。敵の数も増えてます。

まず最初に思ったのが、自機と敵との距離が近い時に敵が弾を撃ってくるのはまずいなと。
敵との距離が近い時は弾を撃って欲しくないって事は、自機と敵との距離を計算しなければならない。
自機と敵との距離の計算方法ってのはなんとなくわかるんだけど(X軸とY軸の差を求めれば良いはず)
これまた、スプリクトを書いてみても上手くいかず悩んでいた所、MIA's HomePageさんで素晴らしいスプリクトを発見。
ここのHSP講座の「敵が弾を撃ってみる」の解説の所を読んでみたら自機と敵との距離の計算方法が載っていました。
ここのHSP講座も良い事書いてあってお勧めです^^
自分のスプリクトが上手くいかなかったのは、絶対値ってのを計算してなかったからだと気づいた。
絶対値ってのはWikipediaによると
(実数に関して言うならば、ある実数の絶対値とはその数から負符号を取り除いたものになる。 例えば、3 の絶対値と -3
の絶対値はともに 3 である。 3 も -3 も、どちらも 0 から 3 だけ離れた数だからである。)
だそうです。

これで弾の問題は解決。で、次に思ったのが敵の動きを色々と変化させたいって事。
これは、またまた遊々窓々さんの所のスプリクトを見ていて、敵の生成時間って概念を導入すれば
例えば敵が発生してから、100フレーム目に左に行かせるとか右に行かせるとか、色んな変化が出来るようになった。

試験的に敵のスプリクトを作ってみたのがコレ↓
*************************************
;敵1スプリクト
buffer 1 ;ウィンドウ1をバッファ画面として用意
picload "stg3.gif";画像をバッファに読み込み
screen 0,480,640,0,0,0;メイン画面(ウィンドウ0を480*640で用意)

px=208:py=576;自機の初期位置

emx=12;敵の数
dim ex,emx : dim ey,emx;敵の初期位置
dim dx,emx : dim dy,emx;敵の移動量
dim ef,emx;敵のフラグ
dim em,emx;敵の種類
dim et,emx;敵出現からの時間

emt=100;敵の弾
dim etx,emt : dim ety,emt ;敵弾の位置、移動量
dim etxv,emt; etxv 敵弾x方向運動量
dim etyv,emt; etyv 敵弾y方向運動量
dim etf,emt;敵弾のフラグ

*main
redraw 0 ;仮想画面を指定
color 0,0,0 ;色に黒を指定
boxf 0,0,480,640 ;仮想画面を黒で塗りつぶす

;面データ読み込み
gosub *men ;*men(タイムテーブル)へ移動

;自機移動処理
pk=0 ;自機の傾きの為の変数
stick ky,15;キーボードのチェック
if ky&1 :px-=8 :pk=64 :if px<0 :px=0;カーソルキー左(←)を押した時pxより-8を引く:画面からはみ出さないようにpxが0以下にならないようにする
if ky&4 :px+=8 :pk=128 :if px>416 :px=416
if ky&2 :py-=8 :if py<0 :py=0
if ky&8 :py+=8 :if py>576 :py=576
gmode 2 ;透明化処理の為の命令
pos px,py;自機の座標指定
gcopy 1,pk,0,64,64;バッファ画面(ウィンドウ1)より自機画像をコピー

;敵移動処理
repeat emx ;repeat〜loop間をemx回繰り返す
et(cnt)++
if ef(cnt)<1 : continue ;ef(cnt)が1以下(敵が画面にいない)ならばrepeatに戻る
if enm(cnt)=1 : gosub *em01 ;enm(cnt)(敵の名前)が1ならば*em01へ移動
loop

;敵弾発射処理
repeat emt ;repeat〜loop間をemt回繰り返す
if etf(cnt)=1 { ;etf(cnt)が1(敵弾が画面にある時)if{}内の命令を行う
etx(cnt)=etx(cnt)+etxv(cnt) ;敵弾X軸の移動量
ety(cnt)=ety(cnt)+etyv(cnt) ;敵弾Y軸の移動量
pos etx(cnt),ety(cnt) ;敵弾の座標指定
gcopy 1,192,64,16,16 ;バッファ画面(ウィンドウ1)より敵弾画像をコピー
if etx(cnt)>480 : etf(cnt)=0 ;敵弾座標が480以上になったら敵弾の存在を消す
if etx(cnt)<0 : etf(cnt)=0
if ety(cnt)>640 : etf(cnt)=0
if ety(cnt)<0 : etf(cnt)=0
}
loop

redraw 1 ;メイン画面を更新
await 1 ;これを入れないとパソコンが固まる
gtime=gtime+1 ;タイムテーブルの為の変数
goto *main ;*mainに戻る

*men ;タイムテーブル
if gtime=1 : bx=0 : by=-64 : gosub *eb01;gtimeが0の時、bxに0をbyに-64を代入し*eb01に移動
if gtime=2 : bx=416 : by=-64 : gosub *eb01
if gtime=50 : bx=80 : by=-64 : gosub *eb01
if gtime=51 : bx=336 : by=-64 : gosub *eb01
if gtime=100 : bx=160 : by=-64 : gosub *eb01
if gtime=101 : bx=256 : by=-64 : gosub *eb01

if gtime=252 : gtime=0
return

*eb01
repeat emx ;repeat〜loop間をemx回繰り返す
if ef(cnt)>0 : continue ;ef(cnt)が0以上(すでに敵が画面にいる)ならばrepeatに戻る
enm(cnt)=1 ;敵の名前
ef(cnt)=1 ;敵の有無(1=有)
ex(cnt)=bx : ey(cnt)=by ;敵生成位置決定
dx(cnt)=0 : dy(cnt)=2 ;移動方向
et(cnt)=0 ;敵弾生成時間をリセット
break ;repeat〜loop間のループから、強制的に抜け出す
loop
return

*em01
ek=0 ;敵画像傾きの為の変数
if et(cnt)>150 : if ex(cnt)<240 : dx(cnt)=-3 : ek=64 ;敵生成時間が150以上になった時ex(cnt)(敵のX座標)の値が240以下(画面より左側)ならdx(cnt)(敵のx軸の移動量)に-3を代入しekに64を代入する
if et(cnt)>150 : if ex(cnt)>240 : dx(cnt)=3 : ek=128
ex(cnt)=ex(cnt)+dx(cnt) : ey(cnt)=ey(cnt)+dy(cnt) ;敵の移動量決定
if ey(cnt)>640 : ef(cnt)=0 ;画面から消えたら敵の存在を無しにする
pos ex(cnt),ey(cnt) : gmode 2 : gcopy 1,ek,64,64,64 ;敵1の表示

;敵弾発生処理
sx=px-ex(cnt) ;自機と敵とのx軸の差
sy=py-ey(cnt) ;自機と敵とのy軸の差
txv=sx : tyv=sy ;txv,tyvにそれぞれ代入

if sx<0 : sx=0-sx ;sxの絶対値の計算
if sy<0 : sy=0-sy ;syの絶対値の計算
su=sx : if su;suは自機と敵との大体の距離となる

if su>250 { ;suが250以上の場合if{}内の命令を行う
if ef(cnt)=1 { ;efが1(敵が画面にいる時)の場合if{}内の命令を行う
if etf(cnt)=0 : if enm(cnt)=1 { ;etfが0(敵弾が画面に無い時)、emn(cnt)が1(敵の名前が1の時)の場合if{}内の命令を行う
etx(cnt)=ex(cnt)+24 : ety(cnt)=ey(cnt)+55 ;etx(cnt)にex(cnt)+24を代入。ety(cnt)にey(cnt)+55を代入(弾の初期座標なので、ちょっとずらさないと敵と重なって発射されてしまう)
etf(cnt)=1: etxv(cnt)=0 : etyv(cnt)=5 ;etf(cnt)を1に(敵弾が存在する)、etxv(cnt)を0に(敵弾のX軸移動量)、etyv(cnt)を5に(敵弾のY軸移動量)
}
}
}
return
*************************************
hsp3.0使用 画像は上の画像を使用

コレを実行すると敵が上から出てきて画面の真中位まで来たら、画面より左側の敵は左に、右側の敵は右に去っていくように動く。
んで、弾も自機が近づくと撃たなくなる。ついでに、傾きのアニメーションも入れてみた。アニメの入れ方は自機の傾きのアニメと同じ手法。

実行させるとこんな感じ
tama1.jpg
なんか考えるのが面白くなってきた。
あーわからん!とりあえず、今まで作ったスプリクトを合体させて背景スクロールさせながら敵が出て自機を動かして
って所までは出来たけど、敵弾処理でかなりつまづいてます。
弾をまっすぐ撃ってくるようには出来るんだけど、自機狙い弾が上手くいかない・・・
自機狙ってみたり、明後日の方向に撃ってみたりで、どうなってんだ?て感じ。
かれこれ数時間格闘してみたけど、解決しないので今日はもう寝よう。

今の所こんな感じ↓
tama1.jpg
なかなかSTGっぽくなって来た。
敵も出てきたし、今度は敵弾だーと思ってたんですが、ちょっと疲れてきたのと
背景があまりにも寂しいので、先に背景を作ってみようって事で作ってみました。

s397.jpg
と言っても素材を借りてきて、ほんのちょっと加工しただけですが(汗)
素材はデジタル素材の部屋さんから借りました。ここの素材はカッコイイのばかりで見てるだけでも楽しくなってきます^^

で肝心のスクロール処理なんですが、買った本にスプリクトは載ってたんですが(STGゲームごと)肝心の処理の部分については
殆ど説明が載ってなかったので理解するのに苦しみました。
そのスプリクトを見ながら、スクロールの部分を抜き出したのがコレ↓
*************************************
;背景のスクロール
buffer 2 ;ウィンドウ2をバッファ画面として用意
picload "s397.jpg" ;画像をバッファに読み込み
ssp=645 ;スクロール速度

wxs=480 :wys=640 ;メイン画面の変数
screen 0,wxs,wys ;メイン画面(ウィンドウ0)を480×640ドットで出す

*main
redraw 0 ; 画面に反映しない(仮想画面は書き換わる)
gmode 1 ; ノーマルコピーモード
scr=(scr+ssp)¥wys ;スクロール速度決定。(¥は割り算のあまり。)
pos 0,scr :gcopy 2,0,0,wxs,wys-scr ;下側の背景のコピー座標とコピーする画像の大きさを決めてコピー

if scr!0 { pos 0,0 ;
gcopy 2,0,wys-scr,wxs,scr ;
} ;上側の背景のコピー座標と画像の大きさを決めてコピー

redraw 1 ;メイン画面を更新
await 1 ;これを入れないとパソコンが固まる
goto *main ;*mainに戻る
*************************************
hsp3.0使用 画像は上の画像を使用

処理としては、まず画像をメイン画面よりちょっと下に表示して、上の空いた部分に
画像の下の部分をもってきて表示。
で、更にもうちょっと下に画像を表示して、上の空いた部分に画像の下の部分を持ってきて表示ってのを延々繰り返しています。
スプリクトをみれば、大体なにをしているか?ってのはわかるんですが、一からコレを作れと言われると、とても思いつきそうにありません(汗)

実は、このスプリクトも本には「ssp=645」の部分が「ssp=ginfo_winy-wys」となっていて
この部分が何をしているのか全く理解出来ていません。
特にginfo_winyというのが何なのか?(ヘルプを見るとシステム変数/現在の操作先ウィンドウの初期化Yサイズが代入されています。)
って書いてあるんだけど、んじゃ640-640で0じゃないの?って思うんですが違うんでしょうね・・・そもそもシステム変数ってなんだ?
まだまだ修行が足りないようです。

一応、ginfo_winyってのを使わなくてもスクロールはするので、解らない事は後回しにしときます。
上記スプリクトを実行すると・・・
scr1.jpg

無事スクロールしてくれました^^
ssp=645の数字を増やすと超高速スクロールも可能です。
Twitter
カレンダー
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/20 kt.]
[04/19 うぇむ]
[11/24 kt.]
[11/21 NONAME]
[11/24 kt.]
プロフィール
HN:
kt.
性別:
男性
自己紹介:
プログラミング経験は昔ファミリーベーシックでちょっとさわったくらい。
好きなSTGは、怒首領蜂大往生、エスプガルーダ(2)等の弾幕STGやら雷電シリーズなんかの非弾幕、バトルガレッガ、グラディウスシリーズ、R-TYPE等、STGなら何でも好きです。
音楽がカッコイイSTGが特に好きで、並木学氏は最高!
ブログ内検索
忍者ブログ [PR]