Uploaded by josephkemp09

Year 13 NEA proper (1)

advertisement
[Date]
Year 13 Extended
Project
Dungeon Crawler Game
Super
COUNTESTHORPE LEYSLAND COMMUNITY COLLEGE
Table of Contents
Analysis ......................................................................................................................................................... 3
Description ................................................................................................................................................ 3
Stakeholders ............................................................................................................................................. 3
Computational methods ........................................................................................................................... 3
Decomposition ...................................................................................................................................... 3
Abstraction ............................................................................................................................................ 4
Pattern recognition ............................................................................................................................... 4
Algorithms ............................................................................................................................................. 4
Existing solutions ...................................................................................................................................... 4
Legend of Zelda ..................................................................................................................................... 5
The Binding of Isaac .............................................................................................................................. 5
Neverwinter .......................................................................................................................................... 6
Essential features ...................................................................................................................................... 6
Character movement and actions......................................................................................................... 6
Health .................................................................................................................................................... 6
Graphics ................................................................................................................................................ 6
Sounds ................................................................................................................................................... 7
Menus ................................................................................................................................................... 7
Limitations ................................................................................................................................................ 7
Hardware and software requirements ..................................................................................................... 7
Success criteria.......................................................................................................................................... 8
Design............................................................................................................................................................ 9
Problem Breakdown ................................................................................................................................. 9
Structure ................................................................................................................................................. 11
Algorithms ............................................................................................................................................... 12
Usability features .................................................................................................................................... 15
Data Bases ............................................................................................................................................... 16
Key variables ........................................................................................................................................... 16
User information ................................................................................................................................. 16
Height and width of the game window .............................................................................................. 17
Player and enemy locations ................................................................................................................ 17
Player and enemy health .................................................................................................................... 17
Stage level ........................................................................................................................................... 17
Development and testing........................................................................................................................ 17
Test data.............................................................................................................................................. 17
White box testing ................................................................................................................................ 19
Black Box testing ................................................................................................................................. 19
Acceptance testing .............................................................................................................................. 19
Development............................................................................................................................................... 20
Development methodology .................................................................................................................... 20
Prototype game ...................................................................................................................................... 20
Final game ............................................................................................................................................... 52
Final game testing ................................................................................................................................... 66
Black box testing ................................................................................................................................. 67
White box testing ................................................................................................................................ 68
Evaluation ................................................................................................................................................... 69
Post development testing ....................................................................................................................... 69
Acceptance testing .............................................................................................................................. 71
Test Data ............................................................................................................................................. 71
Success criteria.................................................................................................................................... 73
Essential features ................................................................................................................................ 74
Health .................................................................................................................................................. 75
Graphics .............................................................................................................................................. 75
Sounds ................................................................................................................................................. 75
Menus ................................................................................................................................................. 75
Major Changes ........................................................................................................................................ 75
Limitations .............................................................................................................................................. 75
Maintenance ........................................................................................................................................... 76
Adaptive .............................................................................................................................................. 76
Perfective ............................................................................................................................................ 77
Corrective ............................................................................................................................................ 77
Preventive ........................................................................................................................................... 77
Final Evaluation ....................................................................................................................................... 78
Analysis evaluation ............................................................................................................................. 78
Bibliography ............................................................................................................................................ 78
Appendix ..................................................................................................................................................... 78
Final Game .............................................................................................................................................. 78
Login System ......................................................................................................................................... 110
Pre-game Start Menu............................................................................................................................ 116
Levels..................................................................................................................................................... 122
Analysis
Description
I will be creating a single player dungeon crawler game for PC players only. I will be using Pygame for the
creation of the game as it is very well rounded and easy to use. The game will be an adventure, puzzle
game that will follow the story of a young boy called Paul Carr trying to save his city by defeating the
Tyrannical Ruler Mr. Pakgalis. It will be a puzzle solving game involving some fights with easy enemies as
well as including boss fights. The problem this game will be solving is a lack of entertainment in the 2D
single player market, as there have been less and less games created in this genre as time has continued.
This is mainly because of the development in the details of graphics as well as better graphical power
allowing many more computers to run 3D games. This game will provide many people who enjoy 2D
single player games with entertainment anytime they wish as the game will be available offline.
Stakeholders
The stakeholders in my project will be anybody who uses a computer, but it will mainly be targeted
towards gamers that are between the ages of 10 and 25, however older people that grew up playing 2D
dungeon crawler games might also be interested as this is what they enjoyed doing in their youth, so it
might give them some nostalgia. This would mean that there would need to be a varying level of
difficulty so younger players can play and enjoy the game. Both people that are bad at using computers
and good at using computers should be able to use this game as it will be simple to understand but also
have how to play menus as well as tutorials. It will be targeted towards PC gamers as this game will only
be available on PC. The game is designed to be casual, but a time trial game mode makes the game more
competitive to speed run. Overall the main target demographic of this game is teenagers who
commonly use a computer in their free time.
Computational methods
Decomposition
This is where complex code is broken down into smaller, more manageable segments which enables the
writer and other people to understand or analyse what is going on more easily and make changes
quicker. I will split my code up into subroutines that will handle various parts of the game, login system,
or menu screens. This will make my code easier to read and find specific parts of that need to be altered.
It will also make my code run better as I can import the separate programs only when they are needed.
Because of this I will spend less time looking for specific parts of my code to change and more time
changing parts of my code that need updating. This will make the development process of the program
far easier as I can isolate specific problems.
Abstraction
Abstraction is where unnecessary parts of a problem or program are removed so it is easier to solve.
This will allow the writer or other people to understand the code easier as there is less code that is
unnecessary for example in my code, I will not load certain variables, sprites, or backgrounds into the
game if they are not immediately needed. I will also not be telling the player how certain controls work;
they will just know what happens when they press a button. This will make the game run quicker as the
computer will spend less time loading in unnecessary variables. On top of this it will shorten the code
making the file smaller and my code more easily readable.
Pattern recognition
This is where if code is repeated it can be removed and put into a separate subroutine that can be called
when it is needed. This is good because without it the file size of my game will be a lot larger and more
difficult to run. In my game I will likely use a main loop for all the main characters stats and position and
for all the enemy’s stats and positions. I will also have many subroutines that are called in this main loop
that can alter various aspects of the game such as changing the colour of the health bar depending on
the amount of health the character has.
Algorithms
An algorithm is a finite set of instructions that must be followed in certain calculations or problemsolving situations. In my game algorithms could be used to track the movement of the enemies. For
example, if the player is in a certain field of view the enemy could use the A* or another algorithm to
find the fastest path of getting to the player. This would make the enemies seem more intelligent as if
they were walking around until they randomly hit the player, this would make the game a lot easier and
less real.
Existing solutions
Legend of Zelda
Legend of Zelda is an action adventure 3rd person dungeon
crawler game made in 1986 and published by Nintendo.
During the game you follow the story of a boy named Link,
a commoner, who abruptly starts a mystical quest in order
to save the princess or Hyrule, Zelda, from the evil
antagonist, Ganon.
The game is played as an overhead view where Link will
enter different “rooms” as he reaches any side of the
screen with a path through. In these rooms there can be
various enemies which Link can kill or there can be various
puzzles that Link will be required to solve in order to
progress. At the end of the game, Link will have to face off
against the final boss of Ganon in order to save Zelda and complete the game. Link has three lives per
game and if he runs out of tries he will restart at the last checkpoint or the player can leave the game.
A feature I will take from Legend of Zelda is the progression of rooms. I like how some rooms require a
puzzle to be solved or a certain amount of enemies to be defeated in order to continue. I also like how
the camera on Link will not move while Link is in a certain room, this allows the player to see the entire
room they are in without having to move around and when the player wants to change room there is
not a cut to the next room, instead the camera moves along until the player has full view of the next
room where the player will regain control of Link. This makes the game seem smoother,
The Binding of Isaac
The binding of Isaac is a dungeon crawler game inspired by the
Legend of Zelda. The story is based on the biblical story the binding
of Isaac. In this story Isaacs’s mother is told she has to kill her son
Isaac as a proof of her faith. In fear of death Isaac flees into a
basement filled with monsters which he then has to escape.
A feature I like from the binding of isaac is the variety in enemies
and items that isaac can use. I like how in different types rooms
there are different types of enemy so you know what enemies you
will be facing based on the room you are in. I will be taking these
features as they add another layer of variety to the game,
ultimatelymaking it more fun to play and giving players a reason to
play again (to use different power ups/weapons).
Neverwinter
Neverwinter is a roleplaying, storytelling game where the player chooses the story as they continue
throughout the game. Before beginning to play the game the
player will choose a starting character with different stats such
as speed, attack damage and health. During the game, the
player can upgrade their characters stats and get better gear
such as weapons, armour or abilities
A feature I like in this game is the ability to change your
characters stats before starting the game based on what the
characters race is. I will use this idea in my game by allowing
the player to adjust the characters stats before the game to a
certain degree. By this I mean the speed cannot be increased passed a certain point without decreasing
another stat. This allows the player to choose exactly how they play the game with some limitations.
Essential features
Character movement and actions
The player’s character movement will be controlled by the user’s keyboard and some of the characters
actions will also be used with the keyboard such as inventory opening and dodging. The mouse will
control come of the other characters actions such as abilities.
Health
The character and the enemy will both have health, the characters health will be decided at the start of
the game when the user will have a choice of what kind of character they want to have. The enemy’s
health will be dependent on what kind of enemy it is. For example, lower level enemies will have less
health whereas bosses will have a lot more health. If the characters health runs out the game will end,
this acts as a lose condition for the character. If the enemy runs out of health the enemy will die and the
character will be able to continue. If these conditions were not in the game, it would either be incredibly
pointless as the player cannot die or be impossible to complete as the enemies would have infinite
health. This adds challenge to the game and makes it worth playing.
Graphics
The game will be the same every time apart from some enemy spawn locations, which have a chance to
change on every run. This means the backgrounds will not change game to game and the same one can
be used. All the sprites will be custom made so they fit a certain area. On top of this there will be an
attack, a pickup and a death animation for the player and enemies.
Sounds
All the sounds will fit their purpose so there are no sounds which sound out of place while playing the
game. There will be sounds for walking, attacking, damaging players and enemies, finishing a section
and for dying. The walking sounds will fit the space that the character is in to make it fit the game
better.
Menus
There will be a menu before the game starts to decide the characters colour, health and other aspects of
the characters abilities and will also contain a how to play section so first time players will know what
they are doing before playing the game. Also during the game the user will be able to press Esc to bring
up a pause menu to access the settings and the how to play section again if they want. The user will also
be able to bring up their inventory by pressing tab, to drop items or change what they are holding. The
pause menu will also pause the timer in a time trial run and will give the player time to take a breather if
they want.
Limitations
The main limitation will be the use of pygame. This is because every sprite must be saved as an image in
the same folder as the game. The image is then loaded in as an individual variable in every frame. This is
very inefficient for the processor and could cause problems. Also, pygame has no physics built in, so
physics such as throwing would have to be manually written which can be very difficult.
Another limitation I might face is time. Because most of this year will be developing the idea of the
game, there might not as much time as anticipated to write the code for my game. This could make it
hard to finish on time without rushing so time management will be very important.
On top of this, currently my school does not have pygame downloaded on any computer. This means I
will be primarily making my game at home unless it is installed on all of the computers. This would limit
the time I have to make my project even more as I will not be able to add to it while in a lesson.
Hardware and software requirements
Hardware/software
Description
Justification of why I intend to use it
Keyboard
An input device that is used to enter
characters or functions into a computer
system by pressing the keys on the board.
A handheld input device that controls the on
screen cursor and is used to enter functions
into a computer system by pressing the
buttons on the mouse.
Various keys are used to run various
functions in the game, without a
keyboard this wouldn’t be possible.
Various mouse buttons are used to
run various functions in the game,
without a mouse this wouldn’t be
possible.
Mouse
Monitor
An output device that displays information
obtain via a computer system.
Computer
A device that can store, retrieve and process
data.
A high level, object oriented programming
language and interpreter.
A collection of pixels that creates a visual aid
for the user.
Python
All of the necessary
images installed
The game requires the user to see
what is happening so they can react
accordingly.
Computer is needed to process the
game.
Without python installed, the code
would not be able to be interpreted.
Without the images, the game will
not be able to run as there will be an
error.
Hardware needed:





Processor: 1 gigahertz (GHz) or faster processor or SoC
RAM: 1 gigabyte (GB) or more
Hard disk space: 15 megabytes (MB) or more
Graphics card: DirectX 9 or later with WDDM 1.0 driver
Display: 800 x 600 or larger
Success criteria
Criteria Number
Description
Justification
Menus
Main menu will have five
buttons. Normal game, time
trial, how to play, one to leave
and settings
On pressing the W, A, S or D key
the character will move the
same amount up, down, left or
right respectively
Not many options makes the
menu easy to navigate while
having all of the necessary
options for the player
The character will move the
same amount in each direction
because then it makes the game
seem smoother instead of the
character moving faster side to
side for example
Two attacks makes the game
able to be played very different
because the two attacks are so
different, it adds variety are
more tactical play
Movement
Attacks
Levels
On pressing of mouse 1, the
character will attack in which
ever direction he is facing.
Mouse 2 will also be an attack
that is slower but does more
damage
There will be five levels
throughout the game that
contain different enemies and
puzzles
Different enemies and puzzles
keep the game interesting and
repayable for players
Death
Time trials
When an enemy’s health
reaches 0, he will fall over and
his body will disappear after 2
seconds. If the players health
reaches 0, the character will fall
over and an end screen will
appear
This makes there an end to the
game for the character/player
that isn’t just finishing which
makes the game more difficult,
also if the enemies didn’t die
the game would be almost
impossible to beat. Also, enemy
bodies disappear so they don’t
get in the way.
It should have a time trial
This adds a different way to play
option that if the player picks, a the game and makes it more
timer will start as soon as the
competitive and difficult to get
game starts that will continue to a good time.
count up as the game
continues. The timer will pause
if the game has been paused
and will resume when the
player resumes the game
Design
Problem Breakdown
I will be breaking down my problem into three main components that I can work on separately and
make adjustments where necessary. The main three sections of my project will be the login system, the
pre-game settings menu and the game itself. This will help me to isolate problems into specific modules,
meaning I can make necessary improvements with ease in isolated environments. I will be using flow
diagrams and small sections of pseudocode to create my initial ideas of how I want my programs to run.
These will give me an idea of how the user will interact with the program and how certain features will
work. These sections will also be relatively vague so I can have room to develop the idea more over
time. This means I will have to do more development work to find out how the programs will run in
practice and make sure there are no errors.
Login system
This login system is very simple with only a few processes. The user will be able to either create a new
account or sign in with an existing account. If the user gets the username or password wrong, they get
offered to try again. If the user selects no the program will close but if they choose yes, they will be able
to try again. The user will also be able to exit at any time by pressing the exit button the bottom left.
This allows the user to have freedom to explore the options thy have without making a firm choice. It
also allows them to enter a password or username incorrectly and try again as spelling mistakes can very
easily happen.
Settings menu
The settings module will define the stats for the character in the game and the game will import the
variables into the game to be used. In the settings menu the user will be able to change the stats of his
character, the volume and the difficulty which will be imported into the game to use. The user can also
select the how to play button which will tell the user how to play. Both the how to play and settings
sections have back buttons to return to the menu screen. The last two buttons are for the two games
that can be played, the normal game where the player can casually play and the time trial where the
players run will be timed. This will give the user a lot of freedom with the in game choices before the
game starts so they customise it to their preferences.
Game
My game is broken down into simple processes as seen in my flowchart. The user has a choice when
they first enter to either play the game or leave. In the game loop the user can pause at any time to
change volume, restart the game or exit which allows the user to customise the sound, restart or exit at
any time. The game is designed with simplicity in mind so almost any user can pick up the game and be
able to navigate the menus and make decisions easily. This will increase the amount of people who
enjoy the game
Structure
My game will have one main while loop where some inputs will be detected and all the sprites will be
updated and drawn. My pause menu will also use a while loop to make sure inputs aren’t detected in
the main while loop and nothing is drawn over the top of the pause menu.
The main loop will look like,
While notdone == TRUE THEN
Screen.fill(black)
Sprites.update()
Sprites.draw(screen)
IF wpressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = up
IF apressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = left
IF spressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = down
IF dpressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = right
The pause menu while loop will look like,
While pause = TRUE THEN
Displaypausemenu()
The displaypausemenu() will be a function that can display the pause menu and keep updating the
screen.
Algorithms
The first algorithm will be the main menu of the game. This will allow the user to change any settings
before starting the game. I will do this by finding the x and y values of the mouse on the screen and
checking to see if they are within the area of the button.
For example:
FUNCTION buttondetection
If (mousex and mousey) in button THEN
Buttonpressed = TRUE
RETURN Buttonpressed
This same algorithm can be changed slightly and used for the pause menu. This will bring up an overlay
and allow the user to change any settings or restart the game.
FUNCTION pause
WHILE paused = True
IF exitbuttonpressed = True THEN
CLOSE PROGRAM
IF restartbuttonpressed= True THEN
START NEW GAME
IF resumebuttonpressed= True THEN
RESUME GAME
IF volumedownbuttonpressed = True THEN
VOLUME DOWN
IF volumeupbuttonpressed= True THEN
VOLUME UP
I will also have an algorithm for the movement of the character. This will control how much the
player can go up, down, left, and right.
FUNCTION movement
IF wpressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = up
IF apressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = left
IF spressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = down
IF dpressed = True AND NOT player COLLIDE WITH wall THEN
Playermovement = right
A function for the two different types of attacks will also be needed to allow the character to hit
the enemies.
IF leftarrowpressed = TRUE:
Bullet(-5, 0)
IF rightarrowpressed = TRUE:
Bullet(5, 0)
IF uparrowpressed = TRUE:
Bullet(0,-5)
IF downarrowpressed = TRUE:
Bullet(0, 5)
This section of code will be in the main loop and will be constantly detecting if the user has
pressed the left, right, up or down arrow keys. The parameters are the speed the bullet will
move in the x and y direction. For example if the left arrow is pressed the bullet will move -5
pixels on the x axis and 0 on the y axis every time the sprite is updated.
CLASS Bullet(sprite)
FUNCTION initialising(x, y)
Self.speedx = x
Self.speedy = y
Self.xposition = playerx
Self.yposition = player
FUNCTION update
Self.x += self.speedx
Self.y += self.speedy
IF bullet COLLIDE WITH wall THEN
Self. Kill()
IF bullet COLLIDE WITH enemy THEN
Enemy.kill()
Self.kill()
This section of code allows the bullet class to be called so the bullet can become a sprite. In the
initialising function in the class, the bullet x and y speed is set as well as setting the x and y
values of the sprite to be where the player is so the bullet can come from the player. The
update function in the class allows the sprite to be updated and in this function there are if
statements that will delete the bullet if it makes contact with a wall or enemy and if it hits an
enemy it will kill it.
CLASS CloseAttack(sprite)
FUNCTION initialising(pos)
Self.speed = 10
IF pos = 1 THEN
Self.xposition = player.toprightx
Self.yposition = player.toprighty
ELSE THEN
Self.xposition = player.topleftx
Self.yposition = player.toplefty
FUNCTION update
Self.x += self.speedx
Self.y += self.speedy
Self.start = player.topy
IF bullet COLLIDE WITH enemy THEN
Enemy.kill()
IF self.xposition < player.topy
Self.kill()
This is code for the close range melee attack. It has similar code to the bullet attack in that it
takes a parameter and uses it to place and move it on the screen. It has a pos parameter that
determines what side the attack will be. In the update function, the melee does not get deleted
when it makes contact with the wall or an enemy. This is so it can be a continuous melee that
only stops when it reaches the bottom of the player.
Usability features
The key items a user will need are;



A monitor, so they can see what they are doing
A keyboard, so they can control what the character is doing as well as using the login system
A mouse so they can use the menu screen before the game starts as well as use the pause
menu, winning screen and death screen
The main features my game will need are;




Basic movement mechanics (allowing the player to move left, right, up and down on the screen)
A shooting mechanic (allowing the player to shoot at enemies)
A melee mechanic (to allow the player to melee the enemies)
A level generation
Other things that will be needed are;
 Some of my programs will need data bases to correctly work. These programs are; my
login system, as it needs to store the data of various users and passwords; the game code
will also require a database as it will need to save how fast each player completes the game
so it can be added to a scoreboard in the end-screen.
 I will need multiple programs that the user can traverse through while using the game.
These programs will be a login system, a pre-game settings menu, and the game itself. The
login system will allow the user to login to a previously existing account or create a new one.
The pre-game settings menu will allow the user to change some settings before entering the
game such as volume and difficulty. These will be able to be changed in the game also.
Finally, there will be the game program. This will include the game which will let the user
traverse through 5 levels, encountering enemies on each and requiring the use of a key to
get to the next level.

The user interface will need to be simple and easy to use so anyone of any age will be
able to use it. To achieve this, I will make my buttons have not much text on with the
important ones being in the middle of the screen. This will make it easier for the user to
understand what each button means and what it is used for. It will also reduce the amount
of time the user has to think about what to do. The background for each of my programs will
also be very important. This is because, the background gets the users attention and if
boring can drive the user away from using the program. This is why I will create backgrounds
to fit each one.
 The user should be able to close the program at any time
 The controls for the game should be accessible for most computers, this is why the
controls do not use any mouse inputs as this would make it harder for laptop players to
enjoy.
 The programs should also be easy to understand and learn to use.
Data Bases
I will be using a basic text file to store data taken from the game or the login system.
Key variables
I will have certain variables in my programs that will be used very commonly as well as having other
variables that might be used as a one off.
The most common variables I will have are:
1.
2.
3.
4.
5.
6.
7.
8.
9.
Player.centerx (x coordinate of the player)
Player.centery (y coordinate of the player)
Enemy.centerx (y coordinate of the enemy)
Enemy.centery (y coordinate of the enemy)
Bulletstate (holds data that determines whether a bullet can be fired or not)
meleestate (holds data that determines whether a melee can be used or not)
enemydamage (the amount of damage the enemy can do depending on the difficulty)
enemyspeed (the speed of the enemies depending on the difficulty)
notdone (this holds the data that determines whether or not the games main loop will run)
User information
The user information will need to be unique for every account. I will need to do this by making sure no
username is used twice. This means that there will be no confusion on the leader board after the game
is finished and users can be aware of which account is theirs. I will also ensure that when signing up the
username or password sections cannot be left blank so every username can be seen, the username will
also not be able to start with a space or be over 10 characters.
Height and width of the game window
This variable defines the size of the games window measured in pixels. It is necessary to the
creation of the window the game runs in and is also used as a boundary to stop the player going
off the screen.
Player and enemy locations
Holds the co-ordinates of the player’s and enemies’ characters. These will change as movement
or jump key are pressed or changed by the AI telling the enemy where to go. It is relied on to
display the characters on screen.
Player and enemy health
Player and enemy health will be stored in their own variables and will vary depending on the
difficulty chosen and how much the player or an enemy has been hit. Once the health of the
player reaches 0, they die, and the game is lost. If an enemy’s health gets to 0 they disappear.
Stage level
This variable will hold the stage number the player is on. There will be 20 stages over the entire
game where the difficulty is increased as you progress through the stages therefore the lower
number held in the stage variable the harder the game will be, when the stage variable reaches
0 the player has won.
Validation
Development and testing
Test data
Test number
1
2
3
4
5
Test description
Does login system load
up
Does login system login
works
Test data
Open the main game
file
Using a username and
password to login
Can you create new login Pressing create new
login, typing in a new
username and
password and
pressing enter
Does Game select time
Pressing time trail
trial button work
button
Does Game select time
Pressing the normal
normal game button
game button
work
Expected outcome
Login system is opened
Correct is displayed on
screen continue to
game select
Username and
password added to text
file and proceeds to
game select
Timer starts when
game starts
Timer doesn’t start and
continues to the game
6
Does pause button work
Pressing pause button
7
Does volume up button
work
Does volume down
button work
Does restart game
button work
Press volume up
Game stops and a
pause screen is
displayed over the top
Volume will increase
Press volume down
Volume will decrease
Press restart game
10
Resume game
Press resume game
button
11
Exit game
12
Move character up
Exit game button
pressed
W pressed
Game should go back
to level 1 and timer
should reset if it’s a
time trial
The game should
continue from before it
was paused
The game should close
13
Move character left
14
Move character down
15
Move character right
16
Long range attack
17
Short range attack
18
collision
19
Adding walls
20
Wall collision
21
Enemy attacks
22
Next level
8
9
Character should move
up
A pressed
Character should move
left
S pressed
Character should move
down
D pressed
Character should move
right
Left, right, up or down Projectile fired from the
arrow key pressed
character in direction
depending on the
button pressed
Press , or .
A bar should come
down from the side of
the character
depending on the
button pressed.
When projectile or
If projectile or short
short range attack hit range attack hit enemy,
enemy.
enemy gets deleted
Are walls displayed on Walls can be seen
screen
Moving character into Character can’t move
wall
past wall
When enemy touches If enemy touches
character
character, character
loses health
When character is in Level changes to the
doorway and presses next one and character
space
is moved and enemies
respawn
23
Game ending
When character dies
24
Winning game
Last enemy is killed
25
leader board
26
Play again button
Button on winning
screen is pressed or
button on start screen
is pressed
Play again button is
pressed
Restart game or close
game options are
displayed
Game winning screen
shows up time also gets
shown if time trial is
selected
A leader board of the
10 fastest times are
shown
The game will restart
White box testing
White box testing is where a person with access to the source code and knowledge of the program is
able to test the program so they can provide accurate criticisms which will allow me to change the game
accordingly based on their advice.
Black Box testing
I will also carry out a form of black box testing to help with my development. Black box research is
where a user with no access to the source code and no information of the program will go through and
test the program. This is so I can have feedback from a genuine user that has no bias and will play it as if
they are and end consumer. This feedback will be especially helpful as it is most likely the feedback that
end users will have if this is not carried out. This will allow me to fix major problems before the games
release and not have a bad start to the games release.
Acceptance testing
This is where a list of yes/no questions are asked about the program to test if various features of the
final program will work.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Can the user register a new account?
Yes/No
Can the user login with an existing account?
Yes/No
Can you re-enter your information if you enter it wrong?
Does the exit button work? Yes/No
Does the game run when opened? Yes/No
Can the user pause the game? Yes/No
Can the user progress to the next level? Yes/No
Can the user kill the enemies? Yes/No
Can the user pick up the key? Yes/No
Can the user progress without the key? Yes/No
Does the scoreboard show when selected? Yes/No
Yes/No
12. Can the scoreboard be viewed in order of time (lowest to highest of the top 5) and of
completion percentage (highest to lowest of the top 5)? Yes/No
13. Does it store the users score in a text file? Yes/No
Development
I will be following an iterative design process to ensure I can keep improving my program until it can run
with no errors and work 100% of the time. I will be using pygame for the first time so my code will start
out simple as I learn how to use it. I will start by making the basics of the game such as collision in its
own program so I can isolate mechanics of the game and learn how I can make each of them work. I will
be adding comments throughout my code to make sure I and other people can understand what it
means just by reading through it. I will also document any problems I have throughout the process. For
my main login system and pre-game settings screen I will be using the python module Tkinter as it is
best for GUI-based programs, and I have previous knowledge with this module. Also, because it is a
module of python no extra programs need to be installed for it to run.
Development methodology
The development methodology I will be using is the agile method to ensure my program reaches my
expectations. This is an iterative development process similar to the spiral method however on a smaller
scale as the spiral method is intended for much larger projects. This method includes analysing the
requirements of the program, designing a prototype, coding that prototype and testing it, then
evaluating the code and the process. The smaller scale of the agile method allows me to design,
implement and evaluate prototypes quicker and more efficiently allowing me to complete more in a
short amount of time.
Overall the agile design methodology is a flexible methodology that has short development cycles that
make finding bugs and flaws quicker and easier. The iterative part of this methodology means I will be
constantly reviewing the development process and will repeat the main processes until there are no
more flaws.
Prototype game
I made many test programs before I attempted the final game. This is because I wanted to have separate
programs in which I can isolate specific problems and solve them before implementing them into the
final game. This would save time searching through code trying to solve a problem in a larger program.
The first prototype I made was adding sprites to a screen, one of which the user can control, and
allowing them to collide.
Collision
This was the output of this program:
The sprites were able to collide however the player was still able to move while he was surrounded. I
improved this by making the playerclass update function “check” if there is an enemy where he is about
to move, and if there is the player will stay still. The way this is done is by moving the players
coordinates based on what way the user wants it to move and checking if he then collides with an
enemy. If the player, then collides with an enemy the player will be moved back. This also means the
player can still move up, down and left if there is an enemy on his right, which is something I initially
struggled with making work.
Being new to pygame, I initially had a massive problem with making the squares on the screen able to
collide with each other. I was able to make the squares move around and have 5 red squares chase the
user controlled white square, but they wouldn’t collide. Initially, when I was researching how to make
this possible I came across the line of code “pygame.sprite.spritecollide(self, enemies, False)”. This
seemed to check whether or not a sprite was overlapping another sprite, which I would be able to use to
stop the sprites moving any more. However, when I implemented this line of code, I got this error
message.
This took me a long time to solve as all of the examples I had seen were just using the
“pygame.sprite.spritecollide(self, enemies, False)” and it working. After a long time, I realised that in all
sprite classes, the line “pygame.sprite.Sprite.__init__(self)” was needed in the initialisation function as
well as the line “pygame.sprite.Sprite” needing to be in the brackets of the class. Once this was solved
the sprites finally managed to collide.
Walls
After this I made a program that will place blocks on the screen that the player cannot go through to
make the walls for the levels.
This program contains list which correspond to future levels. The list is set up in a 16:9 aspect ratio (the
most common monitor aspect ratio as well as being the aspect ratio of the screen size, 1280 by 720) and
is a 32 by 18 size. This is so I can place many 40 by 40 squares to make up the walls, floors and exits.
Where there is a “W” a wall will be placed in the program, and “F” means floor will be placed and a “C”
means there will be an exit door. There are also lists with spawn locations of enemies, the amount of
enemies, the location of the exits and the player spawn location for each level.
I never had any problems with this code because all it was is lists, so there was very little that could go
wrong.
Walls
I then made code which would use the wallsinlevels lists to display some walls.
This is the output of the code
This is the main body of code that uses the wallsinlevels code to place walls in specific places. I tested
this program to make sure my method works, and the player cannot go through any walls and make
sure the walls were placed in the position I had wanted them to.
I initially had some problems with the placing of the walls and kept getting this error message
I eventually realised it was because of the order of my variables being wrong.
in this code I had written the I and the ii the wrong way around making the W think its supposed to be
placed off the screen on the y axis whereas it cannot be placed that far because that is not in the list.
After this I had a problem with the walls not being visible, they were working but the player cannot see
them. I eventually realised that this was because I had not added the wall to the correct sprite list so
was not drawing them on the screen.
This method of placing wall blocks based on a list is not the best way to go about implementing walls,
however I couldn’t find a better way to make walls work within a short period of time. This method also
can make the game run slower as it introduces each wall block as a sprite, and lots of sprites require a
lot of the CPUs attention to generate. If I was to do this stage again, I would try to find a better way that
makes the game run better.
Attacks
Next, I made an attacks test file that attempted to allow the user controlled sprite to fire a pixel at other
sprites on the screen and have them disappear if they were hit.
This was the output of the program
This program builds on the foundations of the first program by having a player that the user controls and
enemies the chase the player. But, in this program the player can shoot a projectile at the enemies,
represented by the green dot, which will delete the enemies when it hits them and the projectile will
disappear. This program also has another attack which is a close range attack and is represented by the
blue line. This will also delete an enemy when it hits them but will not disappear on contact. Instead it
will disappear when it when it reaches the bottom of the player. When if first made this program I had
some problems with how to make the attacks work properly. I had originally tried to incorporate the
attacks into the playerclass, but I couldn’t figure out how to correctly use self. With some of the
variables. Instead of this I decided to make the functions completely separate from the playerclass class
while still using variables from it.
End screen
After this I felt the main mechanics of the game had been covered so I moved onto making a pause
menu and an end screen starting with the end screen.
This was the output of the code
The white square can move around and once in the yellow square, the user can press the spacebar
which will display the game over screen. This is done by entering a new while loop, so the game is
paused in the background. There are two buttons on the screen which allow the user to either exit the
game or restart which will go back to the game and re place the player in the centre of the screen. I will
use this code as the outline for the other screens I will use like the winning screen and the pause menu.
The end took me a while to figure out. At first, I had a function that just displayed the end screen, and
the user couldn’t do anything. Unlike in Tkinter, pygame didn’t have buttons. Which made it a lot harder
to allow users to interact with the program’s menus.
After a while of looking through programs with buttons in pygame I found that if I created another
function that detects where the mouse is and if any button is being pressed, io could use that
information to detect if a button has been pressed over the coordinates of an image for a button. Using
this information, I changed the code to this.
Pause Menu
I decided to move on to a pause menu which would be harder than an end screen as it has to keep the
information of the current game.
This is the output of the code
When the “p” key is pressed this pause menu is displayed. It allows the user to raise or lower the
volume, change the difficulty, restart the game, resume the game and exit. When the mouse is hovering
over a button the button outline will go green.
Originally, I thought that this pause menu would be similar to the end screen code. So, I started with
that, changed the button location and images, and thought it would work. And it did, it displayed the
pause screen perfectly. However, the pause menu hadn’t actually paused the games main loop and once
I added enemies, I realised that the pause menu only showed the pause menu and didn’t actually pause
the game. To get around this, I set created a new while loop in the pause menu function which means
the game loop could not continue until that loop had closed.
Login system
After making all of the fundamentals of the game I decided to create a login system and a pre-gamey
menu starting with a login system.
This is the output of the code
This program works by having the user enter a username and password which will be checked against a
text file with all current usernames and passwords to see if the username and password are correct. The
user is able to sign up a new account, however the username cannot be the same as someone else’s
username, the username and password entry boxes also cannot be empty and cannot start with a space.
On top of this the username cannot be over 15 characters long. There is also an exit button in the corner
which the user can use to exit the program if they wish.
During the process of making this program, I encountered a few problems. The first was the “Enter”
button not working on the sign-up screen and producing this error.
This error was occurring because I was also using newacccheck as the function for the input of the
physical enter button which needs a parameter of event to be passed. There were two ways of getting
around this. The first was to create another function without the parameter for the in program button
however this method was very poor as it only increase the amount of lines of code. The other option
was to simply replace the “command = newacccheck” with “command=lambda: newacccheck(5)”. The
reason the number 5 in being passed as a parameter is because a parameter needed to be passed so I
chose a random number. This solution works perfectly and doesn’t increase the amount of lines of code.
Before
After
Pre-game start menu
The pregame start menu allowed the user to change some settings before entering the game and also
read how to play the game.
This is the output of the program
The first screen has buttons that lead the user to different sections. In the Settings section the user will
be able to change the difficulty and the volume. In the how to play section there is a brief description of
the game. In the time trial section there is a button to play the game with a timer. In the normal
playthrough section there is a button to play the game without a timer. Once any section is opened a
back button will appear in the bottom right that allows the user to easily traverse the program.
This program was very easy to code for the most part. The only problem I had was that adding small
numbers in python sometimes doesn’t work well. For example, with the volume, in pygame the volume
works on a scale of 0 to 1. So what my program has is a percentage displayed on the screen and if the
volume in increase, it will go up by one percent, so 0.01 in the variable.
This was the code:
This was the initial output vs the output when volume is added:
For some reason, python sometimes cannot add decimals together without making this mistake. To
solve this problem, I simply multiplied the volume by 100 then added 1 instead. I also needed to make
sure that the volume could not exceed 100 so I put a simple if statement to sort it out
I wasn’t sure whether or not this was the best solution, however I could not think of or find another way
to tackle this problem.
Final game
After making all of these prototypes I decided to attempt to put them together to make the full game.
Outputs of the program:
Final game testing
I will use the testing methods I mentioned in the design section in order to thoroughly test the game to
make sure it functions as intended.
Black box testing
For this form of testing, I had the help from a peer, Oscar White, who doesn’t take computer science
and hasn’t seen the source code. The way I decided to test was by allowing Oscar to run the game
without any knowledge of how the game worked apart from the basic controls of the game. This way he
would be able to play but have the same first impressions as other first-time players.
While testing, he found an issue with the shooting mechanic. This was when the player shot left the
bottle image would not disappear if it did not hit an enemy. This ended up being a problem with how
the sprite was deleted in one part of the code but still being drawn in another part. This was caused by
the bottle being drawn outside of the update function, while there was an update statement in the
function. This meant the bottle sprite would be deleted but not updated so it would be still be drawn
outside of the function.
The way I solved this problem was by moving the draw function to inside the function so if the bottle
sprite was deleted it could not be drawn.
The updated code:
I then got another one of my peers, Daniel Lascelles, that does not take computer science to play
through the game and gave him he same amount of information as Oscar. During his testing, he found
that in the pre-game menu when trying to adjust the volume, the volume number would sometimes
increase by a very small amount making it display a very long decimal.
This is what it previously looked like:
To solve this, I decided to multiply the volume variable by 100 to make the addition not include decimal
places. I decided to do this because there is a slight inaccuracy in floating point calculations in python.
White box testing
For this form of testing I used a peer from my computer science class, Ellis Dann. I decided to give him
full access to the code so he can read through and familiarise himself with the program. This allows him
to look through in an attempt to find possible errors that can occur in the game.
After looking through the code an playing the game, Ellis found on problem with the pause menu. This
was that the volume can be reduced to negative numbers and raised above 100 (as 100 should be the
max and 0 should be the minimum). After attempting to solve this issue I managed to create another
one. This was that the volume could be displayed as -0% after reaching 0%. This was another rounding
problem caused by adding small amounts in python. To combat this I decided to change the 0% if
statement to not allow this to happen as well as rounding the final result to 0 decimal places.
The updated code:
I also got another peer from my computer science, Connor Van Dijk, to test my code. I also gave him
access to my code as well as information about the game. During his testing he found no flaws, however
he did suggest that there should be something to do on each level in order to progress to deter people
from just rushing through the game. Using this idea, I decided to place a key on each level in a predetermined location which the player must retrieve in order to continue. This makes the game slightly
harder but also gives the game more of an incentive to play.
Evaluation
Post development testing
Usability Testing
1. Some of my programs will need data bases to correctly work. These programs are my login
system, as it needs to store the data of various users and passwords; the game code will also
require a database as it will need to save how fast each player completes the game so it can be
added to a scoreboard in the end-screen.
2. I will need multiple programs that the user can traverse through while using the game. These
programs will be a login system, a pre-game settings menu, and the game itself. The login system
will allow the user to login to a previously existing account or create a new one. The pre-game
settings menu will allow the user to change some settings before entering the game such as
volume and difficulty. These will be able to be changed in the game also. Finally, there will be the
game program. This will include the game which will let the user traverse through 5 levels,
encountering enemies on each and requiring the use of a key to get to the next level.
3. The user interface will need to be simple and easy to use so anyone of any age will be able to use
it. To achieve this, I will make my buttons have not much text on with the important ones being
in the middle of the screen. This will make it easier for the user to understand what each button
means and what it is used for. It will also reduce the amount of time the user has to think about
what to do. The background for each of my programs will also be very important. This is because,
the background gets the users attention and if boring can drive the user away from using the
program. This is why I will create backgrounds to fit each one.
4. The user should be able to close the program at any time
5. The controls for the game should be accessible for most computers.
6. The programs should also be easy to understand and learn to use.
Evaluation of these points:
1. I think that all of the databases work as intended and store the correct data and no more that it
needs to function perfectly. I think that storing them in text files wasn’t the best database
however I didn’t know how to store the data in other more secure databases.
2. I think that I have exceeded my expectations in allowing the user to easily traverse through the
menus. I have done this by making the program move on for the user when it is needed without
them knowing how it is done. For example, I have created the login system, so it moves onto the
pre-game settings once the user has input their details, so they don’t have to do it themselves.
The programs also include all of the features that I wanted and more, for example, in the pregame login system it includes the features I wanted it to as well as including a how to play
section to ensure players don’t enter the game confuse
3. The backgrounds I made were good. The reason I think this is that the login menu background is
colourful and draws the eye, which is good for getting players attention, the pre-game settings
menu is simple and only includes an image of the character, and the game background is also
simple to not distract the player from the main game, while being enough to look good. The
button size, font size and button placement I thought was also very good as it puts all of the
buttons near the middle of the screen with big enough writing for the users to easily read it. It
also allows people with worse vision to see and use the program.
4. The user can close the program at any time
5. The controls are accessible for most computers as the controls use standard keyboard letters
and no mouse inputs, to make it easier for laptop players to use.
6. The program is easy to understand and learn. To prove this, I had 10 of my friends use the
program with no prior knowledge as to how the program worked. 8/10 of these people were
able to figure out the game and learn all, by themselves. The other 2 learned slower because
they didn’t read the instructions.
I had a few more people go through my code after this at each section to ensure it was very easy to use
and there were no bugs. The feedback I got was all positive and the general consensus was that it was
well laid out.
Acceptance testing
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Can the user register a new account?
Yes/No
Can the user login with an existing account?
Yes/No
Can you re-enter your information if you enter it wrong? Yes/No
Does the exit button work? Yes/No
Does the game run when opened? Yes/No
Can the user pause the game? Yes/No
Can the user progress to the next level? Yes/No
Can the user kill the enemies? Yes/No
Can the user pick up the key? Yes/No
Can the user progress without the key? Yes/No
Does the scoreboard show when selected? Yes/No
Can the scoreboard be viewed in order of time (lowest to highest of the top 5) and of
completion percentage (highest to lowest of the top 5)? Yes/No
13. Does it store the users score in a text file? Yes/No
Test Data
Test number
1
Test description
Does login system load
up
Test data
Open the main game
file
Actual outcome
Login system is opened
2
Does login system login
works
3
Can you create new login Pressing create new
login, typing in a new
username and
password and
pressing enter
Does Game select time
Pressing time trail
trial button work
button
Does Game select time
Pressing the normal
normal game button
game button
work
Does pause button work Pressing pause button
4
5
6
7
Using a username and
password to login
Does volume up button
work
Does volume down
button work
Does restart game
button work
Press volume up
10
Resume game
Press resume game
button
11
Exit game
12
13
14
15
16
Move character up
Move character left
Move character down
Move character right
Long range attack
Exit game button
pressed
W pressed
A pressed
S pressed
D pressed
Left, right, up or down
arrow key pressed
17
Short range attack
Press , or .
18
collision
19
Adding walls
20
Wall collision
When projectile or
short range attack hit
enemy.
Are walls displayed on
screen
Moving character into
wall
8
9
Press volume down
Press restart game
Correct is displayed on
screen continue to pregame menu
Username and
password added to text
file and proceeds to
pre-game menu
Timer starts when
game starts
Timer doesn’t start and
continues to the game
Game stops and a
pause screen is
displayed over the top
Volume increases by
1%
Volume decreases by
1%
Game goes back to
level 1 and timer is
reset if it’s a time trial
The game continues
from before it was
paused
The game closes
Character moves up
Character moves left
Character moves down
Character moves right
Projectile is fired from
the character in
direction depending on
the button pressed
A bar comes down from
the side of the
character depending on
the button pressed.
If projectile or short
range attack hit enemy,
enemy gets deleted
Walls can be seen
Character can’t move
past wall
21
Enemy attacks
When enemy touches
character
22
Next level
When character is in
doorway and presses
space
23
Game ending
When character dies
24
Winning game
Last enemy is killed
25
leader board
26
Play again button
Button on winning
screen is pressed or
button on start screen
is pressed
Play again button is
pressed
When the enemy
touches the character,
character loses health
Level changes to the
next one and character
is moved and enemies
respawn
Restart game or close
game options are
displayed
Game winning screen
shows up time also gets
shown if time trial is
selected
A leader board of the 5
fastest times are shown
The game restarts
Success criteria
Criteria
Number
Menus
Description
Justification
Has criteria been met?
Main menu will have five
buttons. Normal game,
time trial, how to play,
one to leave and settings
On pressing the W, A, S or
D key the character will
move the same amount
up, down, left or right
respectively
Yes
Attacks
On pressing of mouse 1,
the character will attack in
which ever direction he is
facing. Mouse 2 will also
be an attack that is slower
but does more damage
Not many options makes the
menu easy to navigate while
having all of the necessary
options for the player
The character will move the
same amount in each
direction because then it
makes the game seem
smoother instead of the
character moving faster side
to side for example
Two attacks makes the game
able to be played very
different because the two
attacks are so different, it
adds variety are more
tactical play
Levels
There will be five levels
throughout the game that
Different enemies and
puzzles keep the game
Movement
Yes
No
Instead the arrow keys
are used to shoot in
the direction of the
arrow. This was to
make the game easier
to use for laptop users
Partially met
There are five levels
throughout the game,
contain different enemies
and puzzles
interesting and repayable for
players
Death
When an enemy’s health
reaches 0, he will fall over
and his body will
disappear after 2 seconds.
If the players health
reaches 0, the character
will fall over and an end
screen will appear
Time trials
It should have a time trial
option that if the player
picks, a timer will start as
soon as the game starts
that will continue to count
up as the game continues.
The timer will pause if the
game has been paused
and will resume when the
player resumes the game
This makes there an end to
the game for the
character/player that isn’t
just finishing which makes
the game more difficult, also
if the enemies didn’t die the
game would be almost
impossible to beat. Also,
enemy bodies disappear so
they don’t get in the way.
This adds a different way to
play the game and makes it
more competitive and
difficult to get a good time.
however there aren’t
any puzzles instead
there are keys to
collect on each level.
Partially met
When the players
health reaches 0 the
end screen appears as
the player is dead, but
the enemies don’t fall
over and disappear
after 2 seconds
Yes
Essential features
These features were determined to be essential to the user experience being adequate.
The first essential feature for the game is allowing the character to be controlled by the user. This is
essential because without it the user cannot play the game and can only watch. Also, the actions the
player can do are considered essential as without them the game seems to have little to no point as it
will be too basic. I managed to complete the moving feature with relative ease however I changed my
mind on some of the actions. For example, I had originally thought that the player would have an
inventory and have the ability to dodge. Instead, the character has two forms of attacking enemies. This
means I partially met the criteria of this feature as I did include actions, but not the ones I had first
intended.
The second essential feature of the game is the players and enemies health. This is essential because
without player health the game becomes pointless as the player has nothing to lose in game (there are
no stakes). Also the enemy health is essential because without it the enemies won’t be able to die so will
be able to easily defeat the player. I decided to give the player 100 health and the players just 1. This is
because the enemies deal 1 damage (on easy, 2 on normal and hard) every time the game refreshes
(every 1/80th of a second)
Health
The character and the enemy will both have health, the characters health will be decided at the start of
the game when the user will have a choice of what kind of character they want to have. The enemy’s
health will be dependent on what kind of enemy it is. For example, lower level enemies will have less
health whereas bosses will have a lot more health. If the characters health runs out the game will end,
this acts as a lose condition for the character. If the enemy runs out of health the enemy will die and the
character will be able to continue. If these conditions were not in the game, it would either be incredibly
pointless as the player cannot die or be impossible to complete as the enemies would have infinite
health. This adds challenge to the game and makes it worth playing.
Graphics
The game will be the same every time apart from some enemy spawn locations, which have a chance to
change on every run. This means the backgrounds will not change game to game and the same one can
be used. All the sprites will be custom made so they fit a certain area. On top of this there will be an
attack, a pickup and a death animation for the player and enemies.
Sounds
All the sounds will fit their purpose so there are no sounds which sound out of place while playing the
game. There will be sounds for walking, attacking, damaging players and enemies, finishing a section
and for dying. The walking sounds will fit the space that the character is in to make it fit the game
better.
Menus
There will be a menu before the game starts to decide the characters colour, health and other aspects of
the characters abilities and will also contain a how to play section so first time players will know what
they are doing before playing the game. Also during the game the user will be able to press Esc to bring
up a pause menu to access the settings and the how to play section again if they want. The user will also
be able to bring up their inventory by pressing tab, to drop items or change what they are holding. The
pause menu will also pause the timer in a time trial run and will give the player time to take a breather if
they want.
Major Changes
Limitations
My coding ability
My first major limitation was my coding ability. This affected many areas of my code but mainly the level
generation system. The system works perfectly fine but it can slow a computer down at some points as
there are too many sprites spawned on the screen at one time. However, I did not know how to do it
another way which lead to the sprite system staying. Another area which could have been improved if
not for my lack of ability is the movement animations. As it is now, when a character moves, it stays as a
static png. Generally, my coding ability stopped me from making my code more efficient but it also
impacted other areas such as visuals.
Time
Time was a very limiting factor during this project. This is mainly because I had to learn an entirely new
module of python as well as advancing my knowledge in other modules such as Tkinter. Learning
pygame did take me a very long time to learn as at first I was unsure how sprites and collision worked.
Another time limiting factor was the absence of my teachers. Halfway through my project both of my
computer science teachers unexpectedly left, leaving me with no guidance from them whatsoever. It
then took many weeks to have substitute teachers which then have not turned up to many lessons. Due
to this, it has taken me slightly longer to complete a lot of tasks to do with the writing side I was never
sure what subjects to write about.
Computer performance
Computer performance was a very big limitation as the computers I had available to me at school are
very slow. For example it would usually take about 10 minutes to log in every lesson. This would mean I
was losing 1 and a half hours of time every two weeks. Also, the computers struggled to run a game with
many sprites on the screen at a time, so I had to reduce some of the textures to allow the computer to
run it properly. This is because my program can be heavily dynamic as well as the computers being very
slow.
Range of resources
I had a wide variety of resources from the internet but I mainly got a lot of my information from
YouTube and stack overflow. These resources were integral to helping me learn pygame and progress in
Tkinter. Stack overflow especially helped because it is a site where other inexperienced programmers
can asked questions and experienced programmers can answer. This helped me find the solution to
many problems I faced while learning.
Maintenance
Adaptive
Adaptive maintenance is how well the program can deal with change to software changes such as
updates and patches. This could be changes to python or pygame such as the change from python 2 to
python 3. These major changes to python could change the way that python is written similar to when
python 2 transitioned to python 3 and print statements started needing brackets enclosing them. This
would cause many issues as the python program would not be able to compile because of all of the
errors. One of the main ways to make code more adaptable is to comment out some parts of the code.
This makes it easier to read in the future so changes become easier and even other developers can
understand the code. Another way of making the code more adaptive is to change the file to an
executable. This makes the code far more portable as well as being able to run on any platform without
having to install python. This would be very important for me as having it run on linux would allow me to
reach a wider audience for my game. However, this could be worse as it would be hard to change the
code and would make it less adaptive.
Perfective
Perfective maintenance is where the code is changed based on user feedback to change the way in
which the program functions. A great way to improve the code for perfective maintenance is also by
using comments. This allows other developers in the future to understand the code and make changes
accordingly with the user's new needs. Sensible variable names should also be used to help myself and
future developers understand the code further. For example, just using letters for every variable name
can get confusing whereas using variables like playerx can clearly refer to the players x location. The
main disadvantage of this method is it can be harder to implement changes to the code such as updates
and patches, making it less adaptive with newer versions of python.
Corrective
Corrective adaptation is focused on finding and fixing bugs as fast as possible. Corrective adaptation is
done by asking customers after set periods of time to report on any bugs they found while using the
program. On top of this, I have run many tests to try and identify as many bugs as possible before
finishing this project, however, corrective adaptation can be important because it is nearly impossible to
have a bugless program so the user feedback keeps the game being as bugless as possible. The main way
I have delt with bugs in my program is by using separate modules for each of my main mechanics that I
can use to isolate problems in my code and efficiently find a solution without tampering with
unnecessary parts of the code. This speeds up the process of finding and removing bugs. An example of
this is my adding collision module.
Preventive
Preventive adaptation is based on how reliable the code is and increasing its reliability. A very good way
to improve the reliability of the code is to add preconditions to the code to stop invalid inputs from the
user. For example, in my login system, if a username is not input the user will be asked to login again.
This is used throughout my login system as this is the program with all of the user entry inputs, meaning
it is the only program that can have the incorrect inputs. To counter these problems I simply added a
few if statements that checked the input to see if it was valid. If the result was invalid the user would be
asked to input data again and if it was correct it would continue to the next module.
Final Evaluation
Overall, I think I did very well with this project. I managed to finish well within time and I think my code
was well done
Analysis evaluation
During my analysis I think I did a good job at setting the foundations on what I want my program to
become. I struggled a bit with trying to understand who my stakeholders/target market but eventually I
managed to understand. The computational methods helped me to understand how I will be writing my
code and how I can make it better, more readable and easier to make changes to. I think the research I
did into similar games was very valuable as it allowed me to understand what other games had to
succeed. I learned that the game shouldn’t be 1 dimensional and there should be a goal to reach, there
should also be replay ability so the user can enjoy the game more than once. The essential features
section really helped me to understand what was needed for my program to work as I intended, it set
out the base for my game to be built on so it can succeed. Limitations of the game was a necessary
section to allow me to understand what kind of hardware this game will be played on so I can design it
accordingly. Having a success criteria was incredibly helpful and I think I made mine well as I used as I
developed my game. This was because I covered every single aspect of the game that I wanted at the
time to make sure my game would be good.
Design evaluation
My problem breakdown was well done as it allowed me to understand how I was going to structure my
code and how I would use modules to make coding easier. I think I could have made the flow charts a bit
better and added more detail to the descriptions but they did help me a lot with the structure of my
code. The algorithms section allowed me to see how my code would be written in pseudo code before
actually writing it. Usability features was done well as it allowed me to see what should be done in the
game to make it work well and be successful. I could have used a better data base than a text file,
however I didn’t have enough time to learn how to use another one. Key variables helped be by making
me aware on what variables are needed and need to be sensibly named.
Bibliography
Appendix
Final Game
import pygame, os, time
from wallsinlevels import *
from math import *
from loginsystem import *
if next == True:
from startmenu import *
if after == True:
# initialising pygame
pygame.init()
pygame.mixer.init()
# sets the base volume for all of the sounds
volume = volumev/100
# sets certain sounds to appropriate variable names
footsteps = pygame.mixer.Sound(os.path.join("assets", "footsteps.mp3"))
footsteps.set_volume(volume)
glass = pygame.mixer.Sound(os.path.join("assets", "glass.mp3"))
glass.set_volume(volume)
fire = pygame.mixer.Sound(os.path.join("assets", "fire.mp3"))
fire.set_volume(volume)
# creating the display size
xwidth = 1280
yheight = 720
# using the display size to create the display
size = [1280, 720]
screen = pygame.display.set_mode(size)
# title and icon
icon = pygame.image.load(os.path.join("assets", "icon.png"))
pygame.display.set_icon(icon)
pygame.display.set_caption("My Game")
# variables that hold values of colours that are used later in the game
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
white = (255, 255, 255)
black = (0, 0, 0)
# the font that is used for health and winning screen
font = pygame.font.Font("freesansbold.ttf", 36)
vfont = pygame.font.Font("freesansbold.ttf", 38)
# creating the Groups for players, enemies, walls, attacks and exits
spriteslist = pygame.sprite.Group()
players = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
exitlist = pygame.sprite.Group()
floors = pygame.sprite.Group()
keys = pygame.sprite.Group()
closeattacks = pygame.sprite.Group()
walllist = pygame.sprite.Group()
clock = pygame.time.Clock()
enemieslist = []
# setting the player score as 0
score = 0
aa
bb
cc
dd
ee
=
=
=
=
=
0
0
0
0
0
enemyspeed = 1
enemydamage = 1
door = 255,0,0
if difficulty == "hard":
enemydamage = 2
enemyspeed = 2
elif difficulty == "normal":
enemydamage = 2
enemyspeed = 1
elif difficulty == "easy":
enemydamage = 1
enemyspeed = 1
presskey = False
while presskey == False:
screen.fill(black)
pressbutton = font.render("Press ANY KEY to start.", True, (255, 255,
255))
screen.blit(pressbutton, (420,330))
pygame.display.update()
# allow the exit button to be used
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
presskey = True
# this detects wether or not the mouse is hovering over, clicking or
neither on a button
def buttondetection(buttonx,buttony,buttonwidth,buttonheight):
# allowing the mouse presses to have variable names
leftmouse,middlemouse,rightmouse = pygame.mouse.get_pressed()
xmouse, ymouse = pygame.mouse.get_pos()
# if the mouse is over certain areas of the screen
if xmouse >= buttonx and xmouse <= buttonx+buttonwidth and ymouse >=
buttony and ymouse <= buttony+buttonheight:
# if mouse is hovering over a button
current = "hover"
if leftmouse:
# if the mouse is hovering over the button and has pressed it
current="pressed"
else:
# if the mouse is not hovering over any button
current="none"
clock.tick(80)
pygame.display.update()
# returns variable current which holds the data of whether or not the
mouse has pressed a button, is hovering over a button or not on anything
return current
# this displays the pause screen and the buttons on it
def pause():
global notdone, score, footsteps, glass, fire, volume, starttime,
level, game, character, enemies, enemieslist, enemydamage, enemyspeed, keyc
# loading graphics
pausemenu = pygame.image.load(os.path.join('assets', "paused.png"))
restartbutton = pygame.image.load(os.path.join('assets',
"prestart.png"))
exitbutton = pygame.image.load(os.path.join('assets', "pexit.png"))
resumebutton = pygame.image.load(os.path.join('assets',
"presume.png"))
volumeimage = pygame.image.load(os.path.join('assets',
"pvolume.png"))
upbutton = pygame.image.load(os.path.join('assets', "pvolumeup.png"))
downbutton = pygame.image.load(os.path.join('assets',
"pvolumedown.png"))
difficultyimage = pygame.image.load(os.path.join('assets',
"pdifficulty.png"))
hardbutton = pygame.image.load(os.path.join('assets', "phard.png"))
normalbutton = pygame.image.load(os.path.join('assets',
"pnormal.png"))
easybutton = pygame.image.load(os.path.join('assets', "peasy.png"))
volumebg = pygame.image.load(os.path.join('assets', "volumebg.png"))
# button coordinates and size
exitbuttoncoords = {"x":770,"y":520}
restartbuttoncoords = {"x":436,"y":520}
upbuttoncoords = {"x":730,"y":200}
downbuttoncoords = {"x":500,"y":200}
resumebuttoncoords = {"x":596,"y":520}
easybuttoncoords = {"x":465,"y":440}
normalbuttoncoords = {"x":565,"y":440}
hardbuttoncoords = {"x":725,"y":440}
buttonwidth=50
buttonheight=50
resumebuttonwidth = 164
restartbuttonwidth = 150
exitbuttonwidth = 78
easybuttonwidth = 93
normalbuttonwidth = 150
hardbuttonwidth = 93
# print pause overlay
screen.blit(pausemenu, (515,30))
screen.blit(volumeimage, (560,200))
screen.blit(upbutton,(730, 200))
screen.blit(downbutton,(500, 200))
screen.blit(difficultyimage,(553, 360))
screen.blit(easybutton,(465, 440))
screen.blit(normalbutton,(565, 440))
screen.blit(hardbutton,(725, 440))
screen.blit(restartbutton,(436, 520))
screen.blit(resumebutton,(596, 520))
screen.blit(exitbutton,(770, 520))
# pause menu loopp
paused = True
while paused:
# allow the exit button to be used
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
v = round(volume*100, 0)
volumeperc = vfont.render(str(v)+"%", False, (0, 0, 0))
screen.blit(volumebg,(570, 280))
screen.blit(volumeperc, (580,286))
# if volume up button is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(upbuttoncoords["x"],upbuttoncoords["y"],buttonwidth,buttonheight)
if status == "pressed":
# ups the volume by 0.01 and applies new value it to all
sounds
volume = volume*100
volume += 1
if volume > 100:
volume = 100
volume = volume/100
footsteps.set_volume(volume)
glass.set_volume(volume)
fire.set_volume(volume)
elif status == "hover":
# creates a green border around the button to imply it is
being hovered over
pygame.draw.rect(screen, green,(upbuttoncoords["x"],
upbuttoncoords["y"], buttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it isn't
being hovered over
pygame.draw.rect(screen, white,(upbuttoncoords["x"],
upbuttoncoords["y"], buttonwidth, buttonheight,), 3)
# if volume down is pressed
status =
buttondetection(downbuttoncoords["x"],downbuttoncoords["y"],buttonwidth,buttonhei
ght)
if status == "pressed":
# reduces volume by 0.01 and applies new value to all sounds
volume = volume*100
volume -= 1
if volume < 0:
volume = 0
volume = volume/100
footsteps.set_volume(volume)
glass.set_volume(volume)
fire.set_volume(volume)
elif status == "hover":
# creates a green border around the button to imply it is
being hoverd over
pygame.draw.rect(screen, green,(downbuttoncoords["x"],
downbuttoncoords["y"], buttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it isn't
being hoverd over
pygame.draw.rect(screen, white,(downbuttoncoords["x"],
downbuttoncoords["y"], buttonwidth, buttonheight,), 3)
# if easy is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(easybuttoncoords["x"],easybuttoncoords["y"],easybuttonwidth,butto
nheight)
if status == "pressed":
for i in range(len(enemieslist)):
a = enemieslist[i]
a.speed = 1
a.damage = 1
enemyspeed = 1
enemydamage = 1
elif status == "hover":
# creates a green border around the button to imply it is
being hoverd over
pygame.draw.rect(screen, green,(easybuttoncoords["x"],
easybuttoncoords["y"], easybuttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it isn't
being hoverd over
pygame.draw.rect(screen, white,(easybuttoncoords["x"],
easybuttoncoords["y"], easybuttonwidth, buttonheight,), 3)
# if normal is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(normalbuttoncoords["x"],normalbuttoncoords["y"],normalbuttonwidth
,buttonheight)
if status == "pressed":
for i in range(len(enemieslist)):
a = enemieslist[i]
a.speed = 1
a.damage = 2
enemyspeed = 1
enemydamage = 2
elif status == "hover":
# creates a green border around the button to imply it is
being hoverd over
pygame.draw.rect(screen, green,(normalbuttoncoords["x"],
normalbuttoncoords["y"], normalbuttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it is'nt
being hoverd over
pygame.draw.rect(screen, white,(normalbuttoncoords["x"],
normalbuttoncoords["y"], normalbuttonwidth, buttonheight,), 3)
# if hard is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(hardbuttoncoords["x"],hardbuttoncoords["y"],
hardbuttonwidth,buttonheight)
if status == "pressed":
for i in range(len(enemieslist)):
a = enemieslist[i]
a.speed = 2
a.damage = 2
enemyspeed = 2
enemydamage = 2
elif status == "hover":
# creates a green border around the button to imply it is
being hovered over
pygame.draw.rect(screen, green,(hardbuttoncoords["x"],
hardbuttoncoords["y"], hardbuttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it isn't
being hoverd over
pygame.draw.rect(screen, white,(hardbuttoncoords["x"],
hardbuttoncoords["y"], hardbuttonwidth, buttonheight,), 3)
# restart button is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(restartbuttoncoords["x"],restartbuttoncoords["y"],restartbuttonwi
dth,buttonheight)
if status == "pressed":
# this will remove all walls, players and enemies from the
screen and reset all key valuse to their starting values
# the needed functions will then be called againso the game
can be played
killthings()
character.kill()
keyc.kill()
score = 0
paused = False
level = 1
starttime = time.time()
character = playerclass(100)
spriteslist.add(character)
players.add(character)
levelgen(lvl1, lvl1noofenemies, lvl1spawnsx, lvl1spawnsy,
lvl1crange, lvl1playerspawnx, lvl1playerspawny, keyp1)
elif status == "hover":
# creates a green border around the button to imply it is
being hoverd over
# this also updates the screen
pygame.draw.rect(screen, green,(restartbuttoncoords["x"],
restartbuttoncoords["y"], restartbuttonwidth, buttonheight,), 3)
pygame.display.update()
else:
# creates a white border around the button to imply it isn't
being hoverd over
# this also updates the screen
pygame.draw.rect(screen, white,(restartbuttoncoords["x"],
restartbuttoncoords["y"], restartbuttonwidth, buttonheight,), 3)
pygame.display.update()
# if resume button is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(resumebuttoncoords["x"],resumebuttoncoords["y"],resumebuttonwidth
,buttonheight)
if status == "pressed":
# paused = false which means that the paused loop will end
and the game will continue
paused = False
elif status == "hover":
# creates a green border around the button to imply it is
being hoverd over
pygame.draw.rect(screen, green,(resumebuttoncoords["x"],
resumebuttoncoords["y"], resumebuttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it isn't
being hoverd over
pygame.draw.rect(screen, white,(resumebuttoncoords["x"],
resumebuttoncoords["y"], resumebuttonwidth, buttonheight,), 3)
# if exit button is pressed
# buttondetection function is used to determine whether or not
the mouse has pressed a button, is hovering over a button or not on anything
status =
buttondetection(exitbuttoncoords["x"],exitbuttoncoords["y"],exitbuttonwidth,butto
nheight)
if status == "pressed":
# this will exit the game after ending the paused and game
loop
paused = False
notdone = False
quit()
elif status == "hover":
# creates a green border around the button to imply it is
being hoverd over
pygame.draw.rect(screen, green,(exitbuttoncoords["x"],
exitbuttoncoords["y"], exitbuttonwidth, buttonheight,), 3)
else:
# creates a white border around the button to imply it isn't
being hoverd over
pygame.draw.rect(screen, white,(exitbuttoncoords["x"],
exitbuttoncoords["y"], exitbuttonwidth, buttonheight,), 3)
# function to display the game over screen when the player dies
def gameend():
global notdone, character, level, score, starttime, keyc
# loading graphics
exit = pygame.image.load(os.path.join("assets", "exitend.png"))
restart = pygame.image.load(os.path.join("assets", "restartend.png"))
gameover = pygame.image.load(os.path.join("assets", "gameover.png"))
# button coordinates and size
exitbuttoncoords = {"x":80,"y":577}
restartbuttoncoords = {"x":1116,"y":577}
buttonwidth=50
buttonheight=50
# print pause overlay
screen.blit(gameover, (0,0))
# pause menu loop
game = False
while game == False:
# allow the exit button to be used
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
#printing exit and restart button graphics
screen.blit(exit,(exitbuttoncoords["x"],exitbuttoncoords["y"]))
screen.blit(restart,(restartbuttoncoords["x"],restartbuttoncoords
["y"]))
# restart button is pressed
status =
buttondetection(restartbuttoncoords["x"],restartbuttoncoords["y"],buttonwidth,but
tonheight)
if status == "pressed":
# this will remove all walls, players and enemies from the
screen and reset all key valuse to their starting values
# the needed functions will then be called againso the game
can be played
score = 0
keyc.kill()
game = True
level = 1
character = playerclass(100)
starttime = time.time()
spriteslist.add(character)
players.add(character)
levelgen(lvl1, lvl1noofenemies, lvl1spawnsx, lvl1spawnsy,
lvl1crange, lvl1playerspawnx, lvl1playerspawny, keyp1)
# exit button is pressed
status =
buttondetection(exitbuttoncoords["x"],exitbuttoncoords["y"],buttonwidth,buttonhei
ght)
if status == "pressed":
# this will exit the game after ending the paused and game
loop
game = True
notdone = False
quit()
else:
# this will update the display
pygame.time.delay(50)
pygame.display.update()
# function to dissplay the game over screen when the player dies
def winning():
global notdone, character, level, score, totaltime, totalscore,
starttime
# loading graphics
exit = pygame.image.load(os.path.join("assets", "exitwinner.png"))
restart = pygame.image.load(os.path.join("assets",
"restartwinner.png"))
scoreboard = pygame.image.load(os.path.join("assets",
"scoreboardwinner.png"))
winningscreen = pygame.image.load(os.path.join("assets",
"winningscreen.png"))
winning100 = pygame.image.load(os.path.join("assets",
"100%winningscreen.png"))
confetti = pygame.image.load(os.path.join("assets", "confetti.png"))
# if the player got 100% score it will display a different background
if score == 50:
win = winning100
else:
win = winningscreen
# button coordinates and size
exitbuttoncoords = {"x":80,"y":577}
restartbuttoncoords = {"x":1050,"y":577}
scoreboardbuttoncoords = {"x":565,"y":650}
buttonwidth=150
buttonheight=50
# text for time and % completion
timetaken = font.render("Time: "+str(totaltime), True, (252, 196,
27))
completion = font.render("Completion %: "+str(totalscore), True,
(252, 196, 27))
winy = -720
if timetrialv == True:
c = (str(totaltime)+" "+str(totalscore)+" "+str(username)+"\n")
d=open("playertimes.txt", "a")
d.write(c)
screen.blit(win, (0,0))
# pause menu loop
game = False
while game == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
#printing exit and restart button graphics
screen.blit(win, (0,0))
screen.blit(confetti, (0,winy))
screen.blit(exit,(exitbuttoncoords["x"],exitbuttoncoords["y"]))
screen.blit(restart,(restartbuttoncoords["x"],restartbuttoncoords
["y"]))
screen.blit(scoreboard,(scoreboardbuttoncoords["x"],scoreboardbut
toncoords["y"]))
if timetrialv == True:
screen.blit(timetaken, (270,325))
# if the player has achieved 100% the completion is not showed as
the 100% is shown on the 100% graphic
if timetrialv == True:
screen.blit(completion, (675,325))
else:
screen.blit(completion, (475,325))
# restart button is pressed
status =
buttondetection(restartbuttoncoords["x"],restartbuttoncoords["y"],buttonwidth,but
tonheight)
if status == "pressed":
# this will remove all walls, players and enemies from the
screen and reset all key valuse to their starting values
# the needed functions will then be called againso the game
can be played
score = 0
keyc.kill()
game = True
level = 1
character = playerclass(100)
starttime = time.time()
spriteslist.add(character)
players.add(character)
levelgen(lvl1, lvl1noofenemies, lvl1spawnsx, lvl1spawnsy,
lvl1crange, lvl1playerspawnx, lvl1playerspawny, keyp1)
# scoreboard button is pressed
status =
buttondetection(scoreboardbuttoncoords["x"],scoreboardbuttoncoords["y"],buttonwid
th,buttonheight)
if status == "pressed":
scoreboarddef()
# exit button is pressed
status =
buttondetection(exitbuttoncoords["x"],exitbuttoncoords["y"],buttonwidth,buttonhei
ght)
if status == "pressed":
# this will exit the game after ending the paused and game
loop
game = True
notdone = False
quit()
else:
# this updates the display
pygame.time.delay(50)
pygame.display.update()
# this moves the confetti graphic down the page
winy += 10
def scoreboarddef():
global arr
scoreb = True
board = pygame.image.load(os.path.join("assets", "scoreboard.png"))
sorting(1)
backb = {"x":78,"y":622}
buttonwidth=120
buttonheight=50
timeb = {"x":1100,"y":630}
tbuttonwidth=96
tbuttonheight=40
completionb = {"x":870,"y":630}
cbuttonwidth=250
cbuttonheight=43
aa
bb
cc
dd
ee
=
=
=
=
=
arr[0]
arr[1]
arr[2]
arr[3]
arr[4]
while scoreb == True:
screen.blit(board, (0, 0))
firstname = font.render(str(aa[10:20]), True, (252, 196, 27))
secondname = font.render(str(bb[10:20]), True, (252, 196, 27))
thirdname = font.render(str(cc[10:20]), True, (252, 196, 27))
fourthname = font.render(str(dd[10:20]), True, (252, 196, 27))
fithname = font.render(str(ee[10:20]), True, (252, 196, 27))
firstpercen = font.render(str(aa[5:9]), True, (252, 196, 27))
secondpercen = font.render(str(bb[5:9]), True, (252, 196, 27))
thirdpercen = font.render(str(cc[5:9]), True, (252, 196, 27))
fourthpercen = font.render(str(dd[5:9]), True, (252, 196, 27))
fithpercen = font.render(str(ee[5:9]), True, (252, 196, 27))
firsttime = font.render(str(aa[0:5]), True, (252, 196, 27))
secondtime = font.render(str(bb[0:5]), True, (252, 196, 27))
thirdtime = font.render(str(cc[0:5]), True, (252, 196, 27))
fourthtime = font.render(str(dd[0:5]), True, (252, 196, 27))
fithtime = font.render(str(ee[0:5]), True, (252, 196, 27))
screen.blit(firstname, (100, 210))
screen.blit(secondname, (100, 290))
screen.blit(thirdname, (100, 370))
screen.blit(fourthname, (100, 460))
screen.blit(fithname, (100, 540))
screen.blit(firsttime, (855, 210))
screen.blit(secondtime, (855, 290))
screen.blit(thirdtime, (855, 370))
screen.blit(fourthtime, (855, 460))
screen.blit(fithtime, (855, 540))
screen.blit(firstpercen, (470, 210))
screen.blit(secondpercen, (470, 290))
screen.blit(thirdpercen, (470, 370))
screen.blit(fourthpercen, (470, 460))
screen.blit(fithpercen, (470, 540))
# time button is pressedw
status =
buttondetection(timeb["x"],timeb["y"],tbuttonwidth,tbuttonheight)
if status == "pressed":
sorting(1)
aa = arr[0]
bb = arr[1]
cc = arr[2]
dd = arr[3]
ee = arr[4]
# completion button is pressed
status =
buttondetection(completionb["x"],completionb["y"],cbuttonwidth,cbuttonheight)
if status == "pressed":
sorting(0)
arr.reverse()
aa = arr[0]
bb = arr[1]
cc = arr[2]
dd = arr[3]
ee = arr[4]
# back button is pressedw
status =
buttondetection(backb["x"],backb["y"],buttonwidth,buttonheight)
if status == "pressed":
# ends the loop and goes back to the winning screen
scoreb = False
else:
# this updates the display
pygame.time.delay(50)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
def sorting(type):
global arr
with open("playertimes.txt", "r") as read1:
arr = read1.read().splitlines()
read1.close()
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
x = arr[j]
y = arr[j+1]
if type == 1:
xrange = x[0:4]
yrange = y[0:4]
xrange2 = x[5:9]
yrange2 = y[5:9]
else:
xrange = x[5:9]
yrange = y[5:9]
xrange2 = x[0:4]
yrange2 = y[0:4]
if float(xrange) > float(yrange):
arr[j], arr[j+1] = arr[j+1], arr[j]
elif float(xrange) == float(yrange):
if float(xrange2) < float(yrange2):
arr[j], arr[j+1] = arr[j+1], arr[j]
# function to delete the walls, exits and enemies when the player
completes the level and moves to the next room
def killthings():
for i in walllist:
i.kill()
for i in exitlist:
i.kill()
for i in enemies:
i.kill()
for i in floors:
i.kill()
# player class
class playerclass(pygame.sprite.Sprite):
def __init__(self, hp):
# this makes the class into a sprite when called
pygame.sprite.Sprite.__init__(self)
# the image that will be displayed for the character and the size
of the rectangle (hitbox) around it
self.image = pygame.image.load(os.path.join("assets",
"characterv2.png"))
# creates the hitbox for the player
self.rect = self.image.get_rect()
# setting the players hp to hp (whatever the variable is when
called e.g. playerclass(100) hp = 100)
self.hp = hp
# this sets the first spawn for the player
self.rect.centerx = 640
self.rect.centery = 685
def update(self):
global playerx, playery, b
# checks if any key is being pressed and sets it to the variable
keystate
keystate = pygame.key.get_pressed()
# makes the footsteps noise play
play = False
# every 0.2 seconds while moving the footsteps noise will play
if 0 < (b % 0.2) < 0.01:
play = True
# if the a key is pressed
if keystate[pygame.K_a]:
# the player will move left by 5 pixels and the image will
change to show he is moving left
self.rect.centerx -= 5
self.image = pygame.image.load(os.path.join("assets",
"characterv2l.png"))
# checks if the player is walking into a wall or enemy and if
they are it restets the players position so it hasn't moved
if (pygame.sprite.spritecollide(self, walllist, False)) or
(pygame.sprite.spritecollide(self, enemies, False)):
self.rect.centerx += 5
else:
# this will play footsteps if play = True
if play == True:
footsteps.play()
# if the d key is pressed
if keystate[pygame.K_d]:
# the player will move right by 5 pixels and the image will
change to show he is moving right
self.rect.centerx += 5
self.image = pygame.image.load(os.path.join("assets",
"characterv2r.png"))
# checks if the player is walking into a wall or enemy and if
they are it restets the players position so it hasn't moved
if (pygame.sprite.spritecollide(self, walllist, False)) or
(pygame.sprite.spritecollide(self, enemies, False)):
self.rect.centerx -= 5
else:
# this will play footsteps if play = True
if play == True:
footsteps.play()
# if the w key is pressed
if keystate[pygame.K_w]:
# the player will move up by 5 pixels and the image will
change to show he is moving up
self.rect.centery -= 5
self.image = pygame.image.load(os.path.join("assets",
"characterv2b.png"))
# checks if the player is walking into a wall or enemy and if
they are it restets the players position so it hasn't moved
if (pygame.sprite.spritecollide(self, walllist, False)) or
(pygame.sprite.spritecollide(self, enemies, False)):
self.rect.centery += 5
else:
# this will play footsteps if play = True
if play == True:
footsteps.play()
# if the s key is pressed
if keystate[pygame.K_s]:
# the player will move down by 5 pixels and the image will
change to show he is moving down
self.rect.centery += 5
self.image = pygame.image.load(os.path.join("assets",
"characterv2.png"))
# checks if the player is walking into a wall or enemy and if
they are it restets the players position so it hasn't moved
if (pygame.sprite.spritecollide(self, walllist, False)) or
(pygame.sprite.spritecollide(self, enemies, False)):
self.rect.centery -= 5
else:
# this will play footsteps if play = True
if play == True:
footsteps.play()
# if the player is moving off the screen, it will correct it so
they are on the edge
if (self.rect.centerx) < 32:
(self.rect.centerx) = 32
if (self.rect.centerx) >= 1248:
(self.rect.centerx) = 1248
if (self.rect.centery) < 32:
(self.rect.centery) = 32
if (self.rect.centery) >= 688:
(self.rect.centery) = 688
# class for the bullets the player shoots
class bullet(pygame.sprite.Sprite):
def __init__(self):
# this makes the class into a sprite when called
pygame.sprite.Sprite.__init__(self)
# sets the image for the throwable
self.image = pygame.image.load(os.path.join("assets",
"flask.png"))
#creates the hitbox for the throwable
self.rect = self.image.get_rect()
# sets the throwable speed to 0 in the x and y direction
self.xspeed = 0
self.yspeed = 0
def find(self, x, y):
global bulletstate
# bulletstate = "f" means that another bullet canot be fired
until it = "r"
bulletstate = "f"
# this sets the throwable x and y to the player x and y so it can
com from the player as if they have thrown it
self.rect.centerx = character.rect.centerx
self.rect.centery = character.rect.centery
# this sets the speed of x and y to the parameters of the
function
self.xspeed = x
self.yspeed = y
# this calls the function to start moving the throwable
self.move()
def move(self):
global bulletstate, bullet1, glass, score
if pygame.sprite.spritecollide(self, enemies, True):
# if the throwable hits an enemy it will increase score by 1
and will delete the throwable
glass.play()
self.xspeed, self.yspeed = 0, 0
bulletstate = "r"
self.kill()
bullets.remove(bullet1)
score += 1
if not(pygame.sprite.spritecollide(bullet1, walllist, False) or
pygame.sprite.spritecollide(bullet1, enemies, False) or self.rect.centerx<0 or
self.rect.centerx>1280 or self.rect.centery<0 or self.rect.centery>720):
# if the throwable has not his a wall or gone off the screen
it will move the throwable by xspeed in the x direction and y speed in the y
direction
self.rect.centerx += self.xspeed
self.rect.centery += self.yspeed
# this draws the throwable onto the screen
bullets.draw(screen)
else:
# if the throwable is no longer moving a glass shattering
noise will play, the x and y speed will be set to 0 and the bullet is removet
from the sprite list bullets
# bulletstate = "r" so the throwable can be fired again
glass.play()
self.xspeed, self.yspeed = 0, 0
bulletstate = "r"
self.kill()
bullets.remove(bullet1)
# class for the short range attacks the player has
class closeattack(pygame.sprite.Sprite):
def __init__(self, side):
# this makes the class into a sprite when called
pygame.sprite.Sprite.__init__(self)
# this sets the parameter of side to be an attribute and
determines which side the player wants it to be used
self.side = side
# changes the image depending on what side the player wants it
if self.side == "r":
self.image = pygame.image.load(os.path.join("assets",
"bunsenr.png"))
if self.side == "l":
self.image = pygame.image.load(os.path.join("assets",
"bunsenl.png"))
# gets the hitbox of the attack
self.rect = self.image.get_rect()
# sets attack speed to 5
self.yspeed = 5
def find(self, d):
global meleestate
# this means the melee cannot be used until melee state = "r"
meleestate = "f"
# depending on what side the player wants to meleea different
function will be called
if self.side == "l":
# the starting point of the melee is set to the top right of
the player if the melee is the left
self.rect.topright = character.rect.topleft
self.movel()
elif self.side == "r":
# the starting point of the melee is set to the top left of
the player if the melee is the right
self.rect.topleft = character.rect.topright
self.mover()
def movel(self):
global meleestate, closeatt, amount, fire, score
# this function is for the melee on the left side
# if amount == 70 means if the melee has traveled 70pixels from
its starting place it will be deleted and abother melee will be able to be used
if amount == 70:
# reseting the values so the melee can be used again
self.xspeed, self.yspeed = 0, 0
meleestate = "r"
self.kill()
amount = 0
else:
# this moves the melee further away from its starting place
x,y = character.rect.topleft
y += amount
self.rect.topright = x,y
amount+=5
closeattacks.draw(screen)
fire.play()
if (pygame.sprite.spritecollide(closeatt, enemies, True)):
# this adds score when the melee hits an enemy
score += 2
def mover(self):
global meleestate, closeatt, amount, score
# this function is for the melee on the right side
# if amount == 70 means if the melee has traveled 70pixels from
its starting place it will be deleted and abother melee will be able to be used
if amount == 70:
self.xspeed, self.yspeed = 0, 0
meleestate = "r"
self.kill()
amount = 0
else:
# this moves the melee further away from its starting place
x,y = character.rect.topright
y += amount
self.rect.topleft = x,y
amount+=5
closeattacks.draw(screen)
fire.play()
if (pygame.sprite.spritecollide(closeatt, enemies, True)):
# this adds score when the melee hits an enemy
score += 2
# enemy class
class sprite(pygame.sprite.Sprite):
def __init__(self,x,y, damage, speed):
global enemyimg
# this makes the class a sprite when called
pygame.sprite.Sprite.__init__(self)
# this sets the image as enemy
self.image = pygame.image.load(os.path.join("assets",
"enemy.png"))
# this then creates the hitbox around it
self.rect = self.image.get_rect()
# x and y make up the starting position of the enemy
self.rect.centerx = x
self.rect.centery = y
self.speed = speed
self.damage = damage
self.x = x
self.y = y
def update(self):
global character
# this sets x and y to be local variables of the players x and y
x, y = character.rect.center
# if the player is within 600 pixels of the enemy the enemywill
move towards the player
# (sqrt(abs(x-self.rect.centerx)**2 + abs(yself.rect.centery)**2)) uses pythagoras theorem to determine how far away the
player is
if (sqrt(abs(x-self.rect.centerx)**2 + abs(yself.rect.centery)**2)) < 600:
# if the player is to the right of the enemy
if x > self.rect.centerx:
# the enemy will move right by 1 pixel
self.rect.centerx+=self.speed
# the image will change to fitfor itmoving right
self.image = pygame.image.load(os.path.join("assets",
"enemyr.png"))
# if the enemy is touching the player
if (pygame.sprite.spritecollide(self, players, False)):
# the player will lose 1 hp
character.hp -= self.damage
# if the enemy istouching the player or walls
if (pygame.sprite.spritecollide(self, walllist, False))
or (pygame.sprite.spritecollide(self, players, False)):
# the enemy will get moved back
self.rect.centerx-=self.speed
# if the player is to the left of the enemy
if x < self.rect.centerx:
# the enemy will move left by 1 pixel
self.rect.centerx-=self.speed
# the image will change to fit for itmoving left
self.image = pygame.image.load(os.path.join("assets",
"enemyl.png"))
# if the enemy is touching the player
if (pygame.sprite.spritecollide(self, players, False)):
# the player will lose 1 hp
character.hp -= self.damage
# if the enemy istouching the player or walls
if (pygame.sprite.spritecollide(self, walllist, False))
or (pygame.sprite.spritecollide(self, players, False)):
# the enemy will get moved back
self.rect.centerx+=self.speed
# if the player is below the enemy
if y > self.rect.centery:
# the enemy will move down by 1 pixel
self.rect.centery+=self.speed
# the image will change to fitfor itmoving down
self.image = pygame.image.load(os.path.join("assets",
"enemy.png"))
# if the enemy is touching the player
if (pygame.sprite.spritecollide(self, players, False)):
# the player will lose 1 hp
character.hp -= self.damage
# if the enemy istouching the player or walls
if (pygame.sprite.spritecollide(self, walllist, False))
or (pygame.sprite.spritecollide(self, players, False)):
# the enemy will get moved back
self.rect.centery-= self.speed
# if the player is above the enemy
if y < self.rect.centery:
# the enemy will move up by 1 pixel
self.rect.centery-=self.speed
# the image will change to fit for itmoving up
self.image = pygame.image.load(os.path.join("assets",
"enemyb.png"))
# if the enemy is touching the player
if (pygame.sprite.spritecollide(self, players, False)):
# the player will lose 1 hp
character.hp -= self.damage
# if the enemy istouching the player or walls
if (pygame.sprite.spritecollide(self, walllist, False))
or (pygame.sprite.spritecollide(self, players, False)):
# the enemy will get moved back
self.rect.centery += self.speed
# wall class
class walls(pygame.sprite.Sprite):
def __init__(self, x, y):
# this makes the class a sprite when called
pygame.sprite.Sprite.__init__(self)
# it creates white square, gets the hitbox for that square then
gets assigned an x and y value from the parameters
self.image = pygame.Surface([40, 40])
self.rect = self.image.get_rect()
self.image.fill(white)
self.rect.x = x
self.rect.y = y
# door class
class exit(pygame.sprite.Sprite):
def __init__(self, x, y):
global door
# this makes the class a sprite when called
pygame.sprite.Sprite.__init__(self)
# it creates yellow square, gets the hitbox for that square then
gets assigned an x and y value from the parameters
self.image = pygame.Surface([40, 40])
self.rect = self.image.get_rect()
self.image.fill((door))
self.rect.x = x
self.rect.y = y
def update(self):
global door
self.image.fill((door))
# floor class
class floor(pygame.sprite.Sprite):
def __init__(self, x, y):
# this makes the class a sprite when called
pygame.sprite.Sprite.__init__(self)
# it creates yellow square, gets the hitbox for that square then
gets assigned an x and y value from the parameters
self.image = pygame.image.load(os.path.join("assets",
"floor.jpg"))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# floor class
class key(pygame.sprite.Sprite):
def __init__(self, x, y):
# this makes the class a sprite when called
pygame.sprite.Sprite.__init__(self)
# it creates yellow square, gets the hitbox for that square then
gets assigned an x and y value from the parameters
self.image = pygame.image.load(os.path.join("assets", "key.png"))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# class for creating the level and enemies in that level
def levelgen(lvl, amount, xplace, yplace, crange, playerspawnx,
playerspawny, keyin):
global rect2, usedcrange, xx, yy, wall, leveladding, enemieslist,
character, starttime, keyv, key1, key2, keyc, door
# the character is created and placed at (playerspawnx, playerspawny)
character.rect.center = playerspawnx, playerspawny
# level adding is the increment in which the levels go up by
leveladding = 1
door = 255,0,0
for i in range(18):
for ii in range(32):
# these for loops create a way to go through a 18 by 32 space
which represents the level, walls and exits
# a is the number that represents a value in a list from a
program called wallsinlevel
a = ((i)*32) + ii
# if a is "W"
if lvl[a] == "W":
# a wall is created and placed at (ii*40, i*40) by
calling the class walls
wall = walls((ii*40), (i*40))
spriteslist.add(wall)
walllist.add(wall)
elif lvl[a] == "C":
# an exit is created and placed at (ii*40, i*40) by
calling the class exit
rect2 = exit((ii*40), (i*40))
exitlist.add(rect2)
spriteslist.add(rect2)
usedcrange = crange
elif lvl[a] == "F":
# a floor is created and placed at (ii*40, i*40) by
calling the class floor
flo = floor((ii*40), (i*40))
floors.add(flo)
spriteslist.add(flo)
# depending on amount (number of enemies in level) the loop will run
to place enemies in specific locations
for i in range(amount):
x, y = xplace[i], yplace[i]
# the sprite class is called to create a sprite of an enemy and
adds it to a sprite list,and other lists
sprt = sprite(x,y, enemydamage, enemyspeed)
spriteslist.add(sprt)
enemieslist.append(sprt)
enemies.add(sprt)
keyv = False
key1 = keyin[0]
key2 = keyin[1]
keyc = key(key1, key2)
keys.add(keyc)
# creating an instance of the player class and adding it to the players
group
character = playerclass(100)
spriteslist.add(character)
players.add(character)
# calling the levelgen function in order to create the first level
levelgen(lvl1, lvl1noofenemies, lvl1spawnsx, lvl1spawnsy, lvl1crange,
lvl1playerspawnx, lvl1playerspawny, keyp1)
# clarifying the current level before the game sttarts is 1
level = 1
# not done allows the main game loop to run, bulletstate and meleestate
are set to "r"
notdone = True
bulletstate = "r"
meleestate = "r"
leveladding = 1
bg = pygame.image.load(os.path.join("assets", "forest.png"))
keyimage = pygame.image.load(os.path.join("assets", "key.png"))
# starttime helps find the time taken to complete the game
starttime = time.time()
while
#
sound playing
a
b
notdone == True:
b is used to find the current time in the game which helps with
= time.time()
= a-starttime
# the screen is filled in black
screen.blit(bg, (0, 0))
# the sprites are updated and drawnonto the screen
spriteslist.update()
walllist.draw(screen)
spriteslist.draw(screen)
walllist.draw(screen)
keys.draw(screen)
enemies.draw(screen)
players.draw(screen)
# this refreshes the screen every 1/80th of a second
clock.tick(80)
# if a bullet is being fired the moving function is called
if bulletstate == "f":
bullet1.move()
# if a melee is taking place the moving function will be called
depending on what side it is
if meleestate == "f":
if closeatt.side == "l":
closeatt.movel()
elif closeatt.side == "r":
closeatt.mover()
# displaying the health on the top lef of the screen
healthl = font.render("Health: "+str(character.hp), False, (255, 255,
255))
screen.blit(healthl, (1075,0))
# displaying the score on the bottom left of the screen
scorel = font.render("Score: "+str(score), True, (255, 255, 255))
screen.blit(scorel, (1100,680))
# updating the screen
pygame.display.update()
# gets the inputs from the user
for event in pygame.event.get():
# allows the window to be closed
if event.type == pygame.QUIT:
notdone = False
pygame.quit()
# keyboard inputs from the user
if event.type == pygame.KEYDOWN:
# bullet fired left
if event.key == pygame.K_LEFT:
if bulletstate == "r":
bullet1 = bullet()
spriteslist.add(bullet1)
bullets.add(bullet1)
bullet1.find(-15, 0)
# bullet fired right
if event.key == pygame.K_RIGHT:
if bulletstate == "r":
bullet1 = bullet()
bullets.add(bullet1)
bullet1.find(15, 0)
# bullet fired up
if event.key == pygame.K_UP:
if bulletstate == "r":
bullet1 = bullet()
bullets.add(bullet1)
bullet1.find(0, -15)
# bullet fired down
if event.key == pygame.K_DOWN:
if bulletstate == "r":
bullet1 = bullet()
bullets.add(bullet1)
bullet1.find(0, 15)
# melee to the left
if event.key == pygame.K_COMMA:
if meleestate == "r":
meleestate = "f"
closeatt = closeattack("l")
closeattacks.add(closeatt)
amount = 0
# melee to the right
if event.key == pygame.K_PERIOD:
if meleestate == "r":
meleestate = "f"
closeatt = closeattack("r")
closeattacks.add(closeatt)
amount = 0
#allows the user to progress to the next level
if event.key == pygame.K_SPACE:
# if the payer is within an exit are
if (usedcrange[0] < character.rect.centerx <
usedcrange[1] and usedcrange[2] < character.rect.centery < usedcrange[3]) and
keyv == True:
level+=1
if level == 1:
lvl1spawnsy, lvl1crange,
lvl2spawnsy, lvl2crange,
lvl3spawnsy, lvl3crange,
lvl4spawnsy, lvl4crange,
lvl5spawnsy, lvl5crange,
killthings()
levelgen(lvl1, lvl1noofenemies, lvl1spawnsx,
lvl1playerspawnx, lvl1playerspawny, keyp1)
elif level == 2:
killthings()
levelgen(lvl2, lvl2noofenemies, lvl2spawnsx,
lvl2playerspawnx, lvl2playerspawny, keyp2)
elif level == 3:
killthings()
levelgen(lvl3, lvl3noofenemies, lvl3spawnsx,
lvl3playerspawnx, lvl3playerspawny, keyp3)
elif level == 4:
killthings()
levelgen(lvl4, lvl4noofenemies, lvl4spawnsx,
lvl4playerspawnx, lvl4playerspawny, keyp4)
elif level == 5:
killthings()
levelgen(lvl5, lvl5noofenemies, lvl5spawnsx,
lvl5playerspawnx, lvl5playerspawny, keyp5)
elif level == 6:
killthings()
character.kill()
screen.fill(black)
endtime = time.time()
totaltime = round(endtime-starttime, 1)
totalscore = round((score/50)*100, 2)
winning()
if (pygame.sprite.spritecollide(character, keys, True)):
keyv = True
door = 200,150,0
# pause the game and displays pause menu
if event.key == pygame.K_p:
pause()
# if characterhp = 0 the player dies and the game over screen shows
if character.hp <= 0:
killthings()
character.kill()
screen.fill(black)
gameend()
Login System
from tkinter import *
import os
# initialises tkinter
gui = Tk()
# creates the screen size and name
screenw = 1280
screenh = 720
scrnw = gui.winfo_screenwidth()
scrnh = gui.winfo_screenheight()
x = scrnw/2-screenw/2
y = scrnh/2-screenh/2
gui.geometry(f"{screenw}x{screenh}+{int(x)}+{int(y)}")
gui.title("Login System")
gui.resizable(False, False)
# setting the background
a = (os.path.join("assets", "beautiful bg (1280x720).png"))
pbg = PhotoImage(file = a)
bg = Canvas(width=1280,height=720, bg = "black")
bg.place(relx=0.5,rely=0.5,anchor=CENTER)
bg.create_image(640,360,anchor = CENTER, image=pbg)
go = False
difficulty = "normal"
# this closes the program
def gone():
gui.destroy()
next = False
# this gets rid of certain widgets
def getrid():
global eu, ep, lu, lp, eb, infol, sb, good, yes, no, newaccb, newaccl, backb
eu.place_forget()
ep.place_forget()
lu.place_forget()
lp.place_forget()
eb.place_forget()
infol.place_forget()
sb.place_forget()
try:
newaccb.place_forget()
newaccl.place_forget()
backb.place_forget()
except:
pass
# this closes the program after the user gets their username or password wrong
and decides not to try again
def close():
getrid()
k = Label(gui, text=" Ok ", font=("calibri", "300"))
k.place(relx=0.5, rely=0.5, anchor=CENTER)
gui.after(1000, gone)
# this is displayed if the user gets their username and password correct
def correct():
global go, a, b, c, next
next = True
getrid()
k = Label(gui, text="Correct!", font=("calibri", "150"))
k.place(relx=0.5, rely=0.5, anchor=CENTER)
go = True
gui.after(1500, gone)
def p(event):
global next, after, timetrialv, username
next = True
after = True
timetrialv = True
username = "Joe"
gui.destroy()
#this gets rid of certain widgets
def getrid2():
global good, yes, no
try:
good.place_forget()
yes.place_forget()
no.place_forget()
except:
pass
# this places certain widgets when needed
def place():
global newaccb, backb
good.place_forget()
yes.place_forget()
no.place_forget()
backb.place(relx=0.65, rely=0.326921, anchor=CENTER)
newaccb.place(relx=0.5, rely=0.3929076923, anchor=CENTER)
# this allows the user to go from the sign up menu back to the sign in menu
def back():
global sb, eb, newaccb, infol, newaccl, backb
backb.place_forget()
newaccl.place_forget()
newaccb.place_forget()
eb.place(relx=0.5, rely=0.41, anchor=CENTER)
infol.place(relx=0.5, rely=0.22, anchor=CENTER)
sb.place(relx=0.65, rely=0.326921, anchor=CENTER)
getrid2()
# this allows the user to go to the new account menu
def newacc():
global yes, no, good, newaccb, sb, eb, infol, newaccl, backb
getrid2()
gui.unbind("<Return>")
gui.bind("<Return>", newacccheck)
sb.place_forget()
eb.place_forget()
infol.place_forget()
newaccb = Button(gui,text = "Enter", command=newacccheck,
font=("Calibri","11"))
newaccb.place(relx=0.5, rely=0.41, anchor=CENTER)
newaccl = Label(gui,text = "Enter information for new account,\nthen press
Enter", font=("Calibri","11"))
newaccl.place(relx=0.5, rely=0.22, anchor=CENTER)
backb = Button(gui, text="Back", command=back, font=("Calibri","11"))
backb.place(relx=0.65, rely=0.326921, anchor=CENTER)
# this checks if the new account username is not being used and if the new
username and password is acceptable
def newacccheck():
global eu, ep, newaccb, newaccl, sb, eb, infol, yes, no, good, eu, ep, eb,
backb, lu, lp, c, next
username=eu.get()
b=ep.get()
# this opens the txt file
c = (username+" "+b+"\n")
d = open("uandp.txt", "r")
e = d.read()
# if the username or password is not filled out
if username == "" or b == "":
newaccb.place_forget()
backb.place_forget()
eu.delete(0,END)
ep.delete(0,END)
good = Label(gui, text="Please do not leave Username or Password
empty.\nDo you want to sign up again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=place, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=back, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
# this makes the username or password unable to start with a space
elif username[0] == " " or b[0] == " ":
newaccb.place_forget()
backb.place_forget()
eu.delete(0,END)
ep.delete(0,END)
good = Label(gui, text="Username or Password cannot start with a
space.\nDo you want to sign up again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=place, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=back, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
# this means a username cannot be used twice
elif username in e:
newaccb.place_forget()
backb.place_forget()
eu.delete(0,END)
ep.delete(0,END)
good = Label(gui, text="There is already an account with this name.\nDo
you want to sign up again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=place, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=back, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
# this means a username cannot be over 15 characters
elif len(username) > 15:
newaccb.place_forget()
backb.place_forget()
eu.delete(0,END)
ep.delete(0,END)
good = Label(gui, text="Username cannot be over 15 characters.\nDo you
want to sign up again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=place, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=back, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
# this writes the new username and password to the txt file
else:
c = username+" "+b+"\n"
d=open("uandp.txt", "a")
d.write(c)
d.close()
getrid()
done = Label(gui, text="Thank you\nfor signing up.", font=("Calibri",
"85"))
done.place(relx=0.5, rely=0.5, anchor=CENTER)
gui.after(1500, gone)
gui.unbind("<Return>")
next = True
# this makes the entry boxes empty when the user wants to imput their credentials
again
def passdef():
global yes, no, good, eb
eu.delete(0,END)
ep.delete(0,END)
yes.place_forget()
no.place_forget()
good.place_forget()
eb.place(relx=0.5, rely=0.41, anchor=CENTER)
sb.place(relx=0.65, rely=0.326921, anchor=CENTER)
# this checks to see if the entered credentials are correct
def check(event):
global username, b, sb, players, eb, good, yes, no, bad, players, eu, ep,
empty, new, enter, c, next
eb.place_forget()
username = eu.get()
b = ep.get()
c = (username+" "+b+"\n")
d = open("uandp.txt", "r")
e = d.read()
eu.delete(0,END)
ep.delete(0,END)
# if the username or password is not filled out
if a == "" or b == "":
sb.place_forget()
good = Label(gui, text="Please don't leave any area blank.\nDo you want
to try again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=passdef, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=close, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
d.close()
# this makes the username or password unable to start with a space
elif a[0] == " " or b[0] == " ":
sb.place_forget()
good = Label(gui, text="Username or Password cannot start with a
space.\nDo you want to try again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=passdef, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=close, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
d.close()
# if username or password is incorrect
elif (c not in e) or len(a) == 0 or len(b) == 0:
sb.place_forget()
good = Label(gui, text="Incorrect Username or password.\nDo you want to
try again?", font=("Claibri","11"))
good.place(relx=0.5, rely=0.407,anchor=CENTER)
yes = Button(gui, text="Yes", command=passdef, font=("Claibri","11"))
yes.place(relx=0.475, rely=0.46, anchor=CENTER)
no = Button(gui, text="No", command=close, font=("Claibri","11"))
no.place(relx=0.525, rely=0.46, anchor=CENTER)
d.close()
# correct is called if the username and password is correct
else:
correct()
gui.unbind("<Return>")
# all the labels and buttons that are used immendiately are placed straight away
eu = Entry(font=("Calibri","11"))
eu.place(relx=0.5, rely=0.3076923077, anchor = CENTER)
ep = Entry(show="•", font=("Calibri","11"))
ep.place(relx=0.5, rely=0.3461538462, anchor = CENTER)
lu = Label(gui, text="Username:", font=("Calibri","11"))
lu.place(relx=0.41, rely=0.3076923077, anchor = E)
lp = Label(gui, text=" Password:", font=("Calibri","11"))
lp.place(relx=0.41, rely=0.3461538462, anchor = E)
eb = Button(gui,text = "Enter", command = lambda: check(5),
font=("Calibri","11"))
eb.place(relx=0.5, rely=0.41, anchor=CENTER)
sb = Button(gui,text = "Don't have an account?\nSign Up!", command = newacc,
font=("Calibri","11"))
sb.place(relx=0.65, rely=0.326921, anchor=CENTER)
infol = Label(gui, text = "Input your username and password,\nthen press Enter to
log in.", font=("Calibri","11"))
infol.place(relx=0.5, rely=0.22, anchor=CENTER)
leave=Button(gui,text="Exit",command=gone, font=("Calibri","11"))
leave.place(relx=0,rely=1, anchor=SW)
# the enter key gets bound to check so it can be used to log in
gui.bind("<Return>", check)
gui.bind("<p>", p)
gui.mainloop()
Pre-game Start Menu
from tkinter import *
import os, math
gui = Tk()
# creates the screen size and name
screenw = 1280
screenh = 720
scrnw = gui.winfo_screenwidth()
scrnh = gui.winfo_screenheight()
x = scrnw/2-screenw/2
y = scrnh/2-screenh/2
# sets program in the middle of the screen
gui.geometry(f"{screenw}x{screenh}+{int(x)}+{int(y)}")
gui.title("Start Menu")
gui.resizable(False, False)
gui.configure(bg = "black")
# sets default variables to be use in the game
timetrialv = False
volumev = 15
after = False
# function to close the program
def gone():
gui.destroy()
# function to remove widgets
def getrid():
global np, tt, h2p, settings
np.place_forget()
tt.place_forget()
h2p.place_forget()
settings.place_forget()
# function to place widgets
def place():
global np, tt, h2p, settings, back
label.place_forget()
back.place_forget()
np.place(relx=0.025,rely=0.2,anchor=NW)
tt.place(relx=0.025,rely=0.35,anchor=NW)
h2p.place(relx=0.025,rely=0.5,anchor=NW)
settings.place(relx=0.025,rely=0.65,anchor=NW)
# function to remove widgets from the how to play screen
def h2pgetrid():
global h2pl
h2pl.place_forget()
place()
# function to place widgets for the how to play screen
def h2pdef():
global back, label, variable, h2pl
getrid()
label = Label(gui, text="How to play", font=("Calibri","24"))
label.place(relx=0.025,rely=0.2, anchor = NW)
h2pl = Label(gui, text="You will have to traverse through five different
\nlevels each with a specific number of enemies \nin each room. You must collect
a key in each \nroom to progress to the next level.\n\nControls\nW, A, S, D = Up,
Left, Down, Right\nArrow Keys = Bottle throw\n<, > = Melee",
font=("Calibri","22"), justify=LEFT)
h2pl.place(relx=0.025,rely=0.3, anchor = NW)
back = Button(gui,text="Back", command=h2pgetrid, font=("calibri","16"))
back.place(relx=0.975,rely=0.975, anchor=SE)
# function to remove widgets from the settings menu
def settinggetrid():
global settingl, f, b1, b2, b3, b4, b5, easy, normalb, hard, difficultyl,
volumel, volumeup, volumedown, volumelevel
label.place_forget()
back.place_forget()
difficultyl.place_forget()
easy.place_forget()
normalb.place_forget()
hard.place_forget()
volumel.place_forget()
volumeup.place_forget()
volumedown.place_forget()
volumelevel.place_forget()
place()
# function to place widgets for the settings menu
def settingdef():
global back, label, settingl, f, colour, b1 ,b2 ,b3, b4, b5, f, easy,
normalb, hard, difficultyl, volumel, volumeup, volumedown, volumelevel
getrid()
label = Label(gui, text="Settings", font=("Calibri","24"))
label.place(relx=0.025,rely=0.2, anchor=NW)
back = Button(gui,text="Back", command=settinggetrid, font=("calibri","16"))
back.place(relx=0.975,rely=0.975, anchor=SE)
difficultyl = Label(gui,text="Difficulty", font=("calibri","16"))
difficultyl.place(relx=0.025,rely=0.3)
easy = Button(gui,text="Easy", font=("calibri","16"), command = easydef)
easy.place(relx=0.025,rely=0.4)
normalb = Button(gui,text="Normal", font=("calibri","16"), command = harddef)
normalb.place(relx=0.115,rely=0.4)
hard = Button(gui,text="Hard", font=("calibri","16"), command = harddef)
hard.place(relx=0.225,rely=0.4)
volumel = Label(gui, text = "Volume", font=("calibri","16"))
volumel.place(relx=0.025, rely=0.6)
volumeup = Button(gui,text=" + ", font=("calibri","16"), command = vup)
volumeup.place(relx=0.115,rely=0.7)
volumelevel = Label(gui, text = str(volumev), font=("calibri","16"))
volumelevel.place(relx=0.088, rely=0.71, anchor = N)
volumedown = Button(gui,text=" - ", font=("calibri","16"), command = vdown)
volumedown.place(relx=0.025,rely=0.7)
# function to raise volume
def vup():
global volumelevel, volumev
volumelevel.place_forget()
volumev+= 1
if volumev >= 100:
volumev = 100
volumelevel = Label(gui, text = str(volumev), font=("calibri","16"))
volumelevel.place(relx=0.088, rely=0.71, anchor = N)
# function to lower volume
def vdown():
global volumelevel, volumev
volumelevel.place_forget()
volumev-= 1
if volumev <= 0:
volumev = 0
volumelevel = Label(gui, text = str(volumev), font=("calibri","16"))
volumelevel.place(relx=0.088, rely=0.71, anchor = N)
# function to change difficulty to hard
def harddef():
global difficulty
difficulty = "hard"
# function to change difficulty to normal
def normaldef():
global difficulty
difficulty = "normal"
# function to change difficulty to easy
def easydef():
global difficulty
difficulty = "easy"
# functino to remove wixgets from normal game screen
def normalgetrid():
global normall, normalb, label
label.place_forget()
normall.place_forget()
normalb.place_forget()
place()
# function to place widgets for the normal game screen
def normalplaythrough():
global normall, normalb, label, back
getrid()
back = Button(gui,text="Back", command=normalgetrid, font=("calibri","16"))
back.place(relx=0.975,rely=0.975, anchor=SE)
label = Label(gui, text="Normal Playthrough", font=("Calibri","24"))
label.place(relx=0.025,rely=0.2, anchor=NW)
normall = Label(gui, text="A normal playthrough with no limits or time
restrictions.", font=("Calibri","14"), justify=LEFT)
normall.place(relx=0.025,rely=0.3, anchor = NW)
normalb = Button(gui,text="Play", font=("Calibri", "24"),command=normal)
normalb.place(relx=0.5,rely=0.5,anchor=CENTER)
# function to load the game without a timer
def normal():
global after
after = True
gui.destroy()
# function to load the game with a timer
def timetrial(event):
global timetrialv, after
timetrialv = True
after = True
gui.destroy()
# function to remove the widgets from the time trial menu
def timetrialgetrid():
global normall, normalb, label
label.place_forget()
timel.place_forget()
timeb.place_forget()
time = True
place()
# function to place widgets for the time trial menu
def timeplaythrough():
global timel, timeb, label, back
getrid()
back = Button(gui,text="Back", command=timetrialgetrid,
font=("calibri","16"))
back.place(relx=0.975,rely=0.975, anchor=SE)
label = Label(gui, text="Normal Playthrough", font=("Calibri","24"))
label.place(relx=0.025,rely=0.2, anchor=NW)
timel = Label(gui, text="A timed playthrough", font=("Calibri","14"),
justify=LEFT)
timel.place(relx=0.025,rely=0.3, anchor = NW)
timeb = Button(gui,text="Play", font=("Calibri", "32"),command = lambda:
timetrial(5))
timeb.place(relx=0.5,rely=0.5,anchor=CENTER)
# placing the programs first needed widgets
epicgame = Label(gui,text="Carr's Offline Campaign", font=("carlibri","42"))
epicgame.place(relx=0.025,rely=0.025,anchor=NW)
np=Button(gui,text="Normal Playthrough",command=normalplaythrough,
font=("calibri","24"))
np.place(relx=0.025,rely=0.2,anchor=NW)
tt=Button(gui,text="Time Trial",command=timeplaythrough, font=("calibri","24"))
tt.place(relx=0.025,rely=0.35,anchor=NW)
h2p=Button(gui,text="How to Play",command=h2pdef, font=("calibri","24"))
h2p.place(relx=0.025,rely=0.50,anchor=NW)
settings=Button(gui,text="Settings",command=settingdef, font=("calibri","24"))
settings.place(relx=0.025,rely=0.65,anchor=NW)
leave = Button(gui,text="Exit",command=gone, font=("calibri","16"))
leave.place(relx=0,rely=1,anchor=SW)
z = (os.path.join("assets", "characterv2menu.png"))
character = PhotoImage(file = z)
bg = Canvas(width=250,height=417, bg = "black")
bg.place(relx=0.75,rely=0.5,anchor=CENTER)
bg.create_image(125,208,anchor = CENTER, image=character)
gui.mainloop()
Levels
#Walls for the levels of the game
lvl1 =
["O","O","O","O","O","O","O","O","O","O","O","O","O","W","C","C","C","C","W","O",
"O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","W","C","C","C","C","
W","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","W","F","F","F","F","
W","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","W","W","W","W","W","W","W","W","W","W","W","W","W","F","F","F","F","
W","W","W","W","W","W","W","W","W","W","W","W","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","W","W","F","F","F","W","W","F","F","F","W","W","F","
F","F","W","W","F","F","F","W","W","F","F","F","W","O",
"O","W","F","F","F","W","W","F","F","F","W","W","F","F","F","W","W","F","
F","F","W","W","F","F","F","W","W","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","W","W","W","W","W","W","W","W","W","W","W","W","F","F","F","F","
W","W","W","W","W","W","W","W","W","W","W","W","W","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","W","F","F","F","F","
W","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","W","F","F","F","F","
W","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","W","F","F","F","F","
W","O","O","O","O","O","O","O","O","O","O","O","O","O"]
lvl1spawnsx = [160,120,1070,1140,630]
lvl1spawnsy = [535,180,180,535,290]
lvl1noofenemies = 5
lvl1crange = [540, 700, 0, 80]
keyp1 = [1080, 360]
lvl1playerspawnx = 640
lvl1playerspawny = 670
lvl2 =
["O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","W","W","W","W","W","O","O","O","O",
"W","W","W","W","W","W","W","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","W","W","F","F","F","W","W","W","W","O",
"C","C","F","F","F","F","W","W","O","O","O","O","O","O","O","W","W","W","
W","W","W","W","W","F","F","F","F","F","F","F","W","O",
"C","C","F","F","F","F","F","W","W","W","W","W","W","W","W","W","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"C","C","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"W","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","O","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","W","W","O",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","O","O","O",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","O","O","O",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","W","W","O",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","F","W","W","W","W","F","F","F","F","F","F","F","
F","F","F","W","F","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","W","W","O","O","W","W","F","F","F","F","F","F","
F","F","W","W","W","F","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","W","O","O","O","O","W","F","F","F","F","F","F","
F","F","W","O","W","W","F","F","F","F","F","F","W","O",
"O","W","F","F","F","F","W","O","O","O","O","W","F","F","F","F","F","F","
F","F","W","O","O","W","W","W","W","F","F","F","W","O",
"O","W","W","W","W","W","W","O","O","O","O","W","F","F","F","F","F","F","
F","F","W","O","O","O","O","O","W","W","W","W","W","O",
"O","O","O","O","O","O","O","O","O","O","O","W","F","F","F","F","F","F","
F","F","W","O","O","O","O","O","O","O","O","O","O","O"]
lvl2spawnsx = [160,120,1070,1140,640]
lvl2spawnsy = [555,155,145,565,360]
lvl2noofenemies = 5
lvl2crange = [0,80,80,200]
keyp2 = [1080, 120]
lvl2playerspawnx = 640
lvl2playerspawny = 680
lvl3 =
["O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","W","W","W","W","W","W","W","W","
W","W","W","W","W","W","W","O","O","O","W","W","W","W",
"O","O","O","W","W","W","W","W","W","W","W","F","F","F","F","F","F","F","
F","F","F","F","F","F","W","W","W","W","W","F","F","F",
"O","O","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","F",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","F",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","W",
"W","W","W","F","F","F","F","F","F","F","F","W","W","W","W","W","W","W","
W","W","W","F","F","F","F","F","F","F","F","F","W","W",
"C","C","F","F","F","F","F","F","F","F","W","W","O","O","O","O","O","O","
O","O","W","W","W","F","F","F","F","F","F","W","W","O",
"C","C","F","F","F","F","F","F","F","W","W","O","O","O","O","O","O","O","
O","O","O","O","W","W","F","F","F","F","F","W","O","O",
"C","C","F","F","F","F","F","F","F","W","W","O","O","O","O","O","O","O","
O","O","O","W","W","F","F","F","F","F","W","W","O","O",
"C","C","F","F","F","F","F","F","F","F","W","W","O","O","O","O","O","O","
O","W","W","W","F","F","F","F","F","F","W","O","O","O",
"W","W","W","F","F","F","F","F","F","F","F","W","W","O","O","O","O","W","
W","W","F","F","F","F","F","F","F","W","W","O","O","O",
"O","O","W","F","F","F","F","F","F","F","F","F","W","W","W","W","W","W","
F","F","F","F","F","F","F","F","F","W","O","O","O","O",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","W","W","O","O","O","O",
"O","O","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","W","O","O","O","O","O",
"O","O","O","W","W","W","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","W","W","W","O","O","O","O","O",
"O","O","O","O","O","W","W","W","W","W","W","W","W","W","W","W","W","W","
W","W","W","W","W","W","W","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","O"]
lvl3spawnsx = [840, 450, 150, 400, 860]
lvl3spawnsy = [160, 190, 360, 580, 540]
lvl3noofenemies = 5
lvl3crange = [0,80,280,440]
keyp3 = [400, 440]
lvl3playerspawnx = 1280
lvl3playerspawny = 150
lvl4 =
["O","O","O","O","O","O","O","O","O","O","O","W","C","C","C","C","W","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","W","W","C","C","C","C","W","W","
O","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","W","W","W","W","W","W","F","F","F","F","F","F","W","
W","W","W","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","W","W","W","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","W","W","O","O","O","O","O","O","O","O","O","O",
"O","O","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","W","O","O","O","O","O","O","O","O","O","O",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","W","W","O","O","O","O","O","O","O","O","O",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","W","W","O","O","W","W","W","W","W","W",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","W","W","W","W","F","F","F","F","F",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","F",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","F",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","F",
"O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","W","W",
"O","O","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","W","W","O",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","W","O","O",
"O","O","O","W","W","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","O","O","O",
"O","O","O","O","W","W","W","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","W","W","O","O","O",
"O","O","O","O","O","O","W","W","W","W","W","W","W","W","W","W","W","W","
W","W","W","W","W","W","W","W","W","W","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","O"]
lvl4spawnsx = [355, 210, 540, 780]
lvl4spawnsy = [500, 260, 160, 480]
lvl4noofenemies = 4
lvl4crange = [480,640,0,80]
keyp4 = [280, 160]
lvl4playerspawnx = 1280
lvl4playerspawny = 360
lvl5 =
["O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","O","O","O","O","O","O","O","O","O",
"O","O","O","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","
W","W","W","W","W","W","W","W","W","W","W","W","W","W",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","W",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","W",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","W","W","W","W","
W","F","F","F","F","F","F","F","F","F","F","F","F","W",
"O","O","O","W","F","F","W","W","W","F","F","F","W","W","W","W","W","W","
W","W","W","F","F","F","W","W","W","W","W","F","F","W",
"O","O","O","W","F","F","W","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","F","F","W",
"W","W","W","W","F","F","W","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","F","F","W",
"C","C","F","F","F","F","F","F","F","F","W","W","W","W","W","W","W","W","
W","W","W","W","W","F","F","F","F","F","F","F","F","W",
"C","C","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","W",
"W","W","W","W","F","F","W","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","W","F","F","W",
"O","O","O","W","F","F","W","F","F","F","F","F","F","F","F","F","W","F","
F","F","F","F","F","F","F","F","F","F","W","F","F","W",
"O","O","O","W","F","F","W","W","F","F","F","F","F","F","F","F","W","W","
F","F","F","F","F","F","F","F","F","W","W","F","F","W",
"O","O","O","W","F","F","W","W","W","F","F","F","F","F","F","F","W","W","
W","W","F","F","F","F","F","W","W","W","W","F","F","W",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","W",
"O","O","O","W","F","F","F","F","F","F","F","F","F","F","F","F","F","F","
F","F","F","F","F","F","F","F","F","F","F","F","F","W",
"O","O","O","W","W","W","W","W","W","W","W","W","F","F","F","F","W","W","
W","W","W","W","W","W","W","W","W","W","W","W","W","W",
"O","O","O","O","O","O","O","O","O","O","O","W","F","F","F","F","W","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","O"]
lvl5spawnsx = [660, 1190, 190, 190, 700, 670]
lvl5spawnsy = [120, 270, 250, 500, 600, 400]
lvl5noofenemies = 6
lvl5crange = [0,80,320,400]
keyp5 = [760, 160]
lvl5playerspawnx = 560
lvl5playerspawny = 720
boss =
["W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W",
"W","W","W","W","W","W","W","W","W","W","W","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","O",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","O",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","
O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","
W","W","W","W","W","W","W","W","W","W","W","W","W","W"]
bossspawnsx = []
bossspawnsy = []
bossnoofenemies = 0
bosscrange = [0,0,0,0]
bossplayerspawnx = 1280
bossplayerspawny = 360
border =
["W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W",
"W","W","W","W","W","W","W","W","W","W","W","W",
"W","C","C","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","C","C","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O","O","O","O","O","O","O","O","O","W",
"W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W","W"
,"W","W","W","W","W","W","W","W","W","W","W","W","W","W"]
bordspawnsx = []
bordspawnsy = []
bordnoofenemies = 0
bordcrange = [40,120,40,120]
bordplayerspawnx = 640
bordplayerspawny = 360
Download