finish README

This commit is contained in:
adeliptr 2025-05-11 23:16:55 +09:00
parent 9826e8f115
commit 2cf34b04be
22 changed files with 232 additions and 15 deletions

BIN
.DS_Store vendored

Binary file not shown.

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

9
.idea/cats-vs-mice.iml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/cats-vs-mice.iml" filepath="$PROJECT_DIR$/.idea/cats-vs-mice.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

189
README.md
View File

@ -1,4 +1,189 @@
# Cats vs. Mice
# 🐱 Cats vs. Mice 🐭
## 👤 Student Information
Name : Adelia Putri
Student ID : 20210782
Email : adelia@kaist.ac.kr
Email : adelia@kaist.ac.kr
Git Repository: [Cats vs. Mice Repository](https://github.com/adeliptr/Cats-vs-Mice)
Demo Video: [Cats vs. Mice Demo Video](https://youtu.be/wxM7zTX4wvc)
## 📚 Table of Content
- [🐱 Cats vs. Mice 🐭](#-cats-vs-mice-)
- [👤 Student Information](#-student-information)
- [📚 Table of Content](#-table-of-content)
- [🎮 Game Description](#-game-description)
- [🖼️ Game Interface](#-game-interface)
- [🕹️ Game Mechanics](#-game-mechanics)
- [💸 Currency](#-currency)
- [👾 Characters](#-characters)
- [1. Cats 🐈](#1-cats-)
- [2. Mice 🐁](#2-mice-)
- [🔗 Interactions List](#-interactions-list)
- [🗂️ Code Organization](#-code-organization)
- [💻 Tech Stack](#-tech-stack)
- [🧩 How Components Interact](#-how-components-interact)
- [💡 Design Patterns Used](#-design-patterns-used)
- [🏭 Factory Method Pattern](#-factory-method-pattern)
- [♟️ Strategy Pattern](#-strategy-pattern)
- [⭐️ Special Features](#-special-features)
- [⚠️ Limitation](#-limitation)
- [🙌 Acknowledgement](#-acknowledgement)
## 🎮 Game Description
**Cats vs. Mice** is a tower defense-style strategy game inspired by [*Plants vs. Zombies*](https://en.wikipedia.org/wiki/Plants_vs._Zombies), redesigned with a cute kitchen theme. Players place cats on a tiled kitchen floor to stop waves of invading mice who are after the **Cheese Feast**, a table full of cheesy dishes at the leftmost side of the screen.
> 🎯 **Objective**:
> The players goal is to protect the **Cheese Feast** by defending against waves of incoming mice
> To do this, the player can place different types of **[cats](#1-cats-)** with special abilities to attack the **[mice](#2-mice-)**
> 🏆 **Winning Condition**:
> Successfully stops all the mice from reaching the **Cheese Feast**
> The progress can be seen on the progress bar at the top right of the screen
> ❌ **Losing Condition**:
> A mouse reaches the **Cheese Feast**
<p align="center">
<img src="assets/README/cats_vs_mice.png" height="450">
</p>
### 🖼️ Game Interface
- **Background**: A 5x9 tiled kitchen floor with a checkered pattern
- **Cat Panel**: A row of clickable cat icons showing the price of each cat
- **Cheese Feast**: A table full of cheese dishes on the left side of the screen
- **Mice Entrance**: Mice appear from a hole on the floor on the right side of the screen
- **Defense Line**: Each row has a *robot vacuum* at the far left that activates once a mouse approaches it, sweeping away all mice in that row
- **Cheese** (currency): Drops from `🧑‍🍳 Chef Cat` periodically
- **Progress Bar**: Showing the progress of the game, if the progress bar is full, the player wins the game
## 🕹️ Game Mechanics
### 💸 Currency
- The currency of the game is `🧀 Cheese` (replacing the sun in *Plants vs. Zombies*)
- Players can collect cheese produced by `🧑‍🍳 Chef Cat`
- `🧀 Cheese` is used to buy different types of **[cats](#1-cats-)**, which can be placed on the 5x9 kitchen grid
### 👾 Characters
#### 1. Cats 🐈
- Objective: Protect the **Cheese Feast** by attacking the mice, slowing down the mice, or generating cheese. Each cat has a different ability and price
- Cats can only be placed in empty tiles
- Cats can be removed from the tiles by using the `Cage Button`
- Cats' HP is shown through its opacity, the lower the HP, the lower the opacity
**Cat Roles**
| Icon | Cat Type | Ability | Cheese Cost |
|------|----------|---------|-------------|
| <img src="assets/characters/single_yarn_cat.gif" width="75" height="75"> | Single Yarn Cat | Shoots 1 yarn ball every 3 seconds | 100 |
| <img src="assets/characters/double_yarn_cat.gif" width="75" height="75"> | Double Yarn Cat | Shoots 2 yarn balls every 3 seconds (double damage) | 200 |
| <img src="assets/characters/sleepy_cat.gif" width="75" height="75"> | Sleepy Cat | Sleeps until touched, then instantly attacks mouse that touched it | 150 |
| <img src="assets/characters/chef_cat.gif" width="75" height="75"> | Chef Cat | Produces 25 cheeses every 10 seconds | 50 |
| <img src="assets/characters/ice_cat.gif" width="75" height="75"> | Ice Cat | Slows down mice by throwing snowballs and attacks them | 150 |
Notes:
- `🧶 Yarn` : reduces a mouse's HP by 20 points
- `❄️ Snowball` : reduces a mouse's HP by 8 points + speed reduction (-0.02 units/frame)
#### 2. Mice 🐁
- Objective: Mice enter from the right side and move left toward the **Cheese Feast**
- Mice will move forward in a straight line unless blocked by a cat
- If a mouse reaches a cat, it will attack the cat, which is indicated by a smoke puff
**Mouse Roles**
| Visual | Mouse Type | Description | Appearance |
|------|--------------|-------------|------------|
| <img src="assets/characters/basic_mouse.gif" width="75" height="75"> | Basic Mouse | Walks slowly (0.15), standard HP (100) | Early Game |
| <img src="assets/characters/helmet_mouse.gif" width="75" height="75"> | Helmet Mouse | Wears a helmet, high HP (150) | Mid Game |
| <img src="assets/characters/sporty_mouse.gif" width="75" height="75"> | Sporty Mouse | Moves quickly (2x Basic Mouse), low HP (80) | Mid Game |
| <img src="assets/characters/boss_mouse.gif" width="75" height="75"> | Boss Mouse | Very slow (3x Basic Mouse), very high HP (1000) | Late Game |
### 🔗 Interactions List
In the game, players can do the following actions:
| **Action**| **Trigger** | **Result**|
|----------------|-------------|-----------|
| Cheese pick up | Mouse click on cheese icon | Increase cheese count |
| Place cat | Mouse click on UI + tile | Deduct cheese, place cat |
| Remove cat | Mouse click on UI + cat | Remove cat from the tile |
In the game, these interactions between entities can happen:
| **Interaction**| **Trigger** | **Result**|
|----------------|-------------|-----------|
| Yarn / Snowball hits mouse | Collision | Mouse takes damage |
| Mouse reaches cat | Collision | Mouse attacks cat |
| Mouse reaches robot vacuum | Collision | Robot vacuum move to the right and remove all mice in the rows |
| Mouse reaches Cheese Feast | Collision | Trigger loss state |
| All mice defeated | Mouse count check | Trigger win state |
## 🗂️ Code Organization
### 💻 Tech Stack
This project is developed using JavaScript, HTML, and CSS for structuring and styling the user interface
Libraries used in the project:
- `p5.js`: for drawing and managing canvas-based graphics
- `p5.play`: for sprite and animation handling in the game environment
- `p5.scenemanager`: for managing multiple game scenes (start page and actual game page)
### 🧩 How Components Interact
This game is built using `Object-Oriented Programming (OOP)` principles to create reusable code. The overall structure of the code is as follows:
```
├── README.md
├── assets/ // all game assets
├── css/ // game styling
├── index.html // entry point of the game
├── js/ // external libraries
├── sketch.js // main game script
└── src // core game source code
├── classes // class definitions for game entities
│ ├── Cat.js
│ ├── Mouse.js
│ ├── RobotVacuum.js
├── constants
│ ├── Colors.js // centralized color palette
│ └── Prototype.js // dimensions from Figma prototype
├── level
│ ├── Level1.js // list of mice for level 1
│ └── WinLose.js // win/lose overlay
├── logic
│ ├── Controller.js // UI update functions
│ └── Helper.js // general utility functions
└── scenes // game scenes for screen manager
├── GameScene.js
└── StartScene.js
```
In this project, `GameScene.js` acts as the central coordinator of the gameplay. Below is the significance of each components:
- **Game Loop** (`GameScene.js`): checks for interactions between entities and calls the appropriate methods
- **Entity Classes** (`src/classes/`): each entity manages its own state and behavior (action(), attack(), etc.), which will be called by `GameScene.js`
- **UI Sync** (`Controller.js`): updates DOM (cheese count, progress bar, etc.) based on internal game state
The UML for the classes is as follows:
<p align="center">
<img src="assets/README/classes_uml.png" height="450">
</p>
### 💡 Design Patterns Used
#### 🏭 Factory Method Pattern
- Implemented in the `createCat(type, x, y)` and `createMouse(type, row)` functions
- These functions abstract away the creation logic and allows easy type extension
#### ♟️ Strategy Pattern
- Each `🐱 Cat` subclasses overrides the action() method to implement different attack behaviors (e.g., throwing yarn, exploding)
## ⭐️ Special Features
- **Opacity-based HP indicator**: the cats and mice's opacity lowers as their HP decreases
- **Robot Vacuum**: Activated when a mouse touches it and will defeat all mice in its row upon activation
## ⚠️ Limitation
The current version still has these limitations:
- When a `💤 SleepyCat` overlaps with 2 mice, it only attacks the first mouse that touches it instead of both
- When 2 mice perfectly overlap with each other, one of them won't be detected by other entities like `RobotVacuum`
## 🙌 Acknowledgement
- I learned how to use p5.play from the tutorial at [Learn p5play](https://p5play.org/learn/index.html)
- I found solutions to coding issues on [Stack Overflow](https://stackoverflow.com/questions)
- I referred to [W3Schools CSS Reference](https://www.w3schools.com/cssref/index.php) for styling help
- Some visual assets were sourced from [Flaticon](https://www.w3schools.com/cssref/index.php), [PNGTree](https://pngtree.com/), [LovePik](https://lovepik.com/), [PNGEgg](https://www.pngegg.com/)

BIN
assets/.DS_Store vendored

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 294 KiB

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

BIN
assets/icon/.DS_Store vendored Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 286 KiB

View File

Before

Width:  |  Height:  |  Size: 335 KiB

After

Width:  |  Height:  |  Size: 335 KiB

View File

Before

Width:  |  Height:  |  Size: 301 KiB

After

Width:  |  Height:  |  Size: 301 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 315 KiB

After

Width:  |  Height:  |  Size: 315 KiB

View File

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View File

@ -39,23 +39,23 @@
<div id="catToolbar">
<button class="catButton" id="chefCat">
<img src="assets/chef_cat_icon.png" alt="Chef Cat" class="catIcon" />
<img src="assets/icon/chef_cat_icon.png" alt="Chef Cat" class="catIcon" />
<span>50</span>
</button>
<button class="catButton" id="singleYarnCat">
<img src="assets/single_yarn_cat_icon.png" alt="Single Yarn Cat" class="catIcon" />
<img src="assets/icon/single_yarn_cat_icon.png" alt="Single Yarn Cat" class="catIcon" />
<span>100</span>
</button>
<button class="catButton" id="doubleYarnCat">
<img src="assets/double_yarn_cat_icon.png" alt="Double Yarn Cat" class="catIcon" />
<img src="assets/icon/double_yarn_cat_icon.png" alt="Double Yarn Cat" class="catIcon" />
<span>200</span>
</button>
<button class="catButton" id="sleepyCat">
<img src="assets/sleepy_cat_icon.png" alt="Sleepy Cat" class="catIcon" />
<img src="assets/icon/sleepy_cat_icon.png" alt="Sleepy Cat" class="catIcon" />
<span>150</span>
</button>
<button class="catButton" id="iceCat">
<img src="assets/ice_cat_icon.png" alt="Ice Cat" class="catIcon" />
<img src="assets/icon/ice_cat_icon.png" alt="Ice Cat" class="catIcon" />
<span>150</span>
</button>
</div>
@ -63,7 +63,7 @@
<span class="divider"></span>
<button class="catButton" id="petCage">
<img src="assets/petCage.png" alt="Pet Cage" id="cageIcon" />
<img src="assets/icon/petCage.png" alt="Pet Cage" id="cageIcon" />
</button>
</div>
<div id="gameProgressWrapper">

View File

@ -4,7 +4,6 @@ import { GameScene } from './src/scenes/GameScene.js';
export let mgr;
export let startPageAni;
export const imageAssets = {};
export const catImages = {};
export const catAnimation = {};
export const mouseAnimation = {};
export let selectedCatType = null;
@ -30,12 +29,6 @@ function preload() {
imageAssets.redExplosion = loadImage('assets/red_explosion.png');
imageAssets.grayExplosion = loadImage('assets/gray_explosion.png');
catImages.chefCat = loadImage('assets/chef_cat_icon.png');
catImages.singleYarnCat = loadImage('assets/single_yarn_cat_icon.png');
catImages.doubleYarnCat = loadImage('assets/double_yarn_cat_icon.png');
catImages.sleepyCat = loadImage('assets/sleepy_cat_icon.png');
catImages.iceCat = loadImage('assets/ice_cat_icon.png');
catAnimation.chefCat = loadImage('assets/cat/chef_cat_ani.png');
catAnimation.singleYarnCat = loadImage('assets/cat/single_yarn_cat_ani.png');
catAnimation.doubleYarnCat = loadImage('assets/cat/double_yarn_cat_ani.png');

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@ -10,6 +10,7 @@ import { updateCatButtons, updateCheeseCount, restartGameProgress } from '../log
import { calculateCell, isCellValid } from '../logic/Helper.js';
const gameParent = document.getElementById('gameFrame');
const endingOverlay = document.getElementById('endingOverlay');
const upperContainer = document.getElementById('upperContainer');
const controlPanel = document.getElementById('controlPanel');
const cheeseCount = document.getElementById('cheeseCount');
@ -175,6 +176,7 @@ export function GameScene() {
function resizeFrame() {
gameParent.style.borderRadius = (0.03125 * width) + 'px';
canvas.style.borderRadius = (0.03125 * width) + 'px';
endingOverlay.style.borderRadius = (0.03125 * width) + 'px';
const gridHeight = gameFrame.rows * gameFrame.tileHeight;
upperContainer.style.width = width + 'px';