chingu 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data.tar.gz.sig CHANGED
Binary file
@@ -35,6 +35,7 @@ examples/media/Parallax-scroll-example-layer-3.png
35
35
  examples/media/background1.png
36
36
  examples/media/bullet.png
37
37
  examples/media/bullet_hit.wav
38
+ examples/media/circle.png
38
39
  examples/media/city1.csv
39
40
  examples/media/city1.png
40
41
  examples/media/city2.png
@@ -47,6 +48,7 @@ examples/media/laser.wav
47
48
  examples/media/particle.png
48
49
  examples/media/plane.csv
49
50
  examples/media/plane.png
51
+ examples/media/rect.png
50
52
  examples/media/ruby.png
51
53
  examples/media/saucer.csv
52
54
  examples/media/saucer.gal
@@ -60,7 +62,7 @@ lib/chingu.rb
60
62
  lib/chingu/animation.rb
61
63
  lib/chingu/assets.rb
62
64
  lib/chingu/basic_game_object.rb
63
- lib/chingu/core_extensions.rb
65
+ lib/chingu/core_ext/array.rb
64
66
  lib/chingu/fpscounter.rb
65
67
  lib/chingu/game_object.rb
66
68
  lib/chingu/game_object_list.rb
@@ -70,6 +72,8 @@ lib/chingu/game_states/debug.rb
70
72
  lib/chingu/game_states/edit.rb
71
73
  lib/chingu/game_states/fade_to.rb
72
74
  lib/chingu/game_states/pause.rb
75
+ lib/chingu/gosu_ext/image.rb
76
+ lib/chingu/helpers/class_inheritable_accessor.rb
73
77
  lib/chingu/helpers/game_object.rb
74
78
  lib/chingu/helpers/game_state.rb
75
79
  lib/chingu/helpers/gfx.rb
@@ -86,9 +90,9 @@ lib/chingu/rect.rb
86
90
  lib/chingu/require_all.rb
87
91
  lib/chingu/text.rb
88
92
  lib/chingu/traits/bounding_box.rb
93
+ lib/chingu/traits/bounding_circle.rb
89
94
  lib/chingu/traits/collision_detection.rb
90
95
  lib/chingu/traits/effect.rb
91
- lib/chingu/traits/radius.rb
92
96
  lib/chingu/traits/retrofy.rb
93
97
  lib/chingu/traits/timer.rb
94
98
  lib/chingu/traits/velocity.rb
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{chingu}
5
- s.version = "0.6.1"
5
+ s.version = "0.6.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["ippa"]
9
- s.date = %q{2009-11-22}
9
+ s.date = %q{2009-11-25}
10
10
  s.description = %q{OpenGL accelerated 2D game framework for Ruby.
11
11
  Builds on the awesome Gosu (Ruby/C++) which provides all the core functionality.
12
12
  It adds simple yet powerful game states, prettier input handling, deployment safe asset-handling, a basic re-usable game object and automation of common task.}
13
13
  s.email = ["ippa@rubylicio.us"]
14
14
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "benchmarks/README.txt"]
15
- s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "benchmarks/README.txt", "benchmarks/benchmark.rb", "benchmarks/benchmark3.rb", "benchmarks/benchmark4.rb", "benchmarks/benchmark5.rb", "benchmarks/benchmark6.rb", "benchmarks/meta_benchmark.rb", "benchmarks/meta_benchmark2.rb", "chingu.gemspec", "examples/example1.rb", "examples/example10.rb", "examples/example11.rb", "examples/example12.rb", "examples/example13.rb", "examples/example14.rb", "examples/example2.rb", "examples/example3.rb", "examples/example4.rb", "examples/example5.rb", "examples/example6.rb", "examples/example7.rb", "examples/example8.rb", "examples/example9.rb", "examples/game1.rb", "examples/high_score_list.yml", "examples/media/Parallax-scroll-example-layer-0.png", "examples/media/Parallax-scroll-example-layer-1.png", "examples/media/Parallax-scroll-example-layer-2.png", "examples/media/Parallax-scroll-example-layer-3.png", "examples/media/background1.png", "examples/media/bullet.png", "examples/media/bullet_hit.wav", "examples/media/city1.csv", "examples/media/city1.png", "examples/media/city2.png", "examples/media/droid.bmp", "examples/media/enemy_bullet.png", "examples/media/explosion.wav", "examples/media/fire_bullet.png", "examples/media/fireball.png", "examples/media/laser.wav", "examples/media/particle.png", "examples/media/plane.csv", "examples/media/plane.png", "examples/media/ruby.png", "examples/media/saucer.csv", "examples/media/saucer.gal", "examples/media/saucer.png", "examples/media/spaceship.png", "examples/media/stickfigure.bmp", "examples/media/stickfigure.png", "examples/media/video_games.png", "examples/media/wood.png", "lib/chingu.rb", "lib/chingu/animation.rb", "lib/chingu/assets.rb", "lib/chingu/basic_game_object.rb", "lib/chingu/core_extensions.rb", "lib/chingu/fpscounter.rb", "lib/chingu/game_object.rb", "lib/chingu/game_object_list.rb", "lib/chingu/game_state.rb", "lib/chingu/game_state_manager.rb", "lib/chingu/game_states/debug.rb", "lib/chingu/game_states/edit.rb", "lib/chingu/game_states/fade_to.rb", "lib/chingu/game_states/pause.rb", "lib/chingu/helpers/game_object.rb", "lib/chingu/helpers/game_state.rb", "lib/chingu/helpers/gfx.rb", "lib/chingu/helpers/input_client.rb", "lib/chingu/helpers/input_dispatcher.rb", "lib/chingu/helpers/rotation_center.rb", "lib/chingu/high_score_list.rb", "lib/chingu/inflector.rb", "lib/chingu/input.rb", "lib/chingu/named_resource.rb", "lib/chingu/parallax.rb", "lib/chingu/particle.rb", "lib/chingu/rect.rb", "lib/chingu/require_all.rb", "lib/chingu/text.rb", "lib/chingu/traits/bounding_box.rb", "lib/chingu/traits/collision_detection.rb", "lib/chingu/traits/effect.rb", "lib/chingu/traits/radius.rb", "lib/chingu/traits/retrofy.rb", "lib/chingu/traits/timer.rb", "lib/chingu/traits/velocity.rb", "lib/chingu/window.rb"]
15
+ s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "benchmarks/README.txt", "benchmarks/benchmark.rb", "benchmarks/benchmark3.rb", "benchmarks/benchmark4.rb", "benchmarks/benchmark5.rb", "benchmarks/benchmark6.rb", "benchmarks/meta_benchmark.rb", "benchmarks/meta_benchmark2.rb", "chingu.gemspec", "examples/example1.rb", "examples/example10.rb", "examples/example11.rb", "examples/example12.rb", "examples/example13.rb", "examples/example14.rb", "examples/example2.rb", "examples/example3.rb", "examples/example4.rb", "examples/example5.rb", "examples/example6.rb", "examples/example7.rb", "examples/example8.rb", "examples/example9.rb", "examples/game1.rb", "examples/high_score_list.yml", "examples/media/Parallax-scroll-example-layer-0.png", "examples/media/Parallax-scroll-example-layer-1.png", "examples/media/Parallax-scroll-example-layer-2.png", "examples/media/Parallax-scroll-example-layer-3.png", "examples/media/background1.png", "examples/media/bullet.png", "examples/media/bullet_hit.wav", "examples/media/circle.png", "examples/media/city1.csv", "examples/media/city1.png", "examples/media/city2.png", "examples/media/droid.bmp", "examples/media/enemy_bullet.png", "examples/media/explosion.wav", "examples/media/fire_bullet.png", "examples/media/fireball.png", "examples/media/laser.wav", "examples/media/particle.png", "examples/media/plane.csv", "examples/media/plane.png", "examples/media/rect.png", "examples/media/ruby.png", "examples/media/saucer.csv", "examples/media/saucer.gal", "examples/media/saucer.png", "examples/media/spaceship.png", "examples/media/stickfigure.bmp", "examples/media/stickfigure.png", "examples/media/video_games.png", "examples/media/wood.png", "lib/chingu.rb", "lib/chingu/animation.rb", "lib/chingu/assets.rb", "lib/chingu/basic_game_object.rb", "lib/chingu/core_ext/array.rb", "lib/chingu/fpscounter.rb", "lib/chingu/game_object.rb", "lib/chingu/game_object_list.rb", "lib/chingu/game_state.rb", "lib/chingu/game_state_manager.rb", "lib/chingu/game_states/debug.rb", "lib/chingu/game_states/edit.rb", "lib/chingu/game_states/fade_to.rb", "lib/chingu/game_states/pause.rb", "lib/chingu/gosu_ext/image.rb", "lib/chingu/helpers/class_inheritable_accessor.rb", "lib/chingu/helpers/game_object.rb", "lib/chingu/helpers/game_state.rb", "lib/chingu/helpers/gfx.rb", "lib/chingu/helpers/input_client.rb", "lib/chingu/helpers/input_dispatcher.rb", "lib/chingu/helpers/rotation_center.rb", "lib/chingu/high_score_list.rb", "lib/chingu/inflector.rb", "lib/chingu/input.rb", "lib/chingu/named_resource.rb", "lib/chingu/parallax.rb", "lib/chingu/particle.rb", "lib/chingu/rect.rb", "lib/chingu/require_all.rb", "lib/chingu/text.rb", "lib/chingu/traits/bounding_box.rb", "lib/chingu/traits/bounding_circle.rb", "lib/chingu/traits/collision_detection.rb", "lib/chingu/traits/effect.rb", "lib/chingu/traits/retrofy.rb", "lib/chingu/traits/timer.rb", "lib/chingu/traits/velocity.rb", "lib/chingu/window.rb"]
16
16
  s.homepage = %q{http://github.com/ippa/chingu/tree/master}
17
17
  s.rdoc_options = ["--main", "README.rdoc"]
18
18
  s.require_paths = ["lib"]
@@ -4,121 +4,102 @@ include Gosu
4
4
  include Chingu
5
5
 
6
6
  #
7
- # Demonstrating Chingus HighScoreList-class
8
- # I couldn't keep myself from spicying it up some though :P
7
+ # Demonstrating Chingutrait radius, bounding_box and collision_detection.
9
8
  #
10
9
  class Game < Chingu::Window
11
10
  def initialize
12
11
  super(640,400)
13
- self.input = {:esc => :exit, :space => :remote_high_score, :a => :add}
14
- self.caption = "Example of Chingus HighScore class. Press Space to go to fetch high scores remotely!"
12
+ self.input = {:esc => :exit, :q => :decrease_size, :w => :increase_size, :a => :decrease_speed, :s => :increase_speed}
15
13
 
16
- @title = PulsatingText.create("HIGH SCORES", :x => $window.width/2, :y => 50, :size => 70)
14
+ 10.times { Circle.create(:x => width/2, :y => height/2) }
15
+ 10.times { Box.create(:x => width/2, :y => height/2) }
16
+ @blue = Color.new(0xFF0000FF)
17
+ @white = Color.new(0xFFFFFFFF)
18
+ end
19
+
20
+ def increase_size
21
+ game_objects.each { |go| go.factor += 1 }
22
+ end
23
+ def decrease_size
24
+ game_objects.each { |go| go.factor -= 1 if go.factor > 1 }
25
+ end
26
+ def increase_speed
27
+ game_objects.each { |go| go.velocity_x *= 1.2; go.velocity_y *= 1.2; }
28
+ end
29
+ def decrease_speed
30
+ game_objects.each { |go| go.velocity_x *= 0.8; go.velocity_y *= 0.8; }
31
+ end
32
+
33
+ def update
34
+ super
17
35
 
18
- #
19
- # Load a list from disk, defaults to "high_score_list.yml"
20
- # Argument :size forces list to this size
21
- #
22
- @high_score_list = HighScoreList.load(:size => 10)
36
+ game_objects.each { |go| go.color = @white }
23
37
 
24
38
  #
25
- # Add some new high scores to the list. :name and :score are required but you can put whatever.
26
- # They will mix with the old scores, automatic default sorting on :score
39
+ # Collide Boxes/Circles, Boxes/Boxes and Circles/Circles (basicly all objects on screen)
27
40
  #
28
- 10.times do
29
- data = {:name => "NEW", :score => rand(10000)}
30
-
31
- position = @high_score_list.add(data)
32
- if position
33
- puts "#{data[:name]} - #{data[:score]} got position #{position}"
34
- else
35
- puts "#{data[:name]} - #{data[:score]} didn't make it"
36
- end
37
- end
38
-
39
- create_text
40
-
41
- # @high_score_list.save_to_file # Uncomment to save list to disk
42
- end
43
-
44
- def remote_high_score
45
- game_objects.destroy_all
46
-
47
- @title = PulsatingText.create("REMOTE WEBSERVICE HIGH SCORES", :x => $window.width/2, :y => 50, :size => 30)
41
+ [Box, Circle].each_collision(Box, Circle) { |o, o2| o.color, o2.color = @blue, @blue }
48
42
 
49
43
  #
50
- # :game_id is the unique ID the game has on www.gamercv.com
51
- # :user is the login for that specific game (set by owner)
52
- # :password is the password for that specific game (set by owner)
44
+ # Only collide boxes with other boxes
53
45
  #
54
- # To read a high score list only :game_id is required
55
- # To write to a high score list :user and :password is required as well
46
+ ## Box.each_collision(Box) { |o, o2| o.color, o2.color = @blue, @blue }
47
+
56
48
  #
57
- @high_score_list = HighScoreList.load_remote(:game_id => 1, :user => "chingu", :password => "chingu", :size => 10)
58
- create_text
59
- end
60
-
61
- def add
62
- data = {:name => "NEW", :score => 1600}
63
- position = @high_score_list.add(data)
64
- puts "Got position: #{position.to_s}"
65
- create_text
66
- end
67
-
68
- def create_text
69
- @score_texts ||= []
70
- @score_texts.each { |text| text.destroy }
71
-
49
+ # Only collide circles with other circles
72
50
  #
73
- # Iterate through all high scores and create the visual represenation of it
51
+ ## Circle.each_collision(Circle) { |o, o2| o.color, o2.color = @blue, @blue }
52
+
74
53
  #
75
- @high_score_list.each_with_index do |high_score, index|
76
- y = index * 25 + 100
77
- @score_texts << Text.create(high_score[:name], :x => 200, :y => y, :size => 20)
78
- @score_texts << Text.create(high_score[:score], :x => 400, :y => y, :size => 20)
79
- end
80
-
81
- 5.times do
82
- score = rand(20000)
83
- puts "position for possible score #{score}: #{@high_score_list.position_by_score(score)}"
84
- end
54
+ # Only collide Boxes with Boxes and Circles
55
+ #
56
+ ## Box.each_collision(Box,Circle) { |o, o2| o.color, o2.color = @blue, @blue }
57
+
58
+ self.caption = "traits bounding_box/circle & collision_detection. Q/W: Size. A/S: Speed. FPS: #{fps} Objects: #{game_objects.size}"
85
59
  end
86
-
87
60
  end
88
61
 
89
- #
90
- # colorful pulsating text...
91
- #
92
- class PulsatingText < Text
93
- has_traits :timer, :effect
94
- @@red = Color.new(0xFFFF0000)
95
- @@green = Color.new(0xFF00FF00)
96
- @@blue = Color.new(0xFF0000FF)
62
+ class Circle < GameObject
63
+ has_trait :bounding_circle, :debug => true
64
+ has_traits :velocity, :collision_detection
97
65
 
98
- def initialize(text, options = {})
99
- super(text, options)
66
+ def initialize(options)
67
+ super
68
+ @image = Image["circle.png"]
69
+ self.velocity_x = 3 - rand * 6
70
+ self.velocity_y = 3 - rand * 6
71
+ self.factor = 2
100
72
 
101
- options = text if text.is_a? Hash
102
- @pulse = options[:pulse] || false
103
- self.rotation_center(:center_center)
104
- every(20) { create_pulse } if @pulse == false
73
+ self.input = [:holding_left, :holding_right, :holding_down, :holding_up]
105
74
  end
106
75
 
107
- def create_pulse
108
- pulse = PulsatingText.create(@text, :x => @x, :y => @y, :height => @height, :pulse => true, :image => @image, :zorder => @zorder+1)
109
- colors = [@@red, @@green, @@blue]
110
- pulse.color = colors[rand(colors.size)].dup
111
- pulse.mode = :additive
112
- pulse.alpha -= 150
113
- pulse.scale_rate = 0.002
114
- pulse.fade_rate = -3 + rand(2)
115
- pulse.rotation_rate = rand(2)==0 ? 0.05 : -0.05
116
- end
117
-
76
+ def holding_left; @x -= 1; end
77
+ def holding_right; @x += 1; end
78
+ def holding_down; @y += 1; end
79
+ def holding_up; @y -= 1; end
80
+
118
81
  def update
119
- destroy if self.alpha == 0
82
+ self.velocity_x = -self.velocity_x if @x < 0 || @x > $window.width
83
+ self.velocity_y = -self.velocity_y if @y < 0 || @y > $window.height
120
84
  end
85
+ end
86
+
87
+ class Box < GameObject
88
+ has_trait :bounding_box, :debug => true
89
+ has_traits :velocity, :collision_detection
121
90
 
91
+ def initialize(options)
92
+ super
93
+ @image = Image["rect.png"]
94
+ self.velocity_x = 3 - rand * 6
95
+ self.velocity_y = 3 - rand * 6
96
+ self.factor = 2
97
+ end
98
+
99
+ def update
100
+ self.velocity_x = -self.velocity_x if @x < 0 || @x > $window.width
101
+ self.velocity_y = -self.velocity_y if @y < 0 || @y > $window.height
102
+ end
122
103
  end
123
104
 
124
- Game.new.show
105
+ Game.new.show
@@ -79,7 +79,7 @@ class Particles < Chingu::GameState
79
79
  @yellow = Color.new(0xFFF9F120)
80
80
 
81
81
  # Thanks jsb in #gosu of Encave-fame for fireball.png :)
82
- @fireball_animation = Chingu::Animation.new(:file => media_path("fireball.png"), :width => 32, :height => 32)
82
+ @fireball_animation = Chingu::Animation.new(:file => media_path("fireball.png"), :size => [32,32])
83
83
  @ground_y = $window.height * 0.95
84
84
  end
85
85
 
@@ -12,7 +12,6 @@ class Game < Chingu::Window
12
12
  self.input = {:esc => :exit}
13
13
  self.caption = "Example of game object traits 'velocity' and 'effect'"
14
14
  push_game_state(Particles)
15
- puts RUBY_VERSION
16
15
  end
17
16
 
18
17
  def next_effect; pop_game_state; end
@@ -131,7 +131,7 @@ end
131
131
  #
132
132
  class Player < GameObject
133
133
  has_traits :velocity, :collision_detection, :timer
134
- has_trait :radius, :scale => 0.50, :debug => true
134
+ has_trait :bounding_circle, :scale => 0.50, :debug => true
135
135
 
136
136
  attr_accessor :score
137
137
 
Binary file
Binary file
@@ -25,10 +25,15 @@ ROOT = File.dirname(File.expand_path($0))
25
25
  require 'rubygems' unless RUBY_VERSION =~ /1\.9/
26
26
  require 'gosu'
27
27
  require File.join(CHINGU_ROOT,"chingu","require_all") # Thanks to http://github.com/tarcieri/require_all !
28
+
29
+ # Seems like we need to include chingu/helpers first for BasicGameObject
30
+ # and GameObject to get the correct class_inheritable_accssor
31
+ require_all "#{CHINGU_ROOT}/chingu/helpers"
32
+ require_all "#{CHINGU_ROOT}/chingu/traits"
28
33
  require_all "#{CHINGU_ROOT}/chingu"
29
34
 
30
35
  module Chingu
31
- VERSION = "0.6.1"
36
+ VERSION = "0.6.2"
32
37
 
33
38
  DEBUG_COLOR = Gosu::Color.new(0xFFFF0000)
34
39
  DEBUG_ZORDER = 9999
@@ -1,3 +1,4 @@
1
+ require_rel 'helpers/class_inheritable_accessor'
1
2
  module Chingu
2
3
  #
3
4
  # BasicGameObject. Resonating with 1.9.1, this is our most basic class that all game objects ultimate should build on.
@@ -6,19 +7,23 @@ module Chingu
6
7
  # It will also acts as a container for the trait-system of chingu.
7
8
  #
8
9
  class BasicGameObject
10
+ include Chingu::ClassInheritableAccessor
11
+
9
12
  attr_reader :options, :paused, :visible
10
13
  attr_accessor :parent
11
14
 
12
- def self.trait_options; @trait_options; end
15
+ class_inheritable_accessor :trait_options
16
+ @trait_options = Hash.new
13
17
  def trait_options; self.class.trait_options; end
14
-
18
+
15
19
  #
16
20
  # Adds a trait or traits to a certain game class
17
21
  # Executes a standard ruby "include" the specified module
18
22
  #
19
23
  def self.has_trait(trait, options = {})
20
- @trait_options ||= Hash.new
24
+
21
25
  if trait.is_a?(::Symbol) || trait.is_a?(::String)
26
+ ## puts "has_trait #{trait}, #{options}"
22
27
  begin
23
28
  # Convert user-given symbol (eg. :timer) to a Module (eg. Chingu::Traits::Timer)
24
29
  mod = Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
@@ -26,14 +31,21 @@ module Chingu
26
31
  # Include the module, which will add the containing methods as instance methods
27
32
  include mod
28
33
 
29
- # Add possible classmethods defined in sub-module ClassMethods (eg: Chingu::Traits::Timer::ClassMethods)
30
- mod2 = mod.const_get("ClassMethods")
31
- extend mod2
34
+ # Does sub-module "ClessMethods" exists?
35
+ # (eg: Chingu::Traits::Timer::ClassMethods)
36
+ if mod.const_defined?("ClassMethods")
37
+ # Add methods in scope ClassMethods as.. class methods!
38
+ mod2 = mod.const_get("ClassMethods")
39
+ extend mod2
32
40
 
33
- # If the newly included trait has a initialize_trait method...
34
- # ... call it with the options provided with the has_trait-call
35
- initialize_trait(options) if mod2.method_defined?(:initialize_trait)
41
+ # If the newly included trait has a initialize_trait method in the ClassMethods-scope:
42
+ # ... call it with the options provided with the has_trait-line.
43
+ if mod2.method_defined?(:initialize_trait)
44
+ initialize_trait(options)
45
+ end
46
+ end
36
47
  rescue
48
+ puts $!
37
49
  end
38
50
  end
39
51
  end
@@ -0,0 +1,12 @@
1
+ class Array
2
+ def each_collision(*args)
3
+ list = (self + args).uniq
4
+ collide_pair = []
5
+ list.each_with_index { |nr, i| self[i..size].collect { |nr2| collide_pair << [nr,nr2] } }
6
+ collide_pair.each do |class1,class2|
7
+ class1.each_collision(class2) do |object1, object2|
8
+ yield object1, object2
9
+ end
10
+ end
11
+ end
12
+ end
@@ -19,13 +19,17 @@
19
19
  #
20
20
  #++
21
21
 
22
-
22
+ require_rel 'helpers/*'
23
23
  module Chingu
24
24
  #
25
- # GameObject is our BasisGameObject (class with framespecific stuff)
25
+ # GameObject inherits from BasicGameObject to get traits and some class-methods like .all and .destroy
26
26
  #
27
27
  # On top of that, it encapsulates GOSUs Image#draw_rot and all its parameters.
28
28
  #
29
+ # In Chingu GameObject is a visual object, something to put on screen, centers around the .image-parameter.
30
+ #
31
+ # If you wan't a invisible object but with traits, use BasicGameObject.
32
+ #
29
33
  class GameObject < Chingu::BasicGameObject
30
34
  attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :color, :mode, :zorder
31
35
  attr_reader :factor, :center#, :rotation_center
@@ -71,8 +75,8 @@ module Chingu
71
75
 
72
76
  @mode = options[:mode] || :default # :additive is also available.
73
77
  @zorder = options[:zorder] || 100
74
-
75
- setup_trait(options) if respond_to?(:setup_trait)
78
+
79
+ ## setup_trait(options) if self.respond_to?(:setup_trait)
76
80
  end
77
81
 
78
82
  # Quick way of setting both factor_x and factor_y
@@ -0,0 +1,31 @@
1
+ #
2
+ # This code is from http://railstips.org/2008/6/13/a-class-instance-variable-update
3
+ # But we use the rails-name for it, class_inheritable_accessor, which should make ppl more @ home.
4
+ #
5
+ module Chingu
6
+ module ClassInheritableAccessor
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def class_inheritable_accessor(*args)
13
+ @cattr_inheritable_attrs ||= [:cattr_inheritable_attrs]
14
+ @cattr_inheritable_attrs += args
15
+ args.each do |arg|
16
+ class_eval %(
17
+ class << self; attr_accessor :#{arg} end
18
+ )
19
+ end
20
+ @cattr_inheritable_attrs
21
+ end
22
+
23
+ def inherited(subclass)
24
+ @cattr_inheritable_attrs.each do |inheritable_attribute|
25
+ instance_var = "@#{inheritable_attribute}"
26
+ subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -98,17 +98,18 @@ module Chingu
98
98
 
99
99
  #F-keys, F1-F12
100
100
  (1..12).each do |number|
101
- CONSTANT_TO_SYMBOL[eval("KbF#{number.to_s}")] = ["f#{number.to_s}".to_sym]
102
- CONSTANT_TO_SYMBOL[eval("KbF#{number.to_s}")] = ["F#{number.to_s}".to_sym]
101
+ CONSTANT_TO_SYMBOL[eval("KbF#{number.to_s}")] = ["f#{number.to_s}".to_sym, "F#{number.to_s}".to_sym]
103
102
  end
104
103
 
105
104
  # Gamepad-buttons 0-15
106
105
  (0..15).each do |number|
107
- CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gamepad_button_#{number.to_s}"]
108
- CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gamepad_#{number.to_s}"]
109
- CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["pad_button_#{number.to_s}"]
110
- CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["pad_#{number.to_s}"]
111
- CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gp_#{number.to_s}"]
106
+ CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = [
107
+ "gamepad_button_#{number.to_s}",
108
+ "gamepad_#{number.to_s}",
109
+ "pad_button_#{number.to_s}",
110
+ "pad_#{number.to_s}",
111
+ "gp_#{number.to_s}"
112
+ ]
112
113
  end
113
114
 
114
115
  #
@@ -1,8 +1,9 @@
1
1
  #
2
2
  # Our basic particle class, basicly just a GameObject with trait "effect"
3
3
  #
4
- # TODO: expand on this further, as it is now it doesn't add much.
4
+ # TODO: expand on this further, as it is now it doesn't add enough to warrant a whole new class.
5
5
  #
6
+
6
7
  module Chingu
7
8
  class Particle < Chingu::GameObject
8
9
  has_trait :effect
@@ -13,8 +14,7 @@ module Chingu
13
14
  end
14
15
 
15
16
  def update
16
- super
17
- self.image = @animation.next! if @animation
17
+ self.image = @animation.next if @animation
18
18
  end
19
19
 
20
20
  end
@@ -1,133 +1,140 @@
1
- #--
2
- # Copyright (C)2009 Tony Arcieri
3
- # You can redistribute this under the terms of the MIT license
4
- # See file LICENSE for details
5
- #++
6
-
7
- module RequireAll
8
- # A wonderfully simple way to load your code.
9
- #
10
- # The easiest way to use require_all is to just point it at a directory
11
- # containing a bunch of .rb files. These files can be nested under
12
- # subdirectories as well:
13
- #
14
- # require_all 'lib'
15
- #
16
- # This will find all the .rb files under the lib directory and load them.
17
- # The proper order to load them in will be determined automatically.
18
- #
19
- # If the dependencies between the matched files are unresolvable, it will
20
- # throw the first unresolvable NameError.
21
- #
22
- # You can also give it a glob, which will enumerate all the matching files:
23
- #
24
- # require_all 'lib/**/*.rb'
25
- #
26
- # It will also accept an array of files:
27
- #
28
- # require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file(f) }
29
- #
30
- # Or if you want, just list the files directly as arguments:
31
- #
32
- # require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb'
33
- #
34
- def require_all(*args)
35
- # Handle passing an array as an argument
36
- args.flatten!
37
-
38
- if args.size > 1
39
- # If we got a list, those be are files!
40
- files = args
41
- else
42
- arg = args.first
43
- begin
44
- # Try assuming we're doing plain ol' require compat
45
- stat = File.stat(arg)
46
-
47
- if stat.file?
48
- files = [arg]
49
- elsif stat.directory?
50
- files = Dir.glob File.join(arg, '**', '*.rb')
51
- else
52
- raise ArgumentError, "#{arg} isn't a file or directory"
53
- end
54
- rescue Errno::ENOENT
55
- # If the stat failed, maybe we have a glob!
56
- files = Dir.glob arg
57
-
58
- # Maybe it's an .rb file and the .rb was omitted
59
- if File.file?(arg + '.rb')
60
- require(arg + '.rb')
61
- return true
62
- end
63
-
64
- # If we ain't got no files, the glob failed
65
- raise LoadError, "no such file to load -- #{arg}" if files.empty?
66
- end
67
- end
68
-
69
- # If there's nothing to load, you're doing it wrong!
70
- raise LoadError, "no files to load" if files.empty?
71
-
72
- files.map! { |file| File.expand_path file }
73
-
74
- begin
75
- failed = []
76
- first_name_error = nil
77
-
78
- # Attempt to load each file, rescuing which ones raise NameError for
79
- # undefined constants. Keep trying to successively reload files that
80
- # previously caused NameErrors until they've all been loaded or no new
81
- # files can be loaded, indicating unresolvable dependencies.
82
- files.each do |file|
83
- begin
84
- require file
85
- rescue NameError => ex
86
- failed << file
87
- first_name_error ||= ex
88
- rescue ArgumentError => ex
89
- # Work around ActiveSuport freaking out... *sigh*
90
- #
91
- # ActiveSupport sometimes throws these exceptions and I really
92
- # have no idea why. Code loading will work successfully if these
93
- # exceptions are swallowed, although I've run into strange
94
- # nondeterministic behaviors with constants mysteriously vanishing.
95
- # I've gone spelunking through dependencies.rb looking for what
96
- # exactly is going on, but all I ended up doing was making my eyes
97
- # bleed.
98
- #
99
- # FIXME: If you can understand ActiveSupport's dependencies.rb
100
- # better than I do I would *love* to find a better solution
101
- raise unless ex.message["is not missing constant"]
102
-
103
- STDERR.puts "Warning: require_all swallowed ActiveSupport 'is not missing constant' error"
104
- STDERR.puts ex.backtrace[0..9]
105
- end
106
- end
107
-
108
- # If this pass didn't resolve any NameErrors, we've hit an unresolvable
109
- # dependency, so raise one of the exceptions we encountered.
110
- if failed.size == files.size
111
- raise first_name_error
112
- else
113
- files = failed
114
- end
115
- end until failed.empty?
116
-
117
- true
118
- end
119
-
120
- # Works like require_all, but paths are relative to the caller rather than
121
- # the current working directory
122
- def require_rel(*paths)
123
- # Handle passing an array as an argument
124
- paths.flatten!
125
-
126
- source_directory = File.dirname caller.first.sub(/:\d+$/, '')
127
- paths.each do |path|
128
- require_all File.join(source_directory, path)
129
- end
130
- end
131
- end
132
-
1
+ #--
2
+ # Copyright (C)2009 Tony Arcieri
3
+ # You can redistribute this under the terms of the MIT license
4
+ # See file LICENSE for details
5
+ #++
6
+
7
+ module RequireAll
8
+ # A wonderfully simple way to load your code.
9
+ #
10
+ # The easiest way to use require_all is to just point it at a directory
11
+ # containing a bunch of .rb files. These files can be nested under
12
+ # subdirectories as well:
13
+ #
14
+ # require_all 'lib'
15
+ #
16
+ # This will find all the .rb files under the lib directory and load them.
17
+ # The proper order to load them in will be determined automatically.
18
+ #
19
+ # If the dependencies between the matched files are unresolvable, it will
20
+ # throw the first unresolvable NameError.
21
+ #
22
+ # You can also give it a glob, which will enumerate all the matching files:
23
+ #
24
+ # require_all 'lib/**/*.rb'
25
+ #
26
+ # It will also accept an array of files:
27
+ #
28
+ # require_all Dir.glob("blah/**/*.rb").reject { |f| stupid_file(f) }
29
+ #
30
+ # Or if you want, just list the files directly as arguments:
31
+ #
32
+ # require_all 'lib/a.rb', 'lib/b.rb', 'lib/c.rb', 'lib/d.rb'
33
+ #
34
+ def require_all(*args)
35
+ # Handle passing an array as an argument
36
+ args.flatten!
37
+
38
+ if args.size > 1
39
+ # Expand files below directories
40
+ files = args.map do |path|
41
+ if File.directory? path
42
+ Dir[File.join(path, '**', '*.rb')]
43
+ else
44
+ path
45
+ end
46
+ end.flatten
47
+ else
48
+ arg = args.first
49
+ begin
50
+ # Try assuming we're doing plain ol' require compat
51
+ stat = File.stat(arg)
52
+
53
+ if stat.file?
54
+ files = [arg]
55
+ elsif stat.directory?
56
+ files = Dir.glob File.join(arg, '**', '*.rb')
57
+ else
58
+ raise ArgumentError, "#{arg} isn't a file or directory"
59
+ end
60
+ rescue Errno::ENOENT
61
+ # If the stat failed, maybe we have a glob!
62
+ files = Dir.glob arg
63
+
64
+ # Maybe it's an .rb file and the .rb was omitted
65
+ if File.file?(arg + '.rb')
66
+ require(arg + '.rb')
67
+ return true
68
+ end
69
+
70
+ # If we ain't got no files, the glob failed
71
+ raise LoadError, "no such file to load -- #{arg}" if files.empty?
72
+ end
73
+ end
74
+
75
+ # If there's nothing to load, you're doing it wrong!
76
+ raise LoadError, "no files to load" if files.empty?
77
+
78
+ files.map! { |file| File.expand_path file }
79
+ files.sort!
80
+
81
+ begin
82
+ failed = []
83
+ first_name_error = nil
84
+
85
+ # Attempt to load each file, rescuing which ones raise NameError for
86
+ # undefined constants. Keep trying to successively reload files that
87
+ # previously caused NameErrors until they've all been loaded or no new
88
+ # files can be loaded, indicating unresolvable dependencies.
89
+ files.each do |file|
90
+ begin
91
+ require file
92
+ rescue NameError => ex
93
+ failed << file
94
+ first_name_error ||= ex
95
+ rescue ArgumentError => ex
96
+ # Work around ActiveSuport freaking out... *sigh*
97
+ #
98
+ # ActiveSupport sometimes throws these exceptions and I really
99
+ # have no idea why. Code loading will work successfully if these
100
+ # exceptions are swallowed, although I've run into strange
101
+ # nondeterministic behaviors with constants mysteriously vanishing.
102
+ # I've gone spelunking through dependencies.rb looking for what
103
+ # exactly is going on, but all I ended up doing was making my eyes
104
+ # bleed.
105
+ #
106
+ # FIXME: If you can understand ActiveSupport's dependencies.rb
107
+ # better than I do I would *love* to find a better solution
108
+ raise unless ex.message["is not missing constant"]
109
+
110
+ STDERR.puts "Warning: require_all swallowed ActiveSupport 'is not missing constant' error"
111
+ STDERR.puts ex.backtrace[0..9]
112
+ end
113
+ end
114
+
115
+ # If this pass didn't resolve any NameErrors, we've hit an unresolvable
116
+ # dependency, so raise one of the exceptions we encountered.
117
+ if failed.size == files.size
118
+ raise first_name_error
119
+ else
120
+ files = failed
121
+ end
122
+ end until failed.empty?
123
+
124
+ true
125
+ end
126
+
127
+ # Works like require_all, but paths are relative to the caller rather than
128
+ # the current working directory
129
+ def require_rel(*paths)
130
+ # Handle passing an array as an argument
131
+ paths.flatten!
132
+
133
+ source_directory = File.dirname caller.first.sub(/:\d+$/, '')
134
+ paths.each do |path|
135
+ require_all File.join(source_directory, path)
136
+ end
137
+ end
138
+ end
139
+
133
140
  include RequireAll
@@ -29,8 +29,7 @@ module Chingu
29
29
 
30
30
  module ClassMethods
31
31
  def initialize_trait(options = {})
32
- ## puts "bounding_box initialize_trait #{options}"
33
- @trait_options[:bounding_box] = options
32
+ trait_options[:bounding_box] = options
34
33
  end
35
34
  end
36
35
 
@@ -50,11 +49,10 @@ module Chingu
50
49
  end
51
50
  alias :bb :bounding_box
52
51
 
53
- def draw_trait
52
+ def draw_trait
54
53
  if trait_options[:bounding_box][:debug]
55
54
  $window.draw_rect(self.bounding_box, Chingu::DEBUG_COLOR, Chingu::DEBUG_ZORDER)
56
55
  end
57
-
58
56
  super
59
57
  end
60
58
 
@@ -22,27 +22,36 @@
22
22
  module Chingu
23
23
  module Traits
24
24
  #
25
- # Providing a bounding_box and keeps it up to date by reading:
26
- # image, factor_x, factor_y
25
+ # Providing a bounding circle in the form of 2 attributes, self.radius and self.diameter
26
+ # It creates these 2 attributes from reading image.height, image.width, factor_x and factor_y
27
27
  #
28
- # ...only makes sense with rotation_center = :center
28
+ # ...this usually only makes sense with rotation_center = :center
29
29
  #
30
- module Radius
30
+ module BoundingCircle
31
31
 
32
32
  module ClassMethods
33
33
  def initialize_trait(options = {})
34
- @trait_options[:radius] = options
34
+ trait_options[:radius] = options
35
35
  end
36
36
  end
37
37
 
38
38
  def radius
39
39
  width = self.image.width * self.factor_x.abs
40
40
  height = self.image.height * self.factor_y.abs
41
- radius = (width + height) / 2
41
+ radius = (width + height) / 4
42
42
  radius = radius * trait_options[:radius][:scale] if trait_options[:radius][:scale]
43
43
  return radius
44
44
  end
45
45
 
46
+ def diameter
47
+ radius * 2
48
+ end
49
+
50
+ def circle_left; self.x - self.radius; end
51
+ def circle_right; self.x + self.radius; end
52
+ def circle_top; self.y - self.radius; end
53
+ def circle_bottom; self.y + self.radius; end
54
+
46
55
  def draw_trait
47
56
  if trait_options[:radius][:debug]
48
57
  $window.draw_circle(self.x, self.y, self.radius, Chingu::DEBUG_COLOR)
@@ -36,7 +36,7 @@ module Chingu
36
36
 
37
37
  module ClassMethods
38
38
  def initialize_trait(options = {})
39
- @trait_options[:collision_detection] = options
39
+ trait_options[:collision_detection] = options
40
40
  end
41
41
  end
42
42
 
@@ -46,8 +46,13 @@ module Chingu
46
46
  # two objects "bounding_box" attributs (a Chingu::Rect instance)
47
47
  #
48
48
  def collides?(object2)
49
- bounding_box_collision?(object2)
50
- #radius_collision?(object2)
49
+ if self.respond_to?(:bounding_box) && object2.respond_to?(:bounding_box)
50
+ bounding_box_collision?(object2)
51
+ elsif self.respond_to?(:radius) && object2.respond_to?(:radius)
52
+ radius_collision?(object2)
53
+ else
54
+ bounding_box_radius_collision?(object2)
55
+ end
51
56
  end
52
57
 
53
58
  #
@@ -66,12 +71,35 @@ module Chingu
66
71
  distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
67
72
  end
68
73
 
74
+ #
75
+ # BoundingBox vs Radius collision
76
+ #
77
+ # http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection
78
+ #
79
+ def bounding_box_radius_collision?(object2)
80
+ rect = self.respond_to?(:bounding_box) ? self.bounding_box : object2.bounding_box
81
+ circle = self.respond_to?(:radius) ? self : object2
82
+ radius = circle.radius.to_i
83
+
84
+ distance_x = (circle.x - rect.x - rect.width/2).abs
85
+ distance_y = (circle.y - rect.y - rect.height/2).abs
86
+
87
+ return false if distance_x > (rect.width/2 + circle.radius)
88
+ return false if distance_y > (rect.height/2 + circle.radius)
89
+
90
+ return true if distance_x <= (rect.width/2)
91
+ return true if distance_y <= (rect.height/2)
92
+
93
+ cornerDistance_sq = (distance_x - rect.width/2) ** 2 + (distance_y - rect.height/2) ** 2
94
+ return (cornerDistance_sq <= (circle.radius ** 2))
95
+ end
96
+
69
97
  #
70
98
  # Collides self with all objects of given classes
71
99
  # Yields self and the objects it collides with
72
100
  #
73
- def each_collision(klasses = [])
74
- Array(klasses).each do |klass|
101
+ def each_collision(*klasses)
102
+ Array(klasses).each do |klass|
75
103
  klass.all.each do |object|
76
104
  yield(self, object) if collides?(object)
77
105
  end
@@ -147,11 +175,27 @@ module Chingu
147
175
  # Enemy.each_collision(Bullet).each do |enemy, bullet| enemy.die!; end
148
176
  #
149
177
  #
150
- def each_collision(klasses = [])
178
+ def each_collision(*klasses)
151
179
  # Make sure klasses is always an array.
152
180
  Array(klasses).each do |klass|
153
181
  object2_list = klass.all
154
182
 
183
+ #
184
+ # Possible optimization, look into later.
185
+ #
186
+ # type1 = self.instance_methods.include?(:bounding_box) ? :bb : :bc
187
+ # type2 = klass.instance_methods.include?(:bounding_box) ? :bb : :bc
188
+ # Pointless optmization-attempts?
189
+ #if type1 != type2
190
+ # self.all.each do |object1|
191
+ # object2_list.each do |object2|
192
+ # next if object1 == object2 # Don't collide objects with themselves
193
+ # yield object1, object2 if object1.bounding_box_radius_collision?(object2)
194
+ # end
195
+ # end
196
+ #end
197
+
198
+
155
199
  self.all.each do |object1|
156
200
  object2_list.each do |object2|
157
201
  next if object1 == object2 # Don't collide objects with themselves
@@ -160,9 +204,7 @@ module Chingu
160
204
  end
161
205
  end
162
206
  end
163
-
164
207
  end
165
-
166
208
  end
167
209
  end
168
210
  end
@@ -42,21 +42,18 @@ module Chingu
42
42
 
43
43
  module Effect
44
44
  attr_accessor :rotation_rate, :fade_rate, :scale_rate
45
-
45
+
46
46
  #
47
47
  # Setup
48
48
  #
49
- def setup_trait(options)
49
+ def setup_trait(options)
50
+ ## puts "Effect#setup_trait(#{options})"
50
51
  @rotation_rate = options[:rotation_rate] || nil
51
52
  @scale_rate = options[:scale_rate] || nil
52
53
  @fade_rate = options[:fade_rate] || nil
53
54
  super
54
55
  end
55
-
56
- def draw_trait
57
- super
58
- end
59
-
56
+
60
57
  def update_trait
61
58
  rotate(@rotation_rate) if @rotation_rate
62
59
  fade(@fade_rate) if @fade_rate
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chingu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ippa
@@ -30,7 +30,7 @@ cert_chain:
30
30
  hxtMlw==
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2009-11-22 00:00:00 +01:00
33
+ date: 2009-11-25 00:00:00 +01:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -95,6 +95,7 @@ files:
95
95
  - examples/media/background1.png
96
96
  - examples/media/bullet.png
97
97
  - examples/media/bullet_hit.wav
98
+ - examples/media/circle.png
98
99
  - examples/media/city1.csv
99
100
  - examples/media/city1.png
100
101
  - examples/media/city2.png
@@ -107,6 +108,7 @@ files:
107
108
  - examples/media/particle.png
108
109
  - examples/media/plane.csv
109
110
  - examples/media/plane.png
111
+ - examples/media/rect.png
110
112
  - examples/media/ruby.png
111
113
  - examples/media/saucer.csv
112
114
  - examples/media/saucer.gal
@@ -120,7 +122,7 @@ files:
120
122
  - lib/chingu/animation.rb
121
123
  - lib/chingu/assets.rb
122
124
  - lib/chingu/basic_game_object.rb
123
- - lib/chingu/core_extensions.rb
125
+ - lib/chingu/core_ext/array.rb
124
126
  - lib/chingu/fpscounter.rb
125
127
  - lib/chingu/game_object.rb
126
128
  - lib/chingu/game_object_list.rb
@@ -130,6 +132,8 @@ files:
130
132
  - lib/chingu/game_states/edit.rb
131
133
  - lib/chingu/game_states/fade_to.rb
132
134
  - lib/chingu/game_states/pause.rb
135
+ - lib/chingu/gosu_ext/image.rb
136
+ - lib/chingu/helpers/class_inheritable_accessor.rb
133
137
  - lib/chingu/helpers/game_object.rb
134
138
  - lib/chingu/helpers/game_state.rb
135
139
  - lib/chingu/helpers/gfx.rb
@@ -146,9 +150,9 @@ files:
146
150
  - lib/chingu/require_all.rb
147
151
  - lib/chingu/text.rb
148
152
  - lib/chingu/traits/bounding_box.rb
153
+ - lib/chingu/traits/bounding_circle.rb
149
154
  - lib/chingu/traits/collision_detection.rb
150
155
  - lib/chingu/traits/effect.rb
151
- - lib/chingu/traits/radius.rb
152
156
  - lib/chingu/traits/retrofy.rb
153
157
  - lib/chingu/traits/timer.rb
154
158
  - lib/chingu/traits/velocity.rb
metadata.gz.sig CHANGED
Binary file