require 'singleton' include ShatteredState include ShatteredView include ShatteredModel module Shatter #:nodoc:all #This class is loads the view, controller, and model. It then loads #and starts the game based on these. class GameLoader include Singleton attr_writer :environment attr_reader :media_paths, :render_window, :input_manager, :key_manager, :key_converter attr_accessor :current_state # This will recourse into the app/** directories and load all ruby files # inside those directories. def load_all_sources(shattered_root) File.find_by_extension(shattered_root+"/app", "rb").each do |file| require(file) end end # start the game def run load_all_sources(SHATTERED_ROOT) load_environment # Create our initial state, as defined by the environment. create_state(@environment[:start_state]) start_game end # Create a state from the given name # :sample creates a new SampleState object def create_state(state_name) state_class = eval("#{state_name.to_s.camelize}State") raise Error, "#{state_class} is not a class" unless state_class.is_a? Class state = state_class.new unless state.is_a? ShatteredState::Base raise Error, "#{state_class} is an invalid State object (not of ShatteredState::Base)" end return state end def load_environment #Setup Ogre and the scene for the state raise Error, "Ogre failed to initialize" if !setup_ogre setup_input load_resources(@environment[:media]) end # Given ['app/media', 'media'], searches those directories, recursively, for OGRE media def load_resources(paths) @media_paths = paths # setup our resource paths specified in environment.rb Resources.instance.add_resource_paths(*paths) Resources.instance.setup end #Load the root, setup the render window #TODO: allow for the user to specify whether the window dialogue pops up #further TODO: allow the user to skin the render window dialogue def setup_ogre # TODO: create platform loader for other platforms plugins = SHATTERED_ROOT + "/config/ogre_plugins.windows.cfg" config_save=SHATTERED_ROOT + "/config/ogrerb_defaults.save" log=SHATTERED_ROOT + "/log/ogrerb.log" @root = ShatteredOgre.create_root(plugins, config_save, log) return false if !@root.show_config_dialog # TODO: allow application name to be set. @render_window = @root.initialise(true) return true end #Every time this exits, a game dies. def start_game each_frame do |time_elapsed| current_state.update_timers(time_elapsed) @keyboard.capture #@@environment[:input].flush end end # Main game loop def each_frame timer = Ogre::Timer.new while !@environment[:quit] && Ogre::Root::instance.render_one_frame seconds = timer.get_microseconds / 1000000.0 yield seconds timer.reset end end # Leave the game def quit! @environment[:quit]=true end # load the input manager, the key manager, etc # TODO: Consider how to make input non-exclusive, as well as mouse, etc. # TODO: Investigate any use cases for non-buffered input def setup_input windowHnd = render_window.get_custom_attribute_unsigned_long("WINDOW") @input_manager = OIS::InputManager.create_input_system( { "WINDOW" => "#{windowHnd}", "w32_mouse" => ["DISCL_FOREGROUND", "DISCL_NONEXCLUSIVE"], "w32_keyboard" => ["DISCL_FOREGROUND", "DISCL_NONEXCLUSIVE"] }) @keyboard = @input_manager.create_input_object(OIS::OISKeyboard, true) @key_manager = OIS::KeyManager.new(@keyboard) @key_converter = ShatteredPack::KeyConverter.new(@key_manager) end end end