diff --git a/DepthProject-tolu-patrick b/DepthProject-tolu-patrick
new file mode 160000
index 0000000..bd53202
--- /dev/null
+++ b/DepthProject-tolu-patrick
@@ -0,0 +1 @@
+Subproject commit bd532022d70cd8d87f78f3580c358f5832060f6d
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..847318e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,141 @@
+# PyRacer:
+
+
+## Running The Game:
+PyRacer was developed with Python 3 and requires Python 3.4 or higher installed on your machine to play. In addition to this, cross-platform support is available but on Windows all the necessary libraries must be visible to the directory where the game files are kept.
+
+- In order to run PyRacer you must have PyGame, as this is the library much of the code is based on.
+
+- To install PyGame run the following code that best fits your situation in your terminal:
+
+ - Globally on your OS- `python3 -m pip install -U pygame`
+ - For a singular user- `python3 -m pip install -U pygame --user`
+
+- Some other libraries that may need to be installed are `numpy`, `pathlib`, and `contextlib`.
+
+PyRacer was developed in Ubuntu and is designed to work on Linux and Mac OS, but can also run on Windows with the proper file specifications.
+
+Once PyGame is installed open the directory in which the game files are saved and run `python3 scripts/main.py` in the terminal of that directory.
+
+## Gameplay Overview:
+Here, we have a 2.5D car racing game, in which you have to drive your selected car through obstacles, and on the road in order to complete the track.
+
+The goal of this game is to beat all 6 stages to unlock the last car. Each stage of this racing game is a track, that a car that completes 3 rounds through a selected track chosen in the menu.
+
+For car choices, we have an option of the fastest car, but low durability, a medium speed car with medium durability, and a low speed car with high durability, and your objective is to complete the stage without your car getting destroyed.
+
+There are laser beams coming overhead which enact damage to your car if it comes into contact with the beams. We have turbochargers as icons, which signify the number of stages you have completed. A golden turbocharger means you have completed one of the six stages.
+
+In order to reset number of turbochargers and the saved game data, simply press "r" in the menu.
+In the folder, if you navigate to `data/gamedata/gamedata.txt`, you will see any collection of seven numbers that are either 0's or 1's, which represent the completion values of each course completed. Changing them all to 0, sets all courses as uncompleted.
+
+You also have different background music for each of the stages, as well as a HUD and stage completion indicator, giving you all the information you need to finish the stage.
+To toggle the music on or off at any time, press "m".
+
+To open the web-page for PyRacer's information (it will be a link to this page on GitHub), press "i".
+
+In summation, this game is a modern adaptation of the classic SEGA game 'Outrun', with a remix to the original game play where the you can choose between three different cars and race along 6 different courses. The primary objective of this game is to complete all six courses successfully, and if this goal is achieved you will be rewarded with the special fourth car. Below are the basic descriptions of each car.
+
+*P.S. If you have unlocked the special fourth car press "l" at any time for a surprise!*
+
+### The Sprinter:
+
+
+This car is the fastest but least durable.
+
+### The Sport-Utility:
+
+
+This car is somewhere in between in terms of speed and durability.
+
+### The Big Rig:
+
+
+This car is the slowest but most durable.
+
+### The ?????? ??????:
+
+
+???
+
+
+## Under The Hood:
+This game utilizes the PyGame library to accomplish several tasks; from rendering images and playing music to displaying the head-up display and handling user input. Used in accordance with object-oriented programming this game is brought to life.
+
+
+### Classes & Methods:
+There are five files and four classes that help create the game, with some handling the objects in the game and others handling the data the game uses.
+
+---
+#### The `Player` Class & File:
+This `Player` class is used to display and update the player object (the car that the user controls).
+
+The `__init__()` function defines the source images for each car as well as some positioning and collision defaults.
+The `move()` makes the car move sideways.
+
+---
+#### The `Road` Class & File:
+This `Road` class is used to display and update the road object (the simulation of forward movement in the game).
+
+The `__init__()` function defines the aesthetics of each road that can be rendered and pulls the appropriate track data to read from.
+The `update()` function defines how each slice of the road/ground/sidelines will render depending on self.tilt, and the index of the respective list.
+The `readtrack()` function reads through the track data file and dictates how the overall course will react on each frame switch.
+
+---
+#### The `Laserbeam` Class & File:
+This `Laserbeam` class is used to display and update the laserbeam object (the obstacles that the user must avoid).
+
+The `__init__()` function defines the source image for the lasers and the possibilities of how the lasers will act, as well as some positioning and collision defaults.
+The `update()` function defines how the lasers will act depending on a random given number, and controls the speeds at which they move.
+
+---
+#### The `TrackGenerator` Class & File:
+The `TrackGenerator` class is used to generate a list of numbers that will correlate to how the in-game road will operate.
+Each number from 1 through 5 will cause the road to act differently:
+1 - Road holds to the left.
+2 - Road turns to the left.
+3 - Road holds to the center.
+4 - Road turns to the right.
+5 - Road holds to the right.
+
+The `__init__()` function defines the possible pieces of the track that can be put together.
+The `generate()` function uses the predefined pieces for a track written with strings to make a complete track.
+
+---
+#### The `KeyInput` Class & File:
+The `KeyInput` class is used to handle user input from the keyboard.
+
+The `read()` handles the game's reactions to the user's input.
+
+---
+#### The `GlobalVariables` Class & File:
+The `GlobalVariables` handles the all the global variables in the game.
+
+The `__init__()` function initializes every single global variable that all the other objects can access during runtime.
+
+##### In addition to these classes there is the fundamental 'main' function.
+
+#### The `main` Function:
+The `main()` function is used to run the game, manage which objects render, and play music, along with saving data and pulling data to be read by the objects that need it.
+First all the objects are initialized and then in the following while loop all of the interactions (from user input, to collision detection, to the head-up display and UI) are handled.
+##### The while loop:
+Although dispersed, the while loop in this function can be split into three overall concepts: Graphics Rendering, User Input, and Collision Detection.
+Two of the three concepts are presented in the `ingame == False` statement while all three are presented in the `ingame == True` statement.
+
+
+## Usage Rights:
+**Source Image Citations:**
+Car Sprites:
+Chase H.Q. II/Super H.Q. (Sega Mega Drive/Genesis); Ripped by Yawackhary; Developed by I.T.L.; Taito Corporation 1992.
+
+Lotus Turbo Challenge (Sega Mega Drive/Genesis); Ripped by Yawackhary; Developed by Magnetic Fields, Gremlin Graphics Software; Electronic Arts 1992.
+
+Music Sources:
+Lil Uzi Vert; "Lotus"; Eternal Atake (Deluxe); WMG (on behalf of Atlantic Records); Warner Chappell, Kobalt Music Publishing; Instrumental Remake By OBITX.
+
+Vivid Sound × Hybrid Colors: Sonic Colors Original Soundtrack; Wave Master.
+
+*All other source files were either royalty-free or made in-house.*
+
+# System Diagram:
+
diff --git a/System Diagram.png b/System Diagram.png
new file mode 100644
index 0000000..84e366f
Binary files /dev/null and b/System Diagram.png differ
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..2f7efbe
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-minimal
\ No newline at end of file
diff --git a/data/gamedata/gamedata.txt b/data/gamedata/gamedata.txt
new file mode 100644
index 0000000..7153628
--- /dev/null
+++ b/data/gamedata/gamedata.txt
@@ -0,0 +1 @@
+1111111
\ No newline at end of file
diff --git a/data/tracks/track1.txt b/data/tracks/track1.txt
new file mode 100644
index 0000000..debee7c
--- /dev/null
+++ b/data/tracks/track1.txt
@@ -0,0 +1 @@
+33333333333333333333333333333333333333333333333333444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222333333333322222222222222222222222222222222111111111111111111111111111111114444444444444444444444444444444433333333333333333333333332222222222222222222222222222222211111111111111111111111111111111444444444444444444444444444444443333333333333333333333333333334444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222223333333333333333333333333222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444333333333333333333333333333333
diff --git a/data/tracks/track2.txt b/data/tracks/track2.txt
new file mode 100644
index 0000000..f9e3480
--- /dev/null
+++ b/data/tracks/track2.txt
@@ -0,0 +1 @@
+33333333334444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111444444444444444444444444444444444444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222223333333333333333333322222222222222222222222222222222111111111111111111111111111111114444444444444444444444444444444433333333333333333333333333333344444444444444444444444444444444555555555555555555555555555555552222222222222222222222222222222233333333333333333333333333333333333333332222222222222222222222222222222211111111111111111111111111111111444444444444444444444444444444444444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111444444444444444444444444444444444444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111444444444444444444444444444444443333333333333333333333333333333333333333
diff --git a/data/tracks/track3.txt b/data/tracks/track3.txt
new file mode 100644
index 0000000..2f19b01
--- /dev/null
+++ b/data/tracks/track3.txt
@@ -0,0 +1 @@
+33333333333333333333333333333322222222222222222222222222222222111111111111111111111111111111114444444444444444444444444444444433333333333333333333333333333344444444444444444444444444444444555555555555555555555555555555552222222222222222222222222222222233333333332222222222222222222222222222222211111111111111111111111111111111444444444444444444444444444444444444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222223333333333222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222333333333333333333333333333333444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222333333333333333222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444
diff --git a/data/tracks/track4.txt b/data/tracks/track4.txt
new file mode 100644
index 0000000..ae8c655
--- /dev/null
+++ b/data/tracks/track4.txt
@@ -0,0 +1 @@
+3333333333444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444333333333333333333334444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222223333333333222222222222222211111111111111114444444444444444444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222333332222222222222222111111111111111144444444444444444444444444444444555555555555555522222222222222223333333333333333333333333333334444444444444444555555555555555522222222222222223333333333333333333333333222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444333333333333333333333333333333333333333333333
diff --git a/data/tracks/track5.txt b/data/tracks/track5.txt
new file mode 100644
index 0000000..8fa3ed4
--- /dev/null
+++ b/data/tracks/track5.txt
@@ -0,0 +1 @@
+44444444444444445555555555555555222222222222222233333333333333333333444444444444444455555555555555552222222222222222222222222222222211111111111111114444444444444444333333333333333333332222222222222222111111111111111144444444444444443333333333222222222222222211111111111111114444444444444444333333333333333444444444444444455555555555555552222222222222222333333333333333333333333333333333333333344444444444444445555555555555555222222222222222233333333333333333333333333333333333222222222222222211111111111111114444444444444444444444444444444455555555555555552222222222222222333333333333333333333333333333333333333333333222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444
diff --git a/data/tracks/track6.txt b/data/tracks/track6.txt
new file mode 100644
index 0000000..4ce3b5c
--- /dev/null
+++ b/data/tracks/track6.txt
@@ -0,0 +1 @@
+44444444444444444444444444444444555555555555555555555555555555552222222222222222222222222222222222222222222222222222222222222222111111111111111111111111111111114444444444444444444444444444444433333333334444444455555555222222222222222211111111444444444444444455555555222222222222222211111111444444444444444455555555222222222222222211111111444444443333322222222222222221111111111111111444444444444444433333222222222222222211111111111111114444444444444444444444445555555522222222222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444444444444444444455555555555555552222222222222222333333333333333444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222333332222222211111111444444444444444455555555222222222222222211111111444444444444444455555555222222222222222211111111444444443333333333333332222222222222222111111111111111144444444444444444444444444444444444444444444444455555555555555555555555555555555222222222222222222222222222222223333333333444444444444444455555555555555552222222222222222222222221111111144444444444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222222222222222222211111111111111114444444444444444333333333333333333333333333333
\ No newline at end of file
diff --git a/fonts/Retron2000.ttf b/fonts/Retron2000.ttf
new file mode 100644
index 0000000..f30c7e1
Binary files /dev/null and b/fonts/Retron2000.ttf differ
diff --git a/fonts/SPEERG__.TTF b/fonts/SPEERG__.TTF
new file mode 100644
index 0000000..87ddacd
Binary files /dev/null and b/fonts/SPEERG__.TTF differ
diff --git a/gifs/coursedrive.gif b/gifs/coursedrive.gif
new file mode 100644
index 0000000..acee33b
Binary files /dev/null and b/gifs/coursedrive.gif differ
diff --git a/gifs/coursefinish.gif b/gifs/coursefinish.gif
new file mode 100644
index 0000000..76f3fc6
Binary files /dev/null and b/gifs/coursefinish.gif differ
diff --git a/gifs/intro.gif b/gifs/intro.gif
new file mode 100644
index 0000000..8dd4070
Binary files /dev/null and b/gifs/intro.gif differ
diff --git a/gifs/trackselection.gif b/gifs/trackselection.gif
new file mode 100644
index 0000000..74305ff
Binary files /dev/null and b/gifs/trackselection.gif differ
diff --git a/images/backgrounds/bg1.png b/images/backgrounds/bg1.png
new file mode 100644
index 0000000..6e8f5bb
Binary files /dev/null and b/images/backgrounds/bg1.png differ
diff --git a/images/backgrounds/bg2.png b/images/backgrounds/bg2.png
new file mode 100644
index 0000000..8f2cf28
Binary files /dev/null and b/images/backgrounds/bg2.png differ
diff --git a/images/backgrounds/bg3.png b/images/backgrounds/bg3.png
new file mode 100644
index 0000000..1e53d7e
Binary files /dev/null and b/images/backgrounds/bg3.png differ
diff --git a/images/backgrounds/bg4.png b/images/backgrounds/bg4.png
new file mode 100644
index 0000000..1f04a60
Binary files /dev/null and b/images/backgrounds/bg4.png differ
diff --git a/images/backgrounds/bg5.png b/images/backgrounds/bg5.png
new file mode 100644
index 0000000..63d41e9
Binary files /dev/null and b/images/backgrounds/bg5.png differ
diff --git a/images/backgrounds/bg6.png b/images/backgrounds/bg6.png
new file mode 100644
index 0000000..aa0d09e
Binary files /dev/null and b/images/backgrounds/bg6.png differ
diff --git a/images/menuframes/frame1.png b/images/menuframes/frame1.png
new file mode 100644
index 0000000..fc0bacc
Binary files /dev/null and b/images/menuframes/frame1.png differ
diff --git a/images/menuframes/frame2.png b/images/menuframes/frame2.png
new file mode 100644
index 0000000..0175a56
Binary files /dev/null and b/images/menuframes/frame2.png differ
diff --git a/images/menuframes/frame3.png b/images/menuframes/frame3.png
new file mode 100644
index 0000000..fddb4cb
Binary files /dev/null and b/images/menuframes/frame3.png differ
diff --git a/images/menuframes/frame4.png b/images/menuframes/frame4.png
new file mode 100644
index 0000000..437aa47
Binary files /dev/null and b/images/menuframes/frame4.png differ
diff --git a/images/menuframes/frame5.png b/images/menuframes/frame5.png
new file mode 100644
index 0000000..b1be443
Binary files /dev/null and b/images/menuframes/frame5.png differ
diff --git a/images/menuframes/frame6.png b/images/menuframes/frame6.png
new file mode 100644
index 0000000..dcf3b12
Binary files /dev/null and b/images/menuframes/frame6.png differ
diff --git a/images/objects/finishline.png b/images/objects/finishline.png
new file mode 100644
index 0000000..92e1b0f
Binary files /dev/null and b/images/objects/finishline.png differ
diff --git a/images/objects/goldenturbo.png b/images/objects/goldenturbo.png
new file mode 100644
index 0000000..1446476
Binary files /dev/null and b/images/objects/goldenturbo.png differ
diff --git a/images/objects/laserbeam.png b/images/objects/laserbeam.png
new file mode 100644
index 0000000..105b00c
Binary files /dev/null and b/images/objects/laserbeam.png differ
diff --git a/images/objects/startline.png b/images/objects/startline.png
new file mode 100644
index 0000000..447b6e8
Binary files /dev/null and b/images/objects/startline.png differ
diff --git a/images/player/front1.png b/images/player/front1.png
new file mode 100644
index 0000000..923c313
Binary files /dev/null and b/images/player/front1.png differ
diff --git a/images/player/front2.png b/images/player/front2.png
new file mode 100644
index 0000000..25d40ab
Binary files /dev/null and b/images/player/front2.png differ
diff --git a/images/player/front3.png b/images/player/front3.png
new file mode 100644
index 0000000..7b0770e
Binary files /dev/null and b/images/player/front3.png differ
diff --git a/images/player/front4.png b/images/player/front4.png
new file mode 100644
index 0000000..e838870
Binary files /dev/null and b/images/player/front4.png differ
diff --git a/images/player/left1.png b/images/player/left1.png
new file mode 100644
index 0000000..bc4e282
Binary files /dev/null and b/images/player/left1.png differ
diff --git a/images/player/left2.png b/images/player/left2.png
new file mode 100644
index 0000000..2fb2d4e
Binary files /dev/null and b/images/player/left2.png differ
diff --git a/images/player/left3.png b/images/player/left3.png
new file mode 100644
index 0000000..601184e
Binary files /dev/null and b/images/player/left3.png differ
diff --git a/images/player/left4.png b/images/player/left4.png
new file mode 100644
index 0000000..7863900
Binary files /dev/null and b/images/player/left4.png differ
diff --git a/images/player/right1.png b/images/player/right1.png
new file mode 100644
index 0000000..6bb35c9
Binary files /dev/null and b/images/player/right1.png differ
diff --git a/images/player/right2.png b/images/player/right2.png
new file mode 100644
index 0000000..400c247
Binary files /dev/null and b/images/player/right2.png differ
diff --git a/images/player/right3.png b/images/player/right3.png
new file mode 100644
index 0000000..6bb3e51
Binary files /dev/null and b/images/player/right3.png differ
diff --git a/images/player/right4.png b/images/player/right4.png
new file mode 100644
index 0000000..b891fc5
Binary files /dev/null and b/images/player/right4.png differ
diff --git a/images/player/side1.png b/images/player/side1.png
new file mode 100644
index 0000000..b8e6428
Binary files /dev/null and b/images/player/side1.png differ
diff --git a/images/player/side2.png b/images/player/side2.png
new file mode 100644
index 0000000..9854d4f
Binary files /dev/null and b/images/player/side2.png differ
diff --git a/images/player/side3.png b/images/player/side3.png
new file mode 100644
index 0000000..1da29a4
Binary files /dev/null and b/images/player/side3.png differ
diff --git a/images/player/side4.png b/images/player/side4.png
new file mode 100644
index 0000000..de98229
Binary files /dev/null and b/images/player/side4.png differ
diff --git a/images/player/silhouette.png b/images/player/silhouette.png
new file mode 100644
index 0000000..4767a62
Binary files /dev/null and b/images/player/silhouette.png differ
diff --git a/images/player/straight1.png b/images/player/straight1.png
new file mode 100644
index 0000000..efe4a76
Binary files /dev/null and b/images/player/straight1.png differ
diff --git a/images/player/straight2.png b/images/player/straight2.png
new file mode 100644
index 0000000..cc3cf63
Binary files /dev/null and b/images/player/straight2.png differ
diff --git a/images/player/straight3.png b/images/player/straight3.png
new file mode 100644
index 0000000..ccc0ee5
Binary files /dev/null and b/images/player/straight3.png differ
diff --git a/images/player/straight4.png b/images/player/straight4.png
new file mode 100644
index 0000000..6c9a7a2
Binary files /dev/null and b/images/player/straight4.png differ
diff --git a/images/screenshots/gameplay.png b/images/screenshots/gameplay.png
new file mode 100644
index 0000000..93d1c12
Binary files /dev/null and b/images/screenshots/gameplay.png differ
diff --git a/images/screenshots/mainmenu.png b/images/screenshots/mainmenu.png
new file mode 100644
index 0000000..1eb62ac
Binary files /dev/null and b/images/screenshots/mainmenu.png differ
diff --git a/music/music0.mp3 b/music/music0.mp3
new file mode 100644
index 0000000..1eac315
Binary files /dev/null and b/music/music0.mp3 differ
diff --git a/music/music1.mp3 b/music/music1.mp3
new file mode 100644
index 0000000..1c3cb56
Binary files /dev/null and b/music/music1.mp3 differ
diff --git a/music/music2.mp3 b/music/music2.mp3
new file mode 100644
index 0000000..4207838
Binary files /dev/null and b/music/music2.mp3 differ
diff --git a/music/music3.mp3 b/music/music3.mp3
new file mode 100644
index 0000000..44d3490
Binary files /dev/null and b/music/music3.mp3 differ
diff --git a/music/music4.mp3 b/music/music4.mp3
new file mode 100644
index 0000000..f52ced1
Binary files /dev/null and b/music/music4.mp3 differ
diff --git a/music/music5.mp3 b/music/music5.mp3
new file mode 100644
index 0000000..096d794
Binary files /dev/null and b/music/music5.mp3 differ
diff --git a/music/music6.mp3 b/music/music6.mp3
new file mode 100644
index 0000000..f468de0
Binary files /dev/null and b/music/music6.mp3 differ
diff --git a/music/musicc.mp3 b/music/musicc.mp3
new file mode 100644
index 0000000..648463b
Binary files /dev/null and b/music/musicc.mp3 differ
diff --git a/music/musicf.mp3 b/music/musicf.mp3
new file mode 100644
index 0000000..9f47931
Binary files /dev/null and b/music/musicf.mp3 differ
diff --git a/music/musicl.mp3 b/music/musicl.mp3
new file mode 100644
index 0000000..60817fd
Binary files /dev/null and b/music/musicl.mp3 differ
diff --git a/scripts/__pycache__/globalvariables.cpython-37.pyc b/scripts/__pycache__/globalvariables.cpython-37.pyc
new file mode 100644
index 0000000..48da8f6
Binary files /dev/null and b/scripts/__pycache__/globalvariables.cpython-37.pyc differ
diff --git a/scripts/__pycache__/keyinput.cpython-37.pyc b/scripts/__pycache__/keyinput.cpython-37.pyc
new file mode 100644
index 0000000..04d81e7
Binary files /dev/null and b/scripts/__pycache__/keyinput.cpython-37.pyc differ
diff --git a/scripts/__pycache__/laserbeam.cpython-37.pyc b/scripts/__pycache__/laserbeam.cpython-37.pyc
new file mode 100644
index 0000000..44239f3
Binary files /dev/null and b/scripts/__pycache__/laserbeam.cpython-37.pyc differ
diff --git a/scripts/__pycache__/main.cpython-37.pyc b/scripts/__pycache__/main.cpython-37.pyc
new file mode 100644
index 0000000..44e6952
Binary files /dev/null and b/scripts/__pycache__/main.cpython-37.pyc differ
diff --git a/scripts/__pycache__/player.cpython-37.pyc b/scripts/__pycache__/player.cpython-37.pyc
new file mode 100644
index 0000000..11e6ef2
Binary files /dev/null and b/scripts/__pycache__/player.cpython-37.pyc differ
diff --git a/scripts/__pycache__/road.cpython-37.pyc b/scripts/__pycache__/road.cpython-37.pyc
new file mode 100644
index 0000000..f5d706b
Binary files /dev/null and b/scripts/__pycache__/road.cpython-37.pyc differ
diff --git a/scripts/__pycache__/trackgenerator.cpython-37.pyc b/scripts/__pycache__/trackgenerator.cpython-37.pyc
new file mode 100644
index 0000000..4ec81a5
Binary files /dev/null and b/scripts/__pycache__/trackgenerator.cpython-37.pyc differ
diff --git a/scripts/__pycache__/variables.cpython-37.pyc b/scripts/__pycache__/variables.cpython-37.pyc
new file mode 100644
index 0000000..1199289
Binary files /dev/null and b/scripts/__pycache__/variables.cpython-37.pyc differ
diff --git a/scripts/globalvariables.py b/scripts/globalvariables.py
new file mode 100644
index 0000000..c1ce8e7
--- /dev/null
+++ b/scripts/globalvariables.py
@@ -0,0 +1,60 @@
+#import pygame and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+
+class GlobalVariables():
+ """
+ The `GlobalVariables` handles the all the global variables in the game.
+ """
+ def __init__(self):
+ """
+ The `__init__()` function initializes every single global variable that all the other objects can access during runtime.
+ """
+ self.WIDTH = 800
+ self.HEIGHT = 500
+ self.DISPLAY = pygame.display.set_mode((self.WIDTH,self.HEIGHT),0,32)
+ #boolean to determine if the game is in driving mode and should render the player, road, and obstacles or not
+ self.INGAME = False
+ #set default menu frame: 1-start, 2-car select, 3-course select, 4-win frame, 5-lose frame
+ self.FRAME = 1
+ #set default course to render as defined in road.py
+ self.COURSENUM = 1
+ #set default car to render as defined in player.py
+ self.CARNUM = 1
+ #boolean to determine if the game is on the start screen
+ self.STARTSCREEN = True
+ #value to determine the condition of the user's car (if 0 then mission failed)
+ self.CONDITION = 100
+ #boolean to toggle music on or off
+ self.PLAYMUSIC = True
+ #load game data file
+ datafile = Path('data/gamedata/gamedata.txt')
+ with open(datafile) as file:
+ self.GAMEDATA = file.readline()
+ file.close()
+ #boolean to toggle music on or off
+ playmusic = True
+ #render background image
+ menufilepath = Path('images/menuframes/frame1')
+ menufile = str(menufilepath)+'.png'
+ self.WINDOW = pygame.transform.scale(pygame.image.load(menufile), (self.WIDTH,self.HEIGHT))
+ #initialize dummy car scalings and vertical adjustments
+ self.CARXSCALE = 0
+ self.CARYSCALE = 0
+ self.CARYADJUST = 0
+ #initialize dummy road object
+ self.STREET = None
+ #initialize dummy player object
+ self.RACER = None
+ #initialize dummy laser object
+ self.LASERS = None
+ self.RACERDX = 1
+ self.STREETSPEED = 0
+ self.STREETSP = 0
+
+#define the global object with all the varibles defined inside
+global gvar
+gvar = GlobalVariables()
diff --git a/scripts/keyinput.py b/scripts/keyinput.py
new file mode 100644
index 0000000..c2d1d73
--- /dev/null
+++ b/scripts/keyinput.py
@@ -0,0 +1,197 @@
+#import pygame and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+import webbrowser
+from globalvariables import GlobalVariables, gvar
+from player import Player
+#from trackgenerator import TrackGenerator
+from road import Road
+from laserbeam import Laserbeam
+
+#initialize the source for global variables from import
+global gvar
+
+class KeyInput:
+ """
+ The `KeyInput` class is used to handle user input from the keyboard.
+ """
+ def read(self):
+ """
+ The `read()` handles the game's reactions to the user's input.
+ """
+ if gvar.INGAME == False:
+ #user input
+ for event in pygame.event.get():
+ if event.type==QUIT:
+ pygame.quit()
+ sys.exit()
+ if event.type == pygame.KEYDOWN:
+ #if any key is pressed on the start screen proceed to the car select screen
+ if gvar.FRAME == 1 and gvar.STARTSCREEN == True:
+ if event.key != (pygame.K_LSHIFT or pygame.K_RSHIFT):
+ gvar.FRAME = 2
+ #move left to change which car/course that will be selected
+ if event.key == pygame.K_LEFT:
+ if gvar.FRAME == 2:
+ if gvar.CARNUM > 1:
+ gvar.CARNUM -= 1
+ elif gvar.FRAME == 3:
+ if gvar.COURSENUM > 1:
+ gvar.COURSENUM -= 1
+ #move right to change which car/course that will be selected (within the bounds of what has been unlocked)
+ if event.key == pygame.K_RIGHT:
+ if gvar.FRAME == 2:
+ if gvar.GAMEDATA.count('1') < 6:
+ if gvar.CARNUM < 3:
+ gvar.CARNUM += 1
+ elif gvar.GAMEDATA.count('1') >= 6:
+ if gvar.CARNUM < 4:
+ gvar.CARNUM += 1
+ elif gvar.FRAME == 3:
+ if gvar.COURSENUM < (gvar.GAMEDATA.count('1')+1) and gvar.COURSENUM < 6:
+ gvar.COURSENUM += 1
+ #press enter to make your selection
+ if event.key == pygame.K_RETURN and gvar.STARTSCREEN == False:
+ #select car
+ if gvar.FRAME == 2:
+ gvar.FRAME = 3
+ #load the appropriate course background, create the game objects, reset car condition, start the mucis, and well, start the game!
+ elif gvar.FRAME == 3:
+ bgfilepath = Path('images/backgrounds/bg')
+ bgfile = str(bgfilepath)+str(gvar.COURSENUM)+'.png'
+ gvar.WINDOW = pygame.transform.scale(pygame.image.load(bgfile), (1000,302))
+ gvar.STREET = Road(gvar.COURSENUM)
+ gvar.RACER = Player(gvar.CARNUM, gvar.CARXSCALE/2, gvar.CARYSCALE/2, gvar.WIDTH/2, (7*gvar.HEIGHT/8-20-gvar.CARYADJUST/2))
+ gvar.LASERS = Laserbeam(gvar.COURSENUM)
+ gvar.CONDITION = 100
+ pygame.mixer.music.stop()
+ musicfilepath = Path('music/music')
+ musicfile = str(musicfilepath)+str(gvar.COURSENUM)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ if gvar.PLAYMUSIC == True:
+ pygame.mixer.music.play(-1)
+ gvar.INGAME = True
+ #go back to car select frame and reset music to default if no new car has been unlocked
+ elif gvar.FRAME == 4:
+ #car unlocked scenario
+ if gvar.GAMEDATA.count('1') == 6:
+ gvar.GAMEDATA = '1111111'
+ datafile = Path('data/gamedata/gamedata.txt')
+ file=open(datafile,'w+')
+ file.write(gvar.GAMEDATA)
+ file.close()
+ #new car unlocked frame
+ gvar.FRAME = 6
+ #typical scenario
+ else:
+ pygame.mixer.music.stop()
+ musicfilepath = Path('music/music0')
+ musicfile = str(musicfilepath)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ pygame.mixer.music.play(-1)
+ gvar.FRAME = 2
+ #go back to car select frame and reset music to default
+ elif gvar.FRAME == 5 or gvar.FRAME == 6:
+ pygame.mixer.music.stop()
+ musicfilepath = Path('music/music0')
+ musicfile = str(musicfilepath)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ pygame.mixer.music.play(-1)
+ gvar.FRAME = 2
+ #go back to the previous menu frame
+ if event.key == (pygame.K_LSHIFT or pygame.K_RSHIFT):
+ if gvar.FRAME == 2:
+ gvar.FRAME = 1
+ gvar.STARTSCREEN = True
+ elif gvar.FRAME == 3:
+ gvar.FRAME = 2
+ #reset game data
+ if event.key == pygame.K_r:
+ gvar.CARNUM = 1
+ gvar.COURSENUM = 1
+ datafile = Path('data/gamedata/gamedata.txt')
+ file=open(datafile,'w+')
+ gvar.GAMEDATA = '0000000'
+ file.write(gvar.GAMEDATA)
+ file.close()
+ #toggle music on or off
+ if event.key == pygame.K_m:
+ if gvar.PLAYMUSIC == True:
+ pygame.mixer.music.stop()
+ gvar.PLAYMUSIC = False
+ else:
+ pygame.mixer.music.play(-1)
+ gvar.PLAYMUSIC = True
+ #open information file
+ if event.key == pygame.K_i:
+ webbrowser.open('https://github.com/sd2020spring/DepthProject-tolu-patrick/blob/master/README.md')
+ #play easter egg music
+ if event.key == pygame.K_l:
+ if gvar.GAMEDATA.count('1') >= 6:
+ pygame.mixer.music.stop()
+ musicfilepath = Path('music/musicl')
+ musicfile = str(musicfilepath)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ pygame.mixer.music.play(1)
+ else:
+ for event in pygame.event.get():
+ if event.type==QUIT:
+ pygame.quit()
+ sys.exit()
+ if event.type == pygame.KEYDOWN:
+ #player moves left when the left key is pressed and turning left image is set
+ if event.key == pygame.K_LEFT:
+ if gvar.CARNUM > 4:
+ gvar.RACER.dx = -9*(.001+gvar.STREET.speed)/gvar.CARNUM
+ else:
+ gvar.RACER.dx = -10*(.001+gvar.STREET.speed)/.75
+ gvar.RACER.image = gvar.RACER.imgleft
+ #player moves right when the right key is pressed and turning right image is set
+ if event.key == pygame.K_RIGHT:
+ if gvar.CARNUM > 4:
+ gvar.RACER.dx = 9*(.001+gvar.STREET.speed)/gvar.CARNUM
+ else:
+ gvar.RACER.dx = 10*(.001+gvar.STREET.speed)/.75
+ gvar.RACER.image = gvar.RACER.imgright
+ #player accelerates (the road progresses forward at a continuously increasing rate until max speed) when the up key is pressed
+ if event.key == pygame.K_UP:
+ if gvar.CARNUM != 4:
+ gvar.STREET.sp = .0003/gvar.CARNUM
+ elif gvar.CARNUM == 4:
+ gvar.STREET.sp = .0004
+ #player decelerates (the road progresses forward at a continuously decreasing rate until zero) when the down key is pressed
+ if event.key == pygame.K_DOWN:
+ gvar.STREET.sp = -.00035/gvar.CARNUM
+ #toggle music on or off
+ if event.key == pygame.K_m:
+ if gvar.PLAYMUSIC == True:
+ pygame.mixer.music.stop()
+ gvar.PLAYMUSIC = False
+ else:
+ pygame.mixer.music.play(-1)
+ gvar.PLAYMUSIC = True
+ #play easter egg music
+ if event.key == pygame.K_l:
+ if gvar.GAMEDATA.count('1') >= 6:
+ pygame.mixer.music.stop()
+ pygame.mixer.music.load('music/musicl.mp3')
+ pygame.mixer.music.play(1)
+
+ if event.type == pygame.KEYUP:
+ #player stops moving left
+ if event.key == pygame.K_LEFT:
+ gvar.RACER.dx = 0
+ gvar.RACER.image = gvar.RACER.img
+ #player stops moving right
+ if event.key == pygame.K_RIGHT:
+ gvar.RACER.dx = 0
+ gvar.RACER.image = gvar.RACER.img
+ #player stops accelerating
+ if event.key == pygame.K_UP:
+ gvar.STREET.sp = -.0001
+ #player stops decelerating as quickly
+ if event.key == pygame.K_DOWN:
+ gvar.STREET.sp = -.0001
diff --git a/scripts/laserbeam.py b/scripts/laserbeam.py
new file mode 100644
index 0000000..a2ac733
--- /dev/null
+++ b/scripts/laserbeam.py
@@ -0,0 +1,108 @@
+#import pygame and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+from globalvariables import GlobalVariables, gvar
+import time
+import random
+
+#initialize the source for global variables from import
+global gvar
+#set default display dimensions
+WIDTH = gvar.WIDTH
+HEIGHT = gvar.HEIGHT
+
+laserfilepath = Path('images/objects/laserbeam')
+
+class Laserbeam:
+ """
+ This `Laserbeam` class is used to display and update the laserbeam object (the obstacles that the user must avoid).
+ """
+ def __init__(self, track = 1, img = pygame.transform.scale(pygame.image.load(str(laserfilepath)+'.png'), (85, 500))):
+ """
+ The `__init__()` function defines the source image for the lasers and the possibilities of how the
+ lasers will act, as well as some positioning and collision defaults.
+ """
+ #this sets the initial time to determine when to update the lasers
+ self.starttime = time.clock()
+ #this sets the given time to compare against the initial time
+ self.currenttime = time.clock()
+ #each laser's width
+ self.width = 85
+ #each laser's height
+ self.height = 500
+ #this is the constant at which the lasers will fall
+ self.fallrate = 2
+ #image to be displayed while running
+ self.image = img
+ #this integer corresponds to how the lasers will render: 1-left only, 2-middle only, 3-right only, 4-left and middle, 5-left and right, 6-middle and right
+ self.lasercombo = 0
+ #this boolean checks to see if a laser has hit the groud, if so all the lasers reset
+ self.touchdown = True
+ #defining each laser's x position
+ self.x1 = WIDTH/4-(self.width/2)-45
+ self.x2 = 2*WIDTH/4-(self.width/2)
+ self.x3 = 3*WIDTH/4-(self.width/2)+45
+ #defining each laser's y position
+ self.y1 = -self.height
+ self.y2 = -self.height
+ self.y3 = -self.height
+ #depending on the chosen track the possible combinations will differ with graduating difficulty
+ if track == 1 or track == 2:
+ self.mincombos = 1
+ self.maxcombos = 3
+ elif track == 3 or track == 4:
+ self.mincombos = 1
+ self.maxcombos = 6
+ elif track == 5 or track == 6:
+ self.mincombos = 4
+ self.maxcombos = 6
+
+ def update(self):
+ """
+ The `update()` function defines how the lasers will act depending on a random given number, and controls the speeds at which they move.
+ """
+ #update the current time
+ self.currenttime = time.clock()
+ #if the differences in the times surpasses the framerate threshold the lasers will update accordingly
+ if (self.currenttime-self.starttime) > (.01-(self.fallrate/1000)):
+ #if self.touchdown is true the lasers will reset and will move faster next time
+ if self.touchdown == True:
+ self.lasercombo = random.randint(self.mincombos, self.maxcombos)
+ self.y1 = -self.height
+ self.y2 = -self.height
+ self.y3 = -self.height
+ self.fallrate *= 1.005
+ self.touchdown = False
+ #if self.touchdown is false the lasers will descend accordingly
+ else:
+ if (self.y1 >= -20) or (self.y2 >= -20) or (self.y3 >= -20):
+ self.touchdown = True
+ if self.lasercombo == 1:
+ self.y1 += self.fallrate
+ self.y2 += 0
+ self.y3 += 0
+ elif self.lasercombo == 2:
+ self.y1 += 0
+ self.y2 += self.fallrate
+ self.y3 += 0
+ elif self.lasercombo == 3:
+ self.y1 += 0
+ self.y2 += 0
+ self.y3 += self.fallrate
+ elif self.lasercombo == 4:
+ self.y1 += self.fallrate
+ self.y2 += self.fallrate
+ self.y3 += 0
+ elif self.lasercombo == 5:
+ self.y1 += self.fallrate
+ self.y2 += 0
+ self.y3 += self.fallrate
+ elif self.lasercombo == 6:
+ self.y1 += 0
+ self.y2 += self.fallrate
+ self.y3 += self.fallrate
+ #update the start time to continue the chain
+ self.starttime = time.clock()
diff --git a/scripts/main.py b/scripts/main.py
new file mode 100644
index 0000000..5f1230d
--- /dev/null
+++ b/scripts/main.py
@@ -0,0 +1,273 @@
+#import pygame, local class files, and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+import webbrowser
+from globalvariables import GlobalVariables, gvar
+from keyinput import KeyInput
+from player import Player
+#from trackgenerator import TrackGenerator
+from road import Road
+from laserbeam import Laserbeam
+
+#initialize the source for global variables from import
+global gvar
+
+#set default display dimensions and create a display to render the game, alongside some colors for text display
+WIDTH = gvar.WIDTH
+HEIGHT = gvar.HEIGHT
+DISPLAY = gvar.DISPLAY
+WHITE = (255, 255, 255)
+BLACK = (0,0,0)
+DISPLAY.fill(BLACK)
+
+def main():
+ """
+ The `main()` function is used to run the game, manage which objects render, and play music,
+ along with saving data and pulling data to be read by the objects that need it.
+
+ First all the objects are initialized and then in the following while loop all of the interactions
+ (from user input, to collision detection, to the head-up display and UI) are handled.
+ """
+ #setup pygame window
+ pygame.init()
+ pygame.display.set_caption('PyRacer')
+ #trackgen = TrackGenerator() <- if you want to create new tracks uncomment this...
+ #trackgen.generate() <- ...and this
+ #define the different fonts that will be used
+ carfont = pygame.font.Font('fonts/Retron2000.ttf', 32)
+ coursefont = pygame.font.Font('fonts/Retron2000.ttf', 48)
+ ingamefontbig = pygame.font.Font('fonts/Retron2000.ttf', 32)
+ ingamefontsmall = pygame.font.Font('fonts/Retron2000.ttf', 16)
+ #load the default music and play continuously
+ musicfilepath = Path('music/music0')
+ musicfile = str(musicfilepath)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ pygame.mixer.music.play(-1)
+ #initialize keyboard input object
+ keyreader = KeyInput()
+
+ while True:
+ """
+ As mentioned before this loop handeles all of the interactions.
+
+ Although dispersed, this while loop can be split into three overall concepts:
+ Graphics Rendering, User Input, and Collision Detection.
+
+ Two of the three concepts are presented in the `ingame == False` statement while
+ all three are presented in the `ingame == True` statement.
+ """
+ #things happening during the out-of-game scenario
+ if gvar.INGAME == False:
+ #graphics rendering
+ #if the menu frame is past the first one, we are no longer on the start screen (this is used to prevent a bug when going back to the start screen)
+ if gvar.FRAME > 1:
+ gvar.STARTSCREEN = False
+ #depending on the current car value the image scaling, y-axis adujust for centering, and listed name will change
+ if gvar.CARNUM == 1:
+ gvar.CARXSCALE = 232
+ gvar.CARYSCALE = 128
+ gvar.CARYADJUST = 0
+ carname = 'Sprinter'
+ elif gvar.CARNUM == 2:
+ gvar.CARXSCALE = 232
+ gvar.CARYSCALE = 173
+ gvar.CARYADJUST = 45
+ carname = 'Sport-Utility'
+ elif gvar.CARNUM == 3:
+ gvar.CARXSCALE = 282
+ gvar.CARYSCALE = 246
+ gvar.CARYADJUST = 118
+ carname = 'Big Rig'
+ elif gvar.CARNUM == 4:
+ gvar.CARXSCALE = 244
+ gvar.CARYSCALE = 128
+ gvar.CARYADJUST = 0
+ carname = 'GOLDEN ESPRIT'
+ #depending on the current course value the listed name will change
+ if gvar.COURSENUM == 1:
+ coursename = 'PyRacer Speedway'
+ elif gvar.COURSENUM == 2:
+ coursename = 'Countryside Backroads'
+ elif gvar.COURSENUM == 3:
+ coursename = 'Tundra Expedition'
+ elif gvar.COURSENUM == 4:
+ coursename = 'Desert Caravan'
+ elif gvar.COURSENUM == 5:
+ coursename = 'City Outskirts'
+ elif gvar.COURSENUM == 6:
+ coursename = 'Stellar Highway'
+ #load the source image representing the out-of-game frame the menu is on
+ menufilepath = Path('images/menuframes/frame')
+ menufile = str(menufilepath)+str(gvar.FRAME)+'.png'
+ gvar.WINDOW = pygame.transform.scale(pygame.image.load(menufile), (800,500))
+ #create pygame surface to render car name text (black background with white text)
+ cartitle = carfont.render(carname, True, WHITE, BLACK)
+ #create pygame surface to render course name text (black background with white text)
+ coursetitle = coursefont.render(coursename, True, WHITE, BLACK)
+ #load the source image representing the car in the car select screen
+ carfrontfilepath = Path('images/player/front')
+ carfrontfile = str(carfrontfilepath)+str(gvar.CARNUM)+'.png'
+ carrender = pygame.transform.scale(pygame.image.load(carfrontfile), (gvar.CARXSCALE,gvar.CARYSCALE))
+ #load the source image representing a 'golden turbocharger', the talisman that is gained with each new completed course (acquire all six to unlock 4th car)
+ turbofilepath = Path('images/objects/goldenturbo')
+ turbofile = str(turbofilepath)+'.png'
+ turborender = pygame.transform.scale(pygame.image.load(turbofile), (54,50))
+ #display the out-of-game menu frame
+ DISPLAY.blit(gvar.WINDOW, (0,0))
+ #if on the car select screen render the respective car's image to give off feel of shuffling through garage, along with the number of golden turbos, and the car name
+ if gvar.FRAME == 2:
+ DISPLAY.blit(carrender, (WIDTH/2-gvar.CARXSCALE/2,HEIGHT/2-gvar.CARYADJUST))
+ #in the gamedata file the number of ones is the number of completed courses ('0000000'-no courses completed, '1111111'-all courses completed and special car unlocked)
+ if gvar.GAMEDATA.count('1') < 6:
+ for i in range(gvar.GAMEDATA.count('1')):
+ DISPLAY.blit(turborender, ((WIDTH/2+12.5)-((3-i)*75),385))
+ else:
+ for i in range(6):
+ DISPLAY.blit(turborender, ((WIDTH/2+12.5)-((3-i)*75),385))
+ cartitlebox = cartitle.get_rect()
+ cartitlebox.centerx = WIDTH/2
+ cartitlebox.centery = HEIGHT/2-gvar.CARYADJUST-40
+ DISPLAY.blit(cartitle, cartitlebox)
+ #if on the course select screen render the title of the course about to be selected
+ elif gvar.FRAME == 3:
+ coursetitlebox = coursetitle.get_rect()
+ coursetitlebox.centerx = WIDTH/2
+ coursetitlebox.centery = HEIGHT/2
+ DISPLAY.blit(coursetitle, coursetitlebox)
+ #if on the course complete screen render the title of the course completed
+ elif gvar.FRAME == 4:
+ coursetitlebox = coursetitle.get_rect()
+ coursetitlebox.centerx = WIDTH/2
+ coursetitlebox.centery = HEIGHT/2
+ DISPLAY.blit(coursetitle, coursetitlebox)
+ #if on the course failed screen render the title of the course failed
+ elif gvar.FRAME == 5:
+ coursetitlebox = coursetitle.get_rect()
+ coursetitlebox.centerx = WIDTH/2
+ coursetitlebox.centery = HEIGHT/2
+ DISPLAY.blit(coursetitle, coursetitlebox)
+ #if on the new car unlocked screen render the image of the new car
+ elif gvar.FRAME == 6:
+ imagefilepath = Path('images/player/side4')
+ imagefile = str(imagefilepath)+'.png'
+ carrender = pygame.transform.scale(pygame.image.load(imagefile), (570,156))
+ DISPLAY.blit(carrender, (100,HEIGHT/2-50))
+ coursetitle = coursefont.render('x6', True, WHITE, BLACK)
+ coursetitlebox = coursetitle.get_rect()
+ coursetitlebox.left = 125
+ coursetitlebox.centery = 450
+ DISPLAY.blit(coursetitle, coursetitlebox)
+
+ #user input
+ keyreader.read()
+
+
+ #things happening during the in-game scenario
+ else:
+ #display the course background
+ DISPLAY.blit(gvar.WINDOW, (2*gvar.STREET.tilt-100,0))
+ #create the textbox content and surfaces to display the player's speed, the cource's completion percentage and lap number, and the player's condition
+ speedtext = ingamefontbig.render((str(round((gvar.STREET.speed/6.9)*25000)) + ' km/h'), True, WHITE, BLACK)
+ completiontext = ingamefontsmall.render('[COMPLETION: ' + (str(round((gvar.STREET.distance/len(gvar.STREET.trackroad))*100)) + '% ] [LAP ' + str(gvar.STREET.lapnum) + '/3]'), True, WHITE, BLACK)
+ conditiontext = ingamefontsmall.render('CONDITION: ' + (str(round(gvar.CONDITION)) + ' %'), True, WHITE, BLACK)
+ speedbox = speedtext.get_rect()
+ speedbox.top = 10
+ speedbox.left = 10
+ completionbox = completiontext.get_rect()
+ completionbox.top = 10
+ completionbox.right = WIDTH-10
+ conditionbox = conditiontext.get_rect()
+ conditionbox.top = 40
+ conditionbox.right = WIDTH-10
+
+ #update the lasers
+ gvar.LASERS.update()
+ #make the road read the track data
+ gvar.STREET.readtrack()
+ #update the road accordingly
+ gvar.STREET.update()
+ #move the player (the car) as defined by the user's input
+ gvar.RACER.move()
+
+ #put speed limits on the cars: 1-fast, 2-medium, 3-slow, 4-superfast (maxes out framerate)
+ if gvar.CARNUM == 1:
+ if gvar.STREET.speed > .08:
+ gvar.STREET.speed = .079
+ if gvar.CARNUM == 2:
+ if gvar.STREET.speed > .07:
+ gvar.STREET.speed = .069
+ if gvar.CARNUM == 3:
+ if gvar.STREET.speed > .06:
+ gvar.STREET.speed = .059
+
+ #simulate centrifugal force (the faster the player is moving the more force applied on turns)
+ if gvar.STREET.speed > 0:
+ if gvar.STREET.tilt == 0:
+ gvar.RACER.dxs = 0
+ elif gvar.STREET.tilt == -1:
+ gvar.RACER.dxs = 2.5*(gvar.STREET.speed+.001)
+ elif gvar.STREET.tilt == 1:
+ gvar.RACER.dxs = -2.5*(gvar.STREET.speed+.001)
+ else:
+ gvar.RACER.dxs = 0
+
+ #collision detection between the player object and the laserbeam object (if hit the condition goes down, which each ascending car being more durable)
+ if ((gvar.LASERS.x1 >= gvar.RACER.x and gvar.LASERS.x1 <= gvar.RACER.x+gvar.RACER.width and gvar.LASERS.y1 >= -(gvar.LASERS.height-gvar.RACER.y))
+ or (gvar.LASERS.x2 >= gvar.RACER.x and gvar.LASERS.x2 <= gvar.RACER.x+gvar.RACER.width and gvar.LASERS.y2 >= -(gvar.LASERS.height-gvar.RACER.y))
+ or (gvar.LASERS.x3 >= gvar.RACER.x and gvar.LASERS.x3 <= gvar.RACER.x+gvar.RACER.width and gvar.LASERS.y3 >= -(gvar.LASERS.height-gvar.RACER.y))
+ or (gvar.LASERS.x1+gvar.LASERS.width >= gvar.RACER.x and gvar.LASERS.x1+gvar.LASERS.width <= gvar.RACER.x+gvar.RACER.width and gvar.LASERS.y1 >= -(gvar.LASERS.height-gvar.RACER.y))
+ or (gvar.LASERS.x2+gvar.LASERS.width >= gvar.RACER.x and gvar.LASERS.x2+gvar.LASERS.width <= gvar.RACER.x+gvar.RACER.width and gvar.LASERS.y2 >= -(gvar.LASERS.height-gvar.RACER.y))
+ or (gvar.LASERS.x3+gvar.LASERS.width >= gvar.RACER.x and gvar.LASERS.x3+gvar.LASERS.width <= gvar.RACER.x+gvar.RACER.width and gvar.LASERS.y3 >= -(gvar.LASERS.height-gvar.RACER.y))):
+ gvar.CONDITION -= .1/gvar.CARNUM
+
+ #if the course is completed (100% completeion on final lap) then set ingame to false, switch music, save new game data, and change menu frame
+ if (round((gvar.STREET.distance/len(gvar.STREET.trackroad))*100) >= 100 and gvar.STREET.lapnum >= 3):
+ gvar.INGAME = False
+ #play mission completed music
+ pygame.mixer.music.stop()
+ musicfilepath = Path('music/musicc')
+ musicfile = str(musicfilepath)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ if gvar.PLAYMUSIC == True:
+ pygame.mixer.music.play(-1)
+ gvar.GAMEDATA = gvar.GAMEDATA[:(gvar.COURSENUM-1)] + '1' + gvar.GAMEDATA[(gvar.COURSENUM):]
+ datafile = Path('data/gamedata/gamedata.txt')
+ file=open(datafile,'w+')
+ file.write(gvar.GAMEDATA)
+ file.close()
+ #win frame
+ gvar.FRAME = 4
+
+ #if condition runs out then set ingame to false, switch music, save new game data, and change menu frame
+ if (round(gvar.CONDITION) <= 0):
+ gvar.INGAME = False
+ #play mission failed music
+ pygame.mixer.music.stop()
+ musicfilepath = Path('music/musicf')
+ musicfile = str(musicfilepath)+'.mp3'
+ pygame.mixer.music.load(musicfile)
+ if gvar.PLAYMUSIC == True:
+ pygame.mixer.music.play(-1)
+ #lose frame
+ gvar.FRAME = 5
+
+ #user input
+ keyreader.read()
+
+ #display each object
+ DISPLAY.blit(gvar.RACER.image, (gvar.RACER.x,gvar.RACER.y))
+ DISPLAY.blit(gvar.LASERS.image, (gvar.LASERS.x1,gvar.LASERS.y1))
+ DISPLAY.blit(gvar.LASERS.image, (gvar.LASERS.x2,gvar.LASERS.y2))
+ DISPLAY.blit(gvar.LASERS.image, (gvar.LASERS.x3,gvar.LASERS.y3))
+ DISPLAY.blit(speedtext, speedbox)
+ DISPLAY.blit(completiontext, completionbox)
+ DISPLAY.blit(conditiontext, conditionbox)
+
+ #the following line continuously calls the while loop
+ pygame.display.update()
+
+#the following line calls the main function and starts the game
+main()
diff --git a/scripts/player.py b/scripts/player.py
new file mode 100644
index 0000000..4bff0ea
--- /dev/null
+++ b/scripts/player.py
@@ -0,0 +1,81 @@
+#import pygame and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+from globalvariables import GlobalVariables, gvar
+
+#initialize the source for global variables from import
+global gvar
+#set default display dimensions
+WIDTH = gvar.WIDTH
+HEIGHT = gvar.HEIGHT
+
+playersfilepath = Path('images/player/straight')
+playerlfilepath = Path('images/player/left')
+playerrfilepath = Path('images/player/right')
+
+class Player:
+ """
+ This `Player` class is used to display and update the player object (the car that the user controls).
+ """
+ def __init__(self, car = 1, width = 0, height = 0, x = 0, y = 0,
+ img1 = pygame.transform.scale(pygame.image.load(str(playersfilepath)+'1.png'), (116, 64)),
+ imgleft1 = pygame.transform.scale(pygame.image.load(str(playerlfilepath)+'1.png'), (116, 64)),
+ imgright1 = pygame.transform.scale(pygame.image.load(str(playerrfilepath)+'1.png'), (116, 64)),
+ img2 = pygame.transform.scale(pygame.image.load(str(playersfilepath)+'2.png'), (116, 85)),
+ imgleft2 = pygame.transform.scale(pygame.image.load(str(playerlfilepath)+'2.png'), (116, 85)),
+ imgright2 = pygame.transform.scale(pygame.image.load(str(playerrfilepath)+'2.png'), (116, 85)),
+ img3 = pygame.transform.scale(pygame.image.load(str(playersfilepath)+'3.png'), (128, 116)),
+ imgleft3 = pygame.transform.scale(pygame.image.load(str(playerlfilepath)+'3.png'), (128, 116)),
+ imgright3 = pygame.transform.scale(pygame.image.load(str(playerrfilepath)+'3.png'), (128, 116)),
+ img4 = pygame.transform.scale(pygame.image.load(str(playersfilepath)+'4.png'), (122, 64)),
+ imgleft4 = pygame.transform.scale(pygame.image.load(str(playerlfilepath)+'4.png'), (122, 64)),
+ imgright4 = pygame.transform.scale(pygame.image.load(str(playerrfilepath)+'4.png'), (122, 64)), dxs = 0):
+ """
+ The `__init__()` function defines the source images for each car as well as some positioning and collision defaults.
+ """
+ #car's image and hitbox width
+ self.width = width
+ #car's image and hitbox height
+ self.height = height
+ #car's x position
+ self.x = x
+ #car's y position
+ self.y = y
+ #car's change in x (if moving)
+ self.dx = 0
+ #the selected car will use the source images correlating to its numeral value
+ if car == 1:
+ self.img = img1
+ self.imgleft = imgleft1
+ self.imgright = imgright1
+ elif car == 2:
+ self.img = img2
+ self.imgleft = imgleft2
+ self.imgright = imgright2
+ elif car == 3:
+ self.img = img3
+ self.imgleft = imgleft3
+ self.imgright = imgright3
+ elif car == 4:
+ self.img = img4
+ self.imgleft = imgleft4
+ self.imgright = imgright4
+ #image to be displayed while running
+ self.image = pygame.transform.rotate(self.img, 0)
+ #the simulated centrefugal force
+ self.dxs = 0
+
+ def move(self):
+ """
+ The `move()` makes the car move sideways.
+ """
+ #change x by dx and dxs
+ self.x += self.dx + self.dxs
+ #check to make sure that the car is within the bounds of the display
+ if self.x >= (WIDTH-self.width):
+ self.x = WIDTH-self.width
+ if self.x <= 0:
+ self.x = 0
diff --git a/scripts/road.py b/scripts/road.py
new file mode 100644
index 0000000..41e3ce3
--- /dev/null
+++ b/scripts/road.py
@@ -0,0 +1,169 @@
+#import pygame and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+from globalvariables import GlobalVariables, gvar
+import numpy as np
+import time
+
+#initialize the source for global variables from import
+global gvar
+#set default display dimensions and create a display to render the road
+WIDTH = gvar.WIDTH
+HEIGHT = gvar.HEIGHT
+DISPLAY = gvar.DISPLAY
+
+class Road:
+ """
+ This `Road` class is used to display and update the road object (the simulation of forward movement in the game).
+ """
+ def __init__(self, track = 1, x = 0, y = 0):
+ """
+ The `__init__()` function defines the aesthetics of each road that can be rendered and pulls the appropriate track data to read from.
+ """
+ #this sets the initial time to determine when to update the lasers
+ self.starttime = time.clock()
+ #this sets the given time to compare against the initial time
+ self.currenttime = time.clock()
+ #these if statments determine the color scheme for each course: 1-speedway, 2-countryside, 3-tundra, 4-desert, 5-city, 6-space
+ if track == 1:
+ self.ROAD = (50,50,50)
+ self.GROUND1 = (150,225,50)
+ self.GROUND2 = (100,205,20)
+ self.SIDES1 = (255,0,0)
+ self.SIDES2 = (255,255,255)
+ elif track == 2:
+ self.ROAD = (205,205,120)
+ self.GROUND1 = (80,150,0)
+ self.GROUND2 = (60,120,0)
+ self.SIDES1 = (238,224,0)
+ self.SIDES2 = (187,176,0)
+ elif track == 3:
+ self.ROAD = (200,200,200)
+ self.GROUND1 = (200,220,220)
+ self.GROUND2 = (180,200,200)
+ self.SIDES1 = (250,250,255)
+ self.SIDES2 = (240,240,240)
+ elif track == 4:
+ self.ROAD = (200,200,150)
+ self.GROUND1 = (225,225,160)
+ self.GROUND2 = (205,205,120)
+ self.SIDES1 = (160,160,120)
+ self.SIDES2 = (150,150,100)
+ elif track == 5:
+ self.ROAD = (25,25,25)
+ self.GROUND1 = (5,5,5)
+ self.GROUND2 = (0,0,0)
+ self.SIDES1 = (100,100,100)
+ self.SIDES2 = (50,50,50)
+ elif track == 6:
+ self.ROAD = (5,5,5)
+ self.GROUND1 = (0,0,0)
+ self.GROUND2 = (0,0,0)
+ self.SIDES1 = (255,255,50)
+ self.SIDES2 = (0,0,0)
+ #default width of each slice that makes the road
+ self.roadwidth = 1000
+ #default width of each slice that makes the sidelines
+ self.sidewidth = 1000
+ #create a default list of 200 objects that will be comprised of each slice of the road
+ self.road = np.zeros(200, dtype=object)
+ #create a default list of 100 objects that will be comprised of each slice of the ground
+ self.ground = np.zeros(100, dtype=object)
+ #create a default list of 100 objects that will be comprised of each slice of the sidelines
+ self.sidelines = np.zeros(100, dtype=object)
+ #the individual road/sideline slice x-axis offset from the center
+ self.tilt = 0
+ #the current index in the list of the track data
+ self.distance = 0
+ #the framerate update constant
+ self.speed = 0
+ #the rate of change of the framerate update constant
+ self.sp = 0
+ #this variable determines whether the current road/ground/sideline slice will be the first of second allocated color
+ self.linecolor = 0
+ #the number of complete progessions through the track data that the road has read
+ self.lapnum = 1
+ #open the given track's data file
+ trackfile = Path('data/tracks/track'+str(track)+'.txt')
+ with open(trackfile) as file:
+ self.trackroad = file.readline()
+ file.close()
+
+ def update(self):
+ """
+ The `update()` function defines how each slice of the road/ground/sidelines will render
+ depending on self.tilt, and the index of the respective list.
+ """
+ #create 100 slices of the ground that alternate colors on each frame switch
+ for roadslice in range(100):
+ if self.linecolor % 2 != 0:
+ self.ground[roadslice] = pygame.draw.rect(DISPLAY, self.GROUND1, (-100, HEIGHT-2*(roadslice), 1000, 2))
+ if self.linecolor % 2 == 0:
+ self.ground[roadslice] = pygame.draw.rect(DISPLAY, self.GROUND2, (-100, HEIGHT-2*(roadslice), 1000, 2))
+ roadslice+=1
+ self.linecolor += 1
+ roadslice = 0
+ #create 100 slices of the sidelines that alternate colors on each frame switch, narrow with descending height values, and move accordingly with the tilt
+ for roadslice in range(100):
+ if self.linecolor % 2 != 0:
+ self.road[roadslice] = pygame.draw.rect(DISPLAY, self.SIDES1, (((WIDTH/2)-(self.sidewidth/2) + (2*self.tilt*((2*roadslice*roadslice)/5000))), HEIGHT-2*(roadslice), int(self.sidewidth), 2))
+ if self.linecolor % 2 == 0:
+ self.road[roadslice] = pygame.draw.rect(DISPLAY, self.SIDES2, (((WIDTH/2)-(self.sidewidth/2) + (2*self.tilt*((2*roadslice*roadslice)/5000))), HEIGHT-2*(roadslice), int(self.sidewidth), 2))
+ self.sidewidth-=12
+ roadslice+=1
+ self.linecolor += 1
+ self.sidewidth = 1200
+ roadslice = 0
+ #create 200 slices of the road that narrow with descending height values and move accordingly with the tilt with each frame switch
+ for roadslice in range(200):
+ self.road[roadslice] = pygame.draw.rect(DISPLAY, self.ROAD, (((WIDTH/2)-(self.roadwidth/2) + (self.tilt*((roadslice*roadslice)/5000))), HEIGHT-(roadslice), int(self.roadwidth), 1))
+ self.roadwidth-=5
+ roadslice+=1
+ self.roadwidth=1000
+
+ def readtrack(self):
+ """
+ The `readtrack()` function reads through the track data file and dictates how the overall course will react on each frame switch.
+ """
+ #update the current time
+ self.currenttime = time.clock()
+ #if the differences in the times surpasses the framerate threshold the road/ground/sidelines slices will update accordingly
+ if (self.currenttime-self.starttime) > (.12-self.speed):
+ if self.distance >= len(self.trackroad):
+ self.distance = 0
+ self.lapnum += 1
+ self.speed += self.sp
+ #check to make sure the framerate is not too fast or slow
+ if self.speed <= 0:
+ self.speed = 0
+ elif self.speed >= .09:
+ self.speed = .089
+ #if the framerate is withing the valid bounds give the appropriate values to update all the road/ground/sidelines slices by based on the track data
+ elif self.speed > 0:
+ if self.trackroad[self.distance] == '3':
+ self.tilt += 0
+ self.linecolor += 1
+ self.update()
+ if self.trackroad[self.distance] == '2':
+ self.tilt -= 1
+ self.linecolor += 1
+ self.update()
+ if self.trackroad[self.distance] == '4':
+ self.tilt += 1
+ self.linecolor += 1
+ self.update()
+ if self.trackroad[self.distance] == '1':
+ self.tilt -= 0
+ self.linecolor += 1
+ self.update()
+ if self.trackroad[self.distance] == '5':
+ self.tilt += 0
+ self.linecolor += 1
+ self.update()
+ if self.distance < len(self.trackroad):
+ self.distance += 1
+ #update the start time to continue the chain
+ self.starttime = time.clock()
diff --git a/scripts/trackgenerator.py b/scripts/trackgenerator.py
new file mode 100644
index 0000000..5d94aff
--- /dev/null
+++ b/scripts/trackgenerator.py
@@ -0,0 +1,201 @@
+#import pygame and other necessary libraries
+from pathlib import Path
+import contextlib
+with contextlib.redirect_stdout(None):
+ import pygame, sys
+ from pygame.locals import *
+
+class TrackGenerator:
+ """
+ The `TrackGenerator` class is used to generate a list of numbers that will correlate to how the in-game road will operate.
+
+ Each number from 1 through 5 will cause the road to act differently:
+ 1 - Road holds to the left.
+ 2 - Road turns to the left.
+ 3 - Road holds to the center.
+ 4 - Road turns to the right.
+ 5 - Road holds to the right.
+ """
+ def __init__(self):
+ """
+ The `__init__()` function defines the possible pieces of the track that can be put together.
+ """
+ #road stays straight
+ self.straight = '3'
+ #road turns left, holds left, then turns back right to the center
+ self.left = '222222222222222222222222222222221111111111111111111111111111111144444444444444444444444444444444'
+ self.left2 = '222222222222222211111111111111114444444444444444'
+ self.left3 = '222222221111111144444444'
+ #road turns right, holds right, then turns back left to the center
+ self.right = '444444444444444444444444444444445555555555555555555555555555555522222222222222222222222222222222'
+ self.right2 = '444444444444444455555555555555552222222222222222'
+ self.right3 = '444444445555555522222222'
+ #this string will be used to add and then save the generated data to a text file to pull from later
+ self.road = ''
+
+ def generate(self):
+ """
+ The `generate()` function uses the predefined pieces for a track written with strings to make a complete track.
+ """
+ #continuously add pieces to the overall track
+ '''
+ #TRACK1
+ for trackpieces in range(50):
+ self.road += self.straight
+ self.road += self.right
+ self.road += self.right
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.left
+ for trackpieces in range(25):
+ self.road += self.straight
+ self.road += self.left
+ for trackpieces in range(30):
+ self.road += self.straight
+ self.road += self.right
+ for trackpieces in range(25):
+ self.road += self.straight
+ self.road += self.left
+ for trackpieces in range(30):
+ self.road += self.straight
+ #TRACK2
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.right
+ self.road += self.left
+ self.road += self.right
+ for trackpieces in range(20):
+ self.road += self.straight
+ self.road += self.left
+ for trackpieces in range(30):
+ self.road += self.straight
+ self.road += self.right
+ for trackpieces in range(40):
+ self.road += self.straight
+ self.road += self.left
+ self.road += self.right
+ self.road += self.left
+ self.road += self.right
+ self.road += self.left
+ for trackpieces in range(40):
+ self.road += self.straight
+ #TRACK3
+ for trackpieces in range(30):
+ self.road += self.straight
+ self.road += self.left
+ for trackpieces in range(30):
+ self.road += self.straight
+ self.road += self.right
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.left
+ self.road += self.right
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.left
+ self.road += self.right
+ for trackpieces in range(30):
+ self.road += self.straight
+ self.road += self.right
+ for trackpieces in range(15):
+ self.road += self.straight
+ self.road += self.left
+ #TRACK4
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.right
+ self.road += self.left
+ for trackpieces in range(20):
+ self.road += self.straight
+ self.road += self.right
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.left2
+ self.road += self.right
+ for trackpieces in range(5):
+ self.road += self.straight
+ self.road += self.left2
+ self.road += self.right2
+ for trackpieces in range(30):
+ self.road += self.straight
+ self.road += self.right2
+ for trackpieces in range(25):
+ self.road += self.straight
+ self.road += self.left
+ self.road += self.left
+ for trackpieces in range(45):
+ self.road += self.straight
+ #TRACK5
+ self.road += self.right2
+ for trackpieces in range(20):
+ self.road += self.straight
+ self.road += self.right2
+ self.road += self.left2
+ for trackpieces in range(20):
+ self.road += self.straight
+ self.road += self.left2
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.left2
+ for trackpieces in range(15):
+ self.road += self.straight
+ self.road += self.right2
+ for trackpieces in range(40):
+ self.road += self.straight
+ self.road += self.right2
+ for trackpieces in range(35):
+ self.road += self.straight
+ self.road += self.left2
+ self.road += self.right2
+ for trackpieces in range(45):
+ self.road += self.straight
+ self.road += self.left
+ '''
+ #TRACK6
+ self.road += self.right
+ self.road += self.left
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.right3
+ self.road += self.left3
+ self.road += self.right3
+ self.road += self.left3
+ self.road += self.right3
+ self.road += self.left3
+ for trackpieces in range(5):
+ self.road += self.straight
+ self.road += self.left2
+ for trackpieces in range(5):
+ self.road += self.straight
+ self.road += self.left2
+ self.road += self.right3
+ self.road += self.left
+ self.road += self.right2
+ for trackpieces in range(15):
+ self.road += self.straight
+ self.road += self.right
+ for trackpieces in range(5):
+ self.road += self.straight
+ self.road += self.left3
+ self.road += self.right3
+ self.road += self.left3
+ self.road += self.right3
+ self.road += self.left3
+ for trackpieces in range(15):
+ self.road += self.straight
+ self.road += self.left2
+ self.road += self.right
+ for trackpieces in range(10):
+ self.road += self.straight
+ self.road += self.right2
+ self.road += self.left3
+ self.road += self.right
+ self.road += self.left2
+ for trackpieces in range(30):
+ self.road += self.straight
+
+ #save created data to a text file with the appropriate track name
+ trackfile = Path('data/tracks/track6.txt')
+ file=open(trackfile,'w+')
+ file.write(self.road)
+ file.close()