pixie_dust 0.0.1

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.
Files changed (108) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README +16 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/game.js +9200 -0
  8. data/lib/corelib.js +3331 -0
  9. data/lib/pixie_dust/version.rb +3 -0
  10. data/lib/pixie_dust.rb +14 -0
  11. data/pixie.json +15 -0
  12. data/pixie_dust.gemspec +29 -0
  13. data/source/active_bounds.coffee +48 -0
  14. data/source/ageable.coffee +23 -0
  15. data/source/bounded.coffee +282 -0
  16. data/source/camera.coffee +138 -0
  17. data/source/camera.fade.coffee +69 -0
  18. data/source/camera.flash.coffee +69 -0
  19. data/source/camera.rotate.coffee +11 -0
  20. data/source/camera.shake.coffee +27 -0
  21. data/source/camera.zoom.coffee +25 -0
  22. data/source/camera.zsort.coffee +13 -0
  23. data/source/clampable.coffee +61 -0
  24. data/source/collidable.coffee +126 -0
  25. data/source/collision.coffee +272 -0
  26. data/source/collision_response.coffee +28 -0
  27. data/source/color.coffee +1113 -0
  28. data/source/color_table.coffee +2534 -0
  29. data/source/controllable.coffee +66 -0
  30. data/source/cooldown.coffee +82 -0
  31. data/source/debuggable.coffee +253 -0
  32. data/source/drawable.coffee +167 -0
  33. data/source/dust_emitter.coffee +36 -0
  34. data/source/easing.coffee +38 -0
  35. data/source/emitter.coffee +7 -0
  36. data/source/emitterable.coffee +68 -0
  37. data/source/engine.coffee +274 -0
  38. data/source/engine.collision.coffee +77 -0
  39. data/source/engine.data.coffee +23 -0
  40. data/source/engine.delay.coffee +41 -0
  41. data/source/engine.fps_counter.coffee +32 -0
  42. data/source/engine.game_state.coffee +86 -0
  43. data/source/engine.joysticks.coffee +47 -0
  44. data/source/engine.keyboard.coffee +17 -0
  45. data/source/engine.levels.coffee +69 -0
  46. data/source/engine.mouse.coffee +16 -0
  47. data/source/engine.selector.coffee +166 -0
  48. data/source/engine.stats.coffee +16 -0
  49. data/source/engine.tilemap.coffee +41 -0
  50. data/source/engine_background.coffee +32 -0
  51. data/source/expirable.coffee +47 -0
  52. data/source/flickerable.coffee +78 -0
  53. data/source/follow.coffee +65 -0
  54. data/source/framerate.coffee +42 -0
  55. data/source/game_object.coffee +181 -0
  56. data/source/game_object.effect.coffee +33 -0
  57. data/source/game_object.meter.coffee +191 -0
  58. data/source/game_over.coffee +40 -0
  59. data/source/game_state.coffee +67 -0
  60. data/source/game_state.save_state.coffee +76 -0
  61. data/source/game_state.single_camera.coffee +40 -0
  62. data/source/game_state_cameras.coffee +33 -0
  63. data/source/level_state.coffee +32 -0
  64. data/source/movable.coffee +57 -0
  65. data/source/oscillator.coffee +18 -0
  66. data/source/pixie_dust.coffee +2 -0
  67. data/source/resource_loader.coffee +35 -0
  68. data/source/rotatable.coffee +38 -0
  69. data/source/sprite.coffee +181 -0
  70. data/source/text_effect.coffee +74 -0
  71. data/source/text_effect.floating.coffee +22 -0
  72. data/source/text_screen.coffee +38 -0
  73. data/source/tilemap.coffee +56 -0
  74. data/source/timed_events.coffee +78 -0
  75. data/source/title_screen.coffee +38 -0
  76. data/source/tween.coffee +70 -0
  77. data/test/active_bounds.coffee +67 -0
  78. data/test/bounded.coffee +98 -0
  79. data/test/camera.coffee +29 -0
  80. data/test/clampable.coffee +18 -0
  81. data/test/collidable.coffee +51 -0
  82. data/test/collision.coffee +70 -0
  83. data/test/color.coffee +533 -0
  84. data/test/controllable.coffee +108 -0
  85. data/test/cooldown.coffee +116 -0
  86. data/test/debuggable.coffee +71 -0
  87. data/test/drawable.coffee +31 -0
  88. data/test/emitter.coffee +0 -0
  89. data/test/emitterable.coffee +15 -0
  90. data/test/engine.coffee +228 -0
  91. data/test/engine_data.coffee +12 -0
  92. data/test/engine_delay.coffee +14 -0
  93. data/test/engine_selector.coffee +100 -0
  94. data/test/expirable.coffee +35 -0
  95. data/test/flickerable.coffee +51 -0
  96. data/test/follow.coffee +34 -0
  97. data/test/game_object.coffee +78 -0
  98. data/test/game_object_effect.coffee +17 -0
  99. data/test/metered.coffee +33 -0
  100. data/test/movable.coffee +46 -0
  101. data/test/oscillator.coffee +28 -0
  102. data/test/resource_loader.coffee +7 -0
  103. data/test/rotatable.coffee +20 -0
  104. data/test/sprite.coffee +21 -0
  105. data/test/text.coffee +25 -0
  106. data/test/timed_events.coffee +23 -0
  107. data/test/tweening.coffee +18 -0
  108. metadata +233 -0
@@ -0,0 +1,116 @@
1
+ module "Cooldown"
2
+
3
+ test "objects count down each of their cooldowns", 2, ->
4
+ obj = GameObject
5
+ bullet: 83
6
+ cooldowns:
7
+ bullet:
8
+ target: 3
9
+ approachBy: 1
10
+
11
+ 5.times ->
12
+ obj.update(1)
13
+
14
+ equals obj.I.bullet, 78, "bullet should decrease by 5"
15
+
16
+ 100.times ->
17
+ obj.update(1)
18
+
19
+ equals obj.I.bullet, 3, "bullet should not cool down part target value"
20
+
21
+ test "should handle negative value", ->
22
+ obj = GameObject
23
+ powerup: -70
24
+ cooldowns:
25
+ powerup:
26
+ target: 0
27
+ approachBy: 1
28
+
29
+ 11.times ->
30
+ obj.update(1)
31
+
32
+ equals obj.I.powerup, -59, "powerup should increase by 11"
33
+
34
+ 70.times ->
35
+ obj.update(1)
36
+
37
+ equals obj.I.powerup, 0, "powerup should not cooldown past target value"
38
+
39
+ test "adding many cooldowns to default instance variables", 3, ->
40
+ obj = GameObject
41
+ cool: 20
42
+ rad: 0
43
+ tubular: 0
44
+ cooldowns:
45
+ cool:
46
+ approachBy: 5
47
+ target: -5
48
+ rad:
49
+ approachBy: 0.5
50
+ target: 1.5
51
+ tubular:
52
+ approachBy: 1
53
+ target: 1000
54
+
55
+ 4.times ->
56
+ obj.update(1)
57
+
58
+ equals obj.I.cool, 0
59
+ equals obj.I.rad, 1.5
60
+ equals obj.I.tubular, 4
61
+
62
+ test "#cooldown", 3, ->
63
+ obj = GameObject()
64
+
65
+ obj.cooldown 'health',
66
+ value: 100
67
+
68
+ 3.times ->
69
+ obj.update(1)
70
+
71
+ equals obj.I.health, 97, "health cooldown should exist and equal 97"
72
+
73
+ obj.cooldown 'turbo',
74
+ target: 5
75
+ approachBy: 3
76
+ value: 50
77
+
78
+ 4.times ->
79
+ obj.update(1)
80
+
81
+ equals obj.I.health, 93, "health should continue of cool down when new cooldowns are added"
82
+ equals obj.I.turbo, 38, "turbo should cool down normally"
83
+
84
+ test "should not blow up if cooldowns aren't specified", ->
85
+ obj = GameObject()
86
+
87
+ obj.update(1)
88
+ obj.trigger "afterUpdate", 1
89
+
90
+ equals obj.I.age, 1, "should successfully update"
91
+
92
+ test "use existing value of instance variable as starting value if no value param given", ->
93
+ obj = GameObject()
94
+
95
+ obj.I.health = 3
96
+
97
+ obj.cooldown 'health',
98
+ target: 10
99
+
100
+ 5.times ->
101
+ obj.update(1)
102
+
103
+ equals obj.I.health, 8
104
+
105
+ test "initialize property to 0 if no current value", ->
106
+ obj = GameObject()
107
+
108
+ obj.cooldown 'health',
109
+ target: 10
110
+
111
+ 5.times ->
112
+ obj.update(1)
113
+
114
+ equals obj.I.health, 5
115
+
116
+ module()
@@ -0,0 +1,71 @@
1
+ module "Debuggable"
2
+
3
+ test 'should exist', ->
4
+ obj = GameObject()
5
+
6
+ obj.include Debuggable
7
+
8
+ ok obj.debug
9
+
10
+ test 'should accept x, y for debug position', ->
11
+ obj = GameObject()
12
+
13
+ obj.include Debuggable
14
+
15
+ obj.debug
16
+ x: 40
17
+ y: 90
18
+
19
+ equals obj.I.debug.position.x, 40
20
+ equals obj.I.debug.position.y, 90
21
+
22
+ test 'position should override x, y for debug position', ->
23
+ obj = GameObject()
24
+
25
+ obj.include Debuggable
26
+
27
+ obj.debug
28
+ x: 2
29
+ y: 40
30
+ position:
31
+ x: 67
32
+ y: 34
33
+
34
+ equals obj.I.debug.position.x, 67
35
+ equals obj.I.debug.position.y, 34
36
+
37
+ test '#debug', ->
38
+ obj = GameObject()
39
+
40
+ obj.include Debuggable
41
+
42
+ equals obj.I.debug.enabled, false
43
+
44
+ obj.debug()
45
+
46
+ equals obj.I.debug.enabled, true
47
+
48
+ test '#toggleDebug', ->
49
+ obj = GameObject()
50
+
51
+ obj.include Debuggable
52
+
53
+ equals obj.I.debug.enabled, false
54
+
55
+ obj.toggleDebug()
56
+
57
+ equals obj.I.debug.enabled, true
58
+
59
+ obj.toggleDebug()
60
+
61
+ equals obj.I.debug.enabled, false
62
+
63
+ obj.toggleDebug(false)
64
+
65
+ equals obj.I.debug.enabled, false
66
+
67
+ obj.toggleDebug(true)
68
+
69
+ equals obj.I.debug.enabled, true
70
+
71
+ module()
@@ -0,0 +1,31 @@
1
+ module "Drawable"
2
+
3
+ test "alpha", ->
4
+ object = GameObject()
5
+
6
+ equal object.I.alpha, 1
7
+
8
+ object2 = GameObject
9
+ alpha: 0.5
10
+
11
+ equal object2.I.alpha, 0.5
12
+
13
+ test "scale", ->
14
+ object = GameObject()
15
+
16
+ transform = object.transform()
17
+
18
+ equal transform.a, 1
19
+ equal transform.d, 1
20
+
21
+ object = GameObject
22
+ scale: 2
23
+ scaleX: -1
24
+ scaleY: 0.5
25
+
26
+ transform = object.transform()
27
+
28
+ equal transform.a, -2
29
+ equal transform.d, 1
30
+
31
+ module()
File without changes
@@ -0,0 +1,15 @@
1
+ module "Emitter"
2
+
3
+ test "Particles should move", ->
4
+ e = Emitter()
5
+
6
+ xVelocity = e.I.particleData.velocity.x
7
+
8
+ e.update(1)
9
+
10
+ ok e.I.particles.length
11
+
12
+ equals e.I.particles.first().I.x, xVelocity
13
+
14
+ module()
15
+
@@ -0,0 +1,228 @@
1
+ module "Engine"
2
+
3
+ MockCanvas = ->
4
+ clear: ->
5
+ context: ->
6
+ beginPath: ->
7
+ clip: ->
8
+ rect: ->
9
+ drawRect: ->
10
+ fill: ->
11
+ withTransform: (t, fn) ->
12
+ fn(@)
13
+ clip: ->
14
+
15
+ test "#play, #pause, and #paused", ->
16
+ engine = Engine()
17
+
18
+ equal engine.paused(), false
19
+ engine.pause()
20
+ equal engine.paused(), true
21
+ engine.play()
22
+ equal engine.paused(), false
23
+
24
+ engine.pause()
25
+ equal engine.paused(), true
26
+ engine.pause()
27
+ equal engine.paused(), false
28
+
29
+ engine.pause(false)
30
+ equal engine.paused(), false
31
+
32
+ engine.pause(true)
33
+ equal engine.paused(), true
34
+
35
+ test "#save and #restore", ->
36
+ engine = Engine()
37
+
38
+ engine.add {}
39
+ engine.add {}
40
+
41
+ equals(engine.objects().length, 2)
42
+
43
+ engine.saveState()
44
+
45
+ engine.add {}
46
+
47
+ equals(engine.objects().length, 3)
48
+
49
+ engine.loadState()
50
+
51
+ equals(engine.objects().length, 2)
52
+
53
+ test "before add event", 1, ->
54
+ engine = Engine()
55
+
56
+ engine.bind "beforeAdd", (data) ->
57
+ equals data.test, "test"
58
+
59
+ engine.add
60
+ test: "test"
61
+
62
+ test "#add", ->
63
+ engine = Engine()
64
+
65
+ engine.add "GameObject",
66
+ test: true
67
+
68
+ ok engine.first("GameObject")
69
+
70
+ test "#add class name only", ->
71
+ engine = Engine()
72
+
73
+ engine.add "GameObject"
74
+
75
+ ok engine.first("GameObject")
76
+
77
+ test "zSort", ->
78
+ engine = Engine
79
+ canvas: MockCanvas()
80
+ zSort: true
81
+
82
+ n = 0
83
+ bindDraw = (o) ->
84
+ o.bind 'draw', ->
85
+ n += 1
86
+ o.I.drawnAt = n
87
+
88
+ o2 = engine.add
89
+ zIndex: 2
90
+ o1 = engine.add
91
+ zIndex: 1
92
+
93
+ bindDraw(o1)
94
+ bindDraw(o2)
95
+
96
+ engine.frameAdvance()
97
+
98
+ equals o1.I.drawnAt, 1, "Object with zIndex #{o1.I.zIndex} should be drawn first"
99
+ equals o2.I.drawnAt, 2, "Object with zIndex #{o2.I.zIndex} should be drawn second"
100
+
101
+ test "invalid module throws error", ->
102
+ raises ->
103
+ engine = Engine
104
+ includedModules: ["HellaInvalidModule"]
105
+
106
+ test "excluded modules", ->
107
+ engine = Engine
108
+ excludedModules: "Developer"
109
+
110
+ engine = Engine
111
+ excludedModules: ["Developer"]
112
+
113
+ test "draw events", 2, ->
114
+ engine = Engine
115
+ canvas: MockCanvas()
116
+ backgroundColor: false
117
+
118
+ engine.bind "beforeDraw", ->
119
+ ok true
120
+
121
+ engine.bind "draw", ->
122
+ ok true
123
+
124
+ engine.frameAdvance()
125
+
126
+ test "Remove event", 1, ->
127
+ engine = Engine
128
+ backgroundColor: false
129
+
130
+ object = engine.add
131
+ active: false
132
+
133
+ object.bind "remove", ->
134
+ ok true, "remove called"
135
+
136
+ engine.frameAdvance()
137
+
138
+ test "#find", ->
139
+ engine = Engine()
140
+
141
+ engine.add
142
+ id: "testy"
143
+
144
+ engine.add
145
+ test: true
146
+
147
+ engine.add
148
+ solid: true
149
+ opaque: false
150
+
151
+ equal engine.find("#no_testy").length, 0
152
+ equal engine.find("#testy").length, 1
153
+ equal engine.find(".test").length, 1
154
+ equal engine.find(".solid=true").length, 1
155
+ equal engine.find(".opaque=false").length, 1
156
+
157
+ test "Selector.parse", ->
158
+ a = Engine.Selector.parse("#foo")
159
+ equal a.length, 1
160
+ equal a.first(), "#foo"
161
+
162
+ a = Engine.Selector.parse("#boo, baz")
163
+ equal a.length, 2
164
+ equal a.first(), "#boo"
165
+ equal a.last(), "baz"
166
+
167
+ a = Engine.Selector.parse("#boo,Light.flicker,baz")
168
+ equal a.length, 3
169
+ equal a.first(), "#boo"
170
+ equal a[1], "Light.flicker"
171
+ equal a.last(), "baz"
172
+
173
+ test "Selector.process", ->
174
+ [type, id, attr, value] = Engine.Selector.process("Foo#test.cool=1")
175
+
176
+ equal type, "Foo"
177
+ equal id, "test"
178
+ equal attr, "cool"
179
+ equal value, 1
180
+
181
+ [type, id, attr, value] = Engine.Selector.process(".baz=false")
182
+
183
+ equal type, undefined
184
+ equal id, undefined
185
+ equal attr, "baz"
186
+ equal value, false
187
+
188
+ test "#camera", ->
189
+ engine = Engine()
190
+
191
+ equal engine.camera(), engine.cameras().first()
192
+
193
+ test "#collides", ->
194
+ engine = Engine()
195
+
196
+ engine.collides(Rectangle(0, 0, 10, 10), null)
197
+
198
+ test "Integration", ->
199
+ engine = Engine
200
+ FPS: 30
201
+
202
+ object = engine.add
203
+ class: "GameObject"
204
+ velocity: Point(30, 0)
205
+
206
+ engine.frameAdvance()
207
+
208
+ equals object.I.x, 1
209
+ equals object.I.age, 1/30
210
+
211
+ test "#setState", 3, ->
212
+ engine = Engine()
213
+
214
+ nextState = GameState()
215
+
216
+ engine.setState nextState
217
+
218
+ # Test state change events
219
+ engine.bind "stateEntered", ->
220
+ ok true
221
+ engine.bind "stateExited", ->
222
+ ok true
223
+
224
+ engine.update()
225
+
226
+ equal engine.I.currentState, nextState
227
+
228
+ module()
@@ -0,0 +1,12 @@
1
+ module "Engine"
2
+
3
+ test "#data", ->
4
+ engine = Engine
5
+ backgroundColor: false
6
+
7
+ engine.data.score = 0
8
+ engine.data.score += 50
9
+
10
+ equals engine.data.score, 50
11
+
12
+ module()
@@ -0,0 +1,14 @@
1
+ module "Engine"
2
+
3
+ test "#delay", 1, ->
4
+ engine = Engine
5
+ backgroundColor: false
6
+
7
+ 3.times (n) ->
8
+ engine.delay n, ->
9
+ ok(true)
10
+
11
+ engine.frameAdvance()
12
+
13
+ module()
14
+
@@ -0,0 +1,100 @@
1
+ module "Engine"
2
+
3
+ test "#closest", ->
4
+ engine = Engine()
5
+
6
+ player = engine.add
7
+ x: 0
8
+ y: 0
9
+
10
+ enemy1 = engine.add
11
+ enemy: true
12
+ x: 10
13
+ y: 0
14
+
15
+ enemy2 = engine.add
16
+ enemy: true
17
+ x: 0
18
+ y: 15
19
+
20
+ player2 = engine.add
21
+ x: 0
22
+ y: 10
23
+
24
+ equals engine.closest(".enemy", player.position()), enemy1
25
+ equals engine.closest(".enemy", player2.position()), enemy2
26
+
27
+ test "#each", ->
28
+ engine = Engine()
29
+
30
+ obj1 = engine.add
31
+ rad: "Awesome"
32
+ x: 0
33
+ y: 5
34
+
35
+ obj2 = engine.add
36
+ rad: "Awesome"
37
+ x: 5
38
+ y: 10
39
+
40
+ obj3 = engine.add
41
+ rad: "Awesome"
42
+ x: 5
43
+ y: 10
44
+
45
+ obj4 = engine.add
46
+ rad: "Awesome"
47
+ x: 40
48
+ y: 320
49
+
50
+ indexSum = 0
51
+
52
+ engine.each '.rad=Awesome', (obj, index) ->
53
+ indexSum += index
54
+
55
+ if index is 0
56
+ equals obj, obj1
57
+ else if index is 1
58
+ equals obj, obj2
59
+ else if index is 2
60
+ equals obj, obj3
61
+ else if index is 3
62
+ equals obj, obj4
63
+
64
+ equals indexSum, 6
65
+
66
+ test "#find", ->
67
+ engine = Engine()
68
+
69
+ engine.add
70
+ findable: true
71
+ x: 0
72
+ y: 50
73
+
74
+ equals engine.find('.findable').length, 1
75
+
76
+ engine.add
77
+ findable: true
78
+ x: 50
79
+ y: 30
80
+
81
+ equals engine.find('.findable').length, 2
82
+
83
+ test "#first", ->
84
+ engine = Engine()
85
+
86
+ obj1 = engine.add
87
+ type: 'testObj'
88
+ x: 4
89
+ y: 20
90
+
91
+ equals engine.first('.type=testObj'), obj1, "should find obj1"
92
+
93
+ obj2 = engine.add
94
+ type: 'testObj'
95
+ x: 9
96
+ y: 10
97
+
98
+ equals engine.first('.type=testObj'), obj1, "should only find the first object"
99
+
100
+ module()
@@ -0,0 +1,35 @@
1
+ module "Expirable"
2
+
3
+ test "objects become inactive after their duration", ->
4
+ obj = GameObject
5
+ duration: 5
6
+
7
+ obj.include Expirable
8
+
9
+ 4.times ->
10
+ obj.update(1)
11
+ obj.trigger "afterUpdate", 1
12
+
13
+ equals obj.I.active, true, "object is active until duration is exceeded"
14
+
15
+ 5.times ->
16
+ obj.update(1)
17
+ obj.trigger "afterUpdate", 1
18
+
19
+ equals obj.I.active, false, "object is inactive after duration"
20
+
21
+ test "should fade out if that option is set", ->
22
+ obj = GameObject
23
+ duration: 10
24
+ alpha: 0.8
25
+ fadeOut: true
26
+
27
+ obj.include Expirable
28
+
29
+ 5.times ->
30
+ obj.update(1)
31
+ obj.trigger "afterUpdate", 1
32
+
33
+ equals obj.I.alpha, 0.48
34
+
35
+ module()
@@ -0,0 +1,51 @@
1
+ module "Flickerable"
2
+
3
+ test 'it should set up defaults', ->
4
+ player = GameObject()
5
+
6
+ player.include Flickerable
7
+
8
+ player.flicker()
9
+
10
+ equals player.I.flickerAlpha, 0.5
11
+ equals player.I.flickerFrequency, 0.1
12
+ equals player.I.flickerDuration, 2
13
+
14
+ test 'it should be able to set one param at a time', ->
15
+ player = GameObject()
16
+
17
+ player.include Flickerable
18
+
19
+ player.flicker
20
+ frequency: 20
21
+
22
+ equals player.I.flickerAlpha, 0.5
23
+ equals player.I.flickerFrequency, 20
24
+ equals player.I.flickerDuration, 2
25
+
26
+ enemy = GameObject()
27
+
28
+ enemy.include Flickerable
29
+
30
+ enemy.flicker
31
+ alpha: 0.4
32
+
33
+ equals enemy.I.flickerAlpha, 0.4
34
+ equals enemy.I.flickerFrequency, 0.1
35
+ equals enemy.I.flickerDuration, 2
36
+
37
+ boss = GameObject()
38
+
39
+ boss.include Flickerable
40
+
41
+ boss.flicker
42
+ duration: 3
43
+
44
+ equals boss.I.flickerAlpha, 0.5
45
+ equals boss.I.flickerFrequency, 0.1
46
+ equals boss.I.flickerDuration, 3
47
+
48
+ #TODO test this with new time step stuff
49
+ #test 'it should change the alpha value when the flicker duration has elapsed', ->
50
+
51
+ module()
@@ -0,0 +1,34 @@
1
+ module "Follow"
2
+
3
+ test "should set the correct velocity", ->
4
+ player = GameObject
5
+ x: 50
6
+ y: 50
7
+ width: 10
8
+ height: 10
9
+
10
+ enemy = GameObject
11
+ x: 0
12
+ y: 50
13
+ widht: 10
14
+ height: 10
15
+ speed: 1
16
+
17
+ enemy.include(Follow)
18
+ enemy.follow(player)
19
+
20
+ ok enemy.I.velocity.equal(Point(1, 0)), 'enemy should head toward player with a velocity Point(1, 0)'
21
+
22
+ rightEnemy = GameObject
23
+ x: 100
24
+ y: 50
25
+ width: 10
26
+ height: 10
27
+ speed: 1
28
+
29
+ rightEnemy.include(Follow)
30
+ rightEnemy.follow(player)
31
+
32
+ ok rightEnemy.I.velocity.equal(Point(-1, 0)), 'rightEnemy should head toward player with a velocity Point(-1, 0)'
33
+
34
+ module()