[[目次へもどる>PuyoPuyo]] * ジャマー発生数を計算しよう [#rbb6deb7] #contents スコア計算ができたということはいよいよジャマーの発生数をちゃんと計算できるということである! ** ジャマーの発生数 [#t3b53601] ジャマーは連鎖スコアが大きいほど沢山発生する. ジャマーの発生数の式は以下. ジャマー発生数 = 連鎖スコア / ジャマーレート 非常にわかりやすい. 続いてジャマーレートの式 ジャマーレート = 初期レート * レート倍率 レート倍率は経過時間によって増加する.また,レート倍率はマージンタイムの間は 増加しない.マージンタイムを過ぎると経過時間によって以下の表に基づいたレート倍率となる((これについてはサイトによって諸説あるがまあこまかいことはどうでも良い)). ちなみに経過時間は16進数表記である点に注意.(20(16)=32秒) |経過時間(16)[s]|0|20|40|60|80|A0|C0|E0|100|120|140|160|180|1A0以上|h |レート倍率|3/4|2/4|3/8|2/8|3/16|2/16|3/32|2/32|3/64|2/64|3/128|2/128|3/256|2/256| さて,またこんな表をだらだら書いといてなんだが,マージンタイムも含めたレート倍利率は以下の式で求まる. レート倍率 = if rate_index < 0 then 1 else if rate_index >= 14 then 2/256 else (3 - rate_index % 2)/(4 * 2 ** (rate_index / 2)) ただし rate_index = (sec - margin) / 0x20 レート倍率は最小が1で小数以下は切り捨てる また,例えばジャマーレート70の時に,スコア100をたたくとジャマーは1コ発生するが,この時余った30は保存しておき,次のジャマーの個数計算に加算される((これもぷよぷよのバージョンによって加算されないものもあるが折角なので導入)). ** 実装 [#qec49e9f] あとは淡々と実装していこう. #sh(ruby){{ class JammerManager def initialize(row_s, line_s) @row_s = row_s @line_s = line_s @jammers = 0 @rest = 0 @fall_max = (line_s / 3 + 1) * row_s @gen_jammers = 0 init_order end def calc_effective_rate(rate, margin, playtime) playsec = playtime / 60 rate_index = (playsec - margin) / 0x20 if rate_index < 0 # margin effective_rate = rate elsif rate_index >= 14 # max rate effective_rate = (rate * Rational(2, 256)).to_i else effective_rate = (rate * Rational(3 - rate_index % 2, 4 * 2 ** (rate_index/2))).to_i end [effective_rate, 1].max end def calc_jammer(score, rate, margin, playtime) effective_rate = calc_effective_rate(rate, margin, playtime) score += @rest # prev calc rest @rest = score % effective_rate @gen_jammers = score / effective_rate end end }} デバッグや利便性を考えてスコアと同様にジャマーの発生数の計算結果をインスタンス変数に保存しておくことにした.ジャマーの発生数の計算をそのままプログラムしているだけなので特に問題は無いだろう.あるとすればRationalだろうか.これはRubyの組み込みクラスで分数を表すクラスである.整数や浮動点小数と普通にミックスして計算可能である. #sh(ruby){{ class ScenePuyoPuyo < SceneBase def start @playtime = 0 @margin_time = 96 (略) end def update super @players.each do |controller| controller.update end @playtime += 1 end end }} シーンのプレイタイム(フレーム)をカウントする@playtimeとマージンタイム@margin_timeを追加した.マージンタイムはプレイヤーのさらに上,ゲームルールに属するのでとりあえずシーンに追加することにした. #sh(ruby){{ module GameMain def self.scene @scene.first end end }} シーンが持つ変数を取得しなければならないので,現在のシーンを取得するメソッドをGameMainに追加した. #sh(ruby){{ class Field def initialize(row_s, line_s, block_s, cbm, sm) @row_s = row_s @line_s = line_s @block_s = block_s @fallen = false @eliminated = false @cbm = cbm @sm = sm @chain = 0 @jammer_rate = 70 init_table init_jammer_manager init_blocklist init_connect_table end def eliminate @eliminated = false make_connect_table fair_connect_table @chain += 1 unless @connect_table.empty? @sm.score += @sm.calc_chain_score(@connect_table, @chain) scene = GameMain.scene unless @connect_table.empty? @jm.jammers += @jm.calc_jammer(@sm.chain_score, @jammer_rate, scene.margin_time, scene.playtime) end eliminate_connection @eliminated end end }} 初期ジャマーレートはFieldクラスに追加した.なぜならぷよぷよフィーバーではキャラごとにレートが異なるほか,通常時とフィーバー時でレートが変動するためである. そしてブロックの消去時にジャマーを発生させれば完成である. ** 実行 [#r7dac54f] これでちゃんとジャマーの発生が計算されるようになった. デバッグのためマージンタイムを0にして実行した. #media(PuyoPuyoChap28/PuyoPuyoChap28.flv); 画面上に様々な情報を表示しているが,32秒経過したところでジャマーレートが下がったことに注目.