diff --git a/.DS_Store b/.DS_Store index 2eec86e..4730ede 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -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 diff --git a/.idea/cats-vs-mice.iml b/.idea/cats-vs-mice.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/cats-vs-mice.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..31e1ebc --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..568bc14 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index c991e3b..eeb1915 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,189 @@ -# Cats vs. Mice +# ๐Ÿฑ Cats vs. Mice ๐Ÿญ + +## ๐Ÿ‘ค Student Information Name : Adelia Putri Student ID : 20210782 -Email : adelia@kaist.ac.kr \ No newline at end of file +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 playerโ€™s 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** + +

+ +

+ +### ๐Ÿ–ผ๏ธ 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 | + |------|----------|---------|-------------| + | | Single Yarn Cat | Shoots 1 yarn ball every 3 seconds | 100 | + | | Double Yarn Cat | Shoots 2 yarn balls every 3 seconds (double damage) | 200 | + | | Sleepy Cat | Sleeps until touched, then instantly attacks mouse that touched it | 150 | + | | Chef Cat | Produces 25 cheeses every 10 seconds | 50 | + | | 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 | + |------|--------------|-------------|------------| + | | Basic Mouse | Walks slowly (0.15), standard HP (100) | Early Game | + | | Helmet Mouse | Wears a helmet, high HP (150) | Mid Game | + | | Sporty Mouse | Moves quickly (2x Basic Mouse), low HP (80) | Mid Game | + | | 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: +

+ +

+ + +### ๐Ÿ’ก 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/) \ No newline at end of file diff --git a/assets/.DS_Store b/assets/.DS_Store index 1012b83..54e268d 100644 Binary files a/assets/.DS_Store and b/assets/.DS_Store differ diff --git a/assets/cats_vs_mice.png b/assets/README/cats_vs_mice.png similarity index 100% rename from assets/cats_vs_mice.png rename to assets/README/cats_vs_mice.png diff --git a/assets/README/classes_uml.png b/assets/README/classes_uml.png new file mode 100644 index 0000000..7416a18 Binary files /dev/null and b/assets/README/classes_uml.png differ diff --git a/assets/cat/ice_cat_ani.png b/assets/cat/ice_cat_ani.png index a66bca5..384c1be 100644 Binary files a/assets/cat/ice_cat_ani.png and b/assets/cat/ice_cat_ani.png differ diff --git a/assets/icon/.DS_Store b/assets/icon/.DS_Store new file mode 100644 index 0000000..fd1ee62 Binary files /dev/null and b/assets/icon/.DS_Store differ diff --git a/assets/chef_cat_icon.png b/assets/icon/chef_cat_icon.png similarity index 100% rename from assets/chef_cat_icon.png rename to assets/icon/chef_cat_icon.png diff --git a/assets/double_yarn_cat_icon.png b/assets/icon/double_yarn_cat_icon.png similarity index 100% rename from assets/double_yarn_cat_icon.png rename to assets/icon/double_yarn_cat_icon.png diff --git a/assets/ice_cat_icon.png b/assets/icon/ice_cat_icon.png similarity index 100% rename from assets/ice_cat_icon.png rename to assets/icon/ice_cat_icon.png diff --git a/assets/petCage.png b/assets/icon/petCage.png similarity index 100% rename from assets/petCage.png rename to assets/icon/petCage.png diff --git a/assets/single_yarn_cat_icon.png b/assets/icon/single_yarn_cat_icon.png similarity index 100% rename from assets/single_yarn_cat_icon.png rename to assets/icon/single_yarn_cat_icon.png diff --git a/assets/sleepy_cat_icon.png b/assets/icon/sleepy_cat_icon.png similarity index 100% rename from assets/sleepy_cat_icon.png rename to assets/icon/sleepy_cat_icon.png diff --git a/index.html b/index.html index 44d38d8..a216335 100644 --- a/index.html +++ b/index.html @@ -39,23 +39,23 @@
@@ -63,7 +63,7 @@
diff --git a/sketch.js b/sketch.js index c6bdb76..6e64ffd 100644 --- a/sketch.js +++ b/sketch.js @@ -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'); diff --git a/src/.DS_Store b/src/.DS_Store index 1b2366c..750e1b3 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/scenes/GameScene.js b/src/scenes/GameScene.js index f9f56d5..4654dd5 100644 --- a/src/scenes/GameScene.js +++ b/src/scenes/GameScene.js @@ -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';