Begin refactor of scenes
Refactored the Menu Scene "subclass" as well as the main and settings menus
This commit is contained in:
parent
045a6f4e20
commit
9a82b55505
12 changed files with 320 additions and 236 deletions
16
app/classes/scene_instance.rb
Normal file
16
app/classes/scene_instance.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# class to represent scenes
|
||||||
|
class SceneInstance
|
||||||
|
def initialize(_args, opts = {})
|
||||||
|
@tick_in_background = opts.tick_in_background._? false
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :tick_in_background
|
||||||
|
|
||||||
|
# called every tick of the game loop
|
||||||
|
def tick(args) end
|
||||||
|
|
||||||
|
# custom logic to reset this scene
|
||||||
|
def reset(args) end
|
||||||
|
end
|
|
@ -6,6 +6,7 @@ require 'lib/coalesce.rb'
|
||||||
# then, some basic classes required for lists of assets
|
# then, some basic classes required for lists of assets
|
||||||
require 'app/classes/sprite_instance.rb'
|
require 'app/classes/sprite_instance.rb'
|
||||||
require 'app/classes/sound_instance.rb'
|
require 'app/classes/sound_instance.rb'
|
||||||
|
require 'app/classes/scene_instance.rb'
|
||||||
|
|
||||||
# then, asset lists
|
# then, asset lists
|
||||||
require 'sprites/_list.rb'
|
require 'sprites/_list.rb'
|
||||||
|
@ -23,18 +24,20 @@ require 'app/util/util.rb'
|
||||||
require 'app/util/input.rb'
|
require 'app/util/input.rb'
|
||||||
|
|
||||||
require 'app/constants.rb'
|
require 'app/constants.rb'
|
||||||
require 'app/menu.rb'
|
|
||||||
require 'app/scene.rb'
|
|
||||||
require 'app/game_setting.rb'
|
require 'app/game_setting.rb'
|
||||||
require 'app/text.rb'
|
require 'app/text.rb'
|
||||||
|
|
||||||
# then, the scenes
|
# then, the scenes
|
||||||
|
require 'app/scenes/menu.rb'
|
||||||
require 'app/scenes/gameplay.rb'
|
require 'app/scenes/gameplay.rb'
|
||||||
require 'app/scenes/main_menu.rb'
|
require 'app/scenes/main_menu.rb'
|
||||||
require 'app/scenes/paused.rb'
|
require 'app/scenes/paused.rb'
|
||||||
require 'app/scenes/settings.rb'
|
require 'app/scenes/settings.rb'
|
||||||
require 'app/scenes/cube_tube.rb'
|
require 'app/scenes/cube_tube.rb'
|
||||||
|
|
||||||
|
require 'app/scenes/_list.rb'
|
||||||
|
require 'app/util/scene.rb'
|
||||||
|
|
||||||
# finally, the main tick
|
# finally, the main tick
|
||||||
# NOTE: add all other requires above this
|
# NOTE: add all other requires above this
|
||||||
require 'app/tick.rb'
|
require 'app/tick.rb'
|
||||||
|
|
113
app/menu.rb
113
app/menu.rb
|
@ -1,113 +0,0 @@
|
||||||
module Menu
|
|
||||||
class << self
|
|
||||||
# Updates and renders a list of options that get passed through.
|
|
||||||
#
|
|
||||||
# +options+ data structure:
|
|
||||||
# [
|
|
||||||
# {
|
|
||||||
# text: "some string",
|
|
||||||
# on_select: -> (args) { "do some stuff in this lambda" }
|
|
||||||
# }
|
|
||||||
# ]
|
|
||||||
def tick(args, state_key, options, menu_y: 420)
|
|
||||||
args.state.send(state_key).current_option_i ||= 0
|
|
||||||
args.state.send(state_key).hold_delay ||= 0
|
|
||||||
menu_state = args.state.send(state_key)
|
|
||||||
|
|
||||||
labels = []
|
|
||||||
|
|
||||||
spacer = mobile? ? 100 : 60
|
|
||||||
options.each.with_index do |option, i|
|
|
||||||
text = case option.kind
|
|
||||||
when :toggle
|
|
||||||
"#{text(option[:key])}: #{text_for_setting_val(option[:setting_val])}"
|
|
||||||
else
|
|
||||||
text(option[:key])
|
|
||||||
end
|
|
||||||
|
|
||||||
label = label(
|
|
||||||
text,
|
|
||||||
x: args.grid.w / 2,
|
|
||||||
y: menu_y + (options.length - i * spacer),
|
|
||||||
align: ALIGN_CENTER,
|
|
||||||
size: SIZE_MD
|
|
||||||
)
|
|
||||||
label.key = option[:key]
|
|
||||||
label_size = args.gtk.calcstringbox(label.text, label.size_enum)
|
|
||||||
labels << label
|
|
||||||
if menu_state.current_option_i == i
|
|
||||||
if !mobile? || (mobile? && args.inputs.controller_one.connected)
|
|
||||||
args.outputs.solids << {
|
|
||||||
x: label.x - (label_size[0] / 1.4) - 24 + (Math.sin(args.state.tick_count / 8) * 4),
|
|
||||||
y: label.y - 22,
|
|
||||||
w: 16,
|
|
||||||
h: 16,
|
|
||||||
}.merge(WHITE)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
labels.each do |l|
|
|
||||||
button_border = { w: 340, h: 80, x: l.x - 170, y: l.y - 55 }.merge(WHITE)
|
|
||||||
if mobile?
|
|
||||||
args.outputs.borders << button_border
|
|
||||||
end
|
|
||||||
|
|
||||||
if args.inputs.mouse.up && args.inputs.mouse.inside_rect?(button_border)
|
|
||||||
o = options.find { |o| o[:key] == l[:key] }
|
|
||||||
Sound.play(args, :menu)
|
|
||||||
o[:on_select].call(args) if o
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
args.outputs.labels << labels
|
|
||||||
|
|
||||||
move = nil
|
|
||||||
if args.inputs.down
|
|
||||||
move = :down
|
|
||||||
elsif args.inputs.up
|
|
||||||
move = :up
|
|
||||||
else
|
|
||||||
menu_state.hold_delay = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if move
|
|
||||||
menu_state.hold_delay -= 1
|
|
||||||
|
|
||||||
if menu_state.hold_delay <= 0
|
|
||||||
Sound.play(args, :menu)
|
|
||||||
index = menu_state.current_option_i
|
|
||||||
if move == :up
|
|
||||||
index -= 1
|
|
||||||
else
|
|
||||||
index += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if index < 0
|
|
||||||
index = options.length - 1
|
|
||||||
elsif index > options.length - 1
|
|
||||||
index = 0
|
|
||||||
end
|
|
||||||
menu_state.current_option_i = index
|
|
||||||
menu_state.hold_delay = 10
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if Input.pressed?(args, :primary)
|
|
||||||
Sound.play(args, :select)
|
|
||||||
options[menu_state.current_option_i][:on_select].call(args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def text_for_setting_val(val)
|
|
||||||
case val
|
|
||||||
when true
|
|
||||||
text(:on)
|
|
||||||
when false
|
|
||||||
text(:off)
|
|
||||||
else
|
|
||||||
val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
11
app/scenes/_list.rb
Normal file
11
app/scenes/_list.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Scene
|
||||||
|
SCENES = {
|
||||||
|
DEFAULT: MainMenu,
|
||||||
|
main_menu: MainMenu,
|
||||||
|
settings: SettingsMenu,
|
||||||
|
#paused: PauseMenu,
|
||||||
|
#cube_tube: CubeTube
|
||||||
|
}
|
||||||
|
end
|
|
@ -89,6 +89,7 @@ class CubeTubeGame
|
||||||
|
|
||||||
@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)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_grid_border x, y, w, h, color
|
def render_grid_border x, y, w, h, color
|
||||||
|
|
|
@ -1,50 +1,64 @@
|
||||||
module Scene
|
# frozen_string_literal: true
|
||||||
class << self
|
|
||||||
# what's displayed when your game starts
|
# This is the first screen in this game, allowing access to everything else
|
||||||
def tick_main_menu(args)
|
class MainMenu < MenuScene
|
||||||
draw_bg(args, DARK_PURPLE)
|
def initialize(args, opts = {})
|
||||||
options = [
|
# these are the menu options for the main menu
|
||||||
|
menu_options = [
|
||||||
{
|
{
|
||||||
key: :start,
|
key: :start,
|
||||||
on_select: -> (args) { Scene.switch(args, :cube_tube, reset: true) }
|
on_select: ->(iargs) { Scene.switch(iargs, :cube_tube, reset: true) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: :settings,
|
key: :settings,
|
||||||
on_select: -> (args) { Scene.push(args, :settings, reset: true) }
|
on_select: ->(iargs) { Scene.push(iargs, :settings, reset: true) }
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
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: ->(iargs) { iargs.gtk.request_quit }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
Menu.tick(args, :main_menu, options)
|
super args, opts, menu_options
|
||||||
|
end
|
||||||
|
|
||||||
|
# called every tick of the game loop
|
||||||
|
def tick(args)
|
||||||
|
draw_bg(args, DARK_PURPLE)
|
||||||
|
|
||||||
|
# actual menu logic is handled by the MenuScene super class
|
||||||
|
super
|
||||||
|
|
||||||
|
# additionally draw some labels with information about the game
|
||||||
labels = []
|
labels = []
|
||||||
labels << label(
|
labels << label(
|
||||||
"v#{version}",
|
"v#{version}",
|
||||||
x: 32.from_left, y: 32.from_top,
|
x: 32.from_left, y: 32.from_top,
|
||||||
size: SIZE_XS, align: ALIGN_LEFT)
|
size: SIZE_XS, align: ALIGN_LEFT
|
||||||
|
)
|
||||||
labels << label(
|
labels << label(
|
||||||
title.upcase, x: args.grid.w / 2, y: args.grid.top - 100,
|
title.upcase, x: args.grid.w / 2, y: args.grid.top - 100,
|
||||||
size: SIZE_LG, align: ALIGN_CENTER, font: FONT_BOLD_ITALIC)
|
size: SIZE_LG, align: ALIGN_CENTER, font: FONT_BOLD_ITALIC
|
||||||
|
)
|
||||||
labels << label(
|
labels << label(
|
||||||
"#{text(:made_by)} #{dev_title}",
|
"#{text(:made_by)} #{dev_title}",
|
||||||
x: args.grid.left + 24, y: 48,
|
x: args.grid.left + 24, y: 48,
|
||||||
size: SIZE_XS, align: ALIGN_LEFT)
|
size: SIZE_XS, align: ALIGN_LEFT
|
||||||
|
)
|
||||||
labels << label(
|
labels << label(
|
||||||
:controls_title,
|
:controls_title,
|
||||||
x: args.grid.right - 24, y: 84,
|
x: args.grid.right - 24, y: 84,
|
||||||
size: SIZE_SM, align: ALIGN_RIGHT)
|
size: SIZE_SM, align: ALIGN_RIGHT
|
||||||
|
)
|
||||||
labels << label(
|
labels << label(
|
||||||
args.inputs.controller_one.connected ? :controls_gamepad : :controls_keyboard,
|
args.inputs.controller_one.connected ? :controls_gamepad : :controls_keyboard,
|
||||||
x: args.grid.right - 24, y: 48,
|
x: args.grid.right - 24, y: 48,
|
||||||
size: SIZE_XS, align: ALIGN_RIGHT)
|
size: SIZE_XS, align: ALIGN_RIGHT
|
||||||
|
)
|
||||||
|
|
||||||
args.outputs.labels << labels
|
args.outputs.labels << labels
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
129
app/scenes/menu.rb
Normal file
129
app/scenes/menu.rb
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# A scene which updates and renders a list of options that get passed through.
|
||||||
|
#
|
||||||
|
# +menu_options+ data structure:
|
||||||
|
# [
|
||||||
|
# {
|
||||||
|
# text: 'some string',
|
||||||
|
# on_select: -> (args) { 'do some stuff in this lambda' }
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
class MenuScene < SceneInstance
|
||||||
|
def initialize(args, opts = {}, menu_options = [])
|
||||||
|
super args, opts
|
||||||
|
|
||||||
|
@menu_state ||= {
|
||||||
|
current_option_i: 0,
|
||||||
|
hold_delay: 0
|
||||||
|
}
|
||||||
|
@spacer ||= mobile? ? 100 : 60
|
||||||
|
@menu_options ||= menu_options
|
||||||
|
@menu_y = opts.menu_y._?(420)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_options(args)
|
||||||
|
labels = []
|
||||||
|
@menu_options.each.with_index do |option, i|
|
||||||
|
text = case option.kind
|
||||||
|
when :toggle
|
||||||
|
"#{text(option[:key])}: #{text_for_setting_val(args, option[:key])}"
|
||||||
|
else
|
||||||
|
text(option[:key])
|
||||||
|
end
|
||||||
|
|
||||||
|
l = label(
|
||||||
|
text,
|
||||||
|
x: args.grid.w / 2,
|
||||||
|
y: @menu_y + (@menu_options.length - (i * @spacer)),
|
||||||
|
align: ALIGN_CENTER,
|
||||||
|
size: SIZE_MD
|
||||||
|
)
|
||||||
|
l.key = option[:key]
|
||||||
|
l.width, l.height = args.gtk.calcstringbox(l.text, l.size_enum)
|
||||||
|
labels << l
|
||||||
|
|
||||||
|
if @menu_state.current_option_i == i && (!mobile? || (mobile? && args.inputs.controller_one.connected))
|
||||||
|
args.outputs.solids << {
|
||||||
|
x: l.x - (l.width / 1.4) - 24 + (Math.sin(args.state.tick_count / 8) * 4),
|
||||||
|
y: l.y - 22,
|
||||||
|
w: 16,
|
||||||
|
h: 16
|
||||||
|
}.merge(WHITE)
|
||||||
|
end
|
||||||
|
|
||||||
|
button_border = { w: 340, h: 80, x: l.x - 170, y: l.y - 55 }.merge(WHITE)
|
||||||
|
(args.outputs.borders << button_border) if mobile?
|
||||||
|
if args.inputs.mouse.up && args.inputs.mouse.inside_rect?(button_border)
|
||||||
|
o = options.find { |o| o[:key] == l[:key] }
|
||||||
|
Sound.play(args, :menu)
|
||||||
|
o[:on_select].call(args) if o
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
args.outputs.labels << labels
|
||||||
|
end
|
||||||
|
|
||||||
|
# called every tick of the game loop
|
||||||
|
def tick(args)
|
||||||
|
super
|
||||||
|
|
||||||
|
render_options(args)
|
||||||
|
|
||||||
|
move = nil
|
||||||
|
if Input.down?(args)
|
||||||
|
move = :down
|
||||||
|
elsif Input.up?(args)
|
||||||
|
move = :up
|
||||||
|
else
|
||||||
|
@menu_state.hold_delay = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if move
|
||||||
|
@menu_state.hold_delay -= 1
|
||||||
|
|
||||||
|
if @menu_state.hold_delay <= 0
|
||||||
|
Sound.play(args, :menu)
|
||||||
|
index = @menu_state.current_option_i
|
||||||
|
if move == :up
|
||||||
|
index -= 1
|
||||||
|
else
|
||||||
|
index += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if index.negative?
|
||||||
|
index = @menu_options.length - 1
|
||||||
|
elsif index > @menu_options.length - 1
|
||||||
|
index = 0
|
||||||
|
end
|
||||||
|
@menu_state.current_option_i = index
|
||||||
|
@menu_state.hold_delay = 10
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Input.pressed?(args, :primary)
|
||||||
|
@menu_options[@menu_state.current_option_i][:on_select].call(args)
|
||||||
|
Sound.play(args, :select)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# custom logic to reset this scene
|
||||||
|
def reset(args)
|
||||||
|
super
|
||||||
|
|
||||||
|
@menu_state.current_option_i = 0
|
||||||
|
@menu_state.hold_delay = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def text_for_setting_val(args, key)
|
||||||
|
val = args.state.setting[key]
|
||||||
|
case val
|
||||||
|
when true
|
||||||
|
text(:on)
|
||||||
|
when false
|
||||||
|
text(:off)
|
||||||
|
else
|
||||||
|
val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,25 +1,23 @@
|
||||||
module Scene
|
# frozen_string_literal: true
|
||||||
class << self
|
|
||||||
# reachable via main menu or pause menu, allows for configuring the game
|
|
||||||
# for the player's preferences.
|
|
||||||
def tick_settings(args)
|
|
||||||
draw_bg(args, DARK_GREEN)
|
|
||||||
|
|
||||||
options = [
|
# This is the settings menu, allowing for various settings to be changed
|
||||||
|
class SettingsMenu < MenuScene
|
||||||
|
def initialize(args, opts = {})
|
||||||
|
menu_options = [
|
||||||
{
|
{
|
||||||
key: :sfx,
|
key: :sfx,
|
||||||
kind: :toggle,
|
kind: :toggle,
|
||||||
setting_val: args.state.setting.sfx,
|
|
||||||
on_select: ->(args) do
|
on_select: ->(args) do
|
||||||
|
puts 'toggle sfx'
|
||||||
GameSetting.save_after(args) do |args|
|
GameSetting.save_after(args) do |args|
|
||||||
args.state.setting.sfx = !args.state.setting.sfx
|
args.state.setting.sfx = !args.state.setting.sfx
|
||||||
|
puts "sfx = #{args.state.setting.sfx}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: :music,
|
key: :music,
|
||||||
kind: :toggle,
|
kind: :toggle,
|
||||||
setting_val: args.state.setting.music,
|
|
||||||
on_select: ->(args) do
|
on_select: ->(args) do
|
||||||
GameSetting.save_after(args) do |args|
|
GameSetting.save_after(args) do |args|
|
||||||
args.state.setting.music = !args.state.setting.music
|
args.state.setting.music = !args.state.setting.music
|
||||||
|
@ -29,32 +27,48 @@ module Scene
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: :back,
|
key: :back,
|
||||||
on_select: -> (args) { Scene.pop(args) }
|
on_select: ->(iargs) { Scene.pop(iargs) }
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
if args.gtk.platform?(:desktop)
|
if args.gtk.platform?(:desktop)
|
||||||
options.insert(options.length - 1, {
|
menu_options.insert(
|
||||||
|
menu_options.length - 1,
|
||||||
|
{
|
||||||
key: :fullscreen,
|
key: :fullscreen,
|
||||||
kind: :toggle,
|
kind: :toggle,
|
||||||
setting_val: args.state.setting.fullscreen,
|
|
||||||
on_select: ->(args) do
|
on_select: ->(args) do
|
||||||
GameSetting.save_after(args) do |args|
|
GameSetting.save_after(args) do |args|
|
||||||
args.state.setting.fullscreen = !args.state.setting.fullscreen
|
args.state.setting.fullscreen = !args.state.setting.fullscreen
|
||||||
args.gtk.set_window_fullscreen(args.state.setting.fullscreen)
|
args.gtk.set_window_fullscreen(args.state.setting.fullscreen)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
Menu.tick(args, :settings, options)
|
super args, opts, menu_options
|
||||||
|
end
|
||||||
|
|
||||||
|
# called every tick of the game loop
|
||||||
|
def tick(args)
|
||||||
|
draw_bg(args, DARK_GREEN)
|
||||||
|
|
||||||
|
# actual menu logic is handled by the MenuScene super class
|
||||||
|
super
|
||||||
|
|
||||||
if Input.pressed?(args, :secondary)
|
if Input.pressed?(args, :secondary)
|
||||||
Sound.play(args, :select)
|
Sound.play(args, :select)
|
||||||
options.find { |o| o[:key] == :back }[:on_select].call(args)
|
@menu_options.find { |o| o[:key] == :back }[:on_select].call(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
args.outputs.labels << label(:settings, x: args.grid.w / 2, y: args.grid.top - 200, align: ALIGN_CENTER, size: SIZE_LG, font: FONT_BOLD)
|
args.outputs.labels << label(
|
||||||
end
|
:settings,
|
||||||
|
x: args.grid.w / 2,
|
||||||
|
y: args.grid.top - 200,
|
||||||
|
align: ALIGN_CENTER,
|
||||||
|
size: SIZE_LG,
|
||||||
|
font: FONT_BOLD
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
20
app/tick.rb
20
app/tick.rb
|
@ -1,21 +1,27 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Code that only gets run once on game start
|
# Code that only gets run once on game start
|
||||||
def init(args)
|
def init(args)
|
||||||
Input.reset_swipe(args)
|
Input.reset_swipe(args)
|
||||||
GameSetting.load_settings(args)
|
GameSetting.load_settings(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Code that runs every game tick (mainly just calling other ticks)
|
||||||
def tick(args)
|
def tick(args)
|
||||||
init(args) if args.state.tick_count == 0
|
init(args) if args.state.tick_count.zero?
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
args.state.has_focus ||= true
|
args.state.has_focus ||= true
|
||||||
Scene.push(args, :main_menu, reset: true) if !args.state.scene
|
args.state.scene_stack ||= []
|
||||||
|
Scene.push(args, Scene.default(args), reset: true) if args.state.scene_stack.empty?
|
||||||
|
|
||||||
Input.track_swipe(args) if mobile?
|
Input.track_swipe(args) if mobile?
|
||||||
|
|
||||||
Scene.send("tick_#{args.state.scene}", args)
|
# Scene.send("tick_#{args.state.scene}", args)
|
||||||
|
args.state.scene_stack.each do |scene|
|
||||||
|
scene.tick(args) if scene.tick_in_background || scene == args.state.scene_stack.last
|
||||||
|
end
|
||||||
|
|
||||||
Music.tick(args)
|
Music.tick(args)
|
||||||
|
|
||||||
|
@ -45,7 +51,7 @@ def debug_tick(args)
|
||||||
if args.inputs.keyboard.key_down.i
|
if args.inputs.keyboard.key_down.i
|
||||||
Sound.play(args, :select)
|
Sound.play(args, :select)
|
||||||
Sprite.reset_all(args)
|
Sprite.reset_all(args)
|
||||||
args.gtk.notify!("Sprites reloaded")
|
args.gtk.notify!('Sprites reloaded')
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.inputs.keyboard.key_down.r
|
if args.inputs.keyboard.key_down.r
|
||||||
|
@ -57,9 +63,9 @@ def debug_tick(args)
|
||||||
Sound.play(args, :select)
|
Sound.play(args, :select)
|
||||||
args.state.simulate_mobile = !args.state.simulate_mobile
|
args.state.simulate_mobile = !args.state.simulate_mobile
|
||||||
msg = if args.state.simulate_mobile
|
msg = if args.state.simulate_mobile
|
||||||
"Mobile simulation on"
|
'Mobile simulation on'
|
||||||
else
|
else
|
||||||
"Mobile simulation off"
|
'Mobile simulation off'
|
||||||
end
|
end
|
||||||
args.gtk.notify!(msg)
|
args.gtk.notify!(msg)
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,7 +26,7 @@ module Music
|
||||||
end
|
end
|
||||||
|
|
||||||
def paused(args, channel = 0)
|
def paused(args, channel = 0)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].paused
|
args.audio["MUSIC_CHANNEL_#{channel}"].paused unless stopped(args, channel)
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop(args, channel = 0)
|
def stop(args, channel = 0)
|
||||||
|
@ -34,15 +34,15 @@ module Music
|
||||||
end
|
end
|
||||||
|
|
||||||
def pause(args, channel = 0)
|
def pause(args, channel = 0)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].paused = true
|
args.audio["MUSIC_CHANNEL_#{channel}"].paused = true unless stopped(args, channel)
|
||||||
end
|
end
|
||||||
|
|
||||||
def resume(args, channel = 0)
|
def resume(args, channel = 0)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].paused = false
|
args.audio["MUSIC_CHANNEL_#{channel}"].paused = false unless stopped(args, channel)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_volume(args, volume, channel = 0)
|
def set_volume(args, volume, channel = 0)
|
||||||
args.audio["MUSIC_CHANNEL_#{channel}"].gain = volume
|
args.audio["MUSIC_CHANNEL_#{channel}"].gain = volume unless stopped(args, channel)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tick(args)
|
def tick(args)
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# A scene represents a discreet state of gameplay. Things like the main menu,
|
# A scene represents a discreet state of gameplay. Things like the main menu,
|
||||||
# game over screen, and gameplay.
|
# game over screen, and gameplay.
|
||||||
#
|
#
|
||||||
# Define a new scene by adding one to `app/scenes/` and defining a
|
# Define a new scene by adding one to `app/scenes/` and inheriting from
|
||||||
# `Scene.tick_SCENE_NAME` class method.
|
# SceneInstance
|
||||||
#
|
#
|
||||||
# The main `#tick` of the game handles delegating to the current scene based on
|
# The main `#tick` of the game handles delegating to the current scene based on
|
||||||
# the `args.state.scene` value, which is a symbol of the current scene, ex:
|
# the `args.state.scene` value, which is a symbol of the current scene, ex:
|
||||||
|
@ -14,17 +16,12 @@ module Scene
|
||||||
# ex:
|
# ex:
|
||||||
# Scene.switch(args, :gameplay)
|
# Scene.switch(args, :gameplay)
|
||||||
def switch(args, scene, reset: false, push_or_pop: false)
|
def switch(args, scene, reset: false, push_or_pop: false)
|
||||||
|
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
|
||||||
|
args.state.scene_stack.push(scene) if args.state.scene_stack.empty?
|
||||||
|
|
||||||
if reset
|
scene.reset(args) if reset
|
||||||
args.state.send(scene)&.current_option_i = nil
|
|
||||||
args.state.send(scene)&.hold_delay = nil
|
|
||||||
|
|
||||||
# you can also add custom reset logic as-needed for specific scenes
|
|
||||||
# here
|
|
||||||
args.state.game.reset_game if args.state.game
|
|
||||||
end
|
|
||||||
|
|
||||||
args.state.scene = scene
|
args.state.scene = scene
|
||||||
raise FinishTick, 'finish tick early'
|
raise FinishTick, 'finish tick early'
|
||||||
|
@ -32,17 +29,23 @@ module Scene
|
||||||
|
|
||||||
# Change the current scene and push the previous scene onto the stack
|
# Change the current scene and push the previous scene onto the stack
|
||||||
def push(args, scene, reset: false)
|
def push(args, scene, reset: false)
|
||||||
puts "Pushing #{scene}"
|
|
||||||
args.state.scene_stack ||= []
|
args.state.scene_stack ||= []
|
||||||
args.state.scene_stack.push(args.state.scene)
|
the_scene = scene.is_a?(SceneInstance) ? scene : SCENES[scene].new(args)
|
||||||
|
args.state.scene_stack.push(the_scene)
|
||||||
|
|
||||||
switch(args, scene, reset: reset, push_or_pop: true)
|
switch(args, the_scene, reset: reset, push_or_pop: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return to the previous scene on the stack
|
# Return to the previous scene on the stack
|
||||||
def pop(args, reset: false)
|
def pop(args, reset: false)
|
||||||
scene = !args.state.scene_stack || args.state.scene_stack.empty? ? :back : args.state.scene_stack.pop
|
scene = args.state.scene_stack&.pop
|
||||||
switch(args, scene, reset: reset, push_or_pop: true)
|
|
||||||
|
switch(args, scene._?(default(args)), reset: reset, push_or_pop: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def default(args)
|
||||||
|
args.state.scene_stack ||= []
|
||||||
|
SCENES[:DEFAULT].new(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -8,7 +8,7 @@ module Sound
|
||||||
end
|
end
|
||||||
|
|
||||||
def play(args, key, opts = {})
|
def play(args, key, opts = {})
|
||||||
SOUNDS.fetch(key).play(args, opts)
|
SOUNDS.fetch(key).play(args, opts) if args.state.setting.sfx
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop(args, key)
|
def stop(args, key)
|
||||||
|
|
Loading…
Reference in a new issue