Compare v04 to v05
Produced: 13/1/17 5:34:38 pm
   
Mode:  All  
Left file: /Users/peetj/github/cs-js-beg-platformer/versions/game-04.js  
Right file: /Users/peetj/github/cs-js-beg-platformer/versions/game-05.js  
  1 /* GLOBAL STATE VARIABLES START WITH A __ */
  2 var _player = null;
  3 var _viewportX = 0;
  4 var _scoreDisplay = "";
  5 var _gameStartTime = (new Date()).getTime();
  6 var _timeLeftDisplay = "";
  7 var _secondsTotal = 120;
  8  
  9 /* State */
  10 var __STATE = {};
  11 __STATE.level = 1;
  12 __STATE.gameStarted = false;
  13 __STATE.gameOver = false;
  14 __STATE.timeLeft = _secondsTotal;
  15 __STATE.currentScore = 0;
  16 __STATE.gameOverIsDisplaying = false;
  17 __STATE.numCoinsToCollect = -1;
  18  
  19 const PLAYER_SPEED = 4;
  20 const WALKER_VELOCITY = -80;
  21 const EVENT_PLAYER_DIE = "EVENT_PLAYER_DIE";
  22 const EVENT_PLAYER_HIT_WALKER = "EVENT_PLAYER_HIT_WALKER";
  23 const EVENT_PLAYER_HIT_WALL = "EVENT_PLAYER_HIT_WALL";
  24 const EVENT_GAME_OVER = "EVENT_GAME_OVER";
  25  
1 26 const SCREENWIDTH = 800;
2 27 const SCREENHEIGHT = 600;
3 28 const TILE_WIDTH = 80;
4 29 const TILE_HEIGHT = 60;
5 30 const GRAVITY_STRENGTH = 1000;
6 31 const RIGHT = 0;
7 32 const LEFT = 1;
8 33 const NONE = 2;
9 34  
10 35 var _player = null;
11 36  
12 37 var tileMap = [
13 38   [[0,1],[8,1],[0,13],[4,1],[0,8],[8,1],[0,5],[4,1],[0,7],[8,1],[0,6],[8,1],[0,2]],
14 39   [[0,8],[4,1],[0,3],[4,1],[0,6],[8,1],[0,28]],
15 40   [[0,8],[0,24],[4,1],[0,3],[4,1],[0,6],[8,1],[0,4]],
16 41   [[0,11],[4,1],[0,15],[4,1],[0,13],[4,1],[0,6]],
17 42   [[0,16],[8,1],[0,19],[8,1],[0,11]],
18 43   [[0,9],[4,1],[0,38]],
19 44   [[0,48]],
20 45   [[1,48]]
21 46 ];
22 47  
23 48 Crafty.init(800, 600, document.getElementById('gamecanvas'));
  49 setupGlobalBindings();
24 50  
25 51 var assets = {'tiles': ['img/tile-1.png', 'img/platform.png', 'img/platformx2.png']};
26   var playerSprite = { 'sprites': { 'img/playerSprite.png': { tile: 50, tileh: 77, map: { man_still: [0,0], man_left: [0, 1], man_right: [0, 2], jump_right: [6, 4] } } } };
  52 var playerSprite = { 'sprites': { 'img/playerSprite.png': { tile: 50, tileh: 77, map: { man_left: [0, 1], man_right: [0, 2], jump_right: [6, 4] } } } };
27 53  
28 54 initialiseGame();
29 55  
30 56 function initialiseGame () {
31 57   Crafty.load(assets, function(){
  58     reset();
32 59     loadBackground();
33 60     loadSprites();
34 61     generateMap();
35 62     spawnEntities();
  63     displayText();
  64     /* Load sounds */
  65     Crafty.audio.add("coin", "sounds/coin.wav");
  66     __STATE.gameStarted = true;
36 67   });
37 68 }
38 69  
39 70 function loadBackground () {
40 71   Crafty.background('#3BB9FF');
41 72   //Crafty.background('#FFFFFF url(img/bg.png) repeat-x center center');
42 73 }
43 74  
44 75 function loadSprites () {
45 76   Crafty.load(playerSprite);
46 77 }
47 78  
48 79 function spawnEntities () {
49 80   spawnPlayer();
50 81 }
51 82  
52 83 function spawnPlayer (){
53     _player = Crafty.e('Player, 2D, DOM, man_still, SpriteAnimation, Twoway, Collision, Gravity, Tween, Keyboard')
  84   _player = Crafty.e('Player, 2D, DOM, man_right, SpriteAnimation, Twoway, Collision, Gravity, Tween, Keyboard')
54 85     .attr({
55 86       x: 50,
56 87       y: 263
57 88     })
58       .reel('moveRight', 500, [[0, 2],[1, 2],[2, 2], [3, 2], [4, 2], [5, 2], [6, 2], [7, 2]])
  89     .reel('moveRight', 500, [[0, 2], [1, 2], [2, 2], [3, 2], [4, 2], [5, 2], [6, 2], [7, 2]])
59 90     .reel('moveLeft', 500, [[0, 1], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [7, 1]])
60       .reel('still', 500, [[0,0]])
61 91     .twoway(200, 510)
62 92     .gravity('FloorTile')
63 93     .gravityConst(GRAVITY_STRENGTH)
64 94     .bind('KeyDown',
65 95       function (e) {
66 96         if (Crafty.keydown['37'] && Crafty.keydown['39']) {
67 97           this.pauseAnimation();
68 98           this.resetAnimation();
69 99           this.isMoving = false;
70 100           return;
71 101         }
72 102         if (e.key === Crafty.keys.RIGHT_ARROW && !this.isJumping) {
73 103           this.animate('moveRight', -1);
74 104         }
75 105         else if (e.key === Crafty.keys.LEFT_ARROW && !this.isJumping) {
76 106           this.animate('moveLeft', -1);
77 107         }
78 108         this.isMoving = true;
79 109       }
80 110     )
81 111     .bind('KeyUp',
82 112       function (e) {
83 113         if ((this.isPlaying('moveRight') && e.key === Crafty.keys.RIGHT_ARROW) ||
84 114           (this.isPlaying('moveLeft') && e.key === Crafty.keys.LEFT_ARROW)) {
85 115           this.pauseAnimation();
86 116           this.resetAnimation();
87             this.animate('still');
88    
89 117           /* Check/Set the player's moving state */
90 118           if (e.key === Crafty.keys.RIGHT_ARROW || e.key === Crafty.keys.LEFT_ARROW) {
91 119             this.isMoving = false;
92 120             return;
93 121           }
94 122         }
95 123         /* Kickstart animation if we need to */
96 124         if (this.isDown('RIGHT_ARROW') && !this.isJumping) {
97 125           this.animate('moveRight', -1);
98 126           this.isMoving = true;
99 127         }
100 128         else if (this.isDown('LEFT_ARROW') && !this.isJumping) {
101 129           this.animate('moveLeft', -1);
102 130           this.isMoving = true;
103 131         }
104 132       }
105 133     )
  134     .bind('Moved', function (obj) {
  135       if (this.x >= (SCREENWIDTH / 2) && this.x <= 3440) {
  136         Crafty.viewport.scroll('_x', (this.x - (SCREENWIDTH / 2)) * -1);
  137         displayScore();
  138         displayTimeLeft();
  139       }
  140     })
106 141     .bind('CheckJumping', function (ground) {
107 142       this.isJumping = true;
108 143       var  canJump, doubleJump;
109 144       if(this.canJump === false && !this.inDoubleJumpMode){
110 145         /* Lets check if there is a platform above us */
111 146         var platforms = Crafty('Tile');
112 147         for(var i=0; i < platforms.length; i++){
113 148           var platform = platforms[i];
114 149           platform = Crafty(platform);
115 150           if(platform.x < this.x && platform.y < this.y && platform.x+160 > this.x){
116 151             /* We probably have a platform above us so don't allow double jump */
117 152             canJump = false;
118 153             doubleJump = false;
119 154             break;
120 155           }
121 156         }
122 157         this.canJump = canJump !== undefined ? canJump : true;
123 158         this.inDoubleJumpMode = doubleJump !== undefined ? doubleJump : true;
124 159       }
125 160       else if(this.inDoubleJumpMode){
126 161         this.canJump = false;
127 162       }
128 163       this.pauseAnimation();
129 164       this.resetAnimation();
130 165       this.sprite(this.currentDirection === RIGHT ? 6 : 2, 4);
131 166     })
132 167     .bind('LandedOnGround', function (ground) {
133 168       if (this.isJumping) {
134 169         this.isJumping = false;
135 170         this.gravityConst(GRAVITY_STRENGTH);
136 171         /* We cannot get the direction from the velocity. We'll use the current loaded sprite animation  */
137           //this.sprite(0, this.getReel().id === 'moveRight' ? 2 : 1);
138           this.animate("still");
  172         this.sprite(0, this.getReel().id === 'moveRight' ? 2 : 1);
139 173         /* We may need to enable controls here as we may have disabled them */
140 174         if(this.bounced){
141 175           this.velocity().x = 0;
142 176           this.bounced = false;
143 177         }
144 178         this.inDoubleJumpMode = false;
145 179       }
146 180       /* Will need to enable controls in some circumstances */
147 181       this.enableControl();
148 182     })
149 183     .bind('NewDirection', function (obj) {
150 184       /* 0 is neither right nor left so we don't care about it */
151 185       if (obj.x === 0) return;
152 186       this.currentDirection = obj.x === 1 ? RIGHT : LEFT;
153 187       if (this.currentDirection === RIGHT && !this.isJumping) {
154 188         if (this.isMoving) {
155 189           /* Start running again */
156 190           this.animate('moveRight', -1);
157 191         }else {
158 192           this.sprite(0, 2);
159 193         }
160 194       }
161 195       else if (this.currentDirection === LEFT && !this.isJumping) {
162 196         if (this.isMoving) {
163 197           /* Start running again */
164 198           this.animate('moveLeft', -1);
165 199         }else {
166 200           this.sprite(0, 1);
167 201         }
168 202       }
169       });
  203     })
  204     .bind('EnterFrame', function(){
  205       if(this.x <= -6) this.x = -5;
  206       if(this.x >= 3785) this.x = 3784;
  207     })
170 208  
171 209     /* Set player defaults */
172 210     _player.isJumping = false;
173 211     _player.currentDirection = RIGHT;
174 212     _player.isMoving = false;
175 213     _player.reel('moveRight');
176 214     _player.bounced = false;
177 215     _player.inDoubleJumpMode = false;
178 216 }
179 217  
180 218 function generateMap () {
181 219   const Y_OFFSET = 600 - (tileMap.length * TILE_HEIGHT);
182 220   tileMap.map(function (tileRow, rowIdx) {
183 221     var xPos = 0;
184 222     var yPos = 0;
185 223     tileRow.map(function (tile, tileIdx) {
186 224       yPos = Y_OFFSET + (rowIdx * 60);
187 225       var tileType = tile[0];
188 226       var tileNum = tile[1];
189 227       if (tileType === 0){
190 228         xPos += (tileNum * 80);
191 229       }
192 230       if (tileType === 1) {
193 231         for(var i=0; i < tileNum; i++){
194 232           Crafty.e('FloorTile, 2D, DOM, Image, Collision')
195 233             .attr({ x: xPos, y: yPos, w: TILE_WIDTH, h: TILE_HEIGHT })
196 234             .image(Crafty.assets['img/tile-' + tileType + '.png'].src);
197 235           xPos += 80;
198 236         }
199 237       }
200 238       else{
201 239         if (tileType === 4) {
202 240           Crafty.e('Platform')
203 241             .setImage('img/platform.png')
204 242             .setPlatform(xPos, yPos, 1)
205 243             .addCoins(Crafty.math.randomInt(1,2));
206 244         }
207 245         else if (tileType === 8) {
208 246           Crafty.e('Platform')
209 247             .setImage('img/platformx2.png')
210 248             .setPlatform(xPos, yPos, 2)
211 249             .addCoins(Crafty.math.randomInt(1,2));
212 250         }
213 251         xPos += 80;
214 252       }
215 253     });
216 254   });
217 255 }
  256  
  257 function displayText () {
  258   displayScore();
  259   displayTimeLeft();
  260 }
  261  
  262 function displayTimeLeft () {
  263   if(_timeLeftDisplay){
  264     _timeLeftDisplay.destroy();
  265   }
  266   _timeLeftDisplay = Crafty.e("2D, DOM, Text")
  267     .attr({ x: 720 - Crafty.viewport._x, y: 20 })
  268     .text(__STATE.timeLeft)
  269     .textColor('#FF0000')
  270     .textFont({ size: '14px', weight: 'bold', family: 'Courier New' });
  271 }
  272  
  273 function displayScore () {
  274   if(_scoreDisplay){
  275     _scoreDisplay.destroy();
  276   }
  277   _scoreDisplay = Crafty.e("2D, DOM, Text")
  278     .attr({ x: 750 - Crafty.viewport._x, y: 20 })
  279     .text(pad(__STATE.currentScore, 3))
  280     .textColor('#FF0000')
  281     .textFont({ size: '14px', weight: 'bold', family: 'Courier New' });
  282 }
  283  
  284 function displayGameOver(){
  285   if(Crafty("GameOver"))
  286     Crafty("GameOver").destroy();
  287  
  288   Crafty.e("GameOver, 2D, DOM, Text")
  289     .attr({ x: 280 - Crafty.viewport._x, y: 280, z:100, w: 250 })
  290     .text("GAME OVER").textColor('#FF0000').textFont({ size: '36px', weight: 'bold', family: 'Courier New' });
  291 }
  292  
  293 function displayLevelComplete(){
  294   if(Crafty("LevelComplete"))
  295     Crafty("LevelComplete").destroy();
  296  
  297   Crafty.e("LevelComplete, 2D, DOM, Text")
  298     .attr({ x: 270 - Crafty.viewport._x, y: 280, z:100, w: 350 })
  299     .text("LEVEL COMPLETE").textColor('#33FF33').textFont({ size: '36px', weight: 'bold', family: 'Courier New' });
  300 }
  301  
  302 function updateScore(amt){
  303   __STATE.currentScore += amt;
  304   displayScore();
  305 }
  306  
  307 function pad(num, size) {
  308     var s = num+"";
  309     while (s.length < size) s = "0" + s;
  310     return s;
  311 }
  312  
  313 function setupGlobalBindings () {
  314   Crafty.bind(EVENT_GAME_OVER, function(){
  315     _player.disableControl();
  316     pauseAndResetAnimation(_player);
  317     displayGameOver();
  318   })
  319 }
  320  
  321 function pauseAndResetAnimation (ent){
  322   ent.pauseAnimation();
  323   ent.resetAnimation();
  324 }
  325  
  326 function reinstateMovement () {
  327   _player.enableControl();
  328 }
  329  
  330 function reset () {
  331   _player = null;
  332   _viewportX = 0;
  333   _scoreDisplay = "";
  334   _gameStartTime = (new Date()).getTime();
  335   _timeLeftDisplay = "";
  336   _secondsTotal = 120;
  337  
  338   __STATE.gameStarted = false;
  339   __STATE.gameOver = false;
  340   __STATE.timeLeft = _secondsTotal;
  341   __STATE.currentScore = 0;
  342   __STATE.gameOverIsDisplaying = false;
  343   __STATE.numCoinsToCollect = -1;
  344  
  345   /* Position viewport */
  346   Crafty.viewport.scroll('_x', 0)
  347 }
  348  
  349 Crafty.bind('EnterFrame', function(){
  350   if(__STATE.gameStarted === false)
  351     return;
  352  
  353   if(Crafty.frame() % 50 === 1){
  354     __STATE.timeLeft = _secondsTotal - Math.round(((new Date()).getTime() - _gameStartTime) / 1000);
  355     displayTimeLeft();
  356   }
  357   if(__STATE.gameOver && !__STATE.gameOverIsDisplaying){
  358     /* Display Game Over */
  359     Crafty.trigger(EVENT_GAME_OVER);
  360     __STATE.gameOverIsDisplaying = true;
  361   }
  362 })