diff --git a/lib/chingu/basic_game_object.rb b/lib/chingu/basic_game_object.rb new file mode 100644 index 0000000..f02f214 --- /dev/null +++ b/lib/chingu/basic_game_object.rb @@ -0,0 +1,102 @@ +module Chingu + # + # BasicGameObject. Resonating with 1.9.1, this is our most basic class that all game objects ultimate should build on. + # + # All objects that inherits from this class will by default be automaticly be updated and drawn. + # It will also acts as a container for the trait-system of chingu. + # + class BasicGameObject + attr_reader :options, :parent + + # + # adds a trait or traits to a certain game class + # + # Executes a ruby "include" the specified module + # + def self.has_trait(*traits) + has_traits(*traits) + end + + # + # See #has_trait + # + def self.has_traits(*traits) + Array(traits).each do |trait| + if trait.is_a?(::Symbol) || trait.is_a?(::String) + include Chingu::Traits.const_get(Chingu::Inflector.camelize(trait)) + end + end + end + + # + # BasicGameUnit initialize + # + # - caches all trait methods for fast calls later on + # - call .setup() on all traits that implements it + # - adds game object to correct game state or $window if no game state exists + # + def initialize(options = {}) + @options = options + + # + # A GameObject can either belong to a GameState or our mainwindow ($window) + # .. or live in limbo with manual updates + # + if $window && $window.respond_to?(:game_state_manager) + @parent = $window.game_state_manager.inside_state || $window + @parent.add_game_object(self) if @parent + end + + # This will call #setup on the latest trait mixed in, which then will pass it on with super. + setup_trait(options) + end + + + def setup_trait(options) + end + + def update + end + + def draw + end + + # + # Fetch all objects of a current class. + # Bullet.all # => Enumerator of all objects of class Bullet + # + # NOTE: ObjectSpace doesn't play nice with jruby. + # + def self.all + ObjectSpace.each_object(self) + end + + # + # Destroy all instances of current class that fills a certain condition + # Enemy.destroy_if(&:dead?) # Assumes Enemy.dead? returns true/false depending on aliveness :) + # + # + def self.destroy_if(&block) + all.each do |object| + object.destroy! if yield(object) + end + end + + # + # Clear all intances of objects class: + # Bullet.clear # Removes all Bullet objects from the game + # + def self.clear + all.each { |object| object.destroy! } + end + + # + # Removes object from the update cycle and freezes the object to prevent further modifications. + # If the object isn't being managed by Chingu (ie. you're doing manual update/draw calls) the object is only frozen, not removed from any updae cycle (because you are controlling that). + # + def destroy! + @parent.remove_game_object(self) if @parent + self.freeze + end + end +end \ No newline at end of file diff --git a/lib/chingu/game_states/debug.rb b/lib/chingu/game_states/debug.rb new file mode 100644 index 0000000..3390a99 --- /dev/null +++ b/lib/chingu/game_states/debug.rb @@ -0,0 +1,65 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +# +# Debug game state (F1 is default key to start/exit debug win, 'p' to pause game) +# +module Chingu + module GameStates + class Debug < Chingu::GameState + def initialize(options) + super + @white = Color.new(255,255,255,255) + @fade_color = Gosu::Color.new(100,255,255,255) + + @font = Gosu::Font.new($window, default_font_name, 15) + @paused = true + + self.input = {:p => :pause, :f1 => :return_to_game, :esc => :return_to_game} + end + + def return_to_game + game_state_manager.pop_game_state + end + + def pause + @paused = @paused ? false : true + end + + def update + game_state_manager.previous_game_state.update unless @paused + end + + def draw + game_state_manager.previous_game_state.draw + + $window.draw_quad( 0,0,@fade_color, + $window.width,0,@fade_color, + $window.width,$window.height,@fade_color, + 0,$window.height,@fade_color,10) + + text = "DEBUG CONSOLE" + @font.draw(text, $window.width - @font.text_width(text), @font.height, 999) + end + end + end +end diff --git a/lib/chingu/inflector.rb b/lib/chingu/inflector.rb new file mode 100644 index 0000000..4e8e2c6 --- /dev/null +++ b/lib/chingu/inflector.rb @@ -0,0 +1,34 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +module Chingu + module Inflector + def Inflector.camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) + if first_letter_in_uppercase + lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } + else + lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1] + end + end + + end +end \ No newline at end of file diff --git a/lib/chingu/require_all.rb b/lib/chingu/require_all.rb new file mode 100644 index 0000000..4a58fdd --- /dev/null +++ b/lib/chingu/require_all.rb @@ -0,0 +1,133 @@ +#-- +# Copyright (C)2009 Tony Arcieri +# You can redistribute this under the terms of the MIT license +# See file LICENSE for details +#++ + +module RequireAll + # A wonderfully simple way to load your code. + # + # The easiest way to use require_all is to just point it at a directory + # containing a bunch of .rb files. These files can be nested under + # subdirectories as well: + # + # require_all 'lib' + # + # This will find all the .rb files under the lib directory and load them. + # The proper order to load them in will be determined automatically. + # + # If the dependencies between the matched files are unresolvable, it will + # throw the first unresolvable NameError. + # + # You can also give it a glob, which will enumerate all the matching files: + # + # require_all 'lib/**/*.rb' + # + # It will also accept an array of files: + # + # require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file(f) } + # + # Or if you want, just list the files directly as arguments: + # + # require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb' + # + def require_all(*args) + # Handle passing an array as an argument + args.flatten! + + if args.size > 1 + # If we got a list, those be are files! + files = args + else + arg = args.first + begin + # Try assuming we're doing plain ol' require compat + stat = File.stat(arg) + + if stat.file? + files = [arg] + elsif stat.directory? + files = Dir.glob File.join(arg, '**', '*.rb') + else + raise ArgumentError, "#{arg} isn't a file or directory" + end + rescue Errno::ENOENT + # If the stat failed, maybe we have a glob! + files = Dir.glob arg + + # Maybe it's an .rb file and the .rb was omitted + if File.file?(arg + '.rb') + require(arg + '.rb') + return true + end + + # If we ain't got no files, the glob failed + raise LoadError, "no such file to load -- #{arg}" if files.empty? + end + end + + # If there's nothing to load, you're doing it wrong! + raise LoadError, "no files to load" if files.empty? + + files.map! { |file| File.expand_path file } + + begin + failed = [] + first_name_error = nil + + # Attempt to load each file, rescuing which ones raise NameError for + # undefined constants. Keep trying to successively reload files that + # previously caused NameErrors until they've all been loaded or no new + # files can be loaded, indicating unresolvable dependencies. + files.each do |file| + begin + require file + rescue NameError => ex + failed << file + first_name_error ||= ex + rescue ArgumentError => ex + # Work around ActiveSuport freaking out... *sigh* + # + # ActiveSupport sometimes throws these exceptions and I really + # have no idea why. Code loading will work successfully if these + # exceptions are swallowed, although I've run into strange + # nondeterministic behaviors with constants mysteriously vanishing. + # I've gone spelunking through dependencies.rb looking for what + # exactly is going on, but all I ended up doing was making my eyes + # bleed. + # + # FIXME: If you can understand ActiveSupport's dependencies.rb + # better than I do I would *love* to find a better solution + raise unless ex.message["is not missing constant"] + + STDERR.puts "Warning: require_all swallowed ActiveSupport 'is not missing constant' error" + STDERR.puts ex.backtrace[0..9] + end + end + + # If this pass didn't resolve any NameErrors, we've hit an unresolvable + # dependency, so raise one of the exceptions we encountered. + if failed.size == files.size + raise first_name_error + else + files = failed + end + end until failed.empty? + + true + end + + # Works like require_all, but paths are relative to the caller rather than + # the current working directory + def require_rel(*paths) + # Handle passing an array as an argument + paths.flatten! + + source_directory = File.dirname caller.first.sub(/:\d+$/, '') + paths.each do |path| + require_all File.join(source_directory, path) + end + end +end + +include RequireAll \ No newline at end of file diff --git a/lib/chingu/traits/collision_detection.rb b/lib/chingu/traits/collision_detection.rb new file mode 100644 index 0000000..302be4b --- /dev/null +++ b/lib/chingu/traits/collision_detection.rb @@ -0,0 +1,126 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +module Chingu + module Traits + # + # + # Use QuadTrees: http://lab.polygonal.de/2007/09/09/quadtree-demonstration/ + # + # Makes use of 3 attributes + # @bounding_box - a Rect-instance, uses in bounding_box collisions + # @radius - + # @detect_collisions - [true|false], should object be checked for collisions with Object.each_collision + # + module CollisionDetection + attr_accessor :bounding_box, :radius, :detect_collisions + + def self.included(base) + base.extend(ClassMethods) + end + + # + # Automaticly try to set a bounding_box and radius. Don't overwrite if they already exists. + # + def setup_trait(options) + if @x and @y and @image + @bounding_box ||= Rect.new(@x, @y, @image.width, @image.height) + end + + if @image + @radius ||= @image.width / 2 + end + + @detect_collisions = true + super + end + + # + # The standard method called when self needs to be checked for a collision with another object + # By default it calls bounding_box_collision? which will check for intersectons between the + # two objects "bounding_box" attributs (a Chingu::Rect instance) + # + def collision?(object2) + #bounding_box_collision?(object2) + radius_collision?(object2) + end + + # + # Collide self with a given game object by checking both objects bounding_box'es + # Returns true if colliding. + # + def bounding_box_collision?(object2) + self.bounding_box.collide_rect?(object2.bounding_box) + end + + # + # Collide self using distance between 2 objects and their radius. + # Returns true if colliding. + # + def radius_collision?(object2) + distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius + end + + # + # Have bounding box follow game objects x/y + # + def update + if defined?(@bounding_box) && @bounding_box.is_a?(Rect) + @bounding_box.x = self.x + @bounding_box.y = self.y + end + + super + end + + + module ClassMethods + # + # Class method that will check for collisions between all instances of two classes + # and yield the 2 colliding game object instances. + # + # It will not collide objects with themselves. + # + # example: + # + # Enemy.each_collision(Bullet).each do |enemy, bullet| enemy.die!; end + # + # + def each_collision(klasses = []) + # Make sure klasses is always an array. + Array(klasses).each do |klass| + self.all.each do |object1| + klass.all.each do |object2| + next if object1 == object2 # Don't collide objects with themselves + + if object1.detect_collisions && object2.detect_collisions + yield object1, object2 if object1.collision?(object2) + end + end + end + end + end + end + + end + end +end \ No newline at end of file diff --git a/lib/chingu/traits/effect.rb b/lib/chingu/traits/effect.rb new file mode 100644 index 0000000..3e94876 --- /dev/null +++ b/lib/chingu/traits/effect.rb @@ -0,0 +1,109 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +module Chingu + module Traits + module Effect + # + # Adds .rotating .fading and .zooming to any GameObject. + # + # TODO: better naming? suggestions: + # + # basic gosu unit <-> automation name + # ============================================== + # angle <-> rotation? rotating? automatic_angle? + # factor <-> growth? scale? automatic_zoom? + # alpha <-> fade + # + attr_accessor :rotating, :fading, :zooming + + #def self.initialize_trait(options) + # @effect_options = {:debug => false}.merge(options) + # puts "Effect#initialize" if @effect_options[:debug] + # super + #end + + # + # Setup + # + def setup_trait(options) + @effect_options = {:debug => false}.merge(options) + + @rotating = options[:rotating] || nil + @zooming = options[:zooming] || nil + @fading = options[:fading] || nil + super + end + + def draw + super + end + + def update + rotate(@rotating) if @rotating + fade(@fading) if @fading + zoom(@zooming) if @zooming + super + end + + # Zoom - increase @factor_x and @factor_y at the same time. + def zoom(amount = 0.1) + @factor_x += amount + @factor_y += amount + end + + # Zoom Out - decrease @factor_x and @factor_y at the same time. + def zoom_out(amount = 0.1) + @factor_x -= amount + @factor_y -= amount + end + + # Rotate object 'amount' degrees + def rotate(amount = 1) + @angle += amount + end + + # Fade object by decreasing/increasing color.alpha + def fade(amount = 1) + return if amount == 0 + + new_alpha = @color.alpha + amount + if amount < 0 + @color.alpha = [0, new_alpha].max + else + @color.alpha = [0, new_alpha].min + end + end + + # Fade out objects color by decreasing color.alpha + def fade_out(amount = 1) + fade(-amount) + end + + # Fade in objects color by increasing color.alpha + def fade_in(amount = 1) + fade(amount) + end + + end + end +end \ No newline at end of file diff --git a/lib/chingu/traits/input.rb b/lib/chingu/traits/input.rb new file mode 100644 index 0000000..590e8ef --- /dev/null +++ b/lib/chingu/traits/input.rb @@ -0,0 +1,38 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +module Chingu + module Traits + module Input + + def input=(input_map) + @input = input_map + @parent.add_input_client(self) if @parent + end + + def input + @input + end + + end + end +end \ No newline at end of file diff --git a/lib/chingu/traits/rotation_center.rb b/lib/chingu/traits/rotation_center.rb new file mode 100644 index 0000000..28795dd --- /dev/null +++ b/lib/chingu/traits/rotation_center.rb @@ -0,0 +1,84 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +module Chingu + module Traits + module RotationCenter + # + # returns [center_x, center_y] (see Gosu::Image#draw_rot) + # + @@rotation_centers = { + :top_left => [0,0], + :left_top => [0,0], + + :center_left => [0,0.5], + :middle_left => [0,0.5], + :left_center => [0,0.5], + :left_middle => [0,0.5], + + :bottom_left => [0,1], + :left_bottom => [0,1], + + :top_center => [0.5,0], + :top_middle => [0.5,0], + :center_top => [0.5,0], + :middle_top => [0.5,0], + + :center_center => [0.5,0.5], + :middle_middle => [0.5,0.5], + :center => [0.5,0.5], + :middle => [0.5,0.5], + + :bottom_center => [0.5,1], + :bottom_middle => [0.5,1], + :center_bottom => [0.5,1], + :middle_bottom => [0.5,1], + + :top_right => [1,0], + :right_top => [1,0], + + :center_right => [1,0.5], + :middle_right => [1,0.5], + :right_center => [1,0.5], + :right_middle => [1,0.5], + + :bottom_right => [1,1], + :right_bottom => [1,1] + } + + # + # Sets @center_x and @center_y according to given alignment. Available alignments are: + # + # :top_left, :center_left, :bottom_left, :top_center, + # :center_center, :bottom_center, :top_right, :center_right and :bottom_right + # + # They're also available in the opposite order with the same meaning. + # They're also available (hey, hashlookups are speedy) with "middle" instead of "center" since + # those 2 words basicly have the same meaning and are both understandable. + # + def rotation_center(alignment) + @center_x, @center_y = @@rotation_centers[alignment.to_sym] + end + + end + end +end \ No newline at end of file diff --git a/lib/chingu/traits/velocity.rb b/lib/chingu/traits/velocity.rb new file mode 100644 index 0000000..b94dca4 --- /dev/null +++ b/lib/chingu/traits/velocity.rb @@ -0,0 +1,67 @@ +#-- +# +# Chingu -- Game framework built on top of the opengl accelerated gamelib Gosu +# Copyright (C) 2009 ippa / ippa@rubylicio.us +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +#++ + + +module Chingu + module Traits + # + # A chingu trait providing velocity and acceleration logic. + # + module Velocity + attr_accessor :velocity_x, :velocity_y, :acceleration_x, :acceleration_y, :max_velocity + + #def self.initialize_trait(options) + # @velocity_options = {:debug => false}.merge(options) + # puts "Velocity#initialize" if @velocity_options[:debug] + # super + #end + + def setup_trait(options) + @velocity_options = {:debug => false}.merge(options) + puts "Velocity#setup" if @velocity_options[:debug] + + @velocity_x = options[:velocity_x] || 0 + @velocity_y = options[:velocity_y] || 0 + @acceleration_x = options[:acceleration_x] || 0 + @acceleration_y = options[:acceleration_y] || 0 + @max_velocity = options[:max_velocity] || 1000 + super + end + + # + # Modifies X & Y of parent + # + def update + puts "Velocity#update" if @velocity_options[:debug] + + @velocity_y += @acceleration_y if (@velocity_y + @acceleration_y).abs < @max_velocity + @velocity_x += @acceleration_x if (@velocity_x + @acceleration_x).abs < @max_velocity + @y += @velocity_y + @x += @velocity_x + super + end + + def stop + @acceleration_y = @acceleration_x = @velocity_y = @acceleration_y = 0 + end + end + end +end \ No newline at end of file diff --git a/readme.rdoc b/readme.rdoc index 0bfd70b..49cf807 100644 --- a/readme.rdoc +++ b/readme.rdoc @@ -12,7 +12,3 @@ fynal?! Ruby 1.8+ / 1.9+ gem install gosu gem install ippa-chingu - - - - \ No newline at end of file diff --git a/src/intro_state.rb b/src/intro_state.rb index ce654a7..7dd19e2 100644 --- a/src/intro_state.rb +++ b/src/intro_state.rb @@ -9,11 +9,7 @@ def initialize "...something, a feeling ... I haven't felt in ages..." ].reverse - self.input = { :space => :start_game, :esc => :exit } - end - - def start_game - switch_game_state(Cavern.new) + self.input = { :space => Cavern, :esc => :exit } end def update @@ -31,14 +27,9 @@ def update if ($window.ticks % 2) == 0 @text.color.alpha -= 1 if @text.color.alpha > 0 end - #@text.fade(-1) if ($window.ticks % 2) == 0 end def setup Song["the_eternally_grey_1.ogg"].play(true) end - - #def finalize - # Song.current_song.stop - #end end diff --git a/src/my_game_object.rb b/src/my_game_object.rb index 9050e91..8ec1a11 100644 --- a/src/my_game_object.rb +++ b/src/my_game_object.rb @@ -7,7 +7,7 @@ class MyGameObject < Chingu::GameObject attr_accessor :status, :zorder def initialize(options) - super + super(options.merge({:debug => false})) @center_y = 1 @velocity = 0 @velocity_x = 0 diff --git a/the_eternally_grey.rb b/the_eternally_grey.rb index 5a60e1e..e779be3 100644 --- a/the_eternally_grey.rb +++ b/the_eternally_grey.rb @@ -5,24 +5,16 @@ # $stderr.sync = $stdout.sync = true ROOT_PATH = File.dirname(File.expand_path(__FILE__)) -ENV["RUBYOPT"] = nil -#require 'rubygems' - -begin - require 'gosu' -rescue - require File.join(ROOT_PATH, 'lib', 'gosu.for_1_9.so') -end +require 'gosu' require 'chingu' -#require File.join(ROOT_PATH, 'lib', 'chingu') + +#require '../chingu/lib/chingu.rb' + include Gosu include Chingu -%w{my_game_object enemies cave_objects core_extensions game_over_state intro_state menu_state cavern_state}.each do |file| - require File.join(ROOT_PATH, "src", file) -end - +require_all "#{ROOT_PATH}/src" class Game < Chingu::Window def initialize