diff --git a/Cat.js b/Cat.js index 9944a21..6b12b51 100644 --- a/Cat.js +++ b/Cat.js @@ -1,56 +1,151 @@ -class Cat { - constructor(x, y, cost, image, width) { +import { gameFrame } from './prototype.js'; +import { catAnimation, imageAssets } from './sketch.js'; +import { cheeses } from './GameScene.js'; + +export const movingObjects = []; + +export class Cat { + constructor(x, y, cost, ani, width) { + // (x, y) is the center of the grid + this.sprite = createSprite(x, y, width, width); + this.sprite.addAnis(ani); + this.sprite.changeAni('idle'); + this.sprite.scale = width / 200; + this.x = x; this.y = y; this.cost = cost; - this.image = image; + this.ani = ani; this.width = width; - this.interval = 500; this.HP = 200; } + action() { + // TODO: + // - ChefCat: produces cheese every 10 seconds -> cheese.png pop up on top of the ChefCat every 10 seconds + // - SingleYarnCat: throw a yarn every 3 seconds -> a sprite of yarn.png shows up on the right of the cat with velocity of 1 to the right, + // delete the sprite of yarn when yarn hit a mouse or get out of the gameFrame + // - DoubleYarnCat: similar to SingleYarnCat but throw 2 yarns every 3 seconds, the yarns are visibly detached from each other + // - SleepyCat: stay idle until collide with a mouse, when colliding, change ani into 'wake_up' and then remove the sleepyCat sprite + // - IceCat: throw a snowball every 3 seconds from its mouth, the snowball is a sprite with image snowball.png + // delete the snowball sprite when it hit a mouse or get out of gameFrame + } + attacked(mouse) { this.HP = max(0, this.HP - mouse.AP); } draw() { - image(this.image, this.x, this.y, this.width, this.height); + drawSprite(this.sprite); + // animation(this.ani, this.x, this.y, 0, this.width, this.width); + } + + collide() { + // + } + + changeAni(name) { + this.sprite.changeAni(name); + } + + remove() { + this.sprite.remove(); } } -class ChefCat extends Cat { +export class ChefCat extends Cat { constructor(x, y) { - super(x, y, 50, catImages.chefCat, 100); + super(x, y, 50, catAnimation.chefCat, 100); + this.lastProduced = millis(); } - update() { - + action() { + // Produces 50 cheese every 10 seconds, cheese.png pop in front of the chefCat + if (millis() - this.lastProduced > 10000) { + console.log(`produces Cheese!`) + const cheese = createSprite(this.x + 20, this.y + 20, 20, 20); + cheese.addImage(imageAssets.cheese); + cheese.mouseActive = true; + cheeses.push(cheese); + this.lastProduced = millis(); + } } } -class SingleYarnCat extends Cat { +export class SingleYarnCat extends Cat { constructor(x, y) { - super(x, y, 100, catImages.singleYarnCat, 100); - this.lastShot = 0; + super(x, y, 100, catAnimation.singleYarnCat, 100); + this.lastShot = millis(); + } + + action() { + // Throw yarn every 3 seconds -> yarn has velocity x of 1 (to the right) + if (millis() - this.lastShot > 3000) { + const yarn = createSprite(this.x + gameFrame.tileWidth / 2, this.y, 20, 20); + yarn.addImage(imageAssets.yarn); + yarn.vel.x = 1; + yarn.life = 600; + movingObjects.push(yarn); + this.lastShot = millis(); + } } } -class DoubleYarnCat extends Cat { +export class DoubleYarnCat extends Cat { constructor(x, y) { - super(x, y, 200, catImages.doubleYarnCat, 100); - this.lastShot; + super(x, y, 200, catAnimation.doubleYarnCat, 100); + this.lastShot = millis(); + } + + action() { + // Throw 2 yarns every 3 seconds -> yarn has velocity x of 1 (to the right) + if (millis() - this.lastShot > 3000) { + for (let offset of [0, 20]) { // change to the actual yarn size, not 20 + const yarn = createSprite(this.x + gameFrame.tileWidth / 2 + offset, this.y, 20, 20); + yarn.addImage(imageAssets.yarn); + yarn.vel.x = 1; + yarn.life = 600; + movingObjects.push(yarn); + } + this.lastShot = millis(); + } } } -class SleepyCat extends Cat { +export class SleepyCat extends Cat { constructor(x, y) { - super(x, y, 150, catImages.sleepyCat, 100); + super(x, y, 150, catAnimation.sleepyCat, 100); + this.awake = false; + this.wakeStart = undefined; + } + + action() { + if (this.awake && !this.wakeStart) { + this.changeAni('wake_up'); + this.wakeStart = millis(); + } + if (this.wakeStart && millis() - this.wakeStart > 1000) { + this.remove(); + // Still needs to remove it from the activeCats or grid[row][col] + } } } -class IceCat extends Cat { +export class IceCat extends Cat { constructor(x, y) { - super(x, y, 150, catImages.iceCat, 100); - this.lastShot = 0; + super(x, y, 150, catAnimation.iceCat, 100); + this.lastShot = millis(); + } + + action() { + // Throw snowball every 3 seconds -> snowball has velocity x of 1 (to the right) + if (millis() - this.lastShot > 3000) { + const snowball = createSprite(this.x, this.y, 20, 20); + snowball.addImage(imageAssets.snowball); + snowball.vel.x = 1; + snowball.life = 600; + movingObjects.push(snowball); + this.lastShot = millis(); + } } } \ No newline at end of file diff --git a/assets/chef_cat.png b/assets/chef_cat.png deleted file mode 100644 index cdb6d2a..0000000 Binary files a/assets/chef_cat.png and /dev/null differ diff --git a/assets/chef_cat_ani.png b/assets/chef_cat_ani.png new file mode 100644 index 0000000..0f10f2b Binary files /dev/null and b/assets/chef_cat_ani.png differ diff --git a/assets/chef_cat_icon.png b/assets/chef_cat_icon.png new file mode 100644 index 0000000..d79d180 Binary files /dev/null and b/assets/chef_cat_icon.png differ diff --git a/css/style.css b/css/style.css index 27c7c38..632c1a4 100644 --- a/css/style.css +++ b/css/style.css @@ -1,3 +1,11 @@ +:root { + --dark-brown: #503E28; + --med-brown: #B09472; + --light-brown: #CAB49A; + --dark-yellow: #F7E7BE; + --light-yellow: #FDF4E5; +} + body { background-color: #FDF6E3; margin: 0; @@ -15,46 +23,77 @@ body { max-width: 800px; width: 60vw; aspect-ratio: 800/569; - border-radius: 25px; - border: 1px solid #000; + border-radius: 35px; + /* border: 10px solid #000; */ background: #FFFEF9; + overflow: hidden; } canvas { display: block; + width: 100%; + height: 100%; border-radius: 25px; - border: 1px solid #000; + /* border: 1px solid #000; */ z-index: 0; } -#controlPanel { +#upperContainer { position: absolute; - top: 20px; - left: 50%; - transform: translateX(-50%); - display: flex; gap: 16px; align-items: center; - background: #503E28; - border-radius: 10px; - padding: 12px 16px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + background: var(--med-brown); + border-radius: 25px 25px 0 0; +} + +#controlPanel { + /* background: var(--light-brown); */ + border-radius: 30px 30px 0 0; + display: flex; + flex-direction: row; + gap: 4px; + align-items: center; +} + +#cheeseLabel { + margin-left: 20px; + width: 2.6%; +} + +#cheeseDisplay { + background: var(--light-brown); + height: 100%; + width: auto; + aspect-ratio: 80/83; + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.buttonIcon { + width: 60% } #catToolbar { display: flex; - gap: 8px; - background: #e9dbc7; - padding: 4px 8px; + flex-direction: row; + height: 100%; + width: 46%; + gap: 1px; + background: var(--light-brown); + /* padding: 4px 8px; */ border-radius: 6px; } .catButton { + width: 20%; display: flex; flex-direction: column; align-items: center; - background: #fff3dd; - border: none; + background: var(--light-brown); + border: 1px solid var(--dark-brown); border-radius: 4px; padding: 4px 6px; font-size: 18px; @@ -68,7 +107,29 @@ canvas { } .catButton:hover { - background: #f2e6c7; + background: var(--dark-yellow); +} + +.catButton.activeButton { + background: red; +} + +#petCage { + height: 100%; + width: auto; + aspect-ratio: 66/83; +} + +.catIcon { + width: 100%; + height: auto; + object-fit: contain; +} + +.cheeseIcon { + width: 80%; + height: auto; + object-fit: contain; } #gameProgressWrapper { @@ -82,8 +143,15 @@ canvas { height: 10px; } +#gameBackground { + position: absolute; + translate: -50%; + width: 100%; + /* z-index: -1; */ +} + .Button { - background: #b8956f; + background: var(--med-brown); color: white; border: none; padding: 6px 10px;