chingu 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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