From 120e8d70eb38121c2168f1c9e6a508c5f7642356 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 31 Mar 2024 14:44:16 -0700 Subject: [PATCH 1/6] added baby --- js/game/pet.js | 111 +++++++++++++++++++++++++++++++++++++---------- js/game/stage.js | 6 ++- 2 files changed, 93 insertions(+), 24 deletions(-) diff --git a/js/game/pet.js b/js/game/pet.js index 3dd5d3b..eef6ae5 100644 --- a/js/game/pet.js +++ b/js/game/pet.js @@ -1,6 +1,13 @@ //import { GIF } from "../libs/gif.js"; import { GameObject } from './core.js' +const BABY_CORGI = + 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/babycorgi-sprite-128x128.png' +const TEEN_CORGI = + 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/teencorgi-sprite-128x128.png' +const ADULT_CORGI = + 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/corgi-sprite-128x128.png' + // Our sprite sheet is on a grid of 64pxs // Each row is 64px tall, and each frame is 64px wide const SPRITE_SIZE = 128 @@ -47,9 +54,10 @@ export class Pet extends GameObject { super(x, y, height, width) // Pet state this.x = x + this.currentDirection = 'right' + this.height = height this.width = width - this.currentDirection = 'right' this.emote = false this.talk = false @@ -69,16 +77,20 @@ export class Pet extends GameObject { // Assets this.petImage = new Image() this.petImage.src = - 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/corgi-sprite-128x128.png' + 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/babycorgi-sprite-128x128.png' this.textBubble = new Image() this.textBubble.src = 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/text-bubble.png' - /** - * Creates render sprite functions - * - e.g. renderWalk, renderSniff_walk, renderIdle1 - */ + this.age = 0 + } + + /** + * Creates a list of animations from a spritesheet + * - e.g. renderWalk, renderSniff_walk, renderIdle1 + */ + createSpriteAnimations(image, scaleDownBy) { Object.keys(SPRITE_SHEET).forEach((animName) => { // transform name to title case // FUNC1 -> Func1 @@ -89,12 +101,18 @@ export class Pet extends GameObject { const spriteFrames = SPRITE_SHEET[animName].frames const spriteFramesY = SPRITE_SHEET[animName].row this[funcName] = (ctx, renderCount, slowFpsBy = 10) => { - this.renderSprite( + this.renderSpriteAnimation( ctx, - renderCount, - spriteFrames - 1, - spriteFramesY, - slowFpsBy, + image, + { + renderCount, + spriteFrames: spriteFrames - 1, + spriteFramesY, + slowFpsBy, + }, + { + scaleDownBy, + }, ) } }) @@ -242,6 +260,8 @@ export class Pet extends GameObject { // see if objects interact if (this.isTouching(nearestFood)) { + this.age++ + // Eat food nearestFood.delete() this.setEmote() @@ -251,23 +271,28 @@ export class Pet extends GameObject { } } - renderSprite( - ctx, - renderCount, - spriteFrames, - spriteFramesY, - slowFpsBy = 10, // Slows down fps by n amount - ) { + renderSpriteAnimation(ctx, spriteSheet, frameSettings, options) { + const { + renderCount, + spriteFrames, + spriteFramesY, + slowFpsBy: _slowFpsBy, // Slows down fps by n amount + } = frameSettings + + let slowFpsBy = _slowFpsBy || 10 + + const { scaleDownBy } = options + const _spriteFramesY = SPRITE_SIZE * spriteFramesY - const spriteRenderSize = SPRITE_SIZE // This is the final size users see the sprite as + const spriteRenderSize = SPRITE_SIZE / scaleDownBy // This is the final size users see the sprite as ctx.imageSmoothingEnabled = true ctx.imageSmoothingQuality = 'high' // There is 5 frames in the sprite sheet for walking // so instead of doing this.renderCount % 4 (0 - 5 frames), // we do 0 - 50 frames and scale down for a lower image fps. - var _frame = renderCount % (spriteFrames * slowFpsBy) - var frame = Math.round(_frame / slowFpsBy) + const _frame = renderCount % (spriteFrames * slowFpsBy) + const frame = Math.round(_frame / slowFpsBy) const currentRenderFrame = SPRITE_SIZE * frame @@ -279,7 +304,7 @@ export class Pet extends GameObject { ctx.save() ctx.scale(-1, 1) ctx.drawImage( - this.petImage, + spriteSheet, currentRenderFrame, _spriteFramesY, SPRITE_SIZE, @@ -292,7 +317,7 @@ export class Pet extends GameObject { ctx.restore() } else { ctx.drawImage( - this.petImage, + spriteSheet, currentRenderFrame, _spriteFramesY, SPRITE_SIZE, @@ -352,4 +377,44 @@ export class Pet extends GameObject { ctx.fillText(this.talkText, textX, textY) } } + + render(ctx, renderCount) { + switch (this.age) { + case 0: + this.petImage.src = BABY_CORGI + this.scaleDownBy = 1.5 + + break + case 1: + this.petImage.src = TEEN_CORGI + this.scaleDownBy = 1.2 + + break + case 2: + this.petImage.src = ADULT_CORGI + this.scaleDownBy = 1 + + break + } + + //height = this.height / this.scaleDownBy + //width = this.width / this.scaleDownBy + this.createSpriteAnimations(this.petImage, this.scaleDownBy) + + // render emote + if (this.emote) { + ctx.fillStyle = 'blue' + ctx.font = '10px Arial' + ctx.fillText('❤️', this.x + this.width, this.y) + } + + // render emote + if (this.talk) { + this.renderTextBubble(ctx) + } + + // move the pet + this._showHitBox(ctx) + this.move(ctx, renderCount) + } } diff --git a/js/game/stage.js b/js/game/stage.js index e51edca..11fcac2 100644 --- a/js/game/stage.js +++ b/js/game/stage.js @@ -332,7 +332,10 @@ export class ComfyPetsStage extends ComfyNode { pet.currentDirection = 'right' } + pet.render(ctx, this.renderCount) + // render emote + /* if (pet.emote) { ctx.fillStyle = 'blue' ctx.font = '10px Arial' @@ -345,8 +348,9 @@ export class ComfyPetsStage extends ComfyNode { } // move the pet - //pet._showHitBox(ctx) + pet._showHitBox(ctx) pet.move(ctx, this.renderCount) + */ } } From d4e50d4fe46fbccf638be9a4feece71120c0c3a2 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 31 Mar 2024 15:08:21 -0700 Subject: [PATCH 2/6] persists pet --- custom_routes.py | 28 ++++++++++++++++++++++++++++ js/apiClient.js | 29 +++++++++++++++++++++++++++++ js/game/pet.js | 17 ++++++++++++++++- persistence/__init__.py | 21 +++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) diff --git a/custom_routes.py b/custom_routes.py index 0e84c79..9e92c34 100644 --- a/custom_routes.py +++ b/custom_routes.py @@ -46,3 +46,31 @@ async def comfy_pets_update_inventory(request): print("Error:", e) return web.json_response({ "error": str(e) }, status=400) + +@server.PromptServer.instance.routes.get("/comfy-pets/pets") +async def comfy_pets_get_pet(request): + try: + data = persistence.get_current_pet() + return web.json_response({ + "pet": data + }, content_type='application/json') + except Exception as e: + print("Error:", e) + return web.json_response({ "error": e }, status=400) + +@server.PromptServer.instance.routes.post("/comfy-pets/pets/age") +async def comfy_pets_pets_age(request): + try: + data = await request.json() + age = data.get("age") + + persistence.update_pet_age(age) + + return web.json_response({ + "message": "Pet age updated successfully" + }, content_type='application/json') + + except Exception as e: + print("Error:", e) + return web.json_response({ "error": str(e) }, status=400) + diff --git a/js/apiClient.js b/js/apiClient.js index 71e1fdb..c089bf3 100644 --- a/js/apiClient.js +++ b/js/apiClient.js @@ -74,6 +74,35 @@ export const setUserNewInventory = async (inventory) => { } } +export const setPetAge = async (age) => { + try { + const url = '/comfy-pets/pets/age' + const data = { + age, + } + const requestOptions = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), // Convert the data to JSON format + } + await fetch(url, requestOptions).then((x) => x.json()) + } catch (e) { + throw new Error('Something went wrong') + } +} + +export const getCurrentPet = async () => { + const url = '/comfy-pets/pets' + const { pet } = await fetchWithCache(url) + let parsedUserData = { + ...pet, + ['age']: parseInt(pet.age), + } + return parsedUserData +} + export async function ping() { const user = await getCurrentUser() const userId = user?.user_id diff --git a/js/game/pet.js b/js/game/pet.js index eef6ae5..e9c4bac 100644 --- a/js/game/pet.js +++ b/js/game/pet.js @@ -1,5 +1,6 @@ //import { GIF } from "../libs/gif.js"; import { GameObject } from './core.js' +import { getCurrentPet, setPetAge } from '../apiClient.js' const BABY_CORGI = 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/babycorgi-sprite-128x128.png' @@ -84,6 +85,15 @@ export class Pet extends GameObject { 'https://comfyui-output.nyc3.cdn.digitaloceanspaces.com/text-bubble.png' this.age = 0 + this._initializePet() + } + + async _initializePet() { + const petData = await getCurrentPet() + + for (const key in petData) { + this[key] = petData[key] + } } /** @@ -118,6 +128,11 @@ export class Pet extends GameObject { }) } + grow() { + this.age++ + setPetAge(this.age) + } + _chooseRandomDirection() { const directions = ['left', 'right', 'idle1', 'idle2'] @@ -260,7 +275,7 @@ export class Pet extends GameObject { // see if objects interact if (this.isTouching(nearestFood)) { - this.age++ + this.grow() // Eat food nearestFood.delete() diff --git a/persistence/__init__.py b/persistence/__init__.py index aacf9d8..d2a66fb 100644 --- a/persistence/__init__.py +++ b/persistence/__init__.py @@ -6,6 +6,7 @@ current_dir = os.path.dirname(os.path.abspath(__file__)) data_path = os.path.join(current_dir, ".dat") u_path = os.path.join(data_path, "u") +p_path = os.path.join(data_path, "p") def set_user_id(): if not os.path.exists(data_path): @@ -50,3 +51,23 @@ def update_balance(balance): def update_inventory(inventory): with dbm.open(u_path, 'w') as db: db[b'inventory'] = str(inventory).encode('utf-8') + +def update_pet_age(age): + with dbm.open(p_path, 'w') as db: + db[b'age'] = str(age).encode('utf-8') + +def get_current_pet(): + pet = {} + if not os.path.exists(data_path): + os.makedirs(data_path) + with dbm.open(p_path, 'c') as db: + # Check if user exists + if b'age' not in db: + db[b'age'] = str(0).encode('utf-8') + + # return data + for key in db.keys(): + pet[key.decode('utf-8')] = db[key].decode('utf-8') + + return pet + From 43892f5caab31ce9dfc9b0af42c6813846f22708 Mon Sep 17 00:00:00 2001 From: dennistruong Date: Sun, 31 Mar 2024 15:08:39 -0700 Subject: [PATCH 3/6] added: hitbox size adapts based on age --- js/game/pet.js | 4 ++++ js/game/stage.js | 12 ++++++------ js/utils.js | 11 +++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/js/game/pet.js b/js/game/pet.js index eef6ae5..3f4bb8e 100644 --- a/js/game/pet.js +++ b/js/game/pet.js @@ -86,6 +86,10 @@ export class Pet extends GameObject { this.age = 0 } + /** + * Returns size of pet depending on age + */ + /** * Creates a list of animations from a spritesheet * - e.g. renderWalk, renderSniff_walk, renderIdle1 diff --git a/js/game/stage.js b/js/game/stage.js index 11fcac2..56dff49 100644 --- a/js/game/stage.js +++ b/js/game/stage.js @@ -1,6 +1,6 @@ import { ComfyNode } from '../comfy/comfy.js' import { gameDialog } from '../comfy/ui.js' -import { getRandomNumber } from '../utils.js' +import { getPetSize, getRandomNumber } from '../utils.js' import { Pet } from './pet.js' import { Food } from './food.js' import { container } from './shop/index.js' @@ -136,14 +136,14 @@ export class ComfyPetsStage extends ComfyNode { addPet() { const height = this.size[1] - const petWidth = 75 - const petHeight = 60 + const spawnAge = 0 + const petSize = getPetSize(spawnAge) const pet = new Pet({ x: 0, - y: height - petHeight, - width: petWidth, - height: petHeight, + y: height - petSize.height, + width: petSize.width, + height: petSize.height, }) this.pets.push(pet) diff --git a/js/utils.js b/js/utils.js index 9f71458..c082206 100644 --- a/js/utils.js +++ b/js/utils.js @@ -40,3 +40,14 @@ export function generateId() { return gameId } + +export function getPetSize(age) { + switch (age) { + case 0: + return { width: 45, height: 35 } + case 1: + return { width: 65, height: 50 } + case 2: + return { width: 75, height: 60 } + } +} From f49e6bd61fd293033469f033e0d83d749d197386 Mon Sep 17 00:00:00 2001 From: dennistruong Date: Sun, 31 Mar 2024 15:09:36 -0700 Subject: [PATCH 4/6] fix: removes comment --- js/game/pet.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/game/pet.js b/js/game/pet.js index 3f4bb8e..eef6ae5 100644 --- a/js/game/pet.js +++ b/js/game/pet.js @@ -86,10 +86,6 @@ export class Pet extends GameObject { this.age = 0 } - /** - * Returns size of pet depending on age - */ - /** * Creates a list of animations from a spritesheet * - e.g. renderWalk, renderSniff_walk, renderIdle1 From 2353c046d9bd8ca2348f1fb616169c7aaa50870c Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 31 Mar 2024 15:22:48 -0700 Subject: [PATCH 5/6] Added food consumed --- custom_routes.py | 16 ++++++++++++++++ js/apiClient.js | 19 +++++++++++++++++++ persistence/__init__.py | 4 ++++ 3 files changed, 39 insertions(+) diff --git a/custom_routes.py b/custom_routes.py index 9e92c34..74655cd 100644 --- a/custom_routes.py +++ b/custom_routes.py @@ -74,3 +74,19 @@ async def comfy_pets_pets_age(request): print("Error:", e) return web.json_response({ "error": str(e) }, status=400) +@server.PromptServer.instance.routes.post("/comfy-pets/pets/food-consumed") +async def comfy_pets_pets_age(request): + try: + data = await request.json() + amount = data.get("amount") + + persistence.update_pet_food_consumed(amount) + + return web.json_response({ + "message": "Pet consumed updated successfully" + }, content_type='application/json') + + except Exception as e: + print("Error:", e) + return web.json_response({ "error": str(e) }, status=400) + diff --git a/js/apiClient.js b/js/apiClient.js index c089bf3..8da0e43 100644 --- a/js/apiClient.js +++ b/js/apiClient.js @@ -74,6 +74,25 @@ export const setUserNewInventory = async (inventory) => { } } +export const setPetFoodConsumed = async (amount) => { + try { + const url = '/comfy-pets/pets/food-consumed' + const data = { + amount, + } + const requestOptions = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), // Convert the data to JSON format + } + await fetch(url, requestOptions).then((x) => x.json()) + } catch (e) { + throw new Error('Something went wrong') + } +} + export const setPetAge = async (age) => { try { const url = '/comfy-pets/pets/age' diff --git a/persistence/__init__.py b/persistence/__init__.py index d2a66fb..a7c1121 100644 --- a/persistence/__init__.py +++ b/persistence/__init__.py @@ -55,6 +55,9 @@ def update_inventory(inventory): def update_pet_age(age): with dbm.open(p_path, 'w') as db: db[b'age'] = str(age).encode('utf-8') +def update_pet_food_consumed(amount): + with dbm.open(p_path, 'w') as db: + db[b'food_consumed'] = str(amount).encode('utf-8') def get_current_pet(): pet = {} @@ -64,6 +67,7 @@ def get_current_pet(): # Check if user exists if b'age' not in db: db[b'age'] = str(0).encode('utf-8') + db[b'food_consumed'] = str(0).encode('utf-8') # return data for key in db.keys(): From 08f19adf57fcdab0a3de58691df25603520fcdca Mon Sep 17 00:00:00 2001 From: dennistruong Date: Sun, 31 Mar 2024 16:15:51 -0700 Subject: [PATCH 6/6] hide buttons --- js/comfy/comfy.js | 1 + js/game/buttons.js | 5 +++++ js/game/pet.js | 8 +++++--- js/game/stage.js | 23 +++++++++++++++++------ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/js/comfy/comfy.js b/js/comfy/comfy.js index 5236f58..e1bae76 100644 --- a/js/comfy/comfy.js +++ b/js/comfy/comfy.js @@ -172,6 +172,7 @@ export class Button { this.fontSize = '16' this.fontFamily = 'Arial' this.fontWeight = 'regular' + this.visible = false } inBounds(mouseX, mouseY) { diff --git a/js/game/buttons.js b/js/game/buttons.js index 7c69fc9..8aa580c 100644 --- a/js/game/buttons.js +++ b/js/game/buttons.js @@ -7,9 +7,14 @@ import { darkenHexColor } from '../utils.js' export class BaseComfyPetsButton extends Button { constructor(text, fillColor, textColor) { super(text, fillColor, textColor) + + this.visible = true } render(ctx) { + if (!this.visible) { + return + } // Darken by 10% const buttonFillDark = darkenHexColor(this.backgroundColor, 10) diff --git a/js/game/pet.js b/js/game/pet.js index e9c4bac..5dc78a6 100644 --- a/js/game/pet.js +++ b/js/game/pet.js @@ -90,7 +90,7 @@ export class Pet extends GameObject { async _initializePet() { const petData = await getCurrentPet() - + console.log(petData) for (const key in petData) { this[key] = petData[key] } @@ -129,8 +129,10 @@ export class Pet extends GameObject { } grow() { - this.age++ - setPetAge(this.age) + if (this.age < 2) { + this.age++ + setPetAge(this.age) + } } _chooseRandomDirection() { diff --git a/js/game/stage.js b/js/game/stage.js index 11fcac2..5c3b4d9 100644 --- a/js/game/stage.js +++ b/js/game/stage.js @@ -71,6 +71,7 @@ export class ComfyPetsStage extends ComfyNode { this.gameButtonEndlessRunner.fontWeight = 'bold' this.gameButtonEndlessRunner.fontFamily = 'Courier New' this.gameButtonEndlessRunner.width = 150 + this.gameButtonEndlessRunner.visible = false // Flappy Game this.gameButtonFlappyGame = this.addButton('Play Flappy Dog', {}, () => { @@ -90,6 +91,7 @@ export class ComfyPetsStage extends ComfyNode { this.gameButtonFlappyGame.fontWeight = 'bold' this.gameButtonFlappyGame.fontFamily = 'Courier New' this.gameButtonFlappyGame.width = 150 + this.gameButtonFlappyGame.visible = false // Shop this.shopButton = this.addButton('Shop', {}, () => { @@ -103,6 +105,7 @@ export class ComfyPetsStage extends ComfyNode { this.shopButton.fontSize = 14 this.shopButton.fontWeight = 'bold' this.shopButton.fontFamily = 'Courier New' + this.shopButton.visible = false this.size = [400, 200] @@ -148,17 +151,17 @@ export class ComfyPetsStage extends ComfyNode { this.pets.push(pet) - this.hungerPointsBar = this.addPointBar({ + this.feedLevelBar = this.addPointBar({ x: this.feedButton.x + this.feedButton.width / 4, y: this.feedButton.y + this.feedButton.height + this.gutter, - width: 50, - height: 75, - maxPoints: 10, - label: 'Hunger', + width: 25, + height: 20, + maxPoints: 3, + label: 'Exp', colour: '#aa00ee', associatedId: pet.id, }) - this.guiElements.push(this.hungerPointsBar) + this.guiElements.push(this.feedLevelBar) } addFood() { @@ -307,6 +310,14 @@ export class ComfyPetsStage extends ComfyNode { for (let i = 0; i < this.pets.length; i++) { const pet = this.pets[i] + // Turn on buttons + if (pet.age > 0) { + // Show the game buttons + this.gameButtonEndlessRunner.visible = true + this.gameButtonFlappyGame.visible = true + this.shopButton.visible = true + } + // Delete inactive frames if (!pet.isActive) { this.pets.splice(i, 1)