9914ff4f45b116750d50c40c486b4c5cbe80f9a1
1 var game
= new Phaser
.Game(800, 600, Phaser
.AUTO
, '', { preload: function() { this.state
.add('GamePlay', GamePlay
, true); } });
5 const PLAYER_SPEED
= 200;
6 const WAIT_MENUSTEP
= 100;
9 const MENUITEM_TALK
= 0;
10 const MENUITEM_LEAVE
= 1;
11 const MENUITEM_TAKE
= 2;
13 const GUI_MENUITEM_DISTANCE
= 20;
15 window
.addEventListener("keydown", function(e
) {
16 // Prevent default browser action for arrows and spacebar
17 if([32, 37, 38, 39, 40].indexOf(e
.keyCode
) > -1) {
22 function hasTimePassed(time
, delay
) {
23 return (game
.time
.now
- time
) > delay
;
27 // dialogue is array of {actor, text} records.
28 constructor(dialogue
) {
29 this.dialogue
= dialogue
;
34 return this.dialogue
[this.state
];
42 class Door
extends Phaser
.TileSprite
{
43 constructor(x
, y
, name
, rotation
, vector
, longpanel
) {
44 super(game
, x
, y
, 64, 64, 'objects');
46 this.longpanel
= longpanel
;
48 this.anchor
= new Phaser
.Point(0.5, 0.5);
49 this.tilePosition
= new Phaser
.Point(-64, -64);
50 this.openvector
= Phaser
.Point
.multiply(vector
, new Phaser
.Point(56, 56));
54 this.anchor
= new Phaser
.Point(0.75, 0.5);
55 this.tilePosition
= new Phaser
.Point(0, -64);
56 this.openvector
= Phaser
.Point
.multiply(vector
, new Phaser
.Point(116, 116));
58 if (rotation
=== undefined) rotation
= 0;
59 this.rotation
= rotation
* (Math
.PI
/ 180);
60 this.closetween
= game
.add
.tween(this).to({ x
: this.position
.x
, y
: this.position
.y
}, 1000, Phaser
.Easing
.Sinusoidal
.InOut
, false, 0, 0, false);
61 this.openposition
= Phaser
.Point
.add(this.position
, this.openvector
);
62 this.opentween
= game
.add
.tween(this).to({ x
: this.openposition
.x
, y
: this.openposition
.y
}, 1000, Phaser
.Easing
.Sinusoidal
.InOut
, false, 0, 0, false);
64 game
.physics
.arcade
.enable(this);
65 this.body
.immovable
= true;
66 this.setBody(rotation
);
73 this.body
.setSize(this.width
, 10, this.longpanel
* (rotation
/ 180) * 64, 27);
77 this.body
.setSize(10, this.width
, 27 + (this.longpanel
* 64), this.longpanel
* ((rotation
- 270) / 180) * 64);
80 console
.log("Unable to set body due to unknown rotation:", rotation
);
86 this.opentween
.start();
93 this.closetween
.start();
99 game
.debug
.body(this);
103 class Player
extends Phaser
.Sprite
{
105 super(game
, x
, y
, 'player');
106 this.y
-= this.height
;
107 this.shortname
= "John";
108 this.fullname
= "John Evals";
109 this.offerInteraction(null);
114 game
.physics
.arcade
.enable(this);
115 this.body
.bounce
.y
= 0.2;
116 this.body
.bounce
.x
= 0.2;
117 this.body
.collideWorldBounds
= true;
121 if ((this.alive
) && (!this.freezed
))
123 if (cursors
.left
.isDown
)
125 this.body
.velocity
.x
= -PLAYER_SPEED
;
127 else if (cursors
.right
.isDown
)
129 this.body
.velocity
.x
= PLAYER_SPEED
;
131 if (cursors
.up
.isDown
)
133 this.body
.velocity
.y
= -PLAYER_SPEED
;
135 else if (cursors
.down
.isDown
)
137 this.body
.velocity
.y
= PLAYER_SPEED
;
143 this.body
.velocity
.x
= this.body
.velocity
.y
= 0;
152 this.freezed
= false;
155 offerInteraction(npc
) {
156 this.interactablenpc
= npc
;
160 this.loadTexture(npc
.key
);
163 logic
.gameinterface
.dropNoticeTimeout(Phaser
.Timer
.SECOND
* 5, "You are now identified as " + npc
.fullname
+ "!");
167 class GameNPC
extends Phaser
.Sprite
{
168 constructor(x
, y
, key
, shortname
, fullname
, interaction_distance
) {
169 super(game
, x
, y
, key
);
170 this.y
-= this.height
;
171 this.shortname
= shortname
;
172 this.fullname
= fullname
;
173 this.interaction_distance
= interaction_distance
;
174 this.interactable
= false;
182 this.happy
= false; // Dead people are not happy.
187 if ((!this.interactable
) && (game
.physics
.arcade
.distanceBetween(this, logic
.player
) < this.interaction_distance
)) {
188 logic
.gameinterface
.dropNotice("(ENTER) Interact with " + this.shortname
+ "!");
189 logic
.player
.offerInteraction(this);
190 this.interactable
= true;
192 else if ((this.interactable
) && (game
.physics
.arcade
.distanceBetween(this, logic
.player
) > this.interaction_distance
)) {
193 logic
.gameinterface
.clearNotice();
194 logic
.player
.offerInteraction(null);
195 this.interactable
= false;
197 if ((this.teleport_instructions
) && (game
.physics
.arcade
.distanceBetween(this, logic
.player
) > (game
.width
+ 200))) {
198 this.position
= this.teleport_instructions
.newPosition
;
199 this.teleport_instructions
.callback(this.teleport_instructions
.callbackValue
);
200 this.teleport_instructions
= null;
212 logic
.player
.offerInteraction(null);
213 logic
.player
.takeMe(this);
223 console
.log(this.shortname
, "is happy!");
226 offscreenTeleportation(newPosition
, callback
, callbackValue
) {
227 this.teleport_instructions
= { newPosition
: newPosition
, callback
: callback
, callbackValue
: callbackValue
};
228 console
.log("Offscreen teleport request registered:", this.teleport_instructions
);
232 class NPC_Clara
extends GameNPC
{
234 switch (this.talkcount
) {
236 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "What a morning..." },
237 { actor
: logic
.player
, text
: "Hi Clara! What happened?" },
238 { actor
: this, text
: "No one cares to tell. I just know that I have to log on people manually, as the access control system doesn't work properly." },
239 { actor
: logic
.player
, text
: "Hmm... I'll look into it. Maybe it's just that everyone is fired." },
240 { actor
: this, text
: "Haha! Wouldn't joke about this, though, due to the recent layoffs." },
241 { actor
: logic
.player
, text
: "Well, maybe if we dare to joke about it, it won't happen to us..." },
242 { actor
: this, text
: "Wish it worked like that... Is it some superstition like the belief that having an umbrella with you prevents rain?" },
243 { actor
: logic
.player
, text
: "Nah, that actually works; it's not a superstition, but Murphy's Law!" },
244 { actor
: this, text
: "If you say so..." },
245 { actor
: this, text
: "Anyway, I logged you in and opened the door for you." } ] ));
246 logic
.openDoor("cutedoor");
249 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "John, have you ever thought about losing your employee card?" },
250 { actor
: logic
.player
, text
: "Yeah, you'd just get a new one." },
251 { actor
: this, text
: "You don't understand me, John!" },
252 { actor
: this, text
: "..." },
253 { actor
: this, text
: "I mean... Losing it for real..." },
254 { actor
: this, text
: "Doesn't it feel like it's the culmination of your being?" },
255 { actor
: this, text
: "If I had no card, would I still exist?" },
256 { actor
: logic
.player
, text
: "..." },
257 { actor
: logic
.player
, text
: "You sound very philosophical today." } ] ));
262 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Would you like to hear a random fun fact?" },
263 { actor
: logic
.player
, text
: "Of course!" },
264 { actor
: this, text
: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s," },
265 { actor
: this, text
: "when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap" },
266 { actor
: this, text
: "into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem" },
267 { actor
: this, text
: "Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." },
268 { actor
: logic
.player
, text
: "That's very interesting, I didn't know that!" },
269 { actor
: logic
.player
, text
: "Thanks for sharing, Clara!" } ] ));
272 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Would you like to hear a random fun fact?" },
273 { actor
: logic
.player
, text
: "Of course!..." },
274 { actor
: logic
.player
, text
: "But first..." },
275 { actor
: this, text
: "What is it?" },
276 { actor
: logic
.player
, text
: "..." },
277 { actor
: logic
.player
, text
: "Never mind, go on with what you wanted to say." },
278 { actor
: this, text
: "Lorem Ipsum is simply dummy text of the printing and typesetting industry..." },
279 { actor
: logic
.player
, text
: "I knew that already..." },
280 { actor
: logic
.player
, text
: "But..." },
281 { actor
: logic
.player
, text
: "Would you go out on a date with me?" },
282 { actor
: this, text
: "..." },
283 { actor
: this, text
: "No." } ] ));
284 // FIXME: Clara should have another happy condition.
288 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "..." } ] ));
294 logic
.gameinterface
.dropNotice(this.shortname
+ ": Have a great day, John!");
298 logic
.openDoor("cutedoor");
299 return super.actionTake();
303 return (this.talkcount
< 6);
307 class NPC_Carlos
extends GameNPC
{
309 if (logic
.clara
.alive
) {
310 switch (this.talkcount
) {
312 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "Good morning, Carlos! What's up?" },
313 { actor
: this, text
: "Hey, John! Not too much, I'm just trying to sell some shit to this new client." },
314 { actor
: logic
.player
, text
: "And so? Is it hard to convince them?" },
315 { actor
: this, text
: "Of course, they don't want to buy. It's shit." },
316 { actor
: this, text
: "I mean, who would want to buy shit?" },
317 { actor
: logic
.player
, text
: "Yeah. Relatable... But why are you trying to sell shit? I mean, why not one of our cutting edge technologies?" },
318 { actor
: this, text
: "They couldn't afford it." },
319 { actor
: logic
.player
, text
: "Then why are you trying to sell them... anything at all? They'd better off with a cheaper company." },
320 { actor
: this, text
: "Company policies. Plus the management instructed me to sell to them, no matter what." },
321 { actor
: logic
.player
, text
: "That sucks... Well... good luck!" },
322 { actor
: this, text
: "Thanks..." } ] ));
323 logic
.closeDoor("cutedoor");
324 logic
.openDoor("carlosdoor");
327 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "*Sigh.* I'll probably not work here for long, if I can't sell this shit to the customer." },
328 { actor
: this, text
: "These layoffs are terrifying. They let go of anyone for even the slightest mistake." },
329 { actor
: logic
.player
, text
: "But it's not a mistake when our client doesn't buy something they don't need." },
330 { actor
: this, text
: "Tell this to my boss..." } ] ));
333 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "You know, generally, I think it sucks being a child. One thing I miss though, if you're a child, you're allowed to be silly." },
334 { actor
: this, text
: "..." },
335 { actor
: this, text
: "For example, when my Dad told me that semen is the seed of animals, I theoretized, if I'd bury some pig semen in the garden, a pig would grow out of it..." },
336 { actor
: this, text
: "I was totally fascinated by the thought, because I really wanted to have a pet pig, but Dad wouldn't let me have one." },
337 { actor
: this, text
: "So I thought I could grow my own pig in the garden from pig seeds!" },
338 { actor
: logic
.player
, text
: "Interesting. Where are you going with this?" },
339 { actor
: this, text
: "I don't know... sometimes I feel like I'd rather sell pig semen to our clients, heh!" },
340 { actor
: this, text
: "Uhm..." },
341 { actor
: this, text
: "Totally don't tell this to Saiki!" } ] ));
342 this.pigsemen
= true;
345 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Weren't you heading to the IT department to the right?" },
346 { actor
: this, text
: "You know... the green department which looks way better than blue!" },
347 { actor
: this, text
: "..." },
348 { actor
: this, text
: "Damn, why do I have to work in blue? I just feel... so blue about it." } ] ));
351 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Weren't you heading to the conveniently green department to the right? I guess Saiki is waiting for you." },
352 { actor
: this, text
: "You're so lucky that you can work with her every day!" } ] ));
355 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Guess you'll stay here then. It's cool, you're great company anyway." } ] ));
359 switch (this.talkcount
) {
361 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "Good morning, Carlos!" },
362 { actor
: this, text
: "Whoa, Clara! You have changed so much! I barely recognize you. What's up?" },
363 { actor
: logic
.player
, text
: "I need to talk to Saiki at the IT department, but... my card doesn't allow me to enter there." },
364 { actor
: this, text
: "Well... I can certainly help you with that..." },
365 { actor
: this, text
: "..." } ] ));
368 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "Carlos. You promised to help me." },
369 { actor
: this, text
: "Uhm... It's just... Please give me 5 mins to finish this e-mail." },
370 { actor
: logic
.player
, text
: "I don't have much time, Carlos." },
371 { actor
: this, text
: "See, it's just 5 mins, please be patient. I have a chocolate bar in the fridge. I give it to you. Feel free to have it meanwhile." },
372 { actor
: logic
.player
, text
: "..." } ] ));
375 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "Time is up, Carlos!" },
376 { actor
: this, text
: "Please give me just another min." },
377 { actor
: logic
.player
, text
: "Fine. Please just give me your card and I'll help myself!" },
378 { actor
: this, text
: "But... you know that company policies forbid that, Clara! Please just be a little more patient!" },
379 { actor
: logic
.player
, text
: "You will give me your card now or you will regret!" },
380 { actor
: this, text
: "...?" },
381 { actor
: this, text
: "You're not gonna treat me like this. Forget it!" },
382 { actor
: logic
.player
, text
: "You'll not work here tomorrow." } ] ));
385 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "..." } ] ));
392 if (logic
.clara
.alive
) {
393 logic
.gameinterface
.dropNotice(this.shortname
+ ": Bye, John! Pass on my greetings to Saiki!");
398 logic
.closeDoor("cutedoor");
399 logic
.openDoor("carlosdoor");
400 return super.actionTake();
404 return (logic
.clara
.alive
) || (this.talkcount
< 3);
408 class NPC_Saiki
extends GameNPC
{
410 if (logic
.carlos
.alive
) {
411 switch (this.talkcount
) {
413 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "Hi Saiki!" },
414 { actor
: this, text
: "Hi John! Glad you arrived, here's some work for you!" },
415 { actor
: logic
.player
, text
: "Awesome! What is it?" },
416 { actor
: this, text
: "Haha, joking! Actually, our queue is suspiciously empty for today." },
417 { actor
: logic
.player
, text
: "Yeah... That's really suspicious!" },
418 { actor
: logic
.player
, text
: "Maybe I can get home today in time?" },
419 { actor
: this, text
: "You mean, you wouldn't spend the mandatory free extra working hours?" },
420 { actor
: this, text
: "You steal from the company! The company needs your unpaid hours of work! Otherwise, how would we finance the trash can I ordered for the department?" },
421 { actor
: this, text
: "*Whispers with wink.* I hope you get my sarcasm." },
422 { actor
: logic
.player
, text
: "Haha! I always get it, Saiki!" } ] ));
423 logic
.closeDoor("carlosdoor");
424 logic
.openDoor("saikidoor");
425 logic
.openDoor("peterdoor");
428 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Now that I think about it, there's still one thing. You could look into why the access control system is acting so funny today." },
429 { actor
: this, text
: "Clara has to enter people manually." },
430 { actor
: logic
.player
, text
: "Yeah, I'll definitely check that." } ] ));
433 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "So... what's up with the trash can?" },
434 { actor
: this, text
: "I'm always up for such deep conversation" },
435 { actor
: this, text
: "about trash cans." },
436 { actor
: this, text
: "While we only have one trash can, other departments seem to be abundant of them. And ours is always filled. So I requested an additional trash can." },
437 { actor
: this, text
: "Now the ticket is in PENDING status. The latest work note is from two months ago, telling there is no budget at the moment." },
438 { actor
: logic
.player
, text
: "Hmm... Maybe it's too much to ask. Can we take one from another department?" },
439 { actor
: this, text
: "No, everyone holds on to their trash cans." },
440 { actor
: logic
.player
, text
: "You certainly did your research." },
441 { actor
: this, text
: "Of course. It's an important subject." } ] ));
444 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "My parents named me after a Japanese rock singer." },
445 { actor
: logic
.player
, text
: "Cool! Which band?" },
446 { actor
: this, text
: "I don't remember the band name. But the particular singer has a blue rose in her hair most of the time." } ] ));
449 if ((logic
.carlos
.pigsemen
) && (this.talkcount
== 4)) {
450 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "Did you know that Carlos thought he can grow a pig by burying pig semen in the ground? What do you think about this?" },
451 { actor
: this, text
: "Hmm..." },
452 { actor
: this, text
: "I guess it didn't work." },
453 { actor
: this, text
: "So do you want to know what I think about this?" },
454 { actor
: this, text
: "..." },
455 { actor
: this, text
: "IT'S BRILLIANT!!!" },
456 { actor
: this, text
: "You know, it really sparkled my artistic vision! Now I must draw a pig with its legs rooted into the ground!" },
457 { actor
: logic
.player
, text
: "That's gross. Poor pig." },
458 { actor
: this, text
: "Indeed. But this is the point. He's stuck in one place, cannot move. Like you in life. So you feel sympathy for him." },
459 { actor
: logic
.player
, text
: "You have a point." },
460 { actor
: this, text
: "I think I'll catch Carlos and talk to him. I always liked that guy but I didn't know he's such imaginative." } ] ));
461 this.offscreenTeleportation(new Phaser
.Point(logic
.carlos
.x
, logic
.carlos
.y
+ 64), this.tpDone
, this);
464 if (Phaser
.Math
.random() < 0.5) {
465 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "I've found an orchestrated rendition of „Potential for Anything”. You'll have to check it out, it's breathtaking!" } ] ));
468 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "I don't like that our department is green. The blue one, where Carlos works, looks much better." } ] ));
474 switch (this.talkcount
) {
476 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "I love you, Saiki!" },
477 { actor
: this, text
: "Hi Carlos..." },
478 { actor
: logic
.player
, text
: "I'm infatuated by the mere thought of you." },
479 { actor
: this, text
: "Well... it sounds pretty much creepy." },
480 { actor
: logic
.player
, text
: "Will you go out on a date with me?" },
481 { actor
: this, text
: "..." },
482 { actor
: this, text
: "Sorry to hurt your feelings, but... even though I like you... Your sudden, unprecedented confession makes me scared." },
483 { actor
: this, text
: "Especially with that facial expression." },
484 { actor
: this, text
: "I mean... you're not even joking." },
485 { actor
: this, text
: "So sorry... I won't date you." } ] ));
488 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "I thought I could impress you." },
489 { actor
: this, text
: "I'm sorry." } ] ));
492 logic
.gameinterface
.talk(new Dialogue( [ { actor
: logic
.player
, text
: "You will give me your card." },
493 { actor
: this, text
: "Geez, what for? Go back to your department and work!" },
494 { actor
: logic
.player
, text
: "I need it." },
495 { actor
: this, text
: "..." } ] ));
498 logic
.gameinterface
.talk(new Dialogue( [ { actor
: this, text
: "Don't you have anything better to do, Carlos?" } ] ));
505 if (logic
.carlos
.alive
) {
506 logic
.gameinterface
.dropNotice(this.shortname
+ ": It was nice talking to you!");
511 logic
.closeDoor("carlosdoor");
512 logic
.openDoor("saikidoor");
513 logic
.openDoor("peterdoor");
515 return super.actionTake();
519 return (logic
.carlos
.alive
);
523 console
.log("Woot-woot! Teleport complete:", value
);
525 logic
.carlos
.makeHappy();
526 // FIXME: Need to find a prettier way than this.
527 logic
.carlos
.update = function() { }; // Disable Carlos' interaction. (Saiki will talk for him.)
531 class NPC_Peter
extends GameNPC
{
533 logic
.closeDoor("saikidoor");
534 logic
.openDoor("peterdoor");
535 logic
.openDoor("biancadoor");
536 return super.actionTake();
540 class NPC_Bianca
extends GameNPC
{
542 // All doors open for you if you have all the cards.
543 logic
.openDoor("cutedoor");
544 logic
.openDoor("carlosdoor");
545 logic
.openDoor("saikidoor");
546 return super.actionTake();
551 class GameInterface
extends Phaser
.Group
{
552 constructor(game
, parent
) {
553 super(game
, parent
, 'GUI', false, false, 0);
554 this.back_notice
= new Phaser
.Graphics(game
, 0, game
.height
- 50);
555 this.back_notice
.beginFill(0x000000);
556 this.back_notice
.drawRect(0, 0, game
.width
, 30);
557 this.back_notice
.endFill();
558 this.add(this.back_notice
);
559 this.text_notice
= new Phaser
.Text(game
, 0, this.back_notice
.y
, null, { align
: 'left', fill
: 'white', font
: 'Ubuntu Mono', fontSize
: 18, fontWeight
: 'bold' });
560 this.text_notice
.anchor
.setTo(-0.5, -0.2);
561 this.add(this.text_notice
);
564 this.back_menu
= new Phaser
.Graphics(game
, 150, (game
.height
/ 2) + 40);
565 this.back_menu
.beginFill(0x000000);
566 this.back_menu
.drawRect(0, 0, 155, 105);
567 this.back_menu
.endFill();
568 this.back_menu
.lineStyle(3, Phaser
.Color
.YELLOW
, 1);
569 this.back_menu
.moveTo(10, 35);
570 this.back_menu
.lineTo(this.back_menu
.width
- 10, 35);
571 this.add(this.back_menu
);
572 var style
= { align
: 'left', fill
: 'yellow', font
: 'Ubuntu Mono', fontSize
: 22, fontWeight
: 'bold' };
573 this.text_menutitle
= new Phaser
.Text(game
, this.back_menu
.x
, this.back_menu
.y
, null, style
);
574 this.text_menutitle
.anchor
.setTo(-0.2, -0.2);
575 style
= { align
: 'left', fill
: 'white', font
: 'Ubuntu Mono', fontSize
: 18, fontWeight
: 'bold' };
576 this.text_menuitem_Talk
= new Phaser
.Text(game
, this.back_menu
.x
+ 35, this.back_menu
.y
+ 40, "Talk", style
);
577 this.text_menuitem_Leave
= new Phaser
.Text(game
, this.back_menu
.x
+ 35, this.text_menuitem_Talk
.y
+ GUI_MENUITEM_DISTANCE
, "Leave", style
);
578 this.text_menuitem_Take
= new Phaser
.Text(game
, this.back_menu
.x
+ 35, this.text_menuitem_Leave
.y
+ GUI_MENUITEM_DISTANCE
, "Take ID", style
);
579 style
.fill
= 'yellow';
580 this.text_menucursor
= new Phaser
.Text(game
, this.back_menu
.x
+ 15, this.text_menuitem_Talk
.y
, "→", style
);
581 this.add(this.text_menutitle
);
582 this.add(this.text_menuitem_Talk
);
583 this.add(this.text_menuitem_Leave
);
584 this.add(this.text_menuitem_Take
);
585 this.add(this.text_menucursor
);
587 this.last_menustep
= 0;
589 this.back_talk
= new Phaser
.Graphics(game
, 100, game
.height
- 120);
590 this.back_talk
.beginFill(0x000000);
591 this.back_talk
.drawRect(0, 0, game
.width
- 200, 105);
592 this.back_talk
.endFill();
593 this.back_talk
.lineStyle(3, Phaser
.Color
.YELLOW
, 1);
594 this.back_talk
.moveTo(10, 35);
595 this.back_talk
.lineTo(this.back_talk
.width
- 10, 35);
596 this.add(this.back_talk
);
597 style
= { align
: 'left', fill
: 'yellow', font
: 'Ubuntu Mono', fontSize
: 22, fontWeight
: 'bold' };
598 this.text_talktitle
= new Phaser
.Text(game
, this.back_talk
.x
+ 15, this.back_talk
.y
+ 6, null, style
);
599 //this.text_talktitle.anchor.setTo(-0.2, -0.2);
600 this.add(this.text_talktitle
);
601 this.strikethrough_talktitle
= new Phaser
.Graphics(game
, this.back_talk
.x
, this.back_talk
.y
);
602 this.strikethrough_talktitle
.lineStyle(3, Phaser
.Color
.RED
, 1);
603 this.strikethrough_talktitle
.moveTo(12, 20);
604 this.strikethrough_talktitle
.lineTo(67, 20);
605 this.add(this.strikethrough_talktitle
);
606 style
= { align
: 'left', fill
: 'white', font
: 'Ubuntu Mono', fontSize
: 18, fontWeight
: 'bold' };
607 this.text_talk
= new Phaser
.Text(game
, this.back_talk
.x
+ 35, this.back_talk
.y
+ 40, null, style
);
608 this.text_talk
.wordWrap
= true;
609 this.text_talk
.wordWrapWidth
= this.back_talk
.width
- 70;
610 this.text_talk
.lineSpacing
= -5;
611 this.add(this.text_talk
);
617 this.text_notice
.text
= text
;
618 this.back_notice
.visible
= true;
619 this.text_notice
.visible
= true;
622 dropNoticeTimeout(timeout
, text
) {
623 this.dropNotice(text
);
624 game
.time
.events
.add(timeout
, this.clearNotice
, this);
628 this.back_notice
.visible
= false;
629 this.text_notice
.visible
= false;
636 this.text_menutitle
.text
= npc
.shortname
;
637 this.back_menu
.visible
= true;
638 this.text_menutitle
.visible
= true;
639 this.text_menuitem_Talk
.visible
= true;
640 this.text_menuitem_Leave
.visible
= true;
641 this.text_menuitem_Take
.visible
= true;
642 this.currentmenuitem
= MENUITEM_TALK
;
643 this.actualizeCursorPosition();
644 this.text_menucursor
.visible
= true;
645 this.last_menustep
= game
.time
.now
;
650 this.back_menu
.visible
= false;
651 this.text_menutitle
.visible
= false;
652 this.text_menuitem_Talk
.visible
= false;
653 this.text_menuitem_Leave
.visible
= false;
654 this.text_menuitem_Take
.visible
= false;
655 this.text_menucursor
.visible
= false;
661 this.dialogue
= dialogue
;
663 this.back_talk
.visible
= true;
664 this.text_talktitle
.visible
= true;
665 this.text_talk
.visible
= true;
670 this.dialogue
= null;
671 this.back_talk
.visible
= false;
672 this.text_talktitle
.visible
= false;
673 this.strikethrough_talktitle
.visible
= false;
674 this.text_talk
.visible
= false;
678 console
.log(this.dialogue
);
679 console
.log(this.dialogue
.actual());
680 var actualdialogue
= this.dialogue
.actual();
681 if (actualdialogue
) {
682 if (actualdialogue
.actor
.disguise
) {
683 this.text_talktitle
.text
= actualdialogue
.actor
.shortname
+ " " + actualdialogue
.actor
.disguise
.shortname
;
684 this.strikethrough_talktitle
.visible
= true;
687 this.text_talktitle
.text
= actualdialogue
.actor
.shortname
;
688 this.strikethrough_talktitle
.visible
= false;
690 this.text_talk
.text
= actualdialogue
.text
;
691 this.dialogue
.advance();
697 this.last_talk
= game
.time
.now
;
700 actualizeCursorPosition() {
701 this.text_menucursor
.y
= this.text_menuitem_Talk
.y
+ (this.currentmenuitem
* GUI_MENUITEM_DISTANCE
);
705 if ((this.inMenu
) && (hasTimePassed(this.last_menustep
, WAIT_MENUSTEP
))) {
706 if (cursors
.up
.isDown
)
708 this.currentmenuitem
--;
709 if (this.currentmenuitem
< MENUITEM_TALK
) this.currentmenuitem
= MENUITEM_TAKE
;
710 this.actualizeCursorPosition();
712 else if (cursors
.down
.isDown
)
714 this.currentmenuitem
++;
715 if (this.currentmenuitem
> MENUITEM_TAKE
) this.currentmenuitem
= MENUITEM_TALK
;
716 this.actualizeCursorPosition();
718 if (game
.input
.keyboard
.isDown(Phaser
.Keyboard
.ENTER
)) {
719 logic
.callMenu(this.currentmenuitem
);
721 this.last_menustep
= game
.time
.now
;
723 if ((this.inTalk
) && (game
.input
.keyboard
.isDown(Phaser
.Keyboard
.ENTER
)) && (hasTimePassed(this.last_talk
, WAIT_TALK
))) {
732 this.player
= this.clara
= this.carlos
= this.saiki
= this.peter
= this.bianca
= null;
733 this.gameinterface
= new GameInterface(game
, game
.stage
);
734 //this.doors = game.add.group(game.world, "doors");
735 this.last_menuselect
= 0;
738 createObject(object
) {
739 switch (object
.type
) {
740 case 'spawnpoint': this.createCharacter(object
); break;
741 case 'door': this.createDoor(object
); break;
742 case '': console
.error("Object type is empty:", object
); break;
743 default: console
.error("Unknown object type:", object
);
747 createCharacter(object
) {
749 switch (object
.name
) {
751 newChar
= new Player(object
.x
, object
.y
, 'player');
752 this.player
= newChar
;
753 this.player
.enablePhysics();
754 game
.camera
.follow(this.player
);
757 newChar
= new NPC_Clara(object
.x
, object
.y
, 'clara', "Clara", "Clara Tnavelerri", 200);
758 this.clara
= newChar
;
761 newChar
= new NPC_Carlos(object
.x
, object
.y
, 'carlos', "Carlos", "Carlos Elbacalper", 150);
762 this.carlos
= newChar
;
765 newChar
= new NPC_Saiki(object
.x
, object
.y
, 'saiki', "Saiki", "Saiki Ytpme", 150);
766 this.saiki
= newChar
;
769 newChar
= new NPC_Peter(object
.x
, object
.y
, 'peter', "Peter", "Peter Tluaf", 225);
770 this.peter
= newChar
;
773 newChar
= new NPC_Bianca(object
.x
, object
.y
, 'bianca', "Bianca", "Bianca Gnihton", 150);
774 this.bianca
= newChar
;
777 console
.error("Unknown character:", object
);
779 newChar
.name
= object
.name
;
780 game
.add
.existing(newChar
);
781 console
.log(newChar
);
785 /* Calculate movement vector and correct position (32 = half tile width/height). */
787 switch (object.rotation) {
789 case 0: vector = new Phaser.Point( -1, 0); object.x += 32; object.y -= 32; break;
790 case 90: vector = new Phaser.Point( 0, -1); object.x += 32; object.y += 32; break;
791 case 180: vector = new Phaser.Point( 1, 0); object.x -= 32; object.y += 32; break;
792 case 270: vector = new Phaser.Point( 0, 1); object.x -= 32; object.y -= 32; break;
793 default: console.error("Invalid rotation:", object.rotation);
795 this.doors.add(new Door(object.x, object.y, object.name, object.rotation, vector, object.properties.longpanel));
799 console.log("Menu callback received:", menuitem);
800 this.last_menuselect = game.time.now;
801 this.gameinterface.leaveMenu();
804 this.player.interactablenpc.actionTalk();
807 this.player.interactablenpc.actionLeave();
808 this.player.unfreeze();
811 if (this.player.interactablenpc.actionTake())
812 this.player.unfreeze();
818 if (this.player.interactablenpc) {
819 if (this.player.interactablenpc.endTalk()) {
820 this.gameinterface.npcMenu(this.player.interactablenpc);
823 this.player.unfreeze();
824 this.last_menuselect = game.time.now;
830 this.doors.children.forEach(function(o) { if (o.name == doorname) o.open(); });
833 closeDoor(doorname) {
834 this.doors.children.forEach(function(o) { if (o.name == doorname) o.close(); });
838 return (this.clara.happy) && (this.carlos.happy) && (this.saiki.happy);
842 if ((game.input.keyboard.isDown(Phaser.Keyboard.ENTER)) && (hasTimePassed(this.last_menuselect, WAIT_MENUSTEP))) {
843 if ((this.player.interactablenpc) && (this.player.interactablenpc.interactable) && (!this.gameinterface.inMenu) && (!this.gameinterface.inTalk)) {
844 console.log("Starting interaction with", this.player.interactablenpc.fullname);
845 this.player.freeze();
846 this.gameinterface.npcMenu(this.player.interactablenpc);
853 class GamePlay extends Phaser.State {
858 logic = new GameLogic();
859 game.world.updateOnlyExistingChildren = true;
860 game.state.add('GameOver', GameOver, false);
866 game.load.image('player', 'john.png');
867 game.load.image('clara', 'clara.png');
868 game.load.image('carlos', 'carlos.png');
869 game.load.image('saiki', 'saiki.png');
870 game.load.image('peter', 'peter.png');
871 game.load.image('bianca', 'bianca.png');
872 game.load.image('tileset', 'tileset.png');
873 game.load.image('objects', 'objects.png');
874 game.load.tilemap('gamemap', 'tilemap.json', null, Phaser.Tilemap.TILED_JSON);
880 game.world.setBounds(0, 0, 800, 600);
881 game.stage.backgroundColor = '#000000';
882 game.physics.startSystem(Phaser.Physics.ARCADE);
883 console.log("Debug enabled:", !game.debug.isDisabled);
885 var map = game.add.tilemap('gamemap');
886 map.addTilesetImage('tileset', 'tileset');
887 map.addTilesetImage('objects', 'objects');
888 var layer_floor = map.createLayer('floor');
889 layer_floor.resizeWorld();
890 this.layer_walls = map.createLayer('walls');
891 map.setCollisionBetween(1, 100, true, this.layer_walls);
892 this.layer_furniture = map.createLayer('furniture');
893 map.setCollisionBetween(1, 100, true, this.layer_furniture);
895 // FIXME: Don't create a group here like this, it's too ugly! Now I have it here due to the display order.
896 logic.doors = game.add.group(game.world, "doors");
898 map.objects['objects'].forEach(function(o) { logic.createObject(o); });
899 console.log(map.objects);
901 cursors = game.input.keyboard.createCursorKeys();
908 game.physics.arcade.collide(logic.player, this.layer_walls);
909 game.physics.arcade.collide(logic.player, this.layer_furniture);
910 game.physics.arcade.collide(logic.player, logic.doors);
916 class GameOver extends Phaser.State {
920 console.log("Entered GameOver state.");
921 game.stage.removeChildren(1);
922 game.camera.follow(logic.player);
923 logic.player.freeze();
925 var g = game.add.group(game.stage, "GAMEOVER");
926 this.back_gameover = new Phaser.Graphics(game, 100, game.height / 2 - 200);
927 this.back_gameover.beginFill(0x000000);
928 this.back_gameover.drawRect(0, 0, game.width - 200, 400);
929 this.back_gameover.endFill();
930 this.back_gameover.lineStyle(3, Phaser.Color.YELLOW, 1);
931 this.back_gameover.moveTo(10, 35);
932 this.back_gameover.lineTo(this.back_gameover.width - 10, 35);
933 g.add(this.back_gameover);
934 var style = { align: 'left', fill: 'yellow', font: 'Ubuntu Mono', fontSize: 22, fontWeight: 'bold' };
935 this.text_title = new Phaser.Text(game, this.back_gameover.x + 15, this.back_gameover.y + 6, "ABRUPT GAME OVER", style);
936 g.add(this.text_title);
937 style = { align: 'left', fill: 'white', font: 'Ubuntu Mono', fontSize: 18, fontWeight: 'bold' };
938 this.text_gameover = new Phaser.Text(game, this.back_gameover.x + 35, this.back_gameover.y + 60, null, style);
939 this.text_gameover.wordWrap = true;
940 this.text_gameover.wordWrapWidth = this.back_gameover.width - 70;
941 this.text_gameover.lineSpacing = -5;
942 g.add(this.text_gameover);
944 this.text_gameover.text = this.assess();
949 if (logic.checkAllHappy()) {
950 return "You listened to all of your colleagues' and affected them to make their day a little better. Next day, the company fired Clara, Carlos, Saiki, and you, to comply with its productivity requirements. The company's internal code demand unconditional and illimitable loyalty from employees to maximize productivity. This includes requisites for employees not to exercise human qualities or express personal needs within and outside the corporate environment. The company has determined that neither of the mentioned people complied to these guidelines, due to the amount of socialization they pursued during the work day.\n\nIronically, the layoffs turned everyone's life for the better.";
952 else if (logic.player.disguise) {
953 this.text_gameover.style.fill = 'red';
954 return "You went on your day to accomplish your tasks without caring about anyone. Where are your colleagues now? Clara, Carlos, Saiki? You don't know. But you don't even care. You have never seen them after they served your needs.\n\nNext day, the company promoted you for your effectiveness and loyalty.";
957 return "The company is concerned that you may develop other needs (like wanting to pursue hobbies, spend time with friends and family) those compete for the time you devote for your job. The company reminds you that they demand your entire being to exclusively serve the company's interests. Socializing with your colleagues outside the dedicated team building occasions may hurt your performance. To comply with the productivity requirements, the company has terminated your employment.\n\nClara, Carlos, Saiki are still loyal employees of the company. Probably you could have done something different to find a better outcome.";