cheese currecncy working

This commit is contained in:
adeliptr 2025-05-09 15:08:28 +09:00
parent ad4ec1d64b
commit cb2b42497a
14 changed files with 204 additions and 73 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -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';
}
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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++) {

View File

@ -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;

View File

@ -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 {

View File

@ -16,21 +16,17 @@
<link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<!-- <script defer src="sketch.js"></script> -->
<body>
<h1 id="title">Cats vs Mice</h1>
<div id="gameFrame">
<div id="upperContainer">
<div id="controlPanel">
<!-- <img src="assets/cheeseLabel.png" alt="Cheese Label" id="cheeseLabel"> -->
<label>CH</label>
<img src="assets/cheeseLabel.png" alt="Cheese Label" id="cheeseLabel">
<div id="cheeseDisplay">
<img src="assets/cheese.png" alt="cheeseIcon" class="buttonIcon" id="cheeseIcon">
<img src="assets/cheese.png" alt="Cheese Icon" id="cheeseIcon">
<span id="cheeseCount">50</span>
</div>
<!-- <img src="assets/catsLabel.png" alt="Cat Label" id="cheeseLabel"> -->
<label>CA</label>
<img src="assets/catsLabel.png" alt="Cat Label" id="catsLabel">
<div id="catToolbar">
<button class="catButton" id="chefCat">
<img src="assets/chef_cat_icon.png" alt="Chef Cat" class="catIcon" />
@ -54,13 +50,14 @@
</button>
</div>
<button class="catButton" id="petCage">
<img src="assets/petCage.png" alt="Pet Cage" class="catIcon" />
<span>200</span>
<img src="assets/petCage.png" alt="Pet Cage" id="cageIcon" />
</button>
<!-- <div id="gameProgressWrapper">
<progress id="gameProgress" value="30" max="100"></progress>
<label>Game Progress</label>
</div> -->
<div id="gameProgressWrapper">
<progress id="gameProgress" value="0" max="100"></progress>
<label id="gameProgressLabel">Game Progress</label>
</div>
</div>
</div>
</div>

View File

@ -1,11 +1,65 @@
export const level1Mice = [
{ time: 5, type: 'basicMouse', row: 0 },
{ time: 7, type: 'bossMouse', row: 2},
{ time: 10, type: 'basicMouse', row: 3 },
{ time: 20, type: 'sportyMouse', row: 2 },
{ time: 23, type: 'basicMouse', row: 0 },
{ time: 30, type: 'basicMouse', row: 4 },
{ time: 36, type: 'helmetMouse', row: 1 },
{ time: 45, type: 'basicMouse', row: 0},
{ time: 55, type: 'basicMouse', row: 0}
]
// First 30 seconds — Setup Time (no mice)
{ time: 5, type: 'bossMouse', row: 2 },
// First minute (30 - 89) — Basic Mice only
{ time: 30, type: 'basicMouse', row: 2 },
{ time: 45, type: 'basicMouse', row: 0 },
{ time: 57, type: 'basicMouse', row: 3 },
{ time: 63, type: 'basicMouse', row: 1 },
{ time: 76, type: 'basicMouse', row: 0 },
{ time: 84, type: 'basicMouse', row: 1 },
// Minute 2 (90 - 149) — introduce Helmet Mouse
{ time: 92, type: 'helmetMouse', row: 0 },
{ time: 98, type: 'basicMouse', row: 4 },
{ time: 105, type: 'basicMouse', row: 2 },
{ time: 115, type: 'helmetMouse', row: 1 },
{ time: 125, type: 'helmetMouse', row: 3 },
{ time: 138, type: 'basicMouse', row: 3},
{ time: 149, type: 'basicMouse', row: 4},
// Minute 3 (150 - 209) — introduce Sporty Mouse
{ time: 161, type: 'sportyMouse', row: 1 },
{ time: 167, type: 'basicMouse', row: 0 },
{ time: 175, type: 'helmetMouse', row: 2 },
{ time: 179, type: 'basicMouse', row: 2 },
{ time: 185, type: 'sportyMouse', row: 4 },
{ time: 194, type: 'basicMouse', row: 3},
{ time: 208, type: 'basicMouse', row: 1},
// Minute 4 (210 - 269) — mixed mice
{ time: 212, type: 'basicMouse', row: 3 },
{ time: 216, type: 'helmetMouse', row: 4 },
{ time: 219, type: 'sportyMouse', row: 1 },
{ time: 230, type: 'basicMouse', row: 0 },
{ time: 235, type: 'helmetMouse', row: 2 },
{ time: 238, type: 'sportyMouse', row: 0 },
{ time: 243, type: 'sportyMouse', row: 3 },
{ time: 246, type: 'helmetMouse', row: 4 },
{ time: 251, type: 'sportyMouse', row: 2},
{ time: 253, type: 'helmetMouse', row: 1},
{ time: 257, type: 'basicMouse', row: 0 },
{ time: 260, type: 'helmetMouse', row: 1},
{ time: 266, type: 'sportyMouse', row: 4 },
// Minute 5 (270 - 329) — boss and support
{ time: 272, type: 'bossMouse', row: 2 },
{ time: 275, type: 'basicMouse', row: 1 },
{ time: 280, type: 'basicMouse', row: 4},
{ time: 282, type: 'helmetMouse', row: 1},
{ time: 285, type: 'sportyMouse', row: 0 },
{ time: 290, type: 'helmetMouse', row: 3 },
{ time: 296, type: 'sportyMouse', row: 2},
{ time: 299, type: 'basicMouse', row: 4 },
{ time: 303, type: 'helmetMouse', row: 2 },
{ time: 307, type: 'sportyMouse', row: 0 },
{ time: 310, type: 'sportyMouse', row: 1 },
{ time: 312, type: 'basicMouse', row: 0},
{ time: 314, type: 'sportyMouse', row: 2 },
{ time: 317, type: 'helmetMouse', row: 1 },
{ time: 320, type: 'basicMouse', row: 3 },
{ time: 323, type: 'helmetMouse', row: 4},
{ time: 327, type: 'basicMouse', row: 0}
];

View File

@ -3,7 +3,6 @@ import { GameScene } from './GameScene.js';
export let mgr;
const gameParent = document.getElementById('gameFrame');
const controlPanel = document.getElementById('controlPanel');
const startButton = document.getElementById('startButton');
export let startPageAni, robotVacuum, gameBackground;
export const imageAssets = {};
@ -92,7 +91,6 @@ document.querySelectorAll('.catButton').forEach(button => {
if (selectedCatType === button.id) {
selectedCatType = null;
button.classList.remove('activeButton');
// document.body.style.cursor = 'default';
}
else {
selectedCatType = button.id;
@ -100,10 +98,6 @@ document.querySelectorAll('.catButton').forEach(button => {
btn.classList.remove('activeButton')
);
button.classList.add('activeButton');
// const img = button.querySelector('img');
// if (img) {
// document.body.style.cursor = `url(${img.src}) 32 32, auto`;
// }
}
console.log('Selected cat type:', selectedCatType);
});