ippa-chingu 0.4.8 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/README.rdoc +43 -23
- data/chingu.gemspec +4 -4
- data/examples/example1.rb +2 -0
- data/examples/example2.rb +63 -33
- data/examples/example4.rb +16 -3
- data/examples/example5.rb +3 -3
- data/examples/example6.rb +1 -40
- data/examples/example7.rb +9 -8
- data/examples/example8.rb +109 -0
- data/examples/example9.rb +83 -0
- data/lib/chingu.rb +17 -2
- data/lib/chingu/actor.rb +15 -0
- data/lib/chingu/animation.rb +27 -2
- data/lib/chingu/basic_game_object.rb +140 -0
- data/lib/chingu/core_extensions.rb +15 -5
- data/lib/chingu/effects.rb +1 -1
- data/lib/chingu/fpscounter.rb +0 -1
- data/lib/chingu/game_object.rb +85 -155
- data/lib/chingu/game_state.rb +4 -3
- data/lib/chingu/game_state_manager.rb +3 -4
- data/lib/chingu/game_states/debug.rb +43 -0
- data/lib/chingu/game_states/fade_to.rb +2 -2
- data/lib/chingu/helpers.rb +2 -0
- data/lib/chingu/parallax.rb +2 -2
- data/lib/chingu/particle.rb +5 -4
- data/lib/chingu/traits/collision_detection.rb +33 -0
- data/lib/chingu/traits/deprecated_module_visual.rb +108 -0
- data/lib/chingu/traits/deprecated_visual.rb +100 -0
- data/lib/chingu/traits/effect.rb +80 -0
- data/lib/chingu/traits/input.rb +15 -0
- data/lib/chingu/traits/velocity.rb +59 -0
- data/lib/chingu/window.rb +18 -3
- metadata +16 -4
data/lib/chingu/parallax.rb
CHANGED
@@ -30,9 +30,9 @@ module Chingu
|
|
30
30
|
end
|
31
31
|
|
32
32
|
#
|
33
|
-
# TODO: make use of
|
33
|
+
# TODO: make use of $window.milliseconds_since_last_update here!
|
34
34
|
#
|
35
|
-
def update
|
35
|
+
def update
|
36
36
|
@backgrounds.each do |background|
|
37
37
|
background.x = -@x / background.damping
|
38
38
|
background.y = @y / background.damping
|
data/lib/chingu/particle.rb
CHANGED
@@ -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
|
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,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
|
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
|
150
|
+
@game_state_manager.update
|
136
151
|
end
|
137
152
|
|
138
153
|
#
|