Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whiskers Toy Quest #5184

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions Games/Whiskers_Toy_Quest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# **Whiskers Toy Quest**

---

<br>

## **Description 📃**
Whiskers Toy Quest is an interactive text-based adventure game where players help Whiskers, a curious and playful cat, overcome exciting challenges to retrieve his favorite toys. Designed for children, the game fosters reading skills and enhances decision-making abilities by requiring players to carefully read and type their responses. Featuring diverse game states, branching storylines, and multiple outcomes, Whiskers Toy Quest provides an engaging, educational, and fun experience for kids of all ages.

## **Functionalities 🎮**
- Interactive story progression
- Multiple game states and choices
- Engaging GUI with customtkinter
<br>

## **How to Play? 🎩**
- Launch the game
- Follow the on-screen instructions to make choices
- Help Whiskers find his toys by making the right decisions

## **Installation and Running the Game 🚀**
### Prerequisites
- **Python 3.7 or later**
- **pip** (Python package installer)
- **customtkinter** library

### Steps

1. Clone the repository:
```bash
git clone https://github.com/wenstef/GameZone.git
```
2. Install the required Python libraries using `pip`:
```bash
pip install customtkinter
```
3. Start the game by running the main script:
```bash
python main.py
```
or
```bash
python3 main.py
```

**The game window should open, and you can start playing!**

<br>

## **Screenshots 📸**

<br>
<!-- add your screenshots like this -->
![image](assets/Whiskers_Toy_Quest.png)
![image](assets/Whiskers_Toy_Quest_2.png)
![image](assets/Whiskers_Toy_Quest_3.png)


<br>

Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Binary file added Games/Whiskers_Toy_Quest/assets/bedroom.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/eating.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/ending.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/find_toy.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/hallway.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/living_room.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/outside.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/shiny_object.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/tree.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Games/Whiskers_Toy_Quest/assets/whiskers.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
114 changes: 114 additions & 0 deletions Games/Whiskers_Toy_Quest/game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import customtkinter as ctk
import os
from tkinter import Image
from PIL import Image, ImageTk

class GameGUI:
def __init__(self, master, game_state, whiskers_choices):
self.master = master
self.master.title("Whiskers Toy Quest")
self.master.geometry("800x600")

# Save game state and choices
self.game_state = game_state
self.whiskers_choices = whiskers_choices

# Configure grid layout
self.master.grid_rowconfigure(0, weight=1)
self.master.grid_rowconfigure(1, weight=1)
self.master.grid_columnconfigure(0, weight=1)
self.master.grid_columnconfigure(1, weight=1)

# Title label
self.title_label = ctk.CTkLabel(self.master, text="Whiskers Toy Quest",
font=ctk.CTkFont(size=24, weight="bold"))
self.title_label.grid(row=0, column=0, columnspan=2, pady=10)

# Left frame for button and image
self.left_frame = ctk.CTkFrame(self.master)
self.left_frame.grid(row=1, column=0, sticky="nsew", padx=20, pady=20)

# Story label
self.story_label = ctk.CTkLabel(self.left_frame, text="", wraplength=300, justify="left",
font=ctk.CTkFont(size=14))
self.story_label.pack()

self.image_label = ctk.CTkLabel(self.left_frame, text="", width=400, height=300)
self.image_label.pack(pady=20, padx=20)

# Right frame for story and input
self.right_frame = ctk.CTkScrollableFrame(self.master, width=400, height=500)
self.right_frame.grid(row=1, column=1, sticky="nsew", padx=20, pady=20)

# Question label
self.question_label = ctk.CTkLabel(self.right_frame, text="", wraplength=300, font=ctk.CTkFont(size=14))
self.question_label.pack()

# Input field
self.user_input = ctk.CTkEntry(self.right_frame, placeholder_text="Type your choice here", width=350)
self.user_input.pack(pady=20)
self.user_input.bind("<Return>", self.handle_input)
self.user_input.configure(state="disabled")

# Start the game
self.start_game()

def get_asset_path(self, filename):
"""Get the full path to the asset file."""
return os.path.join("assets", filename)

def start_game(self):
"""Start the game by displaying the intro story."""
self.update_stage_description()
self.user_input.configure(state="normal")

def display_next_char(self, text, callback):
"""Display the next character in a given text."""
if hasattr(self, '_current_text'): # Ensure continuation between calls
current_text = self._current_text
else:
current_text = ""

if len(current_text) < len(text): # If there are more characters to display
next_char = text[len(current_text)] # Get the next character
self._current_text = current_text + next_char # Append the next character
self.story_label.configure(text=self._current_text) # Update the label
self.master.after(50, lambda: self.display_next_char(text, callback)) # Call the function again
else:
delattr(self, '_current_text') # Remove the attribute
callback() # Call the callback function

def update_stage_description(self):
"""Update the stage description and question."""
stage_info = self.game_state.get_current_stage_info()
if stage_info:
self.display_next_char(stage_info['scene_desc'], self.enable_input)
self.update_image(stage_info['image'])
self.question_label.configure(text=stage_info['question'])

def handle_input(self, event):
"""Handle the user input."""
user_input = self.user_input.get().strip()
if user_input:
self.user_input.delete(0, "end") # Clear the input field
if self.game_state.transition_to_next_state(user_input): # Transition to the next state
self.update_stage_description() # Update the stage description
else:
self.story_label.configure(text="Invalid choice. Try again.") # Display an error message

def enable_input(self):
"""Enable the user input field."""
self.user_input.configure(state="normal")

def update_image(self, image_path):
"""Loads and updates the image in the GUI."""
img_path = self.get_asset_path(image_path)
try:
img = Image.open(img_path)
img_resized = ctk.CTkImage(img, size=(350, 350))
self.image_label.configure(image=img_resized, text="")
self.image_label.image = img_resized
except FileNotFoundError:
print(f"Error: Image file not found: {img_path}")
self.image_label.configure(image='', text="Image not found")
self.image_label.image = None
17 changes: 17 additions & 0 deletions Games/Whiskers_Toy_Quest/game_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class WhiskersGameState:
def __init__(self, whiskers_choices):
self.whiskers_choices = whiskers_choices
self.current_state = 'intro'

def get_current_stage_info(self):
"""Retrieve the current stage's information."""
return self.whiskers_choices.get_stage_info(self.current_state)

def transition_to_next_state(self, choice):
"""Move to the next state based on the user's choice."""
current_info = self.whiskers_choices.get_stage_info(self.current_state)
next_states = current_info.get('next_state', {})
if choice in next_states:
self.current_state = next_states[choice]
return True
return False
16 changes: 16 additions & 0 deletions Games/Whiskers_Toy_Quest/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import customtkinter as ctk

from game import GameGUI
from game_state import WhiskersGameState
from whiskers_choices import WhiskersChoices

if __name__ == "__main__":
root = ctk.CTk()
root.title("Whiskers Toy Quest")
root.geometry("800x600")

whiskers_choices = WhiskersChoices() # Create an instance of WhiskersChoices
game_state = WhiskersGameState(whiskers_choices) # Create an instance of WhiskersGameState
gui = GameGUI(root, game_state, whiskers_choices) # Create an instance of GameGUI

root.mainloop() # Start the main event loop
128 changes: 128 additions & 0 deletions Games/Whiskers_Toy_Quest/whiskers_choices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
class WhiskersChoices:
def __init__(self):
self.choices = { # Dictionary of game choices
"intro": {
"image": "living_room.jpg",
"scene_desc": "Whiskers lost his favorite toy and needs your help to find it! Are you ready to embark on a fun adventure?",
"question": "Type 'start' to begin the quest.",
"next_state": {"start": "bedroom"},
},
"bedroom": {
"image": "bedroom.jpg",
"scene_desc": "Whiskers just had a nap and dreamed about his lost toy. He woke up and found himself in the bedroom. He decides to look for his toy.",
"question": "You are in Whiskers' bedroom. What would you like to do? Type 'look under the bed' or 'leave the bedroom' and press Enter.",
"next_state": {
"look under the bed": "under_bed",
"leave the bedroom": "hallway"
},
},
"under_bed": {
"image": "bedroom.jpg",
"scene_desc": "You found a hidden stash of toys under the bed! But none of them are Whiskers' favorite toy.",
"question": "What would you like to do next? Type 'take toy' or 'leave the bedroom' and press Enter.",
"next_state": {"take toy": "play_with_toy_ending", "leave the bedroom": "hallway"},
},
"hallway": {
"image": "hallway.jpg",
"scene_desc": "You are in the hallway. There are several rooms you can explore. But you can also leave the house and go outside.",
"question": "Where would you like to go? Type 'kitchen', 'living room', or 'leave the house and go outside' and press Enter.",
"next_state": {"kitchen": "kitchen", "living room": "living_room", "leave the house and go outside":
"outside"},
},
"kitchen": {
"image": "eating.jpg",
"scene_desc": "You are in the kitchen. It smells like food!",
"question": "What would you like to do? Type 'eat' or 'leave the kitchen' and press Enter.",
"next_state": {"eat": "eating", "leave the kitchen": "hallway"},
},
"living_room": {
"image": "living_room.jpg",
"scene_desc": "You are in the living room. It's cozy and quiet.",
"question": "What would you like to do? Type 'sit on couch' or 'leave the living room' and press Enter.",
"next_state": {"sit on couch": "sitting_on_couch", "leave the living room": "hallway"},
},
"outside": {
"image": "outside.jpg",
"scene_desc": "You are outside the house. The sun is shining, and the birds are chirping. You can explore the garden. Look near the tree or by the pond.",
"question": "What would you like to do? Type 'look near the tree' or 'look by the pond'.",
"next_state": {"look near the tree": "tree", "look by the pond": "pond"},
},
"eating": {
"image": "eating.jpg",
"scene_desc": "You are eating food in the kitchen. Yum! But you're so distracted by the food that you forget about the toy. You can continue eating or start over.",
"question": "What would you like to do next? Type 'continue eating' or 'leave the kitchen' and press Enter.",
"next_state": {"continue eating": "eating_ending", "leave the kitchen": "hallway"},
},
"tree": {
"image": "tree.jpg",
"scene_desc": "You look near the tree and find a buried pile of leaves. Underneath, there's a strange hole that looks like it might hold something interesting.",
"question": "What would you like to do? Type 'dig' to explore the hole or 'go back' to return outside.",
"next_state": {"dig": "find_toy", "go back": "outside"},
},
"pond": {
"image": "shiny_object.jpg",
"scene_desc": "You look by the pond and see some ripples in the water. It seems like something shiny is reflecting sunlight near the edge.",
"question": "What would you like to do? Type 'check shiny object' or 'go back' to return outside.",
"next_state": {"check shiny object": "shiny_object", "go back": "outside"},
},
"find_toy": {
"image": "find_toy.jpg",
"scene_desc": "You dig into the hole near the tree and find Whiskers' favorite toy! He purrs happily, his adventure complete.",
"question": "Congratulations! You've found the toy. Would you like to start a new adventure? Type 'yes' or 'no'.",
"next_state": {"yes": "intro", "no": "ending"},
},
"shiny_object": {
"image": "shiny_object.jpg",
"scene_desc": "The shiny object turns out to be a small bell. It's not the toy, but it seems important.",
"question": "What would you like to do? Type 'take bell' or 'go back'.",
"next_state": {"take bell": "bell_clue", "go back": "outside"},
},
"bell_clue": {
"image": "whiskers.jpg",
"scene_desc": "The bell jingles as you hold it. It reminds Whiskers of something. He runs toward the tree, meowing excitedly.",
"question": "Follow Whiskers? Type 'yes' or 'no'.",
"next_state": {"yes": "find_toy", "no": "outside"},
},
"sitting_on_couch": {
"image": "sitting_on_couch.jpg",
"scene_desc": "You sit on the couch, but Whiskers starts to feel sleepy and distracted.",
"question": "Would you like to keep looking for the toy or take a nap? Type 'keep looking' or 'nap'.",
"next_state": {"keep looking": "hallway", "nap": "nap_ending"},
},
"play_with_toy_ending": {
"image": "whiskers.jpg",
"scene_desc": "Whiskers plays with another toy, it's not his favorite. Maybe next time he'll "
"find it.",
"question": "The adventure ends here. Would you like to start over? Type 'yes' or 'no'.",
"next_state": {"yes": "intro", "no": "ending"},
},
"nap_ending": {
"image": "whiskers.jpg",
"scene_desc": "Whiskers falls asleep on the couch, dreaming again about his toy. Maybe next time he'll find it.",
"question": "The adventure ends here. Would you like to start over? Type 'yes' or 'no'.",
"next_state": {"yes": "intro", "no": "ending"},
},
"eating_ending": {
"image": "eating.jpg",
"scene_desc": "You decide to keep eating and forget all about the toy. Maybe you'll look for it another time.",
"question": "Would you like to start the adventure again? Type 'yes' or 'no'.",
"next_state": {"yes": "intro", "no": "ending"},
},
"start_over": {
"image": "whiskers.jpg",
"scene_desc": "You decide to start the adventure over from the beginning.",
"question": "Type 'start' to begin again.",
"next_state": {"start": "intro"},
},
"ending": {
"image": "ending.jpg",
"scene_desc": "Thank you for helping Whiskers in his adventure! See you next time!",
"question": "",
"next_state": {},
},
}


def get_stage_info(self, state):
"""Returns the information for the given state."""
return self.choices.get(state, {})
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ This repository also provides one such platforms where contributers come over an
| ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | --- |


| [Master Typing](https://github.com/kunjgit/GameZone/tree/main/Games/Master_Typing) | [Treasure Hunt](https://github.com/Antiquely3059/GameZone/tree/main/Games/Treasure%20Hunt) | [Virtual Pet](https://github.com/Antiquely3059/GameZone/tree/main/Games/Virtual_Pet) | [MazeRunner](https://github.com/kunjgit/GameZone/tree/main/Games/MazeRunner) | [Ping_Pong_Singleplayer](https://github.com/kunjgit/GameZone/tree/main/Games/Ping_Pong_Singleplayer) | [Madlibs](https://github.com/AaryanManghnani/GameZone/tree/main/Games/Madlibs) |
| [Whiskers_Toy_Quest](https://github.com/kunjgit/GameZone/tree/main/Games/Whiskers_Toy_Quest) | [Master Typing](https://github.com/kunjgit/GameZone/tree/main/Games/Master_Typing) | [Treasure Hunt](https://github.com/Antiquely3059/GameZone/tree/main/Games/Treasure%20Hunt) | [Virtual Pet](https://github.com/Antiquely3059/GameZone/tree/main/Games/Virtual_Pet) | [MazeRunner](https://github.com/kunjgit/GameZone/tree/main/Games/MazeRunner) | [Ping_Pong_Singleplayer](https://github.com/kunjgit/GameZone/tree/main/Games/Ping_Pong_Singleplayer) | [Madlibs](https://github.com/AaryanManghnani/GameZone/tree/main/Games/Madlibs) |
| [Bulls_And_Cows_New](https://github.com/kunjgit/GameZone/tree/main/Games/Bulls_And_Cows_New)
| [Find The Number](https://github.com/kunjgit/GameZone/tree/main/Games/Find_the_Number)
| [Guess_That_Pokemon](https://github.com/kunjgit/GameZone/tree/main/Games/Guess_That_Pokemon)
Expand Down
Binary file added assets/images/Whiskers_Toy_Quest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading