From 14810f78fdbf1645e9bd6fbdb25613d383a984ed Mon Sep 17 00:00:00 2001 From: Nathan Date: Sat, 9 Mar 2024 19:20:07 -0800 Subject: [PATCH 1/2] Basic --- js/game/core.js | 21 ++++++++++++ js/game/stage.js | 83 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/js/game/core.js b/js/game/core.js index 4e4e0f9..9414306 100644 --- a/js/game/core.js +++ b/js/game/core.js @@ -24,3 +24,24 @@ export class GameObject { this.isActive = false; } } + +export class Button { + constructor(text, fillColor, textColor) { + this.x = 0; + this.y = 0; + this.width = 100; + this.height = 48; + this.id = generateId(); + this.text = text; + this.textColor = textColor; + this.fillColor = fillColor; + } + + inBounds(mouseX, mouseY) { + return !(mouseX < this.x || mouseX > this.x + this.width || mouseY < this.y || mouseY > this.y + this.height); + } + + onClick() { + // implement + } +} diff --git a/js/game/stage.js b/js/game/stage.js index 8d66424..6490f56 100644 --- a/js/game/stage.js +++ b/js/game/stage.js @@ -1,10 +1,17 @@ -import { ComfyNode } from '../comfy/comfy.js'; +import { ComfyNode, app } from '../comfy/comfy.js'; //import { gameDialog } from '../comfy/ui.js'; import { getRandomNumber } from '../utils.js'; +import { Button } from './core.js'; import { Pet } from './pet.js'; import { Food } from './food.js'; //import { startGame } from './endless_runner/index.js'; -import { addFoodEvent } from '../apiClient.js'; +//import { addFoodEvent } from '../apiClient.js'; + +var test = new Button("Hello world", '#eeaa00', '#001122') +test.onClick = () => { + console.log("hello world") +} + /** @@ -16,10 +23,16 @@ export class ComfyPetsStage extends ComfyNode { super() this.title = "Comfy Pet", + /* this.addButton("Feed pet", () => { this.addFood() addFoodEvent() }) + */ + + this.buttons = [ + test + ] /* // @todo @@ -145,12 +158,76 @@ export class ComfyPetsStage extends ComfyNode { ctx.drawImage(this.backgroundImage, 0, 0, width, height); } - renderOnce() { + renderButtons(ctx) { + for (let i = 0; i < this.buttons.length; i++) { + const button = this.buttons[i]; + + ctx.fillStyle = button.fillColor; + ctx.fillRect(button.x, button.y, button.width, button.height); // draw the button text + ctx.fillStyle = button.textColor; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = '25px arial'; + ctx.fillText(button.text, button.x + button.width / 2, button.y + this.button / 2, this.button); + } + } + + /** + * Returns mouse pos relative to this node + */ + getRelativeMousePos() { + const [boundingX, boundingY] = this.getBounding(); + const [mouseX, mouseY] = app.canvas.canvas_mouse; + + const relativeMouseX = mouseX - boundingX; + const relativeMouseY = mouseY - boundingY; + + return [relativeMouseX, relativeMouseY]; + } + + /** + * Checks current mouse position and returns + * whether it is inside the bounding box of this node + */ + isMouseWithinNode() { + const boundingWidth = this.getBounding()[2]; + const boundingHeight = this.getBounding()[3]; + + const [relativeMouseX, relativeMouseY] = this.getRelativeMousePos(); + + if( + relativeMouseX > 0 && + relativeMouseX < boundingWidth && + relativeMouseY > 0 && + relativeMouseY < boundingHeight + ) { + return true; + } else { + return false + } + } + + renderOnce(ctx) { this.addPet() + ctx.canvas.addEventListener('click', ()=>{ + + if(this.isMouseWithinNode()) { + const [mouseX, mouseY] = this.getRelativeMousePos() + for (let i = 0; i < this.buttons.length; i++) { + const button = this.buttons[i]; + if(button.inBounds(mouseX, mouseY)) { + button.onClick() + } + } + } + }); + } render(ctx) { + this.renderBackground(ctx) + this.renderButtons(ctx) this.renderFoods(ctx) this.renderPets(ctx) // render pet onto canvas } From 848fd76e8dc29c1093ce3867280a6190df015b9a Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 10 Mar 2024 18:27:57 -0700 Subject: [PATCH 2/2] Added stylized buttons --- js/comfy/comfy.js | 121 ++++++++++++++++++++++++++++++++++++++++++++- js/game/buttons.js | 88 +++++++++++++++++++++++++++++++++ js/game/core.js | 20 -------- js/game/stage.js | 117 ++++++++++++------------------------------- js/utils.js | 23 +++++++++ 5 files changed, 261 insertions(+), 108 deletions(-) create mode 100644 js/game/buttons.js diff --git a/js/comfy/comfy.js b/js/comfy/comfy.js index 9b106b7..e094ba0 100644 --- a/js/comfy/comfy.js +++ b/js/comfy/comfy.js @@ -25,6 +25,8 @@ export class ComfyNode extends LiteGraph.LGraphNode { this.isVirtualNode = true; this.renderCount = 0; + + this.buttons = [] } /** @@ -37,6 +39,7 @@ export class ComfyNode extends LiteGraph.LGraphNode { } this.render(ctx) + this.renderButtons(ctx) // This animation loop renders frames // continuously, not only when mouse moves. @@ -53,17 +56,71 @@ export class ComfyNode extends LiteGraph.LGraphNode { this.renderCount++; } + /** + * Returns mouse pos relative to this node + * @note - the Y is wrong for this because it doesn't + * take into account the node's header + */ + getRelativeMouseWithinNode() { + const [boundingX, boundingY, boundingWidth, boundingHeight] = this.getBounding(); + const [mouseX, mouseY] = app.canvas.canvas_mouse; + + // Litegraph node header size + var font_size = LiteGraph.DEFAULT_GROUP_FONT_SIZE || 24; + var height = font_size * 1.4; + + const relativeMouseX = mouseX - boundingX; + const relativeMouseY = mouseY - boundingY; + + // is mouse within node? + if( + relativeMouseX > 0 && + relativeMouseX < boundingWidth && + relativeMouseY > 0 && + relativeMouseY < boundingHeight + ) { + return [relativeMouseX, relativeMouseY - height]; + } else { + return false + } + } + + renderButtons(ctx) { + for (let i = 0; i < this.buttons.length; i++) { + const button = this.buttons[i]; + button.render(ctx) + + } + } + + onMouseDown() { + const [mouseX, mouseY] = this.getRelativeMouseWithinNode() + + for (let i = 0; i < this.buttons.length; i++) { + const button = this.buttons[i]; + if(button.inBounds(mouseX, mouseY)) { + button.onClick() + } + } + } + /** * Add a button to the ComfyUI node */ - addButton(buttonText, callback) { - this.addWidget("button", buttonText, "image", callback) + addButton(buttonText, options, callback) { + //this.addWidget("button", buttonText, "image", callback) + var b = new Button("Hello world", '#eeaa00', '#001122') + b.onClick = callback + this.buttons.push(b) + + return b; } /** * Only renders when the user moves their mouse */ + // eslint-disable-next-line render(ctx) { // This function renders a single frame. It is called // every time you move your mouse @@ -72,9 +129,69 @@ export class ComfyNode extends LiteGraph.LGraphNode { /** * Renders on init */ + // eslint-disable-next-line renderOnce(ctx) { // This function renders a single frame when the node // is initialized } } +export class Button { + constructor(text, fillColor, textColor) { + this.x = 0; + this.y = 0; + this.width = 100; + this.height = 48; + this.text = text; + this.color = textColor; + this.fillColor = fillColor; + + this.fontSize = "16"; + this.fontFamily = "Arial"; + this.fontWeight = "regular"; + } + + inBounds(mouseX, mouseY) { + return !(mouseX < this.x || mouseX > this.x + this.width || mouseY < this.y || mouseY > this.y + this.height); + } + + onClick() { + // implement + } + + /** + * Default button styles + */ + render(ctx) { + ctx.fillStyle = this.fillColor; + ctx.beginPath(); + ctx.roundRect( + this.x, + this.y, + this.width, + this.height, + 8 + ); + ctx.fill() + + // draw the button text + ctx.fillStyle = "#fff"//this.color; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + + //console.log(this.fontSize, this.fontWeight, this.fontFamily) + + if(this.fontWeight == 'regular') { + ctx.font = `${this.fontSize}px ${this.fontFamily}`; + } else { + ctx.font = `${this.fontWeight} ${this.fontSize}px ${this.fontFamily}`; + } + + ctx.fillText( + this.text, + this.x + this.width / 2, + this.y + this.height / 2, + //this.button + ); + } +} diff --git a/js/game/buttons.js b/js/game/buttons.js new file mode 100644 index 0000000..7279087 --- /dev/null +++ b/js/game/buttons.js @@ -0,0 +1,88 @@ +import { Button } from '../comfy/comfy.js'; +import { darkenHexColor } from '../utils.js'; + +/** + * General styling + */ +export class BaseComfyPetsButton extends Button { + constructor(text, fillColor, textColor) { + super(text, fillColor, textColor) + } + + render(ctx) { + + // Darken by 10% + const buttonFillDark = darkenHexColor(this.fillColor, 10); + + ctx.fillStyle = buttonFillDark; + ctx.beginPath(); + ctx.roundRect( + this.x, + this.y, + this.width, + this.height, + 8 + ); // draw the button text + ctx.fill() + + ctx.fillStyle = this.fillColor; + ctx.beginPath(); + ctx.roundRect( + this.x, + this.y, + this.width, + this.height - 4, + 8 + ); + ctx.fill() + + ctx.fillStyle = this.color; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + + if(this.fontWeight == 'regular') { + ctx.font = `${this.fontSize}px ${this.fontFamily}`; + } else { + ctx.font = `${this.fontWeight} ${this.fontSize}px ${this.fontFamily}`; + } + + ctx.fillText( + this.text, + this.x + this.width / 2, + this.y + this.height / 2, + //this.button + ); + + + ctx.fillText( + this.text, + this.x + this.width / 2, + this.y + this.height / 2, + ); + } +} + +/** + * Button sizes + */ +export class SmallButton extends BaseComfyPetsButton { + constructor(text, fillColor, textColor) { + super(text, fillColor, textColor) + this.width = 100; + this.height = 24; + } +} +export class MediumButton extends BaseComfyPetsButton { + constructor(text, fillColor, textColor) { + super(text, fillColor, textColor) + this.width = 100; + this.height = 32; + } +} +export class LargeButton extends BaseComfyPetsButton { + constructor(text, fillColor, textColor) { + super(text, fillColor, textColor) + this.width = 100; + this.height = 48; + } +} diff --git a/js/game/core.js b/js/game/core.js index 9414306..16b8a36 100644 --- a/js/game/core.js +++ b/js/game/core.js @@ -25,23 +25,3 @@ export class GameObject { } } -export class Button { - constructor(text, fillColor, textColor) { - this.x = 0; - this.y = 0; - this.width = 100; - this.height = 48; - this.id = generateId(); - this.text = text; - this.textColor = textColor; - this.fillColor = fillColor; - } - - inBounds(mouseX, mouseY) { - return !(mouseX < this.x || mouseX > this.x + this.width || mouseY < this.y || mouseY > this.y + this.height); - } - - onClick() { - // implement - } -} diff --git a/js/game/stage.js b/js/game/stage.js index 6490f56..56c8c14 100644 --- a/js/game/stage.js +++ b/js/game/stage.js @@ -1,16 +1,12 @@ -import { ComfyNode, app } from '../comfy/comfy.js'; +import { ComfyNode } from '../comfy/comfy.js'; //import { gameDialog } from '../comfy/ui.js'; import { getRandomNumber } from '../utils.js'; -import { Button } from './core.js'; import { Pet } from './pet.js'; import { Food } from './food.js'; //import { startGame } from './endless_runner/index.js'; -//import { addFoodEvent } from '../apiClient.js'; +import { addFoodEvent } from '../apiClient.js'; +import { MediumButton } from './buttons.js'; -var test = new Button("Hello world", '#eeaa00', '#001122') -test.onClick = () => { - console.log("hello world") -} @@ -23,16 +19,15 @@ export class ComfyPetsStage extends ComfyNode { super() this.title = "Comfy Pet", - /* - this.addButton("Feed pet", () => { + this.feedButton = this.addButton("Feed pet", {}, () => { this.addFood() addFoodEvent() }) - */ - - this.buttons = [ - test - ] + this.feedButton.x = 8 + this.feedButton.y = 8 + this.feedButton.fontSize = 14; + this.feedButton.fontWeight = "bold"; + this.feedButton.fontFamily = "Courier New"; /* // @todo @@ -53,7 +48,7 @@ export class ComfyPetsStage extends ComfyNode { } addPet() { - const [height] = this.size + const height = this.size[1]; const petWidth = 75; const petHeight = 50; @@ -85,8 +80,21 @@ export class ComfyPetsStage extends ComfyNode { this.foods.push(food) } + /** + * Add a button to the ComfyUI node + */ + addButton(buttonText, options, callback) { + //this.addWidget("button", buttonText, "image", callback) + var b = new MediumButton(buttonText, '#eeaa00', '#fff') + b.onClick = callback + this.buttons.push(b) + + return b; + } + renderPets(ctx) { - const [width, height] = this.size + const [width] = this.size + for (let i = 0; i < this.pets.length; i++) { const pet = this.pets[i]; @@ -122,7 +130,7 @@ export class ComfyPetsStage extends ComfyNode { ctx.drawImage( pet.petGif.image, // img src pet.x, // x - height - pet.height, // y + pet.y, // y pet.width, // width pet.height // height ); @@ -133,8 +141,6 @@ export class ComfyPetsStage extends ComfyNode { } renderFoods(ctx) { - const [height] = this.size - for (let i = 0; i < this.foods.length; i++) { const food = this.foods[i] @@ -142,11 +148,10 @@ export class ComfyPetsStage extends ComfyNode { this.foods.splice(i, 1); } - //ctx.fillStyle = "blue"; ctx.drawImage( food.image, food.x, - height - food.height, + food.y, food.width, food.height ); @@ -158,78 +163,18 @@ export class ComfyPetsStage extends ComfyNode { ctx.drawImage(this.backgroundImage, 0, 0, width, height); } - renderButtons(ctx) { - for (let i = 0; i < this.buttons.length; i++) { - const button = this.buttons[i]; - - ctx.fillStyle = button.fillColor; - ctx.fillRect(button.x, button.y, button.width, button.height); // draw the button text - ctx.fillStyle = button.textColor; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.font = '25px arial'; - ctx.fillText(button.text, button.x + button.width / 2, button.y + this.button / 2, this.button); - } - } - - /** - * Returns mouse pos relative to this node - */ - getRelativeMousePos() { - const [boundingX, boundingY] = this.getBounding(); - const [mouseX, mouseY] = app.canvas.canvas_mouse; - - const relativeMouseX = mouseX - boundingX; - const relativeMouseY = mouseY - boundingY; - - return [relativeMouseX, relativeMouseY]; - } - - /** - * Checks current mouse position and returns - * whether it is inside the bounding box of this node - */ - isMouseWithinNode() { - const boundingWidth = this.getBounding()[2]; - const boundingHeight = this.getBounding()[3]; - - const [relativeMouseX, relativeMouseY] = this.getRelativeMousePos(); - - if( - relativeMouseX > 0 && - relativeMouseX < boundingWidth && - relativeMouseY > 0 && - relativeMouseY < boundingHeight - ) { - return true; - } else { - return false - } - } - - renderOnce(ctx) { + renderOnce() { this.addPet() - ctx.canvas.addEventListener('click', ()=>{ - - if(this.isMouseWithinNode()) { - const [mouseX, mouseY] = this.getRelativeMousePos() - for (let i = 0; i < this.buttons.length; i++) { - const button = this.buttons[i]; - if(button.inBounds(mouseX, mouseY)) { - button.onClick() - } - } - } - }); - } render(ctx) { - this.renderBackground(ctx) - this.renderButtons(ctx) + //this.renderButtons(ctx) this.renderFoods(ctx) this.renderPets(ctx) // render pet onto canvas } } + + + diff --git a/js/utils.js b/js/utils.js index 570d9f4..f3d6175 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,3 +1,26 @@ +export function darkenHexColor(hexColor, percent) { + // Ensure the percent is between 0 and 100 + percent = Math.min(100, Math.max(0, percent)); + + // Convert hex to RGB + let r = parseInt(hexColor.slice(1, 3), 16); + let g = parseInt(hexColor.slice(3, 5), 16); + let b = parseInt(hexColor.slice(5, 7), 16); + + // Calculate the darkness factor + let darkness = 1 - percent / 100; + + // Apply darkness to each RGB component + r = Math.round(r * darkness); + g = Math.round(g * darkness); + b = Math.round(b * darkness); + + // Convert back to hex + const darkHexColor = `#${(r << 16 | g << 8 | b).toString(16).padStart(6, '0')}`; + + return darkHexColor; +} + export function getRandomNumber(min, max) { return Math.random() * (max - min) + min; }