pixie_dust 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README +16 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/game.js +9200 -0
- data/lib/corelib.js +3331 -0
- data/lib/pixie_dust/version.rb +3 -0
- data/lib/pixie_dust.rb +14 -0
- data/pixie.json +15 -0
- data/pixie_dust.gemspec +29 -0
- data/source/active_bounds.coffee +48 -0
- data/source/ageable.coffee +23 -0
- data/source/bounded.coffee +282 -0
- data/source/camera.coffee +138 -0
- data/source/camera.fade.coffee +69 -0
- data/source/camera.flash.coffee +69 -0
- data/source/camera.rotate.coffee +11 -0
- data/source/camera.shake.coffee +27 -0
- data/source/camera.zoom.coffee +25 -0
- data/source/camera.zsort.coffee +13 -0
- data/source/clampable.coffee +61 -0
- data/source/collidable.coffee +126 -0
- data/source/collision.coffee +272 -0
- data/source/collision_response.coffee +28 -0
- data/source/color.coffee +1113 -0
- data/source/color_table.coffee +2534 -0
- data/source/controllable.coffee +66 -0
- data/source/cooldown.coffee +82 -0
- data/source/debuggable.coffee +253 -0
- data/source/drawable.coffee +167 -0
- data/source/dust_emitter.coffee +36 -0
- data/source/easing.coffee +38 -0
- data/source/emitter.coffee +7 -0
- data/source/emitterable.coffee +68 -0
- data/source/engine.coffee +274 -0
- data/source/engine.collision.coffee +77 -0
- data/source/engine.data.coffee +23 -0
- data/source/engine.delay.coffee +41 -0
- data/source/engine.fps_counter.coffee +32 -0
- data/source/engine.game_state.coffee +86 -0
- data/source/engine.joysticks.coffee +47 -0
- data/source/engine.keyboard.coffee +17 -0
- data/source/engine.levels.coffee +69 -0
- data/source/engine.mouse.coffee +16 -0
- data/source/engine.selector.coffee +166 -0
- data/source/engine.stats.coffee +16 -0
- data/source/engine.tilemap.coffee +41 -0
- data/source/engine_background.coffee +32 -0
- data/source/expirable.coffee +47 -0
- data/source/flickerable.coffee +78 -0
- data/source/follow.coffee +65 -0
- data/source/framerate.coffee +42 -0
- data/source/game_object.coffee +181 -0
- data/source/game_object.effect.coffee +33 -0
- data/source/game_object.meter.coffee +191 -0
- data/source/game_over.coffee +40 -0
- data/source/game_state.coffee +67 -0
- data/source/game_state.save_state.coffee +76 -0
- data/source/game_state.single_camera.coffee +40 -0
- data/source/game_state_cameras.coffee +33 -0
- data/source/level_state.coffee +32 -0
- data/source/movable.coffee +57 -0
- data/source/oscillator.coffee +18 -0
- data/source/pixie_dust.coffee +2 -0
- data/source/resource_loader.coffee +35 -0
- data/source/rotatable.coffee +38 -0
- data/source/sprite.coffee +181 -0
- data/source/text_effect.coffee +74 -0
- data/source/text_effect.floating.coffee +22 -0
- data/source/text_screen.coffee +38 -0
- data/source/tilemap.coffee +56 -0
- data/source/timed_events.coffee +78 -0
- data/source/title_screen.coffee +38 -0
- data/source/tween.coffee +70 -0
- data/test/active_bounds.coffee +67 -0
- data/test/bounded.coffee +98 -0
- data/test/camera.coffee +29 -0
- data/test/clampable.coffee +18 -0
- data/test/collidable.coffee +51 -0
- data/test/collision.coffee +70 -0
- data/test/color.coffee +533 -0
- data/test/controllable.coffee +108 -0
- data/test/cooldown.coffee +116 -0
- data/test/debuggable.coffee +71 -0
- data/test/drawable.coffee +31 -0
- data/test/emitter.coffee +0 -0
- data/test/emitterable.coffee +15 -0
- data/test/engine.coffee +228 -0
- data/test/engine_data.coffee +12 -0
- data/test/engine_delay.coffee +14 -0
- data/test/engine_selector.coffee +100 -0
- data/test/expirable.coffee +35 -0
- data/test/flickerable.coffee +51 -0
- data/test/follow.coffee +34 -0
- data/test/game_object.coffee +78 -0
- data/test/game_object_effect.coffee +17 -0
- data/test/metered.coffee +33 -0
- data/test/movable.coffee +46 -0
- data/test/oscillator.coffee +28 -0
- data/test/resource_loader.coffee +7 -0
- data/test/rotatable.coffee +20 -0
- data/test/sprite.coffee +21 -0
- data/test/text.coffee +25 -0
- data/test/timed_events.coffee +23 -0
- data/test/tweening.coffee +18 -0
- metadata +233 -0
@@ -0,0 +1,274 @@
|
|
1
|
+
( ->
|
2
|
+
###*
|
3
|
+
The Engine controls the game world and manages game state. Once you
|
4
|
+
set it up and let it run it pretty much takes care of itself.
|
5
|
+
|
6
|
+
You can use the engine to add or remove objects from the game world.
|
7
|
+
|
8
|
+
There are several modules that can include to add additional capabilities
|
9
|
+
to the engine.
|
10
|
+
|
11
|
+
The engine fires events that you may bind listeners to. Event listeners
|
12
|
+
may be bound with <code>engine.bind(eventName, callback)</code>
|
13
|
+
|
14
|
+
@name Engine
|
15
|
+
@constructor
|
16
|
+
@param {Object} I Instance variables of the engine
|
17
|
+
###
|
18
|
+
|
19
|
+
###*
|
20
|
+
Observe or modify the
|
21
|
+
entity data before it is added to the engine.
|
22
|
+
@name beforeAdd
|
23
|
+
@methodOf Engine#
|
24
|
+
@event
|
25
|
+
@param {Object} entityData
|
26
|
+
###
|
27
|
+
|
28
|
+
###*
|
29
|
+
Observe or configure a <code>gameObject</code> that has been added
|
30
|
+
to the engine.
|
31
|
+
@name afterAdd
|
32
|
+
@methodOf Engine#
|
33
|
+
@event
|
34
|
+
@param {GameObject} object The object that has just been added to the
|
35
|
+
engine.
|
36
|
+
###
|
37
|
+
|
38
|
+
###*
|
39
|
+
Called when the engine updates all the game objects.
|
40
|
+
|
41
|
+
@name update
|
42
|
+
@methodOf Engine#
|
43
|
+
@event
|
44
|
+
@param {Number} elapsedTime The time in seconds that has elapsed since the last update.
|
45
|
+
###
|
46
|
+
|
47
|
+
###*
|
48
|
+
Called after the engine completes an update. Here it is
|
49
|
+
safe to modify the game objects array.
|
50
|
+
|
51
|
+
@name afterUpdate
|
52
|
+
@methodOf Engine#
|
53
|
+
@event
|
54
|
+
###
|
55
|
+
|
56
|
+
###*
|
57
|
+
Called before the engine draws the game objects on the canvas. The current camera transform is applied.
|
58
|
+
|
59
|
+
@name beforeDraw
|
60
|
+
@methodOf Engine#
|
61
|
+
@event
|
62
|
+
@params {PixieCanvas} canvas A reference to the canvas to draw on.
|
63
|
+
###
|
64
|
+
|
65
|
+
###*
|
66
|
+
Called after the engine draws on the canvas. The current camera transform is applied.
|
67
|
+
|
68
|
+
engine.bind "draw", (canvas) ->
|
69
|
+
# print some directions for the player
|
70
|
+
canvas.drawText
|
71
|
+
text: "Go this way =>"
|
72
|
+
x: 200
|
73
|
+
y: 200
|
74
|
+
|
75
|
+
@name draw
|
76
|
+
@methodOf Engine#
|
77
|
+
@event
|
78
|
+
@params {PixieCanvas} canvas A reference to the canvas to draw on.
|
79
|
+
###
|
80
|
+
|
81
|
+
###*
|
82
|
+
Called after the engine draws.
|
83
|
+
|
84
|
+
The current camera transform is not applied. This is great for
|
85
|
+
adding overlays.
|
86
|
+
|
87
|
+
engine.bind "overlay", (canvas) ->
|
88
|
+
# print the player's health. This will be
|
89
|
+
# positioned absolutely according to the viewport.
|
90
|
+
canvas.drawText
|
91
|
+
text: "HEALTH:"
|
92
|
+
position: Point(20, 20)
|
93
|
+
|
94
|
+
canvas.drawText
|
95
|
+
text: player.health()
|
96
|
+
position: Point(50, 20)
|
97
|
+
|
98
|
+
@name overlay
|
99
|
+
@methodOf Engine#
|
100
|
+
@event
|
101
|
+
@params {PixieCanvas} canvas A reference to the canvas to draw on.
|
102
|
+
###
|
103
|
+
|
104
|
+
Engine = (I={}) ->
|
105
|
+
Object.reverseMerge I,
|
106
|
+
FPS: 60
|
107
|
+
paused: false
|
108
|
+
|
109
|
+
frameAdvance = false
|
110
|
+
|
111
|
+
running = false
|
112
|
+
startTime = +new Date()
|
113
|
+
lastStepTime = -Infinity
|
114
|
+
animLoop = (timestamp) ->
|
115
|
+
timestamp ||= +new Date()
|
116
|
+
msPerFrame = (1000 / I.FPS)
|
117
|
+
|
118
|
+
delta = timestamp - lastStepTime
|
119
|
+
remainder = delta - msPerFrame
|
120
|
+
|
121
|
+
if remainder > 0
|
122
|
+
lastStepTime = timestamp - Math.min(remainder, msPerFrame)
|
123
|
+
step()
|
124
|
+
|
125
|
+
if running
|
126
|
+
window.requestAnimationFrame(animLoop)
|
127
|
+
|
128
|
+
update = (elapsedTime) ->
|
129
|
+
self.trigger "beforeUpdate", elapsedTime
|
130
|
+
self.trigger "update", elapsedTime
|
131
|
+
self.trigger "afterUpdate", elapsedTime
|
132
|
+
|
133
|
+
draw = ->
|
134
|
+
return unless canvas = I.canvas
|
135
|
+
|
136
|
+
self.trigger "beforeDraw", canvas
|
137
|
+
self.trigger "draw", canvas
|
138
|
+
self.trigger "overlay", canvas
|
139
|
+
|
140
|
+
step = ->
|
141
|
+
if !I.paused || frameAdvance
|
142
|
+
elapsedTime = (1 / I.FPS)
|
143
|
+
update(elapsedTime)
|
144
|
+
|
145
|
+
draw()
|
146
|
+
|
147
|
+
self = Core(I).extend {
|
148
|
+
###*
|
149
|
+
Start the game simulation.
|
150
|
+
|
151
|
+
engine.start()
|
152
|
+
|
153
|
+
@methodOf Engine#
|
154
|
+
@name start
|
155
|
+
###
|
156
|
+
start: ->
|
157
|
+
unless running
|
158
|
+
running = true
|
159
|
+
window.requestAnimationFrame(animLoop)
|
160
|
+
|
161
|
+
###*
|
162
|
+
Stop the simulation.
|
163
|
+
|
164
|
+
engine.stop()
|
165
|
+
|
166
|
+
@methodOf Engine#
|
167
|
+
@name stop
|
168
|
+
###
|
169
|
+
stop: ->
|
170
|
+
running = false
|
171
|
+
|
172
|
+
###*
|
173
|
+
Pause the game and step through 1 update of the engine.
|
174
|
+
|
175
|
+
engine.frameAdvance()
|
176
|
+
|
177
|
+
@methodOf Engine#
|
178
|
+
@name frameAdvance
|
179
|
+
###
|
180
|
+
frameAdvance: ->
|
181
|
+
I.paused = true
|
182
|
+
frameAdvance = true
|
183
|
+
step()
|
184
|
+
frameAdvance = false
|
185
|
+
|
186
|
+
###*
|
187
|
+
Resume the game.
|
188
|
+
|
189
|
+
engine.play()
|
190
|
+
|
191
|
+
@methodOf Engine#
|
192
|
+
@name play
|
193
|
+
###
|
194
|
+
play: ->
|
195
|
+
I.paused = false
|
196
|
+
|
197
|
+
###*
|
198
|
+
Toggle the paused state of the simulation.
|
199
|
+
|
200
|
+
engine.pause()
|
201
|
+
|
202
|
+
@methodOf Engine#
|
203
|
+
@name pause
|
204
|
+
@param {Boolean} [setTo] Force to pause by passing true or unpause by passing false.
|
205
|
+
###
|
206
|
+
pause: (setTo) ->
|
207
|
+
if setTo?
|
208
|
+
I.paused = setTo
|
209
|
+
else
|
210
|
+
I.paused = !I.paused
|
211
|
+
|
212
|
+
###*
|
213
|
+
Query the engine to see if it is paused.
|
214
|
+
|
215
|
+
engine.pause()
|
216
|
+
|
217
|
+
engine.paused()
|
218
|
+
# true
|
219
|
+
|
220
|
+
engine.play()
|
221
|
+
|
222
|
+
engine.paused()
|
223
|
+
# false
|
224
|
+
|
225
|
+
@methodOf Engine#
|
226
|
+
@name paused
|
227
|
+
###
|
228
|
+
paused: ->
|
229
|
+
I.paused
|
230
|
+
|
231
|
+
###*
|
232
|
+
Change the framerate of the game. The default framerate is 30 fps.
|
233
|
+
|
234
|
+
engine.setFramerate(60)
|
235
|
+
|
236
|
+
@methodOf Engine#
|
237
|
+
@name setFramerate
|
238
|
+
###
|
239
|
+
setFramerate: (newFPS) ->
|
240
|
+
I.FPS = newFPS
|
241
|
+
self.stop()
|
242
|
+
self.start()
|
243
|
+
|
244
|
+
update: update
|
245
|
+
draw: draw
|
246
|
+
}
|
247
|
+
|
248
|
+
self.include Ageable
|
249
|
+
|
250
|
+
Engine.defaultModules.each (moduleName) ->
|
251
|
+
fullModuleName = "Engine.#{moduleName}"
|
252
|
+
throw "##{fullModuleName} is not a valid engine module" unless Engine[moduleName]
|
253
|
+
|
254
|
+
self.include fullModuleName
|
255
|
+
|
256
|
+
self.trigger "init"
|
257
|
+
|
258
|
+
return self
|
259
|
+
|
260
|
+
Engine.defaultModules = [
|
261
|
+
"Data"
|
262
|
+
"Keyboard"
|
263
|
+
"Mouse"
|
264
|
+
"Background"
|
265
|
+
"Delay"
|
266
|
+
"GameState"
|
267
|
+
"Selector"
|
268
|
+
"Collision"
|
269
|
+
"Tilemap"
|
270
|
+
"Levels"
|
271
|
+
]
|
272
|
+
|
273
|
+
(exports ? this)["Engine"] = Engine
|
274
|
+
)()
|
@@ -0,0 +1,77 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Collision</code> module provides some simple collision detection methods to engine.
|
3
|
+
|
4
|
+
@name Collision
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Collision = (I, self) ->
|
11
|
+
###*
|
12
|
+
Detects collisions between a bounds and the game objects.
|
13
|
+
|
14
|
+
@name collides
|
15
|
+
@methodOf Engine#
|
16
|
+
@param bounds The bounds to check collisions with.
|
17
|
+
@param [sourceObject] An object to exclude from the results.
|
18
|
+
@returns {Boolean} true if the bounds object collides with any of the game objects, false otherwise.
|
19
|
+
###
|
20
|
+
collides: (bounds, sourceObject, selector=".solid") ->
|
21
|
+
self.find(selector).inject false, (collided, object) ->
|
22
|
+
collided or (object != sourceObject) and object.collides(bounds)
|
23
|
+
|
24
|
+
###*
|
25
|
+
Detects collisions between a bounds and the game objects.
|
26
|
+
Returns an array of objects colliding with the bounds provided.
|
27
|
+
|
28
|
+
@name collidesWith
|
29
|
+
@methodOf Engine#
|
30
|
+
@param bounds The bounds to check collisions with.
|
31
|
+
@param [sourceObject] An object to exclude from the results.
|
32
|
+
@returns {Array} An array of objects that collide with the given bounds.
|
33
|
+
###
|
34
|
+
collidesWith: (bounds, sourceObject, selector=".solid") ->
|
35
|
+
self.find(selector).select (object) ->
|
36
|
+
object != sourceObject and object.collides(bounds)
|
37
|
+
|
38
|
+
###*
|
39
|
+
Detects collisions between a ray and the game objects.
|
40
|
+
|
41
|
+
@name rayCollides
|
42
|
+
@methodOf Engine#
|
43
|
+
@param source The origin point
|
44
|
+
@param direction A point representing the direction of the ray
|
45
|
+
@param [sourceObject] An object to exclude from the results.
|
46
|
+
@param [selector] A selector to choos which objects in the engine to collide with
|
47
|
+
###
|
48
|
+
rayCollides: ({source, direction, sourceObject, selector}) ->
|
49
|
+
selector ?= ""
|
50
|
+
|
51
|
+
hits = self.find(selector).map (object) ->
|
52
|
+
hit = (object != sourceObject) and Collision.rayRectangle(source, direction, object.centeredBounds())
|
53
|
+
hit.object = object if hit
|
54
|
+
|
55
|
+
hit
|
56
|
+
|
57
|
+
nearestDistance = Infinity
|
58
|
+
nearestHit = null
|
59
|
+
|
60
|
+
hits.each (hit) ->
|
61
|
+
if hit && (d = hit.distance(source)) < nearestDistance
|
62
|
+
nearestDistance = d
|
63
|
+
nearestHit = hit
|
64
|
+
|
65
|
+
nearestHit
|
66
|
+
|
67
|
+
# TODO Allow specification of collision type (i.e. circular)
|
68
|
+
objectsUnderPoint: (point, selector="") ->
|
69
|
+
bounds = {
|
70
|
+
x: point.x
|
71
|
+
y: point.y
|
72
|
+
width: 0
|
73
|
+
height: 0
|
74
|
+
}
|
75
|
+
|
76
|
+
self.find(selector).select (object) ->
|
77
|
+
object.collides(bounds)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Data</code> module provides methods to store global and persistent data in the engine.
|
3
|
+
|
4
|
+
engine.data.score = 0
|
5
|
+
engine.data.score += 10
|
6
|
+
|
7
|
+
engine.data.score # => 10
|
8
|
+
|
9
|
+
@name Data
|
10
|
+
@fieldOf Engine
|
11
|
+
@module
|
12
|
+
@param {Object} I Instance variables
|
13
|
+
@param {Object} self Reference to the engine
|
14
|
+
###
|
15
|
+
Engine.Data = (I={}, self) ->
|
16
|
+
Object.reverseMerge I,
|
17
|
+
data: {}
|
18
|
+
|
19
|
+
Object.defineProperty self, 'data',
|
20
|
+
get: ->
|
21
|
+
I.data
|
22
|
+
|
23
|
+
{}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Delay</code> module provides methods to trigger events after a number of steps have passed.
|
3
|
+
|
4
|
+
@name Delay
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Delay = (I, self) ->
|
11
|
+
delayedEvents = []
|
12
|
+
|
13
|
+
self.bind 'afterUpdate', (elapsedTime) ->
|
14
|
+
[delayedEvents, firingEvents] = delayedEvents.partition (event) ->
|
15
|
+
(event.delay -= elapsedTime) >= 0
|
16
|
+
|
17
|
+
firingEvents.each (event) ->
|
18
|
+
event.callback()
|
19
|
+
|
20
|
+
return
|
21
|
+
|
22
|
+
###*
|
23
|
+
Execute a callback after a number of seconds have passed.
|
24
|
+
|
25
|
+
engine.delay 5, ->
|
26
|
+
engine.add
|
27
|
+
class: "Ghost"
|
28
|
+
|
29
|
+
@name delay
|
30
|
+
@methodOf Engine#
|
31
|
+
@param {Number} seconds The number of steps to wait before executing the callback
|
32
|
+
@param {Function} callback The callback to be executed.
|
33
|
+
|
34
|
+
@returns {Engine} self
|
35
|
+
###
|
36
|
+
delay: (seconds, callback) ->
|
37
|
+
delayedEvents.push
|
38
|
+
delay: seconds
|
39
|
+
callback: callback
|
40
|
+
|
41
|
+
return self
|
@@ -0,0 +1,32 @@
|
|
1
|
+
###*
|
2
|
+
The <code>FPSCounter</code> module tracks and displays the framerate.
|
3
|
+
|
4
|
+
window.engine = Engine
|
5
|
+
...
|
6
|
+
includedModules: ["FPSCounter"]
|
7
|
+
FPSColor: "#080"
|
8
|
+
|
9
|
+
@name FPSCounter
|
10
|
+
@fieldOf Engine
|
11
|
+
@module
|
12
|
+
|
13
|
+
@param {Object} I Instance variables
|
14
|
+
@param {Object} self Reference to the engine
|
15
|
+
###
|
16
|
+
Engine.FPSCounter = (I, self) ->
|
17
|
+
Object.reverseMerge I,
|
18
|
+
showFPS: true
|
19
|
+
FPSColor: "#FFF"
|
20
|
+
|
21
|
+
framerate = Framerate()
|
22
|
+
|
23
|
+
self.bind "overlay", (canvas) ->
|
24
|
+
if I.showFPS
|
25
|
+
canvas.font("bold 9pt consolas, 'Courier New', 'andale mono', 'lucida console', monospace")
|
26
|
+
|
27
|
+
canvas.drawText
|
28
|
+
color: I.FPSColor
|
29
|
+
position: Point(6, 18)
|
30
|
+
text: "fps: #{framerate.fps}"
|
31
|
+
|
32
|
+
framerate.rendered()
|
@@ -0,0 +1,86 @@
|
|
1
|
+
Engine.GameState = (I, self) ->
|
2
|
+
Object.reverseMerge I,
|
3
|
+
currentState: GameState()
|
4
|
+
|
5
|
+
requestedState = null
|
6
|
+
|
7
|
+
# The idea is that all the engine#beforeUpdate triggers happen
|
8
|
+
# before the state beforeUpdate triggers, then the state update
|
9
|
+
# then the state after update, then the engine after update
|
10
|
+
# like a layered cake with states in the middle.
|
11
|
+
self.bind "update", (elapsedTime) ->
|
12
|
+
I.currentState.trigger "beforeUpdate", elapsedTime
|
13
|
+
I.currentState.trigger "update", elapsedTime
|
14
|
+
I.currentState.trigger "afterUpdate", elapsedTime
|
15
|
+
|
16
|
+
self.bind "afterUpdate", ->
|
17
|
+
# Handle state change
|
18
|
+
if requestedState?
|
19
|
+
I.currentState.trigger "exit", requestedState
|
20
|
+
self.trigger 'stateExited', I.currentState
|
21
|
+
|
22
|
+
previousState = I.currentState
|
23
|
+
I.currentState = requestedState
|
24
|
+
|
25
|
+
I.currentState.trigger "enter", previousState
|
26
|
+
self.trigger 'stateEntered', I.currentState
|
27
|
+
|
28
|
+
requestedState = null
|
29
|
+
|
30
|
+
self.bind "draw", (canvas) ->
|
31
|
+
I.currentState.trigger "beforeDraw", canvas
|
32
|
+
I.currentState.trigger "draw", canvas
|
33
|
+
I.currentState.trigger "overlay", canvas
|
34
|
+
|
35
|
+
|
36
|
+
# Just pass through to the current state
|
37
|
+
add: (classNameOrEntityData, entityData={}) ->
|
38
|
+
# Allow optional add "Class", data form
|
39
|
+
if classNameOrEntityData.isString?()
|
40
|
+
entityData.class = classNameOrEntityData
|
41
|
+
else
|
42
|
+
entityData = classNameOrEntityData
|
43
|
+
|
44
|
+
self.trigger "beforeAdd", entityData
|
45
|
+
object = I.currentState.add(entityData)
|
46
|
+
self.trigger "afterAdd", object
|
47
|
+
|
48
|
+
return object
|
49
|
+
|
50
|
+
camera: (n=0) ->
|
51
|
+
self.cameras()[n]
|
52
|
+
|
53
|
+
cameras: (newCameras) ->
|
54
|
+
if newCameras?
|
55
|
+
I.currentState.cameras(newCameras)
|
56
|
+
|
57
|
+
return self
|
58
|
+
else
|
59
|
+
I.currentState.cameras()
|
60
|
+
|
61
|
+
fadeIn: (options={}) ->
|
62
|
+
self.cameras().invoke('fadeIn', options)
|
63
|
+
|
64
|
+
fadeOut: (options={}) ->
|
65
|
+
self.cameras().invoke('fadeOut', options)
|
66
|
+
|
67
|
+
flash: (options={}) ->
|
68
|
+
self.camera(options.camera).flash(options)
|
69
|
+
|
70
|
+
objects: ->
|
71
|
+
I.currentState.objects()
|
72
|
+
|
73
|
+
setState: (newState) ->
|
74
|
+
requestedState = newState
|
75
|
+
|
76
|
+
shake: (options={}) ->
|
77
|
+
self.camera(options.camera).shake(options)
|
78
|
+
|
79
|
+
saveState: ->
|
80
|
+
I.currentState.saveState()
|
81
|
+
|
82
|
+
loadState: (newState) ->
|
83
|
+
I.currentState.loadState(newState)
|
84
|
+
|
85
|
+
reload: ->
|
86
|
+
I.currentState.reload()
|
@@ -0,0 +1,47 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Joysticks</code> module gives the engine access to joysticks.
|
3
|
+
|
4
|
+
# First you need to add the joysticks module to the engine
|
5
|
+
window.engine = Engine
|
6
|
+
...
|
7
|
+
includedModules: ["Joysticks"]
|
8
|
+
# Then you need to get a controller reference
|
9
|
+
# id = 0 for player 1, etc.
|
10
|
+
controller = engine.controller(id)
|
11
|
+
|
12
|
+
# Point indicating direction primary axis is held
|
13
|
+
direction = controller.position()
|
14
|
+
|
15
|
+
# Check if buttons are held
|
16
|
+
controller.actionDown("A")
|
17
|
+
controller.actionDown("B")
|
18
|
+
controller.actionDown("X")
|
19
|
+
controller.actionDown("Y")
|
20
|
+
|
21
|
+
@name Joysticks
|
22
|
+
@fieldOf Engine
|
23
|
+
@module
|
24
|
+
|
25
|
+
@param {Object} I Instance variables
|
26
|
+
@param {Object} self Reference to the engine
|
27
|
+
###
|
28
|
+
Engine.Joysticks = (I, self) ->
|
29
|
+
Joysticks.init()
|
30
|
+
|
31
|
+
self.bind "update", ->
|
32
|
+
# Handle hotswapping, does nothing if already initialized
|
33
|
+
Joysticks.init()
|
34
|
+
|
35
|
+
# Update the joysticks, this also fires joystick events to listeners
|
36
|
+
Joysticks.update()
|
37
|
+
|
38
|
+
###*
|
39
|
+
Get a controller for a given joystick id.
|
40
|
+
|
41
|
+
@name controller
|
42
|
+
@methodOf Engine.Joysticks#
|
43
|
+
|
44
|
+
@param {Number} i The joystick id to get the controller of.
|
45
|
+
###
|
46
|
+
controller: (i) ->
|
47
|
+
Joysticks.getController(i)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
###*
|
2
|
+
This module sets up the keyboard inputs for each engine update.
|
3
|
+
|
4
|
+
@name Keyboard
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Keyboard = (I, self) ->
|
11
|
+
self.bind "beforeUpdate", ->
|
12
|
+
# TODO: Make a Gamepad/Keyboard input module that has web and XNA
|
13
|
+
# implementations
|
14
|
+
updateKeys?()
|
15
|
+
|
16
|
+
return {}
|
17
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
###*
|
2
|
+
This module provides methods for transitioning between levels.
|
3
|
+
|
4
|
+
@name Levels
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Levels = (I, self) ->
|
11
|
+
Object.reverseMerge I,
|
12
|
+
levels: []
|
13
|
+
currentLevel: -1
|
14
|
+
currentLevelName: null
|
15
|
+
|
16
|
+
I.transitioning = false
|
17
|
+
|
18
|
+
loadLevel = (level) ->
|
19
|
+
unless I.transitioning
|
20
|
+
I.transitioning = true
|
21
|
+
|
22
|
+
levelState = LevelState
|
23
|
+
level: level
|
24
|
+
|
25
|
+
I.currentLevelName = level
|
26
|
+
engine.setState levelState
|
27
|
+
|
28
|
+
###*
|
29
|
+
Load map for the next level.
|
30
|
+
|
31
|
+
engine.nextLevel()
|
32
|
+
|
33
|
+
@name nextLevel
|
34
|
+
@methodOf Engine#
|
35
|
+
###
|
36
|
+
nextLevel: ->
|
37
|
+
unless I.transitioning
|
38
|
+
I.currentLevel += 1
|
39
|
+
|
40
|
+
if level = I.levels[I.currentLevel]
|
41
|
+
loadLevel level
|
42
|
+
else
|
43
|
+
engine.setState GameOver()
|
44
|
+
|
45
|
+
###*
|
46
|
+
Load map named <code>level</code>
|
47
|
+
|
48
|
+
engine.goToLevel 'bossFight'
|
49
|
+
|
50
|
+
@name goToLevel
|
51
|
+
@methodOf Engine#
|
52
|
+
###
|
53
|
+
goToLevel: (level) ->
|
54
|
+
#TODO Handle integer levels?
|
55
|
+
loadLevel level
|
56
|
+
|
57
|
+
###*
|
58
|
+
Reload the current level. Useful for retrying after a player dies.
|
59
|
+
|
60
|
+
engine.reloadLevel()
|
61
|
+
|
62
|
+
@name reloadLevel
|
63
|
+
@methodOf Engine#
|
64
|
+
###
|
65
|
+
restartLevel: ->
|
66
|
+
loadLevel I.currentLevelName
|
67
|
+
|
68
|
+
reloadLevel: ->
|
69
|
+
self.restartLevel()
|
@@ -0,0 +1,16 @@
|
|
1
|
+
###*
|
2
|
+
This module sets up the mouse inputs for each engine update.
|
3
|
+
|
4
|
+
@name Mouse
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Mouse = (I, self) ->
|
11
|
+
self.bind "beforeUpdate", ->
|
12
|
+
# TODO: Make a Gamepad/Keyboard/Mouse input module that has web and XNA
|
13
|
+
# implementations
|
14
|
+
updateMouse?()
|
15
|
+
|
16
|
+
return {}
|