Added game icon
[ld38.git] / ld38.js
1 var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });
2 var player;
3 var helptext, wintext;
4 var walls;
5 var gems;
6 var shrinklevel = 0;
7
8 const WAIT_KEY = 200;
9 const WAIT_GEM = 2000;
10 const WALL_THICKNESS = 32;
11 const MAX_GEMS = 16;
12 const WIN_CONDITION = 4;
13
14 var newWorldStartX;
15 var newWorldEndX;
16 var newWorldStartY;
17 var newWorldEndY;
18
19 window.addEventListener("keydown", function(e) {
20 // Prevent default browser action for arrows and spacebar
21 if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
22 e.preventDefault();
23 }
24 }, false);
25
26 class Entity extends Phaser.Sprite {
27 constructor(x, y, sprite) {
28 super(game, x, y, sprite);
29 this.anchor.setTo(.5,.5);
30 }
31
32 enablePhysics() {
33 game.physics.arcade.enable(this);
34 this.body.bounce.y = 0.2;
35 this.body.bounce.x = 0.2;
36 this.body.collideWorldBounds = true;
37 }
38 }
39
40 class Player extends Entity {
41 constructor(x, y, sprite) {
42 super(x, y, sprite);
43 this.lastmovetime = 0;
44 }
45 }
46
47 class Gem extends Entity {
48 constructor(x, y) {
49 super(x, y, 'gem');
50 this.lastInteraction = 0;
51 this.isActivated = false;
52 }
53
54 enablePhysics() {
55 super.enablePhysics();
56 this.body.bounce.y = 0.75;
57 this.body.bounce.x = 0.75;
58 }
59
60 activate() {
61 this.isActivated = true;
62 this.loadTexture('gem_active');
63 }
64
65 deactivate() {
66 this.isActivated = false;
67 this.loadTexture('gem');
68 }
69 }
70
71 function preload () {
72
73 game.load.image('wall', 'wall.png');
74 game.load.image('player', 'player.png');
75 game.load.image('gem', 'gem.png');
76 game.load.image('gem_active', 'gem_active.png');
77
78 }
79
80 function create () {
81
82 game.world.setBounds(0, 0, 800, 600);
83 game.stage.backgroundColor = 'black';
84 game.physics.startSystem(Phaser.Physics.ARCADE);
85
86 walls = game.add.group();
87 walls.classType = Phaser.TileSprite;
88 walls.enableBody = true;
89
90 walls.add(game.add.tileSprite(0, 0, game.world.width, WALL_THICKNESS, 'wall'));
91 walls.add(game.add.tileSprite(0, game.world.height - WALL_THICKNESS, game.world.width, WALL_THICKNESS, 'wall'));
92 walls.add(game.add.tileSprite(0, 0, WALL_THICKNESS, game.world.height, 'wall'));
93 walls.add(game.add.tileSprite(game.world.width - WALL_THICKNESS, 0, WALL_THICKNESS, game.world.height, 'wall'));
94 walls.children.forEach(function(wall) { wall.body.immovable = true; });
95
96 gems = game.add.group();
97 for (var i = 0; i < MAX_GEMS; i++)
98 gems.add(new Gem((Math.random() * (game.world.width - (WALL_THICKNESS * 4))) + (WALL_THICKNESS * 2), (Math.random() * (game.world.height - (WALL_THICKNESS * 4))) + (WALL_THICKNESS * 2)));
99 gems.children.forEach(function(gem) { gem.enablePhysics(); });
100
101 player = new Player(128, game.world.height - 128, 'player');
102 player.enablePhysics();
103 game.add.existing(player);
104 game.camera.follow(player);
105 cursors = game.input.keyboard.createCursorKeys();
106
107 keyboard_handler = keyPress_default;
108
109 newWorldStartX = WALL_THICKNESS;
110 newWorldEndX = game.world.width - WALL_THICKNESS;
111 newWorldStartY = WALL_THICKNESS;
112 newWorldEndY = game.world.height - WALL_THICKNESS;
113
114 helptext = game.add.text(10, 10, "Move with arrows, activate dimension crystals to shrink the world.", { align: 'left', fill: '#000000', fontSize: 14 });
115 helptext.font = "Ubuntu Mono";
116
117 }
118
119 function update () {
120
121 game.physics.arcade.collide(player, walls);
122 game.physics.arcade.overlap(player, gems, gem_overlap, gem_isInteractable);
123
124 var isAllActive = true;
125 gems.children.forEach(function(gem) { if (!gem.isActivated) { isAllActive = false; }});
126 if (isAllActive && (gems.length > 0)) {
127 world_shrink();
128 helptext.kill();
129 if (shrinklevel == WIN_CONDITION) {
130 wintext = game.add.text(0, 0, "YOU WON!\nFinally you are free...", { align: 'center', fill: '#ff00ff', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
131 wintext.x = (game.world.width - wintext.width) / 2;
132 wintext.y = (game.world.height - wintext.height) / 2;
133 walls.children.forEach(function(wall) { wall.body.immovable = false; });
134 var i = 0;
135 gems.children.forEach(function(gem) {
136 switch(i % 4) {
137 case 0: gem.body.gravity.y = 100; break;
138 case 1: gem.body.gravity.x = 100; break;
139 case 2: gem.body.gravity.y = -100; break;
140 case 3: gem.body.gravity.x = -100; break;
141 }
142 i++
143 });
144 }
145 else if (shrinklevel > WIN_CONDITION) {
146 // Kill everything.
147 walls.removeAll(true);
148 gems.removeAll(true);
149 wintext.kill();
150 game.world.setBounds(0, 0, 800 * 3, 600 * 3);
151 player.x = (800 * 3) / 2;
152 player.y = (600 * 3) / 2;
153
154 var endtext;
155 endtext = game.add.text(0, 0, "What are you looking for?", { align: 'center', fill: '#ff00ff', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
156 endtext.x = (800 - endtext.width) / 2;
157 endtext.y = (600 - endtext.height) / 2;
158
159 endtext = game.add.text(0, 0, "YOU DESTROYED\nTHE WORLD!", { align: 'center', fill: '#ff0000', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
160 endtext.x = 800 + (800 - endtext.width) / 2;
161 endtext.y = (600 - endtext.height) / 2;
162
163 endtext = game.add.text(0, 0, "This is cool if you\nthink about it...", { align: 'center', fill: '#00ffff', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
164 endtext.x = (800 * 2) + (800 - endtext.width) / 2;
165 endtext.y = (600 - endtext.height) / 2;
166
167 endtext = game.add.text(0, 0, "You just needed\n\n\n\nsome space.", { align: 'center', fill: '#ff69b4', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
168 endtext.x = (800 - endtext.width) / 2;
169 endtext.y = 600 + (600 - endtext.height) / 2;
170
171 endtext = game.add.text(0, 0, "Bonanza Banzai", { align: 'center', fill: '#00ff00', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
172 endtext.x = (800 * 2) + (800 - endtext.width) / 2;
173 endtext.y = 600 + (600 - endtext.height) / 2;
174
175 endtext = game.add.text(0, 0, "But nobody came.", { align: 'center', fill: '#ff0000', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
176 endtext.x = (800 - endtext.width) / 2;
177 endtext.y = (600 * 2) + (600 - endtext.height) / 2;
178
179 endtext = game.add.text(0, 0, "What do you expect?\nPretty stars?\nOr planets?", { align: 'center', fill: '#00ffff', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
180 endtext.x = 800 + (800 - endtext.width) / 2;
181 endtext.y = (600 * 2) + (600 - endtext.height) / 2;
182
183 endtext = game.add.text(0, 0, "I think you should abandon this game.\nThere's nothing here.", { align: 'center', fill: '#ff00ff', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' });
184 endtext.x = (800 * 2) + (800 - endtext.width) / 2;
185 endtext.y = (600 * 2) + (600 - endtext.height) / 2;
186 }
187 };
188
189 if ((game.time.now - player.lastmovetime) > WAIT_KEY) player.body.velocity.x = player.body.velocity.y = 0;
190 if (keyboard_handler) keyboard_handler();
191
192 }
193
194 function keyPress_default() {
195
196 if (cursors.left.isDown)
197 {
198 player.body.velocity.x = -150;
199 player.angle = -90;
200 player.lastmovetime = game.time.now;
201 }
202 else if (cursors.right.isDown)
203 {
204 player.body.velocity.x = 150;
205 player.angle = 90;
206 player.lastmovetime = game.time.now;
207 }
208 if (cursors.up.isDown)
209 {
210 player.body.velocity.y = -150;
211 player.angle = 0;
212 player.lastmovetime = game.time.now;
213 }
214 else if (cursors.down.isDown)
215 {
216 player.body.velocity.y = 150;
217 player.angle = 180;
218 player.lastmovetime = game.time.now;
219 }
220
221 }
222
223 function gem_isInteractable(player, gem) {
224 return ((game.time.now - gem.lastInteraction) > WAIT_GEM) && (shrinklevel <= WIN_CONDITION);
225 }
226
227 function gem_overlap(player, gem) {
228
229 gem.lastInteraction = game.time.now;
230 gem.activate();
231
232 }
233
234 function world_shrink() {
235
236 if (player.x < (newWorldStartX + (newWorldEndX - newWorldStartX) / 2))
237 newWorldEndX -= (newWorldEndX - newWorldStartX) / 2;
238 else
239 newWorldStartX += (newWorldEndX - newWorldStartX) / 2;
240 if (player.y < (newWorldStartY + (newWorldEndY - newWorldStartY) / 2))
241 newWorldEndY -= (newWorldEndY - newWorldStartY) / 2;
242 else
243 newWorldStartY += (newWorldEndY - newWorldStartY) / 2;
244
245 // Draw a wall around the new world bounds.
246 walls.removeAll(true);
247 walls.add(game.add.tileSprite(newWorldStartX - WALL_THICKNESS, newWorldStartY - WALL_THICKNESS, newWorldEndX - newWorldStartX + WALL_THICKNESS * 2, WALL_THICKNESS, 'wall'));
248 walls.add(game.add.tileSprite(newWorldStartX - WALL_THICKNESS, newWorldEndY, newWorldEndX - newWorldStartX + WALL_THICKNESS * 2, WALL_THICKNESS, 'wall'));
249 walls.add(game.add.tileSprite(newWorldStartX - WALL_THICKNESS, newWorldStartY - WALL_THICKNESS, WALL_THICKNESS, newWorldEndY - newWorldStartY + WALL_THICKNESS * 2, 'wall'));
250 walls.add(game.add.tileSprite(newWorldEndX, newWorldStartY - WALL_THICKNESS, WALL_THICKNESS, newWorldEndY - newWorldStartY + WALL_THICKNESS * 2, 'wall'));
251 walls.children.forEach(function(wall) { wall.body.immovable = true; });
252
253 function relocateGem(gem) {
254 if (gem.x < newWorldStartX) gem.x = newWorldStartX + (newWorldStartX - gem.x);
255 else if (gem.x > newWorldEndX) gem.x = newWorldEndX + (newWorldEndX - gem.x); // Adding negative value is like substraction.
256 if (gem.y < newWorldStartY) gem.y = newWorldStartY + (newWorldStartY - gem.y);
257 else if (gem.y > newWorldEndY) gem.y = newWorldEndY + (newWorldEndY - gem.y); // Same.
258 gem.deactivate();
259 }
260 gems.children.forEach(relocateGem);
261
262 shrinklevel++;
263
264 }