HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0516
もくぬ1Pキャラ攻撃硬直時に2P側を動かしたい7解決


もくぬ

リンク

2015/5/16(Sat) 05:51:05|NO.69222

初歩的な質問すみません。
ロックマンエグゼ風の対戦アクションゲームを製作しています。
その中で、1Pキャラが技を発動中、2P側が身動きを取れない現象が起こっています

*メイン画面

repeat

;gcopyでフィールドと背景描画処理
;キャラ2体の座標取得
;gcopyキャラ2体の描画

;キー入力情報取得
getkey yu,87 
getkey yh,65
getkey ys,83
getkey ym,68

getkey eu,38
getkey eh,37
getkey es,40
getkey em,39

getkey yb,76
getkey eb,102


;キー入力時の挙動
if yb == 1 ; gosub *1P攻撃
if eb == 1 : gosub *2P攻撃
if yu == 1 : gosub *1P上移動
if yh == 1 : gosub *1P左移動
if ys == 1 : gosub *1P下移動
if ym == 1 : gosub *1P右移動
if eu == 1 : gosub *2P上移動
if eh == 1 : gosub *2P左移動
if es == 1 : gosub *2P下移動
if em == 1 : gosub *2P右移動

await 1
loop
stop

*1P攻撃
;フィールドと背景と2Pキャラ描画
;攻撃時の1Pキャラ画像描画
;攻撃命中時処理
await 200 ;攻撃時ディレイ
return


かなり省略していますがこのように記述した場合、
1Pが攻撃時、2P側は何もできません
1Pが何もできないのは仕様通りで問題ないのですが、
1Pの攻撃ディレイ時に2P側を動かす方法はないでしょうか、、、



この記事に返信する


kanamaru

リンク

2015/5/16(Sat) 08:24:37|NO.69223

僕はアクションゲームを作ったことがないのですが、
少なくとも僕だったら、
hspのサンプルにあった踏みゲーを参考にして作ります。
cntのあまりで操作対象を変えるようにするのです。
なぜこうするのかというと、例を挙げます。
今現在、マルチタスクを採用してないOSはほとんどありません。
そんなマルチタスクでは、複数のソフトが同時に動いてたり…。
てことがよくあります。
でも正確には同時に動いてるわけではありません。
高速に操作対象を切り替えているのです。
その頻度がある程度早ければ、(await 1でいいと思います。)
人間の目には同時に動いてるように見えるのです。
これを応用します。
・1p攻撃
・2p攻撃
・1p移動
・2p移動
の四つを行うとして、(移動は上下左右に分ける必要はないかと)
cntを4で割った余りが0,1,2,3のときで場合分けします。
スクリプトの例としては、

repeat if cnt\4=0:gosub *1p攻撃 if cnt\4=1:gosub *2p攻撃 if cnt\4=2:gosub *1p移動 if cnt\4=3:gosub *2p移動 await 1 loop
ラベル名は適切なのに変えてください。
あとは、それぞれのラベルでキーチェックをして、
攻撃したり、移動したりさせればたぶんできるかと
(変数で攻撃を複数回のサブルーチンジャンプに分ければ
 たぶん1p攻撃中に2p移動できる。)



kanamaru

リンク

2015/5/16(Sat) 08:38:46|NO.69224

言い忘れていましたが、
キーチェックのときはstickが便利ですよ。
今回は調べるキーが多いですし、
たくさん変数が必要じゃなくなるので。
あと、攻撃のときにキートリガーを1にする必要があります。



掘木

リンク

2015/5/16(Sat) 08:59:21|NO.69226

逆に問いましょう。
「1Pが攻撃硬直中、なぜ1Pはキーを受け付けないのでしょう?」
ちゃんとトレースしましょう。

端的に言えば、攻撃処理の作りがおかしいです。

解決策はいろいろありますが、
『シューティングゲームで弾を撃ったら弾が消えるまでプレイヤーが動けなくなっちゃった』
とかそんな感じと似てます。いや、それより簡素な形か。


過去ログにもありそう。(調べてないけど)


*戯言//-----------------
私個人としては、プログラム内にwait系の命令が乱立するのは単一動作を主とするプログラムを作りやすい反面、
並列処理を時間制御しつつ行うものは作りづらいように思います。
複数処理を強いる典型であるゲームの場合、
『メインループ内に1つもしくはFPS制御処理部分にだけwait系の命令がある』
そんなプログラム構造を取るようにしています。(良し悪しはあるけどネ)



名無し

リンク

2015/5/16(Sat) 09:20:33|NO.69227

>『メインループ内に1つもしくはFPS制御処理部分にだけwait系の命令がある』
それ普通じゃんと思ってたんだが……でないと何のためのawaitなのかと



暇人

リンク

2015/5/16(Sat) 09:59:34|NO.69228

まずawaitは、指定時間そこでストップする命令なので、当然の結果
通常は、一秒間のメインループ回数を、一定に保つために使う
await 16 ぐらいにすると、秒間60フレームになりディスプレイの
リフレッシュレートと同じ(液晶の主流が60なので)になるので、無駄な描画を減らせる
当然メインループ内にawaitは一回だけ

で、本題
一定時間特定の処理をスルーしたいならカウント用の変数を用意して
特定の処理をしたらスルーさせたいフレーム数を変数に入れて
次のループから変数が1以上ならifで分岐させれば良い


p1x=200 a=0,5,15,20,55,60,65,45,25,10 //攻撃アニメーションデータ10コマ分(右側から使用する) m=0,5 //移動アニメーションデータ2コマ分 repeat redraw 0 gradf 0,0,640,480,1,$4444,$1111 getkey yh,'A' getkey ym,'D' getkey yb,'L' if p1delay=0 { if yh == 1 : gosub *1P左移動 if ym == 1 : gosub *1P右移動 if yb == 1 : gosub *1P攻撃 }else{ p1delay-- } gosub *1P描画 gradf 500,200-(cnt\64),64,64,1,$aa0000,$aa0000 //2pの代わり await 16 redraw 1 loop *1P左移動 p1mindex++ //移動アニメーションインデックス p1x-5 return *1P右移動 p1mindex++ p1x+5 return *1P攻撃 p1delay=10 //ディレイカウンタ p1a=1 //攻撃発動フラグ p1aindex=9 //アニメーションインデックス(0〜9の10コマ) p1mindex=0 return *1P描画 if p1a=1 { gradf p1x,200,64+a(p1aindex),64,1,$88aa,$88aa p1aindex-- if p1aindex=0 {p1a=0} }else{ gradf p1x,200,64,64+m((p1mindex/5)\2),1,$88aa,$88aa //(p1mindex/5)で5フレームに一コマ進む \2してるので2になると0になる(\は割り算の余りを出せる) } return



掘木

リンク

2015/5/16(Sat) 10:03:40|NO.69230

戯言に対する返信に返信する価値があるのかよく分からないけども・・・

>名無しさん
「メインループはユニークで、その中のwaitはプログラム中の唯一のwaitとなる」
という方が正確か。(メインループってプログラム内でユニークじゃないの?ってこと)

サンプルや余所様の配布ソースを見ると、
シーン別にループを組んで、それぞれの中にwaitがいるんですよ。
そのため、コード上にwaitが複数箇所あるコードも見かけます。

各シーン用のループそれぞれをメインループと言うなら、たしかにこちらの言い分は確かに普通でしょうね。
メインループはユニークだろうって考えで言っているのなら、名無しさんはこちらと同じ流儀なのだと思う。



もくぬ

リンク

2015/5/16(Sat) 18:55:12|NO.69238

皆さん分かりやすくどうもありがとうございました!
おかげでなんとか形になりました、助かりました



ONION software Copyright 1997-2023(c) All rights reserved.