CoRサンプル集: テトリスのような落ちものパズルゲームのサンプル
テトリスのような落ちものパズルゲームのサンプル。
音楽・画像などの素材は一切使用していないので、コピペだけで移植出来ます。
操作方法
横移動:←→
ソフトドロップ:↓
ハードドロップ:↑
左回転:Z
右回転:X
ホールド:C
音楽・画像などの素材は一切使用していないので、コピペだけで移植出来ます。
操作方法
横移動:←→
ソフトドロップ:↓
ハードドロップ:↑
左回転:Z
右回転:X
ホールド:C
プレー:3
(人数:2)
クリア:2
評価: 10 (1回)
タグが設定されていません
#==============================================================================
# 描画関連ユーティリティ関数
#==============================================================================
# グリッドの中心座標を取得する
#
# @return [Array<Integer>] グリッド原点のピクセル座標 [x, y]
def get_grid_origin
center_x = (CONFIG[:window_width] / 2).floor
center_y = (CONFIG[:window_height] / 2).floor
return center_x + CONFIG[:grid_offset_x], center_y + CONFIG[:grid_offset_y]
end
# グリッド座標がグリッド中央から何ピクセル離れているかを計算する
#
# @param grid_pos [Integer] グリッド座標
# @param width [Integer] グリッド幅 X座標が欲しいなら横マス数、Y座標なら縦マス数
# @return [Integer] ピクセル座標
def grid_center_offset(grid_pos, width, block_size)
correction = block_size / 2 # 補正量
half_width = width / 2
return ((grid_pos - half_width) * block_size + correction).floor
end
# グリッド座標を画面座標(ピクセル)に変換する
#
# @param grid_x [Integer] グリッドX座標
# @param grid_y [Integer] グリッドY座標
# @return [Array<Integer>] ピクセル座標 [x, y]
def get_grid_position(grid_x, grid_y)
cell_size = CONFIG[:cell_size]
origin_x, origin_y = get_grid_origin()
px = origin_x + grid_center_offset(grid_x, CONFIG[:grid_width], cell_size)
py = origin_y + grid_center_offset(grid_y, CONFIG[:grid_height], cell_size)
return px, py
end
# グリッドとセル用スプライトを生成する
#
# @param sprite_name [String] セル描画用スプライト名
# @return [Array<Array>] グリッド配列とスプライト配列
def make_grid(sprite_name)
height = CONFIG[:grid_height]
width = CONFIG[:grid_width]
grid = Array.new(height) { Array.new(width, 0) }
cell_sprites = Array.new(height) do |y|
Array.new(width) do |x|
px, py = get_grid_position(x, y)
put_text sprite_name do
position px, py
text '■'
end
end
end
return grid, cell_sprites
end
# グリッドの差分を計算する
#
# @param current [Array<Array>] 現在のグリッド
# @param previous [Array<Array>, nil] 前回のグリッド(nil の場合は全描画)
# @return [Array<Array<(Integer, Integer)>] 変更されたセルの座標ペア配列
def grid_diff(current, previous)
height = CONFIG[:grid_height]
width = CONFIG[:grid_width]
# 初回描画または全描画の場合
return height.times.flat_map { |y| width.times.map { |x| [y, x] } } if previous.nil?
diffs = []
height.times do |y|
width.times do |x|
diffs << [y, x] if previous[y][x] != current[y][x]
end
end
return diffs
end
# グリッド上のブロックを描画する(変更箇所のみ)
#
# @param cell_sprites [Array<Array>] 各セルのスプライト配列
# @param grid [Array<Array>] 参照するグリッド
# @param changed_cells [Array<(Integer, Integer)>] 変更されたセルの座標配列(全描画時は全て含む)
def draw_grid(cell_sprites, grid, changed_cells)
changed_cells.each do |y, x|
current = grid[y][x]
color = (current == 0) ? FREE_CELL_COLOR : BLOCK_PATTERNS.fetch(current, ERROR_BLOCK_COLOR)
sprite = cell_sprites[y][x]
sprite.color color
sprite.scale 1.0, 1.0
end
end
# 描画後に前回グリッド情報を更新する
#
# @param prev_grid [Array<Array>] 前回グリッド(※参照元を変更する)
# @param grid [Array<Array>] 現在グリッド
# @param changed_cells [Array<(Integer, Integer)>] 変更されたセルの座標
def update_prev_grid!(prev_grid, grid, changed_cells)
if prev_grid.nil?
return
end
changed_cells.each do |y, x|
prev_grid[y][x] = grid[y][x]
end
end
# 行消去時のアニメーションを行う関数
# @param line_indices [Array<Integer>] 消去対象の行インデックス
# @param cell_sprites [Array<Array>] セルスプライト配列
# @param duration [Integer] アニメーション全体の時間(ms)
def animate_line_clear(line_indices, cell_sprites, duration = 100)
cell_size = CONFIG[:cell_size]
start_time = getLocalCurrentDate()
while true
time_diff = DateTimeArray.diff_ms(getLocalCurrentDate(), start_time)
frame = [time_diff, duration].min
# 経過フレームに応じた拡大率を決める
scale = 1 - (frame / duration)
line_indices.each do |y|
cell_sprites[y].each do |sprite|
sprite.scale scale, scale
end
end
if time_diff >= duration
return
end
wait_time(1)
end
end
#==============================================================================
# グリッド関連のロジック処理
#==============================================================================
# 一列がすべて埋まっている行を削除し、空行を上に追加する
#
# @param grid [Array<Array>] 現在のグリッド(2次元配列)
# @return [Array<Array>] 新しいグリッドと消去行
def clear_lines(grid)
width = CONFIG[:grid_width]
new_grid = []
cleared_line_indices = []
grid.each_with_index do |row, y|
if row.include?(0)
new_grid << row
else
cleared_line_indices << y
end
end
# 消去行数に応じて上に空行を追加
empty_row = Array.new(width, 0)
cleared_line_indices.length.times do
new_grid.unshift(empty_row.dup)
end
return new_grid, cleared_line_indices
end
# ピースが衝突しない最上位置(y座標)を探す
#
# @param piece [Piece] チェック対象のピース
# @param grid [Array<Array>] 参照するグリッド
# @return [Integer] 衝突しない位置のy座標
def find_valid_spawn_y(piece, grid)
y_offset = -1
while true
unless piece.colliding?(0, y_offset, piece.blocks, grid, false)
return piece.y + y_offset
end
y_offset -= 1
end
end
コード一覧
プレー内容を公開する