ゲーム作ってます5
投稿者: taki 投稿日:2016/11/14 01:52
≪ゲーム作ってます6
|
ゲーム作ってます4.5≫
自作戦闘の話です。
前回ブログが通常よりも反響があったので
興味のある人が多い分野なのかもしれません。
ブログ閲覧数を稼ぐチャンス。
というわけで今回はとりあえず制作過程の一部と作ったものを公開して
次回もう一回ぐらい続きをブログに書こうと思います。
長いので戻るボタンを押すなら今ですよ。
1.何の為に我々は戦うのか
ゲームに戦闘を入れる必要はあるのかをまず考えます。
面倒くさいことはなるべく無しで済ませたいのです。
ストーリーメインのゲームだと自分で育てたキャラがボスを倒すことで
達成感が得られるので楽しみに繋がる気がします。
戦闘システムが独特なものはそれ自体がゲームの楽しみの中心だったりします。
今回は上記のどっちでもねーなーとは思いつつ、プレーヤーにゲームを進める上で
必要な呪文がどんなものかヒントを出すために、半ば仕方なく実装することにしました。
スタートはこんなですが作り始めると割と楽しいです。
2.仕様をどうしよう
実装することは決まったのでもう少し具体的に
どんなシステムにするか考えます。
理想はこの段階でどんなスクリプトにするかまでキチンと決めてから
スクリプトの編集に入ることですが、私はそれが可能な境地には達していないので
ざっくりとだけ決めて詳細は手を動かしながら考えることにします。
必要な機能としては
・キーボードからコマンドを入力できること
・コマンドに応じて効果の異なる呪文が使えること
・HPの情報をもとに勝敗が判定できること
なるべく簡単に済ませたいなーというわけで
・1対1でプレイヤーが必ず先攻
(複数対複数は1対1よりべらぼうに面倒くさいのです。)
このぐらい考えると頭がショートするので
まずは1対1で互いに攻撃するだけの簡単なものを作ってみます。
簡単なものを作って後から付け加えていくやり方だと
とりあえず動かすことができるのでモチベーションが保ちやすい気がします。
一番効率がいいのは最初に仕様を固めるやり方だと思いますが
残念ながらレベルが足りません。
3.頼むから動いてくれよ
ターン制で交互に攻撃するだけのものをまずは作ってみます。
後で応用が利くように攻撃によるダメージ計算は別の自作関数で作ります。
この時「〇〇の攻撃、XXはダメージ」というのをどうするかで悩みます。
ダメージの計算やメッセージの表示を二つ作ってフラグで切り替えるのは
呪文が増えた数だけ手間が2倍になるので避けたかったのです。
ここでやってみたのは攻撃するキャラクタと受けるキャラクタを表す変数を作って
ターンによってその変数の中身を入れ替える方法です。
おしゃれに(?)配列とか使ってますgetVariable("tp")というやつです。
tpが何の略だったかは忘れました。
後にこの方法を使えば複数対複数も作れるのではという思いつきが
長い寄り道につながります。
とりあえずここでどうやってターンを切り替えるか、勝敗を判定するか
どのタイミングで攻撃するキャラにステータスを入れて、
攻撃を受けたキャラのステータスをもとのキャラに反映するかといった部分を
つかむことができたので、次はキーボードから入力したコマンドを使えるようにします。
4.ちからつきるとはなさけない
やたらめったら長くなってしまったので続きは次回にしたいと思います。
(正直にいうとブログを書くのに力尽きました)
とりあえず現在実装しているものを貼っておきます。
コマンドを入力できるようにして、状態異常を作って
経験値制レベルアップもできるようになっています。
頼むからそうなっていてくれ。
質問頂ければなるべくさっさと答えます。
ツイート
前回ブログが通常よりも反響があったので
興味のある人が多い分野なのかもしれません。
ブログ閲覧数を稼ぐチャンス。
というわけで今回はとりあえず制作過程の一部と作ったものを公開して
次回もう一回ぐらい続きをブログに書こうと思います。
長いので戻るボタンを押すなら今ですよ。
1.何の為に我々は戦うのか
ゲームに戦闘を入れる必要はあるのかをまず考えます。
面倒くさいことはなるべく無しで済ませたいのです。
ストーリーメインのゲームだと自分で育てたキャラがボスを倒すことで
達成感が得られるので楽しみに繋がる気がします。
戦闘システムが独特なものはそれ自体がゲームの楽しみの中心だったりします。
今回は上記のどっちでもねーなーとは思いつつ、プレーヤーにゲームを進める上で
必要な呪文がどんなものかヒントを出すために、半ば仕方なく実装することにしました。
スタートはこんなですが作り始めると割と楽しいです。
2.仕様をどうしよう
実装することは決まったのでもう少し具体的に
どんなシステムにするか考えます。
理想はこの段階でどんなスクリプトにするかまでキチンと決めてから
スクリプトの編集に入ることですが、私はそれが可能な境地には達していないので
ざっくりとだけ決めて詳細は手を動かしながら考えることにします。
必要な機能としては
・キーボードからコマンドを入力できること
・コマンドに応じて効果の異なる呪文が使えること
・HPの情報をもとに勝敗が判定できること
なるべく簡単に済ませたいなーというわけで
・1対1でプレイヤーが必ず先攻
(複数対複数は1対1よりべらぼうに面倒くさいのです。)
このぐらい考えると頭がショートするので
まずは1対1で互いに攻撃するだけの簡単なものを作ってみます。
簡単なものを作って後から付け加えていくやり方だと
とりあえず動かすことができるのでモチベーションが保ちやすい気がします。
一番効率がいいのは最初に仕様を固めるやり方だと思いますが
残念ながらレベルが足りません。
3.頼むから動いてくれよ
ターン制で交互に攻撃するだけのものをまずは作ってみます。
後で応用が利くように攻撃によるダメージ計算は別の自作関数で作ります。
この時「〇〇の攻撃、XXはダメージ」というのをどうするかで悩みます。
ダメージの計算やメッセージの表示を二つ作ってフラグで切り替えるのは
呪文が増えた数だけ手間が2倍になるので避けたかったのです。
ここでやってみたのは攻撃するキャラクタと受けるキャラクタを表す変数を作って
ターンによってその変数の中身を入れ替える方法です。
おしゃれに(?)配列とか使ってますgetVariable("tp")というやつです。
tpが何の略だったかは忘れました。
後にこの方法を使えば複数対複数も作れるのではという思いつきが
長い寄り道につながります。
とりあえずここでどうやってターンを切り替えるか、勝敗を判定するか
どのタイミングで攻撃するキャラにステータスを入れて、
攻撃を受けたキャラのステータスをもとのキャラに反映するかといった部分を
つかむことができたので、次はキーボードから入力したコマンドを使えるようにします。
def attack() getVariable("tp")[1][1]=getVariable("tp")[1][1]-getVariable("tp")[0][2]*(1+0.1*rand(6)) if getVariable("tp")[1][1]<0 getVariable("tp")[1][1]=0 end return end def battle() turn=0 a=createArray() a[0]=createArray() a[1]=createArray() a[0][0]="主人公" a[0][1]=100 a[0][2]=10 a[1][0]="enemy" a[1][1]=50 a[1][2]=10 setFlag("battle",true) setVariable("tp",createArray()) getVariable("tp")[0]=createArray() getVariable("tp")[1]=createArray() while getFlag("battle") speak("HPP",a[0][1],"\nhpe",a[1][1],"\nturn",turn) if turn==0 i=0 while i<2 j=0 while j<3 getVariable("tp")[i][j]=a[i][j] j=j+1 end i=i+1 end elsif turn==1 i=1 ii=0 while i>-1 j=0 while j<3 getVariable("tp")[i][j]=a[ii][j] j=j+1 end i=i-1 ii=ii+1 end end hpas_old=getVariable("tp")[1][1] attack() speak(getVariable("tp")[0][0],"の攻撃","\n",getVariable("tp")[1][0],"は",hpas_old-getVariable("tp")[1][1],"のダメージ") if getVariable("tp")[1][1]==0 setFlag("battle",false) end if turn==0 i=0 while i<2 j=0 while j<3 a[i][j]=getVariable("tp")[i][j] j=j+1 end i=i+1 end elsif turn==1 i=1 ii=0 while i>-1 j=0 while j<3 a[ii][j]=getVariable("tp")[i][j] j=j+1 end i=i-1 ii=ii+1 end end case turn when 0 turn=1 when 1 turn=0 end end end
4.ちからつきるとはなさけない
やたらめったら長くなってしまったので続きは次回にしたいと思います。
(正直にいうとブログを書くのに力尽きました)
とりあえず現在実装しているものを貼っておきます。
コマンドを入力できるようにして、状態異常を作って
経験値制レベルアップもできるようになっています。
頼むからそうなっていてくれ。
質問頂ければなるべくさっさと答えます。
def battle(ne) turn=0 a=createArray() a[0]=createArray() a[1]=createArray() i=0 while i<14 a[0][i]=getVariable("status")[0][i] a[1][i]=getVariable("status")[ne][i] i=i+1 end a[0][14]=0 a[1][14]=0 setFlag("battle",true) setVariable("tp",createArray()) getVariable("tp")[0]=createArray() getVariable("tp")[1]=createArray() while getFlag("battle") speak("HPP",a[0][2],"\nhpe",a[1][2],"\nturn",turn) if turn==0 i=0 while i<2 j=0 while j<15 getVariable("tp")[i][j]=a[i][j] j=j+1 end i=i+1 end elsif turn==1 i=1 ii=0 while i>-1 j=0 while j<15 getVariable("tp")[i][j]=a[ii][j] j=j+1 end i=i-1 ii=ii+1 end end if turn==0 command() else setVariable("command",getVariable("status")[ne][floor(9+rand(3))]) end if getVariable("command")!="CURE" case getVariable("tp")[0][14] when 0 when 1 if rand(3)!=0 setVariable("command","PARALYSIS") end when 2 if getVariable("command")!="FIRE" setVariable("command","FROZEN") end end end judge_battle() if getVariable("tp")[1][2]==0||getVariable("tp")[0][2]==0 setFlag("battle",false) end if turn==0 i=0 while i<2 j=0 while j<15 a[i][j]=getVariable("tp")[i][j] j=j+1 end i=i+1 end elsif turn==1 i=1 ii=0 while i>-1 j=0 while j<15 a[ii][j]=getVariable("tp")[i][j] j=j+1 end i=i-1 ii=ii+1 end end case turn when 0 turn=1 when 1 turn=0 end end #____result_____ i=0 while i<14 getVariable("status")[0][i]=a[0][i] i=i+1 end if a[0][2]>0&&a[1][2]==0 speak("playerは勝利した") speak("playerは",getVariable("status")[ne][8],"経験値を得た") getVariable("status")[0][8]=getVariable("status")[0][8]+getVariable("status")[ne][8] if getVariable("status")[0][8]>=getVariable("status")[0][9] getVariable("status")[0][1]=getVariable("status")[0][1]+1 speak("レベル",getVariable("status")[0][1],"になった") getVariable("status")[0][12]=floor(getVariable("status")[0][12]*1.5) getVariable("status")[0][13]=floor(getVariable("status")[0][13]*1.2) getVariable("status")[0][2]=getVariable("status")[0][12] getVariable("status")[0][3]=getVariable("status")[0][13] i=4 while i<8 getVariable("status")[0][i]=getVariable("status")[0][i]+20 i=i+1 end getVariable("status")[0][9]=floor(getVariable("status")[0][9]*2.5) else speak("次のレベルに必要な経験値は",getVariable("status")[0][9]-getVariable("status")[0][8]) end elsif a[0][2]>0&&a[1][2]>0 setVariable("px",getVariable("px")-getVariable("vx")) setVariable("py",getVariable("py")-getVariable("vy")) else speak("playerは力尽きた") setPartyMemberDeathAll() end deleteAllSprite() px=getVariable("px") py=getVariable("py") pass=getVariable("map")[px][py][0] cout=getVariable("counter") wall=getVariable("wall")[pass][cout] setSpriteRect(createSprite(wall), 0,0 , 512, 384, 0, 0, 512, 384) drawCanvas() end
def judge_battle() hpas_old=getVariable("tp")[1][2] hact_old=getVariable("tp")[0][2] mpas_old=getVariable("tp")[1][3] mact_old=getVariable("tp")[0][3] stanm=createArray() stanm[0]=getVariable("tp")[0][14] stanm[1]=getVariable("tp")[1][14] case getVariable("command") when "ATTACK" speak(getVariable("tp")[0][0],"の攻撃") getVariable("tp")[1][2]=getVariable("tp")[1][2]-floor(getVariable("tp")[0][4]*(1+0.1*rand(6))-getVariable("tp")[1][5]*0.5) when "ESCAPE" speak(getVariable("tp")[0][0],"は逃亡を試みた") if getVariable("tp")[0][0]==getVariable("status")[0][0] #if rand(3)==0 setFlag("battle",false) speak("うまく逃げ切った") #else #speak("逃亡に失敗した") #end else speak("魔王からは逃げられない") end when "PARALYSIS" speak(getVariable("tp")[0][0],"はマヒしていて動けない") when "FROZEN" speak(getVariable("tp")[0][0],"は氷漬けで動けない") else speak(getVariable("tp")[0][0],"は",getVariable("command"),"を唱えた") case getVariable("command") when "CONVERT" speak(getVariable("tp")[0][0],"から光があふれる") getVariable("tp")[0][3]=getVariable("tp")[0][3]+floor(getVariable("tp")[0][2]*0.1) getVariable("tp")[0][2]=floor(getVariable("tp")[0][2]*0.9) if getVariable("tp")[0][3]>getVariable("tp")[0][13] getVariable("tp")[0][3]=getVariable("tp")[0][13] end when "EXPLOSION" if getVariable("tp")[0][3]<30 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-30 speak("激しい爆発とともに轟音が鳴り響く") getVariable("tp")[1][2]=getVariable("tp")[1][2]-floor(50*getVariable("tp")[0][6]/getVariable("tp")[1][7]) end when "FIRE" if getVariable("tp")[0][3]<20 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-20 speak("火柱が立ち上る") getVariable("tp")[1][2]=getVariable("tp")[1][2]-floor(20*getVariable("tp")[0][6]/getVariable("tp")[1][7]) if stanm[0]==2 stanm[0]=0 end end when "BLIZZARD" if getVariable("tp")[0][3]<30 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-30 speak("猛吹雪が吹き荒れる") getVariable("tp")[1][2]=getVariable("tp")[1][2]-floor(20*getVariable("tp")[0][6]/getVariable("tp")[1][7]) stanm[0]=2 stanm[1]=2 end when "THUNDER" if getVariable("tp")[0][3]<30 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-30 speak("激しい稲妻が周囲を駆ける") getVariable("tp")[1][2]=getVariable("tp")[1][2]-floor(30*getVariable("tp")[0][6]/getVariable("tp")[1][7]) if rand(3)==0 stanm[1]=1 end end when "FREEZE" if getVariable("tp")[0][3]<30 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-30 speak("辺りが冷気に包まれる") getVariable("tp")[1][2]=getVariable("tp")[1][2]-floor(20*getVariable("tp")[0][6]/getVariable("tp")[1][7]) if rand(3)==0 stanm[1]=2 end end when "POISON" if getVariable("tp")[0][3]<30 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-30 speak("毒の霧がたちこめる") stanm[1]=3 end when "HEAL" if getVariable("tp")[0][3]<10 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-10 speak("癒しの光が",getVariable("tp")[0][0],"を包む") getVariable("tp")[0][2]=getVariable("tp")[0][2]+floor(getVariable("tp")[0][12]*0.2) if getVariable("tp")[0][2]>getVariable("tp")[0][12] getVariable("tp")[0][2]=getVariable("tp")[0][12] end end when "CURE" if getVariable("tp")[0][3]<20 speak("しかし魔力が足りなかった") else getVariable("tp")[0][3]=getVariable("tp")[0][3]-20 speak("浄化の光が",getVariable("tp")[0][0],"を包む") stanm[0]=0 end else speak("しかし何も起こらなかった") end end if getVariable("tp")[1][2]<0 getVariable("tp")[1][2]=0 end if hact_old-getVariable("tp")[0][2]>0 speak(getVariable("tp")[0][0],"は",hact_old-getVariable("tp")[0][2],"のダメージ") end if hpas_old-getVariable("tp")[1][2]>0 speak(getVariable("tp")[1][0],"は",hpas_old-getVariable("tp")[1][2],"のダメージ") end if mpas_old-getVariable("tp")[1][3]>0 speak(getVariable("tp")[1][0],"は魔力を",mpas_old-getVariable("tp")[1][3],"失った") end if hact_old-getVariable("tp")[0][2]<0 speak(getVariable("tp")[0][0],"は",getVariable("tp")[0][2]-hact_old,"回復した") end if mact_old-getVariable("tp")[0][3]<0 speak(getVariable("tp")[0][0],"は魔力を",getVariable("tp")[0][3]-mact_old,"回復した") end i=0 while i<2 if stanm[i]!=getVariable("tp")[i][14] case stanm[i] when 0 speak(getVariable("tp")[i][0],"は状態異常から回復した") when 1 speak(getVariable("tp")[i][0],"はマヒした") when 2 speak(getVariable("tp")[i][0],"は凍りついた") when 3 speak(getVariable("tp")[i][0],"は毒をあびた") when 4 speak(getVariable("tp")[i][0],"は魔法を封じられた") end end getVariable("tp")[i][14]=stanm[i] i=i+1 end if stanm[0]==3 damage=floor(getVariable("tp")[0][12]*0.1) if damage>getVariable("tp")[0][2] damage=getVariable("tp")[0][2] end speak(getVariable("tp")[0][0],"は毒によって",damage,"のダメージ") getVariable("tp")[0][2]=getVariable("tp")[0][2]-damage end
コメントする
コメントするには、ログインする必要があります。
コメント一覧
お恥ずかしながら、 わたくしも戦闘のプログラムを考えておるのですが、 こんなふうに整然とはしておりません・・・ やっぱりプログラムに熟練している方は違うよね、ラヴィ君・・・ |
汎用性を意識してスクリプトを組まれているところが、 すごいですね。 経験値制のシステムの作り方や、 ダメージの計算式など参考になる点がたくさんあります。 |
そこそこ重いので、
保管用のold以外にも
内部処理用のwrkを予め
準備しておいても良いかも
ラストで代入すれば
呼び出しが2回ですみますし
文字数自体も短く出来ます
ここまでスクリプトを見ていただけて嬉しいです。
関数によって処理に必要な時間の幅があるのですね。
wrkを準備すれば確かに文字数もぐっと減らすことができて
変数の意味も分かりやすくなっていいですね。