win-lose condition applied

This commit is contained in:
adeliptr 2025-05-10 00:17:37 +09:00
parent cb2b42497a
commit 05d1136461
11 changed files with 110 additions and 23 deletions

View File

@ -5,6 +5,7 @@ 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';
import { showWinningScreen, showLosingScreen } from './level/WinLose.js';
const gameParent = document.getElementById('gameFrame');
const upperContainer = document.getElementById('upperContainer');
@ -14,6 +15,7 @@ const gameProgress = document.getElementById('gameProgress');
export const activeCats = [];
export const activeMice = Array.from({ length: 5 }, () => []);
const robotVacuums = [];
let leftBar, rightBar, cheeseFeast;
export let gameSprites = [];
export let cheeses = [];
export let grid = Array(5).fill().map(() => Array(9).fill(null));
@ -40,6 +42,7 @@ function isCellValid(row, col) {
export function GameScene() {
this.enter = function() {
select('#upperContainer').show();
select('#endingOverlay').hide();
select('#menuButton').show();
select('#startButton').hide();
@ -52,6 +55,23 @@ export function GameScene() {
gameSprites = []; // kayanya ga butuh, sama kayak allSprites
leftBar = createSprite(gameFrame.border / 2, gameFrame.padding_up + gameFrame.tileHeight * 2.5, gameFrame.border, gameFrame.tileHeight * 5);
leftBar.color = Colors.dark_brown;
leftBar.layer = 10;
leftBar.overlaps(allSprites);
gameSprites.push(leftBar);
rightBar = createSprite(width - gameFrame.border / 2, gameFrame.padding_up + gameFrame.tileHeight * 2.5, gameFrame.border, gameFrame.tileHeight * 5);
rightBar.color = Colors.dark_brown;
rightBar.layer = 10;
rightBar.overlaps(allSprites);
gameSprites.push(rightBar);
cheeseFeast = createSprite(gameFrame.tileWidth / 4, gameFrame.padding_up + gameFrame.tileHeight * 2.5, gameFrame.tileWidth / 2, gameFrame.tileHeight * 5);
cheeseFeast.opacity = 0;
cheeseFeast.overlaps(mouseGroup);
gameSprites.push(cheeseFeast)
for (let row = 0; row < gameFrame.rows; row ++) {
let x = gameFrame.paddingRobot + gameFrame.robotSize / 2;
let y = gameFrame.padding_up + row * gameFrame.tileHeight + gameFrame.tileHeight / 2;
@ -111,6 +131,11 @@ export function GameScene() {
for (let i = 0; i < activeMice[row].length; i++) {
const currMouse = activeMice[row][i];
currMouse.attack();
if (cheeseFeast.overlaps(currMouse.sprite)) {
showLosingScreen();
}
sleepyCats.forEach((cat) => {
if (cat.sprite.overlaps(currMouse.sprite)) {
cat.awake = true;
@ -227,13 +252,13 @@ function updateCheeseCount(n) {
function spawnMouse(type, row) {
let x = width;
let y = gameFrame.padding_up + row * gameFrame.tileHeight + gameFrame.tileHeight / 2;
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);
if (row + 1 < gameFrame.rows) activeMice[row + 1].push(newMouse);
}
mouseGroup.add(newMouse.sprite);
gameSprites.push(newMouse.sprite);
@ -244,6 +269,10 @@ export function updateProgressBar() {
miceKilled++;
const percentage = Math.floor((miceKilled / level1Mice.length) * 100);
gameProgress.value = percentage;
if (percentage >= 100) {
showWinningScreen();
}
console.log(`killed ${miceKilled} out of ${level1Mice.length}, % = ${percentage}`);
}
@ -260,7 +289,7 @@ function updateCatButtons() {
const catType = button.id;
const cost = catCosts[catType];
if (int(cheeseCount.textContent) < cost) {
if (parseInt(cheeseCount.textContent) < cost) {
button.disabled = true;
button.style.cursor = 'not-allowed';
button.style.opacity = '0.5';

View File

@ -5,6 +5,7 @@ export function StartScene() {
const self = this;
select('#upperContainer').hide();
select('#endingOverlay').hide();
select('#menuButton').hide();
select('#startButton').show();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
assets/game_background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -28,6 +28,24 @@ body {
overflow: hidden;
}
#endingOverlay {
position: fixed;
max-width: 800px;
width: 60vw;
aspect-ratio: 800/569;
border-radius: 35px;
background-color: rgba(80, 62, 40, 0.75);
z-index: 100;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#endingText {
color: var(--dark-yellow);
}
canvas {
display: block;
width: 100%;
@ -38,9 +56,6 @@ canvas {
#upperContainer {
position: absolute;
display: flex;
flex-direction: row;
gap: 16px;
align-items: center;
background: var(--med-brown);
border-radius: 25px 25px 0 0;
@ -52,13 +67,10 @@ canvas {
border-radius: 30px 30px 0 0;
display: flex;
flex-direction: row;
gap: 10px;
/* TODO: ganti ke % apa ya, 10px magic number bgt */
align-items: center;
}
#cheeseLabel {
margin-left: 20px;
height: 100%;
}
@ -69,8 +81,7 @@ canvas {
#cheeseDisplay {
background: var(--light-brown);
height: 100%;
width: auto;
aspect-ratio: 80/83;
width: 9.7%;
border-radius: 8px;
display: flex;
flex-direction: column;
@ -99,7 +110,6 @@ canvas {
border: 1px solid var(--dark-brown);
border-radius: 4px;
padding: 4px 6px;
font-size: 18px;
cursor: pointer;
transition: background 0.2s;
}
@ -117,6 +127,10 @@ canvas {
background: red;
}
.divider {
width: 1.5%;
}
#petCage {
height: 100%;
width: auto;
@ -143,17 +157,22 @@ canvas {
}
#gameProgressWrapper {
width: 22%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
height: 50%;
justify-content: center;
}
#gameProgress {
appearance: none;
width: 75%;
height: 20%;
border-radius: 100px;
margin-top: 5%;
background-color: var(--dark-brown);
border: 4px solid #4b392b;
border: 4px solid var(--dark-brown);
overflow: hidden;
}
@ -168,9 +187,11 @@ canvas {
}
#gameProgressLabel {
margin-top: 0.5rem;
font-size: 1.2rem;
font-weight: bold;
height: 20%;
font-weight: 600;
font-family: "Inter", sans-serif;
margin-top: 4%;
color: var(--dark-brown);
}
#gameBackground {

View File

@ -14,19 +14,29 @@
<script type="module" src="sketch.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
</head>
<body>
<h1 id="title">Cats vs Mice</h1>
<div id="gameFrame">
<div id="endingOverlay">
<h1 id="endingText">Congrats! You've finished level 1!</h1>
<button class="Button" id="quitButton">Quit Game</button>
</div>
<div id="upperContainer">
<div id="controlPanel">
<img src="assets/cheeseLabel.png" alt="Cheese Label" id="cheeseLabel">
<div id="cheeseDisplay">
<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="catsLabel">
<div id="catToolbar">
<button class="catButton" id="chefCat">
<img src="assets/chef_cat_icon.png" alt="Chef Cat" class="catIcon" />
@ -49,18 +59,24 @@
<span>150</span>
</button>
</div>
<span class="divider"></span>
<button class="catButton" id="petCage">
<img src="assets/petCage.png" alt="Pet Cage" id="cageIcon" />
</button>
<span class="divider"></span>
<div id="gameProgressWrapper">
<progress id="gameProgress" value="0" max="100"></progress>
<progress id="gameProgress" value="0" max="100"></progress>
<label id="gameProgressLabel">Game Progress</label>
</div>
</div>
</div>
</div>
<button class="Button" id="startButton">Start Game</button>
<button class="Button" id="menuButton">Menu</button>
</body>

View File

@ -1,6 +1,6 @@
export const level1Mice = [
// First 30 seconds — Setup Time (no mice)
{ time: 5, type: 'bossMouse', row: 2 },
// { time: 5, type: 'basicMouse', row: 2 },
// First minute (30 - 89) — Basic Mice only
{ time: 30, type: 'basicMouse', row: 2 },

17
level/WinLose.js Normal file
View File

@ -0,0 +1,17 @@
const endingOverlay = document.getElementById('endingOverlay');
const endingText = document.getElementById('endingText');
const endingMessage = {
win: "Nice job! The Cheese Feast is safe!",
lose: "Oh no! The mice crashed the Cheese Feast!<br>Give it another shot! (whiskers crossed)"
}
export function showWinningScreen() {
endingText.innerHTML = endingMessage.win;
endingOverlay.style.display = 'flex';
}
export function showLosingScreen() {
endingText.innerHTML = endingMessage.lose;
endingOverlay.style.display = 'flex';
}

View File

@ -4,7 +4,7 @@ import { GameScene } from './GameScene.js';
export let mgr;
const gameParent = document.getElementById('gameFrame');
const startButton = document.getElementById('startButton');
export let startPageAni, robotVacuum, gameBackground;
export let startPageAni;
export const imageAssets = {};
export const catImages = {};
export const catAnimation = {};
@ -16,14 +16,12 @@ function preload() {
width: 1440, height: 1024, frames: 5
});
startPageAni.frameDelay = 10;
robotVacuum = loadImage('assets/robot_vacuum.png');
gameBackground = loadImage('assets/gamebg3.png');
imageAssets.cheese = loadImage('assets/cheese.png');
imageAssets.yarn = loadImage('assets/yarn.png');
imageAssets.snowball = loadImage('assets/snowball.png');
imageAssets.robotVacuum = loadImage('assets/robot_vacuum.png');
imageAssets.gameBackground = loadImage('assets/gamebg3.png');
imageAssets.gameBackground = loadImage('assets/game_background.png');
imageAssets.mouse = loadImage('assets/mouse.png');
imageAssets.redExplosion = loadImage('assets/red_explosion.png');
imageAssets.grayExplosion = loadImage('assets/gray_explosion.png');
@ -86,6 +84,11 @@ menuButton.addEventListener('click', function (event) {
mgr.showScene(StartScene);
});
quitButton.addEventListener('click', function (event) {
event.preventDefault();
mgr.showScene(StartScene);
});
document.querySelectorAll('.catButton').forEach(button => {
button.addEventListener('click', () => {
if (selectedCatType === button.id) {