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


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
1012
紀楽院RPGゲームの戦闘での素早さ比較による行動順番8解決


紀楽院

リンク

2013/10/12(Sat) 06:29:37|NO.57568

はじめまして。
私は今、HSPでゲーム製作を行っています。
ジャンルはRPGなのですが戦闘システムをキャラクターのステータスに素早さを設けて
その能力が高い順で行動順番をとるという形にしたいと思っています。
具体的にすると
1.味方全員の行動を全て選択
2.敵味方全員の素早さを比較
3.素早さの高い順で行動
というふうにしたいと思っています。
一対一の戦闘なら容易なのですが複数人の戦闘ともなると
各キャラクター間での行動優先順位をつけなければなりません。
ですが、その優先順位のつけかたが考え付かず、
色々調べてもみましたがそれでもわからず今回、質問させていただきました。
ご助力の程、何卒お願いいたします。



この記事に返信する


ポテト(流星群)

リンク

2013/10/12(Sat) 08:32:12|NO.57569

単純に全部パターン比較をrepeat〜loopでやるか
ソートした後の最終要素から処理していくか…かな?

全パターンやる場合、
例えば3vs3の場合として、
非常に冗長な処理になるけど、
全員の素早さが
speed(0〜5)にはいっていたとする。
これで、speed(0)がそれ以外のどれか一つより大きい場合は順番値を1上げる。
を繰り返し、最終的に5〜0まで出来るので5から順に処理をしていく…とか?
恐らくとても綺麗とは言えないソースになりそうだけど。

ソートはそのまま、
適当なソート方でソートした後にその順に処理していく感じになるかな。



Ve

リンク

2013/10/12(Sat) 08:33:50|NO.57570

素早さの値でソート処理をすれば良いです。

【 HSP+ソート 】で検索すれば、いろんなサンプルソースが載ったサイトが出てきますよ。



紀楽院

リンク

2013/10/13(Sun) 04:51:59|NO.57583

お二人ともご回答ありがとうございます。
ソートのやり方はなんとなくわかったのですが
降順にソートした後、その順番で行動させる方法で悩んでいます。
例えば、味方3人の素早さ=1,3,5 敵3人の素早さ=2,4,6を降順にソートした場合
行動順1=敵A 素早さ6
行動順2=味方A 素早さ5
行動順3=敵B 素早さ4
行動順4=味方B 素早さ3
行動順5=敵C 素早さ2
行動順6=味方C 素早さ1
となります。このとき、行動順1は敵Aなので最初に敵Aを行動させる。
つまり、行動順1が敵Aならば敵Aプログラムを読ませる。味方Aならば味方Aプログラムを読ませる。
それが終了すると行動順2のキャラクターが行動を開始。
味方Bならば味方Bプログラムを、敵Bならば敵Bプログラムを読ませる。
このようにしたいと思っているのですが、行動順を決めるだけならばさほど難しくはないのですが
それを順番通りに行動させることが出来ません。
HSPを始めて日が浅いため、苦戦しております。
再度、お力添えをよろしくお願いします。



asdfjkl;

リンク

2013/10/13(Sun) 11:07:21|NO.57585

repeat-loopで行動順に処理するといいと思います。

いろいろと方法はあると思いますが一例として
まず敵や見方すべてにIDを割り振り
素早さ順にソートして、その結果を基にIDを格納した配列変数を作る。
というのが考えられます。
こうする事で順番をIDに変えてくれるフィルターができます。

人によってIDの管理のしかたが変わってきますが、
以下の例では要素番号をそのままIDとして使っています。
自分のプログラムにあわせて工夫してみてください。

dim HP,4 HP(0)=50 //見方AのHP ID:0 HP(1)=75 //見方BのHP ID:1 HP(2)=25 //敵AのHP ID:2 HP(3)=30 //敵BのHP ID:3 //攻撃順が決定して //敵A→見方A→敵B→見方Bとなった dim order,4 order(0)=2 //敵AのID:2 order(1)=0 //見方AのID:0 order(2)=3 //敵BのID:3 order(3)=1 //見方BのID:1 //これでorder(n)(n=0,1,2,3)とすれば //n+1番目に攻撃するIDを取得できます //3回目に攻撃するID mes order(2) //3回目に攻撃する人のHP mes HP(order(2)) mes "" repeat 4 //それぞれの処理 mes HP(order(cnt)) //IDごとに別の処理も可能 if (order(cnt) <= 1){ //見方の処理 }else{ //敵の処理 } loop



Taddi

リンク

2013/10/13(Sun) 14:36:02|NO.57587

私もRPGを製作するときに悩みました。

私の場合は、
素早さなどでソートするときに合わせて
「だれが(id)」「何を(action)」「誰に(target)」
という部分も一緒に並べ替えしました。

あとはそのリストをrepeat-loop…asdfjkl;さんが説明されているとおりです。
一例ということで参考にしてください。

ちなみにスクリプトだとこんな感じです。
(このままでは実行できません。参考程度にご覧ください。)

//アクションの実行順をソート #deffunc sort_btl_action repeat 10 if cnt<6{ ;パーティー if btl_action(cnt)=1|btl_action(cnt)=4|btl_action(cnt)=7{ ;まもる・かばう・はやうちは初めに実行 set_sp=get_equip_data(cnt,EQU_SPD)+get_temp_prm(cnt,BTL_TEMP_SPD)+999 }else{ set_sp=get_equip_data(cnt,EQU_SPD)+get_temp_prm(cnt,BTL_TEMP_SPD) } }else{ ;敵 set_sp=get_enemy_data(cnt-6,ENEMY_SPD)+get_temp_prm(cnt,BTL_TEMP_SPD) } btl_all_sp(cnt)=set_sp*10+cnt ;ソート時にかぶらないための処理 loop repeat 10 repeat 10 - cnt - 1 if btl_all_sp(cnt) < btl_all_sp(cnt+1) { ;敏捷性 btl_all_sp(cnt) ^= btl_all_sp(cnt+1) btl_all_sp(cnt+1) ^= btl_all_sp(cnt) btl_all_sp(cnt) ^= btl_all_sp(cnt+1) ;ID btl_all_id(cnt) ^= btl_all_id(cnt+1) btl_all_id(cnt+1) ^= btl_all_id(cnt) btl_all_id(cnt) ^= btl_all_id(cnt+1) ;行動 btl_action(cnt) ^= btl_action(cnt+1) btl_action(cnt+1) ^= btl_action(cnt) btl_action(cnt) ^= btl_action(cnt+1) ;ターゲット btl_target(cnt) ^= btl_target(cnt+1) btl_target(cnt+1) ^= btl_target(cnt) btl_target(cnt) ^= btl_target(cnt+1) } loop loop return



暇人

リンク

2013/10/13(Sun) 16:57:03|NO.57593

既に回答出てますが・・・
敵味方に識別用のIDを付ける
今回は初期キャラデータの順番をIDにしてる
素早さを一つの配列に纏める
同時に通し番号を付ける
ソートするのは通し番号の配列のみ

味方早=1,3,5 //素早さが味方ID順に並んでるとする 味方数=3 味方PT=0,1,2 敵早=2,4,6 //素早さが敵ID順に並んでるとする 敵数=3 //敵出現数 敵GP=0,1,2 pos 0,0 mes "ソート前" no=0 repeat 味方数 //敵味方を統合し通し番号を付ける 統合no(no)=no //要素数を通し番号とする ID=味方PT(cnt) 統合早(no)=味方早(ID) //一つの配列に素早さを纏める mes strf("%.9s%2d %8s%d %8s%d","統合no=",no,"味方ID=",ID,"味方早=",味方早(ID)) no++ loop no=味方数 repeat 敵数 //敵味方を統合し通し番号を付ける 統合no(no)=no //要素数を通し番号とする ID=敵GP(cnt) 統合早(no)=敵早(ID) //一つの配列に素早さを纏める mes strf("%.9s%2d %8s%d %8s%d","統合no=",no,"敵ID=",ID,"敵早=",敵早(ID)) no++ loop 統合数=no //ソート repeat limit(統合数-1,0,統合数)//一つ下のと比較するので-1 noA=統合no(cnt)//上から順番に通し番号を取り出し noB=統合no(cnt+1) 早A=統合早(noA)//通し番号を要素数として素早さ取り出し 早B=統合早(noB) if 早A<早B { 統合no(cnt)=noB 統合no(cnt+1)=noA continue 0 //入れ替えが有ったので最初から比較開始 } loop color 200 mes "ソート後" repeat 統合数 no=統合no(cnt) if no<味方数 {//味方数未満は味方を表し、味方PT(no)で味方のIDを取得出来る //ここが味方処理(味方数〜統合数-1までの数が統合敵noになる) 味方ptno=no mes strf("%.9s%2d %8s%d %8s%d","統合no=",no,"味方ID=",味方PT(味方ptno),"味方早=",統合早(no)) }else{//味方数以上は敵を表し、敵GP(no-味方数)で敵のIDを取得出来る //ここが敵処理(0〜味方数-1までの数が統合味方noになる) 敵gpno=no-味方数 mes strf("%.9s%2d %8s%d %8s%d","統合no=",no,"敵ID=",敵GP(敵gpno),"敵早=",統合早(no)) } loop




これを実際にゲームで使う感じにすると

randomize 味方名="仲間A","仲間B","仲間C","仲間D","仲間E" 味方HP=300,200,150,80,123,243 味方早=1,3,5,4,10 //素早さが味方ID順に並んでるとする 味方数=3 味方PT=0,2,4 敵名="敵A","敵B","敵C","敵D","敵E","敵F","敵G","敵H" 敵HP=310,123,243,100,200,150,245,213 敵早=2,4,6,1,5,3,4,7 //素早さが敵ID順に並んでるとする pos 500,0 button gosub "リセット",*label *start color 255,255,255 boxf color dim 敵重複数,20 敵数=rnd(4)+2 //敵出現数 repeat 敵数 ID=rnd(length(敵早)) 敵GP(cnt)=ID 敵重複数(ID)++ //同じ種類の敵を数える loop pos 0,0 mes "ソート前" no=0 repeat 味方数 //敵味方を統合し通し番号を付ける 統合no(no)=no //要素数を通し番号とする ID=味方PT(cnt) 統合名(no)=味方名(ID) 統合早(no)=味方早(ID) mes strf("%.9s%2d %8s%d %8s%d %8s","統合no=",no,"味方ID=",ID,"味方早=",味方早(ID),味方名(ID)) no++ loop repeat 敵数 //IDを一つの配列に統合 統合no(no)=no //要素数を通し番号とする ID=敵GP(cnt) idcnt=敵重複数(ID) if idcnt>1 {//同種が2以上なので名前に番号を付ける idcnt+$100 //元の数を壊したくないので$100を足して番号にする(番号として使うときは$100で割る) 統合名(no)=敵名(ID)+"("+(idcnt/$100)+")" 敵重複数(ID)=idcnt }else{ 統合名(no)=敵名(ID) } 統合早(no)=敵早(ID) mes strf("%.9s%2d %8s%d %8s%d %8s","統合no=",no,"敵ID=",ID,"敵早=",敵早(ID),敵名(ID)) no++ loop 統合数=no dim 統合HP,統合数 //ソート repeat 統合数-1 noA=統合no(cnt) noB=統合no(cnt+1) 早A=統合早(noA) 早B=統合早(noB) if 早A<早B { 統合no(cnt)=noB 統合no(cnt+1)=noA continue 0 } loop color 255 mes "ソート後" cposx=ginfo_cx cposy=ginfo_cy repeat tagno=-1 redraw 0 color 220,230,220 boxf 0,cposy,640,480 repeat 統合数 if (sel_index=cnt) {color 200}else{color 200,100,255} pos cposx,cposy+16*cnt no=統合no(cnt) if no<味方数 {//味方数未満は味方を表し、味方PT(no)で味方のIDを取得出来る //ここが味方処理 味方ptno=no ID=味方PT(味方ptno) HP=(味方HP(ID)-統合HP(no)) if HP>0 { mes strf("%.9s%2d %8s%d %8s%d %8s","統合no=",no,"味方ID=",ID,"味方早=",統合早(no),統合名(no)) if (sel_index=cnt) { color 0,100,255 }else{ if abs((味方ptno*100+50)-mousex+35)<50 and (abs(430-mousey+20)<30) { color 200,0,100 tagno=no }else{ color 0,0,150 } } pos 味方ptno*100+50,430 mes "名前:"+統合名(no) mes "HP:"+HP+"/"+味方HP(ID) }else{ //HP0以下 if sel_index=cnt {sel_index++} //既に死んでるので次のnoに移動 } }else{//味方数以上は敵を表し、敵GP(no-味方数)で敵のIDを取得出来る //ここが敵処理 敵gpno=no-味方数 ID=敵GP(敵gpno) HP=(敵HP(ID)-統合HP(no)) if HP >0 { mes strf("%.9s%2d %8s%d %8s%d %8s","統合no=",no,"敵ID=",ID,"敵早=",統合早(no),統合名(no)) if (sel_index=cnt) { color 0,100,255 }else{ if abs((敵gpno*100+50)-mousex+35)<50 and (abs(370-mousey+20)<30) { color 200,0,100 tagno=no }else{ color 0,0,150 } } pos 敵gpno*100+50,370 mes "名前:"+統合名(no) mes "HP:"+HP+"/"+敵HP(ID) }else{//HP0以下 if sel_index=cnt {sel_index++} //既に死んでるので次のnoに移動 } } loop redraw 1 await 16 stick st if st&512 {sel_index++}//右クリックで次のnoを選択 if (st&256)>0 and tagno>=0{//左クリックでタッゲートにダメージを与える dmg=rnd(25)+5 統合HP(tagno)+dmg title "ターゲットNO="+tagno+" "+統合名(tagno)+" ダメージ="+dmg } sel_index=sel_index\統合数 if loopexit {break} loop loopexit=0 sel_index=0 tagno=0 goto *start stop *label loopexit=1 return



暇人

リンク

2013/10/16(Wed) 21:20:58|NO.57640

NO.57593のソートはちょっと手抜き(10個程度のソートなら問題ないけど)なのと
安定ソート(同じ素早さの場合ソート前の順序を保存)なので違うソートも

NO.57593のより平均して半分ぐらいの処理時間だが安定ソートではない
同じ素早さの数により結果が違う

repeat 統合数 _cnt=cnt noA=統合no(cnt) 早A=統合早(noA) repeat 統合数-cnt,cnt noB=統合no(cnt) if 早A < 統合早(noB) {//入れ替えするか比較 if noA ! noB {//同じNOは除外する 統合no(_cnt)=noB 統合no(cnt)=noA noA=noB 早A=統合早(noA) } } loop loop
> if 早A < 統合早(noB) {//入れ替えするか比較
の比較記号を <= にするとソート前の同じ素早さの順序を反転した安定(?)ソートになる

通常の安定ソートにするには味方と敵を統合noに入れた後に

repeat 統合数/2 temp=統合no(cnt) 統合no(cnt)=統合no(統合数-1-cnt) 統合no(統合数-1-cnt)=temp loop
でソート前の順序を反転してからソートする



紀楽院

リンク

2013/10/18(Fri) 04:12:45|NO.57656

皆さん、様々な回答ありがとうございました。
おかげさまでなんとか解決することができました。
これからまたなにかありましたら質問させていただきますので
そのときまたよろしくお願いします。



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