Maze Runner is a First Person game that runs on a terminal window. The Player will get to choose between an easy maze or a difficult one. The rule is simple. Find the red door in the maze and escape as fast as possible. The player is only allowed to use the map for a limited number of times. The time taken to finish one round is recorded.
I made this project to learn more about the usage of the very basic state machine in python and also the rendering technique that many game engines use, Ray Tracing.
Ray Tracing is one of many rendering techniques. Steps on how it works are as follows:
- Light rays are shot out from the player's point of view.
- For every light ray, trace where each of them is going to.
- When a collision with an object is detected, a portion of the light ray will be absorbed and some will bounce off in different directions.
- The light ray keeps being absorbed and bouncing until it reaches the light source or a very dark opaque object.
- The aggregated value from those bounces will give the amount of light or shadow that should be shown for each pixel on the screen.
With the constraint that I have in this coding project; a terminal window as the display and a must to use python, an interpreted language (which may run less efficiently as compiled programming language like C++), I limit the extend of ray tracing the game uses.
In Maze Runner, the light rays only bounce off once from the wall and the distance of the wall from the players determines how bright or dark the pixel is.
The size of the wall is scaled with a linear inverse relationship with the distance of the object. This is similar to the effect that cameras in real life.
In Maze Runner, the state machine manages the upper-level state of the game. The upper-level state consists of the state of the screen that is displayed to the player and how the screen should change with the keyboard input from the player.
I tried to use the state machine to manage all of the states of the game. However, it hits the performance very badly; the game ran for around 5 frames per second (FPS)instead of the normal 20 frames per second (FPS) on average. Therefore, I keep some of the in-game controls such as movement and trigger actions inside the variables of the main function not inside the state of the state machine object.
- libdw
- asciimatics – Install by running
conda install -c conda-forge asciimatics
.
-
Ensure that asciimatics and libdw are installed. The game will run into an error if these libraries are not installed properly. See below for instructions to install asciimatics.
-
Open power shell (Win X + A) or any of your favorite terminal or Anaconda Prompt.
# Move to the project directory. $ cd </project/folder> # Run the game. $ python ./main.py
Ensure that asciimatics and libdw are installed. The game will run into an error if these libraries are not installed properly. See below for instructions to install asciimatics.
-
Open power shell (Win X + A) or any of your favorite terminal or Anaconda Prompt.
# Clone the whole repository. $ git clone https://github.com/ulaladungdung/maze-runner.git # Run the game. $ python ./src/main.py
-
Open your Anaconda Prompt with Admin privilege.
-
Copy and paste this line of command:
conda install -c conda-forge asciimatics
-
Press Enter.
-
Close this window and reopen Anaconda Prompt.
-
Open your Command Prompt with Admin privilege.
-
Copy and paste this line of command:
pip install asciimatics
-
Press Enter.
-
Restart ANao
GPU
is a wrapper for asciimatic
library.GPU
allows other classes to print any ASCII character on the terminal window and to get the keyboard and mouse input event from the terminal window.
Properties:
- screen - get the Screen object of the terminal window.
- height - The number of lines in the window.
- width - The number of character in one line.
Constants:
- __DISABLE_KEYBOARD_INTERRUPT - Disable keyboard interruption in terminal. For example, ignoring
^Z
or^C
.
Grab the lower lever control of the terminal window it is on.
Close the current screen and clear buffer to prevent memory leaks.
Parameters:
- restore – If True, only discard the display buffer of the terminal window. Otherwise, remove buffer and closes all the opened input to the terminal window
Returns: None
Print the text at the specified location using the specified colour and attributes.
Parameters:
- char – The (single line) text to be printed.
- x – The column (x coord) for the start of the text.
- y – The line (y coord) for the start of the text.
- colour – The colour of the text to be displayed.
- attr – The cell attribute of the text to be displayed.
- bg – The background colour of the text to be displayed.
- transparent – Whether to print spaces or not, thus giving a transparent effect.
Returns: None
The colours and attributes are as follow. Note that not all terminal supports the colour and attributes.
COLOUR_RED = 1
COLOUR_GREEN = 2
COLOUR_YELLOW = 3
COLOUR_BLUE = 4
COLOUR_MAGENTA = 5
COLOUR_CYAN = 6
COLOUR_WHITE = 7
A_BOLD = 1
A_NORMAL = 2
Check for any events (e.g. key-press or mouse movement) without waiting.
Returns: An Event object if anything was detected, otherwise it returns None.
Flush the buffer to the terminal window
Returns: None
Set the title for this terminal window. This will typically change the text displayed in the window title bar.
Parameters:
- title – The title to be set.
Returns: None
Loop through the list of effect.
Parameters:
- effect_list – The list of preset effect to be playes
- duration – The amount of time the scene will play for. A value of –1 means don’t stop.
- stop_on_resize – Whether to stop when the screen is resized. Default is to carry on regardless – which will typically result in an error.
- input_handler – Function to call for any input. The input_handler input function just takes one parameter – the input event that was not handled.
Returns: None
A point object in a 2D
space.
Parameters:
- x – The x coordinate.
- y – The y coordinate.
Properties:
- x – The x coordinate in float.
- y – The y coordinate in float.
- x_int – The x coordinate in integer.
- y_int – The y coordinate in integer.
Move the point towards a direction.
Parameters:
- distance – The magnitude of how far the point moves.
- angle – The direction where the point moves to
Returns: None
This is the main screen of the game. The concept of Ray Tracing is used to estimate the color of a every pixel rendered from the map.
Generate maze depends on the difficulty set.
Parameters:
- difficulty – The set difficulty of the map.
EASY
for easy map andHARD
for a more difficult map.
Returns: The maze in a list of string.
Display the main menu for user to see when the game starts.
Display the rules and objectives of the map to the user.
Display the result of the round to the user
Pop up a screen that pauses the game. Time is stopped also.
Pop up a screen that shows the map of the maze, the location of the player and the location of the objective. There is a limited amount of time the user can use the map.
Start the game.
Shutdown the GPU object and clear up all the used memory. Exit the game.
Parameters:
- player_pos – The coordinate object of the player.
- map – The map of the round.
Returns: None
The object that stores the machine state and is responsible for upper level state management.
Properties:
- start_state – The initial state of the machine.
Process the input with the current state of the machine.
The extension function of get_next_values().
__screen_menu(self, state, inp_key_code)
__screen_wait(self, state, inp_key_code)
__screen_play(self, state, inp_key_code)
__screen_pause(self, state, inp_key_code)
__screen_result(self, state, inp_key_code)
__screen_map(self, state, inp_key_code)
__screen_default(self, state, inp)
Properties:
- state – The current state of the machine.
- inp_key_code – The input key pressed on the keyboard.
Returns:
- next_state – The next state of the machine.
- output – The output from the input and the current state machine.
- use asciimatics to try make a splash screen
######################################################################
# #
# #
# #
# #
# #
# #
# #
# #
# #
# #
# #
# #
# #
# PRESS ENTER TO START #
# #
######################################################################
-
make level 1 map (Bird view)
-
use get_input() to move user from the level 1 map
-
make a 3d perspective
- Use ray collision detection. Further one less shady then the nearer one (see if can apply anti aliasing)
- option B:
- Use premade perspective ascii to make the map.
-
Testing
-
Optimize
- Migrate to a more efficient programming language. Currently it performs at 20 FPS in average.
- Add an online leaderboard where different players can compete.
- click enter to start
- start from level 1 - 10
- there is a timer that starts counting
- level 1 is to get used to the control
- keyboard
A, W, S, and D
to move - mouse dragging to rotate camera.