1 /**
2 A class to represent the player on the screen
3 @author <a href="mailto:matthewcasperson@gmail.com">Matthew Casperson</a>
4 @class
5 */
6 function Player()
7 {
8 /** The maximum height of the jump
9 @type Number
10 */
11 this.jumpHeight = 64;
12 /** The constant or half PI
13 @type Number
14 */
15 this.halfPI = Math.PI / 2;
16 /** The amount of time to spend in the air when jumping
17 @type Number
18 */
19 this.jumpHangTime = 0.5;
20 /** The speed to progress alone the sine wave that defines
21 the jumping arc
22 @type Number
23 */
24 this.jumpSinWaveSpeed = this.halfPI / this.jumpHangTime;
25 /** The current position on the sine wave that defines the jump arc
26 @type Number
27 */
28 this.jumpSinWavePos = 0;
29 /** The rate to fall at
30 @type Number
31 */
32 this.fallMultiplyer = 1.5;
33 /** True when the player is on the ground, false otherwise
34 @type Boolean
35 */
36 this.grounded = true;
37 /** the players running speed
38 @type Number
39 */
40 this.speed = 75;
41 /** True if the player is moving left, false otherwise
42 @type Boolean
43 */
44 this.left = false;
45 /** True if the player is moving right, false otherwise
46 @type Boolean
47 */
48 this.right = false;
49 /** A reference to the level object
50 @type Level
51 */
52 this.level = null;
53 /** The distance between the player and the edge of the screen
54 @type Number
55 */
56 this.screenBorder = 20;
57
58 /**
59 Initialises this object
60 */
61 this.startupPlayer = function(level)
62 {
63 this.startupAnimatedGameObject(g_idle_left, 300, 400 - 48 - 48, 4, 6, 20);
64 this.level = level;
65 return this;
66 }
67
68 /**
69 Called when a key is pressed
70 @param event Event Object
71 */
72 this.keyDown = function(event)
73 {
74 var updateRequired = false;
75
76 // left
77 if (event.keyCode == 37 && !this.left)
78 {
79 this.left = true;
80 updateRequired = true;
81 }
82 // right
83 if (event.keyCode == 39 && !this.right)
84 {
85 this.right = true;
86 updateRequired = true;
87 }
88 if (event.keyCode == 32 && this.grounded)
89 {
90 this.grounded = false;
91 this.jumpSinWavePos = 0;
92 }
93
94 if (updateRequired)
95 this.updateAnimation();
96
97 }
98
99 /**
100 Called when a key is pressed
101 @param event Event Object
102 */
103 this.keyUp = function(event)
104 {
105 // left
106 if (event.keyCode == 37)
107 {
108 this.left = false;
109 this.setAnimation(g_idle_left, 6, 20);
110 }
111 // right
112 if (event.keyCode == 39)
113 {
114 this.right = false;
115 this.setAnimation(g_idle_right, 6, 20);
116 }
117
118 this.updateAnimation();
119 }
120
121 /**
122 Updates the current animation depending on the movement
123 of the player. This accounts for the fact that both
124 the left and right arrow keys can be pressed at the
125 same time.
126 */
127 this.updateAnimation = function()
128 {
129 if (this.right && this.left)
130 this.setAnimation(g_idle_left, 6, 20);
131 else if (this.right)
132 this.setAnimation(g_run_right, 12, 20);
133 else if (this.left)
134 this.setAnimation(g_run_left, 12, 20);
135 }
136
137 /**
138 Updates the object
139 @param dt The time since the last frame in seconds
140 @param context The drawing context
141 @param xScroll The global scrolling value of the x axis
142 @param yScroll The global scrolling value of the y axis
143 */
144 this.update = function (/**Number*/ dt, /**CanvasRenderingContext2D*/context, /**Number*/ xScroll, /**Number*/ yScroll)
145 {
146 if (this.left)
147 this.x -= this.speed * dt;
148 if (this.right)
149 this.x += this.speed * dt;
150
151 // XOR operation (JavaScript does not have a native XOR operator)
152 // only test for a collision if the player is moving left or right (and not trying to do both at
153 // the same time)
154 if ((this.right || this.left) && !(this.left && this.right))
155 {
156 // this will be true until the player is no longer colliding
157 var collision = false;
158 // the player may have to be pushed back through several block stacks (especially if the
159 // frame rate is very slow)
160 do
161 {
162 // the current position of the player (test the left side if running left
163 // and the right side if running right)
164 var xPos = this.left ? this.x : this.x + this.frameWidth;
165 // the index of stack of blocks that the player is standing on/in
166 var currentBlock = this.level.currentBlock(xPos);
167 // the height of the stack of blocks that the player is standing on/in
168 var groundHeight = this.level.groundHeight(currentBlock);
169 // the height of the player (we need the height from the ground up,
170 // whereas the this.y value represents the position of the player
171 // from the "sky" down).
172 var playerHeight = context.canvas.height - (this.y + this.image.height);
173 // if the player is not higher than the stack of blocks, it must be colliding
174 if (playerHeight < groundHeight)
175 {
176 collision = true;
177 // we are moving right, so push the player left
178 if (this.right)
179 this.x = this.level.blockWidth * currentBlock - this.frameWidth - 1;
180 // we are moving left, push the player right
181 else
182 this.x = this.level.blockWidth * (currentBlock + 1);
183 }
184 else
185 {
186 collision = false;
187 }
188 } while (collision)
189 }
190
191 // keep the player bound to the level
192 if (this.x > this.level.blocks.length * this.level.blockWidth - this.frameWidth - 1)
193 this.x = this.level.blocks.length * this.level.blockWidth - this.frameWidth - 1;
194 if (this.x > context.canvas.width - this.frameWidth + xScroll - this.screenBorder)
195 g_GameObjectManager.xScroll = this.x - (context.canvas.width - this.frameWidth - this.screenBorder);
196 // modify the xScroll value to keep the player on the screen
197 if (this.x < 0)
198 this.x = 0;
199 if (this.x - this.screenBorder < xScroll)
200 g_GameObjectManager.xScroll = this.x - this.screenBorder;
201
202 // if the player is jumping or falling, move along the sine wave
203 if (!this.grounded)
204 {
205 // the last position on the sine wave
206 var lastHeight = this.jumpSinWavePos;
207 // the new position on the sine wave
208 this.jumpSinWavePos += this.jumpSinWaveSpeed * dt;
209
210 // we have fallen off the bottom of the sine wave, so continue falling
211 // at a predetermined speed
212 if (this.jumpSinWavePos >= Math.PI)
213 this.y += this.jumpHeight / this.jumpHangTime * this.fallMultiplyer * dt;
214 // otherwise move along the sine wave
215 else
216 this.y -= (Math.sin(this.jumpSinWavePos) - Math.sin(lastHeight)) * this.jumpHeight;
217 }
218
219 // now that the player has had it's y position changed we need to check for a collision
220 // with the ground below the player. we have to check both the players left and right sides
221 // for a collision with the ground
222
223 // left side
224 var currentBlock1 = this.level.currentBlock(this.x);
225 // right side
226 var currentBlock2 = this.level.currentBlock(this.x + this.frameWidth);
227 // ground height below the left side
228 var groundHeight1 = this.level.groundHeight(currentBlock1);
229 // ground height below the right side
230 var groundHeight2 = this.level.groundHeight(currentBlock2);
231 // the heighest point under the player
232 var maxGroundHeight = groundHeight1 > groundHeight2 ? groundHeight1 : groundHeight2;
233 // the players height (relaitive to the bottom of the screen)
234 var playerHeight = context.canvas.height - (this.y + this.image.height);
235
236 // we have hit the ground
237 if (maxGroundHeight >= playerHeight)
238 {
239 this.y = context.canvas.height - maxGroundHeight - this.image.height;
240 this.grounded = true;
241 this.jumpSinWavePos = 0;
242 }
243 // otherwise we are falling
244 else if (this.grounded)
245 {
246 this.grounded = false;
247 // starting falling down the sine wave (i.e. from the top)
248 this.jumpSinWavePos = this.halfPI;
249 }
250 }
251 }
252
253 Player.prototype = new AnimatedGameObject;
Top