diff --git a/src/assets/assets.ts b/src/assets/assets.ts index 289e163..4b69f7c 100644 --- a/src/assets/assets.ts +++ b/src/assets/assets.ts @@ -6,6 +6,10 @@ const images: Image[] = [ // Backgrounds image('backgrounds/background', 'background'), image('backgrounds/playarea-base', 'playArea_base'), + image('backgrounds/grid1', 'grid1'), + image('backgrounds/grid2', 'grid2'), + image('backgrounds/grid3', 'grid3'), + image('backgrounds/grid4', 'grid4'), // Characters image('characters/player', 'player'), @@ -32,9 +36,14 @@ const images: Image[] = [ image('items/checkout', 'checkout'), // UI - image('ui/hud', 'hud'), + image('ui/angyv', 'angyv'), image('ui/bubble', 'bubble'), image('ui/exclamation', 'exclamation'), + image('ui/happy', 'happy'), + image('ui/love', 'love'), + image('ui/money', 'money'), + image('ui/question', 'question'), + image('ui/sad', 'sad'), image('ui/timer', 'timer'), // Titlescreen @@ -43,7 +52,8 @@ const images: Image[] = [ image('titlescreen/foreground', 'title_foreground'), image('titlescreen/character', 'title_character'), - + //temp + image('temp/invwindow', 'invwindow'), ]; @@ -51,17 +61,37 @@ const images: Image[] = [ const spritesheets: SpriteSheet[] = [ //temp spritesheet('temp/invbutton', 'invbutton', 128, 128), + spritesheet('temp/fwbutton', 'fwbutton', 64, 262), + spritesheet('temp/rock', 'rock', 100, 100), + spritesheet('temp/coke', 'coke', 100, 100), + spritesheet('temp/brocc', 'brocc', 100, 100), + spritesheet('temp/hotdog', 'hotdog', 100, 100), + spritesheet('temp/hourglass', 'hourglass', 100, 100), + spritesheet('temp/hypnosis', 'hypnosis', 100, 100), + spritesheet('temp/milk', 'milk', 100, 100), + spritesheet('temp/pocky', 'pocky', 100, 100), + spritesheet('temp/polish', 'polish', 100, 100), + spritesheet('temp/snowglobe', 'snowglobe', 100, 100), + spritesheet('temp/usb', 'usb', 100, 100), + spritesheet('temp/pillowtalk', 'pillowtalk', 100, 100), + spritesheet('temp/shuriken', 'shuriken', 100, 100), + + spritesheet('temp/blankspr', 'blankspr', 100, 100), ]; /* Audios */ const audios: Audio[] = [ music('title', 'm_main_menu'), music('first', 'm_first'), + sound('place', 'place', 0.5), + sound('return', 'return', 0.5), + sound('scroll', 'scroll', 0.5), sound('tree/rustle', 't_rustle', 0.5), + sound('tree/meme_explosion_sound', 'meme_explosion_sound', 0.5), ]; /* Fonts */ -await loadFont('Sketch', 'Game Font'); +await loadFont('DynaPuff-Medium', 'Game Font'); export { images, diff --git a/src/assets/images/backgrounds/grid1.png b/src/assets/images/backgrounds/grid1.png new file mode 100644 index 0000000..2a7a546 Binary files /dev/null and b/src/assets/images/backgrounds/grid1.png differ diff --git a/src/assets/images/backgrounds/grid2.png b/src/assets/images/backgrounds/grid2.png new file mode 100644 index 0000000..33c807e Binary files /dev/null and b/src/assets/images/backgrounds/grid2.png differ diff --git a/src/assets/images/backgrounds/grid3.png b/src/assets/images/backgrounds/grid3.png new file mode 100644 index 0000000..e34823a Binary files /dev/null and b/src/assets/images/backgrounds/grid3.png differ diff --git a/src/assets/images/backgrounds/grid4.png b/src/assets/images/backgrounds/grid4.png new file mode 100644 index 0000000..d7b4403 Binary files /dev/null and b/src/assets/images/backgrounds/grid4.png differ diff --git a/src/assets/images/temp/anger.png b/src/assets/images/temp/anger.png new file mode 100644 index 0000000..4d0f58f Binary files /dev/null and b/src/assets/images/temp/anger.png differ diff --git a/src/assets/images/temp/blankspr.png b/src/assets/images/temp/blankspr.png new file mode 100644 index 0000000..9348f41 Binary files /dev/null and b/src/assets/images/temp/blankspr.png differ diff --git a/src/assets/images/temp/brocc.png b/src/assets/images/temp/brocc.png new file mode 100644 index 0000000..650fccd Binary files /dev/null and b/src/assets/images/temp/brocc.png differ diff --git a/src/assets/images/temp/coke.png b/src/assets/images/temp/coke.png new file mode 100644 index 0000000..c800dbd Binary files /dev/null and b/src/assets/images/temp/coke.png differ diff --git a/src/assets/images/temp/fwbutton.png b/src/assets/images/temp/fwbutton.png new file mode 100644 index 0000000..2e1f4f5 Binary files /dev/null and b/src/assets/images/temp/fwbutton.png differ diff --git a/src/assets/images/temp/hotdog.png b/src/assets/images/temp/hotdog.png new file mode 100644 index 0000000..94363c5 Binary files /dev/null and b/src/assets/images/temp/hotdog.png differ diff --git a/src/assets/images/temp/hourglass.png b/src/assets/images/temp/hourglass.png new file mode 100644 index 0000000..7b19422 Binary files /dev/null and b/src/assets/images/temp/hourglass.png differ diff --git a/src/assets/images/temp/hypnosis.png b/src/assets/images/temp/hypnosis.png new file mode 100644 index 0000000..7046f80 Binary files /dev/null and b/src/assets/images/temp/hypnosis.png differ diff --git a/src/assets/images/temp/invwindow.png b/src/assets/images/temp/invwindow.png new file mode 100644 index 0000000..9a2ac06 Binary files /dev/null and b/src/assets/images/temp/invwindow.png differ diff --git a/src/assets/images/temp/milk.png b/src/assets/images/temp/milk.png new file mode 100644 index 0000000..50dd6ea Binary files /dev/null and b/src/assets/images/temp/milk.png differ diff --git a/src/assets/images/temp/pillowtalk.png b/src/assets/images/temp/pillowtalk.png new file mode 100644 index 0000000..57da7ad Binary files /dev/null and b/src/assets/images/temp/pillowtalk.png differ diff --git a/src/assets/images/temp/pocky.png b/src/assets/images/temp/pocky.png new file mode 100644 index 0000000..ad6997f Binary files /dev/null and b/src/assets/images/temp/pocky.png differ diff --git a/src/assets/images/temp/polish.png b/src/assets/images/temp/polish.png new file mode 100644 index 0000000..d6019e9 Binary files /dev/null and b/src/assets/images/temp/polish.png differ diff --git a/src/assets/images/temp/rock.png b/src/assets/images/temp/rock.png new file mode 100644 index 0000000..a8f99d7 Binary files /dev/null and b/src/assets/images/temp/rock.png differ diff --git a/src/assets/images/temp/shuriken.png b/src/assets/images/temp/shuriken.png new file mode 100644 index 0000000..bf19759 Binary files /dev/null and b/src/assets/images/temp/shuriken.png differ diff --git a/src/assets/images/temp/snowglobe.png b/src/assets/images/temp/snowglobe.png new file mode 100644 index 0000000..4ad94ff Binary files /dev/null and b/src/assets/images/temp/snowglobe.png differ diff --git a/src/assets/images/temp/usb.png b/src/assets/images/temp/usb.png new file mode 100644 index 0000000..e7cb863 Binary files /dev/null and b/src/assets/images/temp/usb.png differ diff --git a/src/assets/images/ui/bubble.png b/src/assets/images/ui/bubble.png index 24781fd..88bebb9 100644 Binary files a/src/assets/images/ui/bubble.png and b/src/assets/images/ui/bubble.png differ diff --git a/src/assets/images/ui/bubble2.png b/src/assets/images/ui/bubble2.png deleted file mode 100644 index 88bebb9..0000000 Binary files a/src/assets/images/ui/bubble2.png and /dev/null differ diff --git a/src/assets/images/ui/exclamation.png b/src/assets/images/ui/exclamation.png index 955a6fa..2cc5302 100644 Binary files a/src/assets/images/ui/exclamation.png and b/src/assets/images/ui/exclamation.png differ diff --git a/src/assets/images/ui/exclamation2.png b/src/assets/images/ui/exclamation2.png deleted file mode 100644 index 2cc5302..0000000 Binary files a/src/assets/images/ui/exclamation2.png and /dev/null differ diff --git a/src/assets/images/ui/hud.png b/src/assets/images/ui/hud.png deleted file mode 100644 index b4e5866..0000000 Binary files a/src/assets/images/ui/hud.png and /dev/null differ diff --git a/src/assets/sounds/place.mp3 b/src/assets/sounds/place.mp3 new file mode 100644 index 0000000..93bbdad Binary files /dev/null and b/src/assets/sounds/place.mp3 differ diff --git a/src/assets/sounds/return.mp3 b/src/assets/sounds/return.mp3 new file mode 100644 index 0000000..7bec483 Binary files /dev/null and b/src/assets/sounds/return.mp3 differ diff --git a/src/assets/sounds/scroll.mp3 b/src/assets/sounds/scroll.mp3 new file mode 100644 index 0000000..340745e Binary files /dev/null and b/src/assets/sounds/scroll.mp3 differ diff --git a/src/assets/sounds/tree/escape.mp3 b/src/assets/sounds/tree/escape.mp3 new file mode 100644 index 0000000..d0ba2fb Binary files /dev/null and b/src/assets/sounds/tree/escape.mp3 differ diff --git a/src/assets/sounds/tree/meme_explosion_sound.mp3 b/src/assets/sounds/tree/meme_explosion_sound.mp3 new file mode 100644 index 0000000..f1f7bff Binary files /dev/null and b/src/assets/sounds/tree/meme_explosion_sound.mp3 differ diff --git a/src/components/Board.ts b/src/components/Board.ts index 428ac0e..cedc5b7 100644 --- a/src/components/Board.ts +++ b/src/components/Board.ts @@ -1,17 +1,24 @@ import { GameScene } from "@/scenes/GameScene"; export class Board extends Phaser.GameObjects.Container { + public scene: GameScene; public size: number; private grid: Phaser.GameObjects.Grid; private things: any[]; - constructor(scene: GameScene, x: number, y: number, width: number, height: number) { + constructor( + scene: GameScene, + x: number, + y: number, + width: number, + height: number + ) { super(scene, x, y); scene.add.existing(this); this.scene = scene; - this.size = 130; + this.size = scene.H / (height + 2); this.grid = this.scene.add.grid( 0, 0, @@ -31,6 +38,26 @@ export class Board extends Phaser.GameObjects.Container { update(time: number, delta: number) {} + // Resize the board to new level + resize(width: number, height: number) { + this.size = this.scene.H / height; + + this.grid.destroy(); + this.grid = this.scene.add.grid( + 0, + 0, + width * this.size, + height * this.size, + this.size, + this.size, + 0xffffff, + 0.1, + 0xff0000, + 0.2 + ); + this.add(this.grid); + } + // Return coordinates of the grid cell gridToCoord(gridX: number, gridY: number) { return { diff --git a/src/components/Customer.ts b/src/components/Customer.ts index 4a400c9..7ea9f63 100644 --- a/src/components/Customer.ts +++ b/src/components/Customer.ts @@ -7,19 +7,40 @@ import { interpolateColor } from "@/functions"; import { ThoughtBubble } from "./ThoughtBubble"; import { StationType } from "./StationData"; +export interface CustomerType { + spr: string; + tags: string[]; + antitags: string[]; + budget: number; + +} + export class Customer extends Button { // Movement public lastX: number; // Last position on the grid public lastY: number; public dragX: number; // Current drag position public dragY: number; + public tags: string[]; public currentStation: Station | null; public currentEmployee: Employee | null; - + public cdata: CustomerType; // Requests public itinerary: StationType[]; // List of stations to visit public requestedStation: StationType | null; + // Happiness variables + public baseTip: number; + public tipMultiplier: number; + public tipBonus: number; + public happinessStage: number; //0-6, rounds down + public minHappiness: number = 0; // bonuses + public maxHappiness: number = 6; // bonuses + + public patience: number; + public minPatience: number; // bonuses + public lockPatience: boolean; // bonuses + // Stats public doingCuteThing: boolean; public tasksCompleted: number; @@ -29,6 +50,7 @@ export class Customer extends Button { // Graphics private sprite: Phaser.GameObjects.Sprite; private thoughtBubble: ThoughtBubble; + private angryImage: Phaser.GameObjects.Image; private happinessTimer: Timer; constructor(scene: GameScene, x: number, y: number) { @@ -52,16 +74,21 @@ export class Customer extends Button { this.happiness = 1; /* Sprite */ - const size = 150; - this.sprite = this.scene.add.sprite(0, 0, "player"); + const size = 120; + this.sprite = this.scene.add.sprite(0, 0, "small_customer_walk1"); this.sprite.setOrigin(0.5, 1.0); this.sprite.y += size / 2; this.sprite.setScale(size / this.sprite.width); this.add(this.sprite); + this.angryImage = this.scene.add.image(0, -0.3 * size, "angyv"); + this.angryImage.setScale(0.25); + this.angryImage.setVisible(false); + this.add(this.angryImage); + this.thoughtBubble = new ThoughtBubble( scene, - 0.2 * size, + 0.4 * size, -0.6 * size, size ); @@ -86,9 +113,8 @@ export class Customer extends Button { this.y += (this.dragY - this.y) * 0.5; const wobble = this.doingCuteThing ? 0.1 : 0.02; - const squish = - 1.0 + wobble * Math.sin((6 * time) / 1000) - 0.2 * this.holdSmooth; - this.setScale(1.0, squish); + const squish = 1.0 + wobble * Math.sin((6 * time) / 1000); + this.setScale(1.0, squish - 0.2 * this.holdSmooth); this.sprite.setTint( interpolateColor(0xffffff, 0xff0000, 1 - this.happiness) ); @@ -104,12 +130,15 @@ export class Customer extends Button { interpolateColor(0xff0000, 0x00ff00, this.happiness) ); this.happinessTimer.redraw(this.happiness); + this.angryImage.setVisible(this.happiness <= 0.5); if (this.happiness <= 0) { this.leave(); + this.thoughtBubble.showSymbol("sad"); } } else { this.happinessTimer.setVisible(false); + this.angryImage.setVisible(false); } } @@ -144,7 +173,7 @@ export class Customer extends Button { this.happiness = 1; if (this.requestedStation === station.stationType) { - this.thoughtBubble.markAsReady(); + this.thoughtBubble.showSymbol("exclamation"); } } } @@ -153,10 +182,13 @@ export class Customer extends Button { this.currentEmployee = employee; this.sprite.input!.enabled = !employee; + + this.thoughtBubble.showSymbol(Phaser.Math.RND.pick(["happy", "love"])); } setAction(temp: boolean) { this.doingCuteThing = temp; + this.thoughtBubble.hide(); } setRequest(type: StationType | null) { diff --git a/src/components/Employee.ts b/src/components/Employee.ts index c00fb77..18e6efe 100644 --- a/src/components/Employee.ts +++ b/src/components/Employee.ts @@ -1,34 +1,41 @@ import { GameScene } from "@/scenes/GameScene"; import { Button } from "./elements/Button"; import { Customer } from "./Customer"; +import { EmployeeData, EmployeeId, EmployeeType } from "./EmployeeData"; export class Employee extends Button { + public employeeId: EmployeeId; public currentCustomer: Customer | null; public doingCuteThing: boolean; private spriteSize: number; private sprite: Phaser.GameObjects.Sprite; - constructor(scene: GameScene, x: number, y: number) { + constructor(scene: GameScene, x: number, y: number, id: EmployeeId) { super(scene, x, y); scene.add.existing(this); this.scene = scene; + this.employeeId = id; this.currentCustomer = null; /* Sprite */ this.spriteSize = 200; - this.sprite = this.scene.add.sprite(0, 0, "worker"); + this.sprite = this.scene.add.sprite(0, 0, this.spriteKey); this.sprite.setOrigin(0.5, 1.0); this.sprite.y += this.spriteSize / 2; this.sprite.setScale(this.spriteSize / this.sprite.width); this.add(this.sprite); + + // Make employee clickable during shopping + this.bindInteractive(this.sprite); + this.sprite.input!.enabled = false; } update(time: number, delta: number) { const factor = this.doingCuteThing ? 0.1 : 0.02; const squish = 1.0 + factor * Math.sin((6 * time) / 1000); - this.setScale(1.0, squish); + this.setScale(1.0, squish - 0.2 * this.holdSmooth); } setCustomer(customer: Customer | null) { @@ -63,4 +70,50 @@ export class Employee extends Button { setAction(temp: boolean) { this.doingCuteThing = temp; } + + setClickable(value: boolean) { + this.sprite.input!.enabled = value; + } + + upgrade() { + if (this.upgradeTo) { + this.employeeId = this.upgradeTo!; + this.sprite.setTexture(this.spriteKey); + } + } + + /* Getters */ + + get employeeType(): EmployeeType { + return EmployeeData[this.employeeId].type; + } + + get employeeName(): string { + console.log(this.employeeId, EmployeeData[this.employeeId]); + return EmployeeData[this.employeeId].name; + } + + get employeeTier(): number { + return EmployeeData[this.employeeId].tier; + } + + get spriteKey(): string { + return EmployeeData[this.employeeId].spriteKey; + } + + get walkSpeed(): number { + return EmployeeData[this.employeeId].walkSpeed ?? 0; + } + + get workSpeed(): number { + return EmployeeData[this.employeeId].workSpeed ?? 0; + } + + get upgradeCost(): number { + return EmployeeData[this.employeeId].upgradeCost ?? 0; + } + + get upgradeTo(): EmployeeId | undefined { + return EmployeeData[this.employeeId].upgradeTo; + } } diff --git a/src/components/EmployeeData.ts b/src/components/EmployeeData.ts new file mode 100644 index 0000000..c31ff2f --- /dev/null +++ b/src/components/EmployeeData.ts @@ -0,0 +1,88 @@ +/* Employee category data */ + +export enum EmployeeType { + Raccoon, + Human, // Temporary. Replace with whatever. +} + +/* Specific employee instance data */ + +export enum EmployeeId { + RaccoonTier1, + RaccoonTier2, + RaccoonTier3, + HumanTier1, + HumanTier2, + HumanTier3, +} + +export interface EmployeeInterface { + type: EmployeeType; // Employee type + name: string; // Employee name + tier: number; // Tier number + spriteKey: string; // Employee image key + walkSpeed: number; // Speed of the employee walking + workSpeed: number; // Speed of the employee working + upgradeCost?: number; // Cost to upgrade the employee + upgradeTo?: EmployeeId; // Employee to upgrade to +} + +export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { + [EmployeeId.RaccoonTier1]: { + type: EmployeeType.Raccoon, + name: "Raccoon employee", + tier: 1, + spriteKey: "worker", + walkSpeed: 1, + workSpeed: 1, + upgradeCost: 100, + upgradeTo: EmployeeId.RaccoonTier2, + }, + [EmployeeId.RaccoonTier2]: { + type: EmployeeType.Raccoon, + name: "Raccoon employee", + tier: 2, + spriteKey: "worker", + walkSpeed: 2, + workSpeed: 2, + upgradeCost: 500, + upgradeTo: EmployeeId.RaccoonTier3, + }, + [EmployeeId.RaccoonTier3]: { + type: EmployeeType.Raccoon, + name: "Raccoon employee", + tier: 3, + spriteKey: "worker", + walkSpeed: 3, + workSpeed: 3, + }, + + [EmployeeId.HumanTier1]: { + type: EmployeeType.Human, + name: "Human employee", + tier: 1, + spriteKey: "player", + walkSpeed: 1, + workSpeed: 1, + upgradeCost: 100, + upgradeTo: EmployeeId.HumanTier2, + }, + [EmployeeId.HumanTier2]: { + type: EmployeeType.Human, + name: "Human employee", + tier: 2, + spriteKey: "player", + walkSpeed: 2, + workSpeed: 2, + upgradeCost: 500, + upgradeTo: EmployeeId.HumanTier3, + }, + [EmployeeId.HumanTier3]: { + type: EmployeeType.Human, + name: "Human employee", + tier: 3, + spriteKey: "player", + walkSpeed: 3, + workSpeed: 3, + }, +}; diff --git a/src/components/Inventory.ts b/src/components/Inventory.ts new file mode 100644 index 0000000..1af986d --- /dev/null +++ b/src/components/Inventory.ts @@ -0,0 +1,175 @@ +import { BaseScene } from "@/scenes/BaseScene"; +import { GameScene } from "@/scenes/GameScene"; +import { Item } from "./Item"; +import { SimpleButton } from "./elements/SimpleButton"; +import { ItemButton } from "./ItemButton"; + +export class Inventory extends Phaser.GameObjects.Container { + public scene: GameScene; + public isOpen: boolean = false; + public itemList: Item[]; + public display: ItemButton[]; + public window: Phaser.GameObjects.Image; + public fwButton: SimpleButton; + public title: Phaser.GameObjects.Text; + public tdisplay: Phaser.GameObjects.Text; + private currentIndices: number[] = [0,11]; + private coordinates: number[][] = [ + [64,64], [148,64], [232,64], + [64,148], [148,148], [232,148], + [64,232], [148,232], [232,232], + [64,316], [148,316], [232,316] + ]; + constructor(scene:GameScene, x:number, y:number, stock:number[]){ + super(scene,x,y); + this.scene=scene; + this.itemList = [ + new Item(0,"rock",stock[0],1,["rock","cheap"],["cheap"],"Complimentary Pet Rock","A loving pet rock to cheer up any customer. Works modestly well."), + new Item(1,"coke",stock[1],50,["drug"],["illegal","cool"],"Cocaine","A delicious white powder made from plants. Improves working speed a whole bunch!"), + new Item(2,"hotdog",stock[2],25,["velociraptor","meat","bread","skeleton","ketchup","mustard","gay"],["meat","elitist","gay","gluten"],"Hot Dog","A big wiener with sauce, to satisfy any meat lover. You can also buy a bacon-wrapped cheesy version for 69 kr."), + new Item(3,"brocc",stock[3],12,["triceratops","veggie","healthy","stinky"],["veggie","healthy","stinky"],"Broccoli","This large stalk of free-range broccoli is perfect for vegans and herbivorous animals."), + new Item(4,"usb",stock[4],30,["protogen","tech","metal","nerd"],["nerd","tech"],"Mini USB Drive", "Additional storage space in a compact unit. I wonder who would want this?"), + new Item(5,"milk",stock[5],40,["dragon","horny","creamy","lactose","gay"],["horny","creamy","lactose","gay"],"Fresh Milk","Fresh, creamy milk for dragons. Still warm and thick."), + new Item(6,"snowglobe",stock[6],35,["lugia","kitsch","cold","ball"],["kitsch","cold","ball"],"Snowglobe","A cute little snowglobe. A certain type of customer might want this."), + new Item(7,"pocky",stock[7],30,["boykisser","weeb","cringe","sweet","chocolate"],["weeb","cringe","sweet"],"P*cky","Sweet snack made of edible sticks. There's a traditional game where you kiss while biting them. A favorite of virgins."), + new Item(8,"hourglass",stock[8],110,["time","physics","glass"],["physics"],"Hourglass","Turns back the time on a customer's patience. Might make it hard to work though..."), + new Item(9,"hypnosis",stock[9],90,["hypno","horny","kinky","weird","psychic"],["horny","kinky","weird"],"Hypnosis","Uses a state of hypnosis to keep a customer's patience constant. You can't increase it any more either though."), + new Item(10,"polish",stock[10],80,["expensive","creamy","musky"],["expensive","musky"],"Extra-Premium Polish","Gives scales a wonderful gloss and unique scent. Most customers love it, but comes at a premium."), + new Item(11,"pillowtalk",stock[11],50,["horny","soft","cringe"],["horny","cringe"],"Pillow Talk","Talk to a customer alluringly to have them use more services. Good telemarketing is vital!"), + new Item(12,"shuriken",stock[12],75,["sharp","weeb","ninja","cringe","cool"],["cool","cringe","weeb","sharp"],"Shuriken","Some type of fidget spinner that sharpens mental capabilites. Allows a worker to critical manicure."), + ]; + this.display = []; + this.window = new Phaser.GameObjects.Image(this.scene,x,y,"invwindow"); + this.window.setAlpha(0.85); + //this.window.setVisible(false); + this.window.setOrigin(-1,0); + this.add(this.window); + this.window.setDepth(1); + this.title = this.scene.addText({ + x: 75, + y: 760, + size: 30, + color: "#FFFFFF", + text: "", + }); + this.tdisplay = this.scene.addText({ + x: 75, + y: 845, + size: 25, + color: "#FFFFFF", + text: "", + }); + this.tdisplay.setWordWrapWidth(500); + this.add(this.title); + this.add(this.tdisplay); + this.fwButton = new SimpleButton(this.scene,x,y,"","fwbutton",10); + this.fwButton.on("click", ()=> {this.scroll()}); + this.scene.add.existing(this); + } + + unhighlight(){ + for(let p=0; p ib.destroy()); + this.setPosition(-650,0); + this.isOpen=false; + this.display = []; + this.window.setVisible(false); + } + + open(){ + this.scene.sound.play("t_rustle"); + this.window.setVisible(true); + console.log("Open Processed"); + this.x = 0; + this.y = 0; + this.isOpen=true; + this.populate(); + } + + returnItem(id: number){ + this.itemList[id].quant++; + } + + updateAmountText(id:number, i: number){ + if(i > 0) { + this.title.setText(this.itemList[id].name + " x" + i); + } else { + this.title.setText(""); + this.tdisplay.setText(""); + } + } + + scroll(){ + if(this.currentIndices[1] < this.itemList.length) { + let b = this.currentIndices[1] + 1; + let e = this.currentIndices[1] + 11; + this.currentIndices = [b,e]; + } else { + this.currentIndices = [0,11]; + } + this.repopulate(); + + } +} \ No newline at end of file diff --git a/src/components/Item.ts b/src/components/Item.ts new file mode 100644 index 0000000..a0d2d05 --- /dev/null +++ b/src/components/Item.ts @@ -0,0 +1,40 @@ +export class Item { + public id:number; + public spr:string; + public quant:number; + public price:number; + public tags:string[]; + public antitags:string[]; + public name:string; + public desc:string; + + //-1 - default item, does nothing + //0 - Complimentary Pet Rock - increases satisfaction by one stage + //1 - cocaine - doubles station workspeed, once + //2 - hot dog - increases satisfaction by 2 stages for velociraptors + //3 - broccoli - increases satisfaction by 2 stages for triceratops + //4 - usb - increases satisfaction by 2 stages for protogen + //5 - fresh milk - increases satisfaction by 2 stages for dragon + //6 - snow globe - increases satisfaction by 2 stages for lugia + //7 - pocky - increases satisfaction by 2 stages for boykisser + //8 - hourglass - station takes twice as long, but resets patience + //9 - hypnosis - customers no longer lose patience after being serviced at least once, but patience cannot increase either + //10 - extra polish - increases tips received by 100% base amount, unless customer is cheap + //11 - pillow talk - adds a random station to the end of a customer's itinerary + //12 - shuriken - barbers can crit, crit causes happiness to raise one stage + + constructor(id:number,sp:string,qt:number,pr:number,tgs:string[],atgs:string[],name:string,dsc:string) { + this.id=id; + this.spr=sp; + this.quant=qt; + this.price=pr; + this.tags=tgs; + this.antitags=atgs; + this.name=name; + this.desc=dsc; + } + + setQuantity(n:number){ + this.quant=n; + } +} \ No newline at end of file diff --git a/src/components/ItemButton.ts b/src/components/ItemButton.ts new file mode 100644 index 0000000..9c4c96e --- /dev/null +++ b/src/components/ItemButton.ts @@ -0,0 +1,146 @@ +import { Item } from "./Item"; +import { Inventory } from "./Inventory"; +import { Button } from "./elements/Button"; +import { BaseScene } from "@/scenes/BaseScene"; + +export class ItemButton extends Button { + public id: number; + public index: number; + public sprname: string; + public spr: Phaser.GameObjects.Sprite; + public default: number[]; + public state: number = 0; + public passivate: boolean = false; + public dragX: number; // Current drag position + public dragY: number; + public doingCuteThing: boolean; + private parent: Inventory; + constructor(scene:BaseScene,x:number,y:number,parent: Inventory, id:number, index:number, spr:string){ + super(scene,x,y); + this.parent = parent; + this.default = [x,y]; + this.id=id; + this.index=index; + this.sprname = spr; + this.spr = new Phaser.GameObjects.Sprite(this.scene,x,y,spr,0); + this.spr.setOrigin(0.5,0.5); + this.bindInteractive(this.spr, true); + this.add(this.spr); + this.parent.add(this); + this.setDepth(4); + + } + + onDown( + pointer: Phaser.Input.Pointer, + localX: number, + localY: number, + event: Phaser.Types.Input.EventData + ) { + + super.onDown(pointer,localX,localY,event); + if(this.passivate){ + return; + } else { + this.parseClick(); + } + + } + + update(time: number, delta: number){ + if(this.state == 3) { + this.x = this.dragX-this.default[0]; + this.y = this.dragY-this.default[1]; + + /* + this.x += (this.dragX - this.x) * 0.5; + this.y += (this.dragY - this.y) * 0.5; + */ + } + /* + const factor = this.doingCuteThing ? 0.1 : 0.02; + const squish = 1.0 + factor * Math.sin((6 * time) / 1000); + this.setScale(1.0, squish); + */ + } + + parseClick(){ + if(this.state == 0) { + this.parent.unhighlight(); + this.select(); + this.parent.highlight(this.id); + } else if (this.state == 1) { + this.state = 3; + this.parent.remove(this); + this.parent.scene.setActiveItem(this); + this.setPosition(0,0); + this.split(); + this.passivate = true; + this.setDepth(5); + } + } + + onDragStart(pointer: Phaser.Input.Pointer, dragX: number, dragY: number) { + this.dragged = true; + this.emit("itempickup"); + } + + onDrag(pointer: Phaser.Input.Pointer, dragX: number, dragY: number) { + this.hold = false; + this.dragX = pointer.x; + this.dragY = pointer.y; + this.emit("itemdrag"); + } + + onDragEnd(pointer: Phaser.Input.Pointer, dragX: number, dragY: number) { + this.dragged = false; + if(this.state == 3) { + this.emit("itemdrop"); + } + } + + select(){ + this.state = 1; + this.spr.setFrame(1); + } + + unselect(){ + if(this.parent.itemList[this.id].quant <= 0){ + this.shadow(); + } else { + this.state = 0; + this.spr.setFrame(0); + this.passivate = false; + } + } + + shadow(){ + this.spr.setFrame(2); + this.passivate = true; + this.state = 2; + } + + snapTo(x:number,y:number){ + this.x=x-this.default[0]; + this.y=y-this.default[1]; + } + + unshadow(){ + this.state = 1; + this.spr.setFrame(1); + this.passivate = false; + } + + split(){ + this.parent.display[this.index] = new ItemButton(this.scene,this.default[0],this.default[1],this.parent,this.id,this.index,this.sprname); + this.parent.itemList[this.id].quant--; + let r = this.parent.itemList[this.id].quant; + if(r <= 0) { + this.parent.display[this.index].shadow(); + } else { + this.parent.display[this.index].select(); + } + this.parent.updateAmountText(this.id,r); + } + +} \ No newline at end of file diff --git a/src/components/ItemHandler.ts b/src/components/ItemHandler.ts new file mode 100644 index 0000000..70e112a --- /dev/null +++ b/src/components/ItemHandler.ts @@ -0,0 +1,113 @@ +import { Item } from "./Item"; +import { GameScene } from "@/scenes/GameScene"; +import { Station } from "./Station"; +import { Customer } from "./Customer"; +import { StationType } from "./StationData"; + +export class ItemHandler { + public scene: GameScene; + constructor(scene:GameScene) { + this.scene = scene; + } + + process(i: Item, st: Station, ct: Customer){ + switch(i.id) + { + case -1: { + break; + } case 0: { + break; + } case 1: { + st.taskHaste *= 0.5; + break; + } case 2: { + this.parsePreferredItem(i,st,ct); + break; + } case 3: { + this.parsePreferredItem(i,st,ct); + break; + } case 4: { + this.parsePreferredItem(i,st,ct); + break; + } case 5: { + this.parsePreferredItem(i,st,ct); + break; + } case 6: { + this.parsePreferredItem(i,st,ct); + break; + } case 7: { + this.parsePreferredItem(i,st,ct); + break; + } case 8: { + ct.patience = 100; + st.taskHaste*=2; + break; + } case 9: { + ct.lockPatience = true; + break; + } case 10: { + let tstate = 0 + if((i.antitags.length > 0) && ct.cdata.antitags.length > 0){ + for(let na = 0; na < i.antitags.length; na++){ + if(ct.cdata.antitags.includes(i.tags[na])) { + tstate = -1; + } + } + } + + if(tstate == -1) { + ct.happinessStage -= 2; + ct.maxHappiness = 3; + ct.tipMultiplier *= 0.1; + return; + } else { + ct.tipMultiplier ++; + return; + } + } case 11: { + let r = Math.random()*3; + if(r < 1) { + ct.itinerary.push(StationType.HornAndNails); + } else if (r < 2) { + ct.itinerary.push(StationType.ScalePolish); + } else if (r < 3) { + ct.itinerary.push(StationType.GoldBath); + } + } case 12: { + + } + break; + } + } + + parsePreferredItem(i: Item, st:Station, ct:Customer){ + let state = 0; + if((i.tags.length > 0) && (ct.cdata.tags.length > 0)) { + for(let nt = 0; nt < i.tags.length; nt++){ + if(ct.cdata.tags.includes(i.tags[nt])) { + state = 1; + } + } + } + + if((i.antitags.length > 0) && ct.cdata.antitags.length > 0){ + for(let na = 0; na < i.antitags.length; na++){ + if(ct.cdata.antitags.includes(i.tags[na])) { + state = -1; + } + } + } + + if(state == 0) { + ct.happinessStage += 2; + return; + } else if (state == -1) { + ct.happinessStage -= 2; + ct.maxHappiness = 3; + return; + } else { + ct.happinessStage += 0.5; + return; + } + } +} \ No newline at end of file diff --git a/src/components/Levels.ts b/src/components/Levels.ts new file mode 100644 index 0000000..32931f5 --- /dev/null +++ b/src/components/Levels.ts @@ -0,0 +1,85 @@ +export enum LevelId { + Level1, + Level2, + Level3, +} + +export interface Level { + id: LevelId; + background: string; + width: number; + height: number; + grid: number[][]; + customerArrivalTimes: number[]; +} + +export enum BlockType { + Empty = 0, + Wall = 1, + WaitingSeat = 2, + HornAndNails = 3, + ScalePolish = 4, + GoldBath = 5, + CashRegister = 6, + Employee = 9, +} + +const _ = BlockType.Empty; +const X = BlockType.Wall; + +export const LevelData: Level[] = [ + { + id: LevelId.Level1, + background: "grid1", + width: 6 + 2, + height: 4 + 2, + grid: [ + [X, X, X, X, X, X, X, X], + [X, 2, _, 3, 3, _, 4, X], + [X, 2, _, _, _, _, 4, X], + [_, _, _, 5, 5, _, _, X], + [X, 9, 9, _, _, 6, _, _], + [X, X, X, X, X, X, X, X], + ], + customerArrivalTimes: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90], + }, + { + id: LevelId.Level2, + background: "grid4", + width: 7 + 2, + height: 5 + 2, + grid: [ + [X, X, X, X, X, X, X, X, X], + [X, 2, _, _, _, _, _, _, X], + [X, 2, _, 3, 3, 3, _, 4, X], + [X, 2, _, _, _, _, _, 4, X], + [_, _, _, 5, 5, 5, _, _, X], + [X, 9, 9, 9, _, _, 6, _, _], + [X, X, X, X, X, X, X, X, X], + ], + customerArrivalTimes: [ + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, + ], + }, + { + id: LevelId.Level3, + background: "grid3", + width: 8 + 2, + height: 6 + 2, + grid: [ + [X, X, X, X, X, X, X, X, X, X], + [X, 2, _, _, _, _, _, _, _, X], + [X, 2, _, 3, _, 3, _, 4, 4, X], + [X, 2, _, 3, _, 3, _, _, _, X], + [X, 2, _, _, _, _, _, 4, 4, X], + [_, _, _, 5, 5, 5, _, _, _, X], + [X, 9, 9, 9, 9, _, _, 6, _, _], + [X, X, X, X, X, X, X, X, X, X], + ], + customerArrivalTimes: [ + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, + ], + }, +]; diff --git a/src/components/Station.ts b/src/components/Station.ts index 65c7932..4381bd7 100644 --- a/src/components/Station.ts +++ b/src/components/Station.ts @@ -13,12 +13,24 @@ import { interpolateColor } from "@/functions"; export class Station extends Button { public stationId: StationId; public currentCustomer: Customer | null; // The customer using the station + //public taskDuration: number; // Time it takes to complete a task + public taskSpeed: number = 1; // For permanent bonuses + public taskHaste: number = 1; // For temporary bonuses + + public taskTimer: number = 0; + + public appliedItems: number[]; + public appliedSprites: Phaser.GameObjects.Sprite[]; + //public admissionFee: number; // Cost to use the station private sprite: Phaser.GameObjects.Image; private text: Phaser.GameObjects.Text; private progressTimer: Timer; + + + constructor(scene: GameScene, x: number, y: number, id: StationId) { super(scene, x, y); scene.add.existing(this); @@ -54,11 +66,18 @@ export class Station extends Button { ); this.progressTimer.setVisible(false); this.add(this.progressTimer); + + // Make station clickable during shopping + this.bindInteractive(this.sprite); + this.sprite.input!.enabled = false; + + this.appliedItems = []; + this.appliedSprites = []; } update(time: number, delta: number) { const squish = 1.0 + 0.02 * Math.sin((6 * time) / 1000); - this.setScale(1.0, squish); + this.setScale(1.0, squish - 0.2 * this.holdSmooth); } setCustomer(customer: Customer | null) { @@ -69,7 +88,8 @@ export class Station extends Button { startTask() { this.text.setText("Working"); - + this.parseItems(); + this.clearItems(); this.scene.tweens.addCounter({ from: 1, to: 0, @@ -88,12 +108,52 @@ export class Station extends Button { }); } + setClickable(value: boolean) { + this.sprite.input!.enabled = value; + } + + upgrade() { + if (this.upgradeTo) { + this.stationId = this.upgradeTo!; + this.sprite.setTexture(this.spriteKey); + } + } + + applyItem(id: number, sp: string){ + this.appliedItems.push(id); + let st = new Phaser.GameObjects.Sprite(this.scene,-70+(35*this.appliedItems.length),40,sp); + st.setOrigin(0.5,0.5); + st.setScale(0.4); + st.setDepth(2); + st.setAlpha(0.85); + this.add(st); + this.appliedSprites.push(st); + } + + clearItems(){ + this.appliedItems = []; + this.appliedSprites.forEach((sp) => sp.destroy()); + this.appliedSprites = []; + } + + parseItems(){ + + } + /* Getters */ get stationType(): StationType { return StationData[this.stationId].type; } + get stationName(): string { + return StationData[this.stationId].name; + } + + get stationTier(): number { + return StationData[this.stationId].tier; + } + get spriteKey(): string { return StationData[this.stationId].spriteKey; } diff --git a/src/components/StationData.ts b/src/components/StationData.ts index 229d8ec..67a4e30 100644 --- a/src/components/StationData.ts +++ b/src/components/StationData.ts @@ -24,7 +24,7 @@ export const StationTypeData: { [key in StationType]: StationTypeInterface } = { }, [StationType.ScalePolish]: { symbolKey: "wax", - color: 0x00ff00, + color: 0xffff00, }, [StationType.GoldBath]: { symbolKey: "gold", @@ -32,7 +32,7 @@ export const StationTypeData: { [key in StationType]: StationTypeInterface } = { }, [StationType.CashRegister]: { symbolKey: "cash", - color: 0xffff00, + color: 0x00ff00, }, }; @@ -56,6 +56,8 @@ export enum StationId { export interface StationInterface { type: StationType; // Station type + name: string; // Station name + tier: number; // Tier number spriteKey: string; // Station image key taskDuration?: number; // Time it takes to complete a task admissionFee?: number; // Customer pays this amount to use the station @@ -66,23 +68,31 @@ export interface StationInterface { export const StationData: { [key in StationId]: StationInterface } = { [StationId.WaitingSeatTier1]: { type: StationType.WaitingSeat, + name: "WaitingSeat station", + tier: 1, spriteKey: "waitchair_1", upgradeCost: 100, upgradeTo: StationId.WaitingSeatTier2, }, [StationId.WaitingSeatTier2]: { type: StationType.WaitingSeat, + name: "WaitingSeat station", + tier: 2, spriteKey: "waitchair_2", upgradeCost: 500, upgradeTo: StationId.WaitingSeatTier3, }, [StationId.WaitingSeatTier3]: { type: StationType.WaitingSeat, + name: "WaitingSeat station", + tier: 3, spriteKey: "waitchair_3", }, [StationId.HornAndNailsTier1]: { type: StationType.HornAndNails, + name: "HornAndNails station", + tier: 1, spriteKey: "nail_1", taskDuration: 3000, admissionFee: 10, @@ -91,6 +101,8 @@ export const StationData: { [key in StationId]: StationInterface } = { }, [StationId.HornAndNailsTier2]: { type: StationType.HornAndNails, + name: "HornAndNails station", + tier: 2, spriteKey: "nail_2", taskDuration: 2500, admissionFee: 20, @@ -99,6 +111,8 @@ export const StationData: { [key in StationId]: StationInterface } = { }, [StationId.HornAndNailsTier3]: { type: StationType.HornAndNails, + name: "HornAndNails station", + tier: 3, spriteKey: "nail_3", taskDuration: 2000, admissionFee: 30, @@ -106,6 +120,8 @@ export const StationData: { [key in StationId]: StationInterface } = { [StationId.ScalePolishTier1]: { type: StationType.ScalePolish, + name: "ScalePolish station", + tier: 1, spriteKey: "wax_1", taskDuration: 2000, admissionFee: 10, @@ -114,6 +130,8 @@ export const StationData: { [key in StationId]: StationInterface } = { }, [StationId.ScalePolishTier2]: { type: StationType.ScalePolish, + name: "ScalePolish station", + tier: 2, spriteKey: "wax_2", taskDuration: 1500, admissionFee: 20, @@ -122,6 +140,8 @@ export const StationData: { [key in StationId]: StationInterface } = { }, [StationId.ScalePolishTier3]: { type: StationType.ScalePolish, + name: "ScalePolish station", + tier: 3, spriteKey: "wax_3", taskDuration: 1000, admissionFee: 30, @@ -129,6 +149,8 @@ export const StationData: { [key in StationId]: StationInterface } = { [StationId.GoldBathTier1]: { type: StationType.GoldBath, + name: "GoldBath station", + tier: 1, spriteKey: "bath_1", taskDuration: 4000, admissionFee: 20, @@ -137,6 +159,8 @@ export const StationData: { [key in StationId]: StationInterface } = { }, [StationId.GoldBathTier2]: { type: StationType.GoldBath, + name: "GoldBath station", + tier: 2, spriteKey: "bath_2", taskDuration: 3000, admissionFee: 30, @@ -145,6 +169,8 @@ export const StationData: { [key in StationId]: StationInterface } = { }, [StationId.GoldBathTier3]: { type: StationType.GoldBath, + name: "GoldBath station", + tier: 3, spriteKey: "bath_3", taskDuration: 2000, admissionFee: 40, @@ -152,6 +178,8 @@ export const StationData: { [key in StationId]: StationInterface } = { [StationId.CashRegister]: { type: StationType.CashRegister, + name: "CashRegister station", + tier: 1, spriteKey: "checkout", taskDuration: 500, }, diff --git a/src/components/Overlay.ts b/src/components/SummaryOverlay.ts similarity index 76% rename from src/components/Overlay.ts rename to src/components/SummaryOverlay.ts index 312a31a..93ac6f3 100644 --- a/src/components/Overlay.ts +++ b/src/components/SummaryOverlay.ts @@ -2,7 +2,7 @@ import { GameScene } from "@/scenes/GameScene"; import { RoundRectangle } from "./elements/RoundRectangle"; import { TextButton } from "./TextButton"; -export class Overlay extends Phaser.GameObjects.Container { +export class SummaryOverlay extends Phaser.GameObjects.Container { public scene: GameScene; private background: Phaser.GameObjects.Rectangle; @@ -16,10 +16,14 @@ export class Overlay extends Phaser.GameObjects.Container { scene.add.existing(this); this.scene = scene; + this.setVisible(false); + this.setAlpha(0); + // Fullscreen blackness this.background = this.scene.add.rectangle(0, 0, scene.W, scene.H, 0, 0.75); this.background.setOrigin(0); this.add(this.background); + this.background.setInteractive(); this.panel = new RoundRectangle(scene, { x: scene.W / 2, @@ -66,4 +70,27 @@ export class Overlay extends Phaser.GameObjects.Container { update(time: number, delta: number) { this.okButton.update(time, delta); } + + open() { + this.setVisible(true); + this.setAlpha(0); + this.scene.tweens.add({ + targets: this, + alpha: 1, + duration: 200, + }); + } + + close() { + this.setVisible(true); + this.setAlpha(1); + this.scene.tweens.add({ + targets: this, + alpha: 0, + duration: 200, + onComplete: () => { + this.setVisible(false); + }, + }); + } } diff --git a/src/components/TextButton.ts b/src/components/TextButton.ts index c929260..1ef1b57 100644 --- a/src/components/TextButton.ts +++ b/src/components/TextButton.ts @@ -49,7 +49,12 @@ export class TextButton extends Button { this.setScale(1.0 - 0.1 * this.holdSmooth); } - open() { - - } + setText(text: string) { + this.text.setText(text); + } + + setEnabled(enabled: boolean) { + this.setAlpha(enabled ? 1 : 0.5); + this.border.input!.enabled = enabled; + } } diff --git a/src/components/ThoughtBubble.ts b/src/components/ThoughtBubble.ts index 078e937..8836092 100644 --- a/src/components/ThoughtBubble.ts +++ b/src/components/ThoughtBubble.ts @@ -4,7 +4,7 @@ import { StationType, StationTypeData } from "./StationData"; export class ThoughtBubble extends Phaser.GameObjects.Container { private background: Phaser.GameObjects.Image; private image: Phaser.GameObjects.Ellipse; - private exclamation: Phaser.GameObjects.Image; + private symbol: Phaser.GameObjects.Image; constructor(scene: GameScene, x: number, y: number, size: number) { super(scene, x, y); @@ -16,28 +16,50 @@ export class ThoughtBubble extends Phaser.GameObjects.Container { this.background.setVisible(false); this.add(this.background); - this.image = this.scene.add.ellipse(0, -0.07 * size, 40, 40, 0); + this.image = this.scene.add.ellipse(0, -0.05 * size, 40, 40, 0); this.image.setVisible(false); this.add(this.image); - this.exclamation = this.scene.add.image(0, -0.07 * size, "exclamation"); - this.exclamation.setScale(60 / this.exclamation.width); - this.exclamation.setVisible(false); - this.add(this.exclamation); + this.symbol = this.scene.add.image(0, -0.02 * size, "exclamation"); + this.symbol.setScale(70 / this.symbol.width); + this.symbol.setVisible(false); + this.add(this.symbol); + } + + hide() { + this.background.setVisible(false); + this.image.setVisible(false); + this.symbol.setVisible(false); } setRequest(type: StationType | null) { this.background.setVisible(type !== null); this.image.setVisible(type !== null); - this.exclamation.setVisible(false); + this.symbol.setVisible(false); if (type !== null) { this.image.fillColor = StationTypeData[type].color; } + + if (type === StationType.CashRegister) { + this.showSymbol("money"); + } } - markAsReady() { + showSymbol( + key: + | "exclamation" + | "angyv" + | "happy" + | "love" + | "money" + | "question" + | "sad" + ) { + this.background.setVisible(true); this.image.setVisible(false); - this.exclamation.setVisible(true); + this.symbol.setVisible(true); + + this.symbol.setTexture(key); } } diff --git a/src/components/UI.ts b/src/components/UI.ts index 1a30c7a..6184bcd 100644 --- a/src/components/UI.ts +++ b/src/components/UI.ts @@ -1,5 +1,6 @@ import { GameScene } from "@/scenes/GameScene"; import { Timer } from "./Timer"; +import { TextButton } from "./TextButton"; export class UI extends Phaser.GameObjects.Container { public scene: GameScene; @@ -9,6 +10,7 @@ export class UI extends Phaser.GameObjects.Container { private dayProgressTimer: Timer; private dayText: Phaser.GameObjects.Text; private moneyText: Phaser.GameObjects.Text; + private nextButton: TextButton; constructor(scene: GameScene) { super(scene, 0, 0); @@ -16,11 +18,11 @@ export class UI extends Phaser.GameObjects.Container { this.scene = scene; const panelWidth = 300; - const panelHeight = 400; + const panelHeight = 600; this.panel = this.scene.add.container( - scene.W - panelWidth / 2, - panelHeight / 2 + scene.W - panelWidth / 2 - 50, + panelHeight / 2 + 50 ); this.add(this.panel); @@ -60,7 +62,7 @@ export class UI extends Phaser.GameObjects.Container { this.moneyText = this.scene.addText({ x: 0, - y: 0.3 * panelHeight, + y: 100, size: 40, color: "#FFFFFF", text: "Money: $0", @@ -68,6 +70,12 @@ export class UI extends Phaser.GameObjects.Container { this.moneyText.setStroke("black", 4); this.moneyText.setOrigin(0.5); this.panel.add(this.moneyText); + + this.nextButton = new TextButton(scene, 0, 300, "Next day"); + this.panel.add(this.nextButton); + this.nextButton.on("click", () => { + this.emit("nextDay"); + }); } update(time: number, delta: number) {} @@ -83,4 +91,8 @@ export class UI extends Phaser.GameObjects.Container { setMoney(money: number) { this.moneyText.setText(`Money: $${money}`); } + + setShoppingMode(isShopping: boolean) { + this.nextButton.setVisible(isShopping); + } } diff --git a/src/components/UpgradeOverlay.ts b/src/components/UpgradeOverlay.ts new file mode 100644 index 0000000..ec45d27 --- /dev/null +++ b/src/components/UpgradeOverlay.ts @@ -0,0 +1,214 @@ +import { GameScene } from "@/scenes/GameScene"; +import { RoundRectangle } from "./elements/RoundRectangle"; +import { TextButton } from "./TextButton"; +import { Station } from "./Station"; +import { Employee } from "./Employee"; +import { StationData } from "./StationData"; +import { EmployeeData } from "./EmployeeData"; + +export class UpgradeOverlay extends Phaser.GameObjects.Container { + public scene: GameScene; + + private selectedStation: Station | null = null; + private selectedEmployee: Employee | null = null; + + private background: Phaser.GameObjects.Rectangle; + private panel: RoundRectangle; + private titleText: Phaser.GameObjects.Text; + private moneyText: Phaser.GameObjects.Text; + private buyButton: TextButton; + + constructor(scene: GameScene) { + super(scene, 0, 0); + scene.add.existing(this); + this.scene = scene; + + this.setVisible(false); + this.setAlpha(0); + + // Fullscreen blackness + this.background = this.scene.add.rectangle(0, 0, scene.W, scene.H, 0, 0.75); + this.background.setOrigin(0); + this.add(this.background); + + this.panel = new RoundRectangle(scene, { + x: 0, + y: 0, + width: 600, + height: 300, + radius: 20, + color: 0xffffff, + }); + this.add(this.panel); + + this.titleText = this.scene.addText({ + x: 0, + y: -100, + size: 50, + color: "#FFFFFF", + text: "...", + }); + this.titleText.setOrigin(0.5); + this.titleText.setStroke("black", 4); + this.panel.add(this.titleText); + + this.moneyText = this.scene.addText({ + x: -250, + y: -50, + size: 40, + color: "#FFFFFF", + text: "...", + }); + this.moneyText.setStroke("black", 4); + this.moneyText.setOrigin(0); + this.panel.add(this.moneyText); + + this.buyButton = new TextButton(scene, 220, 150, "$100"); + this.panel.add(this.buyButton); + this.buyButton.on("click", () => { + if (this.selectedStation) { + this.emit("upgradeStation", this.selectedStation); + } else { + this.emit("upgradeEmployee", this.selectedEmployee); + } + }); + + // Interactions + + // Dismiss overlay when clicking outside of panel + this.background.setInteractive(); + this.background.on("pointerdown", this.close, this); + + // Prevent clicks on panel from closing overlay + this.panel.setInteractive(); + } + + update(time: number, delta: number) { + this.buyButton.update(time, delta); + } + + selectStation(station: Station) { + this.selectedEmployee = null; + this.selectedStation = station; + this.titleText.setText(station.stationName); + + // Position panel + if (station.x > this.scene.W / 2) { + this.panel.x = station.x - 500; + this.panel.y = station.y; + } else { + this.panel.x = station.x + 500; + this.panel.y = station.y; + } + + // Upgrade text if there is an upgrade available + if (station.upgradeTo) { + const nextData = StationData[station.upgradeTo]; + const durationDiff = nextData.taskDuration! - station.taskDuration; + const revenueDiff = nextData.admissionFee! - station.admissionFee; + + let text = ""; + text += `Tier: ${station.stationTier}\n`; + if (station.taskDuration > 0) { + text += `Duration: ${station.taskDuration / 1000}s (${ + durationDiff / 1000 + }s)\n`; + } + if (station.admissionFee > 0) { + text += `Revenue: $${station.admissionFee} (+$${revenueDiff})\n`; + } + this.moneyText.setText(text); + + this.buyButton.setVisible(true); + this.buyButton.setText(`$${station.upgradeCost}`); + } + // Otherwise, show current stats + else { + let text = ""; + text += `Tier: ${station.stationTier}\n`; + text += `Duration: ${station.taskDuration / 1000}s\n`; + text += `Revenue: $${station.admissionFee}\n`; + this.moneyText.setText(text); + + this.buyButton.setVisible(false); + } + + // Enable/disable buy button + const canAfford = station.upgradeCost <= this.scene.money; + this.buyButton.setEnabled(canAfford); + + this.open(); + } + + selectEmployee(employee: Employee) { + this.selectedStation = null; + this.selectedEmployee = employee; + this.titleText.setText(employee.employeeName); + + // Position panel + if (employee.x > this.scene.W / 2) { + this.panel.x = employee.x - 500; + this.panel.y = employee.y; + } else { + this.panel.x = employee.x + 500; + this.panel.y = employee.y; + } + + // Upgrade text if there is an upgrade available + if (employee.upgradeTo) { + const nextData = EmployeeData[employee.upgradeTo]; + const walkDiff = nextData.walkSpeed! - employee.walkSpeed; + const workDiff = nextData.workSpeed! - employee.workSpeed; + + let text = ""; + text += `Tier: ${employee.employeeTier}\n`; + text += `Walk speed: ${employee.walkSpeed} (+${walkDiff}s)\n`; + text += `Work speed: ${employee.workSpeed} (+${workDiff})\n`; + this.moneyText.setText(text); + + this.buyButton.setVisible(true); + this.buyButton.setText(`$${employee.upgradeCost}`); + } + // Otherwise, show current stats + else { + let text = ""; + text += `Tier: ${employee.employeeTier}\n`; + text += `Walk speed: ${employee.walkSpeed}\n`; + text += `Work speed: ${employee.workSpeed}\n`; + this.moneyText.setText(text); + + this.buyButton.setVisible(false); + } + + // Enable/disable buy button + const canAfford = employee.upgradeCost <= this.scene.money; + this.buyButton.setEnabled(canAfford); + + this.open(); + } + + open() { + if (this.alpha < 1) { + this.setVisible(true); + this.setAlpha(0); + this.scene.tweens.add({ + targets: this, + alpha: 1, + duration: 200, + }); + } + } + + close() { + this.setVisible(true); + this.setAlpha(1); + this.scene.tweens.add({ + targets: this, + alpha: 0, + duration: 200, + onComplete: () => { + this.setVisible(false); + }, + }); + } +} diff --git a/src/components/elements/Button.ts b/src/components/elements/Button.ts index aba1a47..6e2d6e4 100644 --- a/src/components/elements/Button.ts +++ b/src/components/elements/Button.ts @@ -4,8 +4,8 @@ export class Button extends Phaser.GameObjects.Container { public scene: BaseScene; // private hover: boolean; private _hold: boolean; - protected dragged: boolean; - protected blocked: boolean; + public dragged: boolean; + public blocked: boolean; public liftSmooth: number; public holdSmooth: number; public category: number; diff --git a/src/components/elements/SimpleButton.ts b/src/components/elements/SimpleButton.ts new file mode 100644 index 0000000..932da97 --- /dev/null +++ b/src/components/elements/SimpleButton.ts @@ -0,0 +1,83 @@ +import { BaseScene } from "@/scenes/BaseScene"; +import { Button } from "./Button"; + +export class SimpleButton extends Button { + public index: number; + public value: string; + private sprite: Phaser.GameObjects.Sprite; + private tdisplay: Phaser.GameObjects.Text; + private disabled: boolean = false; + + constructor(scene: BaseScene, x: number, y: number, v: string, spr: string, fsize: number = 40) { + super(scene, x, y); + this.sprite = scene.add.sprite(0, 0, spr, 0); + this.sprite.setOrigin(0.5,0.5); + this.add(this.sprite); + this.bindInteractive(this.sprite); + this.value = v; + this.tdisplay = scene.addText({ text: v, color: "white", size: fsize }); + this.tdisplay.setOrigin(0.5); + this.add(this.tdisplay); + this.index = -1; + this.disabled = false; + } + + center() { + this.sprite.setOrigin(0.5,0.5); + this.tdisplay.setOrigin(0.5,0.5); + } + + reCenter(x:number,y:number) { + this.sprite.setOrigin(x,y); + this.tdisplay.setOrigin(x,y); + } + + setValue(data: string){ + this.value = data; + this.tdisplay.setText(this.value); + } + + setIndex(i: number){ + this.index = i; + } + + turnOff(){ + this.disabled = true; + this.resetState(); + } + + turnOn(){ + this.disabled = false; + this.resetState(); + } + + resetState(){ + this.tdisplay.setColor("white"); + this.sprite.setFrame(0); + } + + onDown( + pointer: Phaser.Input.Pointer, + localX: number, + localY: number, + event: Phaser.Types.Input.EventData + ) { + if (!this.disabled) { + super.onDown(pointer, localX, localY, event); + this.tdisplay.setColor("green"); + this.sprite.setFrame(1); + } + } + onUp( + pointer: Phaser.Input.Pointer, + localX: number, + localY: number, + event: Phaser.Types.Input.EventData + ) { + if (!this.disabled) { + super.onUp(pointer, localX, localY, event); + this.tdisplay.setColor("white"); + this.sprite.setFrame(0); + } + } +} diff --git a/src/components/elements/ToggleButton.ts b/src/components/elements/ToggleButton.ts new file mode 100644 index 0000000..c89e0be --- /dev/null +++ b/src/components/elements/ToggleButton.ts @@ -0,0 +1,27 @@ +import { BaseScene } from "@/scenes/BaseScene"; +import { Button } from "./Button"; + +export class ToggleButton extends Button{ + public scene:BaseScene; + public spr:Phaser.GameObjects.Sprite + public toggled: boolean = false; + constructor(scene:BaseScene,x:number,y:number,spr:string){ + super(scene,x,y); + this.scene=scene; + this.spr=new Phaser.GameObjects.Sprite(this.scene,0,0,spr,0); + this.spr.setOrigin(0.5,0.5); + this.bindInteractive(this.spr); + this.add(this.spr); + } + + toggleForward(){ + this.toggled = true; + this.spr.setFrame(1); + } + + toggleBackward(){ + this.toggled = false; + this.spr.setFrame(0); + } + +} \ No newline at end of file diff --git a/src/scenes/GameScene.ts b/src/scenes/GameScene.ts index 88d10c7..c73f22c 100644 --- a/src/scenes/GameScene.ts +++ b/src/scenes/GameScene.ts @@ -4,8 +4,22 @@ import { Employee } from "@/components/Employee"; import { Customer } from "@/components/Customer"; import { Station } from "@/components/Station"; import { UI } from "@/components/UI"; -import { Overlay } from "@/components/Overlay"; import { StationId, StationType } from "@/components/StationData"; +import { Inventory } from "@/components/Inventory"; +import { SimpleButton } from "@/components/elements/SimpleButton"; +import { ToggleButton } from "@/components/elements/ToggleButton"; +import { ItemButton } from "@/components/ItemButton"; +import { ItemHandler } from "@/components/ItemHandler"; +import { UpgradeOverlay } from "@/components/UpgradeOverlay"; +import { SummaryOverlay } from "@/components/SummaryOverlay"; +import { EmployeeId } from "@/components/EmployeeData"; +import { BlockType, LevelData, LevelId } from "@/components/Levels"; + +enum GameState { + Cutscene, + Day, + Shopping, +} export class GameScene extends BaseScene { private background: Phaser.GameObjects.Image; @@ -14,15 +28,21 @@ export class GameScene extends BaseScene { private employees: Employee[]; private customers: Customer[]; private ui: UI; - private overlay: Overlay; + private upgradeOverlay: UpgradeOverlay; + private summaryOverlay: SummaryOverlay; private paused: boolean = false; private browsing: boolean = false; + private inventory: Inventory; + private invButton: ToggleButton; + private iHandler: ItemHandler; + public activeItem: ItemButton; // Game stats - private day: number = 0; - private dayDuration: number = 60000; // 1 minute - private timeOfDay: number = 0; - private money: number = 0; + public state: GameState = GameState.Cutscene; + public day: number = 0; + public dayDuration: number = 60000; // 1 minute + public timeOfDay: number = 0; + public money: number = 0; constructor() { super({ key: "GameScene" }); @@ -34,52 +54,97 @@ export class GameScene extends BaseScene { this.input.addPointer(2); this.input.dragDistanceThreshold = 10; - this.background = this.add.image(0, 0, "background"); + this.background = this.add.image(0, 0, "grid1"); this.background.setOrigin(0); this.fitToScreen(this.background); - this.board = new Board(this, 930, 550, 8, 6); + this.board = new Board(this, this.CX, this.CY, 6, 4); this.stations = []; - this.addStation(0, 0, StationId.WaitingSeatTier1); - this.addStation(0, 1, StationId.WaitingSeatTier2); - this.addStation(0, 2, StationId.WaitingSeatTier3); - this.addStation(2, 2, StationId.HornAndNailsTier1); - this.addStation(3, 2, StationId.HornAndNailsTier2); - this.addStation(4, 2, StationId.HornAndNailsTier3); - this.addStation(2, 0, StationId.HornAndNailsTier1); - this.addStation(3, 0, StationId.HornAndNailsTier2); - this.addStation(4, 0, StationId.HornAndNailsTier3); - this.addStation(5, 1, StationId.ScalePolishTier1); - this.addStation(6, 1, StationId.ScalePolishTier2); - this.addStation(7, 1, StationId.ScalePolishTier3); - this.addStation(5, 3, StationId.GoldBathTier1); - this.addStation(6, 3, StationId.GoldBathTier2); - this.addStation(7, 3, StationId.GoldBathTier3); - this.addStation(5, 5, StationId.CashRegister); + // this.addStation(0, 0, StationId.WaitingSeatTier1); + // this.addStation(0, 1, StationId.WaitingSeatTier2); + // this.addStation(0, 2, StationId.WaitingSeatTier3); + // this.addStation(2, 2, StationId.HornAndNailsTier1); + // this.addStation(3, 2, StationId.HornAndNailsTier2); + // this.addStation(4, 2, StationId.HornAndNailsTier3); + // this.addStation(2, 0, StationId.HornAndNailsTier1); + // this.addStation(3, 0, StationId.HornAndNailsTier2); + // this.addStation(4, 0, StationId.HornAndNailsTier3); + // this.addStation(5, 1, StationId.ScalePolishTier1); + // this.addStation(6, 1, StationId.ScalePolishTier2); + // this.addStation(7, 1, StationId.ScalePolishTier3); + // this.addStation(5, 3, StationId.GoldBathTier1); + // this.addStation(6, 3, StationId.GoldBathTier2); + // this.addStation(7, 3, StationId.GoldBathTier3); + // this.addStation(5, 5, StationId.CashRegister); this.employees = []; - this.addEmployee(0, 5); - this.addEmployee(1, 5); - this.addEmployee(2, 5); - this.addEmployee(3, 5); + // this.addEmployee(0, 5, EmployeeId.RaccoonTier1); + // this.addEmployee(1, 5, EmployeeId.RaccoonTier1); + // this.addEmployee(2, 5, EmployeeId.RaccoonTier1); + // this.addEmployee(3, 5, EmployeeId.HumanTier1); this.customers = []; - this.addCustomer(); - this.addCustomer(); - this.addCustomer(); this.ui = new UI(this); this.ui.setDepth(1000); - - this.overlay = new Overlay(this); - this.overlay.setVisible(false); - this.overlay.setDepth(1001); - this.overlay.on("progress", () => { - this.overlay.setVisible(false); + this.iHandler = new ItemHandler(this); + + this.inventory = new Inventory(this,-650,0,[4,5,2,6,3,0,0,0,0,0,0,0,0]); + this.invButton = new ToggleButton(this,64,540,"invbutton"); + this.add.existing(this.invButton); + this.invButton.on("click", ()=> {this.toggleInventory()}); + this.inventory.setDepth(10); + this.invButton.setDepth(9); + this.invButton.setAlpha(0.75); + this.activeItem = new ItemButton(this,-500, -500, this.inventory, -1, -100, "blankspr"); + this.ui.setMoney(this.money); + this.ui.setDay(this.day); + this.ui.on("nextDay", () => { this.startDay(); }); + this.upgradeOverlay = new UpgradeOverlay(this); + this.upgradeOverlay.setDepth(1010); + this.upgradeOverlay.on("upgradeStation", (station: Station) => { + this.money -= station.upgradeCost; + this.ui.setMoney(this.money); + station.upgrade(); + this.upgradeOverlay.selectStation(station); + }); + this.upgradeOverlay.on("upgradeEmployee", (employee: Employee) => { + this.money -= employee.upgradeCost; + this.ui.setMoney(this.money); + employee.upgrade(); + this.upgradeOverlay.selectEmployee(employee); + }); + + this.summaryOverlay = new SummaryOverlay(this); + this.summaryOverlay.setDepth(1020); + this.summaryOverlay.on("progress", () => { + this.summaryOverlay.setVisible(false); + }); + + /* Init */ + + // TEMPORARY: Spawn customers every 5 seconds, if allowed + this.time.addEvent({ + delay: 5000, + callback: () => { + // Spawn new customer if shop is still open + if ( + this.state == GameState.Day && + this.timeOfDay > 0 && + this.getAvailableWaitingSeat() + ) { + this.addCustomer(); + } + }, + loop: true, + }); + + // this.setState(GameState.Shopping); + this.loadLevel(LevelId.Level1); this.startDay(); } @@ -89,14 +154,91 @@ export class GameScene extends BaseScene { } this.stations.forEach((s) => s.update(time, delta)); this.employees.forEach((e) => e.update(time, delta)); - this.customers.forEach((c) => c.update(time, delta)); + this.customers.forEach((x) => x.update(time, delta)); this.ui.update(time, delta); - this.overlay.update(time, delta); + this.summaryOverlay.update(time, delta); + this.activeItem.update(time,delta); + if(this.activeItem.state == 3){ + this.snapItem(); + } + this.upgradeOverlay.update(time, delta); + + // Depth sorting hack + if (this.state === GameState.Day) { + this.stations.forEach((s) => s.setDepth(s.y / 100 + 0)); + this.employees.forEach((e) => e.setDepth(e.y / 100 + 1)); + this.customers.forEach((c) => + c.setDepth(c.y / 100 + (c.dragged ? 100 : 1)) + ); + } + } + + // Set game state + setState(state: GameState) { + this.state = state; + + const isShopping = state === GameState.Shopping; + + this.stations.forEach((s) => s.setClickable(isShopping)); + this.employees.forEach((e) => e.setClickable(isShopping)); + this.ui.setShoppingMode(isShopping); + if (isShopping) this.summaryOverlay.open(); + } + + // Load level data + loadLevel(id: LevelId) { + const level = LevelData[id]; + + this.background.setTexture(level.background); + this.board.resize(level.width, level.height); + + // Clear all stations, employees, and customers + this.stations.forEach((s) => s.destroy()); + this.employees.forEach((e) => e.destroy()); + this.customers.forEach((c) => c.destroy()); + this.stations = []; + this.employees = []; + this.customers = []; + + // Load level data items + for (let y = 0; y < level.height; y++) { + for (let x = 0; x < level.width; x++) { + const gridX = x; + const gridY = y; + const block = level.grid[y][x]; + + switch (block) { + case BlockType.Empty: + break; + case BlockType.Wall: + break; + case BlockType.WaitingSeat: + this.addStation(gridX, gridY, StationId.WaitingSeatTier1); + break; + case BlockType.HornAndNails: + this.addStation(gridX, gridY, StationId.HornAndNailsTier1); + break; + case BlockType.ScalePolish: + this.addStation(gridX, gridY, StationId.ScalePolishTier1); + break; + case BlockType.GoldBath: + this.addStation(gridX, gridY, StationId.GoldBathTier1); + break; + case BlockType.CashRegister: + this.addStation(gridX, gridY, StationId.CashRegister); + break; + case BlockType.Employee: + this.addEmployee(gridX, gridY, EmployeeId.RaccoonTier1); + break; + } + } + } } // Start a new day startDay() { + this.setState(GameState.Day); this.day += 1; this.ui.setDay(this.day); @@ -113,17 +255,11 @@ export class GameScene extends BaseScene { }, }); - // Spawn customers every 3 seconds - this.time.addEvent({ - delay: 3000, - callback: () => { - // Spawn new customer if shop is still open - if (this.timeOfDay > 0 && this.getAvailableWaitingSeat()) { - this.addCustomer(); - } - }, - loop: true, - }); + // Reset depth + this.stations.forEach((s) => s.setDepth(0)); + this.employees.forEach((e) => e.setDepth(0)); + + this.addCustomer(); } endDay() {} @@ -149,6 +285,16 @@ export class GameScene extends BaseScene { customer.nextActivity(); } }); + + // Station clicked during shopping + station.on("click", () => { + if (this.state === GameState.Shopping && !this.upgradeOverlay.visible) { + this.upgradeOverlay.selectStation(station); + + this.stations.forEach((s) => s.setDepth(0)); + station.setDepth(2000); + } + }); } openInventory() { @@ -156,9 +302,9 @@ export class GameScene extends BaseScene { } // Add new employee - addEmployee(gridX: number, gridY: number) { + addEmployee(gridX: number, gridY: number, id: EmployeeId) { const coord = this.board.gridToCoord(gridX, gridY); - const employee = new Employee(this, coord.x, coord.y); + const employee = new Employee(this, coord.x, coord.y, id); this.employees.push(employee); // Employee reached the destination @@ -175,6 +321,16 @@ export class GameScene extends BaseScene { employee.setCustomer(null); } }); + + // Employee clicked during shopping + employee.on("click", () => { + if (this.state === GameState.Shopping && !this.upgradeOverlay.visible) { + this.upgradeOverlay.selectEmployee(employee); + + this.employees.forEach((e) => e.setDepth(0)); + employee.setDepth(2000); + } + }); } // Add new customer @@ -245,7 +401,7 @@ export class GameScene extends BaseScene { // Open overlay if no more customers if (this.customers.length === 0) { - this.overlay.setVisible(true); + this.setState(GameState.Shopping); } }); @@ -317,8 +473,8 @@ export class GameScene extends BaseScene { const { gridX, gridY } = this.board.coordToGrid(station.x, station.y); const { x, y } = this.board.gridToCoord(gridX, gridY - 1); - customer.setEmployee(closestEmployee); customer.setRequest(null); + customer.setEmployee(closestEmployee); closestEmployee.setCustomer(customer); closestEmployee.walkTo(x, y); @@ -352,4 +508,75 @@ export class GameScene extends BaseScene { customer.requestedStation = activities[0]; customer.nextActivity(); } + + toggleInventory(){ + this.inventory.toggle(); + if(this.inventory.isOpen) { + this.invButton.setPosition(714,540); + this.invButton.toggleForward(); + } else { + this.invButton.setPosition(64,540); + this.invButton.toggleBackward(); + } + } + + setActiveItem(i: ItemButton){ + this.activeItem.destroy(); + this.activeItem = i; + this.activeItem.on("itemdrop", () => { + this.cleanUpItem(); + }); + + this.add.existing(this.activeItem); + //new ItemButton(this,-500, -500, this.inventory, -1, -100, "blankspr"); + } + + parseItems(i: number, st: Station, c: Customer){ + this.iHandler.process(this.inventory.itemList[i], st,c); + } + + snapItem() { + let s = this.getClosestStationToItem(this.activeItem); + if(s) { + this.activeItem.snapTo(s.x,s.y); + } + } + + cleanUpItem(){ + let s = this.getClosestStationToItem(this.activeItem); + if(s) { + s.applyItem(this.activeItem.id,this.activeItem.sprname); + this.sound.play("place"); + } else { + this.inventory.returnItem(this.activeItem.id); + this.sound.play("return"); + } + this.activeItem.destroy(); + this.activeItem = new ItemButton(this,-500, -500, this.inventory, -1, -100, "blankspr"); + } + + getClosestStationToItem(item: ItemButton): Station | null { + let closestStation = null; + let closestDistance = Infinity; + const maxDistance = 75; + + this.stations.forEach((station) => { + const distance = Phaser.Math.Distance.Between( + item.dragX, + item.dragY, + station.x, + station.y + ); + if ( + !station.currentCustomer && + distance < closestDistance && + distance < maxDistance && + station.appliedItems.length < 3 + ) { + closestStation = station; + closestDistance = distance; + } + }); + return closestStation; + } } diff --git a/src/scenes/GlobalVariables.ts b/src/scenes/GlobalVariables.ts new file mode 100644 index 0000000..8290f7a --- /dev/null +++ b/src/scenes/GlobalVariables.ts @@ -0,0 +1,21 @@ +export class GlobalVariables +{ + + + + constructor (){ + + } + + save(){ + + } + + addItem(){ + + } + + reset(){ + + } +} \ No newline at end of file