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,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
|
data/source/tween.coffee
ADDED
@@ -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()
|