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,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()