Added win condition
[ld38.git] / ld38.js
1 var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });
2 var helptext, wintext;
3 var walls;
4 var gems;
5 var shrinklevel = 0;
6
7 const WAIT_KEY = 200;
8 const WAIT_GEM = 2000;
9 const WALL_THICKNESS = 32;
10 const MAX_GEMS = 16;
11 const WIN_CONDITION = 4;
12
13 var newWorldStartX;
14 var newWorldEndX;
15 var newWorldStartY;
16 var newWorldEndY;
17
18 window.addEventListener("keydown", function(e) {
19 // Prevent default browser action for arrows and spacebar
20 if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
21 e.preventDefault();
22 }
23 }, false);
24
25 class Entity extends Phaser.Sprite {
26 constructor(x, y, sprite) {
27 super(game, x, y, sprite);
28 this.anchor.setTo(.5,.5);
29 }
30
31 enablePhysics() {
32 game.physics.arcade.enable(this);
33 this.body.bounce.y = 0.2;
34 this.body.bounce.x = 0.2;
35 this.body.collideWorldBounds = true;
36 }
37 }
38
39 class Player extends Entity {
40 constructor(x, y, sprite) {
41 super(x, y, sprite);
42 this.lastmovetime = 0;
43 }
44 }
45
46 class Gem extends Entity {
47 constructor(x, y) {
48 super(x, y, 'gem');
49 this.lastInteraction = 0;
50 this.isActivated = false;
51 }
52
53 enablePhysics() {
54 super.enablePhysics();
55 this.body.bounce.y = 0.75;
56 this.body.bounce.x = 0.75;
57 }
58
59 activate() {
60 this.isActivated = true;
61 this.loadTexture('gem_active');
62 }
63
64 deactivate() {
65 this.isActivated = false;
66 this.loadTexture('gem');
67 }
68 }
69
70 function preload () {
71
72 game.load.image('wall', 'wall.png');
73 game.load.image('player', 'player.png');
74 game.load.image('gem', 'gem.png');
75 game.load.image('gem_active', 'gem_active.png');
76
77 }
78
79 function create () {
80
81 game.world.setBounds(0, 0, 800, 600);
82 game.stage.backgroundColor = 'black';
83 game.physics.startSystem(Phaser.Physics.ARCADE);
84
85 walls = game.add.group();
86 walls.classType = Phaser.TileSprite;
87 walls.enableBody = true;
88
89 walls.add(game.add.tileSprite(0, 0, game.world.width, WALL_THICKNESS, 'wall'));
90 walls.add(game.add.tileSprite(0, game.world.height - WALL_THICKNESS, game.world.width, WALL_THICKNESS, 'wall'));
91 walls.add(game.add.tileSprite(0, 0, WALL_THICKNESS, game.world.height, 'wall'));
92 walls.add(game.add.tileSprite(game.world.width - WALL_THICKNESS, 0, WALL_THICKNESS, game.world.height, 'wall'));
93 walls.children.forEach(function(wall) { wall.body.immovable = true; });
94
95 gems = game.add.group();
96 for (var i = 0; i < MAX_GEMS; i++)
97 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)));
98 gems.children.forEach(function(gem) { gem.enablePhysics(); });
99
100 player = new Player(128, game.world.height - 128, 'player');
101 player.enablePhysics();
102 game.add.existing(player);
103 game.camera.follow(player);
104 cursors = game.input.keyboard.createCursorKeys();
105
106 keyboard_handler = keyPress_default;
107
108 newWorldStartX = WALL_THICKNESS;
109 newWorldEndX = game.world.width - WALL_THICKNESS;
110 newWorldStartY = WALL_THICKNESS;
111 newWorldEndY = game.world.height - WALL_THICKNESS;
112
113 helptext = game.add.text(10, 10, "Move with arrows, activate dimension crystals to shrink the world.", { align: 'left', fill: '#000000', fontSize: 14 });
114 helptext.font = "Ubuntu Mono";
115
116 }
117
118 function update () {
119
120 game.physics.arcade.collide(player, walls);
121 game.physics.arcade.overlap(player, gems, gem_overlap, gem_isInteractable);
122
123 var isAllActive = true;
124 gems.children.forEach(function(gem) { if (!gem.isActivated) { isAllActive = false; }});
125 if (isAllActive && (gems.length > 0)) {
126 console.log(shrinklevel);
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 }
151 };
152
153 if ((game.time.now - player.lastmovetime) > WAIT_KEY) player.body.velocity.x = player.body.velocity.y = 0;
154 if (keyboard_handler) keyboard_handler();
155
156 }
157
158 function keyPress_default() {
159
160 if (cursors.left.isDown)
161 {
162 player.body.velocity.x = -150;
163 player.angle = -90;
164 player.lastmovetime = game.time.now;
165 }
166 else if (cursors.right.isDown)
167 {
168 player.body.velocity.x = 150;
169 player.angle = 90;
170 player.lastmovetime = game.time.now;
171 }
172 if (cursors.up.isDown)
173 {
174 player.body.velocity.y = -150;
175 player.angle = 0;
176 player.lastmovetime = game.time.now;
177 }
178 else if (cursors.down.isDown)
179 {
180 player.body.velocity.y = 150;
181 player.angle = 180;
182 player.lastmovetime = game.time.now;
183 }
184
185 }
186
187 function gem_isInteractable(player, gem) {
188 return ((game.time.now - gem.lastInteraction) > WAIT_GEM) && (shrinklevel <= WIN_CONDITION);
189 }
190
191 function gem_overlap(player, gem) {
192
193 gem.lastInteraction = game.time.now;
194 gem.activate();
195
196 }
197
198 function world_shrink() {
199
200 if (player.x < (newWorldStartX + (newWorldEndX - newWorldStartX) / 2))
201 newWorldEndX -= (newWorldEndX - newWorldStartX) / 2;
202 else
203 newWorldStartX += (newWorldEndX - newWorldStartX) / 2;
204 if (player.y < (newWorldStartY + (newWorldEndY - newWorldStartY) / 2))
205 newWorldEndY -= (newWorldEndY - newWorldStartY) / 2;
206 else
207 newWorldStartY += (newWorldEndY - newWorldStartY) / 2;
208
209 // Draw a wall around the new world bounds.
210 walls.removeAll(true);
211 walls.add(game.add.tileSprite(newWorldStartX - WALL_THICKNESS, newWorldStartY - WALL_THICKNESS, newWorldEndX - newWorldStartX + WALL_THICKNESS * 2, WALL_THICKNESS, 'wall'));
212 walls.add(game.add.tileSprite(newWorldStartX - WALL_THICKNESS, newWorldEndY, newWorldEndX - newWorldStartX + WALL_THICKNESS * 2, WALL_THICKNESS, 'wall'));
213 walls.add(game.add.tileSprite(newWorldStartX - WALL_THICKNESS, newWorldStartY - WALL_THICKNESS, WALL_THICKNESS, newWorldEndY - newWorldStartY + WALL_THICKNESS * 2, 'wall'));
214 walls.add(game.add.tileSprite(newWorldEndX, newWorldStartY - WALL_THICKNESS, WALL_THICKNESS, newWorldEndY - newWorldStartY + WALL_THICKNESS * 2, 'wall'));
215 walls.children.forEach(function(wall) { wall.body.immovable = true; });
216
217 function relocateGem(gem) {
218 if (gem.x < newWorldStartX) gem.x = newWorldStartX + (newWorldStartX - gem.x);
219 else if (gem.x > newWorldEndX) gem.x = newWorldEndX + (newWorldEndX - gem.x); // Adding negative value is like substraction.
220 if (gem.y < newWorldStartY) gem.y = newWorldStartY + (newWorldStartY - gem.y);
221 else if (gem.y > newWorldEndY) gem.y = newWorldEndY + (newWorldEndY - gem.y); // Same.
222 gem.deactivate();
223 }
224 gems.children.forEach(relocateGem);
225
226 shrinklevel++;
227
228 }