pixie_dust 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,181 @@
1
+ ###*
2
+ The Sprite class provides a way to load images for use in games.
3
+
4
+ By default, images are loaded asynchronously. A proxy object is
5
+ returned immediately. Even though it has a draw method it will not
6
+ draw anything to the screen until the image has been loaded.
7
+
8
+ @name Sprite
9
+ @constructor
10
+ ###
11
+
12
+ ( ->
13
+ LoaderProxy = ->
14
+ draw: ->
15
+ fill: ->
16
+ frame: ->
17
+ update: ->
18
+ width: null
19
+ height: null
20
+ image: null
21
+
22
+ # Cache loaded images
23
+ spriteCache = {}
24
+
25
+ Sprite = (image, sourceX, sourceY, width, height) ->
26
+ sourceX ||= 0
27
+ sourceY ||= 0
28
+ width ||= image.width
29
+ height ||= image.height
30
+
31
+ ###*
32
+ Draw this sprite on the given canvas at the given position.
33
+
34
+ @name draw
35
+ @methodOf Sprite#
36
+ @param {PowerCanvas} canvas Reference to the canvas to draw the sprite on
37
+ @param {Number} x Position on the x axis to draw the sprite
38
+ @param {Number} y Position on the y axis to draw the sprite
39
+ ###
40
+ draw: (canvas, x, y) ->
41
+ canvas.drawImage(
42
+ image,
43
+ sourceX,
44
+ sourceY,
45
+ width,
46
+ height,
47
+ x,
48
+ y,
49
+ width,
50
+ height
51
+ )
52
+
53
+ ###*
54
+ Draw this sprite on the given canvas tiled to the x, y,
55
+ width, and height dimensions specified.
56
+
57
+ @name fill
58
+ @methodOf Sprite#
59
+ @param {PowerCanvas} canvas Reference to the canvas to draw the sprite on
60
+ @param {Number} x Position on the x axis to draw the sprite
61
+ @param {Number} y Position on the y axis to draw the sprite
62
+ @param {Number} width How far to tile the sprite on the x-axis
63
+ @param {Number} height How far to tile the sprite on the y-axis
64
+ @param {String} repeat Repeat options. Can be `repeat-x`, `repeat-y`, `no-repeat`, or `repeat`. Defaults to `repeat`
65
+ ###
66
+ fill: (canvas, x, y, width, height, repeat="repeat") ->
67
+ pattern = canvas.createPattern(image, repeat)
68
+ canvas.drawRect({x, y, width, height, color: pattern})
69
+
70
+ width: width
71
+ height: height
72
+ image: image
73
+
74
+ ###*
75
+ Loads all sprites from a sprite sheet found in
76
+ your images directory, specified by the name passed in.
77
+
78
+ @name loadSheet
79
+ @methodOf Sprite
80
+ @param {String} name Name of the spriteSheet image in your images directory
81
+ @param {Number} tileWidth Width of each sprite in the sheet
82
+ @param {Number} tileHeight Height of each sprite in the sheet
83
+ @returns {Array} An array of sprite objects
84
+ ###
85
+ Sprite.loadSheet = (name, tileWidth, tileHeight) ->
86
+ url = ResourceLoader.urlFor("images", name)
87
+
88
+ sprites = []
89
+ image = new Image()
90
+
91
+ image.onload = ->
92
+ imgElement = this
93
+ (image.height / tileHeight).times (row) ->
94
+ (image.width / tileWidth).times (col) ->
95
+ sprites.push(Sprite(imgElement, col * tileWidth, row * tileHeight, tileWidth, tileHeight))
96
+
97
+ image.src = url
98
+
99
+ return sprites
100
+
101
+ ###*
102
+ Loads a sprite from a given url.
103
+
104
+ @name load
105
+ @methodOf Sprite
106
+ @param {String} url
107
+ @param {Function} [loadedCallback]
108
+ @returns {Sprite} A sprite object
109
+ ###
110
+ Sprite.load = (url, loadedCallback) ->
111
+ if sprite = spriteCache[url]
112
+ loadedCallback?.defer(sprite)
113
+ return sprite
114
+
115
+ img = new Image()
116
+ proxy = LoaderProxy()
117
+
118
+ img.onload = ->
119
+ spriteCache[url] = Object.extend(proxy, Sprite(this))
120
+
121
+ loadedCallback?(proxy)
122
+
123
+ img.src = url
124
+
125
+ return proxy
126
+
127
+ ###*
128
+ Loads a sprite with the given pixie id.
129
+
130
+ @name fromPixieId
131
+ @methodOf Sprite
132
+ @param {Number} id Pixie Id of the sprite to load
133
+ @param {Function} [callback] Function to execute once the image is loaded. The sprite proxy data is passed to this as a parameter.
134
+ @returns {Sprite}
135
+ ###
136
+ Sprite.fromPixieId = (id, callback) ->
137
+ Sprite.load("http://pixieengine.com/s3/sprites/#{id}/original.png", callback)
138
+
139
+ ###*
140
+ A sprite that draws nothing.
141
+
142
+ @name EMPTY
143
+ @fieldOf Sprite
144
+ @constant
145
+ @returns {Sprite}
146
+ ###
147
+ ###*
148
+ A sprite that draws nothing.
149
+
150
+ @name NONE
151
+ @fieldOf Sprite
152
+ @constant
153
+ @returns {Sprite}
154
+ ###
155
+ Sprite.EMPTY = Sprite.NONE = LoaderProxy()
156
+
157
+ ###*
158
+ Loads a sprite from a given url.
159
+
160
+ @name fromURL
161
+ @methodOf Sprite
162
+ @param {String} url The url where the image to load is located
163
+ @param {Function} [callback] Function to execute once the image is loaded. The sprite proxy data is passed to this as a parameter.
164
+ @returns {Sprite}
165
+ ###
166
+ Sprite.fromURL = Sprite.load
167
+
168
+ ###*
169
+ Loads a sprite with the given name.
170
+
171
+ @name loadByName
172
+ @methodOf Sprite
173
+ @param {String} name The name of the image in your images directory
174
+ @param {Function} [callback] Function to execute once the image is loaded. The sprite proxy data is passed to this as a parameter.
175
+ @returns {Sprite}
176
+ ###
177
+ Sprite.loadByName = (name, callback) ->
178
+ Sprite.load(ResourceLoader.urlFor("images", name), callback)
179
+
180
+ (exports ? this)["Sprite"] = Sprite
181
+ )()
@@ -0,0 +1,74 @@
1
+ ###*
2
+ The Text Effect class provides a method to display moving text onscreen, fading out the text over the effect duration.
3
+
4
+ # adds a TextEffect to the engine at (60, 100)
5
+ engine.add 'TextEffect'
6
+ x: 60
7
+ y: 100
8
+
9
+ @name TextEffect
10
+ @constructor
11
+ ###
12
+
13
+ ###*
14
+ Updates the position of the text based on the effect velocity. Updates the
15
+ alpha based on the elapsed time since the effect creation.
16
+
17
+ @name update
18
+ @methodOf TextEffect#
19
+ @event
20
+ ###
21
+
22
+ ###*
23
+ Draws text from `I.textShadow` `I.text`.
24
+
25
+ @name draw
26
+ @methodOf TextEffect#
27
+ @param {PixieCanvas} canvas
28
+ @event
29
+ ###
30
+ TextEffect = (I={}) ->
31
+ Object.reverseMerge I,
32
+ color: Color('green')
33
+ duration: -1
34
+ font: '20px Helvetica'
35
+ text: '100'
36
+ textShadow: Color('black')
37
+ alpha: 1
38
+ rotation: 0
39
+ velocity: Point(0, 0)
40
+
41
+ self = GameObject(I)
42
+
43
+ self.bind "update", ->
44
+ I.rotation += I.rotationalVelocity if I.rotationalVelocity?
45
+
46
+ I.alpha = (1 - (I.age / I.duration)).clamp(0, 1)
47
+
48
+ self.unbind "draw"
49
+ self.bind "draw", (canvas) ->
50
+ unless I.color.channels
51
+ I.color = Color(I.color)
52
+
53
+ unless I.textShadow.channels
54
+ I.textShadow = Color(I.textShadow)
55
+
56
+ I.color.a = I.alpha
57
+ I.textShadow.a = I.alpha
58
+
59
+ I.width = canvas.measureText(I.text)
60
+
61
+ canvas.font I.font
62
+ canvas.drawText
63
+ color: I.textShadow
64
+ x: 1 - I.width
65
+ y: 1
66
+ text: I.text
67
+
68
+ canvas.drawText
69
+ color: I.color
70
+ x: 0 - I.width
71
+ y: 0
72
+ text: I.text
73
+
74
+ return self
@@ -0,0 +1,22 @@
1
+ ###*
2
+ `TextEffect.Floating` is a simple subclass of `TextEffect`. It provides some defaults
3
+ to move the text upward and fade it out over 0.5 seconds.
4
+
5
+ # adds a FloatingTextEffect to the engine
6
+ # at (50, 50). This effect will float upward
7
+ # at 90 pixels/sec and will fadeOut over 0.5 seconds
8
+ engine.add 'TextEffect.Floating'
9
+ x: 50
10
+ y: 50
11
+
12
+ @see TextEffect
13
+ @name Floating
14
+ @fieldOf TextEffect
15
+ @constructor
16
+ ###
17
+ TextEffect.Floating = (I={}) ->
18
+ Object.reverseMerge I,
19
+ duration: 0.5
20
+ velocity: Point(0, -90)
21
+
22
+ return TextEffect(I)
@@ -0,0 +1,38 @@
1
+ ###*
2
+ The Text Screen class is a GameState that provides convenience methods for drawing text to screen.
3
+
4
+ @name TextScreen
5
+ @constructor
6
+ ###
7
+ TextScreen = (I={}) ->
8
+ Object.reverseMerge I,
9
+ font: 'Helvetica'
10
+ fontSize: 24
11
+ fontColor: 'white'
12
+ yPosition: App.height / 2
13
+
14
+ self = GameState(I).extend
15
+ ###*
16
+ Draw center aligned text at the given y position.
17
+
18
+ screen = TextScreen()
19
+ screen.centerText canvas, 'Centering text is easy'
20
+
21
+ @name centerText
22
+ @methodOf TextScreen#
23
+ @param {PixieCanvas} canvas The canvas to draw on
24
+ @param {String} text The text to draw
25
+ @param {Object} options These include font, size, color, and yPosition
26
+ ###
27
+ centerText: (canvas, text, options={}) ->
28
+ font = options.font || I.font
29
+ size = options.size || I.fontSize
30
+ color = options.color || I.fontColor
31
+ yPosition = options.y || I.yPosition
32
+
33
+ canvas.font "#{size}px #{font}"
34
+
35
+ canvas.centerText
36
+ y: yPosition
37
+ text: text
38
+ color: color
@@ -0,0 +1,56 @@
1
+ ( ->
2
+ Map = (data, entityCallback) ->
3
+ tileHeight = data.tileHeight
4
+ tileWidth = data.tileWidth
5
+
6
+ spriteLookup = {}
7
+
8
+ for uuid, entity of App.entities
9
+ spriteLookup[uuid] = Sprite.fromURL(entity.tileSrc)
10
+
11
+ loadEntities = () ->
12
+ return unless entityCallback
13
+
14
+ data.layers.each (layer, layerIndex) ->
15
+ if instances = layer.instances
16
+ for instance in instances
17
+ {x, y, uuid} = instance
18
+
19
+ instanceData = Object.extend(
20
+ layer: layerIndex
21
+ sprite: spriteLookup[uuid]
22
+ x: x + tileWidth/2 # Centered Coordinates
23
+ y: y + tileHeight/2 # Centered Coordinates
24
+ , App.entities[uuid] # Global entity properties
25
+ #TODO: Maybe map specific properties?
26
+ , instance.properties) # Instance properties
27
+
28
+ entityCallback(instanceData)
29
+
30
+ loadEntities()
31
+
32
+ data
33
+
34
+ Tilemap = (name, callback, entityCallback) ->
35
+ fromPixieId(App.Tilemaps[name], callback, entityCallback)
36
+
37
+ loadByName = (name, callback, entityCallback) ->
38
+ url = ResourceLoader.urlFor("tilemaps", name)
39
+
40
+ proxy = {}
41
+
42
+ $.getJSON url, (data) ->
43
+ Object.extend(proxy, Map(data, entityCallback))
44
+
45
+ callback? proxy
46
+
47
+ return proxy
48
+
49
+ Tilemap.load = (options) ->
50
+ if options.pixieId
51
+ fromPixieId options.pixieId, options.complete, options.entity
52
+ else if options.name
53
+ loadByName options.name, options.complete, options.entity
54
+
55
+ (exports ? this)["Tilemap"] = Tilemap
56
+ )()
@@ -0,0 +1,78 @@
1
+ ###*
2
+ The TimedEvents module allows arbitrary code to be executed at set intervals. <code>GameObject</code> includes this module by default
3
+
4
+ TimedEvents module
5
+ @name TimedEvents
6
+ @module
7
+ @constructor
8
+ @param {Object} I Instance variables
9
+ ###
10
+ TimedEvents = (I={}, self) ->
11
+ Object.reverseMerge I,
12
+ everyEvents: []
13
+ delayEvents: []
14
+
15
+ self.bind "update", (elapsedTime) ->
16
+ for event in I.everyEvents
17
+ {fn, period} = event
18
+ while event.lastFired < I.age + elapsedTime
19
+ self.sendOrApply(fn)
20
+ event.lastFired += period
21
+
22
+ [I.delayEvents, firingEvents] = I.delayEvents.partition (event) ->
23
+ (event.delay -= elapsedTime) >= 0
24
+
25
+ firingEvents.each (event) ->
26
+ self.sendOrApply(event.fn)
27
+
28
+ ###*
29
+ Execute <code>fn</code> every <code>n</code> frames.
30
+
31
+ player = GameObject()
32
+
33
+ player.include TimedEvents
34
+
35
+ # doSomething is called every 4 seconds
36
+ player.every 4, ->
37
+ doSomething()
38
+
39
+ @name every
40
+ @methodOf TimedEvents#
41
+ @param {Number} n Number of frames to wait before executing the callback
42
+ @param {Function} fn Code to execute after <code>n</code> frames has passed
43
+ ###
44
+ every: (period, fn) ->
45
+ return unless period > 0
46
+
47
+ I.everyEvents.push
48
+ fn: fn
49
+ period: period
50
+ lastFired: I.age
51
+
52
+ ###*
53
+ Execute a callback after a number of seconds have passed.
54
+
55
+ self.delay 5, ->
56
+ engine.add
57
+ class: "Ghost"
58
+
59
+ @name delay
60
+ @methodOf TimedEvents#
61
+ @param {Number} steps The number of steps to wait before executing the callback
62
+ @param {Function} callback The callback to be executed.
63
+
64
+ @returns {Engine} self
65
+ ###
66
+ delay: (seconds, fn) ->
67
+ I.delayEvents.push
68
+ delay: seconds
69
+ fn: fn
70
+
71
+ return self
72
+
73
+ # TODO: Move this into a more core module
74
+ sendOrApply: (fn, args...) ->
75
+ if typeof fn is "function"
76
+ fn.apply(self, args)
77
+ else
78
+ self.send(fn, args...)
@@ -0,0 +1,38 @@
1
+ ###*
2
+ The Title Screen class sets up a simple game title screen using <code>App.name</code>
3
+
4
+ @see TextScreen
5
+ @name TitleScreen
6
+ @constructor
7
+ ###
8
+
9
+ ###*
10
+ Goes to the next level on any user input.
11
+
12
+ @name update
13
+ @methodOf TitleScreen#
14
+ @event
15
+ ###
16
+
17
+ ###*
18
+ Overlays the title text in the middle of the screen. Uses <code>App.name</code>
19
+
20
+ @name overlay
21
+ @methodOf TitleScreen#
22
+ @param {PixieCanvas} canvas
23
+ @event
24
+ ###
25
+ TitleScreen = (I={}) ->
26
+ self = TextScreen(I)
27
+
28
+ self.bind 'update', ->
29
+ engine.nextLevel() if justPressed.any
30
+
31
+ self.bind "overlay", (canvas) ->
32
+ self.centerText canvas, App.name
33
+
34
+ self.centerText canvas, "Press any key to start",
35
+ size: 12
36
+ y: App.height / 2 + 30
37
+
38
+ return self
@@ -0,0 +1,70 @@
1
+ ###*
2
+ The <code>Tween</code> module provides a method to tween object properties.
3
+
4
+ @name Tween
5
+ @module
6
+ @constructor
7
+ @param {Object} I Instance variables
8
+ @param {Core} self Reference to including object
9
+ ###
10
+ Tween = (I={}, self) ->
11
+ Object.reverseMerge I,
12
+ activeTweens: {}
13
+
14
+ # Add events and methods here
15
+ self.bind "update", (elapsedTime) ->
16
+ t = I.age + elapsedTime
17
+ for property, data of I.activeTweens
18
+ if t >= data.endTime
19
+ I[property] = data.end
20
+ I.activeTweens[property].complete?()
21
+ delete I.activeTweens[property]
22
+ else
23
+ if data.easing.isString?()
24
+ easingFunction = Easing[data.easing](data.start, data.end)
25
+ else
26
+ easingFunction = data.easing
27
+
28
+ I[property] = easingFunction((t - data.startTime) / data.duration)
29
+
30
+ ###*
31
+ Modify the object's properties over time.
32
+
33
+ player = GameObject()
34
+
35
+ player.tween 30,
36
+ x: 50
37
+ y: 50
38
+ easing: "quadratic"
39
+
40
+ player = GameObject()
41
+
42
+ player.tween 30,
43
+ x: 150
44
+ y: 150
45
+ complete: ->
46
+ player.dance()
47
+
48
+ @name tween
49
+ @methodOf Tween#
50
+ @param {Number} duration How long (in frames) until the object's properties reach their final values.
51
+ @param {Object} properties Which properties to tween. Set the `easing` property to specify the easing function.
52
+ ###
53
+ tween: (duration, properties) ->
54
+ properties = Object.extend({}, properties) # Make a local copy
55
+
56
+ easing = properties.easing || "linear"
57
+ complete = properties.complete
58
+
59
+ delete properties.easing
60
+ delete properties.complete
61
+
62
+ for property, target of properties
63
+ I.activeTweens[property] =
64
+ complete: complete
65
+ end: target
66
+ start: I[property]
67
+ easing: easing
68
+ duration: duration
69
+ startTime: I.age
70
+ endTime: I.age + duration
@@ -0,0 +1,67 @@
1
+ module "ActiveBounds"
2
+
3
+ window.App ||= {}
4
+
5
+ App.width = 640
6
+ App.height = 480
7
+
8
+ test "shouldn't remove object inside activeBounds", ->
9
+ obj = GameObject
10
+ x: 50
11
+ y: 50
12
+ width: 32
13
+ height: 32
14
+
15
+ obj.include ActiveBounds
16
+
17
+ destroySpy = false
18
+
19
+ obj.bind 'destroy', ->
20
+ destroySpy = true
21
+
22
+ obj.update(1)
23
+
24
+ equals destroySpy, false
25
+
26
+ test "should remove objects outside of activeBounds", 2, ->
27
+ obj = GameObject
28
+ x: 50
29
+ y: 50
30
+ width: 32
31
+ height: 32
32
+
33
+ obj.include ActiveBounds
34
+
35
+ destroySpy = false
36
+
37
+ obj.bind 'destroy', ->
38
+ destroySpy = true
39
+
40
+ obj.I.x = 10000
41
+ obj.I.y = 50
42
+
43
+ obj.update(1)
44
+
45
+ ok destroySpy, 'obj should be destroyed when it goes outside the x bounds'
46
+
47
+ obj2 = GameObject
48
+ x: 100
49
+ y: 250
50
+ width: 16
51
+ height: 26
52
+
53
+ obj2.include ActiveBounds
54
+
55
+ destroySpy = false
56
+
57
+ obj2.bind 'destroy', ->
58
+ destroySpy = true
59
+
60
+ obj2.I.x = 100
61
+ obj2.I.y = 50000
62
+
63
+ obj2.update(1)
64
+
65
+ ok destroySpy, 'obj2 should be destroyed when it goes outside the y bounds'
66
+
67
+ module()