chingu 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- [H��7��ųhE�u��5�AMܐR��ä'
2
- B��©r@
1
+ ���M���ʜ ��G��5mǂ��tz��5��~ :kLJ����_Qˡ��e�z��(
2
+ 2�7����qh�y�rA�d
3
+ q �G_"Z\��{�N:g�k�� ��Y�m�Aĺ��a��RZ_bW���Fп��". �s��AQ7�~� ㏉ A�R� �]$k�a��D-�1����N#�S�_�u�@og�k��J �</J��ҋ�!�*a�4�!HL�8vG�J7�.��t}��7��x!p��L�ϙ��e�)�Z�Ž�
data/README.rdoc CHANGED
@@ -90,6 +90,8 @@ Both $window and game states gets some new graphical helpers, currently only 3,
90
90
  fill() # Fills whole window with color 'color'.
91
91
  fill_rect() # Fills a given Rect 'rect' with Color 'color'
92
92
  fill_gradient() # Fills window or a given rect with a gradient between two colors.
93
+ draw_circle() # Draws a circle
94
+ draw_rect() # Draws a rect
93
95
 
94
96
  If you base your models on GameObject (or BasicGameObject) you get:
95
97
  Enemy.all # Returns an Array of all Enemy-instances
@@ -445,13 +447,41 @@ Chingus inputhandler will detect that Menu is a GameState-class, create a new in
445
447
 
446
448
  === Traits
447
449
  Traits (often called behaivors) is a way of adding logic to any class inheriting from BasicGameObject / GameObject.
448
- Chingus trait-implementation is just ordinary ruby modules with 3 special methods:
450
+ Chingus trait-implementation is just ordinary ruby modules with 3 special methods:
449
451
  - setup_trait
450
452
  - update_trait
451
453
  - draw_trait
452
454
  Each of those 3 methods must call "super" to continue the trait-chain.
453
455
 
454
- Example:
456
+ Inside a certian trait-module you can also have a module called ClassMethods, methods inside that module will be added,
457
+ yes you guessed it, as class methods. If initialize_trait is defined inside ClassMethods it will be called class-evaluation time
458
+ (basicly on the has_trait :some_trait line).
459
+
460
+ A simple trait could be:
461
+
462
+ module Chingu
463
+ module Trait
464
+ module Inspect
465
+ module ClassMethods
466
+ def initialize_trait(options)
467
+ # possible initialize stuff here
468
+ end
469
+
470
+ def inspect
471
+ "There's {self.size} active instances of class {self.to_s}"
472
+ end
473
+ end
474
+ end
475
+ end
476
+
477
+ class Enemy < GameObject
478
+ has_trait :inspect # includes Chingu::Trait::Inspect and extends Chingu::Trait::Inspect::ClassMethods
479
+ end
480
+ 10.times { Enemy.create }
481
+ Enemy.inspect # => There's 10 active instances of class Enemy
482
+
483
+
484
+ Example of using traits :velocity and :timer:
455
485
 
456
486
  class Ogre < Chingu::GameObject
457
487
  has_traits :velocity, :timer
@@ -466,8 +496,8 @@ Example:
466
496
  # These 2 parameters will affect @x and @y every game-iteration
467
497
  # So if your ogre is standing on the ground, make sure you cancel out the effect of @acceleration_y
468
498
  #
469
- @velocity_x = 1 # move constantly to the right
470
- @acceleration_y = 0.4 # gravity is basicly a downwards acceleration
499
+ self.velocity_x = 1 # move constantly to the right
500
+ self.acceleration_y = 0.4 # gravity is basicly a downwards acceleration
471
501
  end
472
502
 
473
503
  def hit_by(object)
@@ -475,7 +505,7 @@ Example:
475
505
  # during() and then() is provided by the timer-trait
476
506
  # flash red for 300 millisec when hit, then go back to normal
477
507
  #
478
- during(100) { @color = @red; @mode = :additive }.then { @color = @white; @mode = :default }
508
+ during(100) { self.color = @red; self.mode = :additive }.then { self.color = @white; self.mode = :default }
479
509
  end
480
510
  end
481
511
 
@@ -483,7 +513,7 @@ The flow for a game object then becomes:
483
513
 
484
514
  -- creating a GameObject class X ( with a "has_trait :bounding_box, :scale => 0.80" )
485
515
  1) trait gets merged into X, instance and class methods are added
486
- 2) GameObject.initialize_trait(:scale => 0.80)
516
+ 2) GameObject.initialize_trait(:scale => 0.80) (initialize_trait is a class-method!)
487
517
  -- creating an instance of X
488
518
  1) GameObject#initialize(options)
489
519
  2) GameObject#setup_trait(options)
@@ -497,7 +527,7 @@ There's a couple of traits included as default in Chingu:
497
527
 
498
528
  ==== Trait "timer"
499
529
  Adds timer functionality to your game object
500
- during(300) { @color = Color.new(0xFFFFFFFF) } # forces @color to white every update for 300 ms
530
+ during(300) { self.color = Color.new(0xFFFFFFFF) } # forces @color to white every update for 300 ms
501
531
  after(400) { self.destroy } # destroy object after 400 ms
502
532
  between(1000,2000) { self.rotate(10) } # starting after 1 second, call rotate(10) every update during 1 second
503
533
  every(2000) { Sound["bleep.wav"].play } # play bleep.wav every 2 seconds
@@ -514,7 +544,7 @@ You can also scale the calculated rect with has_trait-options:
514
544
  # Make player think he's better @ dodging bullets then he really is ;)
515
545
  has_trait :bounding_box, :scale => 0.80
516
546
 
517
- ==== Trait "radius"
547
+ ==== Trait "bounding_circle"
518
548
  Adds accessor 'radius', which returns a Fixnum based on current image size,factor_x and factor_y
519
549
  You can also scale the calculated radius with has_trait-options:
520
550
 
@@ -530,14 +560,23 @@ Adds class and instance methods for basic collision detection.
530
560
 
531
561
  # Class method example
532
562
  # This will collide all Enemy-instances with all Bullet-instances using the attribute #radius from each object.
533
- Enemy.each_radius_collision(Bullet) do |enemy, bullet|
563
+ Enemy.each_bounding_circle_collision(Bullet) do |enemy, bullet|
534
564
  end
535
565
 
536
566
  # You can also use the instance methods. This will use the Rect bounding_box from @player and each EnemyRocket-object.
537
567
  @player.each_bounding_box_collision(EnemyRocket) do |player, enemyrocket|
538
568
  player.die!
539
569
  end
570
+
571
+ #
572
+ # each_collision automatically tries to access #radius and #bounding_box to see what a certain game object provides
573
+ # It knows how to collide radius/radius, bounding_box/bounding_box and radius/bounding_box !
574
+ # Since You're not explicity telling what collision type to use it might be slighty slower.
575
+ #
576
+ [Player, PlayerBullet].each_collision(Enemy, EnemyBullet) do |friend, foe|
540
577
 
578
+ end
579
+
541
580
  * API isn't stabilized yet! *
542
581
 
543
582
  ==== (IN DEVELOPMENT) Trait "retrofy"
@@ -562,7 +601,7 @@ Chingu solves this problem behind the scenes for the most common assets. The 2 l
562
601
  Image["player.png"]
563
602
 
564
603
  You also have:
565
- Sound["shot.png"]
604
+ Sound["shot.wav"]
566
605
  Song["intromusic.ogg"]
567
606
 
568
607
  The default settings are like this:
@@ -589,7 +628,7 @@ Text is a class to give the use of Gosu::Font more rubyish feel and fit it bette
589
628
  @font.draw("A Text", 200, 50, 55, 2.0)
590
629
 
591
630
  # Chingu
592
- @text = Chingu::Text.create(:text => "A Text", :x => 200, :y => 50, :zorder => 55, :factor_x => 2.0)
631
+ @text = Chingu::Text.create("A Text", :x => 200, :y => 50, :zorder => 55, :factor_x => 2.0)
593
632
  @text.draw
594
633
 
595
634
  @text.draw is usually not needed as Text is a GameObject and therefore automaticly updated/drawn (it #create is used instead of #new)
@@ -610,7 +649,7 @@ GameObject.all is naming straight from rails for example. Most stuff in GameObje
610
649
 
611
650
  As far as possible, use correct rubyfied english game_objects, not gameobjects. class HighScore, not Highscore.
612
651
 
613
- == TODO:
652
+ == TODO - this list is discontinued and no longer updated
614
653
  * add :padding and :align => :topleft etc to class Text
615
654
  * (skip) rename Chingu::Window so 'include Chingu' and 'include Gosu' wont make Window collide
616
655
  * (done) BasicObject vs GameObject vs ScreenObject => Became BasicGameObject and GameObject
@@ -656,9 +695,11 @@ As far as possible, use correct rubyfied english game_objects, not gameobjects.
656
695
 
657
696
  == CREDITS:
658
697
  * Jacius of Rubygame (For doing cool stuff that's well documented as re-usable). So far rect.rb and named_resource.rb is straight outta Rubygame.
698
+ * Banister (of texplay fame) for general feedeback and help with ruby-internals and building the trait-system
659
699
  * Jduff for input / commits
660
700
  * Jlnr,Philymore,Shawn24,JamesKilton for constructive feedback/discussions
661
701
  * Ariel Pillet for codesuggestions and cleanups
702
+ * Deps for making the first real full game with Chingu (and making it better in the process)
662
703
  * Thanks to http://github.com/tarcieri for require_all code, good stuff
663
704
 
664
705
  == REQUIREMENTS:
data/chingu.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{chingu}
5
- s.version = "0.6.2"
5
+ s.version = "0.6.3"
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-25}
9
+ s.date = %q{2009-11-26}
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.}
@@ -11,8 +11,8 @@ class Game < Chingu::Window
11
11
  super(640,400)
12
12
  self.input = {:esc => :exit, :q => :decrease_size, :w => :increase_size, :a => :decrease_speed, :s => :increase_speed}
13
13
 
14
- 10.times { Circle.create(:x => width/2, :y => height/2) }
15
- 10.times { Box.create(:x => width/2, :y => height/2) }
14
+ 20.times { Circle.create(:x => width/2, :y => height/2) }
15
+ 20.times { Box.create(:x => width/2, :y => height/2) }
16
16
  @blue = Color.new(0xFF0000FF)
17
17
  @white = Color.new(0xFFFFFFFF)
18
18
  end
@@ -38,7 +38,10 @@ class Game < Chingu::Window
38
38
  #
39
39
  # Collide Boxes/Circles, Boxes/Boxes and Circles/Circles (basicly all objects on screen)
40
40
  #
41
- [Box, Circle].each_collision(Box, Circle) { |o, o2| o.color, o2.color = @blue, @blue }
41
+ # Before optmization: 25 FPS (20 boxes and 20 circles)
42
+ # Cached radius and rects:
43
+ #
44
+ #[Box, Circle].each_collision(Box, Circle) { |o, o2| o.color, o2.color = @blue, @blue }
42
45
 
43
46
  #
44
47
  # Only collide boxes with other boxes
@@ -69,8 +72,8 @@ class Circle < GameObject
69
72
  self.velocity_x = 3 - rand * 6
70
73
  self.velocity_y = 3 - rand * 6
71
74
  self.factor = 2
72
-
73
- self.input = [:holding_left, :holding_right, :holding_down, :holding_up]
75
+ self.input = [:holding_left, :holding_right, :holding_down, :holding_up] # NOTE: giving input an Array, not a Hash
76
+ cache_bounding_circle
74
77
  end
75
78
 
76
79
  def holding_left; @x -= 1; end
@@ -94,11 +97,14 @@ class Box < GameObject
94
97
  self.velocity_x = 3 - rand * 6
95
98
  self.velocity_y = 3 - rand * 6
96
99
  self.factor = 2
100
+ cache_bounding_box
97
101
  end
98
102
 
99
103
  def update
100
104
  self.velocity_x = -self.velocity_x if @x < 0 || @x > $window.width
101
105
  self.velocity_y = -self.velocity_y if @y < 0 || @y > $window.height
106
+ #@x = @x.to_i
107
+ #@y = @y.to_i
102
108
  end
103
109
  end
104
110
 
data/examples/example4.rb CHANGED
@@ -34,7 +34,7 @@ class Game < Chingu::Window
34
34
  push_game_state(Intro)
35
35
 
36
36
  # Yes you can do crazy things like this :)
37
- self.input = { :left_mouse_button => lambda{Chingu::Text.create(:text => "Woff!")}, :esc => :exit}
37
+ self.input = { :left_mouse_button => lambda{Chingu::Text.create(:text => "Woff!")}, :esc => :exit}
38
38
  end
39
39
  end
40
40
 
@@ -51,8 +51,8 @@ class Player < Chingu::GameObject
51
51
  def move_down; @y += 1; end
52
52
 
53
53
  def fire
54
- #puts $window.current_parent.to_s
55
- #puts $window.game_state_manager.inside_state
54
+ #puts "current_scope: #{$window.current_scope.to_s}"
55
+ #puts "inside_state: #{$window.game_state_manager.inside_state}"
56
56
  Bullet.create(:x => @x - 20, :y => @y)
57
57
  Bullet.create(:x => @x, :y => @y)
58
58
  Bullet.create(:x => @x + 20, :y => @y)
data/examples/example6.rb CHANGED
@@ -43,9 +43,18 @@ class Game < Chingu::Window
43
43
  end
44
44
 
45
45
  class State1 < Chingu::GameState
46
- def draw
47
- Image["ruby.png"].draw(0,0,0)
46
+
47
+ #
48
+ # This is another way of achieving the same thing as the out-commeted draw-code
49
+ # Since .create is used, it's automatically updated and drawn
50
+ #
51
+ def setup
52
+ Chingu::GameObject.create(:image => "ruby.png", :rotation_center => :top_left)
48
53
  end
54
+
55
+ #def draw
56
+ # Image["ruby.png"].draw(0,0,0)
57
+ #end
49
58
  end
50
59
 
51
60
  class State2 < Chingu::GameState
data/examples/example9.rb CHANGED
@@ -76,9 +76,13 @@ class ParticleState < Chingu::GameState
76
76
  end
77
77
 
78
78
  #
79
- # GameObject.each_collsion / each_radius_collision wont collide an object with itself
79
+ # GameObject.each_collsion / each_bounding_box_collision wont collide an object with itself
80
80
  #
81
- FireCube.each_radius_collision(FireCube) do |cube1, cube2|
81
+ # FireCube.each_bounding_circle_collision(FireCube) do |cube1, cube2| # 30 FPS on my computer
82
+ #
83
+ # Let's see if we can optimize each_collision, starts with 19 FPS
84
+ #
85
+ FireCube.each_collision(FireCube) do |cube1, cube2|
82
86
  cube1.die!
83
87
  cube2.die!
84
88
  end
data/examples/game1.rb CHANGED
@@ -35,12 +35,10 @@ class Level < Chingu::GameState
35
35
  def initialize(options = {})
36
36
  super
37
37
 
38
- @parallax = Parallax.create
39
- #ParallaxLayer.has_trait :retrofy
40
- #@parallax << ParallaxLayer.new(:image => Image["city3.png"].retrofy, :center => 0, :damping => 4, :factor => $window.factor)
41
- @parallax << ParallaxLayer.new(:image => Image["city2.png"].retrofy, :center => 0, :damping => 2, :factor => $window.factor)
42
- @parallax << ParallaxLayer.new(:image => Image["city1.png"].retrofy, :center => 0, :damping => 1, :factor => $window.factor)
43
- @player = Player.create(:x => 10, :y => 10)
38
+ @parallax = Parallax.create(:rotation_center => :top_left)
39
+ @parallax << { :image => Image["city2.png"].retrofy, :damping => 2, :factor => $window.factor }
40
+ @parallax << { :image => Image["city1.png"].retrofy, :damping => 1, :factor => $window.factor }
41
+ @player = Player.create(:x => 30, :y => 10)
44
42
 
45
43
  @bg1 = Color.new(0xFFCE28FF)
46
44
  @bg2 = Color.new(0xFF013E87)
@@ -95,12 +93,12 @@ class Level < Chingu::GameState
95
93
  push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
96
94
 
97
95
  # Collide player with enemies and enemy bullets
98
- @player.each_radius_collision(Enemy) do |player, enemy|
96
+ @player.each_bounding_circle_collision(Enemy) do |player, enemy|
99
97
  enemy.die
100
98
  push_game_state(GameOver)
101
99
  end
102
100
 
103
- Bullet.each_radius_collision(Enemy) do |bullet, enemy|
101
+ Bullet.each_bounding_circle_collision(Enemy) do |bullet, enemy|
104
102
  bullet.die
105
103
  if enemy.hit_by(bullet)
106
104
  @player.score += 20
@@ -9,6 +9,8 @@
9
9
  :score: 9912
10
10
  - :name: NEW
11
11
  :score: 9900
12
+ - :name: NEW
13
+ :score: 9886
12
14
  - :name: NEW
13
15
  :score: 9885
14
16
  - :name: NEW
@@ -19,5 +21,3 @@
19
21
  :score: 9746
20
22
  - :name: NEW
21
23
  :score: 9742
22
- - :name: NEW
23
- :score: 9736
data/lib/chingu.rb CHANGED
@@ -33,7 +33,7 @@ require_all "#{CHINGU_ROOT}/chingu/traits"
33
33
  require_all "#{CHINGU_ROOT}/chingu"
34
34
 
35
35
  module Chingu
36
- VERSION = "0.6.2"
36
+ VERSION = "0.6.3"
37
37
 
38
38
  DEBUG_COLOR = Gosu::Color.new(0xFFFF0000)
39
39
  DEBUG_ZORDER = 9999
@@ -7,7 +7,7 @@ module Chingu
7
7
  # It will also acts as a container for the trait-system of chingu.
8
8
  #
9
9
  class BasicGameObject
10
- include Chingu::ClassInheritableAccessor
10
+ include Chingu::Helpers::ClassInheritableAccessor # adds classmethod class_inheritable_accessor
11
11
 
12
12
  attr_reader :options, :paused, :visible
13
13
  attr_accessor :parent
@@ -65,9 +65,10 @@ module Chingu
65
65
  #
66
66
  # A GameObject either belong to a GameState or our mainwindow ($window)
67
67
  #
68
- if !@parent && $window && $window.respond_to?(:game_state_manager)
69
- @parent = $window.game_state_manager.inside_state || $window
70
- end
68
+ #if !@parent && $window && $window.respond_to?(:game_state_manager)
69
+ # @parent = $window.game_state_manager.inside_state || $window
70
+ #end
71
+ @parent = $window.current_scope if !@parent && $window
71
72
 
72
73
  # if true, BasicGameObject#update will be called
73
74
  @paused = options[:paused] || false
@@ -97,6 +98,7 @@ module Chingu
97
98
  #
98
99
  instance.parent.add_game_object(instance) if instance.parent
99
100
 
101
+
100
102
  return instance
101
103
  end
102
104
 
@@ -168,14 +170,14 @@ module Chingu
168
170
  # Bullet.all.each do {} # Iterate through all bullets in current game state
169
171
  #
170
172
  def self.all
171
- $window.current_parent.game_objects.of_class(self).dup
173
+ $window.current_scope.game_objects.of_class(self).dup
172
174
  end
173
175
 
174
176
  #
175
177
  # Returns
176
178
  #
177
179
  def self.size
178
- $window.current_parent.game_objects.of_class(self).size
180
+ $window.current_scope.game_objects.of_class(self).size
179
181
  end
180
182
 
181
183
  #
@@ -9,4 +9,27 @@ class Array
9
9
  end
10
10
  end
11
11
  end
12
+
13
+ def each_bounding_circle_collision(*args)
14
+ list = (self + args).uniq
15
+ collide_pair = []
16
+ list.each_with_index { |nr, i| self[i..size].collect { |nr2| collide_pair << [nr,nr2] } }
17
+ collide_pair.each do |class1,class2|
18
+ class1.each_bounding_circle_collision(class2) do |object1, object2|
19
+ yield object1, object2
20
+ end
21
+ end
22
+ end
23
+
24
+ def each_bounding_box_collision(*args)
25
+ list = (self + args).uniq
26
+ collide_pair = []
27
+ list.each_with_index { |nr, i| self[i..size].collect { |nr2| collide_pair << [nr,nr2] } }
28
+ collide_pair.each do |class1,class2|
29
+ class1.each_bounding_box_collision(class2) do |object1, object2|
30
+ yield object1, object2
31
+ end
32
+ end
33
+ end
34
+
12
35
  end
@@ -37,7 +37,6 @@ module Chingu
37
37
  include Chingu::Helpers::InputClient # Adds input and input=
38
38
  include Chingu::Helpers::RotationCenter # Adds easy and verbose modification of @center_x and @center_y
39
39
 
40
-
41
40
  def initialize(options = {})
42
41
  super
43
42
 
@@ -45,7 +44,7 @@ module Chingu
45
44
  if options[:image].is_a?(Gosu::Image)
46
45
  @image = options[:image]
47
46
  elsif options[:image].is_a? String
48
- @image = Image[options[:image]]
47
+ @image = Gosu::Image[options[:image]]
49
48
  end
50
49
 
51
50
  @x = options[:x] || 0
@@ -76,7 +75,7 @@ module Chingu
76
75
  @mode = options[:mode] || :default # :additive is also available.
77
76
  @zorder = options[:zorder] || 100
78
77
 
79
- ## setup_trait(options) if self.respond_to?(:setup_trait)
78
+ #setup_trait(options) if self.respond_to?(:setup_trait)
80
79
  end
81
80
 
82
81
  # Quick way of setting both factor_x and factor_y
@@ -54,20 +54,23 @@ module Chingu
54
54
  include Chingu::Helpers::GameObject # Adds game_objects_of_class etc ...
55
55
  include Chingu::Helpers::InputDispatcher # Input dispatch-helpers
56
56
  include Chingu::Helpers::InputClient # GameState can have it's own inputmap
57
+ include Chingu::Helpers::ClassInheritableAccessor # adds classmethod class_inheritable_accessor
57
58
 
58
59
  attr_reader :options
59
60
  attr_accessor :game_state_manager, :game_objects
60
61
 
61
- def self.trait_options; @trait_options; end
62
+ class_inheritable_accessor :trait_options
63
+ @trait_options = Hash.new
62
64
  def trait_options; self.class.trait_options; end
63
-
65
+
64
66
  #
65
67
  # Adds a trait or traits to a certain game class
66
68
  # Executes a standard ruby "include" the specified module
67
69
  #
68
70
  def self.has_trait(trait, options = {})
69
- @trait_options ||= Hash.new
71
+
70
72
  if trait.is_a?(::Symbol) || trait.is_a?(::String)
73
+ ## puts "has_trait #{trait}, #{options}"
71
74
  begin
72
75
  # Convert user-given symbol (eg. :timer) to a Module (eg. Chingu::Traits::Timer)
73
76
  mod = Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
@@ -75,14 +78,21 @@ module Chingu
75
78
  # Include the module, which will add the containing methods as instance methods
76
79
  include mod
77
80
 
78
- # Add possible classmethods defined in sub-module ClassMethods (eg: Chingu::Traits::Timer::ClassMethods)
79
- mod2 = mod.const_get("ClassMethods")
80
- extend mod2
81
+ # Does sub-module "ClessMethods" exists?
82
+ # (eg: Chingu::Traits::Timer::ClassMethods)
83
+ if mod.const_defined?("ClassMethods")
84
+ # Add methods in scope ClassMethods as.. class methods!
85
+ mod2 = mod.const_get("ClassMethods")
86
+ extend mod2
81
87
 
82
- # If the newly included trait has a initialize_trait method...
83
- # ... call it with the options provided with the has_trait-call
84
- initialize_trait(options) if mod2.method_defined?(:initialize_trait)
88
+ # If the newly included trait has a initialize_trait method in the ClassMethods-scope:
89
+ # ... call it with the options provided with the has_trait-line.
90
+ if mod2.method_defined?(:initialize_trait)
91
+ initialize_trait(options)
92
+ end
93
+ end
85
94
  rescue
95
+ puts $!
86
96
  end
87
97
  end
88
98
  end
@@ -114,6 +114,7 @@ module Chingu
114
114
  current_game_state.finalize if current_game_state.respond_to?(:finalize) && options[:finalize]
115
115
 
116
116
  # So BasicGameObject#create connects object to new state in its setup()
117
+ # Is this doubled in GameState.initialize() ?
117
118
  self.inside_state = new_state
118
119
 
119
120
  # Call setup
@@ -131,8 +132,10 @@ module Chingu
131
132
  @game_states[-1] = new_state
132
133
  end
133
134
  end
134
- ## MOVEDE: self.inside_state = current_game_state
135
+ ## MOVED: self.inside_state = current_game_state
135
136
  end
137
+
138
+ self.inside_state = nil # no longer 'inside' (as in within initialize() etc) a game state
136
139
  end
137
140
  alias :switch :switch_game_state
138
141
 
@@ -157,6 +160,7 @@ module Chingu
157
160
  new_state.setup if new_state.respond_to?(:setup) && options[:setup]
158
161
 
159
162
  # Make sure the game state knows about the manager
163
+ # Is this doubled in GameState.initialize() ?
160
164
  new_state.game_state_manager = self
161
165
 
162
166
  # Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
@@ -172,6 +176,8 @@ module Chingu
172
176
  end
173
177
  ## MOVED: self.inside_state = current_game_state
174
178
  end
179
+
180
+ self.inside_state = nil # no longer 'inside' (as in within initialize() etc) a game state
175
181
  end
176
182
  alias :push :push_game_state
177
183
 
@@ -195,6 +201,7 @@ module Chingu
195
201
  @game_states.pop
196
202
 
197
203
  # So BasicGameObject#create connects object to new state in its setup()
204
+ # Is this doubled in GameState.initialize() ?
198
205
  self.inside_state = current_game_state
199
206
 
200
207
  # Call setup on the new current state
@@ -205,7 +212,9 @@ module Chingu
205
212
  transitional_game_state = @transitional_game_state.new(current_game_state, @transitional_game_state_options)
206
213
  self.switch_game_state(transitional_game_state, :transitional => false)
207
214
  end
215
+
208
216
  ## MOVED: self.inside_state = current_game_state
217
+ self.inside_state = nil # no longer 'inside' (as in within initialize() etc) a game state
209
218
  end
210
219
  alias :pop :pop_game_state
211
220
 
@@ -3,27 +3,29 @@
3
3
  # But we use the rails-name for it, class_inheritable_accessor, which should make ppl more @ home.
4
4
  #
5
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
6
+ module Helpers
7
+ module ClassInheritableAccessor
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
21
10
  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))
11
+
12
+ module ClassMethods
13
+ def class_inheritable_accessor(*args)
14
+ @cattr_inheritable_attrs ||= [:cattr_inheritable_attrs]
15
+ @cattr_inheritable_attrs += args
16
+ args.each do |arg|
17
+ class_eval %(
18
+ class << self; attr_accessor :#{arg} end
19
+ )
20
+ end
21
+ @cattr_inheritable_attrs
22
+ end
23
+
24
+ def inherited(subclass)
25
+ @cattr_inheritable_attrs.each do |inheritable_attribute|
26
+ instance_var = "@#{inheritable_attribute}"
27
+ subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
28
+ end
27
29
  end
28
30
  end
29
31
  end
@@ -29,6 +29,7 @@ module Chingu
29
29
  module GameObject
30
30
 
31
31
  def add_game_object(object)
32
+ # puts "#{self.to_s} add_game_object(#{object.to_s})"
32
33
  @game_objects.add_game_object(object)
33
34
  end
34
35
 
@@ -115,7 +115,7 @@ module Chingu
115
115
  def draw_circle(cx,cy,r,color)
116
116
  0.step(360, CIRCLE_STEP) do |a1|
117
117
  a2 = a1 + CIRCLE_STEP
118
- $window.draw_line cx + offset_x(a1, r), cy + offset_y(a1, r), color, cx + offset_x(a2, r), cy + offset_y(a2, r), color, 9999
118
+ $window.draw_line cx + Gosu.offset_x(a1, r), cy + Gosu.offset_y(a1, r), color, cx + Gosu.offset_x(a2, r), cy + Gosu.offset_y(a2, r), color, 9999
119
119
  end
120
120
  end
121
121
 
@@ -36,7 +36,8 @@ module Chingu
36
36
  #
37
37
  # Options (in hash-format):
38
38
  #
39
- # repeat: [true|false] When one layer ends within the screen, repeat/loop it
39
+ # repeat_x: [true|false] repeat layer on X-axis
40
+ # repeat_y: [true|false] repeat layer on Y-axis
40
41
  #
41
42
  def initialize(options = {})
42
43
  super(options)
@@ -61,7 +62,7 @@ module Chingu
61
62
  # returns true if any part of the parallax-scroller is inside the window
62
63
  #
63
64
  def inside_window?
64
- return true if @repeat
65
+ return true if @repeat_x || @repeat_y
65
66
  @layers.each { |layer| return true if layer.inside_window? }
66
67
  return false
67
68
  end
@@ -122,31 +123,30 @@ module Chingu
122
123
  #
123
124
  def draw
124
125
  @layers.each do |layer|
125
- layer.draw
126
+ #layer.draw
126
127
 
127
128
  save_x, save_y = layer.x, layer.y
128
129
 
129
130
  # If layer lands inside our window and repeat_x is true (defaults to true), draw it until window ends
130
131
  while layer.repeat_x && layer.x < $window.width
131
132
  while layer.repeat_y && layer.y < $window.height
132
- layer.y += layer.image.height
133
133
  layer.draw
134
+ layer.y += layer.image.height
134
135
  end
135
136
  layer.y = save_y
136
137
 
137
- layer.x += layer.image.width
138
138
  layer.draw
139
+ layer.x += layer.image.width
139
140
  end
140
141
 
141
- # Special loop for when repeat_y is set but not repeat_x
142
+ # Special loop for when repeat_y is true but not repeat_x
142
143
  if layer.repeat_y && !layer.repeat_x
143
144
  while layer.repeat_y && layer.y < $window.height
144
- layer.y += layer.image.height
145
145
  layer.draw
146
+ layer.y += layer.image.height
146
147
  end
147
148
  end
148
149
 
149
-
150
150
  layer.x = save_x
151
151
  end
152
152
  self
data/lib/chingu/text.rb CHANGED
@@ -72,7 +72,7 @@ module Chingu
72
72
  @align = options[:align] || :left
73
73
  @max_width = options[:max_width]
74
74
 
75
- self.rotation_center(:top_left)
75
+ self.rotation_center = :top_left
76
76
 
77
77
  @gosu_font = Gosu::Font.new($window, @font, @height)
78
78
 
@@ -32,8 +32,23 @@ module Chingu
32
32
  trait_options[:bounding_box] = options
33
33
  end
34
34
  end
35
-
36
- def bounding_box
35
+
36
+ def setup_trait(options)
37
+ @cached_bounding_box = nil
38
+ super
39
+ end
40
+
41
+ #
42
+ # Returns an instance of class Rect
43
+ #
44
+ def bounding_box
45
+ if @cached_bounding_box
46
+ @cached_bounding_box.x = self.x + @_x_diff
47
+ @cached_bounding_box.y = self.y + @_y_diff
48
+
49
+ return @cached_bounding_box
50
+ end
51
+
37
52
  width = self.image.width * self.factor_x.abs
38
53
  height = self.image.height * self.factor_y.abs
39
54
 
@@ -49,6 +64,18 @@ module Chingu
49
64
  end
50
65
  alias :bb :bounding_box
51
66
 
67
+ def cache_bounding_box
68
+ @cached_bounding_box = nil
69
+ @cached_bounding_box = self.bounding_box
70
+ @_x_diff = @cached_bounding_box.x - self.x
71
+ @_y_diff = @cached_bounding_box.y - self.y
72
+ end
73
+
74
+ #def update_trait
75
+ # cache_bounding_box if trait_options[:bounding_box][:cache] && !@cached_bounding_box
76
+ # super
77
+ #end
78
+
52
79
  def draw_trait
53
80
  if trait_options[:bounding_box][:debug]
54
81
  $window.draw_rect(self.bounding_box, Chingu::DEBUG_COLOR, Chingu::DEBUG_ZORDER)
@@ -31,15 +31,22 @@ module Chingu
31
31
 
32
32
  module ClassMethods
33
33
  def initialize_trait(options = {})
34
- trait_options[:radius] = options
34
+ trait_options[:bounding_circle] = options
35
35
  end
36
36
  end
37
37
 
38
+ def setup_trait(options)
39
+ @cached_radius = nil
40
+ super
41
+ end
42
+
38
43
  def radius
44
+ return @cached_radius if @cached_radius
45
+
39
46
  width = self.image.width * self.factor_x.abs
40
47
  height = self.image.height * self.factor_y.abs
41
48
  radius = (width + height) / 4
42
- radius = radius * trait_options[:radius][:scale] if trait_options[:radius][:scale]
49
+ radius = radius * trait_options[:bounding_circle][:scale] if trait_options[:bounding_circle][:scale]
43
50
  return radius
44
51
  end
45
52
 
@@ -47,13 +54,23 @@ module Chingu
47
54
  radius * 2
48
55
  end
49
56
 
57
+ def cache_bounding_circle
58
+ @cached_radius = nil
59
+ @cached_radius = self.radius
60
+ end
61
+
62
+ #def update_trait
63
+ # cache_bounding_circle if trait_options[:bounding_circle][:cache] && !@cached_radius
64
+ # super
65
+ #end
66
+
50
67
  def circle_left; self.x - self.radius; end
51
68
  def circle_right; self.x + self.radius; end
52
69
  def circle_top; self.y - self.radius; end
53
70
  def circle_bottom; self.y + self.radius; end
54
71
 
55
72
  def draw_trait
56
- if trait_options[:radius][:debug]
73
+ if trait_options[:bounding_circle][:debug]
57
74
  $window.draw_circle(self.x, self.y, self.radius, Chingu::DEBUG_COLOR)
58
75
  end
59
76
  super
@@ -49,11 +49,12 @@ module Chingu
49
49
  if self.respond_to?(:bounding_box) && object2.respond_to?(:bounding_box)
50
50
  bounding_box_collision?(object2)
51
51
  elsif self.respond_to?(:radius) && object2.respond_to?(:radius)
52
- radius_collision?(object2)
52
+ bounding_circle_collision?(object2)
53
53
  else
54
- bounding_box_radius_collision?(object2)
54
+ bounding_box_bounding_circle_collision?(object2)
55
55
  end
56
56
  end
57
+ alias :collision? :collides?
57
58
 
58
59
  #
59
60
  # Collide self with a given game object by checking both objects bounding_box'es
@@ -67,8 +68,8 @@ module Chingu
67
68
  # Collide self using distance between 2 objects and their radius.
68
69
  # Returns true if colliding.
69
70
  #
70
- def radius_collision?(object2)
71
- distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
71
+ def bounding_circle_collision?(object2)
72
+ Gosu.distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
72
73
  end
73
74
 
74
75
  #
@@ -76,7 +77,7 @@ module Chingu
76
77
  #
77
78
  # http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection
78
79
  #
79
- def bounding_box_radius_collision?(object2)
80
+ def bounding_box_bounding_circle_collision?(object2)
80
81
  rect = self.respond_to?(:bounding_box) ? self.bounding_box : object2.bounding_box
81
82
  circle = self.respond_to?(:radius) ? self : object2
82
83
  radius = circle.radius.to_i
@@ -110,10 +111,10 @@ module Chingu
110
111
  # Explicit radius-collision
111
112
  # Works like each_collsion but with inline-code for speedups
112
113
  #
113
- def each_radius_collision(klasses = [])
114
+ def each_bounding_circle_collision(klasses = [])
114
115
  Array(klasses).each do |klass|
115
116
  klass.all.each do |object|
116
- yield(self, object) if distance(self.x, self.y, object.x, object.y) < self.radius + object.radius
117
+ yield(self, object) if Gosu.distance(self.x, self.y, object.x, object.y) < self.radius + object.radius
117
118
  end
118
119
  end
119
120
  end
@@ -135,7 +136,7 @@ module Chingu
135
136
  #
136
137
  # Works like each_collision but with inline-code for speedups
137
138
  #
138
- def each_radius_collision(klasses = [])
139
+ def each_bounding_circle_collision(klasses = [])
139
140
  Array(klasses).each do |klass|
140
141
  object2_list = klass.all
141
142
  #total_radius = object1.radius + object2.radius # possible optimization?
@@ -143,7 +144,7 @@ module Chingu
143
144
  self.all.each do |object1|
144
145
  object2_list.each do |object2|
145
146
  next if object1 == object2 # Don't collide objects with themselves
146
- yield object1, object2 if distance(object1.x, object1.y, object2.x, object2.y) < object1.radius + object2.radius
147
+ yield object1, object2 if Gosu.distance(object1.x, object1.y, object2.x, object2.y) < object1.radius + object2.radius
147
148
  end
148
149
  end
149
150
  end
@@ -190,7 +191,7 @@ module Chingu
190
191
  # self.all.each do |object1|
191
192
  # object2_list.each do |object2|
192
193
  # next if object1 == object2 # Don't collide objects with themselves
193
- # yield object1, object2 if object1.bounding_box_radius_collision?(object2)
194
+ # yield object1, object2 if object1.bounding_box_bounding_circle_collision?(object2)
194
195
  # end
195
196
  # end
196
197
  #end
data/lib/chingu/window.rb CHANGED
@@ -59,8 +59,15 @@ module Chingu
59
59
  @milliseconds_since_last_tick = 0
60
60
  end
61
61
 
62
- def current_parent
63
- game_state_manager.current_game_state || self
62
+ #
63
+ # Returns self inside GameState.initialize (a game state is not 'active' inside initialize())
64
+ # Or returns current active game state (as in a switched to or pushed game state)
65
+ # ... Falls back to returning $window
66
+ #
67
+ # current_scope is used to make GameObject.all and friends work everywhere.
68
+ #
69
+ def current_scope
70
+ game_state_manager.inside_state || game_state_manager.current_game_state || self
64
71
  end
65
72
 
66
73
  #
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.2
4
+ version: 0.6.3
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-25 00:00:00 +01:00
33
+ date: 2009-11-26 00:00:00 +01:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
metadata.gz.sig CHANGED
Binary file