diff --git a/.DS_Store b/.DS_Store index 2467131..5baa70c 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/GameScene.js b/GameScene.js index f496796..053ee7a 100644 --- a/GameScene.js +++ b/GameScene.js @@ -1,7 +1,7 @@ import { prototypeFrame, gameFrame } from './constants/Prototype.js'; import { Colors } from './constants/Colors.js'; import { imageAssets, selectedCatType, resetCatType } from './sketch.js'; -import { createCat, sleepyCats, throwables } from './classes/Cat.js'; +import { createCat, SleepyCat, sleepyCats, throwables } from './classes/Cat.js'; import { createMouse } from './classes/Mouse.js'; import { RobotVacuum } from './classes/RobotVacuum.js'; import { level1Mice } from './level/Level1.js'; @@ -10,14 +10,16 @@ const gameParent = document.getElementById('gameFrame'); const upperContainer = document.getElementById('upperContainer'); const controlPanel = document.getElementById('controlPanel'); const cheeseCount = document.getElementById('cheeseCount'); +const gameProgress = document.getElementById('gameProgress'); export const activeCats = []; export const activeMice = Array.from({ length: 5 }, () => []); const robotVacuums = []; -let gameSprites = []; +export let gameSprites = []; export let cheeses = []; export let grid = Array(5).fill().map(() => Array(9).fill(null)); let startTime; let levelMice = [...level1Mice]; +export let miceKilled = 0; export let catGroup, mouseGroup, throwableGroup, cheeseGroup; export function calculateCell(mouseX, mouseY) { @@ -61,6 +63,7 @@ export function GameScene() { } startTime = millis() / 1000; + cheeseCount.textContent = 50; } this.setup = function() { @@ -91,6 +94,7 @@ export function GameScene() { strokeWeight(gameFrame.border); // fix the border radius --> create a ratio for it rect(gameFrame.border / 2, gameFrame.border / 2, width - gameFrame.border, height - gameFrame.border, 35); + updateCatButtons(); drawGrid(); let currTime = millis() / 1000 - startTime; @@ -111,12 +115,11 @@ export function GameScene() { if (cat.sprite.overlaps(currMouse.sprite)) { cat.awake = true; cat.action(currMouse); - activeMice[row].splice(i, 1); } }) activeCats.forEach((cat) => { - if (cat.sprite.overlaps(currMouse.sprite)) { + if (!(cat instanceof SleepyCat) && cat.sprite.overlaps(currMouse.sprite)) { currMouse.targetCat = cat; console.log(`seting targetCat to ${currMouse.targetCat}`); } @@ -152,7 +155,6 @@ export function GameScene() { const cat = grid[row][col]; if (cat) { cat.remove(); - // TODO: need to remove from activeCats too const index = activeCats.indexOf(cat); if (index !== -1) { activeCats.splice(index, 1); @@ -169,7 +171,7 @@ export function GameScene() { grid[row][col] = newCat; activeCats.push(newCat); catGroup.add(newCat.sprite); - gameSprites.push(newCat.sprite); // Is this redundant? kedouble2 + gameSprites.push(newCat.sprite); updateCheeseCount(-newCat.cost); resetCatType(); } @@ -204,13 +206,11 @@ export function GameScene() { mouseX > x && mouseX < x + gameFrame.tileWidth && mouseY > y && mouseY < y + gameFrame.tileHeight ); + + if (isHovering && selectedCatType && selectedCatType === 'petCage' && grid[row][col] != null) fill('red'); + else if (isHovering && selectedCatType && selectedCatType != 'petCage' && grid[row][col] == null) fill('red'); + else fill((row + col) % 2 === 0 ? Colors.dark_yellow : Colors.light_yellow); - if (isHovering && selectedCatType && grid[row][col] == null) { - fill('red'); - } - else { - fill((row + col) % 2 === 0 ? Colors.dark_yellow : Colors.light_yellow); - } noStroke(); rect(x, y, gameFrame.tileWidth, gameFrame.tileHeight); } @@ -219,11 +219,9 @@ export function GameScene() { } function updateCheeseCount(n) { - console.log(`update cheeseCount by ${n}`) let currCheese = int(cheeseCount.textContent); currCheese += n; cheeseCount.textContent = currCheese; - // TODO: handle if n is negative and currCheese < -n somewhere else } function spawnMouse(type, row) { @@ -233,7 +231,44 @@ function spawnMouse(type, row) { let newMouse = new createMouse(type, x, y, row); if (newMouse) { activeMice[row].push(newMouse); + if (type == 'bossMouse') { + if (row - 1 >= 0) activeMice[row - 1].push(newMouse); + if (row + 1 >= gameFrame.rows) activeMice[row + 1].push(newMouse); + } mouseGroup.add(newMouse.sprite); - gameSprites.push(newMouse.sprite); // Is this redundant? kedouble2 sama allSprites + gameSprites.push(newMouse.sprite); } +} + +export function updateProgressBar() { + miceKilled++; + const percentage = Math.floor((miceKilled / level1Mice.length) * 100); + gameProgress.value = percentage; + console.log(`killed ${miceKilled} out of ${level1Mice.length}, % = ${percentage}`); +} + +const catCosts = { + chefCat: 50, + singleYarnCat: 100, + doubleYarnCat: 200, + sleepyCat: 150, + iceCat: 150 +}; + +function updateCatButtons() { + document.querySelectorAll('.catButton').forEach(button => { + const catType = button.id; + const cost = catCosts[catType]; + + if (int(cheeseCount.textContent) < cost) { + button.disabled = true; + button.style.cursor = 'not-allowed'; + button.style.opacity = '0.5'; + } + else { + button.disabled = false; + button.style.opacity = '1'; + button.style.cursor = 'pointer'; + } + }) } \ No newline at end of file diff --git a/assets/catsLabel.png b/assets/catsLabel.png index 10757f5..d8dc347 100644 Binary files a/assets/catsLabel.png and b/assets/catsLabel.png differ diff --git a/assets/cheese.png b/assets/cheese.png index 20a41d3..f1ffa11 100644 Binary files a/assets/cheese.png and b/assets/cheese.png differ diff --git a/assets/cheeseLabel.png b/assets/cheeseLabel.png index 1d1dde8..22a9f59 100644 Binary files a/assets/cheeseLabel.png and b/assets/cheeseLabel.png differ diff --git a/assets/sleepy_cat_ani.png b/assets/sleepy_cat_ani.png index bb4cdec..babdd32 100644 Binary files a/assets/sleepy_cat_ani.png and b/assets/sleepy_cat_ani.png differ diff --git a/classes/Cat.js b/classes/Cat.js index 366f7b1..14f048a 100644 --- a/classes/Cat.js +++ b/classes/Cat.js @@ -1,6 +1,6 @@ import { gameFrame } from '../constants/Prototype.js'; import { catAnimation, imageAssets } from '../sketch.js'; -import { grid, cheeses, activeCats, activeMice, calculateCell, mouseGroup, throwableGroup, catGroup } from '../GameScene.js'; +import { grid, cheeses, activeCats, activeMice, calculateCell, mouseGroup, throwableGroup, gameSprites } from '../GameScene.js'; import { Yarn, Snowball } from './Throwable.js'; export const throwables = []; @@ -98,6 +98,7 @@ class Cat { addExplosion(spriteSheet) { this.explosion = createSprite(this.x, this.y, this.width, this.width); + gameSprites.push(this.explosion); this.explosion.spriteSheet = spriteSheet; this.explosion.scale = gameFrame.catRatio; this.explosion.life = 90; @@ -119,13 +120,13 @@ class ChefCat extends Cat { action() { // Produces 25 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 + this.width / 4 + this.offset * this.width / 20, this.y + this.width / 3 + this.offset * this.width / 20); cheese.scale = this.width / 216; cheese.image = imageAssets.cheese; cheese.collider = 'static'; cheese.overlaps(mouseGroup); cheeses.push(cheese); + gameSprites.push(cheese); this.lastProduced = millis(); this.offset = (this.offset + 1) % 3; } @@ -188,10 +189,11 @@ class DoubleYarnCat extends Cat { } } -class SleepyCat extends Cat { +export class SleepyCat extends Cat { constructor(x, y) { super(x, y, 150, catAnimation.sleepyCat, catAniDesc.sleepyCat); this.awake = false; + this.hasAttacked = false; this.wakeStart = undefined; this.targetMouse = undefined; } @@ -208,8 +210,10 @@ class SleepyCat extends Cat { } if (this.wakeStart != undefined) { - if (millis() - this.wakeStart > 900) { - if (this.targetMouse) this.targetMouse.remove(); + if (!this.hasAttacked && this.targetMouse && millis() - this.wakeStart > 900) { + this.targetMouse.attacked(150); + if (this.targetMouse && this.targetMouse.HP > 0) this.targetMouse.sprite.changeAni('walk'); + this.hasAttacked = true; } if (millis() - this.wakeStart > 1480) { this.remove(); diff --git a/classes/Mouse.js b/classes/Mouse.js index 25d54ec..719d76d 100644 --- a/classes/Mouse.js +++ b/classes/Mouse.js @@ -1,6 +1,6 @@ import { gameFrame } from '../constants/Prototype.js'; import { mouseAnimation } from '../sketch.js'; -import { activeMice, mouseGroup } from '../GameScene.js'; +import { activeMice, mouseGroup, updateProgressBar } from '../GameScene.js'; const mouseAniDesc = { idle: { row: 0, frameSize: [200, 200] }, @@ -24,15 +24,30 @@ class Mouse { this.targetCat = undefined; this.lastAttack = 0; this.defaultSpeed = speed; - this.defaultHP = HP + this.defaultHP = HP; + this.isAlive = true; } remove() { this.sprite.remove(); - const index = activeMice[this.row].indexOf(this); + let index = activeMice[this.row].indexOf(this); if (index != -1) { activeMice[this.row].splice(index, 1); } + if (this.defaultHP = 1000) { + if (this.row - 1 >= 0) { + index = activeMice[this.row - 1].indexOf(this); + if (index != -1) activeMice[this.row - 1].splice(index, 1); + } + if (this.row + 1 < gameFrame.rows) { + index = activeMice[this.row + 1].indexOf(this); + if (index != -1) activeMice[this.row + 1].splice(index, 1); + } + } + if (this.isAlive) { + this.isAlive = false; + updateProgressBar(); + } } attack() { @@ -53,6 +68,7 @@ class Mouse { attacked(point) { this.HP -= point; + console.log(`I'm being attacked by ${point} points and my HP is now ${this.HP}`) if (this.HP <= 0) this.remove(); else { this.sprite.opacity = (this.HP / this.defaultHP) * 0.5 + 0.5; @@ -74,13 +90,13 @@ class HelmetMouse extends Mouse { class SportyMouse extends Mouse { constructor(x, y, row) { - super(x, y, row, -0.25, 75, 20, mouseAnimation.sportyMouse, gameFrame.tileWidth); + super(x, y, row, -0.3, 85, 20, mouseAnimation.sportyMouse, gameFrame.tileWidth); } } class BossMouse extends Mouse { constructor(x, y, row) { - super(x, y, row, -0.05, 500, 50, mouseAnimation.bossMouse, 3 * gameFrame.tileWidth); + super(x, y, row, -0.05, 1000, 50, mouseAnimation.bossMouse, 3 * gameFrame.tileWidth); } } diff --git a/classes/RobotVacuum.js b/classes/RobotVacuum.js index 6c96652..20cc75d 100644 --- a/classes/RobotVacuum.js +++ b/classes/RobotVacuum.js @@ -17,7 +17,7 @@ export class RobotVacuum { action() { if (!this.activated) { this.activated = true; - this.sprite.vel.x = 1; + this.sprite.vel.x = 2; } for (let i = 0; i < activeMice[this.row].length; i++) { diff --git a/classes/Throwable.js b/classes/Throwable.js index 4f0112d..106c90e 100644 --- a/classes/Throwable.js +++ b/classes/Throwable.js @@ -1,11 +1,12 @@ import { gameFrame } from '../constants/Prototype.js'; import { imageAssets } from '../sketch.js'; +import { gameSprites } from '../GameScene.js'; export class Throwable { constructor(x, y, point, img, width) { this.sprite = createSprite(x, y, width, width); + gameSprites.push(this.sprite); this.sprite.image = img; - // TODO: check on the scale again this.sprite.scale = gameFrame.tileWidth / 1024; this.sprite.vel.x = 1; this.sprite.rotationSpeed = 1; diff --git a/css/style.css b/css/style.css index 632c1a4..126f355 100644 --- a/css/style.css +++ b/css/style.css @@ -19,12 +19,11 @@ body { #gameFrame { position: relative; - flex-shrink: 0; + /* flex-shrink: 0; */ max-width: 800px; width: 60vw; aspect-ratio: 800/569; border-radius: 35px; - /* border: 10px solid #000; */ background: #FFFEF9; overflow: hidden; } @@ -34,16 +33,18 @@ canvas { width: 100%; height: 100%; border-radius: 25px; - /* border: 1px solid #000; */ z-index: 0; } #upperContainer { position: absolute; + display: flex; + flex-direction: row; gap: 16px; align-items: center; background: var(--med-brown); border-radius: 25px 25px 0 0; + width: 100%; } #controlPanel { @@ -51,13 +52,18 @@ canvas { border-radius: 30px 30px 0 0; display: flex; flex-direction: row; - gap: 4px; + gap: 10px; + /* TODO: ganti ke % apa ya, 10px magic number bgt */ align-items: center; } #cheeseLabel { margin-left: 20px; - width: 2.6%; + height: 100%; +} + +#catsLabel { + height: 100%; } #cheeseDisplay { @@ -72,16 +78,13 @@ canvas { align-items: center; } -.buttonIcon { - width: 60% -} - #catToolbar { display: flex; flex-direction: row; height: 100%; - width: 46%; - gap: 1px; + width: auto; + aspect-ratio: 330/83; + /* gap: 1px; */ background: var(--light-brown); /* padding: 4px 8px; */ border-radius: 6px; @@ -106,7 +109,7 @@ canvas { color: #333; } -.catButton:hover { +.catButton:not(:disabled):hover { background: var(--dark-yellow); } @@ -117,7 +120,8 @@ canvas { #petCage { height: 100%; width: auto; - aspect-ratio: 66/83; + aspect-ratio: 60/83; + justify-content: center; } .catIcon { @@ -126,8 +130,14 @@ canvas { object-fit: contain; } -.cheeseIcon { - width: 80%; +#cageIcon { + width: 100%; + height: auto; + object-fit: contain; +} + +#cheeseIcon { + width: 50%; height: auto; object-fit: contain; } @@ -136,11 +146,31 @@ canvas { display: flex; flex-direction: column; align-items: center; + height: 50%; } #gameProgress { - width: 100px; - height: 10px; + appearance: none; + border-radius: 100px; + background-color: var(--dark-brown); + border: 4px solid #4b392b; + overflow: hidden; +} + +#gameProgress::-webkit-progress-bar { + background-color: var(--dark-brown); + border-radius: 100px; +} + +#gameProgress::-webkit-progress-value { + background-color: var(--dark-yellow); + border-radius: 100px; +} + +#gameProgressLabel { + margin-top: 0.5rem; + font-size: 1.2rem; + font-weight: bold; } #gameBackground { diff --git a/index.html b/index.html index 2dd880a..4b16b41 100644 --- a/index.html +++ b/index.html @@ -16,21 +16,17 @@ - -