2018年 5月2日
製作がほとんど進んでなくで、データの構造を 1ヶ月もずっと考えてるけどまだ形になってない。
だから報告する事が無いんだけど、折角のゴールデンウィークだし、じゃあ別の企画をと思ってコメント参加型の簡単ブラウザゲームを作っていってみる事にした。
1マップ防衛シューティングをコメントを参考にしながら作っていく
ほんとは作りたいゲームアイデアだけは沢山あるんだけど形にするのが大変で、今回ももう 1年も使ってるし、だからメインの時間じゃ無くて夕食後の空いた時間とかに簡単なミニゲームを改良しながら公開する方式で、ちまちまと作る事にしてみる。
改良とか実装にはみなさんのコメントの書き込みを参考にして逐次改良していく方式の予定で、コメント無ければ自分で適当にいじっていきます。
こういう要素を実装してみてとか、グラとか音とかの要望とか、ゲームの方向性とか設定とか、なんでもかまいませんので書いてみてください。
ここにでは無くてホームページのゲーム記事のコメント欄にお願いします。
なお、ヒマな時間余裕のある時間に気が向いたらいじる予定なので、実装に時間がかかったり、きびしくなったら突然消えて失踪もありえると思うので、あらかじめご了承下さい。
合わせて多少プログラム講座っぽくしてみる予定だけど、まあ HSPだし自分には教えるほどの技術がある訳じゃ全く無いので参考程度の内容になるでしょう。
ああ、それと費用対効果はアフィリエイト、つまり広告バナーを予定してます。
企画第一弾のゲームはコチラ
と言う事で「1マップ防衛シューティング」という極めて初歩的で作るのが簡単なゲームです。
ver.0.001のソースはコレ
; 企画第一弾 : 1画面防衛シューティングを作ろう ; var.0.001 #include "hsp3dish.as" ; HSPdishの宣言 randomize ; 乱数の初期化 wx=640 ; 画面の大きさx wy=360 ; 画面の大きさy ox=20 ; キャラ大きさx oy=20 ; キャラ大きさy font "",ox ; キャラの大きさ設定 px=wx/2-ox/2 ; プレイヤーの座標x py=wy/2-oy/2 ; プレイヤーの座標y sf=0 ; ショット発射フラグ sx=0.0 ; ショット座標x sy=0.0 ; ショット座標y ssp=7.0 ; スピード eb=20 ; 敵最大数 dim ef,eb ; 出現フラグ ddim ex,eb ; 敵座標x ddim ey,eb ; 敵座標y ddim edx,eb; 敵移動量x ddim edy,eb; 敵移動量y esp=1.0 ; 敵スピード ec=0 ; 出現カウント ecb=10 ; 出現間隔(フレーム) scr=0 ; スコア hiscr=0 ; ハイスコア *main mainf=0 ; ゲームフラグ repeat ; メインループ ---------------------------------- x=mousex : y=mousey ; マウスの座標 ; SHOT ---------- if sf=0 { ; 弾が発射されて無い sx=double(px) : sy=double(py) ; 初期座標 xn=double(x-px) ; 自機とマウスの距離x yn=double(y-py) ; 自機とマウスの距離y rad=atan(xn,yn) ; 距離xyから角度を求める sdx=sin(rad)*ssp ; 角度とスピードから移動量xを求める sdy=cos(rad)*ssp ; 角度とスピードから移動量yを求める sf=1 ; 発射フラグ on } if sf=1 { ; 弾が発射されている sx+=sdx ; xの移動 sy+=sdy ; yの移動 repeat eb ; 敵との当たり判定 if ef(cnt)=0 : continue if sx<ex(cnt)+ox and ex(cnt)<sx+ox and sy<ey(cnt)+oy and ey(cnt)<sy+oy { ef(cnt)=0 : sf=0 ; 当たった敵とショットを消す scr+ ; スコア if hiscr<scr : hiscr=scr ; ハイスコアの更新 break } loop if sf=1 : if sx<0-ox or wx<sx or sy<0-oy or wy<sy : sf=0 ; 枠外でフラグ off } ; 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) : eys=-oy ; 上 if r=1 : exs=rnd(wx) : eys=wy ; 下 if r=2 : exs=-ox : eys=rnd(wy) ; 左 if r=3 : exs=wx : eys=rnd(wy) ; 右 ex(cnt)=double(exs) ; 初期位置x ey(cnt)=double(eys) ; 初期位置y xn=double(px-exs) ; 敵と自機の距離x yn=double(py-eys) ; 敵と自機の距離y rad=atan(xn,yn) ; 距離xyから角度を求める edx(cnt)=sin(rad)*esp ; 角度とスピードから移動量xを求める edy(cnt)=cos(rad)*esp ; 角度とスピードから移動量yを求める ec=ecb ; 出現ウエイト break ; 登録終わり loop loop repeat eb if ef(cnt)=0 : continue ; 無し ex(cnt)+=edx(cnt) : ey(cnt)+=edy(cnt) ; 移動 if px<ex(cnt)+ox and ex(cnt)<px+ox and py<ey(cnt)+oy and ey(cnt)<py+oy { mainf=1 : break ; 自機と当たりで GAME OVER } if ex(cnt)<0-ox or wx<ex(cnt) or ey(cnt)<0-oy or wy<ey(cnt) : ef(cnt)=0 ; 枠外でフラグ off loop redraw 0 ; 表示 color 1,1,1 : boxf ; 黒塗り color 255,255,255 pos px,py : mes "●" ; 自機 pos sx,sy : mes "・" ; ショット repeat eb if ef(cnt)=0 : continue ; 無い pos ex(cnt),ey(cnt) : mes "敵" ; 敵 loop pos wx-300,5 : mes "SCORE "+scr pos wx-150,5 : mes "HI SCORE "+hiscr if mainf=1 : pos wx/2-43,wy/2+50 : mes "GAME OVER" redraw 1 await 1000/15 ; ウエイト、FPS 15 repeat ; GAME OVER 表示待機 ----------- if mainf=0 : break await 1000/15 stick k : if k=0 : continue ; ボタンでゲーム再開 repeat eb ef(cnt)=0 ; 敵リセット loop sf=0 ; ショットリセット scr=0 ; スコアリセット mainf=0 ; ゲーム再開 break loop ; ---------- loop ; -------------------------------------------------- end ; 終わり
とりあえずプロトタイプ 1号はこれだけで動きます。
プログラム講座というか説明
これは構造は初期設定が終わったら 1つだけの repeat~loopで繰り返していて、await 1000/15で 15FPS( 1秒間に 15回表示)表示にしている。
1ループだけのため、gameover画面はちょっと強引に付け足してる。
repeatは HSP特有の(と思われる)便利な「繰り返し」の命令で、他の言語だと while文とか for~next文になると思う。
これの便利なのは if文と break(ループ終わり)とか continue(ここで繰り返し)を使う事で、条件分岐に使える事。
何が良いのかって if文の{ }よりスッキリして見易いとかそんな所(笑)
例えばソースのショットは if分だが、敵の処理は repeatになってる。
awaitはその時間分だけ待つ命令。
ループルーチンだと最低でも await 0を入れないと操作できなくなる。
1秒=1000なので、1000/15で 15分の 1秒待ってくれる。
randomizeは乱数の初期化かな?
たぶん通常は乱数テーブルを参照して乱数を出すため、いつも乱数が同じになってしまうが、randomizeを実行するとたしか時間を元に乱数を出すんだかで乱数がバラバラに出される、だいたい必須かな。
sfとか efの fは自分はフラグという意味で使っていて、f=0なら存在しない、f=1なら存在してる。
だから弾にあたったり、画面外に出たら f=0にする事で消す。
出現の場合はフラグ f=1にする。
xは x座標で横の座標、yは y座標で縦の座標だね。
今回一番難しくて、かつ一番ゲームプログラミング的に基本的なのが三角関数による座標の移動計算だ。
実は自分はロクに勉強しなかったので三角関数がなんであるかよく分からない。
しかしまあ使い方だけ分かっていてソースに実装してしまえば、とりあえずは困らない。
と言う訳で、基本的な勉強は他の人のを参照して下さい。
HSP開発 wikiさんの三角関数記事
まあザックリ言って「角度が分かれば x(横)と y(縦)の移動量が分かる」という事なんだろう。
1、まず角度を求める。
求め方は A地点から B地点の座標を引いたものを atan(アークタンジェント)に放り込む。
角度r=atan(Ax-Bx,Ay-By)
この atanはプログラムの命令文だから、数学的にどういう処理をしているかは知らない。
とにかくこれで A地点と B地点の角度が分かる。
2、求めた角度を元に xと yの移動量を出す。
x= sin(角度r) × スピードで
y= cos(角度r) × スピードで
出されるが、これまたここでの sin(サイン)、cos(コサイン)は命令文なので、数学的な事はあえて分からない。
とにかくも角度が分かれば、あとはスピードを掛けてやれば xと yの移動量が出されるので、現在のキャラの座標に足してやれば良い。
なお、自分はどうしても反対方向に飛んで行ってしまうので、そういう場合には Ax-Bxを Bx-Axのように反対にしてやると良い。
重要なのは、どうしても整数では無く小数点を使った実数でないと移動の角度がカクカクと限定されたものになってしまう。
そのためショット、敵、共に実数の小数点の変数を使ってる。
doubleは実数の変数定義だし、ddimも実数の配列変数定義となってる。
後は当たり判定だけど、Aの左が Bの右より左で、Aの右が Bの左より右で、という感じで座標が重なってるか調べる。
とりあえずこれが初歩でシンプルな当たり判定の方法になります。
redraw 0 は描画開始
redraw 1 は描画終了
なので、その間に描画処理をする。
とまあそんな感じなんだけど、まあやっぱりプログラミング講座はそれ専用にページを用意しないと難しいみたいだね。
はじめまして、
半年前から、楽しく読ませていただいてます。
3年前ぐらいのandroid4.2のchromeブラウザで見たところ
FPSは30ぐらいを目指してもよいのかとおもいました。
制限として弾を制限しているようですが、弾は連射できて
段数に制限があり、むやみに打つと単発から打てなくなるなどどうでしょうか?
例:ジャレコのエクセリオンのようなもの
今後も、活躍期待しております。
うわあああああ、その2
済みません今までコメント滅多に無かったので、どうしても見逃してしまいました。
これからはコメント確認するようにします。
コメントありがとうございます。
そう、スマホなら FPS30でもたぶん FPS60でもいけるのではないでしょうか。
なぜ FPS15なのかと言うと、pen4くらいの単コア PCのブラウザを使う人がいたら、という理由です。
まあもう滅多にいないとは思いますし、そもそもそんな古いPCで webGLが動くのも無いとは思うんですけど、開発者としてはなるべくどんな環境でも動くものを、という発想はあると思います。
つまりスマホ向けオンリーなら FPS30で問題無いと思います。
エクセリオンやってみました。
これなら弾数を何かで補充する特殊ショットの強力バルカン砲みたいな要素でできそうですね。
ああ、しかしコメントを見た今日、ショットをバルカンにした所だ(笑)
そうだねえ、しかしメインショットを単発にするのは今のゲーム的にはストレスがあるかなあ、メインショットが大砲とか弓なら有りか。
主人公を弓にして、特殊ショットを流星矢みたいにしてみるとか、特殊ショットの時だけ連弩みたいのに持ち替えてとか、う~ん。
(じゃ無くて、この時はショット単発にしたの自分だったのか忘れてました
それでエクセリオンと言ってくれた訳ですね、よく思いつきましたね
これはゲーム的な制限では無くて、最初のプログラムとしてもっとも簡素にしたという理由からなので、ショット数に制限は無いです
いずれにしてもコメント読むの遅すぎました)
次回実装予定が特殊攻撃(副武装)なんですけど、アイデアを入れてみるかな。
う~ん集弾率の高い強力高速速射砲みたいの。
次回はロケット弾を予定してたんですけど、まあその内特殊攻撃を複数化する予定だったので順番を後にしても良いかな、アイデアありがとうございます。
そして、コメントに気がつかずに済みませんでした。