gosu_extensions 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/lib/traits/moveable.rb +5 -122
- data/lib/traits/pod.rb +15 -14
- data/lib/units/sprite.rb +159 -0
- data/lib/units/thing.rb +62 -85
- data/spec/lib/units/thing_spec.rb +4 -2
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/lib/traits/moveable.rb
CHANGED
@@ -12,143 +12,26 @@ module Moveable extend Trait
|
|
12
12
|
Backwards = :backwards; def self.backwards strength = 1.0; [Backwards, strength] end
|
13
13
|
# TODO Jump = :jump
|
14
14
|
|
15
|
-
|
16
|
-
klass.extend ClassMethods
|
17
|
-
end
|
18
|
-
|
19
|
-
module ClassMethods
|
20
|
-
|
21
|
-
# Initial setting.
|
22
|
-
#
|
23
|
-
def friction amount = nil, &block
|
24
|
-
to_execute = block_given? ? block : lambda { amount }
|
25
|
-
InitializerHooks.register self do
|
26
|
-
self.friction = to_execute[]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
def velocity amount = nil, &block
|
30
|
-
to_execute = block_given? ? block : lambda { amount }
|
31
|
-
InitializerHooks.register self do
|
32
|
-
self.velocity = to_execute[]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
def rotation amount = nil, &block
|
36
|
-
to_execute = block_given? ? block : lambda { amount }
|
37
|
-
InitializerHooks.register self do
|
38
|
-
self.rotation = to_execute[]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def random_rotation
|
43
|
-
rotation { 2*Math::PI*rand }
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
# Directly set the position of our Moveable using a vector.
|
49
|
-
#
|
50
|
-
def warp vector
|
51
|
-
@shape.body.p = vector
|
52
|
-
end
|
53
|
-
|
54
|
-
# Directly set the position of our Moveable.
|
55
|
-
#
|
56
|
-
def warp_to x, y
|
57
|
-
@shape.body.p = CP::Vec2.new(x, y)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Directly set the position of our Moveable.
|
61
|
-
#
|
62
|
-
def position= position
|
63
|
-
@shape.body.p = position
|
64
|
-
end
|
65
|
-
def position
|
66
|
-
@shape.body.p
|
67
|
-
end
|
68
|
-
|
69
|
-
# Directly set the torque of our Moveable.
|
70
|
-
#
|
71
|
-
def torque= torque
|
72
|
-
@shape.body.t = torque
|
73
|
-
end
|
74
|
-
def torque
|
75
|
-
@shape.body.t
|
76
|
-
end
|
77
|
-
|
78
|
-
# Directly set the speed of our Moveable.
|
79
|
-
#
|
80
|
-
def speed= v
|
81
|
-
@shape.body.v = v
|
82
|
-
end
|
83
|
-
def speed
|
84
|
-
@shape.body.v
|
85
|
-
end
|
86
|
-
def current_speed
|
87
|
-
speed.length
|
88
|
-
end
|
89
|
-
|
90
|
-
# Directly set the rotation of our Moveable.
|
91
|
-
#
|
92
|
-
def rotation= rotation
|
93
|
-
@shape.body.a = rotation % (2*Math::PI)
|
94
|
-
end
|
95
|
-
def rotation
|
96
|
-
@shape.body.a
|
97
|
-
end
|
98
|
-
def drawing_rotation
|
99
|
-
self.rotation.radians_to_gosu
|
100
|
-
end
|
101
|
-
def rotation_vector
|
102
|
-
@shape.body.a.radians_to_vec2
|
103
|
-
end
|
104
|
-
|
105
|
-
def friction= friction
|
106
|
-
@shape.u = friction
|
107
|
-
end
|
108
|
-
def friction
|
109
|
-
@shape.u
|
110
|
-
end
|
111
|
-
|
112
|
-
# Length is the vector length you want.
|
113
|
-
#
|
114
|
-
# Note: radians_to_vec2
|
115
|
-
#
|
116
|
-
def rotation_as_vector length
|
117
|
-
rotation = -self.rotation + Math::PI / 2
|
118
|
-
x = Math.sin rotation
|
119
|
-
y = Math.cos rotation
|
120
|
-
total_length = Math.sqrt(x**2 + y**2)
|
121
|
-
multiplier = length / total_length
|
122
|
-
CP::Vec2.new(x * multiplier, y * multiplier)
|
123
|
-
end
|
124
|
-
|
125
|
-
def move
|
126
|
-
|
127
|
-
end
|
128
|
-
|
129
|
-
# Methods for controls.
|
15
|
+
# Default methods for controls.
|
130
16
|
#
|
131
17
|
def accelerate strength = 1.0
|
132
18
|
self.speed += self.rotation_vector * strength/SUBSTEPS
|
133
19
|
end
|
134
20
|
def move_left strength = 1.0
|
135
|
-
self.speed += CP::Vec2.new(-strength.to_f/SUBSTEPS, 0)
|
21
|
+
self.speed += CP::Vec2.new(-strength.to_f/SUBSTEPS, 0)
|
136
22
|
end
|
137
23
|
def move_right strength = 1.0
|
138
|
-
self.speed += CP::Vec2.new(strength.to_f/SUBSTEPS, 0)
|
24
|
+
self.speed += CP::Vec2.new(strength.to_f/SUBSTEPS, 0)
|
139
25
|
end
|
140
26
|
def move_up strength = 1.0
|
141
|
-
self.speed += CP::Vec2.new(0, -strength.to_f/SUBSTEPS)
|
27
|
+
self.speed += CP::Vec2.new(0, -strength.to_f/SUBSTEPS)
|
142
28
|
end
|
143
29
|
def move_down strength = 1.0
|
144
|
-
self.speed += CP::Vec2.new(0, strength.to_f/SUBSTEPS)
|
30
|
+
self.speed += CP::Vec2.new(0, strength.to_f/SUBSTEPS)
|
145
31
|
end
|
146
32
|
def backwards strength = 1.0
|
147
33
|
accelerate -0.5*strength
|
148
34
|
end
|
149
|
-
# def jump strength = 100
|
150
|
-
# self.speed += CP::Vec2.new(0, -strength.to_f/SUBSTEPS) if self.current_speed <= 1
|
151
|
-
# end
|
152
35
|
|
153
36
|
# Movement rules
|
154
37
|
#
|
data/lib/traits/pod.rb
CHANGED
@@ -26,6 +26,7 @@ module Pod extend Trait
|
|
26
26
|
|
27
27
|
def holds_attachments
|
28
28
|
class_inheritable_accessor :prototype_attachments
|
29
|
+
self.prototype_attachments ||= []
|
29
30
|
hook = lambda do
|
30
31
|
self.class.prototype_attachments.each do |type, x, y|
|
31
32
|
attach type.new(self.window), x, y
|
@@ -42,7 +43,6 @@ module Pod extend Trait
|
|
42
43
|
# attach Cannon, 30, 10
|
43
44
|
#
|
44
45
|
def attach type, x, y
|
45
|
-
self.prototype_attachments ||= []
|
46
46
|
self.prototype_attachments << [type, x, y]
|
47
47
|
end
|
48
48
|
|
@@ -50,18 +50,7 @@ module Pod extend Trait
|
|
50
50
|
|
51
51
|
module InstanceMethods
|
52
52
|
|
53
|
-
|
54
|
-
attachment.extend Attachable # This is where Ruby shines.
|
55
|
-
window.register attachment
|
56
|
-
end
|
57
|
-
|
58
|
-
#
|
59
|
-
#
|
60
|
-
def attachments
|
61
|
-
@attachments || @attachments = []
|
62
|
-
end
|
63
|
-
|
64
|
-
#
|
53
|
+
# Attach an instance to this.
|
65
54
|
#
|
66
55
|
def attach attachment, x, y
|
67
56
|
# TODO Move to better place.
|
@@ -72,12 +61,24 @@ module Pod extend Trait
|
|
72
61
|
attachments << attachment
|
73
62
|
end
|
74
63
|
|
75
|
-
#
|
64
|
+
# Detach an instance from this.
|
76
65
|
#
|
77
66
|
def detach attachment
|
78
67
|
self.attachments.delete attachment if self.attachments
|
79
68
|
end
|
80
69
|
|
70
|
+
|
71
|
+
def materialize attachment
|
72
|
+
attachment.extend Attachable # This is where Ruby shines.
|
73
|
+
window.register attachment
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
#
|
78
|
+
def attachments
|
79
|
+
@attachments || @attachments = [] # TODO use Attachments.new
|
80
|
+
end
|
81
|
+
|
81
82
|
#
|
82
83
|
#
|
83
84
|
def move_attachments
|
data/lib/units/sprite.rb
CHANGED
@@ -1,5 +1,164 @@
|
|
1
|
+
# Sprite is the basic object in Gosu Extensions.
|
2
|
+
#
|
3
|
+
# It is different from Thing in that it has no body. It's just a bodyless, displayed sprite.
|
4
|
+
#
|
1
5
|
class Sprite
|
2
6
|
|
3
7
|
include VectorUtilities
|
8
|
+
include Imageable
|
9
|
+
include InitializerHooks
|
10
|
+
include ItIsA
|
11
|
+
it_is Moveable
|
12
|
+
|
13
|
+
attr_reader :window
|
14
|
+
|
15
|
+
# Every thing knows the window it is attached to.
|
16
|
+
#
|
17
|
+
def initialize window
|
18
|
+
@window = window
|
19
|
+
self.destroyed = false
|
20
|
+
after_initialize
|
21
|
+
end
|
22
|
+
|
23
|
+
# Default layer is Layer::Players.
|
24
|
+
#
|
25
|
+
def layer
|
26
|
+
Layer::Players
|
27
|
+
end
|
28
|
+
# Default rotation is upwards.
|
29
|
+
#
|
30
|
+
def rotation
|
31
|
+
@rotation || -Math::PI/2
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
|
36
|
+
# Define a layer.
|
37
|
+
#
|
38
|
+
def layer layer
|
39
|
+
define_method :layer do
|
40
|
+
layer
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
#
|
46
|
+
def rotation amount = nil, &block
|
47
|
+
# Override default.
|
48
|
+
#
|
49
|
+
to_execute = block_given? ? block : lambda { amount }
|
50
|
+
InitializerHooks.append self do
|
51
|
+
self.rotation = to_execute[]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
def random_rotation
|
55
|
+
rotation { 2*Math::PI*rand }
|
56
|
+
end
|
57
|
+
|
58
|
+
# Plays a random sound of the given sounds.
|
59
|
+
#
|
60
|
+
def plays paths, options = {}
|
61
|
+
paths = [*paths]
|
62
|
+
InitializerHooks.register self do
|
63
|
+
sound = Gosu::Sample.new self.window, File.join(Resources.root, paths[rand(paths.size)])
|
64
|
+
sound.play options[:volume] || 1.0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
# Override this.
|
71
|
+
#
|
72
|
+
def move
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# Do something threaded.
|
77
|
+
#
|
78
|
+
# Default is: Instantly, in the next step.
|
79
|
+
#
|
80
|
+
def threaded time = 1, &code
|
81
|
+
self.window.threaded time, &code
|
82
|
+
end
|
83
|
+
|
84
|
+
# Some things you can only do every x time units.
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
# sometimes :loading, self.frequency do
|
88
|
+
# projectile = self.shot.shoot_from self
|
89
|
+
# projectile.rotation = self.muzzle_rotation[target]
|
90
|
+
# projectile.speed = self.muzzle_velocity[target] * projectile.velocity
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
def sometimes variable, units = 1, &block
|
94
|
+
name = :"@#{variable}"
|
95
|
+
return if instance_variable_get(name)
|
96
|
+
instance_variable_set name, true
|
97
|
+
result = block.call
|
98
|
+
threaded units.to_i do
|
99
|
+
self.instance_variable_set name, false
|
100
|
+
end
|
101
|
+
result
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
#
|
106
|
+
def add_to environment
|
107
|
+
# A sprite is not added to the physical environment.
|
108
|
+
end
|
109
|
+
|
110
|
+
# Destroy this thing.
|
111
|
+
#
|
112
|
+
attr_writer :destroyed
|
113
|
+
def destroyed?
|
114
|
+
@destroyed
|
115
|
+
end
|
116
|
+
def destroyed!
|
117
|
+
# Override
|
118
|
+
end
|
119
|
+
def destroy!
|
120
|
+
return if self.destroyed?
|
121
|
+
self.destroyed!
|
122
|
+
self.destroyed = true
|
123
|
+
end
|
124
|
+
|
125
|
+
# Draws its image.
|
126
|
+
#
|
127
|
+
def draw
|
128
|
+
self.image.draw_rot self.position.x, self.position.y, self.layer, self.drawing_rotation, 0.5, 0.5, *self.current_size
|
129
|
+
end
|
130
|
+
def current_size
|
131
|
+
[1.0, 1.0] # default implementation - change this to [1.0, 2.0] if you want a "light" version ;)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Derived Position/Movement methods.
|
135
|
+
#
|
136
|
+
def warp vector
|
137
|
+
self.position = vector
|
138
|
+
end
|
139
|
+
# Directly set the position of our Moveable.
|
140
|
+
#
|
141
|
+
def warp_to x, y
|
142
|
+
warp CP::Vec2.new(x, y)
|
143
|
+
end
|
144
|
+
def drawing_rotation
|
145
|
+
self.rotation.radians_to_gosu
|
146
|
+
end
|
147
|
+
def rotation_vector
|
148
|
+
self.rotation.radians_to_vec2
|
149
|
+
end
|
150
|
+
def current_speed
|
151
|
+
speed.length
|
152
|
+
end
|
153
|
+
|
154
|
+
# Movement and Position.
|
155
|
+
#
|
156
|
+
|
157
|
+
#
|
158
|
+
#
|
159
|
+
attr_accessor :position, :speed
|
160
|
+
def rotation= rotation
|
161
|
+
@rotation = rotation % (2*Math::PI)
|
162
|
+
end
|
4
163
|
|
5
164
|
end
|
data/lib/units/thing.rb
CHANGED
@@ -1,34 +1,8 @@
|
|
1
|
+
# Thing is a physical version of a sprite. Collides and has a mass and a moment.
|
2
|
+
#
|
1
3
|
class Thing < Sprite
|
2
4
|
|
3
|
-
|
4
|
-
include ItIsA
|
5
|
-
|
6
|
-
# TODO Move these.
|
7
|
-
#
|
8
|
-
it_is Imageable
|
9
|
-
it_is Moveable
|
10
|
-
|
11
|
-
attr_writer :layer
|
12
|
-
attr_reader :window, :shape
|
13
|
-
|
14
|
-
# Every thing knows the window it is attached to.
|
15
|
-
#
|
16
|
-
def initialize window
|
17
|
-
@window = window
|
18
|
-
self.destroyed = false
|
19
|
-
after_initialize
|
20
|
-
end
|
21
|
-
|
22
|
-
# Default layer is Layer::Players.
|
23
|
-
#
|
24
|
-
def self.layer layer
|
25
|
-
InitializerHooks.register self do
|
26
|
-
self.layer = layer
|
27
|
-
end
|
28
|
-
end
|
29
|
-
def layer
|
30
|
-
@layer || Layer::Players
|
31
|
-
end
|
5
|
+
attr_reader :shape
|
32
6
|
|
33
7
|
def mass
|
34
8
|
0.1
|
@@ -36,6 +10,9 @@ class Thing < Sprite
|
|
36
10
|
def moment
|
37
11
|
0.1
|
38
12
|
end
|
13
|
+
def friction
|
14
|
+
100.0
|
15
|
+
end
|
39
16
|
|
40
17
|
class << self
|
41
18
|
@@form_shape_class_mapping = {
|
@@ -49,7 +26,7 @@ class Thing < Sprite
|
|
49
26
|
define_method :radius do
|
50
27
|
args.first # TODO fix!
|
51
28
|
end
|
52
|
-
InitializerHooks.
|
29
|
+
InitializerHooks.prepend self do
|
53
30
|
shape_class = form_shape_class_mapping[form]
|
54
31
|
raise "Shape #{form} does not exist." unless shape_class
|
55
32
|
|
@@ -71,6 +48,19 @@ class Thing < Sprite
|
|
71
48
|
amount
|
72
49
|
end
|
73
50
|
end
|
51
|
+
def friction amount
|
52
|
+
define_method :friction do
|
53
|
+
amount
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# TODO needed?
|
57
|
+
#
|
58
|
+
def velocity amount = nil, &block
|
59
|
+
to_execute = block_given? ? block : lambda { amount }
|
60
|
+
InitializerHooks.register self do
|
61
|
+
self.velocity = to_execute[]
|
62
|
+
end
|
63
|
+
end
|
74
64
|
|
75
65
|
def collision_type type
|
76
66
|
to_execute = lambda do |shape|
|
@@ -84,60 +74,12 @@ class Thing < Sprite
|
|
84
74
|
end
|
85
75
|
end
|
86
76
|
|
87
|
-
# Plays a random sound of the given sounds.
|
88
|
-
#
|
89
|
-
def plays paths, options = {}
|
90
|
-
paths = [*paths]
|
91
|
-
InitializerHooks.register self do
|
92
|
-
sound = Gosu::Sample.new self.window, File.join(Resources.root, paths[rand(paths.size)])
|
93
|
-
sound.play options[:volume] || 1.0
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
77
|
end
|
98
78
|
|
99
|
-
#
|
79
|
+
# Unregister with the environment if destroyed.
|
100
80
|
#
|
101
|
-
# Default is: Instantly, in the next step.
|
102
|
-
#
|
103
|
-
def threaded time = 1, &code
|
104
|
-
self.window.threaded time, &code
|
105
|
-
end
|
106
|
-
|
107
|
-
# Destroy this thing.
|
108
|
-
#
|
109
|
-
attr_writer :destroyed
|
110
|
-
def destroyed?
|
111
|
-
@destroyed
|
112
|
-
end
|
113
|
-
def destroyed!
|
114
|
-
# Override
|
115
|
-
end
|
116
81
|
def destroy!
|
117
|
-
|
118
|
-
self.destroyed!
|
119
|
-
self.window.unregister self
|
120
|
-
self.destroyed = true
|
121
|
-
end
|
122
|
-
|
123
|
-
# Some things you can only do every x time units.
|
124
|
-
#
|
125
|
-
# Example:
|
126
|
-
# sometimes :loading, self.frequency do
|
127
|
-
# projectile = self.shot.shoot_from self
|
128
|
-
# projectile.rotation = self.muzzle_rotation[target]
|
129
|
-
# projectile.speed = self.muzzle_velocity[target] * projectile.velocity
|
130
|
-
# end
|
131
|
-
#
|
132
|
-
def sometimes variable, units = 1, &block
|
133
|
-
name = :"@#{variable}"
|
134
|
-
return if instance_variable_get(name)
|
135
|
-
instance_variable_set name, true
|
136
|
-
result = block.call
|
137
|
-
threaded units.to_i do
|
138
|
-
self.instance_variable_set name, false
|
139
|
-
end
|
140
|
-
result
|
82
|
+
self.window.unregister self if super
|
141
83
|
end
|
142
84
|
|
143
85
|
# Add this thing to an environment.
|
@@ -149,13 +91,48 @@ class Thing < Sprite
|
|
149
91
|
environment.add_shape self.shape
|
150
92
|
end
|
151
93
|
|
152
|
-
#
|
94
|
+
# Movement and Position
|
95
|
+
#
|
96
|
+
|
97
|
+
#
|
98
|
+
#
|
99
|
+
def speed= v
|
100
|
+
@shape.body.v = v
|
101
|
+
end
|
102
|
+
def speed
|
103
|
+
@shape.body.v
|
104
|
+
end
|
105
|
+
#
|
106
|
+
#
|
107
|
+
def rotation= rotation
|
108
|
+
@shape.body.a = rotation % (2*Math::PI)
|
109
|
+
end
|
110
|
+
def rotation
|
111
|
+
@shape.body.a
|
112
|
+
end
|
113
|
+
#
|
114
|
+
#
|
115
|
+
def position= position
|
116
|
+
@shape.body.p = position
|
117
|
+
end
|
118
|
+
def position
|
119
|
+
@shape.body.p
|
120
|
+
end
|
121
|
+
#
|
122
|
+
#
|
123
|
+
def friction= friction
|
124
|
+
@shape.u = friction
|
125
|
+
end
|
126
|
+
def friction
|
127
|
+
@shape.u
|
128
|
+
end
|
129
|
+
#
|
153
130
|
#
|
154
|
-
def
|
155
|
-
|
131
|
+
def torque= torque
|
132
|
+
@shape.body.t = torque
|
156
133
|
end
|
157
|
-
def
|
158
|
-
|
134
|
+
def torque
|
135
|
+
@shape.body.t
|
159
136
|
end
|
160
137
|
|
161
138
|
end
|
@@ -116,10 +116,12 @@ describe Thing do
|
|
116
116
|
end
|
117
117
|
context 'non-default' do
|
118
118
|
before(:each) do
|
119
|
-
|
119
|
+
class Thong < Thing
|
120
|
+
layer :non_default_layer
|
121
|
+
end
|
120
122
|
end
|
121
123
|
it "should be on the non default layer" do
|
122
|
-
|
124
|
+
Thong.new(:some_window).layer.should == :non_default_layer
|
123
125
|
end
|
124
126
|
end
|
125
127
|
end
|