CoRサンプル集: テトリスのような落ちものパズルゲームのサンプル
テトリスのような落ちものパズルゲームのサンプル。
音楽・画像などの素材は一切使用していないので、コピペだけで移植出来ます。
操作方法
横移動:←→
ソフトドロップ:↓
ハードドロップ:↑
左回転:Z
右回転:X
ホールド:C
音楽・画像などの素材は一切使用していないので、コピペだけで移植出来ます。
操作方法
横移動:←→
ソフトドロップ:↓
ハードドロップ:↑
左回転:Z
右回転:X
ホールド:C
プレー:3
(人数:2)
クリア:2
評価: 10 (1回)
タグが設定されていません
require_code 'defines.rb' # ゲームの基本設定
require_code 'piece.rb'
require_code 'grid_util.rb'
require_code 'hold.rb'
require_code 'input_manager.rb'
require_code 'input_handler.rb'
require_code 'score.rb'
require_code 'datetime_array.rb'
require_code 'extension.rb'
scene 'main' do
# シーン内で使う変数の定義
ren = nil # 連鎖数
score = nil # スコア
prev_score = nil # 1つ前のスコアを記憶
grid = nil
prev_grid = nil
frame_count = nil
is_game_over = nil
need_new_piece = nil
is_render_grid = nil
should_process_piece = nil
next_pieces = nil # 次のピースのリスト
prev_next_pieces = nil
bag = nil # バッグシステム用リスト
hold_locked = nil
# インスタンス
input_manager = nil
current_piece = nil
render_piece = nil
hold_piece = nil
prev_hold_piece = nil
hold_out_piece = nil
# スプライト
cell_sprites = nil
piece_sprites = nil
next_piece_sprites = nil
hold_piece_sprites = nil
score_sprites = nil
message_sprites = nil
preload do
end
create do
# グリッドの初期化
grid, cell_sprites = make_grid('cell-sprite')
prev_grid = Array.new(CONFIG[:grid_height]) { Array.new(CONFIG[:grid_width], nil) } # 1つ前のグリッドを記憶
# prev_grid = nil # 毎回全描画するならnilを代入
is_render_grid = true
# ピースの初期化
max_blocks = PIECE_BLOCKS.values.map { |shape| shape.flatten.count(1) }.max
piece_sprites = make_piece_sprites('cell-sprite', max_blocks)
current_piece = render_piece = nil
need_new_piece = true
# ネクストピースの初期化
put_text 'next-title-sprite' do
position NEXT_PIECE_CONFIG[:x], NEXT_PIECE_CONFIG[:title_y]
text 'Next'
end
next_piece_sprites = Array.new(CONFIG[:next_piece_count]) do
make_piece_sprites('next-piece-sprite', max_blocks)
end
next_pieces = []
prev_next_pieces = []
bag = []
# ホールド機能の初期化
if CONFIG[:enable_hold]
put_text 'hold-title-sprite' do
position HOLD_CONFIG[:x], HOLD_CONFIG[:title_y]
text "Hold:#{CONFIG[:controls][:hold]}キー"
end
hold_piece_sprites = make_piece_sprites('hold-piece-sprite', max_blocks)
hold_locked = false
end
hold_piece = prev_hold_piece = hold_out_piece = nil
# スコア用の初期化
ren = 0
score = prev_score = 0
score_sprites = put_text 'score_text' do
position HOLD_CONFIG[:x], 160
text CONFIG[:score_format] % score
end
# その他の初期化
# メッセージ用スプライトを用意
message_sprites = put_text 'game_message' do
position (CONFIG[:window_width] / 2).floor, (CONFIG[:window_height] / 2).floor
text ''
bold true
end
input_manager = InputManager.new # 入力キー管理
is_game_over = false
frame_count = 0
should_process_piece = false
end
update do
start_time = getLocalCurrentDate()
if !CONFIG[:enable_hold]
# ホールド機能が無効ならhold_lockedをtrueにしてホールド処理をさせない
hold_locked = true
end
# ピース操作
unless current_piece.nil?
# ホールド処理を試みる
if input_manager.key_pressed?(keyboard, CONFIG[:controls][:hold], start_time)
hold_successful, hold_piece, hold_out_piece, hold_locked = try_hold(current_piece, hold_piece, hold_locked)
if hold_successful
current_piece = nil
need_new_piece = true
next # 落下や操作はスキップ
end
end
# 入力操作(移動・回転)
should_process_piece ||= handle_input(current_piece, input_manager, start_time, grid)
# 自動落下タイミング
should_process_piece ||= frame_count % CONFIG[:drop_interval] == 0
end
# ピースの落下、または着地時処理
if should_process_piece
should_process_piece = false
if current_piece.colliding?(0, 1, current_piece.blocks, grid, false)
if current_piece.place(grid)
current_piece = nil
wait_time(1) # 処理を一旦renderへ渡す
grid, cleared_line_indices = clear_lines(grid)
clear_lines_count = cleared_line_indices.length
if clear_lines_count == 0
ren = 0
else
ren += 1
is_render_grid = false
animate_line_clear(cleared_line_indices, cell_sprites)
# prev_gridの消した行をnilに書換え
unless prev_grid.nil?
cleared_line_indices.each do |y|
prev_grid[y] = Array.new(CONFIG[:grid_width])
end
end
is_render_grid = true
end
score = scoring(score, grid, clear_lines_count, ren)
hold_locked = false # ピースがロックされた後、hold_lockedをリセットする
need_new_piece = true
else
# ゲームオーバーへ
is_game_over = true
end
else
current_piece.move(0, 1, grid)
end
end
# ピース生成
if need_new_piece
need_new_piece = false
if hold_out_piece.nil?
# 次のピースのリストを用意(生成分+待機分)
while next_pieces.length <= CONFIG[:next_piece_count]
if bag.empty?
# バッグが空なら更新
bag = next_bag(PIECE_BLOCKS.keys)
end
piece_type = bag.shift # バッグ先頭から切り出し
next_pieces << Piece.new(piece_type, [piece_type]) # ピースを作成
# next_pieces << Piece.new(piece_type, BLOCK_PATTERNS.keys) # ピースを作成(ブロックランダム)
end
# 次のピースを取得
current_piece = next_pieces.shift
else
# ホールドしていたピースを出す
current_piece = hold_out_piece
hold_out_piece = nil
end
# ピースのポジションを設定
current_piece.initialize_position
if current_piece.colliding?(0, 0, current_piece.blocks, grid)
# ゲームオーバーへ
current_piece.y = find_valid_spawn_y(current_piece, grid)
is_game_over = true
end
end
# ゲームオーバー
if is_game_over
message_sprites.text "Game Over"
# ゲームオーバー後もピースを描画させる
render_piece = current_piece
current_piece = nil
wait_time(1000)
openActivityFeedWindow("スコア:#{score}")
game_clear
end
frame_count += 1
end
render do
# グリッド
if is_render_grid
diff = grid_diff(grid, prev_grid)
draw_grid(cell_sprites, grid, diff)
update_prev_grid!(prev_grid, grid, diff)
end
# ピース
if !is_game_over
render_piece = current_piece
end
draw_piece(render_piece, piece_sprites)
# ネクスト
if next_pieces != prev_next_pieces
draw_next_piece(next_pieces, next_piece_sprites)
prev_next_pieces = next_pieces.dup
end
# ホールド
if CONFIG[:enable_hold] && hold_piece != prev_hold_piece
draw_hold_piece(hold_piece, hold_piece_sprites)
prev_hold_piece = hold_piece
end
# スコア
if prev_score != score
score_sprites.text CONFIG[:score_format] % score
prev_score = score
end
end
end
# ------------------------------
# スプライトの定義
# ------------------------------
# セル用
text 'cell-sprite' do
origin :center
font_size CONFIG[:cell_size]
color FREE_CELL_COLOR
end
# ネクストピース用
text 'next-piece-sprite' do
origin :center
font_size NEXT_PIECE_CONFIG[:block_size]
color FREE_CELL_COLOR
end
text 'next-title-sprite' do
origin :center
font_size NEXT_PIECE_CONFIG[:title_size]
color '#FFFFFF'
end
# ホールド機能用
text 'hold-piece-sprite' do
origin :center
font_size HOLD_CONFIG[:block_size]
color FREE_CELL_COLOR
end
text 'hold-title-sprite' do
origin :center
font_size HOLD_CONFIG[:title_size]
color '#FFFFFF'
end
# スコア
text 'score_text' do
origin :center
font_size 32
color '#FFFFFF'
end
# ゲームメッセージ
text 'game_message' do
origin :center # :left_top
font_size 64
color '#FFFFFF'
end
start_scene 'main'
プレー内容を公開する