[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