From f8015b753f9063d9edd60a33cb0e2d5d92ada61e Mon Sep 17 00:00:00 2001 From: Junior Date: Tue, 18 Jun 2024 19:58:15 -0400 Subject: [PATCH 1/2] Add a basic python example for variable scope --- Python/045_scope.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Python/045_scope.py diff --git a/Python/045_scope.py b/Python/045_scope.py new file mode 100644 index 0000000..8aef65f --- /dev/null +++ b/Python/045_scope.py @@ -0,0 +1,58 @@ +# Scope of variables +# The "scope" of a variable means: +# "where is this variable and its value accessible" + +# Variables are used to store data throughout a program. +# Creating a variable is commonly done like this: +# +# A string literal: +# my_string = "This Is Text" +# A scalar value: +# my_number = 47 +# A data structure (i.e. list, dict, tuple, set, etc.): +# my_list = ["a", "j", "p", "y"] +# An object/class instantiation: +# my_object = Button("label", color=(25, 128, 199)) +# +# Each of the examples above are "variable assignments". +# An assignment names a variable (such as 'my_number' above) +# and sets a specific value to that named variable. + +# Variables assigned at the "top logical level" of the program +# are in what we call the "global scope" or called "global variables". +# This means that those variables and their values are available +# within the main body of the program, from within functions, +# and from within classes. +# +# More informationL https://www.w3schools.com/python/python_variables_global.asp +# Better/More Complex: https://realpython.com/python-use-global-variable-in-function/ + +name = "Donkey" +age = 44 +streets = ["Brown Bark", "Pine Knot", "Thomas Jefferson"] + +def alter(): + print(name) + age = 3 + streets[1] = "George Wythe" + +alter() +print(name) +print(age) +print(streets) + +# This shows us several things: +# 1) The variable "name" is available inside the alter() function +# 2) The streets[] list is available +# 3) and its elements can be changed within the alter() function +# 4) The "age" variable assigned in the alter() function does not +# effect the globally scoped variable "age" +# +# One of the key topics here is "mutability". This topic is quite +# complex and involved. Here's a link where you can read more: +# https://realpython.com/python-mutable-vs-immutable-types/ +# +# The TLDR of that page is: +# 1) It's poor practice to try to change any global scope variables inside a function +# 2) Variable types that are "mutable" (link above) can be altered in subroutines/functions +# 3) Variable types that are "immutable" (link above) CANNOT be altered in subs/functions \ No newline at end of file From 3ace82b6a7bd668c03b76e5255429418000800a5 Mon Sep 17 00:00:00 2001 From: Junior Date: Wed, 19 Jun 2024 08:45:48 -0400 Subject: [PATCH 2/2] Add a pygame sprite example --- PyGame/Basics/020_sprite.py | 135 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 PyGame/Basics/020_sprite.py diff --git a/PyGame/Basics/020_sprite.py b/PyGame/Basics/020_sprite.py new file mode 100644 index 0000000..e3f994c --- /dev/null +++ b/PyGame/Basics/020_sprite.py @@ -0,0 +1,135 @@ +import os +os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" +import pygame +import random +import sys + +pygame.init() + +# Some variables used to initialize the window +# These are in all caps to indicate they are global +# constants and should not ever be changed programatically +# - The width and height are in pixels +# - The colors are (Red, Green, Blue) tuples +WIN_WIDTH = 600 +WIN_HEIGHT = 480 +WIN_BG_COLOR = (26, 110, 43) +TEXT_COLOR = (242, 238, 10) +PIXEBOY_200 = pygame.font.Font(os.path.join("font", "Pixeboy.ttf"), 200) +PIXEBOY_20 = pygame.font.Font(os.path.join("font", "Pixeboy.ttf"), 20) +SPRITE_STEP_SIZE = 3 + +# The object class for our sprite (inherits from pygame.sprite.Sprite) +class Sprite(pygame.sprite.Sprite): + def __init__(self, image: pygame.Surface, start_x: int, start_y: int): + super().__init__() + self.image = image + self.next_x = 1 + self.next_y = 1 + self.rect = self.image.get_rect() + self.rect.x = start_x + self.rect.y = start_y + + def move(self): + self.rect.x += self.next_x * SPRITE_STEP_SIZE + if (self.rect.x + self.image.get_width()) > WIN_WIDTH: + self.rect.x = WIN_WIDTH - self.image.get_width() + self.next_x = -1 + elif self.rect.x < 0: + self.rect.x = 0 + self.next_x = 1 + self.rect.y += self.next_y * SPRITE_STEP_SIZE + if (self.rect.y + self.image.get_height()) > WIN_HEIGHT: + self.rect.y = WIN_HEIGHT - self.image.get_height() + self.next_y = -1 + elif self.rect.y < 0: + self.rect.y = 0 + self.next_y = 1 + + def collidepoint(self, p_x: int, p_y: int): + if self.rect.collidepoint(p_x, p_y): + return True + else: + return False + +def draw_background(): + window.fill(WIN_BG_COLOR) + title_text_1 = PIXEBOY_200.render("HELLO", True, TEXT_COLOR) + title_text_2 = PIXEBOY_200.render("WORLD", True, TEXT_COLOR) + text_x = (WIN_WIDTH // 2) - (title_text_1.get_width() // 2) + text_y = 25 + window.blit(title_text_1, (text_x, text_y)) + 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)) + click_text = PIXEBOY_20.render("Click The Deuce", 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)) + +window = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) +pygame.display.set_caption('PyGame Sprites') +icon = pygame.image.load(os.path.join("img", "melon_icon_64.png")) +icon.convert_alpha() +pygame.display.set_icon(icon) + +# 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_start_x = (WIN_WIDTH // 2) - (emoji.get_width() // 2) +emoji_start_y = WIN_HEIGHT - 25 - emoji.get_height() +draw_background() + +all_sprites = pygame.sprite.Group() +deuce_sprite = Sprite(emoji, emoji_start_x, emoji_start_y) +all_sprites.add(deuce_sprite) + +# We can import audio files with mixer.Sound() +# Only .ogg (Ogg Vorbis) format files should be used +# The audio program Audacity can be used to convert files to .ogg +# Here we will import several and put them in a list +audio = [] +audio.append(pygame.mixer.Sound(os.path.join("snd", "toot.ogg"))) +audio.append(pygame.mixer.Sound(os.path.join("snd", "toot_echo.ogg"))) +audio.append(pygame.mixer.Sound(os.path.join("snd", "toot_trip.ogg"))) +audio.append(pygame.mixer.Sound(os.path.join("snd", "toot_wet.ogg"))) +clock = pygame.time.Clock() + +# Some run-time variables handling the state of the program +running = True +emoji_hover = False +# The main loop. This while loop runs until "running" is False +while running is True: + # We'll get the current mouse cursor position + mouse_x, mouse_y = pygame.mouse.get_pos() + # If the rectangle bounding the emoji is currently + # colliding with the current mouse cursor position + # Then change cursor + if deuce_sprite.collidepoint(mouse_x, mouse_y): + pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_HAND) + emoji_hover = True + else: + pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_ARROW) + emoji_hover = False + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + # pygame.MOUSEBUTTONDOWN happens the moment a mouse button is clicked + if event.type == pygame.MOUSEBUTTONDOWN and emoji_hover is True: + audio[random.randrange(0, len(audio))].play() + # pygame.KEYDOWN happens the moment a key is pressed down + if event.type == pygame.KEYDOWN: + # If the pressed key is "ESC" button, then let's exit + if event.key == pygame.K_ESCAPE: + running = False + draw_background() + all_sprites.draw(window) + pygame.display.flip() + deuce_sprite.move() + clock.tick(60) + +# We get to this poince once "running" is False. +# Clean up pygame with the quit() method, then exit program. +pygame.quit() +sys.exit() \ No newline at end of file