diff --git a/PreReq/VirtualTermianLevel.reg b/PreReq/VirtualTermianLevel.reg new file mode 100644 index 0000000..15c941f Binary files /dev/null and b/PreReq/VirtualTermianLevel.reg differ diff --git a/PyGame/Basics/000_Intro.py b/PyGame/Basics/000_Intro.py index dc09bf1..3cd0363 100644 --- a/PyGame/Basics/000_Intro.py +++ b/PyGame/Basics/000_Intro.py @@ -12,15 +12,14 @@ import sys # This initializes the back-end bits and pieces of pygame pygame.init() -# Some variables used to initialize the window +# Some global variables used to initialize the window # The width and height are in pixels -win_width = 600 -win_height = 480 -running = True +WIN_WIDTH = 600 +WIN_HEIGHT = 480 # We create a window object used to draw pygame things # It is initialized with set_mode((width, height)) -window = pygame.display.set_mode((win_width, win_height)) +window = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) # This sets the text in the window's title bar pygame.display.set_caption("PyGame Basics") # this clock variable is just an instance of the @@ -29,6 +28,7 @@ pygame.display.set_caption("PyGame Basics") clock = pygame.time.Clock() # The main loop. This while loop runs until "running" is False +running = True while running is True: # pygame.event.get() returns any events that have happened # since the last call to get(). This lets us catch any diff --git a/PyGame/Basics/005_windowskin.py b/PyGame/Basics/005_windowskin.py index 1c20056..7a9e9bf 100644 --- a/PyGame/Basics/005_windowskin.py +++ b/PyGame/Basics/005_windowskin.py @@ -7,15 +7,14 @@ pygame.init() # Some variables used to initialize the window # The width and height are in pixels -win_width = 600 -win_height = 480 -win_bg_color = (26, 110, 43) -text_color = (242, 238, 10) -running = True +WIN_WIDTH = 600 +WIN_HEIGHT = 480 +WIN_BG_COLOR = (26, 110, 43) +TEXT_COLOR = (242, 238, 10) # We create a window object used to draw pygame things # It is initialized with set_mode((width, height)) -window = pygame.display.set_mode((win_width, win_height)) +window = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) pygame.display.set_caption('PyGame Fancy Basics') # In order to work with images they must be turned into # an object. The image.load() method is used to read in an @@ -29,7 +28,7 @@ icon.convert_alpha() pygame.display.set_icon(icon) # This will fill the entire window with a single color # The color parameter must be a three element tuple (r, g, b) -window.fill(win_bg_color) +window.fill(WIN_BG_COLOR) # Here we use the Font() method to import a True Type font # from the "font/" folder with a size of 200 pixeboy_200 = pygame.font.Font(os.path.join("font", "Pixeboy.ttf"), 200) @@ -39,14 +38,14 @@ pixeboy_200 = pygame.font.Font(os.path.join("font", "Pixeboy.ttf"), 200) # is font antialiased (pretty much always True) # color of text (this is a R, G, B tuple) # This is called a "text surface" -title_text_1 = pixeboy_200.render("HELLO", True, text_color) -title_text_2 = pixeboy_200.render("WORLD", True, text_color) +title_text_1 = pixeboy_200.render("HELLO", True, TEXT_COLOR) +title_text_2 = pixeboy_200.render("WORLD", True, TEXT_COLOR) # Text is drawn on the screen by specifying the top left # corner of an imaginary rectangle that contains the text # We want to center this text in the window so we # subtract half the width of the text (get_width()) # from half the width of the program window -text_x = (win_width // 2) - (title_text_1.get_width() // 2) +text_x = (WIN_WIDTH // 2) - (title_text_1.get_width() // 2) # We'll start 25 pixels from the top of the window text_y = 25 # The blit() method draws a text surface in the specified @@ -57,7 +56,7 @@ window.blit(title_text_1, (text_x, text_y)) # Now we do the same thing for the second line of text # just moved down (y) by the height of the first line of # text plus an extra 25 pixels for separation -text_x = (win_width // 2) - (title_text_2.get_width() // 2) +text_x = (WIN_WIDTH // 2) - (title_text_2.get_width() // 2) text_y = 25 + title_text_2.get_height() + 25 window.blit(title_text_2, (text_x, text_y)) # Just like the icon used for the title bar @@ -65,13 +64,14 @@ window.blit(title_text_2, (text_x, text_y)) emoji = pygame.image.load(os.path.join("img", "poop_emoji_sm.png")) emoji.convert_alpha() # Let's place the image 25 pixels from the bottom of the window -emoji_x = (win_width // 2) - (emoji.get_width() // 2) -emoji_y = win_height - 25 - emoji.get_height() +emoji_x = (WIN_WIDTH // 2) - (emoji.get_width() // 2) +emoji_y = WIN_HEIGHT - 25 - emoji.get_height() # And we blit/draw it onto the window the same way as we do text window.blit(emoji, (emoji_x, emoji_y)) clock = pygame.time.Clock() # The main loop. This while loop runs until "running" is False +running = True while running is True: for event in pygame.event.get(): if event.type == pygame.QUIT: diff --git a/PyGame/Basics/010_mousesound.py b/PyGame/Basics/010_mousesound.py index 86202ec..49da272 100644 --- a/PyGame/Basics/010_mousesound.py +++ b/PyGame/Basics/010_mousesound.py @@ -8,43 +8,41 @@ pygame.init() # Some variables used to initialize the window # The width and height are in pixels -win_width = 600 -win_height = 480 -win_bg_color = (26, 110, 43) -text_color = (242, 238, 10) -running = True -emoji_hover = False +WIN_WIDTH = 600 +WIN_HEIGHT = 480 +WIN_BG_COLOR = (26, 110, 43) +TEXT_COLOR = (242, 238, 10) -window = pygame.display.set_mode((win_width, win_height)) +window = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) pygame.display.set_caption('PyGame Fancy Basics') icon = pygame.image.load(os.path.join("img", "melon_icon_64.png")) icon.convert_alpha() pygame.display.set_icon(icon) -window.fill(win_bg_color) +window.fill(WIN_BG_COLOR) # Import font pixeboy_200 = pygame.font.Font(os.path.join("font", "Pixeboy.ttf"), 200) # Create two lines of text -title_text_1 = pixeboy_200.render("HELLO", True, text_color) -title_text_2 = pixeboy_200.render("WORLD", True, text_color) +title_text_1 = pixeboy_200.render("HELLO", True, TEXT_COLOR) +title_text_2 = pixeboy_200.render("WORLD", True, TEXT_COLOR) # Draw first line of text -text_x = (win_width // 2) - (title_text_1.get_width() // 2) +text_x = (WIN_WIDTH // 2) - (title_text_1.get_width() // 2) text_y = 25 window.blit(title_text_1, (text_x, text_y)) # Draw second line of text -text_x = (win_width // 2) - (title_text_2.get_width() // 2) +text_x = (WIN_WIDTH // 2) - (title_text_2.get_width() // 2) text_y = 25 + title_text_2.get_height() + 25 window.blit(title_text_2, (text_x, text_y)) # Import image emoji = pygame.image.load(os.path.join("img", "poop_emoji_sm.png")) emoji.convert_alpha() # Let's place the image 25 pixels from the bottom of the window -emoji_x = (win_width // 2) - (emoji.get_width() // 2) -emoji_y = win_height - 25 - emoji.get_height() +emoji_x = (WIN_WIDTH // 2) - (emoji.get_width() // 2) +emoji_y = WIN_HEIGHT - 25 - emoji.get_height() window.blit(emoji, (emoji_x, emoji_y)) pixeboy_20 = pygame.font.Font(os.path.join("font", "Pixeboy.ttf"), 20) -click_text = pixeboy_20.render("Click Me", True, text_color) -text_x = (win_width // 2) - (click_text.get_width() // 2) -text_y = win_height - 5 - click_text.get_height() +click_text = pixeboy_20.render("Click Me", True, TEXT_COLOR) +text_x = (WIN_WIDTH // 2) - (click_text.get_width() // 2) +text_y = WIN_HEIGHT - 5 - click_text.get_height() window.blit(click_text, (text_x, text_y)) # We can import audio files with mixer.Sound() # Only .ogg (Ogg Vorbis) format files should be used @@ -58,6 +56,8 @@ audio.append(pygame.mixer.Sound(os.path.join("snd", "toot_wet.ogg"))) clock = pygame.time.Clock() # The main loop. This while loop runs until "running" is False +running = True +emoji_hover = False while running is True: # We'll get the current mouse cursor position mouse_x, mouse_y = pygame.mouse.get_pos() diff --git a/PyGame/Basics/015_pyinstaller.py b/PyGame/Basics/015_pyinstaller.py index 07ebddf..6914156 100644 --- a/PyGame/Basics/015_pyinstaller.py +++ b/PyGame/Basics/015_pyinstaller.py @@ -14,12 +14,10 @@ pygame.init() # Some variables used to initialize the window # The width and height are in pixels -win_width = 600 -win_height = 480 -win_bg_color = (26, 110, 43) -text_color = (242, 238, 10) -running = True -emoji_hover = False +WIN_WIDTH = 600 +WIN_HEIGHT = 480 +WIN_BG_COLOR = (26, 110, 43) +TEXT_COLOR = (242, 238, 10) # This function takes a list of path arguments # and prepends the sys._MEIPASS variable if the @@ -32,36 +30,36 @@ def get_real_path(*path_args: str): my_path = os.path.join(*path_args) return my_path -window = pygame.display.set_mode((win_width, win_height)) +window = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) pygame.display.set_caption('PyGame Fancy Basics') icon = pygame.image.load(get_real_path("img", "melon_icon_64.png")) icon.convert_alpha() pygame.display.set_icon(icon) -window.fill(win_bg_color) +window.fill(WIN_BG_COLOR) # Import font pixeboy_200 = pygame.font.Font(get_real_path("font", "Pixeboy.ttf"), 200) # Create two lines of text -title_text_1 = pixeboy_200.render("HELLO", True, text_color) -title_text_2 = pixeboy_200.render("WORLD", True, text_color) +title_text_1 = pixeboy_200.render("HELLO", True, TEXT_COLOR) +title_text_2 = pixeboy_200.render("WORLD", True, TEXT_COLOR) # Draw first line of text -text_x = (win_width // 2) - (title_text_1.get_width() // 2) +text_x = (WIN_WIDTH // 2) - (title_text_1.get_width() // 2) text_y = 25 window.blit(title_text_1, (text_x, text_y)) # Draw second line of text -text_x = (win_width // 2) - (title_text_2.get_width() // 2) +text_x = (WIN_WIDTH // 2) - (title_text_2.get_width() // 2) text_y = 25 + title_text_2.get_height() + 25 window.blit(title_text_2, (text_x, text_y)) # Import image emoji = pygame.image.load(get_real_path("img", "poop_emoji_sm.png")) emoji.convert_alpha() # Let's place the image 25 pixels from the bottom of the window -emoji_x = (win_width // 2) - (emoji.get_width() // 2) -emoji_y = win_height - 25 - emoji.get_height() +emoji_x = (WIN_WIDTH // 2) - (emoji.get_width() // 2) +emoji_y = WIN_HEIGHT - 25 - emoji.get_height() window.blit(emoji, (emoji_x, emoji_y)) pixeboy_20 = pygame.font.Font(get_real_path("font", "Pixeboy.ttf"), 20) -click_text = pixeboy_20.render("Click Me", True, text_color) -text_x = (win_width // 2) - (click_text.get_width() // 2) -text_y = win_height - 5 - click_text.get_height() +click_text = pixeboy_20.render("Click Me", True, TEXT_COLOR) +text_x = (WIN_WIDTH // 2) - (click_text.get_width() // 2) +text_y = WIN_HEIGHT - 5 - click_text.get_height() window.blit(click_text, (text_x, text_y)) # We can import audio files with mixer.Sound() # Only .ogg (Ogg Vorbis) format files should be used @@ -75,6 +73,8 @@ audio.append(pygame.mixer.Sound(get_real_path("snd", "toot_wet.ogg"))) clock = pygame.time.Clock() # The main loop. This while loop runs until "running" is False +running = True +emoji_hover = False while running is True: # We'll get the current mouse cursor position mouse_x, mouse_y = pygame.mouse.get_pos() diff --git a/PyGame/FailBoard/fail.py b/PyGame/FailBoard/fail.py index a04c859..1b8b9a2 100644 --- a/PyGame/FailBoard/fail.py +++ b/PyGame/FailBoard/fail.py @@ -19,7 +19,8 @@ class Button: flashing: bool = False unflash_on: float = 0.0 -buttons = { +# Define buttons and their associated keyboard keys +BUTTONS = { str(pygame.K_1): Button(2, 0, pygame.K_1, "1", "8bit-fail.ogg"), str(pygame.K_2): Button(2, 1, pygame.K_2, "2", "brass-fail-8.ogg"), str(pygame.K_3): Button(2, 2, pygame.K_3, "3", "brass-fail-11.ogg"), @@ -31,7 +32,8 @@ buttons = { str(pygame.K_9): Button(0, 2, pygame.K_9, "9", "wrong.ogg") } -keypad_map = { +# Map number-pad numbers to normal keyboard numbers for simplicity +KEYPAD_MAP = { str(pygame.K_KP_1): pygame.K_1, str(pygame.K_KP_2): pygame.K_2, str(pygame.K_KP_3): pygame.K_3, @@ -43,7 +45,8 @@ keypad_map = { str(pygame.K_KP_9): pygame.K_9 } -valid_keys_numbers = [ +# The valid keyboard keys that represent numbers for buttons +VALID_KEYS_NUMBERS = [ pygame.K_1, pygame.K_2, pygame.K_3, @@ -55,45 +58,46 @@ valid_keys_numbers = [ pygame.K_9 ] -#pygame.mixer.pre_init(44100, 16, 2, 64000) +# Some program globals +WIDTH = 1000 +HEIGHT = 975 +BACKGROUND_COLOR = (150, 150, 150) +LABEL_COLOR = (255, 255, 255) +LABEL_COLOR_FLASH = (0, 0, 0) + pygame.init() -#pygame.mixer.init() - -width = 1000 -height = 975 -background_color = (150, 150, 150) -label_color = (255, 255, 255) -label_color_flash = (0, 0, 0) - -screen = pygame.display.set_mode((width, height)) +screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('Epic Fail Sound Board') icon = pygame.image.load(os.path.join("img", "fail-icon.png")) icon.convert_alpha() pygame.display.set_icon(icon) -screen.fill(background_color) +screen.fill(BACKGROUND_COLOR) pygame.display.flip() logo = pygame.image.load(os.path.join("img", "fail.png")) logo.convert_alpha() -screen.blit(logo, ((width // 2) - (logo.get_width() // 2), 20)) +screen.blit(logo, ((WIDTH // 2) - (logo.get_width() // 2), 20)) button_origin_x = 100 button_origin_y = logo.get_height() + 20 + 25 button_img = pygame.image.load(os.path.join("img", "button-red.png")) button_img.convert_alpha() cheesy_font = pygame.font.Font(os.path.join("font", "New Cheese.ttf"), 60) -for b in buttons.values(): +for b in BUTTONS.values(): x = button_origin_x + ((button_img.get_width() + 100) * b.column) y = button_origin_y + ((button_img.get_height() + 30) * b.row) b.center_x = x + (button_img.get_width() // 2) b.center_y = y + (button_img.get_height() // 2) screen.blit(button_img, (x, y)) - b_text = cheesy_font.render(b.label, True, label_color) + b_text = cheesy_font.render(b.label, True, LABEL_COLOR) text_x = x + (button_img.get_width() // 2) - (b_text.get_width() // 2) text_y = y + (button_img.get_height() // 2) - (b_text.get_height() // 2) screen.blit(b_text, (text_x, text_y)) pygame.display.flip() +# This function processes a button press/activation +# 1) Flash the button +# 2) Play the sound def do_button(key): - for b in buttons.values(): + for b in BUTTONS.values(): if b.key == key: audio = pygame.mixer.Sound(os.path.join("snd", b.sound_file)) flash_button(b) @@ -101,11 +105,11 @@ def do_button(key): def flash_button(b: Button): if b.flashing == False: - text_color = label_color_flash + text_color = LABEL_COLOR_FLASH b.flashing = True b.unflash_on = time.time() + 0.1 else: - text_color = label_color + text_color = LABEL_COLOR b.flashing = False b_text = cheesy_font.render(b.label, True, text_color) text_x = b.center_x - (b_text.get_width() // 2) @@ -120,20 +124,20 @@ while True: mouse_click = None if event.type == pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y = pygame.mouse.get_pos() - for b in buttons.values(): + for b in BUTTONS.values(): if math.hypot(mouse_x - b.center_x, mouse_y - b.center_y) <= (button_img.get_width() // 2): mouse_click = b.key if event.type == pygame.KEYDOWN or not mouse_click is None: if mouse_click is None: - my_key = keypad_map[str(event.key)] if str(event.key) in keypad_map.keys() else event.key + my_key = KEYPAD_MAP[str(event.key)] if str(event.key) in KEYPAD_MAP.keys() else event.key else: my_key = mouse_click if my_key == pygame.K_ESCAPE: pygame.quit() sys.exit() - elif my_key in valid_keys_numbers: + elif my_key in VALID_KEYS_NUMBERS: do_button(my_key) - for b in buttons.values(): + for b in BUTTONS.values(): if b.flashing == True and time.time() >= b.unflash_on: flash_button(b) pygame.display.flip() \ No newline at end of file diff --git a/Python/027_function.py b/Python/027_function.py index 34d2f56..0e00f00 100644 --- a/Python/027_function.py +++ b/Python/027_function.py @@ -1,6 +1,8 @@ # A simple example of making a function +from colorama import just_fix_windows_console from Utils.TextColors import TextColors +just_fix_windows_console() # Functions are blocks of code that can be # called/referenced from elsewhere in the code. diff --git a/Python/029_scope.py b/Python/029_scopedocstring.py similarity index 71% rename from Python/029_scope.py rename to Python/029_scopedocstring.py index fb8e800..165b066 100644 --- a/Python/029_scope.py +++ b/Python/029_scopedocstring.py @@ -15,7 +15,16 @@ MAX_STUDENTS_PER_TEACHER = 25 # Let's create a couple functions to get values # This function makes use of the MAX_TEACHERS global variable -def get_teacher_count(): +# This is also an example of a "docstring". A docstring is text +# that is displayed in the IDE and provides additional information +# to the coder about what the function does and what it returns. +def get_teacher_count() -> int: + """ + Returns the number of teachers at the school. + + Returns: + int: The number of teachers as provided by user input. Value restricted to MAX_TEACHERS. + """ count = 0 while count == 0: # Get a value from the user @@ -35,7 +44,20 @@ def get_teacher_count(): # This function makes use of the MAX_STUDENTS_PER_TEACHER global variable # and is passed the number of teachers obtained from get_teacher_count() -def get_student_count(teacher_count: int): +def get_student_count(teacher_count: int) -> int: + """ + Get the number of students at the school from user input. + + Number will be restricted to: + * teacher_count at a minimum, + * (teacher_count * MAX_STUDENTS_PER_TEACHER) as a maximum. + + Arguments: + teacher_count (int): The number of teachers at the school. + + Returns: + int: The number of students at the school. + """ count = 0 # Can't have fewer students than teachers min_students = teacher_count diff --git a/README.md b/README.md index cb8a719..bf90c40 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,26 @@ This repository is primarily a collection of resources and learning aides for St * The requests module provides web/REST API access * The colorama module provides access to color and cursor positioning in a terminal +* The termcolor module provides access to console text colors as well in a different way (include for compatibility) Inside a terminal: ```bash -pip install requests colorama +pip install requests colorama termcolor +``` + +By default the CMD and Powershell terminals will not properly show ANSI colors in Windows. This can be fixed by using the colorama module with the following code: +```python +import sys +if sys.platform == "win32": + from colorama import just_fix_windows_console + just_fix_windows_console() +``` + +In order to get ANSI colors in windows CMD or Powershell without using the colorama module (can be useful in other things so if you do have admin access this is handy to do regardless) the virtual terminal level must be set to 1. + +Inside an **Administrator** terminal in the `PreReq/` folder: +```bash +reg import VirtualTerminalLevel.reg ``` ## [Python Basics](Python/)