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