From 7463873fd5c18fd11a140cb6fcc871574cf5b003 Mon Sep 17 00:00:00 2001 From: alesan99 Date: Wed, 21 Feb 2024 21:00:26 -0600 Subject: [PATCH] Add basic pet interaction Change player mouse controls (movement) Fix missing images --- website/assets/areas/chictoriassecret.json | 4 +- website/game/menu/pet.js | 54 ++++++++++++++++++++++ website/game/menu/quests.js | 1 - website/game/objects/character.js | 3 ++ website/game/objects/pet.js | 47 ++++++++++++++++--- website/game/objects/player.js | 50 +++++++++++++++++--- website/game/shape.js | 17 +++++++ website/game/world.js | 12 ++++- website/index.html | 5 +- 9 files changed, 173 insertions(+), 20 deletions(-) create mode 100644 website/game/menu/pet.js diff --git a/website/assets/areas/chictoriassecret.json b/website/assets/areas/chictoriassecret.json index e40a882..4aaa7a5 100644 --- a/website/assets/areas/chictoriassecret.json +++ b/website/assets/areas/chictoriassecret.json @@ -71,9 +71,9 @@ "id": "tutorial", "text": [ "You're like new around here aren't you?", - "Whenever you see a chicken like me (except theres no-one like me) you can buy stuff using nuggets.", + "Whenever you see a chicken like me, you can buy stuff using nuggets.", "You can earn nuggets by playing games in the Arcade or completing quests given to you by chickens.", - "Now buy some new clothes, it's embarrasing talking to you when you look like that." + "Now buy some new clothes, it's embarrassing talking to you when you look like that." ], "condition": { "quest": "tutorial", diff --git a/website/game/menu/pet.js b/website/game/menu/pet.js new file mode 100644 index 0000000..dee8201 --- /dev/null +++ b/website/game/menu/pet.js @@ -0,0 +1,54 @@ +// Pet menu; Shows your pet's status + +MENUS["petMenu"] = new class extends Menu { + //Initialize + constructor () { + super(234,104, 560,350) + } + + load (config) { + this.openTimer = 0 + + this.buttons = {} + } + + keyPress(key) { + } + + keyRelease(key) { + } + + mouseClick(button, x, y) { + let clicked = super.mouseClick(button, x, y) + if (!clicked) { + closeMenu() + } + return clicked + } + + mouseRelease(button, x, y) { + return super.mouseRelease(button, x, y) + } + + draw() { + // Window + let scale = 1 + if (this.openTimer < 1) { + scale = easing("easeOutBack", this.openTimer) + } + DRAW.image(IMG.menu, null, this.x+this.w*0.5, this.y+this.h*0.5, 0, scale, scale, 0.5, 0.5) + + DRAW.setColor(112, 50, 16, scale) + DRAW.setFont(FONT.caption) + DRAW.text("Pet", 512, this.y+38, "center") + + // Render all buttons + this.drawButtons() + } + + update(dt) { + this.openTimer = Math.min(1, this.openTimer + 4*dt) + + this.updateButtons(dt) + } +}() \ No newline at end of file diff --git a/website/game/menu/quests.js b/website/game/menu/quests.js index a4c4f04..34125c6 100644 --- a/website/game/menu/quests.js +++ b/website/game/menu/quests.js @@ -42,7 +42,6 @@ MENUS["questsMenu"] = new class extends Menu { // Text DRAW.setColor(112, 50, 16, scale) DRAW.setFont(FONT.caption) - //DRAW.text("Connected Players", 512, 142, "center") DRAW.text("Quests", 512, this.y+38, "center") let y = this.y+100 diff --git a/website/game/objects/character.js b/website/game/objects/character.js index c2030a0..31bb509 100644 --- a/website/game/objects/character.js +++ b/website/game/objects/character.js @@ -300,7 +300,10 @@ class Character extends PhysicsObject { // Play emote animation; will stop when player moves emote(i) { if (ANIM[i] != null) { + // Reset player animation state this.dir = "down" + this.flip = 1 + // Play emote animation this.anim.playAnimation(ANIM[i][0], ANIM[i][1], 0) if (this == PLAYER) { diff --git a/website/game/objects/pet.js b/website/game/objects/pet.js index 0423163..a78109b 100644 --- a/website/game/objects/pet.js +++ b/website/game/objects/pet.js @@ -7,14 +7,14 @@ class Pet extends PhysicsObject { super(spatialHash,x,y) this.x = x this.y = y - this.w = 20 - this.h = 20 + this.w = 40 + this.h = 30 this.shape = new Shape( - -this.w/2, -this.h/2, - this.w/2, -this.h/2, - this.w/2, this.h/2, - -this.w/2, this.h/2 + -this.w/2, -this.h, + this.w/2, -this.h, + this.w/2, 0, + -this.w/2, 0 ) this.sx = 0 @@ -24,6 +24,16 @@ class Pet extends PhysicsObject { this.id = id this.owner = owner + // Clickable + this.mouseOver = false + this.clickRegion = { + x: -this.w/2, + y: -this.h, + w: this.w, + h: this.h + } + this.activated = false + // Graphics this.image = ITEMS.pet[id].image this.sprite = ITEMS.pet[id].sprite @@ -50,11 +60,20 @@ class Pet extends PhysicsObject { let angle = Math.atan2(ty-this.y, tx-this.x) this.sx = Math.cos(angle)*200 this.sy = Math.sin(angle)*200 + this.activated = false // Temporary, moving will let you click on pet again } else { this.sx = 0 this.sy = 0 } } + + // Click + if ((this.activated == false) && this.checkMouseOver()) { + this.mouseOver = true + CURSOR.on = true + } else { + this.mouseOver = false + } } draw(drawX=this.x, drawY=this.y, dir=this.dir) { @@ -66,6 +85,22 @@ class Pet extends PhysicsObject { DRAW.image(this.image, this.anim.getFrame(), drawX, drawY, 0, this.flip*this.scale, this.scale, 0.5, 1) } + checkMouseOver() { + let [mouseX, mouseY] = getMousePos() + let cr = this.clickRegion + return (mouseX-this.x > cr.x && mouseY-this.y > cr.y && mouseX-this.x < cr.x+cr.w && mouseY-this.y < cr.y+cr.h) + } + + click(button, x, y) { + if (button == 0 && this.mouseOver) { + // Open pet menu + openMenu("petMenu") + this.activated = true + return true + } + return false + } + collide (name, obj, nx, ny) { return false } diff --git a/website/game/objects/player.js b/website/game/objects/player.js index 8d35c5e..e889d75 100644 --- a/website/game/objects/player.js +++ b/website/game/objects/player.js @@ -15,6 +15,10 @@ class Player { } this.mouseHold = false + this.target = false + this.targetX = 0 + this.targetY = 0 + // Which triggers is the player currently inside of? this.triggers = new Map() } @@ -25,19 +29,30 @@ class Player { // Handle movement inputs // If mouse button is being held, the player should be controlled by the mouse - // Otherwise, use arrow key inputs if (this.mouseHold) { let [mx, my] = getMousePos() - let targetX = mx-char.x - let targetY = my-char.y + 20 + this.target = true + this.targetX = mx + this.targetY = my + } + if (this.target) { + let targetX = this.targetX + let targetY = this.targetY + 20 + let targetDiffX = targetX - char.x + let targetDiffY = targetY - char.y + + let [dx, dy] = vec2Unit(targetDiffX, targetDiffY) //convert to direction normal + let futureX = char.x + dx*char.speed*dt + let futureY = char.y + dy*char.speed*dt - if ( ((char.x - mx)**2 + (char.y-20 - my)**2) >= char.speed**2*dt ) { // Don't move if already close enough to the target location - let [dx, dy] = vec2Unit(targetX, targetY) //convert to direction normal - this.obj.move(dx, dy) + if ((((targetX-futureX > 0) != (targetX-char.x > 0)) || ((targetY-futureY > 0) != (targetY-char.y > 0)))) { // Don't move anymore if crossing target coordinate + this.target = false + char.move(0, 0) } else { - this.obj.move(0, 0) + char.move(dx, dy) } + // Otherwise, use arrow key inputs } else { let dx = 0 let dy = 0 @@ -82,15 +97,19 @@ class Player { // Movement case "ArrowLeft": this.arrowKeys.left = true + this.target = false break case "ArrowUp": this.arrowKeys.up = true + this.target = false break case "ArrowRight": this.arrowKeys.right = true + this.target = false break case "ArrowDown": this.arrowKeys.down = true + this.target = false break case " ": this.interact() @@ -118,6 +137,23 @@ class Player { } } + // Reset state of player and player controller when moving to new area + reset(x, y, dir="down") { + let char = this.obj + // Teleport character + char.setPosition(x, y) + char.dir = dir + char.flip = 1 + + // Also teleport pet + if (char.pet) { + char.petObj.setPosition(x, y) + } + + // Stop movement + this.target = false + } + mouseClick(button, x, y) { // Movement // Check if left mouse button is being held diff --git a/website/game/shape.js b/website/game/shape.js index 11feacc..8adc595 100644 --- a/website/game/shape.js +++ b/website/game/shape.js @@ -37,4 +37,21 @@ class Shape { this.w = this.x2-this.x1 this.h = this.y2-this.y1 } + + // Check if point is inside shape + checkInside(x, y) { + if (!(x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2)) { + return false // Not inside bounding box; don't bother checking actual shape + } + for (let i = 0; i < this.v.length; i+= 2) { + let [vx, vy] = [this.v[i], this.v[i+1]] + let [vx2, vy2] = [this.v[(i+2)%this.v.length], this.v[(i+3)%this.v.length]] + let [nx, ny] = vec2Norm(vx2-vx, vy2-vy) + let [px, py] = [x-vx, y-vy] + if (vec2Dot(nx, ny, px, py) > 0) { + return false + } + } + return true + } } diff --git a/website/game/world.js b/website/game/world.js index 6779c37..ee46b0d 100644 --- a/website/game/world.js +++ b/website/game/world.js @@ -59,7 +59,9 @@ class World { this.oldArea = this.area this.area = area + // Transport player to new area PLAYER.area = this.area + PLAYER_CONTROLLER.reset(canvasWidth/2, canvasHeight/2, "down") // Clear any uneeded objects for (const [name, npc] of Object.entries(NPCS)) { @@ -111,8 +113,7 @@ class World { // Get spawn location for (const [i, obj] of Object.entries(OBJECTS["Warp"])) { if ((obj.fromWarp && obj.fromWarp == fromWarp) || (obj.fromArea && obj.fromArea == this.fromArea)) { - PLAYER.setPosition(obj.frontx, obj.fronty+PLAYER.shape.h/2) - PLAYER.dir = obj.facing + PLAYER_CONTROLLER.reset(obj.frontx, obj.fronty+PLAYER.shape.h/2, obj.facing) } } } @@ -406,6 +407,13 @@ class World { return true } } + + // Pet interaction + for (const [id, obj] of Object.entries(OBJECTS["Pet"])) { + if (obj.click(button, x, y)) { + return true + } + } // Click on click triggers for (const [id, obj] of Object.entries(OBJECTS["Trigger"])) { diff --git a/website/index.html b/website/index.html index 8a12c51..fe7e132 100644 --- a/website/index.html +++ b/website/index.html @@ -5,11 +5,11 @@ Chicken Society - +