From e3a2c9abe0bdc8e9da2ad21a1b8255e8d92479be Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Fri, 8 May 2020 19:03:45 -0500 Subject: [PATCH] Added require_all method to replace explicitly requiring every source file, added SoundManager and sound effects, added sound for shield/health regen --- README.md | 2 +- assets/base/shared/sound/master.yaml | 11 ++ assets/base/shared/sound/sfx/shield_regen.wav | Bin 0 -> 1466 bytes i-mic-fps.rb | 125 +++--------------- lib/managers/sound_manager.rb | 53 ++++++++ lib/overlay.rb | 2 +- lib/sound_effect.rb | 19 +++ lib/sound_effects/fade_in.rb | 32 +++++ lib/sound_effects/fade_in_and_out.rb | 22 +++ lib/sound_effects/fade_out.rb | 9 ++ lib/sound_effects/shield_regen.rb | 25 ++++ lib/states/game_states/boot.rb | 2 + lib/window.rb | 1 + 13 files changed, 197 insertions(+), 106 deletions(-) create mode 100644 assets/base/shared/sound/master.yaml create mode 100644 assets/base/shared/sound/sfx/shield_regen.wav create mode 100644 lib/managers/sound_manager.rb create mode 100644 lib/sound_effect.rb create mode 100644 lib/sound_effects/fade_in.rb create mode 100644 lib/sound_effects/fade_in_and_out.rb create mode 100644 lib/sound_effects/fade_out.rb create mode 100644 lib/sound_effects/shield_regen.rb diff --git a/README.md b/README.md index c09bc6a..6964647 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # I-MIC FPS Creating a multiplayer first-person-shooter in pure Ruby; Using C extensions only for Rendering, Sound, and Input. ([Gosu](https://libgosu.org) and [opengl-bindings](https://github.com/vaiorabbit/ruby-opengl/)) -![](https://raw.githubusercontent.com/cyberarm/i-mic-fps/master/screenshots/screenshot-game.png) +![screenshot](https://raw.githubusercontent.com/cyberarm/i-mic-fps/master/screenshots/screenshot-game.png) ## Using Requires a Ruby runtime that supports the gosu and opengl-bindings C-extensions (truffleruby 1.0.0-rc12 did not work when tested. Rubinus was not tested.) diff --git a/assets/base/shared/sound/master.yaml b/assets/base/shared/sound/master.yaml new file mode 100644 index 0000000..75768ad --- /dev/null +++ b/assets/base/shared/sound/master.yaml @@ -0,0 +1,11 @@ +--- +playlists: + - menus: + - nighttime: + - daytime: +music: +sounds: + - + name: shield_regen + type: sfx + path: sfx/shield_regen.wav \ No newline at end of file diff --git a/assets/base/shared/sound/sfx/shield_regen.wav b/assets/base/shared/sound/sfx/shield_regen.wav new file mode 100644 index 0000000000000000000000000000000000000000..514c16af595858158875e6d5e37ae32248be2d41 GIT binary patch literal 1466 zcmaKsZD?C{6vl7*vbIUuCTZH`JvT|y#!lN}<^~f-rCX)Y7t}gCPIs`WotI>KxozJSDJ1UxHax7pTrtt*Or)b(yI%#2VZMbxD1xE)uq0x_8Br`htne z>N|B!UE#dM+>Clpy``qr`)s_b{!l*MtWE9JSJafss~?JQ7GE#kEdH#fPIgUKo-$9r zG5^x?#kJ9|vscgm;=8R~E%p7ePjkDszqWhwvEX3-sXO~$e0Jl&sI(Q17KRG7g*n+L zjj~~VZ>?LuTD6jpZt0U@*a7L19nuODm5?N*S?-gEBrgxkF7i&E!H0$q^|g(kOPc(|0;Ki`pz1W=)WR&p4ZMY_Zu^iGu{5BwbwYC)*y|8JDcYsO}=g z_Bd=5#PG-27{eXm$|1Bc&L}xb4#RCl3*m^+#Xy28?o_4(>4MZvxI!RIgdAtc$qn=Y zDnDEuJ|9~H)Iq#KBEYxkCjw41ayGEb4}4Vhzys%n@i`IT46?}&ywq-~C4265^^W3& ztCMP2w`@V(LVwp+OXVS|;cBFeTrO2qZeUN;IefWPih*iK1*aQ_hq)>?m7)J_{bT(J z?pWnaySYdE?rNBE$t~+P|Arf!zgu3m*}qqgZ^(mk*;=;Vu})d@)~3}aC*()T7Pc3D z;|X6m@b5EY`%et@3>14NA8F1{wKhes*B&;m-J01*uTOqey|!6O&42sB`n&n*w@+5+ zwECv_Q!%Mt=D(iSefp3d(U0q$I;;(SQ*Em2>W2DDmFY$u(ixr939?UnbQ$3SZe4}u z(-GZ-63`907S*F`fEV5eAJki&vq{%c*8p2-#2F(emPVI5^_gnlcz z!MQ@%xl#l+h8kx!?s!6+VIqo>;55-wAmQ|3?mdLljuds0r%5<4$w~YfkfzQu*#gr- zXV)f5T(`2xW->bGAPbY_J&=Jl;Zh*2x4}H1`+A=o%JJ6h9q1YC?d~6nQIAbb96i3P zqvPP8E;m|QTHf|gl$(voae^0)`u!|kQ>oO}{$0NDn?!o?kdK1{6 H|5@}Os(vf& literal 0 HcmV?d00001 diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 1f61304..adf7d3e 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -20,118 +20,35 @@ end Dir.chdir(File.dirname(__FILE__)) -require_relative "lib/ext/numeric" -require_relative "lib/ext/load_opengl" - include CyberarmEngine include OpenGL include GLU -require_relative "lib/version" -require_relative "lib/constants" -require_relative "lib/common_methods" +def require_all(directory) + files = Dir["#{directory}/**/*.rb"].sort! -require_relative "lib/trees/aabb_tree_debug" -require_relative "lib/trees/aabb_tree" -require_relative "lib/trees/aabb_node" + begin + failed = [] + first_name_error = nil -require_relative "lib/managers/input_mapper" -require_relative "lib/managers/entity_manager" -require_relative "lib/managers/light_manager" -require_relative "lib/managers/network_manager" -require_relative "lib/managers/collision_manager" -require_relative "lib/managers/physics_manager" + files.each do |file| + begin + require_relative file + rescue NameError => name_error + failed << file + first_name_error ||= name_error + end + end -require_relative "lib/renderer/renderer" -require_relative "lib/renderer/g_buffer" -require_relative "lib/renderer/opengl_renderer" -require_relative "lib/renderer/bounding_box_renderer" - -require_relative "lib/states/game_state" -require_relative "lib/ui/menu" - -require_relative "lib/ui/command" -require_relative "lib/ui/subcommand" -Dir.glob("#{IMICFPS::GAME_ROOT_PATH}/lib/ui/commands/*.rb").each do |cmd| - require_relative cmd + if failed.size == files.size + raise first_name_error + else + files = failed + end + end until( failed.empty? ) end -require_relative "lib/ui/console" -require_relative "lib/ui/menus/main_menu" -require_relative "lib/ui/menus/settings_menu" -require_relative "lib/ui/menus/extras_menu" -require_relative "lib/ui/menus/multiplayer_menu" -require_relative "lib/ui/menus/level_select_menu" -require_relative "lib/ui/menus/game_pause_menu" -require_relative "lib/states/game_states/boot" -require_relative "lib/states/game_states/close" -require_relative "lib/states/game_states/game" -require_relative "lib/states/game_states/loading_state" - -require_relative "lib/hud" -require_relative "lib/hud/widget" -require_relative "lib/hud/widgets/ammo" -require_relative "lib/hud/widgets/radar" -require_relative "lib/hud/widgets/health" - -require_relative "lib/subscription" -require_relative "lib/publisher" -require_relative "lib/event" -require_relative "lib/event_handler" -require_relative "lib/event_handlers/input" -require_relative "lib/event_handlers/entity_moved" -require_relative "lib/event_handlers/entity_lifecycle" - -require_relative "lib/scripting" -require_relative "lib/scripting/sandbox" -require_relative "lib/scripting/whitelist" - -require_relative "lib/component" -require_relative "lib/components/building" - -require_relative "lib/game_objects/entity" -require_relative "lib/game_objects/light" -require_relative "lib/game_objects/particle_emitter" - -require_relative "lib/game_objects/camera" -require_relative "lib/game_objects/entities/player" -require_relative "lib/game_objects/entities/skydome" -require_relative "lib/game_objects/entities/terrain" - -require_relative "lib/texture" -require_relative "lib/model" -require_relative "lib/model_cache" -require_relative "lib/model/parser" -require_relative "lib/model/model_object" -require_relative "lib/model/material" - -require_relative "lib/model/parsers/wavefront_parser" -require_relative "lib/model/parsers/collada_parser" - -require_relative "lib/map_parser" -require_relative "lib/manifest" -require_relative "lib/map" - -require_relative "lib/scene" -require_relative "lib/scenes/turn_table" - -require_relative "lib/crosshair" -require_relative "lib/demo" - -require_relative "lib/networking/director" -require_relative "lib/networking/packet_handler" -require_relative "lib/networking/client" -require_relative "lib/networking/server" -require_relative "lib/networking/connection" - -require_relative "lib/networking/backends/memory_server" -require_relative "lib/networking/backends/memory_connection" - -require_relative "lib/overlay" -require_relative "lib/window" - -require_relative "lib/tools/asset_viewer" -require_relative "lib/tools/map_editor" +require_all "lib" # Don't launch game if IMICFPS_SERVER_MODE is defined # or if game is being packaged @@ -167,4 +84,4 @@ unless prevent_launch?[0] end else puts prevent_launch?[1] -end \ No newline at end of file +end diff --git a/lib/managers/sound_manager.rb b/lib/managers/sound_manager.rb new file mode 100644 index 0000000..12628ef --- /dev/null +++ b/lib/managers/sound_manager.rb @@ -0,0 +1,53 @@ +class IMICFPS + module SoundManager + extend CyberarmEngine::Common + + MASTERS = {} + EFFECTS = [] + PLAYLISTS = {} + + def self.master_volume + 1.0 + end + + def self.music_volume + 0.25 * master_volume + end + + def self.sfx_volume + 0.5 * master_volume + end + + def self.load_master(package) + return if MASTERS.dig(package) + + yaml = YAML.load_file( "#{IMICFPS.assets_path}/#{package}/shared/sound/master.yaml" ) + MASTERS[package] = yaml + end + + def self.sound(package, name) + if data = sound_data(package, name.to_s) + get_sample("#{IMICFPS.assets_path}/#{package}/shared/sound/#{data["path"]}") + else + raise "Missing sound: '#{name}' in package '#{package}'" + end + end + + def self.sound_data(package, name) + load_master(package) + if master = MASTERS.dig(package) + return master["sounds"].find { |s| s["name"] == name } + end + + return nil + end + + def self.sound_effect(klass, options) + EFFECTS << klass.new(options) + end + + def self.update + EFFECTS.each { |e| e.update; EFFECTS.delete(e) if e.done? } + end + end +end \ No newline at end of file diff --git a/lib/overlay.rb b/lib/overlay.rb index a3048c1..ab5ddf4 100644 --- a/lib/overlay.rb +++ b/lib/overlay.rb @@ -29,7 +29,7 @@ class IMICFPS if window.config.get(:options, :fps) create_slot "FPS: #{Gosu.fps}" - create_slot "Frame time: #{Gosu.milliseconds - window.delta_time}ms" if window.config.get(:debug_options, :stats) + create_slot "Frame time: #{(Gosu.milliseconds - window.delta_time).to_s.rjust(3, "0")}ms" if window.config.get(:debug_options, :stats) end if window.config.get(:debug_options, :stats) diff --git a/lib/sound_effect.rb b/lib/sound_effect.rb new file mode 100644 index 0000000..04e0447 --- /dev/null +++ b/lib/sound_effect.rb @@ -0,0 +1,19 @@ +class IMICFPS + class SoundEffect + attr_reader :sound, :options + def initialize(options = {}) + raise "expected Hash, got #{options.class}" unless options.is_a?(Hash) + @options = options + + raise "sound not specified!" unless @options[:sound] + + setup + end + + def setup + end + + def update + end + end +end \ No newline at end of file diff --git a/lib/sound_effects/fade_in.rb b/lib/sound_effects/fade_in.rb new file mode 100644 index 0000000..5ddcd69 --- /dev/null +++ b/lib/sound_effects/fade_in.rb @@ -0,0 +1,32 @@ +class IMICFPS + class SoundEffect + class FadeIn < SoundEffect + def setup + @start_time = Gosu.milliseconds + @duration = @options[:duration] # in milliseconds + @initial_volume = @options[:volume] ? @options[:volume] : 0.0 + @sound = @options[:sound] + + raise "duration not specified!" unless @duration + + @channel = @sound.play(calculate_volume) + end + + def ratio + (Gosu.milliseconds - @start_time.to_f) / @duration + end + + def calculate_volume + volume = (SoundManager.sfx_volume - @initial_volume) * ratio + end + + def update + @channel.volume = calculate_volume + end + + def done? + (Gosu.milliseconds - @start_time.to_f) / @duration >= 1.0 + end + end + end +end \ No newline at end of file diff --git a/lib/sound_effects/fade_in_and_out.rb b/lib/sound_effects/fade_in_and_out.rb new file mode 100644 index 0000000..4a617d7 --- /dev/null +++ b/lib/sound_effects/fade_in_and_out.rb @@ -0,0 +1,22 @@ +class IMICFPS + class SoundEffect + class FadeInAndOut < FadeIn + def setup + @hang_time = @options[:hang_time] ? @options[:hang_time] : 0.0 + + super + end + + # TODO: Handle hang time + def ratio + r = super + + if r < 0.5 + r * 2 + else + 2.0 - (r * 2) + end + end + end + end +end \ No newline at end of file diff --git a/lib/sound_effects/fade_out.rb b/lib/sound_effects/fade_out.rb new file mode 100644 index 0000000..628bc77 --- /dev/null +++ b/lib/sound_effects/fade_out.rb @@ -0,0 +1,9 @@ +class IMICFPS + class SoundEffect + class FadeOut < FadeIn + def ratio + 1.0 - super + end + end + end +end \ No newline at end of file diff --git a/lib/sound_effects/shield_regen.rb b/lib/sound_effects/shield_regen.rb new file mode 100644 index 0000000..9d1b9f5 --- /dev/null +++ b/lib/sound_effects/shield_regen.rb @@ -0,0 +1,25 @@ +class IMICFPS + class SoundEffect + class ShieldRegen < SoundEffect + def setup + @sound = SoundManager.sound("base", :shield_regen) + @player = @options[:player] + + @channel = @sound.play(0.0, 0.0, true) + end + + def ratio + @player.health + end + + def update + @channel.speed = 0.5 + ratio / 2 + @channel.volume = 1.0 - ratio / 2 + end + + def done? + ratio >= 1.0 + end + end + end +end \ No newline at end of file diff --git a/lib/states/game_states/boot.rb b/lib/states/game_states/boot.rb index 50e3f07..aaa03b3 100644 --- a/lib/states/game_states/boot.rb +++ b/lib/states/game_states/boot.rb @@ -7,6 +7,7 @@ class IMICFPS @start_time = Gosu.milliseconds @time_to_live = 3_000 + # SoundManager.sound_effect(SoundEffect::FadeIn, sound: SoundManager.sound("base", :shield_regen), duration: 3_000.0) window.needs_cursor = false end @@ -32,6 +33,7 @@ class IMICFPS @title.draw + fill(Gosu::Color.rgba(0,0,0, 255 * (1.2 - fraction_left))) end end diff --git a/lib/window.rb b/lib/window.rb index 63a5d2b..985a8b9 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -68,6 +68,7 @@ class IMICFPS @console.update if @show_console @overlay.update + SoundManager.update @number_of_vertices = 0 @delta_time = Gosu.milliseconds