Finished refactoring the pause and gameplay scenes

This commit is contained in:
Gordon Pedersen 2023-03-27 17:03:10 +11:00
parent 2065a6b4d6
commit ba376238b2
7 changed files with 473 additions and 497 deletions

View file

@ -5,7 +5,7 @@ module Scene
DEFAULT: MainMenu, DEFAULT: MainMenu,
main_menu: MainMenu, main_menu: MainMenu,
settings: SettingsMenu, settings: SettingsMenu,
#paused: PauseMenu, paused: PauseMenu,
#cube_tube: CubeTube cube_tube: CubeTubeGame
} }
end end

View file

@ -1,22 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
# Extension to the scene class for the cube tube scene # this is the main gameplay!
module Scene class CubeTubeGame < GameplayScene
class << self def initialize(args, opts = {})
def tick_cube_tube(args) super
# call the gameplay scene tick method (handles pause menu, etc)
tick_gameplay(args)
args.state.game ||= CubeTubeGame.new args
args.state.game.tick
end
end
end
#
class CubeTubeGame
def initialize args
@args = args @args = args
@blocksize = 30 @blocksize = 30
@grid_w = 10 @grid_w = 10
@grid_h = 20 @grid_h = 20
@ -59,10 +49,371 @@ class CubeTubeGame
@current_music = :music1 @current_music = :music1
reset_game reset(args)
end end
def reset_game def render_background
# draw a solid black background
@args.outputs.solids << [
0,
0,
1280,
1280,
0, 0, 0
]
@bg_x += (@level + 1) * 2 unless @gameover
@bg_x %= @bg_w if @bg_x >= @bg_w
Sprite.for(:tunnel).render(@args, { x: @bg_x, y: 0, w: @bg_w, h: 720 })
Sprite.for(:tunnel).render(@args, { x: @bg_x - @bg_w, y: 0, w: @bg_w, h: 720 })
Sprite.for(:train).render(@args, { x: 0, y: @grid_x - 64 })
end
def render_foreground
Sprite.for(:train_fore).render(@args, { x: 0, y: @grid_x - 64 })
end
# x and y are positions in the grid, not pixels
def render_block(x, y, color)
@sprite_index[color].render(
@args,
{
x: (1280 - @grid_y) - (y * @blocksize) - 6,
y: @grid_x + (x * @blocksize),
w: @blocksize + 6,
h: @blocksize
}
)
end
def render_grid
(0..@grid_w - 1).each do |x|
(0..@grid_h - 1).each do |y|
if @grid[x][y] != 0 && (!@lines_to_clear.include?(y) || (@line_clear_timer % 14) < 7)
render_block(x, y, @grid[x][y])
end
end
end
end
def render_piece(piece, piece_x, piece_y)
(0..piece.length - 1).each do |x|
(0..piece[x].length - 1).each do |y|
render_block(piece_x + x, piece_y + y, piece[x][y]) if piece[x][y] != 0
end
end
end
def render_current_piece
render_piece(@current_piece, @current_piece_x, @current_piece_y) if @line_clear_timer <= 0
end
def render_next_piece
screen_x = @grid_y + 400
screen_y = @grid_x + 80
screen_w = 250
screen_h = 200
Sprite.for(:screen).render(@args, { x: screen_x, y: screen_y + 10, w: screen_w, h: screen_h + 10 })
next_piece = @line_clear_timer <= 0 ? @next_piece : @current_piece
centerx = (@next_piece_box[2] - next_piece.length) / 2
centery = (@next_piece_box[3] - next_piece[0].length) / 2
render_piece next_piece, @next_piece_box[0] + centerx, @next_piece_box[1] + centery
@args.outputs.labels << [screen_x + 33, screen_y + screen_h - 8, 'Next piece', 8, 255, 255, 255, 255 ]
screen_s =
case (@args.state.tick_count % 32)
when 0..7
:screen_s1
when 8..15
:screen_s2
when 16..23
:screen_s3
when 24..31
:screen_s4
end
Sprite.for(screen_s).render(@args, { x: screen_x, y: screen_y + 10, w: screen_w, h: screen_h + 10 })
end
def render_score
@args.outputs.labels << [200, 600, "Lines: #{@lines}", 10, 255, 255, 255, 255]
@args.outputs.labels << [400, 600, "Level: #{@level}", 10, 255, 255, 255, 255]
end
def render_gameover
@args.outputs.solids << [0, 245, 1280, 200, 0, 0, 0, 255]
@args.outputs.labels << [200, 450, 'GAME OVER', 100, 255, 255, 255, 255]
end
def render
render_background
render_next_piece
render_current_piece
render_grid
render_foreground
render_score
render_gameover if @showgameover
end
def current_piece_colliding
(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
case @level
when 0 then 53
when 1 then 49
when 2 then 45
when 3 then 41
when 4 then 37
when 5 then 33
when 6 then 28
when 7 then 22
when 8 then 17
when 9 then 11
when 10 then 10
when 11 then 9
when 12 then 8
when 13 then 7
when 14..15 then 6
when 16..17 then 5
when 18..19 then 4
else 3
end
end
def change_music
@current_music = @current_music == :music1 ? :music2 : :music1
Music.queue_up(@current_music)
end
def line_full?(row)
(0..@grid_w - 1).each do |x|
return false if @grid[x][row].zero?
end
true
end
def plant_current_piece
(0..@current_piece.length - 1).each do |x|
(0..@current_piece[x].length - 1).each do |y|
next if @current_piece[x][y].zero?
@grid[@current_piece_x + x][@current_piece_y + y] = @current_piece[x][y]
end
end
@lines_to_clear = []
# see if any rows need to be cleared out
(0..@grid_h - 1).each do |y|
next unless line_full?(y)
# no empty space in the row
@lines_to_clear.push y
@lines += 1
@line_clear_timer = 70
if (@lines % 10).floor.zero?
@level += 1
change_music
end
end
select_next_piece
if @lines_to_clear.empty?
Sound.play(@args, :drop)
if current_piece_colliding
@gameover = true
Music.stop(@args)
end
else
Sound.play(@args, :clear)
@current_speed = get_speed
end
@next_move = @current_speed + 2
end
def select_next_piece
@current_piece = @next_piece
@current_piece_x = 4
@current_piece_y = -1
r = (rand 7) + 1
@next_piece =
case r
when 1 then [[r, 0], [r, r], [0, r]]
when 2 then [[0, r], [r, r], [r, 0]]
when 3 then [[r, r, r], [r, 0, 0]]
when 4 then [[r, r], [r, r] ]
when 5 then [[r], [r], [r], [r]]
when 6 then [[r, 0], [r, r], [r, 0]]
when 7 then [[r, 0, 0], [r, r, r]]
end
select_next_piece if @current_piece.nil?
end
def rotate_current_piece_left
Sound.play(@args, :rotate)
@current_piece = @current_piece.transpose.map(&:reverse)
@current_piece_x = @grid_w - @current_piece.length if (@current_piece_x + @current_piece.length) >= @grid_w
end
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)
end
def fill_grid
b = false
(0..@grid_h - 1).each do |y|
(0..@grid_w - 1).each do |x|
if @grid[x][y].zero?
@grid[x][y] = (rand 7) + 1
b = true
end
end
return nil if b
end
@showgameover = true
end
def restart_game
reset(@args)
end
def move_current_piece_up
if (@current_piece_x + @current_piece.length) < @grid_w
@current_piece_x += 1
if current_piece_colliding
Sound.play(@args, :move_deny)
@current_piece_x -= 1
else
Sound.play(@args, :move)
end
else
Sound.play(@args, :move_deny)
end
end
def move_current_piece_down
if @current_piece_x.positive?
@current_piece_x -= 1
if current_piece_colliding
Sound.play(@args, :move_deny)
@current_piece_x += 1
else
Sound.play(@args, :move)
end
else
Sound.play(@args, :move_deny)
end
end
def iterate_line_clear
return false unless @line_clear_timer.positive?
@line_clear_timer -= 1
return true unless @line_clear_timer.zero?
@lines_to_clear.each do |y|
y.downto(1).each do |i|
(0..@grid_w - 1).each do |j|
@grid[j][i] = @grid[j][i - 1]
end
end
(0..@grid_w - 1).each do |i|
@grid[i][0] = 0
end
end
Sound.play(@args, :drop)
@lines_to_clear = []
false
end
def iterate_input
restart_game if Input.pressed?(@args, :primary) && @gameover && @showgameover
return if @gameover
move_current_piece_down if Input.pressed?(@args, :down)
move_current_piece_up if Input.pressed?(@args, :up)
@next_move -= @current_speed / 3 if Input.pressed_or_held?(@args, :left)
rotate_current_piece_left if Input.pressed?(@args, :rotate_left)
rotate_current_piece_right if Input.pressed?(@args, :rotate_right)
end
# train bounce effect
def iterate_train_bounce
# TODO: time it better to the music
case @args.state.tick_count % (@current_speed * 6)
when 0..3, (@current_speed * 2)..((@current_speed * 2) + 3)
@grid_x = @start_grid_x + 3
else
@grid_x = @start_grid_x
end
end
def iterate_movement
@next_move -= 1
return unless @next_move <= 0
@next_move = @current_speed
@current_piece_y += 1
return unless current_piece_colliding
@current_piece_y -= 1
plant_current_piece
end
def iterate
# input first
iterate_input
fill_grid if @gameover && !@showgameover
# skip the rest if it's game over
return if @gameover
# resume music if it's paused
Music.resume(@args) if !Music.stopped(@args) && Music.paused(@args)
iterate_train_bounce
# if we're currently animating a line clear, then skip the movement logic
return if iterate_line_clear
iterate_movement
end
# called every tick of the game loop
def tick(args)
iterate
render
super
end
# custom logic to reset this scene
def reset(args)
super
@lines = 0 @lines = 0
@level = 0 @level = 0
@current_speed = get_speed @current_speed = get_speed
@ -88,393 +439,7 @@ class CubeTubeGame
end end
@current_music = :music1 @current_music = :music1
Music.play(@args, @current_music) Music.play(args, @current_music)
Music.set_volume(args, args.state.setting.music ? 0.8 : 0.0) Music.set_volume(args, args.state.setting.music ? 0.8 : 0.0)
end end
end
def render_grid_border x, y, w, h, color
for i in x..(x+w)-1 do
render_block i, y, color
render_block i, (y + h - 1), color
end
for i in y..(y+h)-1 do
render_block x, i, color
render_block (x + w - 1), i, color
end
end
def render_background
# draw a solid black background
@args.outputs.solids << [
0,
0,
1280,
1280,
0, 0, 0
]
@bg_x += (@level+1)*2 unless @gameover
if(@bg_x >= @bg_w)
@bg_x %= @bg_w
end
Sprite.for(:tunnel).render(@args, { x: @bg_x, y: 0, w: @bg_w, h: 720 })
Sprite.for(:tunnel).render(@args, { x: @bg_x - @bg_w, y: 0, w: @bg_w, h: 720 })
Sprite.for(:train).render(@args, { x: 0, y: @grid_x - 64 })
end
def render_foreground
Sprite.for(:train_fore).render(@args, { x: 0, y: @grid_x - 64 })
end
# x and y are positions in the grid, not pixels
def render_block x, y, color
@sprite_index[color].render(
@args,
{
x: (1280 - @grid_y) - (y * @blocksize) - 6,
y: @grid_x + (x * @blocksize),
w: @blocksize + 6,
h: @blocksize
}
)
end
def render_grid
#render_grid_border -1, -1, @grid_w + 2, @grid_h + 2, 8
for x in 0..@grid_w-1 do
for y in 0..@grid_h-1 do
render_block x, y, @grid[x][y] if @grid[x][y] != 0 && (!@lines_to_clear.include?(y) || (@line_clear_timer % 14) < 7)
end
end
end
def render_piece piece, piece_x, piece_y
for x in 0..piece.length-1 do
for y in 0..piece[x].length-1 do
render_block piece_x + x, piece_y + y, piece[x][y] if piece[x][y] != 0
end
end
end
def render_current_piece
render_piece @current_piece, @current_piece_x, @current_piece_y if @line_clear_timer <= 0
end
def render_next_piece
screen_x = @grid_y + 400
screen_y = @grid_x + 80
screen_w = 250
screen_h = 200
Sprite.for(:screen).render(@args, { x: screen_x, y: screen_y + 10, w: screen_w, h: screen_h + 10 })
next_piece = @line_clear_timer <= 0 ? @next_piece : @current_piece
# render_grid_border *@next_piece_box, 8
centerx = (@next_piece_box[2] - next_piece.length) / 2
centery = (@next_piece_box[3] - next_piece[0].length) / 2
render_piece next_piece, @next_piece_box[0] + centerx, @next_piece_box[1] + centery
@args.outputs.labels << [screen_x + 33, screen_y + screen_h - 8, "Next piece", 8, 255, 255, 255, 255 ]
screen_s = case (@args.state.tick_count % 32)
when 0..7
:screen_s1
when 8..15
:screen_s2
when 16..23
:screen_s3
when 24..31
:screen_s4
end
Sprite.for(screen_s).render(@args, { x: screen_x, y: screen_y + 10, w: screen_w, h: screen_h + 10 })
end
def render_score
@args.outputs.labels << [ 200, 600, "Lines: #{@lines}", 10, 255, 255, 255, 255 ]
@args.outputs.labels << [ 400, 600, "Level: #{@level}", 10, 255, 255, 255, 255 ]
@args.outputs.labels << [ 400, 563, "(Speed: #{(1/(@current_speed/60)).round 2} L/s)", 0.1, 255, 255, 255, 255 ]
end
def render_gameover
@args.outputs.solids << [ 0, 245, 1280, 200, 0, 0, 0, 255]
@args.outputs.labels << [ 200, 450, "GAME OVER", 100, 255, 255, 255, 255 ]
end
def render
render_background
render_next_piece
render_current_piece
render_grid
render_foreground
render_score
render_gameover if @showgameover
end
def current_piece_colliding
for x in 0..@current_piece.length-1 do
for y in 0..@current_piece[x].length-1 do
if (@current_piece[x][y] != 0) && ((@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
return false
end
def get_speed
return case @level
when 0 then 53
when 1 then 49
when 2 then 45
when 3 then 41
when 4 then 37
when 5 then 33
when 6 then 28
when 7 then 22
when 8 then 17
when 9 then 11
when 10 then 10
when 11 then 9
when 12 then 8
when 13 then 7
when 14 then 6
when 15 then 6
when 16 then 5
when 17 then 5
when 18 then 4
when 19 then 4
when 20 then 3
else 3
end
end
def change_music
if @current_music == :music1
@current_music = :music2
else
@current_music = :music1
end
queue = Music.queue
Music.queue_up(@current_music)
end
def plant_current_piece
rows_to_check = []
for x in 0..@current_piece.length-1 do
for y in 0..@current_piece[x].length-1 do
if @current_piece[x][y] != 0
col = @current_piece_x + x
row = @current_piece_y + y
@grid[col][row] = @current_piece[x][y]
rows_to_check << row if !rows_to_check.include? row
end
end
end
@lines_to_clear = []
# see if any rows need to be cleared out
for y in 0..@grid_h-1
full = true
for x in 0..@grid_w-1
if @grid[x][y] == 0
full = false
break
end
end
if full # no empty space in the row
@lines_to_clear.push y
@lines += 1
@line_clear_timer = 70
if (@lines%10).floor == 0
@level += 1
change_music
end
end
end
select_next_piece
if @lines_to_clear.empty?
Sound.play(@args, :drop)
if current_piece_colliding
@gameover = true
Music.stop(@args)
end
else
Sound.play(@args, :clear)
@current_speed = get_speed
end
@next_move = @current_speed + 2
end
def select_next_piece
@current_piece = @next_piece
@current_piece_x = 4
@current_piece_y = -1
r = (rand 7) + 1
@next_piece = case r
when 1 then [ [r, 0], [r, r], [0, r]]
when 2 then [ [0, r], [r, r], [r, 0]]
when 3 then [ [r, r, r], [r, 0, 0]]
when 4 then [ [r, r], [r, r] ]
when 5 then [ [r], [r], [r], [r]]
when 6 then [ [r, 0], [r, r], [r, 0]]
when 7 then [ [r, 0, 0], [r, r, r]]
end
select_next_piece if @current_piece == nil
end
def rotate_current_piece_left
Sound.play(@args, :rotate)
@current_piece = @current_piece.transpose.map(&:reverse)
if(@current_piece_x + @current_piece.length) >= @grid_w
@current_piece_x = @grid_w - @current_piece.length
end
end
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)
end
def fill_grid
b = false
for y in 0..@grid_h-1 do
for x in 0..@grid_w-1 do
if @grid[x][y] == 0
@grid[x][y] = (rand 7) + 1
b = true
end
end
return if b
end
@showgameover = true
end
def restart_game
reset_game
end
def iterate
# check input first
k = @args.inputs.keyboard
c = @args.inputs.controller_one
if @gameover
if @showgameover
if k.key_down.space || k.key_down.enter || c.key_down.start
restart_game
end
else
fill_grid
end
return
end
unless Music.stopped(@args)
Music.resume(@args) if Music.paused(@args)
end
if @line_clear_timer.positive?
@line_clear_timer -= 1
if @line_clear_timer.zero?
for y in @lines_to_clear
for i in y.downto(1) do
for j in 0..@grid_w-1
@grid[j][i] = @grid[j][i-1]
end
end
for i in 0..@grid_w-1
@grid[i][0] = 0
end
end
Sound.play(@args, :drop)
@lines_to_clear = []
end
return
end
if k.key_down.down || k.key_down.s || c.key_down.down
if @current_piece_x > 0
@current_piece_x -= 1
if current_piece_colliding
Sound.play(@args, :move_deny)
@current_piece_x += 1
else
Sound.play(@args, :move)
end
else
Sound.play(@args, :move_deny)
end
end
if k.key_down.up || k.key_down.w || c.key_down.up
if (@current_piece_x + @current_piece.length) < @grid_w
@current_piece_x += 1
if current_piece_colliding
Sound.play(@args, :move_deny)
@current_piece_x -= 1
else
Sound.play(@args, :move)
end
else
Sound.play(@args, :move_deny)
end
end
if k.key_down.left || k.key_held.left || k.key_down.a || k.key_held.a || c.key_down.left || c.key_held.left
@next_move -= @current_speed / 3
end
if k.key_down.plus || k.key_down.equal_sign
@level += 1
@current_speed = get_speed
end
if k.key_down.q || c.key_down.a
rotate_current_piece_left
end
if k.key_down.e || c.key_down.b
rotate_current_piece_right
end
case @args.state.tick_count % (@current_speed * 6)
when 0..3, (@current_speed * 2)..((@current_speed * 2) + 3)
@grid_x = @start_grid_x + 3
else
@grid_x = @start_grid_x
end
@next_move -= 1
if @next_move <= 0
@next_move = @current_speed
@current_piece_y += 1
if current_piece_colliding
@current_piece_y -= 1
plant_current_piece
end
end
end
def tick
iterate
render
end
end

View file

@ -1,54 +1,51 @@
module Scene # frozen_string_literal: true
class << self
# This is your main entrypoint into the actual fun part of your game!
def tick_gameplay(args)
labels = []
sprites = []
# focus tracking # This is a base class for the main gameplay, handling things like pausing
if !args.state.has_focus && args.inputs.keyboard.has_focus class GameplayScene < SceneInstance
args.state.has_focus = true def initialize(_args, opts = {})
elsif args.state.has_focus && !args.inputs.keyboard.has_focus super
args.state.has_focus = false end
end
# auto-pause & input-based pause # called every tick of the game loop
if !args.state.has_focus || Input.pressed?(args, :pause) def tick(args)
return pause(args) super
end
tick_pause_button(args, sprites) if mobile? # focus tracking
if !args.state.has_focus && args.inputs.keyboard.has_focus
draw_bg(args, BLACK) args.state.has_focus = true
elsif args.state.has_focus && !args.inputs.keyboard.has_focus
# labels << label("GAMEPLAY", x: 40, y: args.grid.top - 40, size: SIZE_LG, font: FONT_BOLD) args.state.has_focus = false
args.outputs.labels << labels
args.outputs.sprites << sprites
end end
def pause(args) # auto-pause & input-based pause
Sound.play(args, :select) return pause(args) if !args.state.has_focus || Input.pressed?(args, :pause)
return Scene.push(args, :paused, reset: true)
end
def tick_pause_button(args, sprites) tick_pause_button(args) if mobile?
pause_button = {
x: 72.from_right, draw_bg(args, BLACK)
y: 72.from_top, end
w: 52,
h: 52, def pause(args)
path: Sprite.for(:pause), Sound.play(args, :select)
} Scene.push(args, :paused, reset: true)
pause_rect = pause_button.dup end
pause_padding = 12
pause_rect.x -= pause_padding def tick_pause_button(args)
pause_rect.y -= pause_padding pause_button = {
pause_rect.w += pause_padding * 2 x: 72.from_right,
pause_rect.h += pause_padding * 2 y: 72.from_top,
if args.inputs.mouse.down && args.inputs.mouse.inside_rect?(pause_rect) w: 52,
return pause(args) h: 52,
end path: Sprite.for(:pause)
sprites << pause_button }
end pause_rect = pause_button.dup
pause_padding = 12
pause_rect.x -= pause_padding
pause_rect.y -= pause_padding
pause_rect.w += pause_padding * 2
pause_rect.h += pause_padding * 2
return pause(args) if args.inputs.mouse.down && args.inputs.mouse.inside_rect?(pause_rect)
args.outputs.sprites << pause_button
end end
end end

View file

@ -55,7 +55,7 @@ class MenuScene < SceneInstance
button_border = { w: 340, h: 80, x: l.x - 170, y: l.y - 55 }.merge(WHITE) button_border = { w: 340, h: 80, x: l.x - 170, y: l.y - 55 }.merge(WHITE)
(args.outputs.borders << button_border) if mobile? (args.outputs.borders << button_border) if mobile?
if args.inputs.mouse.up && args.inputs.mouse.inside_rect?(button_border) if args.inputs.mouse.up && args.inputs.mouse.inside_rect?(button_border)
o = options.find { |o| o[:key] == l[:key] } o = @menu_options.find { |o| o[:key] == l[:key] }
Sound.play(args, :menu) Sound.play(args, :menu)
o[:on_select].call(args) if o o[:on_select].call(args) if o
end end
@ -105,6 +105,11 @@ class MenuScene < SceneInstance
@menu_options[@menu_state.current_option_i][:on_select].call(args) @menu_options[@menu_state.current_option_i][:on_select].call(args)
Sound.play(args, :select) Sound.play(args, :select)
end end
if Input.pressed?(args, :secondary) && !Scene.stack(args).empty?
Sound.play(args, :select)
Scene.pop(args)
end
end end
# custom logic to reset this scene # custom logic to reset this scene

View file

@ -1,42 +1,46 @@
module Scene # frozen_string_literal: true
class << self
# scene reached from gameplay when the player needs a break
def tick_paused(args)
draw_bg(args, DARK_YELLOW)
options = [ # This is the pause menu, triggered by a button press when the player wants a
{ # break from gameplay.
key: :resume, class PauseMenu < MenuScene
on_select: -> (args) { Scene.pop(args) } def initialize(args, opts = {})
}, menu_options = [
{ {
key: :settings, key: :resume,
on_select: -> (args) { Scene.push(args, :settings, reset: true) } on_select: ->(args) { Scene.pop(args) }
}, },
{ {
key: :return_to_main_menu, key: :settings,
on_select: -> (args) { Scene.switch(args, :main_menu) } on_select: ->(args) { Scene.push(args, :settings, reset: true) }
}, },
] {
key: :return_to_main_menu,
on_select: ->(args) { Scene.switch(args, :main_menu) }
}
]
if args.gtk.platform?(:desktop) if args.gtk.platform?(:desktop)
options << { menu_options << {
key: :quit, key: :quit,
on_select: -> (args) { args.gtk.request_quit } on_select: ->(args) { args.gtk.request_quit }
} }
end
Menu.tick(args, :paused, options)
Music.pause(args) unless Music.stopped(args)
if Input.pressed?(args, :secondary)
Sound.play(args, :select)
options.find { |o| o[:key] == :resume }[:on_select].call(args)
end
args.outputs.labels << label(:paused, x: args.grid.w / 2, y: args.grid.top - 200, align: ALIGN_CENTER, size: SIZE_LG, font: FONT_BOLD)
end end
super args, opts, menu_options
end
# called every tick of the game loop
def tick(args)
super
Music.pause(args) unless Music.stopped(args) || Music.paused(args)
args.outputs.labels << label(
:paused,
x: args.grid.w / 2,
y: args.grid.top - 200,
align: ALIGN_CENTER,
size: SIZE_LG,
font: FONT_BOLD
)
end end
end end

View file

@ -55,11 +55,6 @@ class SettingsMenu < MenuScene
# actual menu logic is handled by the MenuScene super class # actual menu logic is handled by the MenuScene super class
super super
if Input.pressed?(args, :secondary)
Sound.play(args, :select)
@menu_options.find { |o| o[:key] == :back }[:on_select].call(args)
end
args.outputs.labels << label( args.outputs.labels << label(
:settings, :settings,
x: args.grid.w / 2, x: args.grid.w / 2,

View file

@ -19,10 +19,16 @@ module Scene
args.state.scene_stack ||= [] args.state.scene_stack ||= []
# if we're here /not/ from push or pop, clear the scene stack # if we're here /not/ from push or pop, clear the scene stack
args.state.scene_stack.clear unless push_or_pop args.state.scene_stack.clear unless push_or_pop
# if `scene` is not a `SceneInstance`, it's probably a symbol representing # if `scene` is not a `SceneInstance`, it's probably a symbol representing
# the scene we're switching to, so go get it. # the scene we're switching to, so go get it.
the_scene = scene.is_a?(SceneInstance) ? scene : SCENES[scene].new(args) the_scene = scene.is_a?(SceneInstance) ? scene : SCENES[scene].new(args)
puts '---'
puts 'switching to'
puts scene unless scene.is_a?(SceneInstance)
puts SCENES[scene] unless scene.is_a?(SceneInstance)
puts the_scene
puts '---'
# if the stack is empty (e.g. we just cleared it), then push this scene # if the stack is empty (e.g. we just cleared it), then push this scene
args.state.scene_stack.push(the_scene) if args.state.scene_stack.empty? args.state.scene_stack.push(the_scene) if args.state.scene_stack.empty?
@ -53,5 +59,9 @@ module Scene
args.state.scene_stack ||= [] args.state.scene_stack ||= []
SCENES[:DEFAULT].new(args) SCENES[:DEFAULT].new(args)
end end
def stack(args)
args.state.scene_stack ||= []
end
end end
end end