A bunch of polish
- lock delay - wall kick tests - an entirely new music track that changes per level - Changes to how the music class works (especially when not passing a specific channel) - New sound effects for getting a tetris, changing levels and game over - Change piece colours to match the commonly accepted ones I really should commit more often...
This commit is contained in:
parent
6e967fb2e5
commit
b05fb1e0db
54 changed files with 318 additions and 71 deletions
|
@ -115,7 +115,7 @@ class SoundInstance
|
||||||
end
|
end
|
||||||
|
|
||||||
def play_music(args, opts = { channel: 0 })
|
def play_music(args, opts = { channel: 0 })
|
||||||
@looping = true
|
# @looping = true
|
||||||
@key = "MUSIC_CHANNEL_#{opts[:channel]}"
|
@key = "MUSIC_CHANNEL_#{opts[:channel]}"
|
||||||
play(args, opts)
|
play(args, opts)
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,13 +21,13 @@ class CubeTubeGame < GameplayScene
|
||||||
|
|
||||||
@sprite_index = [
|
@sprite_index = [
|
||||||
Sprite.for(:black),
|
Sprite.for(:black),
|
||||||
Sprite.for(:red),
|
Sprite.for(:cyan),
|
||||||
Sprite.for(:green),
|
|
||||||
Sprite.for(:blue),
|
Sprite.for(:blue),
|
||||||
Sprite.for(:yellow),
|
|
||||||
Sprite.for(:indigo),
|
|
||||||
Sprite.for(:violet),
|
|
||||||
Sprite.for(:orange),
|
Sprite.for(:orange),
|
||||||
|
Sprite.for(:yellow),
|
||||||
|
Sprite.for(:green),
|
||||||
|
Sprite.for(:violet),
|
||||||
|
Sprite.for(:red),
|
||||||
Sprite.for(:gray)
|
Sprite.for(:gray)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -43,11 +43,63 @@ class CubeTubeGame < GameplayScene
|
||||||
@current_piece_x = 0
|
@current_piece_x = 0
|
||||||
@current_piece_y = 0
|
@current_piece_y = 0
|
||||||
@current_piece = nil
|
@current_piece = nil
|
||||||
|
@current_piece_rotation = 0
|
||||||
@next_piece = nil
|
@next_piece = nil
|
||||||
@lines_to_clear = []
|
@lines_to_clear = []
|
||||||
@line_clear_timer = 0
|
@line_clear_timer = 0
|
||||||
|
@lock_delay = 30
|
||||||
|
@lock_timer = 0
|
||||||
|
|
||||||
@current_music = :music1
|
@current_song = 0
|
||||||
|
@current_song_progress = 0
|
||||||
|
|
||||||
|
@cursor_down = nil
|
||||||
|
@cursor_down_tick = nil
|
||||||
|
@cursor_piece_x_origin = nil
|
||||||
|
@cursor_piece_y_origin = nil
|
||||||
|
|
||||||
|
# wall kick tests taken from https://tetris.fandom.com/wiki/SRS#Wall_Kicks
|
||||||
|
@wall_kick_tests = {
|
||||||
|
[0, 1] => [[-1, 0], [-1, 1], [0, -2], [-1, -2]],
|
||||||
|
[1, 0] => [[1, 0], [1, -1], [0, 2], [1, 2]],
|
||||||
|
[1, 2] => [[1, 0], [1, -1], [0, 2], [1, 2]],
|
||||||
|
[2, 1] => [[-1, 0], [-1, 1], [0, -2], [-1, -2]],
|
||||||
|
[2, 3] => [[1, 0], [1, 1], [0, -2], [1, -2]],
|
||||||
|
[3, 2] => [[-1, 0], [-1, -1], [0, 2], [-1, 2]],
|
||||||
|
[3, 0] => [[-1, 0], [-1, -1], [0, 2], [-1, 2]],
|
||||||
|
[0, 3] => [[1, 0], [1, 1], [0, -2], [1, -2]],
|
||||||
|
}
|
||||||
|
|
||||||
|
@wall_kick_tests_i = {
|
||||||
|
[0, 1] => [[-2, 0], [1, 0], [-2, -1], [1, 2]],
|
||||||
|
[1, 0] => [[2, 0], [-1, 0], [2, 1], [-1, -2]],
|
||||||
|
[1, 2] => [[-1, 0], [2, 0], [-1, 2], [2, -1]],
|
||||||
|
[2, 1] => [[1, 0], [-2, 0], [1, -2], [-2, 1]],
|
||||||
|
[2, 3] => [[2, 0], [-1, 0], [2, 1], [-1, -2]],
|
||||||
|
[3, 2] => [[-2, 0], [1, 0], [-2, -1], [1, 2]],
|
||||||
|
[3, 0] => [[1, 0], [-2, 0], [1, -2], [-2, 1]],
|
||||||
|
[0, 3] => [[-1, 0], [2, 0], [-1, 2], [2, -1]],
|
||||||
|
}
|
||||||
|
|
||||||
|
@song = [
|
||||||
|
[
|
||||||
|
[:underscore_b, :underscore2_a, :underscore2_b, :underscore_bridge1, :underscore_bridge2_a, :underscore_b, :underscore_a],
|
||||||
|
[:silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar],
|
||||||
|
],[
|
||||||
|
[:lead_beats, :lead_beats, :lead_beats, :lead_beats, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :lead_beats, :lead_beats],
|
||||||
|
[:underscore_a, :underscore_b, :underscore2_a, :underscore2_b, :underscore_bridge1, nil, :underscore_bridge2_a, nil, nil, :underscore_b]
|
||||||
|
],[
|
||||||
|
[:fill1, :fill1, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar],
|
||||||
|
[nil, nil, :lead1, nil, nil, nil, :lead2, nil, nil, nil]
|
||||||
|
],[
|
||||||
|
[:silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar],
|
||||||
|
[:post_lead, nil, :post_lead2, nil, :loop1_a, :loop1_b, :loop1_a, :loop1_b, :loop2_a, :loop2_b, :loop2_a, :loop2_b],
|
||||||
|
|
||||||
|
],[
|
||||||
|
[:fill1, :fill1, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar, :silent_bar],
|
||||||
|
[nil, nil, :lead1, nil, nil, nil, :lead2, nil, nil, nil, :post_lead, nil, :post_lead2, nil, :loop1_a, :loop1_b, :loop1_a, :loop1_b, :loop2_a, :loop2_b, :loop2_a, :loop2_b]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
reset(args)
|
reset(args)
|
||||||
end
|
end
|
||||||
|
@ -107,7 +159,7 @@ class CubeTubeGame < GameplayScene
|
||||||
(y - @current_piece_y).between?(0, @current_piece[x - @current_piece_x].length - 1) &&
|
(y - @current_piece_y).between?(0, @current_piece[x - @current_piece_x].length - 1) &&
|
||||||
!@current_piece[x - @current_piece_x][y - @current_piece_y].zero?
|
!@current_piece[x - @current_piece_x][y - @current_piece_y].zero?
|
||||||
# render the current piece
|
# render the current piece
|
||||||
render_block(x, y, @current_piece[x - @current_piece_x][y - @current_piece_y])
|
render_block(x, y, @current_piece[x - @current_piece_x][y - @current_piece_y]) if @lines_to_clear.empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -191,12 +243,14 @@ class CubeTubeGame < GameplayScene
|
||||||
render_gameover if @showgameover
|
render_gameover if @showgameover
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_piece_colliding
|
def piece_colliding(piece, piece_x, piece_y)
|
||||||
(0..@current_piece.length - 1).each do |x|
|
return true if (piece_x + piece.length) > @grid_w || piece_x < 0
|
||||||
(0..@current_piece[x].length - 1).each do |y|
|
|
||||||
next if @current_piece[x][y].zero?
|
(0..piece.length - 1).each do |x|
|
||||||
if (@current_piece_y + y >= @grid_h) ||
|
(0..piece[x].length - 1).each do |y|
|
||||||
((@current_piece_y + y) >= 0 && @grid[@current_piece_x + x][@current_piece_y + y] != 0)
|
next if piece[x][y].zero?
|
||||||
|
if (piece_y + y >= @grid_h) ||
|
||||||
|
((piece_y + y) >= 0 && @grid[piece_x + x][piece_y + y] != 0)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -204,6 +258,20 @@ class CubeTubeGame < GameplayScene
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_piece_colliding
|
||||||
|
piece_colliding(@current_piece, @current_piece_x, @current_piece_y)
|
||||||
|
# (0..@current_piece.length - 1).each do |x|
|
||||||
|
# (0..@current_piece[x].length - 1).each do |y|
|
||||||
|
# next if @current_piece[x][y].zero?
|
||||||
|
# if (@current_piece_y + y >= @grid_h) ||
|
||||||
|
# ((@current_piece_y + y) >= 0 && @grid[@current_piece_x + x][@current_piece_y + y] != 0)
|
||||||
|
# return true
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# false
|
||||||
|
end
|
||||||
|
|
||||||
def get_speed
|
def get_speed
|
||||||
case @level
|
case @level
|
||||||
when 0 then 53
|
when 0 then 53
|
||||||
|
@ -228,8 +296,19 @@ class CubeTubeGame < GameplayScene
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_music
|
def change_music
|
||||||
@current_music = @current_music == :music1 ? :music2 : :music1
|
@current_song = (@current_song + 1) % @song.length
|
||||||
Music.queue_up(@current_music)
|
@current_song_progress = 0
|
||||||
|
|
||||||
|
case @level
|
||||||
|
when 5
|
||||||
|
Music.queue_up(:bridge)
|
||||||
|
when 10
|
||||||
|
Music.queue_up(:bridge)
|
||||||
|
when 15
|
||||||
|
Music.queue_up(:bridge)
|
||||||
|
when 20
|
||||||
|
Music.queue_up(:bridge)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def line_full?(row)
|
def line_full?(row)
|
||||||
|
@ -240,6 +319,13 @@ class CubeTubeGame < GameplayScene
|
||||||
end
|
end
|
||||||
|
|
||||||
def plant_current_piece
|
def plant_current_piece
|
||||||
|
@lock_timer -= 1
|
||||||
|
return unless @lock_timer <= 0
|
||||||
|
|
||||||
|
@cursor_down = nil
|
||||||
|
@cursor_piece_x_origin = nil
|
||||||
|
@cursor_piece_y_origin = nil
|
||||||
|
|
||||||
(0..@current_piece.length - 1).each do |x|
|
(0..@current_piece.length - 1).each do |x|
|
||||||
(0..@current_piece[x].length - 1).each do |y|
|
(0..@current_piece[x].length - 1).each do |y|
|
||||||
next if @current_piece[x][y].zero?
|
next if @current_piece[x][y].zero?
|
||||||
|
@ -260,7 +346,8 @@ class CubeTubeGame < GameplayScene
|
||||||
@line_clear_timer = 70
|
@line_clear_timer = 70
|
||||||
if (@lines % 10).floor.zero?
|
if (@lines % 10).floor.zero?
|
||||||
@level += 1
|
@level += 1
|
||||||
change_music
|
change_music()
|
||||||
|
Sound.play(@args, :horn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -274,6 +361,7 @@ class CubeTubeGame < GameplayScene
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Sound.play(@args, :clear)
|
Sound.play(@args, :clear)
|
||||||
|
Sound.play(@args, :fourlines) if @lines_to_clear.length == 4
|
||||||
@current_speed = get_speed
|
@current_speed = get_speed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -285,32 +373,70 @@ class CubeTubeGame < GameplayScene
|
||||||
|
|
||||||
@current_piece_x = 4
|
@current_piece_x = 4
|
||||||
@current_piece_y = -1
|
@current_piece_y = -1
|
||||||
|
@current_piece_rotation = 0
|
||||||
|
@lock_timer = @lock_delay
|
||||||
|
|
||||||
r = (rand 7) + 1
|
r = (rand 7) + 1
|
||||||
@next_piece =
|
@next_piece =
|
||||||
case r
|
case r
|
||||||
when 1 then [[r, 0], [r, r], [0, r]]
|
when 1 then [[r], [r], [r], [r]] # I
|
||||||
when 2 then [[0, r], [r, r], [r, 0]]
|
when 2 then [[0, r], [0, r], [r, r]] # J
|
||||||
when 3 then [[r, r, r], [r, 0, 0]]
|
when 3 then [[r, r], [0, r], [0, r]] # L
|
||||||
when 4 then [[r, r], [r, r] ]
|
when 4 then [[r, r], [r, r]] # O
|
||||||
when 5 then [[r], [r], [r], [r]]
|
when 5 then [[r, 0], [r, r], [0, r]] # S
|
||||||
when 6 then [[r, 0], [r, r], [r, 0]]
|
when 6 then [[0, r], [r, r], [0, r]] # T
|
||||||
when 7 then [[r, 0, 0], [r, r, r]]
|
when 7 then [[0, r], [r, r], [r, 0]] # Z
|
||||||
end
|
end
|
||||||
select_next_piece if @current_piece.nil?
|
select_next_piece if @current_piece.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def rotate_current_piece_left
|
def wall_kick(new_piece, old_rotation, new_rotation)
|
||||||
|
is_i = new_piece.length == 1 || (new_piece.length == 4 && new_piece[0].length == 1)
|
||||||
|
|
||||||
|
kick_test_set = is_i ? @wall_kick_tests_i : @wall_kick_tests
|
||||||
|
kick_test = kick_test_set[[old_rotation, new_rotation]]
|
||||||
|
kick_test.each do |t|
|
||||||
|
collide = piece_colliding(new_piece, @current_piece_x + t[0], @current_piece_y + t[1])
|
||||||
|
next if collide
|
||||||
|
|
||||||
|
@current_piece_x += t[0]
|
||||||
|
@current_piece_y += t[1]
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def rotate_current_piece(new_piece, new_rotation)
|
||||||
|
should_rotate = false
|
||||||
|
if piece_colliding(new_piece, @current_piece_x, @current_piece_y)
|
||||||
|
should_rotate = wall_kick(new_piece, @current_piece_rotation, new_rotation)
|
||||||
|
else
|
||||||
|
should_rotate = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if should_rotate
|
||||||
|
@lock_timer = @lock_delay
|
||||||
|
@current_piece_rotation = new_rotation
|
||||||
|
@current_piece = new_piece
|
||||||
Sound.play(@args, :rotate)
|
Sound.play(@args, :rotate)
|
||||||
@current_piece = @current_piece.transpose.map(&:reverse)
|
else
|
||||||
@current_piece_x = @grid_w - @current_piece.length if (@current_piece_x + @current_piece.length) >= @grid_w
|
# wall kick failed. Don't do the rotation
|
||||||
|
Sound.play(@args, :move_deny)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rotate_current_piece_left
|
||||||
|
new_piece = @current_piece.transpose.map(&:reverse)
|
||||||
|
new_rotation = (@current_piece_rotation - 1) % 4
|
||||||
|
rotate_current_piece(new_piece, new_rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def rotate_current_piece_right
|
def rotate_current_piece_right
|
||||||
Sound.play(@args, :rotate)
|
|
||||||
@current_piece = @current_piece.transpose.map(&:reverse)
|
@current_piece = @current_piece.transpose.map(&:reverse)
|
||||||
@current_piece = @current_piece.transpose.map(&:reverse)
|
@current_piece = @current_piece.transpose.map(&:reverse)
|
||||||
@current_piece = @current_piece.transpose.map(&:reverse)
|
@current_piece = @current_piece.transpose.map(&:reverse)
|
||||||
|
new_rotation = (@current_piece_rotation + 1) % 4
|
||||||
|
rotate_current_piece(new_piece, new_rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_grid
|
def fill_grid
|
||||||
|
@ -339,6 +465,7 @@ class CubeTubeGame < GameplayScene
|
||||||
@current_piece_x -= 1
|
@current_piece_x -= 1
|
||||||
else
|
else
|
||||||
Sound.play(@args, :move)
|
Sound.play(@args, :move)
|
||||||
|
@lock_timer = @lock_delay
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Sound.play(@args, :move_deny)
|
Sound.play(@args, :move_deny)
|
||||||
|
@ -353,6 +480,7 @@ class CubeTubeGame < GameplayScene
|
||||||
@current_piece_x += 1
|
@current_piece_x += 1
|
||||||
else
|
else
|
||||||
Sound.play(@args, :move)
|
Sound.play(@args, :move)
|
||||||
|
@lock_timer = @lock_delay
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Sound.play(@args, :move_deny)
|
Sound.play(@args, :move_deny)
|
||||||
|
@ -376,6 +504,7 @@ class CubeTubeGame < GameplayScene
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Sound.play(@args, :drop)
|
Sound.play(@args, :drop)
|
||||||
|
@lock_timer = @lock_delay
|
||||||
@lines_to_clear = []
|
@lines_to_clear = []
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
@ -384,15 +513,70 @@ class CubeTubeGame < GameplayScene
|
||||||
restart_game if Input.pressed?(@args, :primary) && @gameover && @showgameover
|
restart_game if Input.pressed?(@args, :primary) && @gameover && @showgameover
|
||||||
return if @gameover
|
return if @gameover
|
||||||
|
|
||||||
|
if @lines_to_clear.empty?
|
||||||
move_current_piece_down if Input.pressed?(@args, :down)
|
move_current_piece_down if Input.pressed?(@args, :down)
|
||||||
move_current_piece_up if Input.pressed?(@args, :up)
|
move_current_piece_up if Input.pressed?(@args, :up)
|
||||||
@next_move -= @current_speed / 3 if Input.pressed_or_held?(@args, :left)
|
if Input.pressed_or_held?(@args, :left)
|
||||||
|
@next_move -= @current_speed / 3
|
||||||
|
@lock_timer -= @current_speed / 3 if @lock_timer > 0
|
||||||
|
end
|
||||||
rotate_current_piece_left if Input.pressed?(@args, :rotate_left)
|
rotate_current_piece_left if Input.pressed?(@args, :rotate_left)
|
||||||
rotate_current_piece_right if Input.pressed?(@args, :rotate_right)
|
rotate_current_piece_right if Input.pressed?(@args, :rotate_right)
|
||||||
|
|
||||||
|
if @args.inputs.mouse.button_left || @args.inputs.finger_one
|
||||||
|
if @cursor_down.nil?
|
||||||
|
@cursor_down = @args.inputs.mouse.button_left ? @args.inputs.mouse.point : @args.inputs.finger_one
|
||||||
|
@cursor_down_tick = @args.state.tick_count
|
||||||
|
@cursor_piece_x_origin = @current_piece_x
|
||||||
|
@cursor_piece_y_origin = @current_piece_y
|
||||||
|
end
|
||||||
|
|
||||||
|
cursor = @args.inputs.mouse.button_left ? @args.inputs.mouse.point : @args.inputs.finger_one
|
||||||
|
|
||||||
|
delta_x = cursor.x - @cursor_down.x
|
||||||
|
if delta_x.negative? && delta_x.abs > (@blocksize * 2) && @cursor_piece_x_origin == @current_piece_x
|
||||||
|
@next_move -= @current_speed / 3
|
||||||
|
@lock_timer -= @current_speed / 3 if @lock_timer.positive?
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
delta_y = cursor.y - @cursor_down.y
|
||||||
|
delta_block = (delta_y / @blocksize).floor
|
||||||
|
max_delta = 0
|
||||||
|
if delta_block.negative?
|
||||||
|
@cursor_piece_x_origin.downto((@cursor_piece_x_origin + delta_block)) do |i|
|
||||||
|
break if piece_colliding(@current_piece, i, @current_piece_y)
|
||||||
|
|
||||||
|
max_delta = i
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@cursor_piece_x_origin.upto((@cursor_piece_x_origin + delta_block)) do |i|
|
||||||
|
break if piece_colliding(@current_piece, i, @current_piece_y)
|
||||||
|
|
||||||
|
max_delta = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@current_piece_x = max_delta
|
||||||
|
else
|
||||||
|
if !@cursor_down.nil? && (@cursor_down_tick + 30) >= @args.state.tick_count && @cursor_piece_x_origin == @current_piece_x
|
||||||
|
rotate_current_piece_left
|
||||||
|
end
|
||||||
|
@cursor_down = nil
|
||||||
|
@cursor_down_tick = nil
|
||||||
|
@cursor_piece_x_origin = nil
|
||||||
|
@cursor_piece_y_origin = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if @args.inputs.mouse.click
|
||||||
|
rotate_current_piece_left if @cursor_piece_x_origin.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if @args.inputs.keyboard.key_down.equal_sign
|
if @args.inputs.keyboard.key_down.equal_sign
|
||||||
@level += 1
|
@level += 1
|
||||||
@lines += 10
|
@lines += 10
|
||||||
|
change_music()
|
||||||
|
Sound.play(@args, :horn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -411,13 +595,29 @@ class CubeTubeGame < GameplayScene
|
||||||
@next_move -= 1
|
@next_move -= 1
|
||||||
return unless @next_move <= 0
|
return unless @next_move <= 0
|
||||||
|
|
||||||
@next_move = @current_speed
|
|
||||||
@current_piece_y += 1
|
@current_piece_y += 1
|
||||||
|
|
||||||
return unless current_piece_colliding
|
if current_piece_colliding
|
||||||
|
|
||||||
@current_piece_y -= 1
|
@current_piece_y -= 1
|
||||||
plant_current_piece
|
plant_current_piece
|
||||||
|
else
|
||||||
|
@lock_timer = @lock_delay
|
||||||
|
@next_move = @current_speed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def iterate_music
|
||||||
|
Music.resume(@args) if !Music.stopped?(@args) && Music.paused?(@args)
|
||||||
|
return unless Music.stopped?(@args, 0) && (!Music.queue[0] || Music.queue[0].empty?)
|
||||||
|
|
||||||
|
song_length = @song[@current_song][0].length
|
||||||
|
@current_song_progress = @current_song_progress % song_length # just in case we changed to a shorter song
|
||||||
|
@song[@current_song].each_with_index do |track, i|
|
||||||
|
if @current_song_progress < track.length && !track[@current_song_progress].nil?
|
||||||
|
Music.play(@args, track[@current_song_progress], { channel: i })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@current_song_progress = (@current_song_progress + 1) % song_length
|
||||||
end
|
end
|
||||||
|
|
||||||
def iterate
|
def iterate
|
||||||
|
@ -428,8 +628,7 @@ class CubeTubeGame < GameplayScene
|
||||||
# skip the rest if it's game over
|
# skip the rest if it's game over
|
||||||
return if @gameover
|
return if @gameover
|
||||||
|
|
||||||
# resume music if it's paused
|
iterate_music
|
||||||
Music.resume(@args) if !Music.stopped(@args) && Music.paused(@args)
|
|
||||||
|
|
||||||
iterate_train_bounce
|
iterate_train_bounce
|
||||||
|
|
||||||
|
@ -461,6 +660,7 @@ class CubeTubeGame < GameplayScene
|
||||||
@current_piece_x = 4
|
@current_piece_x = 4
|
||||||
@current_piece_y = -1
|
@current_piece_y = -1
|
||||||
@current_piece = nil
|
@current_piece = nil
|
||||||
|
@current_piece_rotation = 0
|
||||||
@next_piece = nil
|
@next_piece = nil
|
||||||
select_next_piece
|
select_next_piece
|
||||||
@lines_to_clear = []
|
@lines_to_clear = []
|
||||||
|
@ -475,8 +675,10 @@ class CubeTubeGame < GameplayScene
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@current_music = :music1
|
@current_song = 0
|
||||||
Music.play(args, @current_music)
|
@current_song_progress = 0
|
||||||
Music.set_volume(args, args.state.setting.music ? 0.8 : 0.0)
|
Music.stop(args)
|
||||||
|
Music.set_volume(args, args.state.setting.music ? 0.6 : 0.0)
|
||||||
|
Music.play(args, :underscore_a)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,7 +30,7 @@ class MainMenu < MenuScene
|
||||||
# actual menu logic is handled by the MenuScene super class
|
# actual menu logic is handled by the MenuScene super class
|
||||||
super
|
super
|
||||||
|
|
||||||
Music.play(args, :ambience) if args.state.setting.music && Music.stopped(args)
|
Music.play(args, :ambience) if args.state.setting.music && Music.stopped?(args)
|
||||||
@next_announcement ||= 0
|
@next_announcement ||= 0
|
||||||
if @next_announcement <= args.state.tick_count
|
if @next_announcement <= args.state.tick_count
|
||||||
next_sec = random(20..50)
|
next_sec = random(20..50)
|
||||||
|
|
|
@ -32,6 +32,6 @@ class PauseMenu < MenuScene
|
||||||
# called every tick of the game loop
|
# called every tick of the game loop
|
||||||
def tick(args)
|
def tick(args)
|
||||||
super
|
super
|
||||||
Music.pause(args) unless Music.stopped(args) || Music.paused(args)
|
Music.pause(args) unless Music.stopped?(args) || Music.paused?(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,9 @@ end
|
||||||
# Code that runs every game tick (mainly just calling other ticks)
|
# Code that runs every game tick (mainly just calling other ticks)
|
||||||
def tick(args)
|
def tick(args)
|
||||||
init(args) if args.state.tick_count.zero?
|
init(args) if args.state.tick_count.zero?
|
||||||
|
|
||||||
|
Music.tick(args)
|
||||||
|
|
||||||
# this looks good on non 16:9 resolutions; game background is different
|
# this looks good on non 16:9 resolutions; game background is different
|
||||||
args.outputs.background_color = TRUE_BLACK.values
|
args.outputs.background_color = TRUE_BLACK.values
|
||||||
|
|
||||||
|
@ -22,8 +25,6 @@ def tick(args)
|
||||||
scene.tick(args) if scene.tick_in_background || scene == args.state.scene_stack.last
|
scene.tick(args) if scene.tick_in_background || scene == args.state.scene_stack.last
|
||||||
end
|
end
|
||||||
|
|
||||||
Music.tick(args)
|
|
||||||
|
|
||||||
debug_tick(args)
|
debug_tick(args)
|
||||||
rescue FinishTick
|
rescue FinishTick
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,40 +21,64 @@ module Music
|
||||||
MUSIC.fetch(key).play_music(args, opts)
|
MUSIC.fetch(key).play_music(args, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def stopped(args, channel = 0)
|
def stopped?(args, channel = nil)
|
||||||
!args.audio.key?("MUSIC_CHANNEL_#{channel}")
|
channel_names(args, channel).none? do |c|
|
||||||
|
args.audio.key?(c)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def paused(args, channel = 0)
|
def paused?(args, channel = nil)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].paused unless stopped(args, channel)
|
channel_names(args, channel).all? do |c|
|
||||||
|
args.audio.key?(c) && args.audio[c].paused
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop(args, channel = 0)
|
def stop(args, channel = nil)
|
||||||
args.audio.delete("MUSIC_CHANNEL_#{channel}")
|
channel_names(args, channel).each do |c|
|
||||||
|
args.audio.delete(c)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def pause(args, channel = 0)
|
def pause(args, channel = nil)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].paused = true unless stopped(args, channel)
|
channel_names(args, channel).each do |c|
|
||||||
|
args.audio[c].paused = true unless stopped?(args, c)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def resume(args, channel = 0)
|
def resume(args, channel = nil)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].paused = false unless stopped(args, channel)
|
channel_names(args, channel).each do |c|
|
||||||
|
args.audio[c].paused = false unless stopped?(args, c)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_volume(args, volume, channel = 0)
|
def set_volume(args, volume, channel = nil)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].gain = volume unless stopped(args, channel)
|
channel_names(args, channel).each do |c|
|
||||||
|
args.audio[c].gain = volume
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def channel_names(args, channel = nil)
|
||||||
|
if channel.nil?
|
||||||
|
args.audio.keys.select do |key|
|
||||||
|
key.start_with? 'MUSIC_CHANNEL_'
|
||||||
|
end
|
||||||
|
elsif channel.is_a?(String)
|
||||||
|
[channel]
|
||||||
|
elsif channel.is_a?(Numeric)
|
||||||
|
["MUSIC_CHANNEL_#{channel}"]
|
||||||
|
else
|
||||||
|
channel
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def tick(args)
|
def tick(args)
|
||||||
queue.each do |channel, value|
|
queue.each do |channel, value|
|
||||||
unless value.empty?
|
next if value.empty?
|
||||||
|
|
||||||
if args.audio["MUSIC_CHANNEL_#{channel}"]
|
if args.audio["MUSIC_CHANNEL_#{channel}"]
|
||||||
if args.audio["MUSIC_CHANNEL_#{channel}"].looping
|
args.audio["MUSIC_CHANNEL_#{channel}"].looping = false if args.audio["MUSIC_CHANNEL_#{channel}"].looping
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].looping = false
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
value.shift.play_music(args, { channel: channel, gain: args.state.setting.music ? 0.8 : 0.0 })
|
value.shift.play_music(args, { channel: channel, gain: args.state.setting.music ? 0.8 : 0.0, paused: false })
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,14 +16,14 @@ icon=metadata/icon.png
|
||||||
# compile_ruby=false
|
# compile_ruby=false
|
||||||
|
|
||||||
# Uncomment the entry below to specify the package name for your APK
|
# Uncomment the entry below to specify the package name for your APK
|
||||||
# packageid=org.dev.gamename
|
packageid=au.death.cubetube
|
||||||
|
|
||||||
# Setting this property to true will enable High DPI rendering (try in combination with scale_quality to see what looks best)
|
# Setting this property to true will enable High DPI rendering (try in combination with scale_quality to see what looks best)
|
||||||
# highdpi=false
|
# highdpi=false
|
||||||
|
|
||||||
# === Portrait Mode ===
|
# === Portrait Mode ===
|
||||||
# The orientation can be set to either landscape (1280x720) or portrait (720x1280)
|
# The orientation can be set to either landscape (1280x720) or portrait (720x1280)
|
||||||
# orientation=landscape
|
orientation=landscape
|
||||||
|
|
||||||
# === HD Mode ===
|
# === HD Mode ===
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,24 @@
|
||||||
|
|
||||||
module Music
|
module Music
|
||||||
MUSIC = {
|
MUSIC = {
|
||||||
music1: SoundInstance.new({ path: 'music/music1.ogg', looping: true }),
|
ambience: SoundInstance.new({ path: 'music/ambience1.ogg', looping: true }),
|
||||||
music2: SoundInstance.new({ path: 'music/music2.ogg', looping: true }),
|
underscore_a: SoundInstance.new({ path: 'music/pyramids/underscore1_a.ogg', looping: false }),
|
||||||
ambience: SoundInstance.new({ path: 'music/ambience1.ogg', looping: true })
|
underscore_b: SoundInstance.new({ path: 'music/pyramids/underscore1_b.ogg', looping: false }),
|
||||||
|
underscore2_a: SoundInstance.new({ path: 'music/pyramids/underscore2_a.ogg', looping: false }),
|
||||||
|
underscore2_b: SoundInstance.new({ path: 'music/pyramids/underscore2_b.ogg', looping: false }),
|
||||||
|
underscore_bridge1: SoundInstance.new({ path: 'music/pyramids/underscore_bridge1.ogg', looping: false }),
|
||||||
|
underscore_bridge2_a: SoundInstance.new({ path: 'music/pyramids/underscore_bridge2+a.ogg', looping: false }),
|
||||||
|
lead_beats: SoundInstance.new({ path: 'music/pyramids/lead_beats.ogg', looping: false }),
|
||||||
|
fill1: SoundInstance.new({ path: 'music/pyramids/fill1.ogg', looping: false }),
|
||||||
|
lead1: SoundInstance.new({ path: 'music/pyramids/lead1.ogg', looping: false }),
|
||||||
|
lead2: SoundInstance.new({ path: 'music/pyramids/lead2.ogg', looping: false }),
|
||||||
|
loop1_a: SoundInstance.new({ path: 'music/pyramids/loop1_a.ogg', looping: false }),
|
||||||
|
loop1_b: SoundInstance.new({ path: 'music/pyramids/loop1_b.ogg', looping: false }),
|
||||||
|
loop2_a: SoundInstance.new({ path: 'music/pyramids/loop1_a.ogg', looping: false }),
|
||||||
|
loop2_b: SoundInstance.new({ path: 'music/pyramids/loop1_b.ogg', looping: false }),
|
||||||
|
post_lead: SoundInstance.new({ path: 'music/pyramids/post_lead.ogg', looping: false }),
|
||||||
|
post_lead2: SoundInstance.new({ path: 'music/pyramids/post_lead2.ogg', looping: false }),
|
||||||
|
bridge: SoundInstance.new({ path: 'music/pyramids/underscore_bridge2+a.ogg', looping: false }),
|
||||||
|
silent_bar: SoundInstance.new({ path: 'music/pyramids/silent_bar.ogg', looping: false }),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
BIN
music/music1.ogg
BIN
music/music1.ogg
Binary file not shown.
BIN
music/music2.ogg
BIN
music/music2.ogg
Binary file not shown.
BIN
music/pyramids/fill1.ogg
Normal file
BIN
music/pyramids/fill1.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/lead1.ogg
Normal file
BIN
music/pyramids/lead1.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/lead2.ogg
Normal file
BIN
music/pyramids/lead2.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/lead_beats.ogg
Normal file
BIN
music/pyramids/lead_beats.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/loop1_a.ogg
Normal file
BIN
music/pyramids/loop1_a.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/loop1_b.ogg
Normal file
BIN
music/pyramids/loop1_b.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/loop2_a.ogg
Normal file
BIN
music/pyramids/loop2_a.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/loop2_b.ogg
Normal file
BIN
music/pyramids/loop2_b.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/post_lead.ogg
Normal file
BIN
music/pyramids/post_lead.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/post_lead2.ogg
Normal file
BIN
music/pyramids/post_lead2.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/silent_bar.ogg
Normal file
BIN
music/pyramids/silent_bar.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/underscore1_a.ogg
Normal file
BIN
music/pyramids/underscore1_a.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/underscore1_b.ogg
Normal file
BIN
music/pyramids/underscore1_b.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/underscore2_a.ogg
Normal file
BIN
music/pyramids/underscore2_a.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/underscore2_b.ogg
Normal file
BIN
music/pyramids/underscore2_b.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/underscore_bridge1.ogg
Normal file
BIN
music/pyramids/underscore_bridge1.ogg
Normal file
Binary file not shown.
BIN
music/pyramids/underscore_bridge2+a.ogg
Normal file
BIN
music/pyramids/underscore_bridge2+a.ogg
Normal file
Binary file not shown.
|
@ -5,13 +5,16 @@ module Sound
|
||||||
menu: SoundInstance.new({ path: 'sounds/menu.wav' }),
|
menu: SoundInstance.new({ path: 'sounds/menu.wav' }),
|
||||||
select: SoundInstance.new({ path: 'sounds/select.wav' }),
|
select: SoundInstance.new({ path: 'sounds/select.wav' }),
|
||||||
clear: SoundInstance.new({ path: 'sounds/clear.wav' }),
|
clear: SoundInstance.new({ path: 'sounds/clear.wav' }),
|
||||||
|
fourlines: SoundInstance.new({ path: 'sounds/fourlines.wav' }),
|
||||||
drop: SoundInstance.new({ path: 'sounds/drop.wav' }),
|
drop: SoundInstance.new({ path: 'sounds/drop.wav' }),
|
||||||
move: SoundInstance.new({ path: 'sounds/move.wav' }),
|
move: SoundInstance.new({ path: 'sounds/move.wav' }),
|
||||||
move_deny: SoundInstance.new({ path: 'sounds/move_deny.wav' }),
|
move_deny: SoundInstance.new({ path: 'sounds/move_deny.wav' }),
|
||||||
rotate: SoundInstance.new({ path: 'sounds/rotate.wav' }),
|
rotate: SoundInstance.new({ path: 'sounds/rotate.wav' }),
|
||||||
|
gameover: SoundInstance.new({ path: 'sounds/gameover.wav' }),
|
||||||
train_stop: SoundInstance.new({ path: 'sounds/train_stop.wav' }),
|
train_stop: SoundInstance.new({ path: 'sounds/train_stop.wav' }),
|
||||||
train_stop2: SoundInstance.new({ path: 'sounds/train_stop2.wav' }),
|
train_stop2: SoundInstance.new({ path: 'sounds/train_stop2.wav' }),
|
||||||
train_leave: SoundInstance.new({ path: 'sounds/train_leave.wav' }),
|
train_leave: SoundInstance.new({ path: 'sounds/train_leave.wav' }),
|
||||||
|
horn: SoundInstance.new({ path: 'sounds/horn.wav' }),
|
||||||
chime: SoundInstance.new({ path: 'sounds/please_stand_clear.wav' }),
|
chime: SoundInstance.new({ path: 'sounds/please_stand_clear.wav' }),
|
||||||
ambient1: SoundInstance.new({ path: 'sounds/announcement.ogg', loop: false }),
|
ambient1: SoundInstance.new({ path: 'sounds/announcement.ogg', loop: false }),
|
||||||
ambient2: SoundInstance.new({ path: 'sounds/announcement2.ogg', loop: false }),
|
ambient2: SoundInstance.new({ path: 'sounds/announcement2.ogg', loop: false }),
|
||||||
|
|
BIN
sounds/fourlines.wav
Normal file
BIN
sounds/fourlines.wav
Normal file
Binary file not shown.
BIN
sounds/gameover.wav
Normal file
BIN
sounds/gameover.wav
Normal file
Binary file not shown.
BIN
sounds/horn.wav
Normal file
BIN
sounds/horn.wav
Normal file
Binary file not shown.
|
@ -15,6 +15,7 @@ module Sprite
|
||||||
red: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/red.png' }),
|
red: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/red.png' }),
|
||||||
green: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/green.png' }),
|
green: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/green.png' }),
|
||||||
blue: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/blue.png' }),
|
blue: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/blue.png' }),
|
||||||
|
cyan: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/cyan.png' }),
|
||||||
yellow: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/yellow.png' }),
|
yellow: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/yellow.png' }),
|
||||||
indigo: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/indigo.png' }),
|
indigo: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/indigo.png' }),
|
||||||
violet: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/violet.png' }),
|
violet: SpriteInstance.new({ w: 176, h: 148, path: 'sprites/box/violet.png' }),
|
||||||
|
|
BIN
sprites/box/cyan.png
Normal file
BIN
sprites/box/cyan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 564 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in a new issue