2017年 10月19日
やっと初歩の攻撃部分だけできた。
差配プログラムも変更されたが、部隊が 3部隊で 1部隊 3ユニットというややこしさと、武器を持ってる持って無い、射程がある、ユニットによっては手の攻撃が無い、2手攻撃、複数攻撃とか要素が多くて大変だった。
あまりの作成する要素の量と、たぶん現在全行程の3割くらいしか進んでない状況から、もう完成しないのではないかと日に 1度は思う。
やっぱりもっと簡単なゲームから制作した方が良かったのか・・・・。
そう考えるのはクリエイターのお約束なんだろうなあ。
まずは恐怖のソースを。
/////// 戦闘 ////////////////////////////
*battle_syoki ; 戦闘初期 ////////////////////////////////
return
#deffunc fn_syo ; 隊列処理
n1=(fg1-1)*3
n2=(fg2-1)*3
if ud(fn1(n1+1)*udb+26)=0 : fn1(n1+1)=fn1(n1+2) : fn1(n1+2)=fn1(n1+3) : fn1(n1+3)=0 ; 先頭がいなければ一つ詰める
if ud(fn2(n2+1)*udb+26)=0 : fn2(n2+1)=fn2(n2+2) : fn2(n2+2)=fn2(n2+3) : fn2(n2+3)=0
anif1=1
repeat 3,1 ; 全滅確認
if fn1(n1+cnt)>0 : anif1=0 : break
loop
if anif1=1 {
ff1(fg1)=0 ; 部隊消去
fff=1
repeat 3,1 ; 全部隊全滅確認
if ff1(cnt)>0 : fff=0 : break
loop
if fff=1 : ff1(0)=0 : btvf=-9; 全滅
btvf- : return
}
anif2=1
repeat 3,1 ; 全滅確認
if fn2(n2+cnt)>0 : anif2=0 : break
loop
if anif2=1 {
ff2(fg2)=0 ; 部隊消去
fff=1
repeat 3,1 ; 全部隊全滅確認
if ff2(cnt)>0 : fff=0 : break
loop
if fff=1 : ff2(0)=0 : btvf=9 ; 全滅
btvf+
}
return
#deffunc d_syo ; 死亡処理
fn2(et)=0
return
#deffunc atk int atkn,int atket,int atkrg ; 攻撃(攻撃値、攻撃する列、射程)
atkf=0 ; 攻撃したかフラグ
repeat 3,1 ; 射程
if atkrg<(ut-1)+cnt : break ; 射程外
et=cnt : en=ffn(et) : if en=0 : continue ; 隊列にいない
eg=en*udb : if ud(eg+26)<=0 : continue ; HPが0
atkf+ : break ; 攻撃した
loop
if atkf=0 : return ; 射程内に敵がいなかった
atkg=atkn*gensui/100 ; 攻撃力
atn=0 : repeat 2 : atn+=rnd(atkg+1) : loop ; 攻撃値
;dgs "atn ",atn,5
dfn=0 : repeat 2 : dfn+=rnd(ud(eg+12)+1) : loop ; 防御値
;dgs "dfn ",dfn,6
dm=atn-dfn
if dm<=0 : return ; ダメージ無し
if fs=1 : dmp_set dm,3+et,1 ; ダメージ表示
if fs=2 : dmp_set dm,et,1
repeat 1 ; HP処理
ud(eg+26)-=dm : if ud(eg+26)>0 : break
ud(eg+26)=0
;if fs=1 : fn2(et)=0
;if fs=2 : fn1(et)=0
loop
return
*atack ; 攻撃処理
en=0 ; 敵ユニットNo.
dgs "intvc",intvc,0
dgs "un ",un,1
dgs "fs ",fs,2
dgs "ut ",ut,3
dgs "16 ",ud(ug+16),4
gensui=100 ; 攻撃減衰率
if ud(ug+16)=0 and ut=1 : gensui=120 : atk ud(ug+11),1,1 ; 素アタック
if ud(ug+16)=2 { ; 2手 ------------------------
repeat 1 ; 右手
if ud(ug+40)=0 { ; 素手
if ud(ug+41)=0 or id(ud(ug+41)*idb+16)=5 { ; 左手が素手か盾
atk ud(ug+11),1,1 : gensui=75 : break ; 右素手攻撃
}
}
if ud(ug+40)>0 { ; 右手武器
in=ud(ug+40) : ig=in*idb
atk ud(ug+11)+id(ig+11),1,id(ig+17) ; 右手武器攻撃
gensui=75
}
loop
repeat 1 ; 左手
if ud(ug+40)=0 and ud(ug+41)=0 : atk ud(ug+11),1,1 : break ; 素手なら左素手攻撃
if ud(ug+41)>0 { ; 左手武器
in=ud(ug+40) : ig=in*idb
atk ud(ug+11)+id(ig+11),1,id(ig+17) ; 左手武器攻撃
}
loop
} ; -------------------------------------------
if ud(ug+16)>2 { ; 複数手 ---------------
repeat ud(ug+16) ; 手数
if ud(ug+40+cnt)=0 : atk ud(ug+11),1,1 : gensui-=25 : continue ; 素手
if ud(ug+40+cnt)>0 { ; 武器
in=ud(ug+40) : ig=in*idb
if id(ig+16)!5 : atk ud(ug+11)+id(ig+11),1,id(ig+17) : gensui-=25 ; 盾で無ければ攻撃
continue
}
loop
} ; --------------------------------------
redraw 0
color 0,0,0 : boxf : color 255,255,255
btl_put
dmp_put
dg_put
redraw 1
pkey
return
*d_atack
return
*fight ; 戦闘 ///////////////////////////////////////
btn=0 ; ターン
fg1=fc1\3+1 ; 戦闘する部隊
fg2=fc2\3+1
repeat 3 ; 3回戦闘
btn+
;dgs "btn ",btn,9
; イニシアティブ --------------
dim intv,6 ; イニシアティブ、順番
dim intvn,6 ; 値
repeat 6 ; リセット
intv(cnt)=0
intvn(cnt)=0
loop
repeat 3 : cnt2=cnt ; 値計算
cn1=(fg1-1)*3+cnt+1
cn2=(fg2-1)*3+cnt+1
if fn1(cn1)>0 { ; 攻勢側
intv(cnt)=fn1(cn1)
ug=fn1(cn1)*udb
n=0 : if ud(ug+8)=22 : n=ud(ug+9) ; 速攻
repeat 2 : intvn(cnt2)+=rnd(ud(ug+23)+n+1)+1 : loop ; 値
}
if fn2(cn2)>0 { ; 防衛側
intv(3+cnt)=fn2(cn2)
ug=fn2(cn2)*udb
n=0 : if ud(ug+8)=22 : n=ud(ug+9) ; 速攻
repeat 2 : intvn(3+cnt2)+=rnd(ud(ug+23)+n+1)+1 : loop ; 値
}
loop
repeat 5 : cnt2=5-cnt ; バブルソート
repeat cnt2
n1=intv(5-cnt) : nd1=intvn(5-cnt)
n2=intv(5-cnt-1) : nd2=intvn(5-cnt-1)
if nd1<=nd2 : continue
intv(5-cnt)=n2 : intv(5-cnt-1)=n1 ; 入れ替え
intvn(5-cnt)=nd2 : intvn(5-cnt-1)=nd1
loop
loop
; 攻撃 --------------
repeat 6 : intvc=cnt
un=intv(intvc) : ug=un*udb ; ユニットNo.
if un=0 : continue ; ユニットが無い
if ud(ug+26)<=0 : continue ; HPが0
repeat 3,1 ; 敵味方識別
if fn1((fg1-1)*3+cnt)=un : fs=1 : break
if fn2((fg2-1)*3+cnt)=un : fs=2 : break
loop
repeat 3,1 ; 隊列何番目か
if fs=1 : if fn1((fg1-1)*3+cnt)=un : ut=cnt : break
if fs=2 : if fn2((fg2-1)*3+cnt)=un : ut=cnt : break
loop
repeat 3,1 ; 敵ユニットNo.格納
if fs=1 : ffn(cnt)=fn2((fg2-1)*3+cnt)
if fs=2 : ffn(cnt)=fn1((fg1-1)*3+cnt)
loop
gosub *atack ; 攻撃処理
loop
fn_syo ; 隊列処理
redraw 0
color 0,0,0 : boxf : color 255,255,255
btl_put
dmp_put
dg_put
redraw 1
if anif1=1 or anif2=1 : break ; 全滅した
loop
return
*battle ; 戦闘メイン ////////////////////////////////
btvf=0 ; 勝利フラグ
repeat 1 ; -------------------------------------------------
dim ff1,4 ; forceフラグ、攻撃側
dim ff2,4 ; forceフラグ、防衛側
repeat 4 : ff1(cnt)=0 : ff2(cnt)=0 : loop ; リセット
repeat 3 : cnt2=cnt ; 部隊が存在するか
repeat 3
un=mu(kn1*10+cnt2*3+cnt+1)
if un=0 or ud(un*udb+26)<=0 : continue
ff1(cnt2+1)=1 : ff1(0)=1 : break
loop
repeat 3
un=mu(kn2*10+cnt2*3+cnt+1)
if un=0 or ud(un*udb+26)<=0 : continue
ff2(cnt2+1)=1 : ff2(0)=1 : break
loop
loop
if ff2(0)=0 : btvf=1 : break; 防衛部隊が無いので勝利
; ユニットNo.ひかえ ---------
dim fn1,10 ; 攻勢側ユニットNo.
dim fn2,10 ; 防衛側ユニットNo.
dim ffn,4 ; 敵戦闘部隊
repeat 3 : cnt2=cnt
repeat 3,1
un=mu(kn1*10+cnt2*3+cnt)
if ud(un*udb+26)>0 : fn1(cnt2*3+cnt)=un : else : fn1(cnt2*3+cnt)=0
un=mu(kn2*10+cnt2*3+cnt)
if ud(un*udb+26)>0 : fn2(cnt2*3+cnt)=un : else : fn2(cnt2*3+cnt)=0
loop
loop
; 戦闘部隊差配 -------------
fc1=0 : fc2=0 ; 部隊No.
repeat 3 ; 攻撃側
if ff1(fc1\3+1)=0 : fc1+ : continue
bf=0 ; 不戦勝フラグ
repeat 3 ; 防衛側
if ff2(fc2\3+1)=1 : gosub *fight : fc2+ : bf=1 : break
fc2+
loop
if bf=0 : btvf+ ; 不戦勝
if ff1(0)=0 or ff2(0)=0 : break ; 全滅した
fc1+
loop
if ff1(0)=0 or ff2(0)=0 : break ; 全滅した
repeat 3 ; 防衛側
if fc2>=3 : break ; 全部隊戦闘したので終わり
if ff2(fc2\3+1)=0 : fc2+ : continue
bf=0 ; 不戦負フラグ
repeat 3 ; 攻撃側
if ff1(fc1\3+1)=1 : gosub *fight : fc1+ : bf=1 : break
fc1+
loop
if bf=0 : btvf- ; 不戦負
if ff1(0)=0 or ff2(0)=0 : break ; 全滅した
fc2+
loop
loop ;------------------------------------------------------
hextf=0
; 勝敗処理 ----------------
if btvf>0 { ; 勝利
mpl(kn)=1
clrf=1
repeat 25,1
if map(cnt)=0 : continue
if mpl(cnt)!1 : clrf=0 : break
loop
if clrf=1 : mainf=7 : kc=10 ; GAME CLEAR
return
}
return
う~む、これを見て分かる人はおるまい。
とにかくまず *battleから入る。
*battleは部隊が存在するかと、戦う順番(差配)を決め、戦闘が起これば*fightへ。
最後に勝敗を決めてマップを書きなおすか決める。
*fightは部隊同士の戦闘処理で、今回は敵も味方も攻撃するほうを都度 un、ud、ug、防御側を en、ed、egとすることによって、次の*atackつまり戦闘処理を敵味方同じにする事によって、ソースを 2重にすることを避けた。
これについては、今後様々な特殊能力による変則的なプログラムを書くのを楽にするため。
思考錯誤しながら間違い(バグ)なく敵味方 2つも書いてらんない。
イニシアティブ(攻撃の順番)もかなり思考錯誤した。
イニシアティブは知力による。
intvにユニットNo.が格納され、intvnに速さ値が格納され、これを元にintvを早い順に並べ変える。
攻撃はintv順に行われる。
ffn=一時的に防御側の隊のユニットNo.を格納する。
これによって、*atack部分で防御側のユニット隊列が分かるようになる。
つまりこれ無しで相手を特定するのはかなりややこしい。
fn_syo ; 隊列処理、ユニットの HPが 0になったら、隊列を詰める。
これは 1回全ユニットが攻撃を終えてから、つまり 1戦闘ターン後に判定される。
先頭のユニットが健在なら、後列の離脱は無視される。
この時に部隊の全滅と全部体の全滅を確認し、全滅なら*battleへ戻る。
この辺の取り決めだけでも相当に思考錯誤した。
それからやっと個別の攻撃(atk)になる。
右手か左手に武器を持ってるか、あるいは両手とも素手か、左手が盾なら右手は素手攻撃になるとか、左手が片手武で右手が装備無しなら右手の素手攻撃は行われず左手の攻撃だけとか、右手武器の攻撃をした後、左手武器の右手武器の値を引いてから左手武器の値を足さなければいけいけど、そうなると攻撃値を全装備アイテムから計算しなおさなければいけないし、それを一々沢山出てくる攻撃箇所で行うのは大変だとか、もうカオス。
結局ユニットデータの攻撃値 ud(ug+11)には武器以外のアイテムの攻撃地だけを足して基礎値とし、武器値は装備している武器の内一番高いものを ud(ug+20)という使ってないデータに別に割り振る事にした。
すると素手の場合は ud(ug+11)をそのまま使えば良いし、武器なら都度その値に武器の攻撃力を足せばいい。
今の所 ud(ug+20)はステータス画面での攻撃力表示の時に使うくらいか。
そんな感じの思考錯誤を何日か経て、なんとか*atackのソースの基礎部分が出来た所だ。
gensuiは攻撃回数による減衰を表す。
gensui=75なら 75%の攻撃力になる。
つまり右手左手攻撃なら、左手攻撃は 75%になるよに今の所している。
複数攻撃なら 25%ずつ減る。
それからいよいよダメージ計算(atk)になる。
今回射程内に敵がいるかとか、HPが 0かとかはこちらで判定する事にした。
これによって*atackソース内でいちいち個別に判定しなくて済む。
ダメージ値等の値計算は一時的なもので、段々ゲームバランスの調整と共に変えていく。
とにかく稼動しなけりゃどうにもならない。
さらに頭痛いのだが、これに属性の計算をしなければいけない。
どういう計算にするかは、まだ考えてる途中だ。
それではテスト。
攻め込む側。

防衛側。差配確認のためわざと 2部隊にしている。

まだ制作途中なので分かり難いが、ダメージ表示を見ると 2回(左右素手)攻撃している(赤い 3の表示に重なってる)

2戦闘目。
HPが 0になると、とりあえず半透明表示。

次のターン、部隊が詰められる。

次のターン前列に来た。

次の部隊(3戦闘目)
防衛側は第三部隊が無いので繰越で第一部隊が出る。

今回はとりあえずここまで。