Skip to content

Commit

Permalink
see last commitmsg
Browse files Browse the repository at this point in the history
  • Loading branch information
ippa committed Sep 17, 2009
1 parent e908b8e commit 2ee823b
Show file tree
Hide file tree
Showing 13 changed files with 765 additions and 28 deletions.
102 changes: 102 additions & 0 deletions 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
65 changes: 65 additions & 0 deletions 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
34 changes: 34 additions & 0 deletions 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
133 changes: 133 additions & 0 deletions 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

0 comments on commit 2ee823b

Please sign in to comment.