ippa-chingu 0.4.8 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -30,9 +30,9 @@ module Chingu
30
30
  end
31
31
 
32
32
  #
33
- # TODO: make use of time here!
33
+ # TODO: make use of $window.milliseconds_since_last_update here!
34
34
  #
35
- def update(time)
35
+ def update
36
36
  @backgrounds.each do |background|
37
37
  background.x = -@x / background.damping
38
38
  background.y = @y / background.damping
@@ -1,18 +1,19 @@
1
1
  #
2
2
  # Our basic particle class
3
3
  #
4
- include Chingu
5
4
  module Chingu
6
- class Particle < Chingu::GameObject
5
+ class Particle < Chingu::GameObject
6
+ add_component :effect
7
+
7
8
  def initialize(options)
8
9
  super({:mode => :additive}.merge(options))
9
10
  @rotation = options[:rotation] || 0
10
11
  @zoom = options[:zoom] || 0
11
- @fade = options[:fade] || 0
12
+ @fade = options[:fade] || 0
12
13
  @animation = options[:animation] || nil
13
14
  end
14
15
 
15
- def update(time)
16
+ def update
16
17
  self.image = @animation.next! if @animation
17
18
  self.rotate(@rotation)
18
19
  self.zoom(@zoom)
@@ -0,0 +1,33 @@
1
+ module Chingu
2
+ module Components
3
+ #
4
+ # TODO: everything. convert to class?
5
+ #
6
+ # Use QuadTrees: http://lab.polygonal.de/2007/09/09/quadtree-demonstration/
7
+ #
8
+ module CollisionDetection
9
+
10
+ def self.included(base)
11
+ base.extend(ClassMethods)
12
+ end
13
+
14
+ def collision?(object2)
15
+ self.rect.collide_rect?(object2.rect)
16
+ end
17
+
18
+ module ClassMethods
19
+ def each_collision(klasses = [])
20
+ # Make sure klasses is always an array.
21
+ Array(klasses).each do |klass|
22
+ self.all.each do |object1|
23
+ klass.all.each do |object2|
24
+ yield object1, object2 if object1.collision?(object2)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,108 @@
1
+ module Chingu
2
+ module Components
3
+ module Visual
4
+ attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :color, :mode, :zorder
5
+
6
+ #
7
+ # :x screen x-coordinate (default 0, to the left)
8
+ # :y screen y-coordinate (default 0, top of screen)
9
+ # :angle angle of object, used in draw_rot, (default 0, no rotation)
10
+ # :zorder a gameclass "foo" with higher zorder then gameclass "bar" is drawn on top of "foo".
11
+ # :center_x relative horizontal position of the rotation center on the image.
12
+ # 0 is the left border, 1 is the right border, 0.5 is the center (default 0.5)
13
+ # :center_y see center_x. (default 0.5)
14
+ # :factor_x horizontal zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
15
+ # :factor_y vertical zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
16
+ #
17
+ # :update [true|false] Automaticly call #update on object each gameloop. Default +true+.
18
+ # :draw [true|false] Automaticly call #update on object each gameloop. Default +true+.
19
+ #
20
+
21
+ def self.included(base)
22
+ #base.__send__(:alias_method, :orig_initialize, :initialize)
23
+ #base.__send__(:alias_method, :initialize, :orig_initialize)
24
+
25
+ #base.__send__( :alias_method, :initialize_without_extras, :initialize )
26
+ #base.__send__( :alias_method, :initialize, :initialize_with_extras )
27
+ end
28
+
29
+ alias_method :orig_initialize, :initialize
30
+ def initialize(options = {})
31
+
32
+ puts "Visual#initialize"
33
+
34
+ # draw_rot arguments
35
+ @image = options[:image] if options[:image].is_a? Gosu::Image
36
+ @image = Image[options[:image]] if options[:image].is_a? String
37
+ @x = options[:x] || 0
38
+ @y = options[:y] || 0
39
+ @angle = options[:angle] || 0
40
+ @zorder = options[:zorder] || 100
41
+ @center_x = options[:center_x] || options[:center] || 0.5
42
+ @center_y = options[:center_y] || options[:center] || 0.5
43
+ @factor_x = options[:factor_x] || options[:factor] || 1.0
44
+ @factor_y = options[:factor_y] || options[:factor] || 1.0
45
+ @mode = options[:mode] || :default # :additive is also available.
46
+ @color = Gosu::Color.new(options[:color]) if options[:color].is_a? Bignum
47
+ @color = options[:color] if options[:color].respond_to?(:alpha)
48
+ @color = Gosu::Color.new(0xFFFFFFFF) if @color.nil?
49
+
50
+ # Shortcuts for draw_rot arguments
51
+ @factor = 1
52
+
53
+ # gameloop/framework logic
54
+ @update = options[:update] || true
55
+ @draw = options[:draw] || true
56
+
57
+ orig_initialize(options)
58
+ #orig_initialize
59
+ end
60
+
61
+ #
62
+ # Quick way of setting both factor_x and factor_y
63
+ #
64
+ def factor=(factor)
65
+ @factor_x = @factor_y = factor
66
+ end
67
+
68
+ #
69
+ # Quick way of setting both center_x and center_y
70
+ #
71
+ def center=(factor)
72
+ @center_x = @center_y = factor
73
+ end
74
+
75
+ #
76
+ # Returns true if object is inside the game window, false if outside
77
+ #
78
+ def inside_window?(x = @x, y = @y)
79
+ x >= 0 && x <= $window.width && y >= 0 && y <= $window.height
80
+ end
81
+
82
+ #
83
+ # Returns true object is outside the game window
84
+ #
85
+ def outside_window?(x = @x, y = @y)
86
+ not inside_window?(x,y)
87
+ end
88
+
89
+ #
90
+ # The core of the gameclass, the draw_rot encapsulation. Draws the sprite on screen.
91
+ # Calling #to_i on @x and @y enables thoose to be Float's, for subpixel slow movement in #update
92
+ #
93
+ def draw(parent)
94
+ @image.draw_rot(@x.to_i, @y.to_i, @zorder, @angle, @center_x, @center_y, @factor_x, @factor_y, @color, @mode)
95
+ #parent.image.draw_rot( parent.x.to_i,
96
+ # parent.y.to_i,
97
+ # parent.zorder,
98
+ # parent.angle,
99
+ # parent.center_x,
100
+ # parent.center_y,
101
+ # parent.factor_x,
102
+ # parent.factor_y,
103
+ # parent.color,
104
+ # parent.mode)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,100 @@
1
+ module Chingu
2
+ module Components
3
+ class Visual
4
+
5
+ def initialize(parent_class, options)
6
+ @parent_class = parent_class
7
+ @parent_class.class_eval do
8
+ attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :color, :mode, :zorder
9
+
10
+ # Quick way of setting both factor_x and factor_y
11
+ def factor=(factor)
12
+ @factor_x = @factor_y = factor
13
+ end
14
+
15
+ # Quick way of setting both center_x and center_y
16
+ def center=(factor)
17
+ @center_x = @center_y = factor
18
+ end
19
+
20
+ # Returns true if object is inside the game window, false if outside
21
+ def inside_window?(x = @x, y = @y)
22
+ x >= 0 && x <= $window.width && y >= 0 && y <= $window.height
23
+ end
24
+
25
+ # Returns true object is outside the game window
26
+ def outside_window?(x = @x, y = @y)
27
+ not inside_window?(x,y)
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ #
34
+ # :x screen x-coordinate (default 0, to the left)
35
+ # :y screen y-coordinate (default 0, top of screen)
36
+ # :angle angle of object, used in draw_rot, (default 0, no rotation)
37
+ # :zorder a gameclass "foo" with higher zorder then gameclass "bar" is drawn on top of "foo".
38
+ # :center_x relative horizontal position of the rotation center on the image.
39
+ # 0 is the left border, 1 is the right border, 0.5 is the center (default 0.5)
40
+ # :center_y see center_x. (default 0.5)
41
+ # :factor_x horizontal zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
42
+ # :factor_y vertical zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
43
+ #
44
+ # :update [true|false] Automaticly call #update on object each gameloop. Default +true+.
45
+ # :draw [true|false] Automaticly call #update on object each gameloop. Default +true+.
46
+ #
47
+ def setup(parent_instance, options)
48
+ @parent_instance = parent_instance
49
+ @parent_instance.instance_eval do
50
+ # draw_rot arguments
51
+ @image = options[:image] if options[:image].is_a? Gosu::Image
52
+ @image = Image[options[:image]] if options[:image].is_a? String
53
+ @x = options[:x] || 0
54
+ @y = options[:y] || 0
55
+ @angle = options[:angle] || 0
56
+ @zorder = options[:zorder] || 100
57
+ @center_x = options[:center_x] || options[:center] || 0.5
58
+ @center_y = options[:center_y] || options[:center] || 0.5
59
+ @factor_x = options[:factor_x] || options[:factor] || 1.0
60
+ @factor_y = options[:factor_y] || options[:factor] || 1.0
61
+
62
+ @color = Gosu::Color.new(options[:color]) if options[:color].is_a? Bignum
63
+ @color = options[:color] if options[:color].respond_to?(:alpha)
64
+ @color = Gosu::Color.new(0xFFFFFFFF) if @color.nil?
65
+
66
+ @mode = options[:mode] || :default # :additive is also available.
67
+
68
+ # Shortcuts for draw_rot arguments
69
+ @factor = 1
70
+
71
+ # gameloop/framework logic
72
+ @update = options[:update] || true
73
+ @draw = options[:draw] || true
74
+ end
75
+
76
+ end
77
+
78
+ def update(parent)
79
+ end
80
+
81
+ #
82
+ # The core of the gameclass, the draw_rot encapsulation. Draws the sprite on screen.
83
+ # Calling #to_i on @x and @y enables thoose to be Float's, for subpixel slow movement in #update
84
+ #
85
+ def draw(parent)
86
+ ## @image.draw_rot(@x.to_i, @y.to_i, @zorder, @angle, @center_x, @center_y, @factor_x, @factor_y, @color, @mode)
87
+ parent.image.draw_rot( parent.x.to_i,
88
+ parent.y.to_i,
89
+ parent.zorder,
90
+ parent.angle,
91
+ parent.center_x,
92
+ parent.center_y,
93
+ parent.factor_x,
94
+ parent.factor_y,
95
+ parent.color,
96
+ parent.mode)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,80 @@
1
+ module Chingu
2
+ module Components
3
+ class Effect
4
+ #
5
+ # Adds .rotating .fading and .zooming to any GameObject.
6
+ #
7
+ # TODO: better naming? suggestions:
8
+ #
9
+ # basic gosu unit <-> automation name
10
+ # ==============================================
11
+ # angle <-> rotation? rotating? automatic_angle?
12
+ # factor <-> growth? scale? automatic_zoom?
13
+ # alpha <-> fade
14
+ #
15
+ def initialize(parent_class, options)
16
+ @parent_class = parent_class
17
+ @parent_class.class_eval do
18
+ attr_accessor :rotating, :fading, :zooming
19
+
20
+ # Zoom - increase @factor_x and @factor_y at the same time.
21
+ def zoom(amount = 0.1)
22
+ @factor_x += amount
23
+ @factor_y += amount
24
+ end
25
+
26
+ # Zoom Out - decrease @factor_x and @factor_y at the same time.
27
+ def zoom_out(amount = 0.1)
28
+ @factor_x -= amount
29
+ @factor_y -= amount
30
+ end
31
+
32
+ # Rotate object 'amount' degrees
33
+ def rotate(amount = 1)
34
+ @angle += amount
35
+ end
36
+
37
+ # Fade object by decreasing/increasing color.alpha
38
+ def fade(amount = 1)
39
+ return if amount == 0
40
+
41
+ new_alpha = @color.alpha + amount
42
+ if amount < 0
43
+ @color.alpha = [0, new_alpha].max
44
+ else
45
+ @color.alpha = [0, new_alpha].min
46
+ end
47
+ end
48
+
49
+ # Fade out objects color by decreasing color.alpha
50
+ def fade_out(amount = 1)
51
+ fade(-amount)
52
+ end
53
+
54
+ # Fade in objects color by increasing color.alpha
55
+ def fade_in(amount = 1)
56
+ fade(amount)
57
+ end
58
+ end
59
+ end
60
+
61
+ #
62
+ # Setup
63
+ #
64
+ def setup(parent_instance, options)
65
+ @parent_instance = parent_instance
66
+ @parent_instance.instance_eval do
67
+ @rotating = options[:rotating] || nil
68
+ @zooming = options[:zooming] || nil
69
+ @fading = options[:fading] || nil
70
+ end
71
+ end
72
+
73
+ def update(parent)
74
+ parent.rotate(parent.rotating) if parent.rotating
75
+ parent.fade(parent.fading) if parent.fading
76
+ parent.zoom(parent.zooming) if parent.zooming
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,15 @@
1
+ module Chingu
2
+ module Components
3
+ module Input
4
+
5
+ def input=(input_map)
6
+ @input = input_map
7
+ @parent.add_input_client(self) if @parent
8
+ end
9
+
10
+ def input
11
+ @input
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ module Chingu
2
+ module Components
3
+ #
4
+ # A chingu component providing velocity and acceleration logic.
5
+ #
6
+ class Velocity
7
+
8
+ def initialize(parent_class, options)
9
+ @parent_class = parent_class
10
+ @parent_class.class_eval do
11
+ attr_accessor :velocity_x, :velocity_y, :acceleration_x, :acceleration_y, :max_velocity
12
+
13
+ def stop
14
+ @acceleration_y = @acceleration_x = @velocity_y = @acceleration_y = 0
15
+ end
16
+ end
17
+ end
18
+
19
+ #
20
+ # Setup
21
+ #
22
+ def setup(parent_instance, options)
23
+ @parent_instance = parent_instance
24
+ @parent_instance.instance_eval do
25
+ @velocity_x = options[:velocity_x] || 0
26
+ @velocity_y = options[:velocity_y] || 0
27
+ @acceleration_x = options[:acceleration_x] || 0
28
+ @acceleration_y = options[:acceleration_y] || 0
29
+ @max_velocity = options[:max_velocity] || 1000
30
+ end
31
+ end
32
+
33
+ #
34
+ # Modifies X & Y of parent
35
+ #
36
+ def update(parent)
37
+ #
38
+ # This is slower oddly enough?
39
+ #
40
+ #parent.velocity_y += parent.acceleration_y if (parent.velocity_y + parent.acceleration_y).abs < parent.max_velocity
41
+ #parent.velocity_x += parent.acceleration_x if (parent.velocity_x + parent.acceleration_x).abs < parent.max_velocity
42
+ #parent.y += parent.velocity_y
43
+ #parent.x += parent.velocity_x
44
+
45
+ parent.instance_eval do
46
+ @velocity_y += @acceleration_y if (@velocity_y + @acceleration_y).abs < @max_velocity
47
+ @velocity_x += @acceleration_x if (@velocity_x + @acceleration_x).abs < @max_velocity
48
+ #vel_y = (@velocity_y + @acceleration_y).abs
49
+ #@velocity_y = vel_y if vel_y < @max_velocity
50
+ #vel_x = (@velocity_x + @acceleration_x).abs
51
+ #@velocity_x = vel_x if vel_x < @max_velocity
52
+
53
+ @y += @velocity_y
54
+ @x += @velocity_x
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/chingu/window.rb CHANGED
@@ -44,6 +44,7 @@ module Chingu
44
44
 
45
45
  @fps_counter = FPSCounter.new
46
46
  @game_state_manager = GameStateManager.new
47
+ @milliseconds_since_last_tick = 0
47
48
  end
48
49
 
49
50
  def add_game_object(object)
@@ -67,6 +68,13 @@ module Chingu
67
68
  def ticks
68
69
  @fps_counter.ticks
69
70
  end
71
+
72
+ #
73
+ # Mathematical short name for "milliseconds since last tick"
74
+ #
75
+ def dt
76
+ @milliseconds_since_last_tick
77
+ end
70
78
 
71
79
  #
72
80
  # Chingus core-logic / loop. Gosu will call this each game-iteration.
@@ -78,8 +86,15 @@ module Chingu
78
86
  # Without this self.fps would return an incorrect value.
79
87
  # If you override this in your Chingu::Window class, make sure to call super.
80
88
  #
81
- @milliseconds_since_last_tick = @fps_counter.register_tick
89
+ @milliseconds_since_last_tick = @fps_counter.register_tick
82
90
 
91
+ intermediate_update
92
+ end
93
+
94
+ #
95
+ # "game logic" update that is safe to call even between Gosus update-calls
96
+ #
97
+ def intermediate_update
83
98
  #
84
99
  # Dispatch inputmap for main window
85
100
  #
@@ -123,7 +138,7 @@ module Chingu
123
138
  # Call update() on all game objects in main game window.
124
139
  #
125
140
  def update_game_objects
126
- @game_objects.each { |object| object.update(@milliseconds_since_last_tick) }
141
+ @game_objects.each { |object| object.update }
127
142
  end
128
143
 
129
144
  #
@@ -132,7 +147,7 @@ module Chingu
132
147
  # -> call update on all game objects in that state
133
148
  #
134
149
  def update_game_state_manager
135
- @game_state_manager.update(@milliseconds_since_last_tick)
150
+ @game_state_manager.update
136
151
  end
137
152
 
138
153
  #