0% found this document useful (0 votes)
4 views93 pages

Filmania Project (Combined)

The document is a project report for a movie-quote guessing game developed by students at The Hindu Senior Secondary School, utilizing Python, mySQL, and Pygame. It includes a bonafide certificate, acknowledgments, an index of topics covered, and detailed descriptions of system requirements, testing technologies, modules, classes, and functions used in the project. The game features user login, various game modes, and a dynamic interface with visual effects and sound management.

Uploaded by

adhvaithb84
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views93 pages

Filmania Project (Combined)

The document is a project report for a movie-quote guessing game developed by students at The Hindu Senior Secondary School, utilizing Python, mySQL, and Pygame. It includes a bonafide certificate, acknowledgments, an index of topics covered, and detailed descriptions of system requirements, testing technologies, modules, classes, and functions used in the project. The game features user login, various game modes, and a dynamic interface with visual effects and sound management.

Uploaded by

adhvaithb84
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 93

THE HINDU SENIOR SECONDARY SCHOOL

BONAFIDE CERTIFICATE

This is to certify that project on is the


bonafide work of -in the Computer
Science department of THE HINDU SENIOR
SECONDARY SCHOOL, Chennai-600 020, during the
year .

Submitted for the practical examination held on

External Examiner Internal Examiner

1|Page
First of all, we would like to thank our Computer
Science Teacher, Mrs.Dhanalakshmi, who was a
constant source of inspiration. She encouraged us to
think creatively and motivated us to work on this
assignment without giving it a second thought. She
expressed full support and provided us with the
different teaching aids that were required to complete
this assignment. She believed in us even when we could
not believe that we could do it. We are also thankful to
every member of this group. It was each and every
individual’s contribution that made this assignment a
success. We were always there to lift each other up,
and that was what helped us stay together till the end.
We thank our parents for always trusting in us and
teaching us to believe in our abilities and strengths and
never give up until the goal is achieved. We are
thankful to all our friends who extended their moral
support.

2|Page
INDEX

SNo. Topic Page


1. Introduction 4
System
2. 5
Requirements
3. Testing Technology 5
Modules, Classes
4. 6
and Functions Used
5. Source Code 28
6. Flowchart 78
7. Output Screens 79
8. Required Images 89
9. Conclusions 90
10. Bibliography 91

3|Page
INTRODUCTION

This project is a movie-quote guessing game


where players identify movies from famous
quotes, using hints and bonuses to improve
their score within a time limit.

It has been built using Python and mySQL,


and Graphic User Interfaces(GUIs) like
Pygame, and many other key concepts like
datatypes, functions, python modules, simple
mySQL queries, python-mySQL interface
and debugging.

The project consists of a User login window,


which allows the user to submit their
“username” and “Password” and log into the
main screen where they can listen to the
instructions, go into the store, play the
special level (if unlocked) or choose a game-
mode to play with each game-mode having
its own Leaderboard respectively.

4|Page
SYSTEM REQUIREMENTS

This project requires an integrated


development environment (IDE) and PIP to
install and run a new module “pygame” which
has been used in the project to create the
game window. There are also a few images
that have to be downloaded and added to the
same folder to execute the code (Attached to
document in the end).

TESTING TECHNOLOGY

The code for this project was developed


using Pycharm IDE. We did intense testing to
ensure that no major bugs and issues
cropped up. Repeated running of the same
code and debugging was done to resolve
most of the bugs.

No other specialized software was used for


this purpose. The final code was also
checked in Python IDLE, after completion.

5|Page
MODULES AND
FUNCTIONS USED

Modules used:
 Pygame
 Random
 Math
 Csv
 Mysql.connector.pooling
 Mysql.connector
 Threading
 Sys
 Re
 Textwrap

Classes used:
1. FlameEffect
Used to create a dynamic flame effect that
follows the player's cursor. It initializes the flame
at the center of the screen and updates its
position based on the cursor's coordinates (x, y),
then draws the flame effect onto the game
screen to add visual appeal and interactivity.

6|Page
2. FlameParticle
Used to create individual flame particles for a fire
effect. Each particle has properties like position,
radius, and burn rate, which control its size and
movement as it "burns." The class draws circles
with varying levels of opacity and color (from
bright orange to gold) to simulate a glowing,
flickering flame, and it gradually shrinks until it
fades out, enhancing the realism of the flame
effect.

3. Flame
Used to manage a collection of FlameParticle
objects to create a full flame effect. It initializes
particles at a specified position and updates their
positions to follow the flame’s movement. When
particles fade out, new ones are generated to
maintain a continuous flame, creating a dynamic
and realistic fire effect on the screen.

4. MatrixColumn
Used to simulate a column of falling characters,
reminiscent of the "Matrix" effect. It initializes with
random characters and colors, applying wave-
like motion and pulsating speed to create
dynamic movement. As the column moves down
the screen, it randomly changes characters and
shifts colors, maintaining a visually engaging
appearance. When the column reaches the
bottom of the screen, it resets to create a
continuous flow of characters.

7|Page
Functions Used:
1. load_movies_from_file(filename)
Used to read a specified file to load movie quotes
organized by difficulty levels: easy, medium, and
hard. It initializes a dictionary to store the quotes,
identifies the current difficulty level based on the
section headers in the file, and populates the
dictionary with movie titles and their
corresponding quotes. The function returns the
structured dictionary of movies and quotes for
later use in the application.

2. get_db_connection()
Used to retrieve a database connection from a
connection pool. This allows for efficient
management of database connections by
reusing existing ones instead of creating new
connections each time, improving performance
and resource utilization in database-driven
applications.

3. preload_questions(num_questions=10)
Used to fetch a specified number of random
questions from a database and stores them in a
global cache. It establishes a database
connection, executes a query to retrieve the
questions and their correct answers, and then
closes the connection. This function helps in
efficiently loading questions for use in a quiz or
game, minimizing database access during
gameplay.

8|Page
4. load_next_question()
Used to retrieve the next question from a
preloaded cache. If the cache is empty, it first calls
preload_questions to load more questions from
the database. The function then pops a question
from the cache and assigns it to the global
variable next_question, ensuring that a new
question is available for the quiz or game. This
mechanism allows for a seamless flow of
questions during gameplay.

5. get_random_quote_from_db()
Used to retrieve a random quote and its
associated correct answer from the current
question stored in the next_question variable. If
next_question is None, it calls
load_next_question to load a new question.
Additionally, it starts a new thread to preload the
next question, ensuring that future calls have a
question ready without interrupting the current
flow. This function helps maintain a smooth user
experience by providing immediate access to
questions while preparing the next one in the
background.

6. draw_glowing_circle(screen, color,
position, radius, glow_radius)
The draw_glowing_circle function creates a
glowing circle effect on the volume screen. It
draws a series of circles with decreasing opacity
(alpha) based on their distance from the center,
creating a smooth glow around a given color at a

9|Page
specified position and radius. The glow_radius
parameter determines how far the glow extends.
This function enhances visual aesthetics by
simulating a glowing effect, often used for
highlighting objects or adding an ambient light
effect in a game or graphical application.

7. draw_slider_handle(screen,position)
The draw_slider_handle function is responsible
for rendering a slider handle on the volume
screen. It first draws a shadow beneath the
handle to give a sense of depth, using a semi-
transparent black color. Then, it calls
draw_glowing_circle to create a glowing effect
around the handle, using a predefined color and
radius for the glow. Finally, it draws the actual
handle itself using the specified handle_color and
radius. This function enhances the visual
appearance of the slider, making it more
attractive and interactive in a graphical user
interface or game.

8. update_volume(delta)
The update_volume function adjusts the audio
volume in the application based on a specified
change (delta). It updates the global volume
variable by adding delta, ensuring that the volume
remains within defined limits (between
VOLUME_MIN and VOLUME_MAX). The function
also calculates the new position for the slider
handle (target_handle_x) based on the updated
volume. Finally, it sets the new volume for both
the background music and any female instruction

10 | P a g e
audio, allowing for real-time audio adjustments in
the user interface.

9. create_stars(num_columns)
The create_stars function generates a specified
number of columns for a visual effect, likely
resembling falling characters or stars in a matrix-
like display. It takes num_columns as an
argument to determine how many columns to
create. The function initializes a global variable
matrix_columns and uses a font for rendering
characters. It calculates the spacing between
each column based on the screen width and
creates a list of MatrixColumn instances,
positioning each column according to its index.
This setup is essential for creating a dynamic
visual effect on the screen.

10. update_stars()
The update_stars function updates the positions
of all the star-like columns on the screen. It
retrieves the current time in milliseconds using
pygame.time.get_ticks(), which is used to create a
time-based effect. The function iterates through
each MatrixColumn in the matrix_columns list and
calls the move method on each column, allowing
them to animate and create a dynamic visual
effect. This function is crucial for continuously
refreshing the display of falling characters or
stars in the animation.

11 | P a g e
11. draw_stars(screen)
The draw_stars function renders the star-like
characters on the screen by iterating through
each MatrixColumn in the matrix_columns list. For
each column, it loops through the characters and
their corresponding colors. It calculates the
vertical position (y) for each character based on
the column's current y position and the font size
(14). If the character is within the screen's height, it
creates a surface for the character using the
specified font and color, then blits (draws) it onto
the screen at the calculated position. This
function is essential for visually displaying the
animated falling effect of characters in the
project.

12. draw_text(surface, text, color, rect,


font, aa=False, bkg=None)
The draw_text function is responsible for
rendering text onto a given surface in a way that
respects the specified dimensions of a
rectangular area (rect). It handles multi-line text
rendering with line spacing and optional anti-
aliasing. The function iteratively checks if the text
can fit within the defined rectangle, wrapping it to
the next line if necessary. When the text exceeds
the vertical bounds of the rectangle, it stops
rendering. It uses the provided font and color to
create an image of the text, which is then blitted
onto the surface at the specified position. This
function is crucial for displaying formatted text in
the project.

12 | P a g e
13. display_instructions(screen)
The display_instructions function manages the
presentation of instructions to the player in a
graphical window. It begins by filling the screen
with a black background and playing a specific
audio track (female_instruction). The background
music is paused during this display, and a flame
effect is initialized to enhance the visual
experience.

14. sound_volume(screen)
The sound_volume function manages the
volume control interface in a Pygame application.
It allows users to adjust the audio volume using
both mouse movements and arrow key presses.
The function runs in a loop until the user decides
to continue, handling events such as mouse
motion (for dragging the volume slider) and key
presses (for incrementing or decrementing the
volume with the left and right arrow keys).

15. display_currency()
The display_currency function retrieves the
player's in-game currency and item counts from
a database, ensuring that certain quantities (skips,
clocks, and golden clocks) do not exceed
specified limits. It fetches the current amounts of
coins, gems, skips, clocks, and golden clocks,
updates the database if limits are breached, and
then visually displays this information on the
screen using Pygame's drawing functions.
Finally, it returns the counts of coins and gems for
further use in the game.
13 | P a g e
16. store(screen)
The store function presents the in-game store
interface where players can purchase various
items using their in-game currency. It initializes the
store display, including background graphics and
item buttons for purchasing skips, clocks, gems,
golden clocks, and a special level upgrade. The
function checks the player's currency and item
limits before allowing purchases, providing
feedback messages based on the transaction
outcome. Players can interact with the store by
clicking buttons or pressing the Enter key to
return to the previous screen. It updates the
display to reflect the current state of the player's
inventory and any purchase confirmations or
error messages.

17. display_start_menu(screen)
The display_start_menu function creates the
start menu for the game, featuring a visually
dynamic background with a blinking "Are you
ready?" message that changes color to grab the
player's attention. It initializes a flame effect that
responds to the mouse position, enhancing the
visual appeal. The menu allows players to start
the game by pressing the Enter key, which also
triggers background music to play from a specific
starting position in the audio file. The menu
remains active until the player decides to start the
game or quits the application, providing a clear
indication of how to proceed with a "Press Enter
to start" message after the blinking phase.

14 | P a g e
18. get_username(screen)
The get_username function manages user input
for a login or registration interface in a game. It
allows users to enter their username and
password, providing a series of prompts and
validations throughout the process. The interface
features a textbox for username input, which
leads to password entry if the username is
recognized or prompts for password creation if
it's new. Users can toggle the visibility of their
password via a checkbox and have the option to
reset their password if needed. The function
includes error messaging for invalid inputs,
guiding the user through the registration or login
flow while utilizing a visually appealing
background and flame effect. It returns the
username once the process is successfully
completed.

19. forgot_password(screen, username)


The forgot_password function facilitates the
password reset process for a user identified by
their username. It presents a text input box where
the user can enter a new password. The function
handles user interactions, including mouse clicks
and keyboard inputs, to toggle the active state of
the input box and capture the new password.
Upon pressing Enter, it validates the new
password and, if valid, updates the user's
password in the database. Feedback is provided
through messages displayed on the screen,
alerting the user to successful updates or errors.
The function visually incorporates a background
and flame effect, returning True upon successful

15 | P a g e
password change or False if the process is
aborted.

20. is_password_valid(password)
The is_password_valid function checks the
strength of a given password against several
criteria to ensure it meets security standards. It
verifies that the password is at least 8
characters long, contains at least one letter,
includes at least one numeric digit, and has at
least one special character (symbol). If the
password fails to meet any of these
requirements, the function returns False along
with a specific error message indicating which
condition was not satisfied. If the password
passes all checks, it returns True and a
confirmation message stating that the password
is valid.

21. verify_password(username, password)


The verify_password function checks whether a
provided password matches the stored
password for a given username in a database. It
executes a SQL query to retrieve the stored
password associated with the specified
username. If a result is found, it compares the
input password with the retrieved stored
password. The function returns True if the
passwords match, indicating successful
verification, and False if they do not match or if the
username does not exist in the database.

16 | P a g e
22. confirm_username(screen, username,
existing_usernames)
The confirm_username function checks if a
specified username already exists in a list of
existing usernames. If the username does not
exist, it returns True (indicating that the username
is available) without further confirmation. If the
username does exist, it displays a confirmation
dialog on the screen, asking the user whether
they want to proceed with that username. The
user can choose to confirm ("Yes") or decline
("No"), and the function returns the appropriate
response based on the user's choice. The
function also incorporates visual elements, such
as drawing background images, stars, messages,
and buttons, while handling user input and mouse
interactions for a dynamic user experience.

23. display_difficulty(screen)
The display_difficulty function presents a user
interface for selecting the difficulty level of a
game. It creates three buttons for "Easy,"
"Medium," and "Hard" difficulty levels and waits for
the user to click one of them. When a button is
clicked, it plays a sound and sets the difficulty
variable to the corresponding level, then exits the
loop. Throughout the process, the function
continuously updates the screen by drawing the
background, animated stars, and the buttons,
while also handling user events such as quitting
the game. Finally, it returns the selected difficulty
level as a string.

17 | P a g e
24. ask_for_music(screen)
The ask_for_music function displays a prompt on
the screen asking the user if they want to enable
music for the game. It features two buttons
labeled "Yes" and "No." The function continuously
listens for user interactions, specifically mouse
clicks on the buttons. If the user clicks "Yes," it
plays a sound and returns True, indicating the
user wants music. If "No" is clicked, it plays a
sound and returns False, indicating the user does
not want music. The function also handles quitting
the game, updates the screen with a background
and animated stars, and visually highlights the
buttons based on mouse hover events.

25. choose_music_playlist(screen)
The choose_music_playlist function allows the
user to select a music playlist for the game by
presenting three options: "Sunny Days," "Rainy
Nights," and "Adrenaline Rush." It listens for mouse
click events, and when the user clicks on one of
the buttons, it plays the corresponding music
track in a loop while also playing a click sound.
The function continuously updates the screen
with a background, animated stars, and displays
the playlist options. Additionally, it provides visual
feedback by highlighting the buttons when the
mouse hovers over them. The function concludes
when the user selects a playlist.

26. play_game(screen, difficulty)


The play_game function initiates a movie-quote
guessing game based on the selected difficulty
18 | P a g e
level. It randomly selects a movie and its
corresponding quote from a predefined
dictionary. The player is prompted to guess the
movie by typing their answer into an input box.
The function handles user input, including
keyboard events for text entry and submission.
When the player submits their guess by pressing
Enter, the function checks if the guess is correct
and displays the appropriate result message. The
screen continuously updates to show the quote,
an animated flame effect, and a blinking cursor in
the input box. After the player submits their guess,
the screen fades out with the result message
before waiting for a brief moment before returning
to the main game loop.

27. display_survival_mode(screen)
The display_survival_mode function presents
the user with a screen featuring a "Survival
Mode" button. It enters a loop that waits for user
interactions until the button is clicked. If the user
clicks the button, a sound effect plays, and the
loop ends, indicating that the player has selected
Survival Mode. Throughout the loop, the function
continuously updates the screen by drawing a
background, animated stars, and the button, while
also handling mouse events for hover effects to
enhance interactivity. The function ultimately
returns True, signifying that the selection was
successful.

19 | P a g e
28. load_leaderboard(mode)
The load_leaderboard function retrieves the
leaderboard data for a specified game mode from
a CSV file. It constructs the filename based on the
provided mode and attempts to open the
corresponding file. If the file exists, it reads the
data using a CSV dictionary reader, converting
each entry's username to lowercase and its
score to an integer. Additionally, it checks for an
'average_time' field, converting it to a float or
setting it to None if the value is 'N/A'. The function
returns the processed leaderboard as a list of
dictionaries. If the file is not found, it returns an
empty list.

29. save_leaderboard(leaderboard, mode)


The save_leaderboard function is designed to
save the current leaderboard data to a CSV file
for a specified game mode. It constructs the
filename based on the provided mode, determining
the appropriate field names to include in the CSV
header (either 'username', 'score', and
'average_time' for survival mode, or just
'username' and 'score' for other modes). The
function then opens the file in write mode and
uses a CSV dictionary writer to create the
header and write each entry in the leaderboard. If
an I/O error occurs during the process, it catches
the exception and prints an error message
indicating the issue.

20 | P a g e
30. display_leaderboard(screen,
leaderboard, mode)
The display_leaderboard function is responsible
for rendering the leaderboard on the screen
during the game. It enters a loop to handle events,
allowing the player to quit or continue by pressing
the Enter key. Within the loop, it draws the
background, stars, and a flame effect while
dynamically adjusting the layout of the
leaderboard based on the screen's dimensions.
The function calculates the required widths for
the username, score, and average time columns,
ensuring they fit within the available space. It then
displays the leaderboard entries, truncating
usernames that are too long and formatting
scores and average times accordingly. Finally, it
prompts the user to press Enter to continue,
updating the display with each frame until the user
decides to proceed.

31. update_leaderboard(username, score,


average_time, mode)
The update_leaderboard function manages
updates to the game's leaderboard based on a
user's performance. It begins by loading the
existing leaderboard from a file and converting
the username to lowercase for consistency. The
function checks if the user already exists in the
leaderboard, updating their score and average
time if their new score is higher or if they match
the existing score but have a shorter average
time. If the user is not found, it adds them as a new
entry. The leaderboard is then sorted by score

21 | P a g e
and, for survival mode, by average time as well.
Finally, the updated leaderboard is saved back to
the file, and a message is printed to confirm the
changes.

32. play_survival_mode(screen, difficulty,


username, used_movies)
The play_survival_mode function implements
the gameplay mechanics for a survival mode quiz
game where players guess movie titles based on
provided quotes. The function initializes various
game elements such as score, time limits, and
player resources (like hints and skips) while
loading these resources from a database. It
enters a loop where it randomly selects a movie
quote for the player to guess, processes user
inputs (including guesses, hints, and skips), and
updates the player's score based on their
performance. The function also handles visual
elements, such as hearts representing player
lives, and implements game controls for pausing,
using hints, and skipping questions. As the game
progresses, it tracks the time taken and
calculates the average time per question after
the game ends, updating the player's coins in the
database accordingly. Finally, it returns the
player's score, average time, and the number of
questions answered.

33. generate_hint(movie)
The generate_hint function creates a hint for a
given movie title by randomly revealing three
letters from the title while obscuring the rest with

22 | P a g e
underscores. It first removes spaces and
converts the movie title to uppercase for
uniformity. If the movie title has three or fewer
letters, the function returns the entire title. For
longer titles, it randomly selects three letters
from the title and constructs a hint where non-
selected letters are replaced with underscores.
The resulting hint is then formatted with spaces
between letters for improved readability and
returned as a string.

34.play_creative_mode(screen,username
, used_movies)
The play_creative_mode function manages the
gameplay for a movie-quote guessing game in
creative mode. It initializes game variables,
including score, hint count, and time limits, while
continuously fetching random movie quotes from
a database. The player interacts with the game by
entering their guesses, using hints, and managing
time constraints. The function includes logic for
rendering the game screen, displaying quotes,
score, hints, and remaining time, and it updates the
game state based on user inputs. If the player
guesses incorrectly or the time runs out, the
game ends, displaying the score and updating the
leaderboard before offering options for the next
steps.

35. special_level()
The special_level function implements a card-
matching game where players match quotes with
their corresponding movies. It initializes game

23 | P a g e
parameters, including score, attempts, and a
countdown timer set for 2 minutes. The function
retrieves random quotes and their matching
movies from a database, creates and shuffles
cards, and manages player interactions through
mouse clicks to reveal cards. When two cards
are selected, it checks for a match, updating the
score and the number of gems obtained. The
function handles the game state, including
displaying the game board, managing time, and
ending the game either when all pairs are found or
time runs out. After the game ends, it presents the
final score, congratulating the player or indicating
game over.

36. display_game_mode(screen)
The display_game_mode function presents a
menu screen where players can select between
different game modes: Survival, Creative, or
access instructions, a store, or a special level. It
initializes buttons for each option and checks for
user interactions, playing a sound on button
clicks. The function retrieves the status of the
special level from the database to determine if it
should be accessible. It updates the screen with a
background, animated stars, and button states,
applying visual effects like color changes on
hover. The function loops until the player selects
a mode or option, then returns the chosen game
mode to the calling function.

24 | P a g e
37.display_score_and_time(screen,score,
average_time, num_questions)
The display_score_and_time function shows a
game-over screen for seven seconds, displaying
the player's final score and the average time per
question answered. It runs a loop that listens for
quit events and updates the screen with a
background, animated stars, and the score text. If
the player answered any questions, it calculates
and displays the average time per question;
otherwise, it indicates that no questions were
answered. The function also incorporates a flame
effect that responds to mouse position, enhancing
the visual experience before exiting after the
designated time.

38.display_end_options(screen,
leaderboard,mode,score,num_questions=
0)
The display_end_options function presents the
player with options after completing a game,
including the ability to play again, view the
leaderboard, or quit. The function initializes a
graphical interface with buttons for each option,
and it handles user input by listening for mouse
clicks. If the player selects "Play Again," it plays a
sound and returns a corresponding string; if
"Leaderboard" is chosen, it calls the function to
display the leaderboard. The "Quit" option exits the
game. Throughout the loop, it continuously
updates the display with the background,
animated stars, and button hover effects,
enhancing the visual experience.

25 | P a g e
39. ask_to_continue_as_same_user
(screen, username)
The ask_to_continue_as_same_user function
prompts the user to decide whether to continue
with the same username or choose a new one. It
displays a message asking if the user wants to
continue, along with the current username
centered on the screen. The function features
two buttons—"Yes" and "No"—that the user can
click. If the "Yes" button is clicked, the function
returns the username in lowercase, allowing the
user to continue. If "No" is selected, it calls another
function to retrieve a new username. Throughout
the loop, the function updates the display with
background visuals, animated stars, and button
hover effects to enhance the user interface
experience.

40. countdown(screen)
The countdown function displays a countdown
from 3 to 1 on the screen, accompanied by a
countdown sound effect. For each number, it
creates a visual effect where the number fades
in and out over a period of one second, with a half-
second fade-out after displaying each number.
During the countdown, the background and
animated stars are redrawn, and mouse events
are processed, allowing the user to adjust sound
settings through a speaker button. The function
ensures that the countdown numbers are
centered on the screen and handles quitting the
game if the window is closed. The overall effect

26 | P a g e
creates a dynamic and engaging countdown
experience before starting a game or a new level.

41. main()
The main function initializes the Pygame
environment for the game "FILMANIA," setting up
the screen and creating visual effects like stars.
It manages the user interface flow, starting with
the display of the start menu and prompting the
user to enter their username. It checks if the
username already exists in the database; if not, it
adds the new user. The game then enters a loop
where it allows the player to select between
"survival" and "creative" game modes. For each
mode, it manages the flow of gameplay, including
difficulty selection, a countdown, playing the
game, updating the leaderboard, and displaying
the score. Players are given options to play again
or quit, with appropriate sound effects and user
prompts to enhance the experience. The loop
continues until the player decides to quit the
game.

27 | P a g e
SOURCE CODE

import pygame
import random
import math
import csv
from mysql.connector.pooling import MySQLConnectionPool
import mysql.connector as sql
import threading
from sys import exit
import re
import textwrap

class FlameEffect:
def __init__(self, screen_width, screen_height):
self.SCREEN_WIDTH = screen_width
self.SCREEN_HEIGHT = screen_height
self.flame = Flame(screen_width // 2, screen_height // 2)

def update(self, x, y):


self.flame.update_position(x, y)

def draw(self, screen):


self.flame.draw_flame(screen)

class FlameParticle:
alpha_layer_qty = 2
alpha_glow_difference_constant = 2

def __init__(self, x, y, r=5):


self.x = x
self.y = y
self.r = r
self.original_r = r
self.alpha_layers = FlameParticle.alpha_layer_qty
self.alpha_glow = FlameParticle.alpha_glow_difference_constant
max_surf_size = 2 * self.r * self.alpha_layers * self.alpha_layers
* self.alpha_glow
self.surf = pygame.Surface((max_surf_size, max_surf_size),
pygame.SRCALPHA)
self.burn_rate = 0.1 * random.randint(1, 4)

def update(self):
self.y -= 7 - self.r
self.x += random.randint(-self.r, self.r)
self.original_r -= self.burn_rate
self.r = int(self.original_r)
if self.r <= 0:
self.r = 1

def draw(self, screen):


max_surf_size = 2 * self.r * self.alpha_layers * self.alpha_layers
* self.alpha_glow
self.surf = pygame.Surface((max_surf_size, max_surf_size),
pygame.SRCALPHA)

28 | P a g e
for i in range(self.alpha_layers, -1, -1):
alpha = 255 - i * (255 // self.alpha_layers - 5)
if alpha <= 0:
alpha = 0
radius = self.r * i * i * self.alpha_glow
if self.r == 4 or self.r == 3:
r, g, b = (255, 69, 0)
elif self.r == 2:
r, g, b = (255, 140, 0)
else:
r, g, b = (255, 215, 0)
color = (r, g, b, alpha)
pygame.draw.circle(self.surf, color, (self.surf.get_width() //
2, self.surf.get_height() // 2), radius)
screen.blit(self.surf, self.surf.get_rect(center=(self.x, self.y)))

class Flame:
def __init__(self, x, y):
self.x = x
self.y = y
self.flame_intensity = 2
self.flame_particles = []
for i in range(self.flame_intensity * 25):
self.flame_particles.append(FlameParticle(self.x +
random.randint(-5, 5), self.y, random.randint(1, 5)))

def update_position(self, x, y):


self.x = x
self.y = y

def draw_flame(self, screen):


for i in self.flame_particles:
if i.original_r <= 0:
self.flame_particles.remove(i)
self.flame_particles.append(FlameParticle(self.x +
random.randint(-5, 5), self.y, random.randint(1, 5)))
del i
else:
i.update()
i.draw(screen)

def load_movies_from_file(filename):
movies = {"easy": {}, "medium": {}, "hard": {}}
current_difficulty = None

with open(filename, 'r', encoding='utf-8') as file:


for line in file:
line = line.strip()
if line.startswith('[') and line.endswith(']'):
current_difficulty = line[1:-1].lower()
elif ':' in line and current_difficulty:
movie, quote = line.split(':', 1)
movies[current_difficulty][movie.strip()] = [quote.strip()]

return movies

db = sql.connect(host='localhost', user='root',
password='hughjackman@wolverine', database='filmania')
cur = db.cursor()
db_config = {
'host': 'localhost',

29 | P a g e
'database': 'filmania',
'user': 'root',
'password': 'hughjackman@wolverine'
}

pool = MySQLConnectionPool(pool_name="mypool", pool_size=5, **db_config)

def get_db_connection():
return pool.get_connection()

question_cache = []
next_question = None

def preload_questions(num_questions=10):
global question_cache
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
query = "SELECT quote, correct_answer FROM questions ORDER BY RAND()
LIMIT %s"
cursor.execute(query, (num_questions,))
question_cache = cursor.fetchall()
cursor.close()
connection.close()

def load_next_question():
global next_question
if not question_cache:
preload_questions()
next_question = question_cache.pop()

def get_random_quote_from_db():
global next_question
if next_question is None:
load_next_question()
current_question = next_question
threading.Thread(target=load_next_question).start()
return current_question['quote'], current_question['correct_answer']

# Initialize pygame
pygame.init()
pygame.mixer.init()

pygame.mixer.music.load('flicker.mp3')
pygame.mixer.music.play()

# Load click sound effect


click_sound = pygame.mixer.Sound('enter.wav')
mouse_click_sound = pygame.mixer.Sound('123.mp3')
netflix_sound = pygame.mixer.Sound('netflix.mp3') # Load Netflix sound
effect
female_instruction = pygame.mixer.Sound('female instruction.mp3')
meendum = pygame.mixer.Sound('meendum.mp3')
meendum.set_volume(1) # Set the volume to maximum (1) or adjust as needed
movies = load_movies_from_file('movie_quotes.txt')

# Screen dimensions
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height),
pygame.SRCALPHA)
pygame.display.set_caption("FILMANIA")

30 | P a g e
# Colors
white = (255, 255, 255)
black = (0, 0, 0)
gray = (200, 200, 200)
red = (255, 0, 0)

# Font
font = pygame.font.Font('sketch.ttf', 40)
font1 = pygame.font.Font('sketch.ttf', 45)

# Load and scale background image


background_image = pygame.image.load('background.jpg')
background_image = pygame.transform.scale(background_image, (screen_width,
screen_height))

# Load button images


easy_button_image = pygame.image.load('10.png')
medium_button_image = pygame.image.load('456.png')
hard_button_image = pygame.image.load('789.png')

# Volume Slider
WIDTH, HEIGHT = 640, 480
SLIDER_WIDTH = 300
SLIDER_HEIGHT = 8
SLIDER_HANDLE_RADIUS = 15
VOLUME_MIN = 0.0
VOLUME_MAX = 1.0
slider_start_x = 250 # X position of the slider start
slider_y = 300 # Y position of the slider center
slider_end_x = slider_start_x + SLIDER_WIDTH
volume = 1.0
slider_handle_x = slider_start_x + SLIDER_WIDTH * volume
volume_text_x = 360 # X position of the volume text
volume_text_y = 320 # Y position of the volume text
bg_color = (30, 30, 30) # Dark background
slider_bg_color = (50, 50, 50) # Dark slider background
slider_active_color = (0, 128, 255) # Active slider bar color
handle_color = (255, 255, 255) # White handle with glow
handle_glow_color = (0, 128, 255) # Light blue for the glowing effect
shadow_color = (0, 0, 0, 100) # Semi-transparent black for shadow
text_color = (255, 255, 255) # White for the text
target_handle_x = slider_handle_x
handle_animation_speed = 0.1
# Arrow key press flags
right_arrow_held = False
left_arrow_held = False
hold_interval = 100
# Timer variables for 100-millisecond delay between volume changes
right_arrow_last_press = 0
left_arrow_last_press = 0
# Function to draw a circle with glow effect
def draw_glowing_circle(screen, color, position, radius, glow_radius):
for i in range(glow_radius):
alpha = max(0, 255 - int(255 * (i / glow_radius))) # Alpha
decreases with distance
glow_color = (*color[:3], alpha) # Create the glowing color
pygame.draw.circle(screen, glow_color, position, radius + i)

# Function to draw the slider handle with shadow


def draw_slider_handle(screen, position):

31 | P a g e
# Draw shadow
pygame.draw.circle(screen, (0, 0, 0, 128), position,
SLIDER_HANDLE_RADIUS + 5)
# Draw the handle
draw_glowing_circle(screen, handle_glow_color, position,
SLIDER_HANDLE_RADIUS, 10)
pygame.draw.circle(screen, handle_color, position,
SLIDER_HANDLE_RADIUS)

# Function to update the volume and the slider handle position


def update_volume(delta):
global volume, target_handle_x, slider_handle_x
volume += delta # Increment or decrement the volume
volume = max(VOLUME_MIN, min(volume, VOLUME_MAX)) # Clamp volume
between 0% and 100%
target_handle_x = slider_start_x + SLIDER_WIDTH * volume # Update the
slider handle position
# Set the new volume
pygame.mixer.music.set_volume(volume)
female_instruction.set_volume(volume)

# Heart image
red_heart = pygame.image.load('heart.png')
grey_heart = pygame.image.load('lost heart.png')
wid = int(red_heart.get_width()*0.2)
hei = int(red_heart.get_height()*0.2)
red_heart = pygame.transform.scale(red_heart, (wid, hei))
grey_heart = pygame.transform.scale(grey_heart, (wid, hei))

# Clock image
pause_button = pygame.image.load('clock.png')
pause_button_off = pygame.image.load('dead_clock.png')
wid = int(pause_button.get_width()*0.15)
hei = int(pause_button.get_height()*0.15)
pause_button = pygame.transform.scale(pause_button, (wid, hei))
pause_button_off = pygame.transform.scale(pause_button_off, (wid, hei))

#Hint image
hint_button = pygame.image.load('hint_on.png')
hint_button_off = pygame.image.load('hint_off.png')
wid = int(hint_button.get_width()*0.13)
hei = int(hint_button.get_height()*0.13)
hint_button = pygame.transform.scale(hint_button, (wid, hei))
hint_button_off = pygame.transform.scale(hint_button_off, (wid, hei))

# Golden clock image


add_time_button = pygame.image.load('golden clock.png')
add_time_button_off = pygame.image.load('dead golden clock.png')
wid = int(add_time_button.get_width()*0.12)
hei = int(add_time_button.get_height()*0.12)
add_time_button = pygame.transform.scale(add_time_button, (wid, hei))
add_time_button_off = pygame.transform.scale(add_time_button_off, (wid,
hei))

# Lock and Unlock


lock_button = pygame.image.load('locked.png')
unlock_button = pygame.image.load('unlocked.png')
wid = int(lock_button.get_width() * 0.5)
hei = int(lock_button.get_height() * 0.5)
lock_button = pygame.transform.scale(lock_button, (wid, hei))
unlock_button = pygame.transform.scale(unlock_button, (wid, hei))

32 | P a g e
# skip image
skip_button = pygame.image.load('skip.png')
skip_button_off = pygame.image.load('empty skip.png')
wid = int(skip_button.get_width()*0.15)
hei = int(skip_button.get_height()*0.15)
wid_store = int(skip_button.get_width()*0.17)
hei_store = int(skip_button.get_height()*0.17)
skip_button = pygame.transform.scale(skip_button, (wid, hei))
skip_store = pygame.transform.scale(skip_button, (wid_store, hei_store))
skip_button_off = pygame.transform.scale(skip_button_off, (wid, hei))

# Speaker image
speaker_button = pygame.image.load('speaker.png')
wid = int(speaker_button.get_width()*0.04)
hei = int(speaker_button.get_height()*0.04)
speaker_button = pygame.transform.scale(speaker_button, (wid, hei))

# Currency images
coin_button = pygame.image.load('coin.png')
gem_button = pygame.image.load('gem.png')
c_wid = int(coin_button.get_width()*0.25)
g_wid = int(gem_button.get_width()*0.22)
c_hei = int(coin_button.get_height()*0.25)
g_hei = int(gem_button.get_height()*0.22)
coin_button = pygame.transform.scale(coin_button, (c_wid, c_hei))
gem_button = pygame.transform.scale(gem_button, (g_wid, g_hei))

# buy image
buy_button = pygame.image.load('buy now.png')
buy_button_off = pygame.image.load('buy now_off.png')
wid = int(buy_button.get_width()*0.2)
hei = int(buy_button.get_height()*0.2)
buy_button = pygame.transform.scale(buy_button, (wid, hei))
buy_button_off = pygame.transform.scale(buy_button_off, (wid, hei))

# Screen dimensions (make sure these are defined in your main script)
screen_width = 800
screen_height = 600

# Number of stars
NUM_STARS = 200

class MatrixColumn:
def __init__(self, x, font):
self.x = x
self.font = font
self.chars = []
self.base_speed = random.uniform(1, 3)
self.speed = self.base_speed
self.length = random.randint(5, 30)
self.wave_offset = random.uniform(0, 2 * math.pi)
self.color_shift = 0
self.reset()

def reset(self):
self.y = random.randint(-300, -50)
self.chars = [self.random_char() for _ in range(self.length)]
self.colors = [(0, random.randint(50, 255), 0) for _ in

33 | P a g e
range(self.length)]
self.colors[0] = (180, 255, 180) # Brighter green for the first
character

def random_char(self):
return
random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567
89@#$%^&*()_+-=[]{}|;:,.<>?")

def move(self, time):


# Wave-like motion
self.x = self.x + math.sin(time * 0.01 + self.wave_offset) * 0

# Pulsating speed
self.speed = self.base_speed + math.sin(time * 0.005) * 0.5

self.y += self.speed
if self.y > screen_height:
self.reset()

# Randomly change some characters


for i in range(1, len(self.chars)):
if random.random() < 0.02:
self.chars[i] = self.random_char()

# Color shifting
self.color_shift = (self.color_shift + 0.02) % (2 * math.pi)

# Update colors with shifting effect


for i in range(len(self.colors)):
r = int((math.sin(self.color_shift + i * 0.1) * 0.5 + 0.5) *
100)
g = int((math.sin(self.color_shift + i * 0.1 + 2) * 0.5 + 0.5)
* 255)
b = int((math.sin(self.color_shift + i * 0.1 + 4) * 0.5 + 0.5)
* 100)
self.colors[i] = (r, g, b)

# Keep the first character bright


self.colors[0] = (180, 255, 180)

def create_stars(num_columns):
global matrix_columns
font = pygame.font.Font(None, 14)
spacing = screen_width // num_columns
matrix_columns = [MatrixColumn(i * spacing, font) for i in
range(num_columns)]

def update_stars():
current_time = pygame.time.get_ticks()
for column in matrix_columns:
column.move(current_time)

def draw_stars(screen):
for column in matrix_columns:
for i, (char, color) in enumerate(zip(column.chars,
column.colors)):
y = column.y + i * 14 # 14 is the font size
if 0 <= y < screen_height:
char_surface = column.font.render(char, True, color)
screen.blit(char_surface, (int(column.x), int(y)))

34 | P a g e
# Function to display text
def draw_text(surface, text, color, rect, font, aa=False, bkg=None):
rect = pygame.Rect(rect)
y = rect.top
line_spacing = -2

# Get the height of the font


font_height = font.size("Tg")[1]

while text:
i = 1
if y + font_height > rect.bottom:
break

# Determine if the row of text will be outside the clip box


while font.size(text[:i])[0] < rect.width and i < len(text):
i += 1

# If we've wrapped the text, then adjust back to the last word
if i < len(text):
i = text.rfind(" ", 0, i) + 1

image = font.render(text[:i], aa, color, bkg)

surface.blit(image, (rect.left, y))


y += font_height + line_spacing

text = text[i:]

return text

def display_instructions(screen):
screen.fill((0, 0, 0))
done = False
female_instruction.play()
start_time = pygame.time.get_ticks()
meendum.set_volume(0) # Pause the audio track meendum
pygame.mixer.music.pause() # Pause the background music
flame_effect = FlameEffect(screen_width, screen_height)

# speaker button
speaker_button_rect = speaker_button.get_rect(center=(750, 550))

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
female_instruction.stop()
female_instruction.play()
start_time = pygame.time.get_ticks()
if event.key == pygame.K_RETURN:
click_sound.play()
female_instruction.stop()
pygame.mixer.music.unpause() # Unpause the background
music
done = True
if event.type == pygame.MOUSEBUTTONDOWN:

35 | P a g e
if speaker_button_rect.collidepoint(event.pos):
mouse_click_sound.play()
sound_volume(screen)

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

draw_text(screen, "LISTEN TO THE BRIEFING CAREFULLY", (255,255,0),


pygame.Rect(176, 240, 600, 200), font)
draw_text(screen, "Press ENTER to continue", (0,255,0),
pygame.Rect(253, 300, 600, 200), font)
draw_text(screen, "Press 'R' to repeat the briefing", (255,0,0),
pygame.Rect(220, 360, 600, 200), font)

# draw speaker button


screen.blit(speaker_button, speaker_button_rect.topleft)

pygame.display.flip()

def sound_volume(screen):
global right_arrow_held
global left_arrow_held
global slider_handle_x
global target_handle_x
global volume
global left_arrow_last_press
global right_arrow_last_press
flame_effect = FlameEffect(screen_width, screen_height)
done = False
while not done:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0]: # If the left mouse button is pressed
mouse_x, mouse_y = event.pos
if slider_start_x <= mouse_x <= slider_end_x and
(slider_y - SLIDER_HEIGHT / 2) <= mouse_y <= (
slider_y + SLIDER_HEIGHT / 2):
target_handle_x = mouse_x
volume = (target_handle_x - slider_start_x) /
(SLIDER_WIDTH)
volume = max(VOLUME_MIN, min(volume, VOLUME_MAX))
# Clamp the volume to the valid range
pygame.mixer.music.set_volume(volume)
# Check for arrow key presses
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT: # Right arrow key pressed
right_arrow_held = True # Set the flag to True
elif event.key == pygame.K_LEFT: # Left arrow key pressed
left_arrow_held = True # Set the flag to True
elif event.key == pygame.K_RETURN:
click_sound.play()
female_instruction.stop()
pygame.mixer.music.unpause() # Unpause the background

36 | P a g e
music
done = True

# Check for arrow key releases


elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT: # Right arrow key released
right_arrow_held = False # Set the flag to False
elif event.key == pygame.K_LEFT: # Left arrow key released
left_arrow_held = False # Set the flag to False

# Draw bg
screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Update volume if the right arrow is held for the specified


interval
if right_arrow_held and current_time - right_arrow_last_press >=
hold_interval:
update_volume(0.01) # Increase volume by 1%
right_arrow_last_press = current_time # Reset the timer

# Update volume if the left arrow is held for the specified


interval
if left_arrow_held and current_time - left_arrow_last_press >=
hold_interval:
update_volume(-0.01) # Decrease volume by 1%
left_arrow_last_press = current_time # Reset the timer

# Smooth animation of handle movement


slider_handle_x += (target_handle_x - slider_handle_x) *
handle_animation_speed

# Draw slider background


pygame.draw.rect(screen, slider_bg_color,
(slider_start_x, slider_y - SLIDER_HEIGHT / 2,
SLIDER_WIDTH, SLIDER_HEIGHT),
border_radius=4)

# Draw the active part of the slider bar


active_slider_width = int((slider_handle_x - slider_start_x) *
(SLIDER_WIDTH / SLIDER_WIDTH))
pygame.draw.rect(screen, slider_active_color,
(slider_start_x, slider_y - SLIDER_HEIGHT / 2,
active_slider_width, SLIDER_HEIGHT),
border_radius=4)

# Draw the handle with shadow and glow


draw_slider_handle(screen, (int(slider_handle_x), slider_y))

# Draw volume text at the custom position with a more minimalist


font
volume_text = font.render(f"{int(volume * 100)}%", True,
text_color)
text = font.render(f"Adjust Volume!!!", True, text_color)
draw_text(screen, "Press ENTER to continue", (0, 255, 0),
pygame.Rect(253, 375, 600, 200), font)
screen.blit(text, (100, 100))

37 | P a g e
screen.blit(volume_text, (volume_text_x, volume_text_y)) #
Positioning the text using custom variables

# Update the display


pygame.display.flip()

def display_currency():
#limit
cur.execute(f'select * from store where username = "{username}"')
data = cur.fetchall()[0]
Skips, clock, gold_clock = data[3], data[4], data[5]
if Skips > 7:
cur.execute(f'update store set skips = 7 where username =
"{username}"')
db.commit()
if clock > 5:
cur.execute(f'update store set clocks = 5 where username =
"{username}"')
db.commit()
if gold_clock > 2:
cur.execute(f'update store set golden_clocks = 2 where username =
"{username}"')
db.commit()
global coins, gems
coins = cur.execute(f'''select coins from store where username =
"{username}"''')
coins = cur.fetchall()[0][0]
gems = cur.execute(f'''select gems from store where username =
"{username}"''')
gems = cur.fetchall()[0][0]
skips = cur.execute(f'''select skips from store where username =
"{username}"''')
skips = cur.fetchall()[0][0]
clocks = cur.execute(f'''select clocks from store where username =
"{username}"''')
clocks = cur.fetchall()[0][0]
golden_clocks = cur.execute(f'''select golden_clocks from store where
username = "{username}"''')
golden_clocks = cur.fetchall()[0][0]
screen.blit(coin_button, (30, 30))
draw_text(screen, f"{coins}", (255, 215, 0), pygame.Rect(100, 40, 200,
50), font)
screen.blit(gem_button, (180, 32))
draw_text(screen, f"{gems}", (15, 82, 186), pygame.Rect(255, 40, 200,
50), font)
screen.blit(skip_button, (330, 25))
draw_text(screen, f"{skips}", (54, 1, 63), pygame.Rect(410, 40, 200,
50), font)
screen.blit(pause_button, (470, 28))
draw_text(screen, f"{clocks}", (255, 0, 0), pygame.Rect(550, 40, 200,
50), font)
screen.blit(add_time_button, (600, 30))
draw_text(screen, f"{golden_clocks}", (255, 0, 0), pygame.Rect(690, 40,
200, 50), font)
return coins, gems

def store(screen):
global Skips, clock, gold_clock
screen.fill((0, 0, 0))
flame_effect = FlameEffect(screen_width, screen_height)
done = False

38 | P a g e
# Buy button
buy_button_rect1 = buy_button.get_rect(center=(220, 200))
buy_button_rect2 = buy_button.get_rect(center=(220, 350))
buy_button_rect3 = buy_button.get_rect(center=(220, 500))
buy_button_rect4 = buy_button.get_rect(center=(620, 200))
buy_button_rect5 = buy_button.get_rect(center=(620, 350))

message = ""
message_end_time = 0
message_end_time1 = 0

while not done:


# draw background
screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)
display_currency()
cur.execute(f'select * from store where username = "{username}"')
data = cur.fetchall()[0]
Skips, clock, gold_clock, spl_level = data[3], data[4], data[5],
data[6]
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
if buy_button_rect1.collidepoint(event.pos):
if Skips < 7:
mouse_click_sound.play()
if coins >= 5:
cur.execute(f'update store set coins = coins -
5 WHERE username = "{username}"')
cur.execute(f'update store set skips = skips +
1 WHERE username = "{username}"')
db.commit()
message = "Purchased successfully!!!"
message_end_time1 = pygame.time.get_ticks() +
2000
else:
message = "You don't have enough coins"
message_end_time = pygame.time.get_ticks() +
2000
else:
message = "You have reached your limit!!!"
message_end_time = pygame.time.get_ticks() + 2000
if buy_button_rect2.collidepoint(event.pos):
if clock < 5:
mouse_click_sound.play()
if coins >= 10:
cur.execute(f'update store set coins = coins -
10 where username = "{username}" ')
cur.execute(f'update store set clocks = clocks
+ 1 where username = "{username}" ')

39 | P a g e
db.commit()
message = "Purchased successfully!!!"
message_end_time1 = pygame.time.get_ticks() +
2000
else:
message = "You don't have enough coins"
message_end_time = pygame.time.get_ticks() +
2000
else:
message = "You have reached your limit!!!"
message_end_time = pygame.time.get_ticks() + 2000
if buy_button_rect3.collidepoint(event.pos):
mouse_click_sound.play()
if coins >= 20:
cur.execute(f'update store set coins = coins - 20
where username = "{username}" ')
cur.execute(f'update store set gems = gems + 1
where username = "{username}" ')
db.commit()
message = "Purchased successfully!!!"
message_end_time1 = pygame.time.get_ticks() + 2000
else:
message = "You don't have enough coins"
message_end_time = pygame.time.get_ticks() + 2000
if buy_button_rect4.collidepoint(event.pos):
if gold_clock < 2:
mouse_click_sound.play()
if gems >= 10:
cur.execute(f'update store set gems = gems - 10
where username = "{username}" ')
cur.execute(
f'update store set golden_clocks =
golden_clocks + 1 where username = "{username}" ')
db.commit()
message = "Purchased successfully!!!"
message_end_time1 = pygame.time.get_ticks() +
2000
else:
message = "You don't have enough gems"
message_end_time = pygame.time.get_ticks() +
2000
else:
message = "You have reached your limit!!!"
message_end_time = pygame.time.get_ticks() + 2000
if buy_button_rect5.collidepoint(event.pos):
if spl_level == "False":
mouse_click_sound.play()
if gems >= 50:
cur.execute(f'update store set gems = gems - 50
where username = "{username}" ')
cur.execute(f'update store set special_level =
"True" where username = "{username}" ')
db.commit()
message = "Purchased successfully!!!"
message_end_time1 = pygame.time.get_ticks() +
2000
else:
message = "You don't have enough gems"
message_end_time = pygame.time.get_ticks() +
2000
else:

40 | P a g e
message = "You have reached your limit!!!"
message_end_time = pygame.time.get_ticks() + 2000

draw_text(screen, "1.", (255, 255, 255), pygame.Rect(50, 120, 700,


200), font)
screen.blit(skip_store, (100, 100))
draw_text(screen, "Cost:", (255, 255, 255), pygame.Rect(175, 120,
700, 200), font)
draw_text(screen, "5 Coins", (255, 255, 255), pygame.Rect(250, 120,
700, 200), font)
if Skips < 7:
screen.blit(buy_button, buy_button_rect1.topleft)
else:
screen.blit(buy_button_off, buy_button_rect1.topleft)

draw_text(screen, "2.", (255, 255, 255), pygame.Rect(50, 270, 700,


200), font)
screen.blit(pause_button, (100, 250))
draw_text(screen, "Cost:", (255, 255, 255), pygame.Rect(175, 270,
700, 200), font)
draw_text(screen, "10 Coins", (255, 255, 255), pygame.Rect(250,
270, 700, 200), font)
if clock < 5:
screen.blit(buy_button, buy_button_rect2.topleft)
else:
screen.blit(buy_button_off, buy_button_rect2.topleft)

draw_text(screen, "3.", (255, 255, 255), pygame.Rect(50, 420, 700,


200), font)
screen.blit(gem_button, (100, 400))
draw_text(screen, "Cost:", (255, 255, 255), pygame.Rect(175, 420,
700, 200), font)
draw_text(screen, "20 Coins", (255, 255, 255), pygame.Rect(250,
420, 700, 200), font)
screen.blit(buy_button, buy_button_rect3.topleft)

draw_text(screen, "4.", (255, 255, 255), pygame.Rect(450, 120, 700,


200), font)
screen.blit(add_time_button, (500, 100))
draw_text(screen, "Cost:", (255, 255, 255), pygame.Rect(575, 120,
700, 200), font)
draw_text(screen, "10 gems", (255, 255, 255), pygame.Rect(650, 120,
700, 200), font)
if gold_clock < 2:
screen.blit(buy_button, buy_button_rect4.topleft)
else:
screen.blit(buy_button_off, buy_button_rect4.topleft)

draw_text(screen, "5.", (255, 255, 255), pygame.Rect(450, 270, 700,


200), font)
if spl_level == "False":
screen.blit(lock_button, (460, 215))
else:
screen.blit(unlock_button, (460, 215))
draw_text(screen, "Cost:", (255, 255, 255), pygame.Rect(575, 270,
700, 200), font)
draw_text(screen, "50 gems", (255, 255, 255), pygame.Rect(650, 270,
700, 200), font)
if spl_level == "False":
screen.blit(buy_button, buy_button_rect5.topleft)
else:

41 | P a g e
screen.blit(buy_button_off, buy_button_rect5.topleft)

draw_text(screen, "Press Enter to go back!!", (255, 255, 255),


pygame.Rect(350, 500, 400, 50), font)

#display any message


if pygame.time.get_ticks() < message_end_time:
draw_text(screen, message, (255, 0, 0), pygame.Rect(350, 450,
400, 50), font)
if pygame.time.get_ticks() < message_end_time1:
draw_text(screen, message, (0, 255, 0), pygame.Rect(350, 450,
400, 50), font)

pygame.display.flip()

# Function to display start menu


def display_start_menu(screen):
score = 0
screen.fill((0, 0, 0))
done = False
show_press_enter = False
start_time = pygame.time.get_ticks()
blink_interval = 700 # Adjust this value to control the speed of
blinking (in milliseconds)
stop_time = 6000 # Adjust this value to control the time of stopping
(in milliseconds)
blink_timer = pygame.time.get_ticks() # Initialize the blink timer
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
done = True

# Calculate starting position in milliseconds (assuming


44100 Hz sample rate as a common default)
start_pos_ms = 400 # 2 seconds
start_pos_samples = int(start_pos_ms * 44.1) #
Assuming 44100 samples per second

# Get sound data as bytes


sound_data = netflix_sound.get_raw()

# Ensure we don't go beyond the sound data length


start_pos_bytes = min(start_pos_samples * 2,
len(sound_data)) # Assuming 2 bytes per sample (16-bit audio)

# Play from the calculated position


pygame.mixer.music.load('netflix.mp3') # Load using
the file path
pygame.mixer.music.play(start=start_pos_samples /
44100) # Start position in seconds
done = True

screen.blit(background_image, (0, 0))


draw_stars(screen)

42 | P a g e
update_stars()

if pygame.time.get_ticks() - start_time < stop_time:


if pygame.time.get_ticks() - blink_timer >= blink_interval:
blink_timer = pygame.time.get_ticks() # Reset the blink
timer
if (pygame.time.get_ticks() - blink_timer) < (blink_interval /
2):
draw_text(screen, "Are you ready?", red, pygame.Rect(300,
250, 200, 50), pygame.font.Font('sketch.ttf', 46), True)
else:
draw_text(screen, "Are you ready?", (0,255,255),
pygame.Rect(300, 250, 200, 50), pygame.font.Font('sketch.ttf', 46), True)
else:
draw_text(screen, "Are you ready?", red, pygame.Rect(300, 250,
200, 50), pygame.font.Font('sketch.ttf', 46), True)
draw_text(screen, "Press Enter to start", (0,255,255),
pygame.Rect(270, 300, 260, 50), pygame.font.Font('sketch.ttf', 46), True)

mouse_x, mouse_y = pygame.mouse.get_pos()


flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

pygame.display.flip()

return score
# Function to get the username
def get_username(screen):
input_box = pygame.Rect(200, 300, 400, 50)
color_inactive = pygame.Color('lightskyblue3')
color_active = pygame.Color('dodgerblue2')
color = color_inactive
active = False
text = ''
password = ''
done = False
flame_effect = FlameEffect(screen_width, screen_height)

message = ""
message_end_time = 0
state = "username"

forgot_password_button = pygame.Rect(500, 360, 200, 50)

# New: Show password checkbox


show_password = False
checkbox_rect = pygame.Rect(200, 370, 20, 20)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_box.collidepoint(event.pos):
mouse_click_sound.play()
active = not active
elif checkbox_rect.collidepoint(event.pos) and state !=
"username":
show_password = not show_password

43 | P a g e
mouse_click_sound.play()
else:
active = False
color = color_active if active else color_inactive

if state == "enter_password" and


forgot_password_button.collidepoint(event.pos):
mouse_click_sound.play()
state = "forgot_password"
password = ''
message = "Enter your new password"
message_end_time = pygame.time.get_ticks() + 2000
if event.type == pygame.KEYDOWN:
if active:
if event.key == pygame.K_RETURN:
if state == "username":
if text.strip():
cur.execute("SELECT username FROM store
WHERE username = %s", (text.lower(),))
if cur.fetchone():
state = "enter_password"
message = "Enter your password"
else:
state = "create_password"
message = "Create a password"
password = ''
else:
message = "Please enter a username!"
message_end_time = pygame.time.get_ticks() +
2000
elif state == "create_password" or state ==
"enter_password":
if password.strip():
if state == "create_password":
is_valid, validation_message =
is_password_valid(password)
if is_valid:
cur.execute("INSERT INTO store
(username, password) VALUES (%s, %s)",
(text.lower(),
password))
db.commit()
return text.lower()
else:
message = validation_message
password = ''
else: # enter_password
if verify_password(text.lower(),
password):
return text.lower()
else:
message = "Incorrect password"
password = ''
message_end_time = pygame.time.get_ticks()
+ 2000
else:
message = "Please enter a password!"
message_end_time = pygame.time.get_ticks()
+ 2000
elif state == "forgot_password":
if password.strip():

44 | P a g e
is_valid, validation_message =
is_password_valid(password)
if is_valid:
cur.execute("UPDATE store SET password
= %s WHERE username = %s",
(password, text.lower()))
db.commit()
message = "Password changed. Please
enter your new password."
state = "enter_password"
password = ''
else:
message = validation_message
password = ''
else:
message = "Please enter a new password!"
message_end_time = pygame.time.get_ticks() +
2000
elif event.key == pygame.K_BACKSPACE:
if state == "username":
text = text[:-1]
else:
password = password[:-1]
else:
if state == "username":
text += event.unicode
else:
password += event.unicode

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

if state == "username":
draw_text(screen, "Enter your username:", (255, 255, 0),
pygame.Rect(200, 230, 400, 50), font)
txt_surface = font.render(text, True, color)
else:
draw_text(screen, message, (255, 255, 0), pygame.Rect(200, 230,
400, 50), font)
if show_password:
txt_surface = font.render(password, True, color)
else:
txt_surface = font.render('*' * len(password), True, color)

width = max(400, txt_surface.get_width() + 10)


input_box.w = width
screen.blit(txt_surface, (input_box.x + 5, input_box.y + 5))
pygame.draw.rect(screen, color, input_box, 2)

if state == "username":
draw_text(screen, "Tip: Keep it short and snappy! ", (255, 0,
255), pygame.Rect(200, 370, 400, 50), font)
else:
# Draw checkbox
pygame.draw.rect(screen, (255, 255, 255), checkbox_rect, 2)
if show_password:
pygame.draw.line(screen, (255, 255, 255),

45 | P a g e
checkbox_rect.topleft, checkbox_rect.bottomright, 2)
pygame.draw.line(screen, (255, 255, 255),
checkbox_rect.topright, checkbox_rect.bottomleft, 2)
draw_text(screen, "Show Password", (255, 255, 255),
pygame.Rect(230, 370, 200, 50), font)

if state == "enter_password":
pygame.draw.rect(screen, (0, 31, 63), forgot_password_button)
forgot_password_button_text = font.render("Forgot Password",
True, (46, 204, 64))
forgot_password_button_text_rect =
forgot_password_button_text.get_rect(
center=forgot_password_button.center)
screen.blit(forgot_password_button_text,
forgot_password_button_text_rect)

if pygame.time.get_ticks() < message_end_time:


draw_text(screen, message, (255, 0, 0), pygame.Rect(200, 430,
400, 50), font)

pygame.display.flip()

return text.lower()

def forgot_password(screen, username):


input_box = pygame.Rect(200, 300, 400, 50)
color_inactive = pygame.Color('lightskyblue3')
color_active = pygame.Color('dodgerblue2')
color = color_inactive
active = False
new_password = ''
done = False
message = "Enter new password"
message_end_time = 0
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_box.collidepoint(event.pos):
active = not active
else:
active = False
color = color_active if active else color_inactive
if event.type == pygame.KEYDOWN:
if active:
if event.key == pygame.K_RETURN:
if new_password.strip():
is_valid, validation_message =
is_password_valid(new_password)
if is_valid:
cur.execute("UPDATE store SET password = %s
WHERE username = %s",
(new_password, username))
db.commit()
return True
else:

46 | P a g e
message = validation_message
new_password = ''
else:
message = "Please enter a new password!"
message_end_time = pygame.time.get_ticks() + 2000
elif event.key == pygame.K_BACKSPACE:
new_password = new_password[:-1]
else:
new_password += event.unicode

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

draw_text(screen, message, (255, 255, 0), pygame.Rect(200, 230,


400, 50), font)
txt_surface = font.render('*' * len(new_password), True, color)
width = max(400, txt_surface.get_width() + 10)
input_box.w = width
screen.blit(txt_surface, (input_box.x + 5, input_box.y + 5))
pygame.draw.rect(screen, color, input_box, 2)

if pygame.time.get_ticks() < message_end_time:


draw_text(screen, message, (255, 0, 0), pygame.Rect(200, 430,
400, 50), font)

pygame.display.flip()

return False

def is_password_valid(password):
if len(password) < 8:
return False, "Password must be at least 8 characters long"
if not re.search(r"[A-Za-z]", password):
return False, "Password must contain at least one letter"
if not re.search(r"\d", password):
return False, "Password must contain at least one number"
if not re.search(r"[!@#$%^&*(),.?\":{}|<>]", password):
return False, "Password must contain at least one symbol"
return True, "Password is valid"

def verify_password(username, password):


cur.execute("SELECT password FROM store WHERE username = %s",
(username,))
result = cur.fetchone()
if result:
stored_password = result[0]
return password == stored_password
return False

def confirm_username(screen, username, existing_usernames):


username_exists = username.lower() in existing_usernames
flame_effect = FlameEffect(screen_width, screen_height)

if not username_exists:

47 | P a g e
return True, False # Username doesn't exist, no need to confirm

yes_button = pygame.Rect(200, 350, 200, 50)


no_button = pygame.Rect(450, 350, 200, 50)
done = False

message1 = f"Username '{username}'"


message2="already exists!"
message3 = "Do you want to continue as this user?"

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if yes_button.collidepoint(event.pos):
mouse_click_sound.play()
return True, True
elif no_button.collidepoint(event.pos):
mouse_click_sound.play()
return False, True

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw messages
draw_text(screen, message1, (255,255,0), pygame.Rect(100, 180, 600,
50), font)
draw_text(screen, message2, (255,0,0), pygame.Rect(100, 230, 600,
50), font)
draw_text(screen, message3, (255, 0, 255), pygame.Rect(100, 280,
600, 50), font)

# Draw buttons
pygame.draw.rect(screen, (0, 31, 63), yes_button)
pygame.draw.rect(screen, (0, 31, 63), no_button)

yes_text = font.render("Yes", True, (46, 204, 64))


no_text = font.render("No", True, (46, 204, 64))

yes_text_rect = yes_text.get_rect(center=yes_button.center)
no_text_rect = no_text.get_rect(center=no_button.center)

screen.blit(yes_text, yes_text_rect)
screen.blit(no_text, no_text_rect)

# Button hover animation


if yes_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), yes_button)
yes_text = font.render("Yes", True, (0, 31, 63))
screen.blit(yes_text, yes_text_rect)
if no_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), no_button)
no_text = font.render("No", True, (0, 31, 63))
screen.blit(no_text, no_text_rect)

48 | P a g e
pygame.display.flip()

# Function to display difficulty options


def display_difficulty(screen):
easy_button = pygame.Rect(150, 250, 150, 50)
medium_button = pygame.Rect(325, 250, 150, 50)
hard_button = pygame.Rect(500, 250, 150, 50)
done = False
difficulty = None
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if easy_button.collidepoint(event.pos):
mouse_click_sound.play()
difficulty = "easy"
done = True
elif medium_button.collidepoint(event.pos):
mouse_click_sound.play()
difficulty = "medium"
done = True
elif hard_button.collidepoint(event.pos):
mouse_click_sound.play()
difficulty = "hard"
done = True

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)
# Draw difficulty buttons
screen.blit(easy_button_image, easy_button.topleft)
screen.blit(medium_button_image, medium_button.topleft)
screen.blit(hard_button_image, hard_button.topleft)

pygame.display.flip()

return difficulty

# Function to ask if the player wants background music


def ask_for_music(screen):
yes_button = pygame.Rect(200, 350, 200, 50)
no_button = pygame.Rect(450, 350, 200, 50)
done = False
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

49 | P a g e
if event.type == pygame.MOUSEBUTTONDOWN:
if yes_button.collidepoint(event.pos):
mouse_click_sound.play()
return True
elif no_button.collidepoint(event.pos):
mouse_click_sound.play()
return False

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw message
draw_text(screen, "READY TO GROOVE?", (255,0,255), pygame.Rect(250,
200, 300, 50), font)

# Draw buttons
pygame.draw.rect(screen, (0, 31, 63), yes_button)
pygame.draw.rect(screen, (0, 31, 63), no_button)

yes_text = font.render("Yes", True, (46, 204, 64))


no_text = font.render("No", True, (46, 204, 64))

yes_text_rect = yes_text.get_rect(center=yes_button.center)
no_text_rect = no_text.get_rect(center=no_button.center)

screen.blit(yes_text, yes_text_rect)
screen.blit(no_text, no_text_rect)

# Button hover animation


if yes_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), yes_button)
yes_text = font.render("Yes", True, (0, 31, 63))
screen.blit(yes_text, yes_text_rect)
if no_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), no_button)
no_text = font.render("No", True, (0, 31, 63))
screen.blit(no_text, no_text_rect)

pygame.display.flip()

# Function to ask the player to choose a music playlist


def choose_music_playlist(screen):
sunny_days_button = pygame.Rect(200, 350, 200, 50)
rainy_nights_button = pygame.Rect(450, 350, 200, 50)
adrenaline_rush_button = pygame.Rect(325, 450, 200, 50)
done = False
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:

50 | P a g e
if sunny_days_button.collidepoint(event.pos):
mouse_click_sound.play()
pygame.mixer.music.load('sunny_days.mp3')
pygame.mixer.music.play(-1)
done = True
elif rainy_nights_button.collidepoint(event.pos):
mouse_click_sound.play()
pygame.mixer.music.load('rainy_nights.mp3')
pygame.mixer.music.play(-1)
done = True
elif adrenaline_rush_button.collidepoint(event.pos):
mouse_click_sound.play()
pygame.mixer.music.load('adrenaline_rush.mp3')
pygame.mixer.music.play(-1)
done = True

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw message
draw_text(screen, "PICK YOUR VIBE!", (255,255,0), pygame.Rect(300,
200, 200, 50), font)

# Draw buttons
pygame.draw.rect(screen, (0, 31, 63), sunny_days_button)
pygame.draw.rect(screen, (0, 31, 63), rainy_nights_button)
pygame.draw.rect(screen, (0, 31, 63), adrenaline_rush_button)

sunny_days_text = font.render("Sunny Days", True, (46, 204, 64))


rainy_nights_text = font.render("Rainy Nights", True, (46, 204,
64))
adrenaline_rush_text = font.render("Adrenaline Rush", True, (46,
204, 64))

sunny_days_text_rect =
sunny_days_text.get_rect(center=sunny_days_button.center)
rainy_nights_text_rect =
rainy_nights_text.get_rect(center=rainy_nights_button.center)
adrenaline_rush_text_rect =
adrenaline_rush_text.get_rect(center=adrenaline_rush_button.center)

screen.blit(sunny_days_text, sunny_days_text_rect)
screen.blit(rainy_nights_text, rainy_nights_text_rect)
screen.blit(adrenaline_rush_text, adrenaline_rush_text_rect)

# Button hover animation


if sunny_days_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), sunny_days_button)
sunny_days_text = font.render("Sunny Days", True, (0, 31, 63))
screen.blit(sunny_days_text, sunny_days_text_rect)
if rainy_nights_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), rainy_nights_button)
rainy_nights_text = font.render("Rainy Nights", True, (0, 31,
63))
screen.blit(rainy_nights_text, rainy_nights_text_rect)
if adrenaline_rush_button.collidepoint(pygame.mouse.get_pos()):

51 | P a g e
pygame.draw.rect(screen, (46, 204, 64), adrenaline_rush_button)
adrenaline_rush_text = font.render("Adrenaline Rush", True, (0,
31, 63))
screen.blit(adrenaline_rush_text, adrenaline_rush_text_rect)

pygame.display.flip()

# Function to play the game


def play_game(screen, difficulty):
movie = random.choice(list(movies[difficulty].keys()))
quote = random.choice(movies[difficulty][movie])

input_box = pygame.Rect(200, 300, 400, 50)


color_inactive = pygame.Color('lightskyblue3')
color_active = pygame.Color('dodgerblue2')
color = color_inactive
active = False
text = ''
done = False
result = ''
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_box.collidepoint(event.pos):
mouse_click_sound.play()
active = not active
else:
active = False
color = color_active if active else color_inactive
if event.type == pygame.KEYDOWN:
if active:
if event.key == pygame.K_RETURN:
click_sound.play() # Play sound effect
if text.lower() == movie.lower():
result = "Correct!"
else:
result = f"Incorrect! The movie was {movie}."
done = True
elif event.key == pygame.K_BACKSPACE:
text = text[:-1]
else:
text += event.unicode

# Draw background image and stars


screen.blit(background_image, (0 , 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw the quote


draw_text(screen, f"Quote: {quote}", white, pygame.Rect(50, 100,
700, 200), font)

52 | P a g e
# Draw the input box and text
txt_surface = font.render(text, True, color)
width = max(400, txt_surface.get_width()+10)
input_box.w = width
screen.blit(txt_surface, (input_box.x+5, input_box.y+5))
pygame.draw.rect(screen, color, input_box, 2)

# Animation: blinking cursor


if pygame.time.get_ticks() % 1000 < 500:
pygame.draw.line(screen, color,
(input_box.x+5+txt_surface.get_width(), input_box.y +5), ( input_box
.x+5+txt_surface.get_width(), input_box.y+25), 2)

pygame.display.flip()

# Clear screen and show result


screen.blit(background_image, (0, 0))
draw_text(screen, result, white, pygame.Rect(200, 200, 400, 200), font)

# Animation: fade out


for i in range(255, -1, -5):
screen.blit(background_image, (0, 0))
draw_text(screen, result, (i, i, i), pygame.Rect(200, 200, 400,
200), font)
pygame.display.flip()

pygame.time.wait(2000)

# Function to display survival mode options


def display_survival_mode(screen):
survival_button = pygame.Rect(300, 250, 200, 50)
done = False
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if survival_button.collidepoint(event.pos):
mouse_click_sound.play()
done = True

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw survival mode button


pygame.draw.rect(screen, (0, 31, 63), survival_button)
draw_text(screen, "Survival Mode", (46, 204, 64), survival_button,
pygame.font.Font('sketch.ttf', 40), True)

53 | P a g e
# Animation: button hover
if survival_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), survival_button)
draw_text(screen, "Survival Mode", (0, 31, 63),
survival_button, pygame.font.Font('sketch.ttf', 40), True)

pygame.display.flip()

return True

# Function to load leaderboard from csv file


def load_leaderboard(mode):
filename = f"{mode}_leaderboard.csv"
try:
with open(filename, "r", newline='') as f:
reader = csv.DictReader(f)
leaderboard = list(reader)
for entry in leaderboard:
entry['username'] = entry['username'].lower()
entry['score'] = int(entry['score'])
if 'average_time' in entry:
entry['average_time'] = float(entry['average_time']) if
entry['average_time'] != 'N/A' else None
return leaderboard
except FileNotFoundError:
return []

def save_leaderboard(leaderboard, mode):


filename = f"{mode}_leaderboard.csv"
try:
with open(filename, "w", newline='') as f:
fieldnames = ['username', 'score', 'average_time'] if mode ==
'survival' else ['username', 'score']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for entry in leaderboard:
writer.writerow(entry)
except IOError as e:
print(f"Error saving leaderboard: {e}")

def display_leaderboard(screen, leaderboard, mode):


done = False
flame_effect = FlameEffect(screen_width, screen_height)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
click_sound.play()
done = True

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()

mouse_x, mouse_y = pygame.mouse.get_pos()


flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

54 | P a g e
# Calculate the maximum width needed for usernames
max_username_width = max([font.size(entry['username'])[0] for entry
in leaderboard[:5]])
available_width = screen_width - 200 # Total available width minus
margins

# Adjust column widths based on available space


rank_width = 50
score_width = 100
time_width = 120 if mode == "survival" else 0
username_width = min(max_username_width, available_width -
rank_width - score_width - time_width)

# Calculate column positions


rank_x = 50
username_x = rank_x + rank_width
score_x = username_x + username_width + 20
time_x = score_x + score_width + 20 if mode == "survival" else 0

draw_text(screen, "Leaderboard", (255, 255, 0), pygame.Rect(300,


50, 200, 50), font, True)

y = 120
for i, entry in enumerate(leaderboard[:5]):
# Rank
draw_text(screen, f"{i+1}.", white, pygame.Rect(rank_x, y,
rank_width, 50), font, True)

# Username (truncate if too long)


display_username = entry['username']
if font.size(display_username)[0] > username_width:
while font.size(display_username + "...")[0] >
username_width:
display_username = display_username[:-1]
display_username += "..."
draw_text(screen, display_username, (255, 255, 0),
pygame.Rect(username_x, y, username_width, 50), font, True)

# Score
draw_text(screen, f"{entry['score']}", (0, 255, 0),
pygame.Rect(score_x, y, score_width, 50), font, True)

# Time (for survival mode)


if mode == "survival":
if entry['average_time'] is not None:
draw_text(screen, f"{entry['average_time']:.2f}s", red,
pygame.Rect(time_x, y, time_width, 50), font, True)
else:
draw_text(screen, "N/A", red, pygame.Rect(time_x, y,
time_width, 50), font, True)

y += 60 # Increased vertical spacing

draw_text(screen, "Press Enter to continue", (255, 255, 255),


pygame.Rect(250, 500, 300, 50), font, True)

pygame.display.flip()

def update_leaderboard(username, score, average_time, mode):


leaderboard = load_leaderboard(mode)

55 | P a g e
# Convert username to lowercase for case-insensitive comparison
username = username.lower()

# Check if the user already exists in the leaderboard


user_exists = False
for entry in leaderboard:
if entry['username'].lower() == username:
print(f"Updating existing user: {username}")
# Update the score and average time if the new score is higher
or the same score with a shorter average time
if score > entry['score'] or (score == entry['score'] and
average_time is not None and average_time < entry.get('average_time',
float('inf'))):
entry['score'] = score
if mode == "survival":
entry['average_time'] = average_time
user_exists = True
break

# If the user doesn't exist, add a new entry


if not user_exists:
print(f"Adding new user: {username}")
if mode == "survival":
leaderboard.append({
"username": username,
"score": score,
"average_time": average_time
})
else:
leaderboard.append({
"username": username,
"score": score
})

# Sort the leaderboard


if mode == "survival":
leaderboard = sorted(leaderboard, key=lambda x: (-x["score"],
x.get("average_time", float("inf"))))
else:
leaderboard = sorted(leaderboard, key=lambda x: x["score"],
reverse=True)

save_leaderboard(leaderboard, mode)
print(f"Leaderboard updated: {leaderboard}")

# Function to play survival mode


def play_survival_mode(screen, difficulty, username, used_movies):
global skip_button
global skip_button_off
global coins
score = 0
clock = pygame.time.Clock()
time_limit = 60 # seconds
total_time = 0
num_questions = 0
done = False
start_time = pygame.time.get_ticks()
message_end_time = 0
heart1 = red_heart
heart2 = red_heart

56 | P a g e
heart3 = red_heart
heart = [1, 2, 3]
skip = []
TIME = []
gold_clock = []
hint_count = []
display_hint = False

# load skips and clocks


cur.execute(f'''select skips from store where username =
"{username}"''')
for i in range(cur.fetchall()[0][0]):
skip.append(i+1)
cur.execute(f'''select clocks from store where username =
"{username}"''')
for i in range(cur.fetchall()[0][0]):
TIME.append(i+1)
cur.execute(f'''select golden_clocks from store where username =
"{username}"''')
for i in range(cur.fetchall()[0][0]):
gold_clock.append(i+1)

#load hints
cur.execute(f'select hints from store where username = "{username}" ')
for i in range(cur.fetchall()[0][0]):
hint_count.append(i+1)

correct_answer = 0

# Blink for bonus text


blink_start_time = 0
blink_duration = 500
bonus_active = False

#Pause
pause_button_rect = pause_button.get_rect(center=(450,475))
paused = False
pause_duration = 10
watch_mech = pygame.mixer.Sound('watch mechanic.mp3')
pause_button_disabled = False
timer_visible = True
blink_interval = 500
last_blink_time = 0
timer_paused_time = 0
sound_playing = False
sound_finished_time = 0

# Hint
hint_button_rect = hint_button.get_rect(center=(723, 130))

# Skip
skip_button_rect = skip_button.get_rect(center=(300, 475))

# Golden Clock
golden_clock_rect = add_time_button.get_rect(center=(600, 475))

# Speaker button
speaker_button_rect = speaker_button.get_rect(center=(750, 550))

flame_effect = FlameEffect(screen_width, screen_height)

57 | P a g e
while True:
available_movies = list(set(movies[difficulty].keys()) -
used_movies)
if not available_movies: # If all movies have been used
break # You can handle this case as needed (e.g., reset
used_movies or end the game)

movie = random.choice(available_movies)
used_movies.add(movie) # Add the selected movie to the set
quote = random.choice(movies[difficulty][movie])

input_box = pygame.Rect(200, 300, 400, 50)


color_inactive = pygame.Color('lightskyblue3')
color_active = pygame.Color('dodgerblue2')
color = color_inactive
active = False
text = ''
question_start_time = pygame.time.get_ticks()
question_done = False

hint = None

while not done and not question_done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_box.collidepoint(event.pos):
mouse_click_sound.play()
active = not active
else:
active = False
if skip_button_rect.collidepoint(event.pos):
if len(skip) != 0:
mouse_click_sound.play()
question_done = True
skip.pop()
cur.execute(f'update store set skips = skips -
1 where username = "{username}"')
db.commit()
color = color_active if active else color_inactive

if pause_button_rect.collidepoint(event.pos):
if len(TIME) != 0:
# watch mechanic
if not sound_playing:
pygame.mixer.music.pause()
watch_mech.play()
sound_playing = True
sound_finished_time =
pygame.time.get_ticks() + int(watch_mech.get_length() * 1000)

TIME.pop()
cur.execute(f'update store set clocks = clocks
- 1 where username = "{username}"')
db.commit()
mouse_click_sound.play()
paused = True
pause_button_disabled = True
pause_start_time = pygame.time.get_ticks()

58 | P a g e
if golden_clock_rect.collidepoint(event.pos):
if len(gold_clock) != 0:
mouse_click_sound.play()
time_limit = time_limit - int(elapsed_time) +
120
gold_clock.pop()
cur.execute(f'update store set golden_clocks =
golden_clocks - 1 where username = "{username}"')
db.commit()

if hint_button_rect.collidepoint(event.pos):
if len(hint_count) != 0:
mouse_click_sound.play()
hint_count.pop()
cur.execute(f'update store set hints = hints -
1 where username = "{username}"')
db.commit()
display_hint = True
hint = generate_hint(movie)

elif speaker_button_rect.collidepoint(event.pos):
mouse_click_sound.play()
sound_volume(screen)
if event.type == pygame.KEYDOWN:
if active:
if event.key == pygame.K_RETURN:
click_sound.play() # Play sound effect
if text.strip() == '':
# Set the end time for the message display
message_end_time = pygame.time.get_ticks()
+ 1500 # Display for 1.5 seconds
else:
if text.lower() == movie.lower():
correct_answer += 1
if 3 < correct_answer <= 5:
score += 2
bonus_active = True
blink_start_time =
pygame.time.get_ticks()
elif 5 < correct_answer <= 10:
score += 3
elif correct_answer > 10:
score += 5
else:
score += 1
question_done = True
if display_hint:
display_hint = False
total_time += pygame.time.get_ticks() -
question_start_time
num_questions += 1
if text.lower() != movie.lower():
correct_answer = 0
s = len(heart)
if s == 3:
heart3 = grey_heart
heart.pop()
elif s == 2:
heart2 = grey_heart
heart.pop()
elif s == 1:

59 | P a g e
heart1 = grey_heart
heart.pop()
if len(heart) == 0:
done = True

elif event.key == pygame.K_BACKSPACE:


text = text[:-1]
else:
text += event.unicode

if sound_playing and pygame.time.get_ticks() >=


sound_finished_time:
pygame.mixer.music.unpause()
sound_playing = False

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()

# Draw the heart


screen.blit(heart3, (700, 40))
screen.blit(heart2, (650, 40))
screen.blit(heart1, (600, 40))

#Draw the speaker button


screen.blit(speaker_button, speaker_button_rect.topleft)

# skip the question


if len(skip) != 0:
screen.blit(skip_button, skip_button_rect.topleft)
draw_text(screen, f"{len(skip)}", red, pygame.Rect(300,
500, 700, 200), font)
else:
screen.blit(skip_button_off, skip_button_rect.topleft)

# golden clock
if len(gold_clock) != 0:
screen.blit(add_time_button, golden_clock_rect.topleft)
draw_text(screen, f"{len(gold_clock)}", red,
pygame.Rect(600, 500, 700, 200), font)
else:
screen.blit(add_time_button_off, golden_clock_rect.topleft)

# Draw the quote


draw_text(screen, f"Quote: {quote}", white, pygame.Rect(50,
100, 700, 200), font)

# Draw the input box and text


txt_surface = font.render(text, True, color)
width = max(400, txt_surface.get_width()+10)
input_box.w = width
screen.blit(txt_surface, (input_box.x+5, input_box.y+5))
pygame.draw.rect(screen, color, input_box, 2)

#Pause button
if len(TIME) != 0:
screen.blit(pause_button, pause_button_rect.topleft)
draw_text(screen, f"{len(TIME)}", red, pygame.Rect(450,

60 | P a g e
500, 700, 200), font)
else:
screen.blit(pause_button_off, pause_button_rect.topleft)

#hint button
if len(hint_count) != 0:
screen.blit(hint_button, hint_button_rect.topleft)
draw_text(screen, f"{len(hint_count)}", red,
pygame.Rect(750, 110, 700, 200), font)
else:
screen.blit(hint_button_off, hint_button_rect.topleft)

if display_hint:
draw_text(screen, f"Hint: {hint}", (0, 255, 0),
pygame.Rect(200, 500, 400, 50), font)

# Draw score and time


draw_text(screen, f"Score: {score}", (0,255,0), pygame.Rect(50,
50, 200, 50), pygame.font.Font('sketch.ttf', 38))

# Blinking Bonus!!!
if bonus_active:
current_time = pygame.time.get_ticks()
if (current_time - blink_start_time) // blink_duration % 2
== 0:
draw_text(screen, "BONUS BONANZA!!!", (255, 255, 0),
pygame.Rect(190, 50, 700, 200), font)

if correct_answer <= 3:
bonus_active = False

if not paused:
elapsed_time = (pygame.time.get_ticks() - start_time -
timer_paused_time) / 1000
if elapsed_time < time_limit:
draw_text(screen, f"Time: {time_limit -
int(elapsed_time)}", red, pygame.Rect(50, 16, 200, 50), pygame.font.Font
('sketch.ttf', 38))
else:
draw_text(screen, "Time's up!", red, pygame.Rect(50,
16, 200, 50), pygame.font.Font('sketch.ttf', 38))
question_done = True
done = True

else:
if int((pygame.time.get_ticks()/500) % 2):
draw_text(screen, f"Time: {time_limit -
int(elapsed_time)}", red, pygame.Rect(50, 16, 200, 50), pygame.font.Font
('sketch.ttf', 38))

if paused:
elapsed_pause_time = (pygame.time.get_ticks() -
pause_start_time) / 1000
if elapsed_pause_time >= pause_duration:
paused = False
timer_paused_time += pygame.time.get_ticks() -
pause_start_time

61 | P a g e
# Check if we need to display the message
current_time = pygame.time.get_ticks()
if current_time < message_end_time:
draw_text(screen, "Please enter a movie name!", (255, 0,
0), pygame.Rect(200, 400, 400, 50), font)

mouse_x, mouse_y = pygame.mouse.get_pos()


flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

pygame.display.flip()
clock.tick(60)

if done:
break

# Calculate average time per question


if num_questions > 0:
average_time = total_time / num_questions / 1000
if score > 10:
coins = (score // 10) + (10 // average_time)
cur.execute(f'update store set coins = coins + {coins} where
username = "{username}"')
db.commit()

else:
average_time = None

return score, average_time, num_questions

def generate_hint(movie):
movie_letters = list(movie.replace(" ", "").upper()) # Remove spaces
and convert to uppercase
if len(movie_letters) <= 3:
return "".join(movie_letters) # If movie name is 3 letters or
less, reveal all
hint_letters = random.sample(movie_letters, 3) # Choose 3 random
letters
hint = ["_" if letter not in hint_letters else letter for letter in
movie.upper()]
return " ".join(hint) # Join with spaces for better readability

# Function to play creative mode


def play_creative_mode(screen, username, used_movies):
score = 0
clock = pygame.time.Clock()
game_over = False
hint_message_end_time = 0
enter_movie_message_end_time = 0
hint_count = 2 # Player starts with 2 hints
hint_button = pygame.Rect(650, 50, 120, 40) # Position and size of
hint button

# Set initial time limit for each question


time_limit = 30 # Start with 30 seconds
min_time_limit = 5 # Minimum time limit
question_count = 0 # Counter for the number of questions answered

countdown(screen)

# Speaker button

62 | P a g e
speaker_button_rect = speaker_button.get_rect(center=(750, 550))

flame_effect = FlameEffect(screen_width, screen_height)

while not game_over:


# Get a database connection
db_connection = get_db_connection()

# Fetch a random quote from the database


cursor = db_connection.cursor(dictionary=True)
cursor.execute("SELECT quote, correct_answer FROM questions ORDER
BY RAND() LIMIT 1")
result = cursor.fetchone()
cursor.close()
db_connection.close() # Close the connection after use

quote = result['quote']
movie = result['correct_answer']

input_box = pygame.Rect(200, 300, 400, 50)


color_inactive = pygame.Color('lightskyblue3')
color_active = pygame.Color('dodgerblue2')
color = color_inactive
active = False
text = ''
hint = None

question_done = False
question_start_time = pygame.time.get_ticks() # Start time for the
question

# ... rest of the function remains unchanged ...

while not game_over and not question_done:


elapsed_time = (pygame.time.get_ticks() - question_start_time)
/ 1000 # Get elapsed time in seconds

for event in pygame.event.get():


if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_box.collidepoint(event.pos):
mouse_click_sound.play()
active = True
color = color_active
elif hint_button.collidepoint(event.pos) and hint_count
> 0:
mouse_click_sound.play()
hint_count -= 1
hint = generate_hint(movie)
hint_message_end_time = pygame.time.get_ticks() +
3000 # Display hint for 3 seconds
else:
active = False
color = color_inactive
if speaker_button_rect.collidepoint(event.pos):
mouse_click_sound.play()
sound_volume(screen)
if event.type == pygame.KEYDOWN:

63 | P a g e
if active:
if event.key == pygame.K_RETURN:
click_sound.play()
if text.strip() == '':
enter_movie_message_end_time =
pygame.time.get_ticks() + 1500 # Display for 1.5 seconds
else:
if text.lower() == movie.lower():
score += 1
else:
game_over = True # End the game on
wrong answer
question_done = True
text = ''
active = False
color = color_inactive
elif event.key == pygame.K_BACKSPACE:
text = text[:-1]
else:
text += event.unicode

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw the quote


draw_text(screen, f"Quote: {quote}", white, pygame.Rect(50,
100, 700, 200), font)

# Draw the input box and text


txt_surface = font.render(text, True, color)
width = max(400, txt_surface.get_width() + 10)
input_box.w = width
screen.blit(txt_surface, (input_box.x + 5, input_box.y + 5))
pygame.draw.rect(screen, color, input_box, 2)

# Draw score
draw_text(screen, f"Score: {score}", (0, 255, 0),
pygame.Rect(50, 50, 200, 50), font)

# draw speaker button


screen.blit(speaker_button, speaker_button_rect.topleft)

# Draw hint button


pygame.draw.rect(screen, (0, 31, 63) if hint_count > 0 else
(169, 169, 169), hint_button)
hint_text = font.render(f"Hint ({hint_count})", True, (46, 204,
64) if hint_count > 0 else (211, 211, 211))
hint_text_rect = hint_text.get_rect(center=hint_button.center)
screen.blit(hint_text, hint_text_rect)
if hint_count > 0 and
hint_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), hint_button)
skip_text = font.render(f"Hint ({hint_count})", True, (0,
31, 63))
screen.blit(skip_text, hint_text_rect)

64 | P a g e
# Display hint if active
current_time = pygame.time.get_ticks()
if current_time < hint_message_end_time:
draw_text(screen, f"Hint: {hint}", (0, 255, 0),
pygame.Rect(200, 450, 400, 50), font)

# Display "Please enter a movie name!" message if needed


if current_time < enter_movie_message_end_time:
draw_text(screen, "Please enter a movie name!", (255, 0,
0), pygame.Rect(200, 400, 400, 50), font)

# Check if time limit has been reached


if elapsed_time >= time_limit:
draw_text(screen, "Time's up!", red, pygame.Rect(200, 400,
400, 50), font)
game_over = True # End the game if time runs out

# Display the remaining time


draw_text(screen, f"Time: {max(0, time_limit -
int(elapsed_time))}s", red, pygame.Rect(50, 16, 200, 50),
pygame.font.Font('sketch.ttf', 38))

pygame.display.flip()
clock.tick(60)

# Reduce time limit after every 3 or 4 questions


question_count += 1
if question_count % 4 == 0: # Adjust this value to change the
frequency of time reduction
time_limit = max(time_limit - 5, min_time_limit) # Reduce time
limit by 5 seconds, but not below the minimum

# Display score in a fresh screen


start_time = pygame.time.get_ticks()
while pygame.time.get_ticks() - start_time < 5000: # Wait for 5
seconds
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)
draw_text(screen, f"Game Over! Your score is {score}.", red,
pygame.Rect(200, 200, 400, 200), font)
pygame.display.flip()

# Update leaderboard
update_leaderboard(username, score, None, "creative")

# Display end options and return the user's choice


return display_end_options(screen, load_leaderboard("creative"),
"creative", score)
def special_level():
score = 0
clock = pygame.time.Clock()

65 | P a g e
game_over = False
gems_obtained = 0
pairs_found = 0
attempts = 0

# Card dimensions and layout - adjusted for better text fitting


CARD_WIDTH = 150 # Increased width
CARD_HEIGHT = 180 # Increased height
CARD_SPACING = 20
ROWS = 3
COLS = 4

# Colors
CARD_BACK = (0, 31, 63) # Dark blue
CARD_FRONT = (46, 204, 64) # Green
TEXT_COLOR = (0, 0, 0) # Black text
SELECTED_COLOR = (225,225,0)

countdown(screen)
flame_effect = FlameEffect(screen_width, screen_height)

# Get quotes and movies from database


db_connection = get_db_connection()
cursor = db_connection.cursor(dictionary=True)
cursor.execute("SELECT quote, correct_answer FROM questions ORDER BY
RAND() LIMIT 6")
pairs = cursor.fetchall()
cursor.close()
db_connection.close()

# Create cards list with quotes and matching movies


cards = []
for pair in pairs:
# Add quote card
cards.append({
'type': 'quote',
'content': pair['quote'],
'match': pair['correct_answer'],
'revealed': False,
'matched': False
})
# Add movie card
cards.append({
'type': 'movie',
'content': pair['correct_answer'],
'match': pair['quote'],
'revealed': False,
'matched': False
})

# Shuffle cards
random.shuffle(cards)

# Calculate card positions


card_positions = []
start_x = (screen_width - (COLS * (CARD_WIDTH + CARD_SPACING))) // 2
start_y = (screen_height - (ROWS * (CARD_HEIGHT + CARD_SPACING))) // 2

for row in range(ROWS):


for col in range(COLS):
x = start_x + col * (CARD_WIDTH + CARD_SPACING)

66 | P a g e
y = start_y + row * (CARD_HEIGHT + CARD_SPACING)
card_positions.append(pygame.Rect(x, y, CARD_WIDTH,
CARD_HEIGHT))

def wrap_text(text, font, max_width):


words = text.split()
lines = []
current_line = []

for word in words:


current_line.append(word)
text_surface = font.render(' '.join(current_line), True,
TEXT_COLOR)

if text_surface.get_width() > max_width - 20: # 20 pixels


padding
if len(current_line) > 1:
# Remove the last word and add the line
current_line.pop()
lines.append(' '.join(current_line))
current_line = [word]
else:
# If a single word is too long, split it
lines.append(word)
current_line = []

if current_line:
lines.append(' '.join(current_line))

return lines

selected_cards = []
reveal_time = None
game_start_time = pygame.time.get_ticks()
time_limit = 120 # 2 minutes time limit

while not game_over:


current_time = pygame.time.get_ticks()
elapsed_time = (current_time - game_start_time) // 1000
remaining_time = max(0, time_limit - elapsed_time)

if remaining_time == 0:
game_over = True

for event in pygame.event.get():


if event.type == pygame.QUIT:
pygame.quit()
exit()

if event.type == pygame.MOUSEBUTTONDOWN and not reveal_time:


mouse_pos = pygame.mouse.get_pos()
for i, rect in enumerate(card_positions):
if rect.collidepoint(mouse_pos) and not
cards[i]['matched'] and not cards[i]['revealed'] and len(selected_cards) <
2:
mouse_click_sound.play()
cards[i]['revealed'] = True
selected_cards.append(i)

if len(selected_cards) == 2:
attempts += 1

67 | P a g e
if (cards[selected_cards[0]]['match'] ==
cards[selected_cards[1]]['content'] or
cards[selected_cards[1]]['match'] ==
cards[selected_cards[0]]['content']):
pairs_found += 1
cards[selected_cards[0]]['matched'] = True
cards[selected_cards[1]]['matched'] = True
score += 100
gems_obtained += 1
cur.execute(f'update store set gems = gems
+ 1 where username = "{username}"')
db.commit()
reveal_time = current_time + 1000

# Clear selected cards after reveal time


if reveal_time and current_time >= reveal_time:
for i in selected_cards:
if not cards[i]['matched']:
cards[i]['revealed'] = False
selected_cards = []
reveal_time = None

# Draw everything
screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw cards
for i, (card, rect) in enumerate(zip(cards, card_positions)):
if card['matched']:
pygame.draw.rect(screen, CARD_FRONT, rect)
elif card['revealed']:
pygame.draw.rect(screen, SELECTED_COLOR, rect)
else:
pygame.draw.rect(screen, CARD_BACK, rect)

if card['revealed'] or card['matched']:
content = card['content']

# Use different font sizes for quotes and movie titles


if card['type'] == 'quote':
font_size = 20 # Smaller font for quotes
else:
font_size = 24 # Larger font for movie titles

card_font = pygame.font.Font('sketch.ttf', font_size)

# Wrap text
lines = wrap_text(content, card_font, rect.width)

# Calculate total height of text


total_height = len(lines) * card_font.get_linesize()
start_y = rect.y + (rect.height - total_height) // 2 #
Center vertically

# Draw each line


for line in lines:
text_surface = card_font.render(line, True, TEXT_COLOR)

68 | P a g e
text_rect = text_surface.get_rect()
text_rect.centerx = rect.centerx
text_rect.y = start_y
screen.blit(text_surface, text_rect)
start_y += card_font.get_linesize()

# Draw HUD
draw_text(screen, f"Score: {score}", (0, 255, 0), pygame.Rect(50,
50, 200, 50), font)
draw_text(screen, f"Gems: {gems_obtained}", (0, 255, 0),
pygame.Rect(50, 100, 200, 50), font)
draw_text(screen, f"Pairs Found: {pairs_found}/6", (255, 255, 255),
pygame.Rect(50, 150, 200, 50), font)
draw_text(screen, f"Attempts: {attempts}", (255, 255, 255),
pygame.Rect(600, 50, 200, 50), font)
draw_text(screen, f"Time: {remaining_time}s", (255, 0, 0),
pygame.Rect(600, 100, 200, 50), font)

if pairs_found == 6:
game_over = True

pygame.display.flip()
clock.tick(60)

# Game over screen


show_game_over = True
start_time = pygame.time.get_ticks()

while show_game_over and pygame.time.get_ticks() - start_time < 5000:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()

if pairs_found == 6:
bonus = max(0, 1000 - (attempts * 50)) # Bonus points based on
attempts
final_score = score + bonus
draw_text(screen , f"Congratulations! You won with a score of
{final_score}!", (0, 255, 0), pygame.Rect(100, 200, 600, 200), font)
else:
draw_text(screen, f"Game Over! Your final score is {score}.",
(255, 0, 0), pygame.Rect(100, 200, 600, 200), font)

pygame.display.flip()
# Function to display game mode options
def display_game_mode(screen):
survival_button = pygame.Rect(200, 250, 200, 50)
creative_button = pygame.Rect(450, 250, 200, 50)
instructions_button = pygame.Rect(200, 350, 200, 50)
store_button = pygame.Rect(450, 350, 200, 50)
spl_level_button = pygame.Rect(300, 450, 200, 50)
spl_level_off_button = pygame.Rect(300, 450, 200, 50)
speaker_button_rect = speaker_button.get_rect(center=(750, 550))
locked_rect = lock_button.get_rect(center=(100, 500))
unlocked_rect = unlock_button.get_rect(center=(100, 500))
done = False

69 | P a g e
game_mode = None
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


cur.execute(f'select special_level from store where username =
"{username}"')
spl_level = cur.fetchall()[0][0]
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if survival_button.collidepoint(event.pos):
mouse_click_sound.play()
game_mode = "survival"
done = True
elif creative_button.collidepoint(event.pos):
mouse_click_sound.play()
game_mode = "creative"
done = True
elif instructions_button.collidepoint(event.pos):
mouse_click_sound.play()
display_instructions(screen)
elif speaker_button_rect.collidepoint(event.pos):
mouse_click_sound.play()
sound_volume(screen)
elif store_button.collidepoint(event.pos):
mouse_click_sound.play()
store(screen)
elif spl_level_button.collidepoint(event.pos):
if spl_level == "True":
mouse_click_sound.play()
special_level()

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()

mouse_x, mouse_y = pygame.mouse.get_pos()


flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw game mode buttons


pygame.draw.rect(screen, (0, 31, 63), survival_button)
pygame.draw.rect(screen, (0, 31, 63), creative_button)
pygame.draw.rect(screen, (0, 31, 63), instructions_button)
pygame.draw.rect(screen, (0, 31, 63), store_button)
if spl_level == "True":
pygame.draw.rect(screen, (0, 31, 63), spl_level_button)
else:
pygame.draw.rect(screen, (211, 211, 211), spl_level_off_button)

survival_text = font.render("Survival Mode", True, (46, 204, 64))


survival_text_rect =
survival_text.get_rect(center=survival_button.center)
creative_text = font.render("Creative Mode", True, (46, 204, 64))
creative_text_rect =
creative_text.get_rect(center=creative_button.center)
instructions_text = font.render("Game Briefing", True, (46, 204,
64))
instructions_text_rect =

70 | P a g e
instructions_text.get_rect(center=instructions_button.center)
store_text = font.render("STORE", True, (46, 204, 64))
store_text_rect = store_text.get_rect(center=store_button.center)
if spl_level == "True":
spl_level_text = font.render("SPL LEVEL", True, (46, 204, 64))
spl_level_text_rect =
store_text.get_rect(center=spl_level_button.center)
else:
spl_level_off_text = font.render("SPL LEVEL", True, (90, 90,
90))
spl_level_off_text_rect =
store_text.get_rect(center=spl_level_button.center)

# Draw the text


screen.blit(survival_text, survival_text_rect)
screen.blit(creative_text, creative_text_rect)
screen.blit(instructions_text, instructions_text_rect)
screen.blit(store_text, store_text_rect)
if spl_level == "True":
screen.blit(spl_level_text, spl_level_text_rect)
else:
screen.blit(spl_level_off_text, spl_level_off_text_rect)
screen.blit(speaker_button, speaker_button_rect.topleft)

display_currency()

# Animation: button hover


if survival_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), survival_button)
survival_text = font.render("Survival Mode", True, (0, 31, 63))
screen.blit(survival_text, survival_text_rect)
elif creative_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), creative_button)
creative_text = font.render("Creative Mode", True, (0, 31, 63))
screen.blit(creative_text, creative_text_rect)
elif instructions_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), instructions_button)
instructions_text = font.render("Game Briefing", True, (0, 31,
63))
screen.blit(instructions_text, instructions_text_rect)
elif store_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), store_button)
store_text = font.render("STORE", True, (0, 31, 63))
screen.blit(store_text, store_text_rect)
elif spl_level_button.collidepoint(pygame.mouse.get_pos()):
if spl_level == "True":
pygame.draw.rect(screen, (46, 204, 64), spl_level_button)
spl_level_text = font.render("SPL LEVEL", True, (0, 31,
63))
screen.blit(spl_level_text, spl_level_text_rect)

pygame.display.flip()

return game_mode
# Function to display score and time
def display_score_and_time(screen, score, average_time, num_questions):
start_time = pygame.time.get_ticks()
flame_effect = FlameEffect(screen_width, screen_height)
while pygame.time.get_ticks() - start_time < 7000: # Display for 7
seconds
for event in pygame.event.get():

71 | P a g e
if event.type == pygame.QUIT:
pygame.quit()
exit()

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()

# Draw score and average time


draw_text(screen, f"Game Over! Your score is {score}.", (0, 255,
0), pygame.Rect(200, 200, 400, 200), font)
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)
if num_questions > 0:
draw_text(screen, f"Average time per question:
{average_time:.2f}s", (255, 0, 0), pygame.Rect(200, 250, 400, 200), font)
else:
draw_text(screen, "You haven't answered any questions!", (255,
0, 0), pygame.Rect(200, 250, 400, 200), font)

pygame.display.flip()
# Control the frame rate

# Function to display end options and handle user choice


def display_end_options(screen, leaderboard, mode, score, num_questions=0):
screen.blit(background_image, (0, 0))
draw_stars(screen)

play_again_button = pygame.Rect(150, 300, 200, 50)


leaderboard_button = pygame.Rect(450, 300, 200, 50)
quit_button = pygame.Rect(300, 400, 200, 50)
done = False
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if play_again_button.collidepoint(event.pos):
print("Play again selected, playing meendum sound") #
Debug print
meendum.play()
return "play_again"
elif leaderboard_button.collidepoint(event.pos):
mouse_click_sound.play()
display_leaderboard(screen, leaderboard, mode)
elif quit_button.collidepoint(event.pos):
mouse_click_sound.play()
return "quit"

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()

mouse_x, mouse_y = pygame.mouse.get_pos()


flame_effect.update(mouse_x, mouse_y)

72 | P a g e
flame_effect.draw(screen)

# Draw buttons
pygame.draw.rect(screen, (0, 31, 63), play_again_button)
pygame.draw.rect(screen, (0, 31, 63), leaderboard_button)
pygame.draw.rect(screen, (0, 31, 63), quit_button)

play_again_text = font.render("Play Again", True, (46, 204, 64))


leaderboard_text = font.render("Leaderboard", True, (46, 204, 64))
quit_text = font.render("Quit", True, (46, 204, 64))

play_again_text_rect =
play_again_text.get_rect(center=play_again_button.center)
leaderboard_text_rect =
leaderboard_text.get_rect(center=leaderboard_button.center)
quit_text_rect = quit_text.get_rect(center=quit_button.center)

screen.blit(play_again_text, play_again_text_rect)
screen.blit(leaderboard_text, leaderboard_text_rect)
screen.blit(quit_text, quit_text_rect)

# Button hover animation


if play_again_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), play_again_button)
play_again_text = font.render("Play Again", True, (0, 31, 63))
screen.blit(play_again_text, play_again_text_rect)
if leaderboard_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), leaderboard_button)
leaderboard_text = font.render("Leaderboard", True, (0, 31,
63))
screen.blit(leaderboard_text, leaderboard_text_rect)
if quit_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), quit_button)
quit_text = font.render("Quit", True, (0, 31, 63))
screen.blit(quit_text, quit_text_rect)
pygame.display.flip()

def ask_to_continue_as_same_user(screen, username):


yes_button = pygame.Rect(200, 350, 200, 50)
no_button = pygame.Rect(450, 350, 200, 50)
done = False
flame_effect = FlameEffect(screen_width, screen_height)

while not done:


for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if yes_button.collidepoint(event.pos):
mouse_click_sound.play()
return username.lower()
elif no_button.collidepoint(event.pos):
mouse_click_sound.play()
return get_username(screen)

# Draw background image and stars


screen.blit(background_image, (0, 0))
draw_stars(screen)

73 | P a g e
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

# Draw message
draw_text(screen, "DO YOU WANT TO CONTINUE AS", (255,255,0),
pygame.Rect(190, 200, 500, 50), font)

# Calculate the x-coordinate to center the username


username_surface = font1.render(username.capitalize() + " ?", True,
(255,0,255))
username_x = (screen_width - username_surface.get_width()) // 2

# Draw the username


screen.blit(username_surface, (username_x, 250))

# Draw buttons
pygame.draw.rect(screen, (0, 31, 63), yes_button)
pygame.draw.rect(screen, (0, 31, 63), no_button)

yes_text = font.render("Yes", True, (46, 204, 64))


no_text = font.render("No", True, (46, 204, 64))

yes_text_rect = yes_text.get_rect(center=yes_button.center)
no_text_rect = no_text.get_rect(center=no_button.center)

screen.blit(yes_text, yes_text_rect)
screen.blit(no_text, no_text_rect)

# Button hover animation


if yes_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), yes_button)
yes_text = font.render("Yes", True, (0, 31, 63))
screen.blit(yes_text, yes_text_rect)
if no_button.collidepoint(pygame.mouse.get_pos()):
pygame.draw.rect(screen, (46, 204, 64), no_button)
no_text = font.render("No", True, (0, 31, 63))
screen.blit(no_text, no_text_rect)

pygame.display.flip()

def countdown(screen):
countdown_sound = pygame.mixer.Sound('count.mp3')
font = pygame.font.Font('sketch.ttf', 100)
countdown_sound.play()
flame_effect = FlameEffect(screen_width, screen_height)

#Speaker Button
speaker_button_rect = speaker_button.get_rect(center=(750, 550))

for i in range(3, 0, -1):

start_time = pygame.time.get_ticks()

while pygame.time.get_ticks() - start_time < 1000:


alpha = min(255, (pygame.time.get_ticks() - start_time) * 255
// 500)

74 | P a g e
screen.blit(background_image, (0, 0))
draw_stars(screen)
update_stars()
mouse_x, mouse_y = pygame.mouse.get_pos()
flame_effect.update(mouse_x, mouse_y)
flame_effect.draw(screen)

text = font.render(str(i), True, (255, 255, 255))


text.set_alpha(alpha)
text_rect = text.get_rect(center=(screen_width // 2,
screen_height // 2))
screen.blit(text, text_rect)

for event in pygame.event.get():


if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if speaker_button_rect.collidepoint(event.pos):
mouse_click_sound.play()
sound_volume(screen)

screen.blit(speaker_button, speaker_button_rect.topleft)

pygame.display.flip()

# Fade out
start_time = pygame.time.get_ticks()
while pygame.time.get_ticks() - start_time < 500:
alpha = max(0, 255 - (pygame.time.get_ticks() - start_time) *
255 // 500)

screen.blit(background_image, (0, 0))


draw_stars(screen)
update_stars()

text = font.render(str(i), True, (255, 255, 255))


text.set_alpha(alpha)
text_rect = text.get_rect(center=(screen_width // 2,
screen_height // 2))
screen.blit(text, text_rect)

for event in pygame.event.get():


if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if speaker_button_rect.collidepoint(event.pos):
mouse_click_sound.play()
sound_volume(screen)

screen.blit(speaker_button, speaker_button_rect.topleft)

pygame.display.flip()

# Main function
def main():
global username
screen = pygame.display.set_mode((screen_width, screen_height))

75 | P a g e
pygame.display.set_caption("FILMANIA")

# Create stars
create_stars(200)
# Initialize flame effect
flame_effect = FlameEffect(screen_width, screen_height)

display_start_menu(screen)
# Get username after start menu
username = get_username(screen)
print("Username:", username)

cur.execute('select username from store')


users = cur.fetchall()
user_exists = False
for i in users:
if username.lower() == i[0]:
user_exists = True
break

if not user_exists:
cur.execute(f'''insert into store values("{username}", 0, 0, 0, 0,
0, "False", "", 0)''')
db.commit()

music_playing = False
music = ""
playlist = ""

used_movies = set() # Initialize the set to keep track of used movies

while True:
if not pygame.display.get_init():
break
game_mode = display_game_mode(screen)
if game_mode == "survival":
if music == "":
music = ask_for_music(screen)
if music:
choose_music_playlist(screen)
difficulty = display_difficulty(screen)
if difficulty:
countdown(screen)
score, average_time, num_questions =
play_survival_mode(screen, difficulty, username, used_movies)
# Update leaderboard
update_leaderboard(username, score, average_time,
"survival")
# Display score and time
display_score_and_time(screen, score, average_time,
num_questions)
# Display end options and handle user choice
choice = display_end_options(screen,
load_leaderboard("survival"), "survival", score, num_questions)
if choice == "play_again":
meendum.play() # Play the meendum sound
used_movies.clear() # Clear the set to allow all
movies to be available again
username = ask_to_continue_as_same_user(screen,
username)
continue

76 | P a g e
elif choice == "quit":
pygame.quit()
return
elif game_mode == "creative":
if music == "":
music = ask_for_music(screen)
if music:
choose_music_playlist(screen)
while True: # This loop allows for multiple games in creative
mode
choice = play_creative_mode(screen, username, used_movies)
if choice == "play_again":
meendum.play() # Play the meendum sound
used_movies.clear() # Clear the set to allow all
movies to be available again
username = ask_to_continue_as_same_user(screen,
username)
threading.Thread(target=load_next_question).start()
break # Break out of the creative mode loop to return
to game mode selection
elif choice == "quit":
pygame.quit()
return
break # Exit the loop if the player doesn't choose to play
again

if __name__ == "__main__":
main()

77 | P a g e
FLOWCHART

78 | P a g e
OUTPUT SCREENS

79 | P a g e
80 | P a g e
81 | P a g e
82 | P a g e
83 | P a g e
84 | P a g e
85 | P a g e
86 | P a g e
87 | P a g e
88 | P a g e
REQUIRED IMAGES

89 | P a g e
CONCLUSIONS

This project was a very great opportunity for


us to learn new concepts and get the
experience of many situations.

It has increased our potential and has


enhanced our problem solving capabilities.
The project had many issues from the
beginning, we had to make changes to make
everything work in a proper manner.

This project has very much contributed to


our knowledge in the programming language.
We would like to thank our teachers again for
giving us such a wonderful and creative
opportunity.

90 | P a g e
https://www.youtube.com/
https://www.google.com/
https://copilot.microsoft.com/
https://ncert.nic.in/
https://www.quora.com/
https://www.wikipedia.org/

91 | P a g e

You might also like