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,166 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Selector</code> module provides methods to query the engine to find game objects.
|
3
|
+
|
4
|
+
@name Selector
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Selector = (I, self) ->
|
11
|
+
|
12
|
+
instanceMethods =
|
13
|
+
set: (attr, value) ->
|
14
|
+
this.each (item) ->
|
15
|
+
item.I[attr] = value
|
16
|
+
|
17
|
+
###*
|
18
|
+
Get the game object matching the given selector that is closest to the given position.
|
19
|
+
|
20
|
+
player = engine.add
|
21
|
+
x: 0
|
22
|
+
y: 0
|
23
|
+
|
24
|
+
enemy1 = engine.add
|
25
|
+
enemy: true
|
26
|
+
x: 10
|
27
|
+
y: 0
|
28
|
+
|
29
|
+
enemy2 = engine.add
|
30
|
+
enemy: true
|
31
|
+
x: 0
|
32
|
+
y: 15
|
33
|
+
|
34
|
+
player2 = engine.add
|
35
|
+
x: 0
|
36
|
+
y: 10
|
37
|
+
|
38
|
+
equals engine.closest(".enemy", player.position()), enemy1
|
39
|
+
equals engine.closest(".enemy", player2.position()), enemy2
|
40
|
+
|
41
|
+
@name closest
|
42
|
+
@methodOf Engine.selector
|
43
|
+
@param {String} selector
|
44
|
+
@param {Point} position
|
45
|
+
###
|
46
|
+
closest: (selector, position) ->
|
47
|
+
self.find(selector).sort (a, b) ->
|
48
|
+
Point.distanceSquared(position, a.position()) - Point.distanceSquared(position, b.position())
|
49
|
+
.first()
|
50
|
+
|
51
|
+
###*
|
52
|
+
Get a selection of GameObjects that match the specified selector criteria. The selector language
|
53
|
+
can select objects by id, class, or attributes. Note that this method always returns an Array,
|
54
|
+
so if you are trying to find only one object you will need something like <code>engine.find("Enemy").first()</code>.
|
55
|
+
|
56
|
+
player = engine.add
|
57
|
+
class: "Player"
|
58
|
+
|
59
|
+
enemy = engine.add
|
60
|
+
class: "Enemy"
|
61
|
+
speed: 5
|
62
|
+
x: 0
|
63
|
+
|
64
|
+
distantEnemy = engine.add
|
65
|
+
class "Enemy"
|
66
|
+
x: 500
|
67
|
+
|
68
|
+
boss = engine.add
|
69
|
+
class: "Enemy"
|
70
|
+
id: "Boss"
|
71
|
+
x: 0
|
72
|
+
|
73
|
+
# to select an object by id use "#anId"
|
74
|
+
engine.find "#Boss"
|
75
|
+
# => [boss]
|
76
|
+
|
77
|
+
# to select an object by class use "MyClass"
|
78
|
+
engine.find "Enemy"
|
79
|
+
# => [enemy, distantEnemy, boss]
|
80
|
+
|
81
|
+
# to select an object by properties use ".someProperty" or ".someProperty=someValue"
|
82
|
+
engine.find ".speed=5"
|
83
|
+
# => [enemy]
|
84
|
+
|
85
|
+
# You may mix and match selectors.
|
86
|
+
engine.find "Enemy.x=0"
|
87
|
+
# => [enemy, boss] # doesn't return distantEnemy
|
88
|
+
|
89
|
+
@name find
|
90
|
+
@methodOf Engine#
|
91
|
+
@param {String} selector
|
92
|
+
@returns {Array} An array of the objects found
|
93
|
+
###
|
94
|
+
each: (selector, fn) ->
|
95
|
+
self.find(selector).each (obj, index) ->
|
96
|
+
fn(obj, index)
|
97
|
+
|
98
|
+
###*
|
99
|
+
Find all game objects that match the given selector.
|
100
|
+
|
101
|
+
@name find
|
102
|
+
@methodOf Engine.selector
|
103
|
+
|
104
|
+
@param {String} selector
|
105
|
+
###
|
106
|
+
find: (selector) ->
|
107
|
+
results = []
|
108
|
+
|
109
|
+
matcher = Engine.Selector.generate(selector)
|
110
|
+
|
111
|
+
self.objects().each (object) ->
|
112
|
+
results.push object if matcher.match object
|
113
|
+
|
114
|
+
Object.extend results, instanceMethods
|
115
|
+
|
116
|
+
###*
|
117
|
+
Find the first game object that matches the given selector.
|
118
|
+
|
119
|
+
@name find
|
120
|
+
@methodOf Engine.selector
|
121
|
+
|
122
|
+
@param {String} selector
|
123
|
+
###
|
124
|
+
first: (selector) ->
|
125
|
+
self.find(selector).first()
|
126
|
+
|
127
|
+
Object.extend Engine.Selector,
|
128
|
+
parse: (selector) ->
|
129
|
+
selector.split(",").invoke("trim")
|
130
|
+
|
131
|
+
process: (item) ->
|
132
|
+
result = /^(\w+)?#?([\w\-]+)?\.?([\w\-]+)?=?([\w\-]+)?/.exec(item)
|
133
|
+
|
134
|
+
if result
|
135
|
+
result[4] = result[4].parse() if result[4]
|
136
|
+
|
137
|
+
result.splice(1)
|
138
|
+
else
|
139
|
+
[]
|
140
|
+
|
141
|
+
generate: (selector) ->
|
142
|
+
components = Engine.Selector.parse(selector).map (piece) ->
|
143
|
+
Engine.Selector.process(piece)
|
144
|
+
|
145
|
+
TYPE = 0
|
146
|
+
ID = 1
|
147
|
+
ATTR = 2
|
148
|
+
ATTR_VALUE = 3
|
149
|
+
|
150
|
+
match: (object) ->
|
151
|
+
for component in components
|
152
|
+
idMatch = (component[ID] == object.I.id) || !component[ID]
|
153
|
+
typeMatch = (component[TYPE] == object.I.class) || !component[TYPE]
|
154
|
+
|
155
|
+
if attr = component[ATTR]
|
156
|
+
if (value = component[ATTR_VALUE])?
|
157
|
+
attrMatch = (object.I[attr] == value)
|
158
|
+
else
|
159
|
+
attrMatch = object.I[attr]
|
160
|
+
else
|
161
|
+
attrMatch = true
|
162
|
+
|
163
|
+
return true if idMatch && typeMatch && attrMatch
|
164
|
+
|
165
|
+
return false
|
166
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Stats</code> module provides methods to query the engine to find game objects.
|
3
|
+
|
4
|
+
@name Stats
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
Engine.Stats = (I, self) ->
|
11
|
+
measure: (objects, field, frequency=30) ->
|
12
|
+
; #TODO
|
13
|
+
|
14
|
+
gatherData: ->
|
15
|
+
self.find()
|
16
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
###*
|
2
|
+
The <code>Tilemap</code> module provides a way to load tilemaps in the engine.
|
3
|
+
|
4
|
+
@name Tilemap
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
|
8
|
+
@param {Object} I Instance variables
|
9
|
+
@param {Object} self Reference to the engine
|
10
|
+
###
|
11
|
+
Engine.Tilemap = (I, self) ->
|
12
|
+
Object.extend I,
|
13
|
+
map: null
|
14
|
+
|
15
|
+
updating = false
|
16
|
+
clearObjects = false
|
17
|
+
|
18
|
+
self.bind "update", ->
|
19
|
+
updating = true
|
20
|
+
|
21
|
+
self.bind "afterUpdate", ->
|
22
|
+
updating = false
|
23
|
+
|
24
|
+
if clearObjects
|
25
|
+
#TODO: Clear these out in a more graceful way, triggering unload events
|
26
|
+
self.objects().clear()
|
27
|
+
clearObjects = false
|
28
|
+
|
29
|
+
###*
|
30
|
+
Loads a new may and unloads any existing map or entities.
|
31
|
+
|
32
|
+
@name loadMap
|
33
|
+
@methodOf Engine#
|
34
|
+
###
|
35
|
+
loadMap: (name, complete) ->
|
36
|
+
clearObjects = updating
|
37
|
+
|
38
|
+
I.map = Tilemap.load
|
39
|
+
name: name
|
40
|
+
complete: complete
|
41
|
+
entity: self.add
|
@@ -0,0 +1,32 @@
|
|
1
|
+
###*
|
2
|
+
This module clears or fills the canvas before drawing the scene.
|
3
|
+
|
4
|
+
@name Clear
|
5
|
+
@fieldOf Engine
|
6
|
+
@module
|
7
|
+
@param {Object} I Instance variables
|
8
|
+
@param {Object} self Reference to the engine
|
9
|
+
###
|
10
|
+
|
11
|
+
Engine.Background = (I, self) ->
|
12
|
+
Object.reverseMerge I,
|
13
|
+
background: null
|
14
|
+
backgroundColor: "#00010D"
|
15
|
+
clear: false
|
16
|
+
|
17
|
+
self.attrAccessor "clear", "backgroundColor"
|
18
|
+
|
19
|
+
self.bind "init", ->
|
20
|
+
if I.background?.isString?()
|
21
|
+
I.background = Sprite.loadByName I.background
|
22
|
+
|
23
|
+
self.bind "beforeDraw", ->
|
24
|
+
if I.clear
|
25
|
+
I.canvas.clear()
|
26
|
+
else if I.background
|
27
|
+
I.background.fill(I.canvas, 0, 0, App.width, App.height)
|
28
|
+
else if I.backgroundColor
|
29
|
+
I.canvas.fill(I.backgroundColor)
|
30
|
+
|
31
|
+
# No public methods
|
32
|
+
return {}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
###*
|
2
|
+
The Expirable module deactivates a <code>GameObject</code> after a specified duration.
|
3
|
+
If a duration is specified the object will update that many times. If -1 is
|
4
|
+
specified the object will have an unlimited duration.
|
5
|
+
|
6
|
+
This module is included by default in <code>GameObjects</code>
|
7
|
+
|
8
|
+
enemy = GameObject
|
9
|
+
x: 50
|
10
|
+
y: 30
|
11
|
+
duration: 5
|
12
|
+
|
13
|
+
enemy.include Expirable
|
14
|
+
|
15
|
+
enemy.I.active
|
16
|
+
# => true
|
17
|
+
|
18
|
+
5.times ->
|
19
|
+
enemy.update(1)
|
20
|
+
|
21
|
+
enemy.I.active
|
22
|
+
# => false
|
23
|
+
|
24
|
+
@name Expirable
|
25
|
+
@module
|
26
|
+
@constructor
|
27
|
+
@param {Object} I Instance variables
|
28
|
+
@param {Core} self Reference to including object
|
29
|
+
###
|
30
|
+
Expirable = (I={}, self) ->
|
31
|
+
Object.reverseMerge I,
|
32
|
+
duration: -1
|
33
|
+
alpha: 1
|
34
|
+
fadeOut: false
|
35
|
+
|
36
|
+
startingAlpha = I.alpha
|
37
|
+
|
38
|
+
self.bind "update", (dt) ->
|
39
|
+
if I.fadeOut
|
40
|
+
I.alpha = startingAlpha * (1 - (I.age / I.duration))
|
41
|
+
|
42
|
+
if I.duration != -1 && I.age >= I.duration
|
43
|
+
I.active = false
|
44
|
+
|
45
|
+
I.alpha = I.alpha.clamp(0, 1)
|
46
|
+
|
47
|
+
return {}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
###*
|
2
|
+
The `Flickerable` module provides a method to flicker a sprite between its current opacity (alpha) and a given opacity.
|
3
|
+
|
4
|
+
player = GameObject
|
5
|
+
alpha: 0.9
|
6
|
+
|
7
|
+
player.include 'Flickerable'
|
8
|
+
|
9
|
+
# called with no arguments, flicker will toggle the player's alpha
|
10
|
+
# value between 0.9 (value provided above) and 0.5 (flickerable default)
|
11
|
+
# every 0.1 second, for a total of 2 seconds
|
12
|
+
player.flicker()
|
13
|
+
|
14
|
+
@name Flickerable
|
15
|
+
@module
|
16
|
+
@constructor
|
17
|
+
@param {Object} I Instance variables
|
18
|
+
@param {Core} self Reference to including object
|
19
|
+
###
|
20
|
+
Flickerable = (I={}, self) ->
|
21
|
+
Object.reverseMerge I,
|
22
|
+
flickerAlpha: 0.5
|
23
|
+
flickerDuration: 0
|
24
|
+
flickerFrequency: 0.1
|
25
|
+
|
26
|
+
originalAlpha = I.alpha
|
27
|
+
frequencyLength = 0
|
28
|
+
|
29
|
+
self.bind 'update', (elapsedTime) ->
|
30
|
+
I.flickerDuration = I.flickerDuration.approach(0, elapsedTime)
|
31
|
+
|
32
|
+
frequencyLength += elapsedTime
|
33
|
+
|
34
|
+
if I.flickerDuration > 0
|
35
|
+
if frequencyLength >= I.flickerFrequency
|
36
|
+
frequencyLength = 0
|
37
|
+
|
38
|
+
if I.alpha is I.flickerAlpha
|
39
|
+
I.alpha = originalAlpha
|
40
|
+
else
|
41
|
+
I.alpha = I.flickerAlpha
|
42
|
+
else
|
43
|
+
I.alpha = originalAlpha
|
44
|
+
|
45
|
+
###*
|
46
|
+
A convenient way to set the flicker instance variables on a sprite. You can modify the
|
47
|
+
instance variables by hand but the suggested way to do it is through this method.
|
48
|
+
|
49
|
+
player = GameObject()
|
50
|
+
|
51
|
+
player.include(Flickerable)
|
52
|
+
|
53
|
+
player.flicker
|
54
|
+
duration: 5
|
55
|
+
frequency: 0.2
|
56
|
+
alpha: 0.3
|
57
|
+
|
58
|
+
# => This causes the sprite to flicker between full opacity
|
59
|
+
# => and 30% opacity every 0.2 seconds for 5 seconds
|
60
|
+
|
61
|
+
@name flicker
|
62
|
+
@methodOf Flickerable#
|
63
|
+
@param {Number} [duration=2] How long the effect lasts in seconds
|
64
|
+
@param {Number} [frequency=0.1] Number of seconds in between opacity changes
|
65
|
+
@param {Number} [alpha=0.5] Alpha value to toggle between
|
66
|
+
@returns {GameObject} The calling object
|
67
|
+
###
|
68
|
+
flicker: (options={}) ->
|
69
|
+
Object.reverseMerge options,
|
70
|
+
duration: 2
|
71
|
+
frequency: 0.1
|
72
|
+
alpha: 0.5
|
73
|
+
|
74
|
+
I.flickerDuration = options.duration
|
75
|
+
I.flickerFrequency = options.frequency
|
76
|
+
I.flickerAlpha = options.alpha
|
77
|
+
|
78
|
+
return self
|
@@ -0,0 +1,65 @@
|
|
1
|
+
###*
|
2
|
+
The Follow module provides a simple method to set an object's
|
3
|
+
direction so that it is pointed at another object.
|
4
|
+
|
5
|
+
The calculated direction is based on the center point of
|
6
|
+
each object.
|
7
|
+
|
8
|
+
This method relies on both objects having <code>position</code> methods.
|
9
|
+
|
10
|
+
Include this module by calling <code>self.include Follow</code>
|
11
|
+
|
12
|
+
player = GameObject
|
13
|
+
x: 50
|
14
|
+
y: 50
|
15
|
+
width: 10
|
16
|
+
height: 10
|
17
|
+
|
18
|
+
enemy = GameObject
|
19
|
+
x: 100
|
20
|
+
y: 50
|
21
|
+
width: 10
|
22
|
+
height: 10
|
23
|
+
velocity: Point(0, 0)
|
24
|
+
speed: 2
|
25
|
+
|
26
|
+
enemy.include Follow
|
27
|
+
|
28
|
+
# Make an enemy follow the player
|
29
|
+
enemy.follow(player)
|
30
|
+
|
31
|
+
# now the enemy's direction will point toward the player
|
32
|
+
enemy.I.direction
|
33
|
+
# => Point(-1, 0)
|
34
|
+
|
35
|
+
# you can use this direction to set a velocity for your object.
|
36
|
+
enemy.I.velocity = enemy.I.direction.scale(I.speed)
|
37
|
+
|
38
|
+
|
39
|
+
@name Follow
|
40
|
+
@module
|
41
|
+
@constructor
|
42
|
+
@param {Object} I Instance variables
|
43
|
+
@param {Core} self Reference to including object
|
44
|
+
###
|
45
|
+
Follow = (I={}, self) ->
|
46
|
+
Object.reverseMerge I,
|
47
|
+
velocity: Point(0, 0)
|
48
|
+
speed: 1
|
49
|
+
|
50
|
+
###*
|
51
|
+
Set your velocity to follow another object.
|
52
|
+
|
53
|
+
enemy.follow(player)
|
54
|
+
|
55
|
+
# => The enemy now has it's velocity attribute set in
|
56
|
+
# the direction of the player, with magnitude equal to
|
57
|
+
# the enemy's speed
|
58
|
+
|
59
|
+
@name follow
|
60
|
+
@methodOf Follow#
|
61
|
+
@param {GameObject} obj The object you want to follow
|
62
|
+
###
|
63
|
+
follow: (obj) ->
|
64
|
+
if obj
|
65
|
+
I.velocity = obj.position().subtract(self.position()).norm(I.speed)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
###*
|
2
|
+
This object keeps track of framerate and displays it by creating and appending an
|
3
|
+
html element to the DOM.
|
4
|
+
|
5
|
+
Once created you call snapshot at the end of every rendering cycle.
|
6
|
+
|
7
|
+
@name Framerate
|
8
|
+
@constructor
|
9
|
+
###
|
10
|
+
Framerate = (options={}) ->
|
11
|
+
numFramerates = 15
|
12
|
+
framerateUpdateInterval = 250
|
13
|
+
|
14
|
+
renderTime = -1
|
15
|
+
framerates = [ ]
|
16
|
+
|
17
|
+
updateFramerate = ->
|
18
|
+
self.fps = framerates.average().round()
|
19
|
+
|
20
|
+
setInterval(updateFramerate, framerateUpdateInterval)
|
21
|
+
|
22
|
+
###*
|
23
|
+
Call this method everytime you render.
|
24
|
+
|
25
|
+
@name rendered
|
26
|
+
@methodOf Framerate#
|
27
|
+
###
|
28
|
+
self =
|
29
|
+
rendered: ->
|
30
|
+
if renderTime < 0
|
31
|
+
renderTime = new Date().getTime()
|
32
|
+
else
|
33
|
+
newTime = new Date().getTime()
|
34
|
+
t = newTime - renderTime
|
35
|
+
|
36
|
+
framerate = 1000 / t
|
37
|
+
framerates.push(framerate)
|
38
|
+
|
39
|
+
while (framerates.length > numFramerates)
|
40
|
+
framerates.shift()
|
41
|
+
|
42
|
+
renderTime = newTime
|
@@ -0,0 +1,181 @@
|
|
1
|
+
###*
|
2
|
+
The default base class for all objects you can add to the engine.
|
3
|
+
|
4
|
+
GameObjects fire events that you may bind listeners to. Event listeners
|
5
|
+
may be bound with <code>object.bind(eventName, callback)</code>
|
6
|
+
|
7
|
+
@name GameObject
|
8
|
+
@extends Core
|
9
|
+
@constructor
|
10
|
+
@instanceVariables age, active, created, destroyed, solid, includedModules, excludedModules
|
11
|
+
###
|
12
|
+
|
13
|
+
###*
|
14
|
+
Triggered when the object is created.
|
15
|
+
|
16
|
+
enemyCount = 0
|
17
|
+
|
18
|
+
enemy = engine.add
|
19
|
+
class: "Enemy"
|
20
|
+
|
21
|
+
enemy.bind 'create', ->
|
22
|
+
enemyCount++
|
23
|
+
|
24
|
+
@name create
|
25
|
+
@methodOf GameObject#
|
26
|
+
@event
|
27
|
+
###
|
28
|
+
|
29
|
+
###*
|
30
|
+
Triggered when object is destroyed. Use
|
31
|
+
the destroy event to add particle effects, play sounds, etc.
|
32
|
+
|
33
|
+
bomb = GameObject()
|
34
|
+
|
35
|
+
bomb.bind 'destroy', ->
|
36
|
+
bomb.explode()
|
37
|
+
Sound.play "Kaboom"
|
38
|
+
|
39
|
+
@name destroy
|
40
|
+
@methodOf GameObject#
|
41
|
+
@event
|
42
|
+
###
|
43
|
+
|
44
|
+
###*
|
45
|
+
Triggered during every update step.
|
46
|
+
|
47
|
+
player = GameObject()
|
48
|
+
|
49
|
+
player.bind 'step', ->
|
50
|
+
# check to see if keys are being pressed and
|
51
|
+
# change the player's velocity
|
52
|
+
if keydown.left
|
53
|
+
player.velocity(Point(-1, 0))
|
54
|
+
else if keydown.right
|
55
|
+
player.velocity(Point(1, 0))
|
56
|
+
else
|
57
|
+
player.velocity(Point(0, 0))
|
58
|
+
|
59
|
+
@name step
|
60
|
+
@methodOf GameObject#
|
61
|
+
@event
|
62
|
+
###
|
63
|
+
|
64
|
+
###*
|
65
|
+
Triggered every update after the <code>step</code> event is triggered.
|
66
|
+
|
67
|
+
player = GameObject()
|
68
|
+
|
69
|
+
# we can really use the update and
|
70
|
+
# step events almost interchangebly
|
71
|
+
player.bind 'update', ->
|
72
|
+
# check to see if keys are being pressed and
|
73
|
+
# change the player's velocity
|
74
|
+
if keydown.left
|
75
|
+
player.velocity(Point(-1, 0))
|
76
|
+
else if keydown.right
|
77
|
+
player.velocity(Point(1, 0))
|
78
|
+
else
|
79
|
+
player.velocity(Point(0, 0))
|
80
|
+
|
81
|
+
@name update
|
82
|
+
@methodOf GameObject#
|
83
|
+
@event
|
84
|
+
###
|
85
|
+
|
86
|
+
###*
|
87
|
+
Triggered when the object is removed from
|
88
|
+
the engine. Use the remove event to handle any clean up.
|
89
|
+
|
90
|
+
boss = GameObject()
|
91
|
+
|
92
|
+
boss.bind 'remove', ->
|
93
|
+
unlockDoorToLevel2()
|
94
|
+
|
95
|
+
@name remove
|
96
|
+
@methodOf GameObject#
|
97
|
+
@event
|
98
|
+
###
|
99
|
+
|
100
|
+
GameObject = (I) ->
|
101
|
+
I ||= {}
|
102
|
+
|
103
|
+
###*
|
104
|
+
@name {Object} I Instance variables
|
105
|
+
@memberOf GameObject#
|
106
|
+
###
|
107
|
+
Object.reverseMerge I,
|
108
|
+
active: true
|
109
|
+
created: false
|
110
|
+
destroyed: false
|
111
|
+
|
112
|
+
self = Core(I).extend {
|
113
|
+
###*
|
114
|
+
Update the game object. This is generally called by the engine.
|
115
|
+
|
116
|
+
@name update
|
117
|
+
@methodOf GameObject#
|
118
|
+
###
|
119
|
+
update: (elapsedTime) ->
|
120
|
+
#TODO Extract this I.active check out into an engine gameObject remove processor or something
|
121
|
+
if I.active
|
122
|
+
self.trigger 'update', elapsedTime
|
123
|
+
|
124
|
+
I.active
|
125
|
+
|
126
|
+
###*
|
127
|
+
Triggers the create event if the object has not already been created.
|
128
|
+
|
129
|
+
@name create
|
130
|
+
@methodOf GameObject#
|
131
|
+
###
|
132
|
+
create: ->
|
133
|
+
self.trigger('create') unless I.created
|
134
|
+
I.created = true
|
135
|
+
|
136
|
+
###*
|
137
|
+
Destroys the object and triggers the destroyed event.
|
138
|
+
|
139
|
+
@name destroy
|
140
|
+
@methodOf GameObject#
|
141
|
+
###
|
142
|
+
destroy: ->
|
143
|
+
self.trigger('destroy') unless I.destroyed
|
144
|
+
|
145
|
+
I.destroyed = true
|
146
|
+
I.active = false
|
147
|
+
}
|
148
|
+
|
149
|
+
GameObject.defaultModules.each (moduleName) ->
|
150
|
+
self.include moduleName
|
151
|
+
|
152
|
+
self
|
153
|
+
|
154
|
+
GameObject.defaultModules = [
|
155
|
+
"Ageable"
|
156
|
+
"Bounded"
|
157
|
+
"Clampable"
|
158
|
+
"Cooldown"
|
159
|
+
"Drawable"
|
160
|
+
"Expirable"
|
161
|
+
"Follow"
|
162
|
+
"GameObject.Meter"
|
163
|
+
"Movable"
|
164
|
+
"Rotatable"
|
165
|
+
"TimedEvents"
|
166
|
+
"Tween"
|
167
|
+
"GameObject.Effect"
|
168
|
+
]
|
169
|
+
|
170
|
+
###*
|
171
|
+
Construct an object instance from the given entity data.
|
172
|
+
@name construct
|
173
|
+
@memberOf GameObject
|
174
|
+
@param {Object} entityData
|
175
|
+
###
|
176
|
+
GameObject.construct = (entityData) ->
|
177
|
+
if entityData.class
|
178
|
+
entityData.class.constantize()(entityData)
|
179
|
+
else
|
180
|
+
GameObject(entityData)
|
181
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
###*
|
2
|
+
A collection of effects to make your game juicy.
|
3
|
+
|
4
|
+
@name Effect
|
5
|
+
@fieldOf GameObject
|
6
|
+
@module
|
7
|
+
@constructor
|
8
|
+
@param {Object} I Instance variables
|
9
|
+
@param {Core} self Reference to including object
|
10
|
+
###
|
11
|
+
GameObject.Effect = (I={}, self) ->
|
12
|
+
|
13
|
+
###*
|
14
|
+
A convenient way to fade out this object over time.
|
15
|
+
|
16
|
+
player = GameObject()
|
17
|
+
|
18
|
+
# Fade the player object out over the next 2 seconds.
|
19
|
+
player.fadeOut 2
|
20
|
+
|
21
|
+
# Fade out and then destroy
|
22
|
+
player.fadeOut, 0.25, ->
|
23
|
+
self.destroy()
|
24
|
+
|
25
|
+
@name fadeOut
|
26
|
+
@methodOf GameObject#
|
27
|
+
@param {Number} [duration=1] Time to fade out in seconds
|
28
|
+
@param {Function} [complete=null] The function to execute when fade out completes.
|
29
|
+
###
|
30
|
+
fadeOut: (duration=1, complete) ->
|
31
|
+
self.tween duration,
|
32
|
+
alpha: 0
|
33
|
+
complete: complete
|