PuyoPuyoChap25
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[目次へもどる>PuyoPuyo]]
* ジャマーを落とそう [#f25c0348]
#contents
ここまでできたらそろそろ得点計算を考えたくなる頃である.
しかし得点計算のために一つ重要なものを忘れてはいないだろ...
そう,おじゃまぷよである.我々はおじゃまぷよをジャマーと...
別に邪魔だからジャマーと呼ぶわけではなく英語でjammerであ...
** JammerManager [#k0149d43]
では早速ジャマーを管理するJammerManagerクラスを作ろう.
#sh(ruby){{
class JammerManager
attr_accessor :jammers
def initialize(row_s, line_s)
@row_s = row_s
@line_s = line_s
@jammers = 0
@fall_max = (line_s / 3 + 1) * row_s
init_order
end
def init_order
@order = Array.new(@row_s){|r| r}.shuffle!.rotate_each
end
def jammers=(num)
@jammers = num
@jammers = 0 if @jammers < 0
end
def get_fall_table
fall_num = @jammers > @fall_max ? @fall_max : @jammers
@jammers -= fall_num
# make table
table = Array.new(@row_s){ [] }
@row_s.times do
break if fall_num == 0
row = @order.next
fall_num -= 1
num = 1 + fall_num / @row_s
table[row] = Array.new(num, :j)
end
return table
end
end
}}
初期化ではフィールドの大きさを与える.これは一度に何個の...
init_orderメソッドではジャマーがどの列にどの順で落ちるか...
get_fall_tableメソッドでは落下するジャマーのテーブルを返...
ジャマーが無ければ空のテーブルだし,めっちゃあれば一度に...
ちなみにBlockクラスに新たにジャマーを表すカラー:jを追加し...
** ジャマーを落とそう [#scb26b8d]
まずジャマーマネージャーを初期化する.ジャマーはフィール...
#sh(ruby){{
class Field
def initialize(row_s, line_s, block_s)
@row_s = row_s
@line_s = line_s
@block_s = block_s
@fallen = false
@eliminated = false
init_control_block_manager
init_table
init_jammer_manager
init_blocklist
init_connect_table
end
def init_jammer_manager
@jm = JammerManager.new(@row_s, @line_s)
end
def falldown_line(r,speed,waiting)
(略)
end
def falldown(speed = -6, waiting = true)
@fallen = false
@row_s.times do |r|
falldown_line(r,speed,waiting)
end
@fallen
end
def start_fall_jammer
fall_table = @jm.get_fall_table
fall_table.each.with_index do |jammers, row|
# col => block
jammers = jammers.map.with_index{|col, i|
next unless col
block = StableBlock.new(col, @block_s)
block.row = row
block.line = @line_s + 2 + i # base : linesize + ...
@active_blocks.push block
block
}
# extend row to size of @line_s + 2
@table[row][@line_s + 1] = @table[row][@line_s + 1]
# concat
@table[row].concat jammers
end
end
def eliminate_connection
@connect_table.each do |connection|
next if connection.size < 4
@eliminated = true # check flag
#### test jammer ####
@jm.jammers += connection.size
connection.each do |block|
block.set_collapse(40)
@table[block.row][block.line] = nil
@active_blocks.delete block
@collapse_blocks.push block
end
end
end
end
}}
start_fall_jammerメソッドによってジャマーをフィールドにセ...
まずはジャマーマネージャーからジャマーテーブルを取得し,...
また,ジャマーの落下は一度にドスン!と落ちてきた方がそれ...
そして肝心のジャマーの追加だが,現状では対戦相手がおらず...
あとはジャマーを落下させるフェーズを追加すれば完成である.
#sh(ruby){{
class FieldController
def init_phase
@phase = Phase.new
# added :control_block handler
@phase.add_start_handler(:control_block,
method(:start_control_block))
# added :falldown handler
@phase.add_condition_handler(:falldown,
method(:falldown_cond))
# added :elimiate handler
@phase.add_condition_handler(:eliminate,
method(:eliminate_cond))
# added :fall_jammer handler
@phase.add_start_handler(:fall_jammer,
method(:start_fall_jammer))
@phase.add_condition_handler(:fall_jammer,
method(:fall_jammer_cond))
@phase.add_end_handler(:fall_jammer,
method(:end_fall_jammer_to_con...
@phase.change :control_block
end
def update
#### debug ####
@field.instance_eval{Debug.print @jm.jammers}
###############
update_blocks
draw_field
return if @phase.waiting
case @phase.phase
when :phase_trans
@phase.trans_condition_check
when :control_block
update_control_block
when :falldown
update_falldown
when :eliminate
update_eliminate
when :fall_jammer
update_fall_jammer
end
end
def start_fall_jammer
@field.start_fall_jammer
end
def end_fall_jammer_to_control_block
@phase.set_timer(16)
end
def update_eliminate
eliminated = @field.eliminate
@phase.change eliminated ? :falldown : :fall_jammer
end
def update_fall_jammer
fallen = @field.falldown(-10, false)
@phase.change :control_block
end
def eliminate_cond
# wait collapse animation
!@field.blocks_reasonable_collapse?
end
def fall_jammer_cond
# wait fall && land animation && standard wait
!@field.blocks_move? && !@field.blocks_land? && @phas...
end
end
}}
これは問題無いだろう.ジャマーフェーズに入ったらstart_fal...
*** 実行 [#y6eda6d8]
さあ早速完成したジャマーを見てみよう!ちなみに左上の数字...
#media(PuyoPuyoChap25/PuyoPuyoChap25.flv);
これでうまく行くと思った?残念!まじで残念な結果にwww~
ジャマーをセットして落下させただけなので4つそろうと消えて...
それどころか消えたジャマーの分もそのままジャマーになって...
** ジャマーをちゃんと処理しよう [#f4919cf3]
このままでは意味不明なのでジャマーをしっかり処理しよう.
まずジャマーは4つくっついても消えないため,つながりチェッ...
そこで,ジャマーブロック一覧をその他のブロックと分けて扱...
#sh(ruby){{
class Field
def init_blocklist
@active_blocks = []
@jamming_blocks = []
@collapse_blocks = []
end
def start_fall_jammer
fall_table = @jm.get_fall_table
fall_table.each.with_index do |jammers, row|
# col => block
jammers = jammers.map.with_index{|col, i|
next unless col
block = StableBlock.new(col, @block_s)
block.row = row
block.line = @line_s + 2 + i # base : linesize + ...
@jamming_blocks.push block
block
}
# extend row to size of @line_s + 2
@table[row][@line_s + 1] = @table[row][@line_s + 1]
# concat
@table[row].concat jammers
end
end
end
}}
次につながりチェック時のデータ構造を拡張する.
今まではつながっているブロック一覧の配列を生成していたが...
#sh(ruby){{
class Field
def check_con_jammer(r,l,col,block)
#return false unless @jamming_blocks.include? block #...
@connect_table[-1][:jammers].push block
return false
end
def check_con_block(r,l,col,block)
return false unless @checklist.include? block
return false unless @table[r][l] && @table[r][l].colo...
@checklist.delete block
@connect_table[-1][:blocks].push block
return true
end
def check_connection(r,l,col)
return if r < 0 || r >= @row_s
return if l < 0 || l >= @line_s
return unless @table[r][l]
block = @table[r][l]
cont = block.color == :j ? check_con_jammer(r,l,col,b...
check_con_block(r,l,col,block)
return unless cont
check_connection(r,l+1,col) # up
check_connection(r,l-1,col) # down
check_connection(r+1,l,col) # right
check_connection(r-1,l,col) # left
end
def make_connect_table
init_connect_table
@checklist = @active_blocks.dup
while !@checklist.empty?
block = @checklist.first
r = block.row; l = block.line
# not consider if block out of screen
if r < 0 || r >= @row_s || l < 0 || l >= @line_s
@checklist.shift
next
end
col = block.color
@connect_table.push({:blocks => [], :jammers => []})
check_connection(r,l,col)
end
end
end
}}
今調査しているブロックがジャマーだった時は現在のつながり...
これで得られたコネクションテーブルに基づいてブロックを消...
これは単純で,4個以上つながっているコネクションであればそ...
少々注意なのはすでに他のコネクションにより消えているジャ...
#sh(ruby){{
class Field
def eliminate_connection
@connect_table.each do |connection|
next if connection[:blocks].size < 4
@eliminated = true # check flag
#### test jammer ####
@jm.jammers += connection[:blocks].size
# delete blocks
connection[:blocks].each do |block|
block.set_collapse(40)
@table[block.row][block.line] = nil
@active_blocks.delete block
@collapse_blocks.push block
end
# delete jammers [naive]
connection[:jammers].each do |jammer|
next unless @jamming_blocks.include?(jammer) # al...
jammer.set_collapse(40)
@table[jammer.row][jammer.line] = nil
@jamming_blocks.delete jammer
@collapse_blocks.push jammer
end
end
end
end
}}
*** 実行 [#z691de2b]
今度はちゃんとしたジャマーとなっている.
#media(PuyoPuyoChap25/PuyoPuyoChap25_2.flv);
** 最後に少々 [#naf825f8]
ジャマーの挙動はほぼオーケーとなったが,ここで一つ見落と...
例えばフィールド一杯にブロックがあるときにジャマーが大量...
すると,フィールドの見えないところにジャマーが大量に乗っ...
別にそれでもいいちゃあいいが,無制限にフィールドの高さが...
#sh(ruby){{
class Field
def slice_limited_line
limit = @line_s + 2
@row_s.times do |row|
next if @table[row].size < limit
@table[row][limit..-1].each do |block|
@jamming_blocks.delete block
end
@table[row] = @table[row][0...limit]
end
end
end
class FieldController
def end_fall_jammer_to_control_block
@phase.set_timer(16)
# delete blocks is over limited line
@field.slice_limited_line
end
end
}}
終了行:
[[目次へもどる>PuyoPuyo]]
* ジャマーを落とそう [#f25c0348]
#contents
ここまでできたらそろそろ得点計算を考えたくなる頃である.
しかし得点計算のために一つ重要なものを忘れてはいないだろ...
そう,おじゃまぷよである.我々はおじゃまぷよをジャマーと...
別に邪魔だからジャマーと呼ぶわけではなく英語でjammerであ...
** JammerManager [#k0149d43]
では早速ジャマーを管理するJammerManagerクラスを作ろう.
#sh(ruby){{
class JammerManager
attr_accessor :jammers
def initialize(row_s, line_s)
@row_s = row_s
@line_s = line_s
@jammers = 0
@fall_max = (line_s / 3 + 1) * row_s
init_order
end
def init_order
@order = Array.new(@row_s){|r| r}.shuffle!.rotate_each
end
def jammers=(num)
@jammers = num
@jammers = 0 if @jammers < 0
end
def get_fall_table
fall_num = @jammers > @fall_max ? @fall_max : @jammers
@jammers -= fall_num
# make table
table = Array.new(@row_s){ [] }
@row_s.times do
break if fall_num == 0
row = @order.next
fall_num -= 1
num = 1 + fall_num / @row_s
table[row] = Array.new(num, :j)
end
return table
end
end
}}
初期化ではフィールドの大きさを与える.これは一度に何個の...
init_orderメソッドではジャマーがどの列にどの順で落ちるか...
get_fall_tableメソッドでは落下するジャマーのテーブルを返...
ジャマーが無ければ空のテーブルだし,めっちゃあれば一度に...
ちなみにBlockクラスに新たにジャマーを表すカラー:jを追加し...
** ジャマーを落とそう [#scb26b8d]
まずジャマーマネージャーを初期化する.ジャマーはフィール...
#sh(ruby){{
class Field
def initialize(row_s, line_s, block_s)
@row_s = row_s
@line_s = line_s
@block_s = block_s
@fallen = false
@eliminated = false
init_control_block_manager
init_table
init_jammer_manager
init_blocklist
init_connect_table
end
def init_jammer_manager
@jm = JammerManager.new(@row_s, @line_s)
end
def falldown_line(r,speed,waiting)
(略)
end
def falldown(speed = -6, waiting = true)
@fallen = false
@row_s.times do |r|
falldown_line(r,speed,waiting)
end
@fallen
end
def start_fall_jammer
fall_table = @jm.get_fall_table
fall_table.each.with_index do |jammers, row|
# col => block
jammers = jammers.map.with_index{|col, i|
next unless col
block = StableBlock.new(col, @block_s)
block.row = row
block.line = @line_s + 2 + i # base : linesize + ...
@active_blocks.push block
block
}
# extend row to size of @line_s + 2
@table[row][@line_s + 1] = @table[row][@line_s + 1]
# concat
@table[row].concat jammers
end
end
def eliminate_connection
@connect_table.each do |connection|
next if connection.size < 4
@eliminated = true # check flag
#### test jammer ####
@jm.jammers += connection.size
connection.each do |block|
block.set_collapse(40)
@table[block.row][block.line] = nil
@active_blocks.delete block
@collapse_blocks.push block
end
end
end
end
}}
start_fall_jammerメソッドによってジャマーをフィールドにセ...
まずはジャマーマネージャーからジャマーテーブルを取得し,...
また,ジャマーの落下は一度にドスン!と落ちてきた方がそれ...
そして肝心のジャマーの追加だが,現状では対戦相手がおらず...
あとはジャマーを落下させるフェーズを追加すれば完成である.
#sh(ruby){{
class FieldController
def init_phase
@phase = Phase.new
# added :control_block handler
@phase.add_start_handler(:control_block,
method(:start_control_block))
# added :falldown handler
@phase.add_condition_handler(:falldown,
method(:falldown_cond))
# added :elimiate handler
@phase.add_condition_handler(:eliminate,
method(:eliminate_cond))
# added :fall_jammer handler
@phase.add_start_handler(:fall_jammer,
method(:start_fall_jammer))
@phase.add_condition_handler(:fall_jammer,
method(:fall_jammer_cond))
@phase.add_end_handler(:fall_jammer,
method(:end_fall_jammer_to_con...
@phase.change :control_block
end
def update
#### debug ####
@field.instance_eval{Debug.print @jm.jammers}
###############
update_blocks
draw_field
return if @phase.waiting
case @phase.phase
when :phase_trans
@phase.trans_condition_check
when :control_block
update_control_block
when :falldown
update_falldown
when :eliminate
update_eliminate
when :fall_jammer
update_fall_jammer
end
end
def start_fall_jammer
@field.start_fall_jammer
end
def end_fall_jammer_to_control_block
@phase.set_timer(16)
end
def update_eliminate
eliminated = @field.eliminate
@phase.change eliminated ? :falldown : :fall_jammer
end
def update_fall_jammer
fallen = @field.falldown(-10, false)
@phase.change :control_block
end
def eliminate_cond
# wait collapse animation
!@field.blocks_reasonable_collapse?
end
def fall_jammer_cond
# wait fall && land animation && standard wait
!@field.blocks_move? && !@field.blocks_land? && @phas...
end
end
}}
これは問題無いだろう.ジャマーフェーズに入ったらstart_fal...
*** 実行 [#y6eda6d8]
さあ早速完成したジャマーを見てみよう!ちなみに左上の数字...
#media(PuyoPuyoChap25/PuyoPuyoChap25.flv);
これでうまく行くと思った?残念!まじで残念な結果にwww~
ジャマーをセットして落下させただけなので4つそろうと消えて...
それどころか消えたジャマーの分もそのままジャマーになって...
** ジャマーをちゃんと処理しよう [#f4919cf3]
このままでは意味不明なのでジャマーをしっかり処理しよう.
まずジャマーは4つくっついても消えないため,つながりチェッ...
そこで,ジャマーブロック一覧をその他のブロックと分けて扱...
#sh(ruby){{
class Field
def init_blocklist
@active_blocks = []
@jamming_blocks = []
@collapse_blocks = []
end
def start_fall_jammer
fall_table = @jm.get_fall_table
fall_table.each.with_index do |jammers, row|
# col => block
jammers = jammers.map.with_index{|col, i|
next unless col
block = StableBlock.new(col, @block_s)
block.row = row
block.line = @line_s + 2 + i # base : linesize + ...
@jamming_blocks.push block
block
}
# extend row to size of @line_s + 2
@table[row][@line_s + 1] = @table[row][@line_s + 1]
# concat
@table[row].concat jammers
end
end
end
}}
次につながりチェック時のデータ構造を拡張する.
今まではつながっているブロック一覧の配列を生成していたが...
#sh(ruby){{
class Field
def check_con_jammer(r,l,col,block)
#return false unless @jamming_blocks.include? block #...
@connect_table[-1][:jammers].push block
return false
end
def check_con_block(r,l,col,block)
return false unless @checklist.include? block
return false unless @table[r][l] && @table[r][l].colo...
@checklist.delete block
@connect_table[-1][:blocks].push block
return true
end
def check_connection(r,l,col)
return if r < 0 || r >= @row_s
return if l < 0 || l >= @line_s
return unless @table[r][l]
block = @table[r][l]
cont = block.color == :j ? check_con_jammer(r,l,col,b...
check_con_block(r,l,col,block)
return unless cont
check_connection(r,l+1,col) # up
check_connection(r,l-1,col) # down
check_connection(r+1,l,col) # right
check_connection(r-1,l,col) # left
end
def make_connect_table
init_connect_table
@checklist = @active_blocks.dup
while !@checklist.empty?
block = @checklist.first
r = block.row; l = block.line
# not consider if block out of screen
if r < 0 || r >= @row_s || l < 0 || l >= @line_s
@checklist.shift
next
end
col = block.color
@connect_table.push({:blocks => [], :jammers => []})
check_connection(r,l,col)
end
end
end
}}
今調査しているブロックがジャマーだった時は現在のつながり...
これで得られたコネクションテーブルに基づいてブロックを消...
これは単純で,4個以上つながっているコネクションであればそ...
少々注意なのはすでに他のコネクションにより消えているジャ...
#sh(ruby){{
class Field
def eliminate_connection
@connect_table.each do |connection|
next if connection[:blocks].size < 4
@eliminated = true # check flag
#### test jammer ####
@jm.jammers += connection[:blocks].size
# delete blocks
connection[:blocks].each do |block|
block.set_collapse(40)
@table[block.row][block.line] = nil
@active_blocks.delete block
@collapse_blocks.push block
end
# delete jammers [naive]
connection[:jammers].each do |jammer|
next unless @jamming_blocks.include?(jammer) # al...
jammer.set_collapse(40)
@table[jammer.row][jammer.line] = nil
@jamming_blocks.delete jammer
@collapse_blocks.push jammer
end
end
end
end
}}
*** 実行 [#z691de2b]
今度はちゃんとしたジャマーとなっている.
#media(PuyoPuyoChap25/PuyoPuyoChap25_2.flv);
** 最後に少々 [#naf825f8]
ジャマーの挙動はほぼオーケーとなったが,ここで一つ見落と...
例えばフィールド一杯にブロックがあるときにジャマーが大量...
すると,フィールドの見えないところにジャマーが大量に乗っ...
別にそれでもいいちゃあいいが,無制限にフィールドの高さが...
#sh(ruby){{
class Field
def slice_limited_line
limit = @line_s + 2
@row_s.times do |row|
next if @table[row].size < limit
@table[row][limit..-1].each do |block|
@jamming_blocks.delete block
end
@table[row] = @table[row][0...limit]
end
end
end
class FieldController
def end_fall_jammer_to_control_block
@phase.set_timer(16)
# delete blocks is over limited line
@field.slice_limited_line
end
end
}}
ページ名: