From 58a394f05aed503473b9dec3095c5203d64c45cb Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 10 Jan 2023 22:24:51 -0700 Subject: [PATCH 01/31] Work on lab 1 --- Lab 01 - First Program/lab_01.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lab 01 - First Program/lab_01.py b/Lab 01 - First Program/lab_01.py index e69de29bb..30d74d258 100644 --- a/Lab 01 - First Program/lab_01.py +++ b/Lab 01 - First Program/lab_01.py @@ -0,0 +1 @@ +test \ No newline at end of file From b1154010c06a82dcffc71b392c994e194a1589fa Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Thu, 12 Jan 2023 18:42:30 -0700 Subject: [PATCH 02/31] First attempt lab 1 -rm --- Lab 01 - First Program/lab_01.py | 15 ++++++++++++++- Testing/test.py | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Lab 01 - First Program/lab_01.py b/Lab 01 - First Program/lab_01.py index 30d74d258..51d795e84 100644 --- a/Lab 01 - First Program/lab_01.py +++ b/Lab 01 - First Program/lab_01.py @@ -1 +1,14 @@ -test \ No newline at end of file +firstName = str("Rob") +lastName = str('Mixon') +age = int(30) +# cant use backticks for string interpolation +print(type(firstName)) +print(type(age)) +print(f'Hello, my name is {firstName} {lastName}.') +print(f'"I am \n {age} \n years \n old"') +print("""I really + wish + that I + could use backticks....""") +print('Where are the semicolons????') + diff --git a/Testing/test.py b/Testing/test.py index e69de29bb..a1422d8d2 100644 --- a/Testing/test.py +++ b/Testing/test.py @@ -0,0 +1,2 @@ +print("It was a dark and stormy night.") +print("Suddenly a shot rang out!") \ No newline at end of file From 5a8d7ed843700fa1db8ded5ffba505ec1151d4b5 Mon Sep 17 00:00:00 2001 From: Rob Mixon <61328315+RobMixon@users.noreply.github.com> Date: Fri, 13 Jan 2023 14:34:35 -0700 Subject: [PATCH 03/31] Update lab_01.py --- Lab 01 - First Program/lab_01.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lab 01 - First Program/lab_01.py b/Lab 01 - First Program/lab_01.py index 51d795e84..4fa353956 100644 --- a/Lab 01 - First Program/lab_01.py +++ b/Lab 01 - First Program/lab_01.py @@ -5,7 +5,7 @@ print(type(firstName)) print(type(age)) print(f'Hello, my name is {firstName} {lastName}.') -print(f'"I am \n {age} \n years \n old"') +print(f'"I am \n {age} \n years \n old."') print("""I really wish that I From c87bc5b9276f568c50588114876e125ef22c9ab8 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Mon, 16 Jan 2023 13:39:40 -0700 Subject: [PATCH 04/31] added scratch work folder --- Scratch Work/drawing_samples.py | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Scratch Work/drawing_samples.py diff --git a/Scratch Work/drawing_samples.py b/Scratch Work/drawing_samples.py new file mode 100644 index 000000000..9a58a873c --- /dev/null +++ b/Scratch Work/drawing_samples.py @@ -0,0 +1,82 @@ +"""" +This is a sample program to show how to draw using the Python programming +language and the Arcade library. +""" + +# Import the "arcade" library +import arcade + +# Open up a window. +# From the "arcade" library, use a function called "open_window" +# Set the window title to "Drawing Example" +# Set the dimensions (width and height) +arcade.open_window(600, 600, "Drawing Example") + +# Set the background color +arcade.set_background_color(arcade.csscolor.SKY_BLUE) + +# Get ready to draw +arcade.start_render() + +# Draw a rectangle +# Left of 0, right of 599 +# Top of 300, bottom of 0 +arcade.draw_lrtb_rectangle_filled(0, 599, 300, 0, arcade.csscolor.GREEN) + +# Tree trunk +arcade.draw_rectangle_filled(100, 320, 20, 60, arcade.csscolor.SIENNA) + +# Tree top +arcade.draw_circle_filled(100, 350, 30, arcade.csscolor.DARK_GREEN) + +# Another tree, with a trunk and ellipse for top +arcade.draw_rectangle_filled(200, 320, 20, 60, arcade.csscolor.SIENNA) +arcade.draw_ellipse_filled(200, 370, 60, 80, arcade.csscolor.DARK_GREEN) + +# Another tree, with a trunk and arc for top +# Arc is centered at (300, 340) with a width of 60 and height of 100. +# The starting angle is 0, and ending angle is 180. +arcade.draw_rectangle_filled(300, 320, 20, 60, arcade.csscolor.SIENNA) +arcade.draw_arc_filled(300, 340, 60, 100, arcade.csscolor.DARK_GREEN, 0, 180) + +# Another tree, with a trunk and triangle for top +# Triangle is made of these three points: +# (400, 400), (370, 320), (430, 320) +arcade.draw_rectangle_filled(400, 320, 20, 60, arcade.csscolor.SIENNA) +arcade.draw_triangle_filled(400, 400, 370, 320, 430, 320, arcade.csscolor.DARK_GREEN) + +# Draw a tree using a polygon with a list of points +arcade.draw_rectangle_filled(500, 320, 20, 60, arcade.csscolor.SIENNA) +arcade.draw_polygon_filled(((500, 400), + (480, 360), + (470, 320), + (530, 320), + (520, 360) + ), + arcade.csscolor.DARK_GREEN) + +# Draw a sun +arcade.draw_circle_filled(500, 550, 40, arcade.color.YELLOW) + +# Rays to the left, right, up, and down +arcade.draw_line(500, 550, 400, 550, arcade.color.YELLOW, 3) +arcade.draw_line(500, 550, 600, 550, arcade.color.YELLOW, 3) +arcade.draw_line(500, 550, 500, 450, arcade.color.YELLOW, 3) +arcade.draw_line(500, 550, 500, 650, arcade.color.YELLOW, 3) + +# Diagonal rays +arcade.draw_line(500, 550, 550, 600, arcade.color.YELLOW, 3) +arcade.draw_line(500, 550, 550, 500, arcade.color.YELLOW, 3) +arcade.draw_line(500, 550, 450, 600, arcade.color.YELLOW, 3) +arcade.draw_line(500, 550, 450, 500, arcade.color.YELLOW, 3) + +# Draw text at (150, 230) with a font size of 24 pts. +arcade.draw_text("Arbor Day - Plant a Tree!", + 150, 230, + arcade.color.BLACK, 24) + +# Finish drawing +arcade.finish_render() + +# Keep the window up until someone closes it. +arcade.run() \ No newline at end of file From 84433595e11461d430dc7ea313cf5131b09b3f6f Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Mon, 16 Jan 2023 17:13:30 -0700 Subject: [PATCH 05/31] building a house --- Lab 02 - Draw a Picture/lab_02.py | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Lab 02 - Draw a Picture/lab_02.py b/Lab 02 - Draw a Picture/lab_02.py index e69de29bb..fc5143795 100644 --- a/Lab 02 - Draw a Picture/lab_02.py +++ b/Lab 02 - Draw a Picture/lab_02.py @@ -0,0 +1,51 @@ +import arcade + +arcade.open_window(800, 800, "landscape") + +#background color +arcade.set_background_color((27, 27, 27)) + +arcade.start_render() + + + +#Ground +arcade.draw_lrtb_rectangle_filled(0, 799, 300, 0, (26, 36, 33)) + +#House +arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.JET) + +#Chimney +arcade.draw_lrtb_rectangle_filled(600, 650, 625, 500, (20, 20, 20)) + +#Roof +arcade.draw_triangle_filled(300, 500, 500, 600, 700, 500, (43, 43, 43)) + +#Door +arcade.draw_lrtb_rectangle_filled(600, 650, 350, 250, arcade.color.DARK_BROWN) +#Door Handle +arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) +#Door Window + +#arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.YELLOW) + +#Window at Ground Level +arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK) +#Upper Windows +arcade.draw_rectangle_outline(420, 450, 60, 60, arcade.color.BLACK) +arcade.draw_rectangle_outline(625, 450, 60, 60, arcade.color.BLACK) + +#Light From House +#arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.YELLOW) + +#moon +arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) +arcade.draw_circle_filled(120, 650, 40, (27, 27, 27)) + +#Shooting Star + +# Finish drawing +arcade.finish_render() + +# Keep the window up until someone closes it. +arcade.run() \ No newline at end of file From 18253ec4cc177caed59a1278ada736e23228bb87 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Mon, 16 Jan 2023 17:51:29 -0700 Subject: [PATCH 06/31] finish drawing rm --- Lab 02 - Draw a Picture/lab_02.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Lab 02 - Draw a Picture/lab_02.py b/Lab 02 - Draw a Picture/lab_02.py index fc5143795..77afef3e0 100644 --- a/Lab 02 - Draw a Picture/lab_02.py +++ b/Lab 02 - Draw a Picture/lab_02.py @@ -7,8 +7,7 @@ arcade.start_render() - - +#Start Drawing #Ground arcade.draw_lrtb_rectangle_filled(0, 799, 300, 0, (26, 36, 33)) @@ -23,26 +22,36 @@ #Door arcade.draw_lrtb_rectangle_filled(600, 650, 350, 250, arcade.color.DARK_BROWN) + #Door Handle -arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) -#Door Window +arcade.draw_circle_filled(610, 290, 3, arcade.color.BLACK) -#arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.YELLOW) +#Door Window +arcade.draw_ellipse_outline(625, 320, 30, 50, arcade.color.BLACK) #Window at Ground Level -arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK) +arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK, 2) + #Upper Windows -arcade.draw_rectangle_outline(420, 450, 60, 60, arcade.color.BLACK) -arcade.draw_rectangle_outline(625, 450, 60, 60, arcade.color.BLACK) +arcade.draw_rectangle_outline(420, 450, 60, 60, arcade.color.BLACK, 2) +arcade.draw_rectangle_outline(625, 450, 60, 60, arcade.color.BLACK, 2) #Light From House -#arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.YELLOW) +arcade.draw_ellipse_filled(625, 320, 28, 48, arcade.color.DARK_YELLOW) +arcade.draw_rectangle_filled(420, 320, 123, 48, arcade.color.DARK_YELLOW) +arcade.draw_rectangle_filled(420, 450, 58, 58, arcade.color.DARK_YELLOW) +arcade.draw_rectangle_filled(625, 450, 58, 58, arcade.color.DARK_YELLOW) #moon arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) arcade.draw_circle_filled(120, 650, 40, (27, 27, 27)) -#Shooting Star +#stars +point_list = ((165, 495), (200, 760), (250, 700), (270, 650), (400, 670), + (450, 780), (490, 620), (510, 730), (525, 700), (560, 630), + (600, 760), (610, 690), (650, 650), (690, 730), (700, 700), + (724, 665), (740, 615), (770, 720), (775, 705), (180, 770)) +arcade.draw_points(point_list, arcade.color.GHOST_WHITE, 2) # Finish drawing arcade.finish_render() From 72cba11fa1f04ad0997bbfd8ab569996f6978119 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 17 Jan 2023 09:17:14 -0700 Subject: [PATCH 07/31] added lines to windows --- Lab 02 - Draw a Picture/lab_02.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Lab 02 - Draw a Picture/lab_02.py b/Lab 02 - Draw a Picture/lab_02.py index 77afef3e0..415c38673 100644 --- a/Lab 02 - Draw a Picture/lab_02.py +++ b/Lab 02 - Draw a Picture/lab_02.py @@ -29,18 +29,20 @@ #Door Window arcade.draw_ellipse_outline(625, 320, 30, 50, arcade.color.BLACK) +#Light From House +arcade.draw_ellipse_filled(625, 320, 28, 48, arcade.color.DARK_YELLOW) +arcade.draw_rectangle_filled(420, 320, 123, 48, arcade.color.DARK_YELLOW) +arcade.draw_rectangle_filled(420, 450, 58, 58, arcade.color.DARK_YELLOW) +arcade.draw_rectangle_filled(625, 450, 58, 58, arcade.color.DARK_YELLOW) + #Window at Ground Level arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK, 2) #Upper Windows arcade.draw_rectangle_outline(420, 450, 60, 60, arcade.color.BLACK, 2) arcade.draw_rectangle_outline(625, 450, 60, 60, arcade.color.BLACK, 2) - -#Light From House -arcade.draw_ellipse_filled(625, 320, 28, 48, arcade.color.DARK_YELLOW) -arcade.draw_rectangle_filled(420, 320, 123, 48, arcade.color.DARK_YELLOW) -arcade.draw_rectangle_filled(420, 450, 58, 58, arcade.color.DARK_YELLOW) -arcade.draw_rectangle_filled(625, 450, 58, 58, arcade.color.DARK_YELLOW) +arcade.draw_line(390, 450, 450, 450, arcade.color.BLACK, 2) +arcade.draw_line(595, 450, 655, 450, arcade.color.BLACK, 2) #moon arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) From 136a575e445db08f22858c3d88b7a48e6b6ba13d Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Thu, 26 Jan 2023 18:01:55 -0700 Subject: [PATCH 08/31] slowly working on this --- Lab 03 - Draw Using Functions/lab_03.py | 77 +++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Lab 03 - Draw Using Functions/lab_03.py b/Lab 03 - Draw Using Functions/lab_03.py index e69de29bb..73ea82943 100644 --- a/Lab 03 - Draw Using Functions/lab_03.py +++ b/Lab 03 - Draw Using Functions/lab_03.py @@ -0,0 +1,77 @@ +import arcade +from arcade.examples.sprite_explosion_particles import PARTICLE_FADE_RATE + +Screen_Width = 800 +Screen_Height = 800 +point_list = ((165, 495), (200, 760), (250, 700), (270, 650), (400, 670), + (450, 780), (490, 620), (510, 730), (525, 700), (560, 630), + (600, 760), (610, 690), (650, 650), (690, 730), (700, 700), + (724, 665), (740, 615), (770, 720), (775, 705), (180, 770)) + +def draw_light_from_house(): + arcade.draw_ellipse_filled(625, 320, 28, 48, arcade.color.DARK_YELLOW) + arcade.draw_rectangle_filled(420, 320, 123, 48, arcade.color.DARK_YELLOW) + arcade.draw_rectangle_filled(420, 450, 58, 58, arcade.color.DARK_YELLOW) + arcade.draw_rectangle_filled(625, 450, 58, 58, arcade.color.DARK_YELLOW) + +def draw_upper_windows(): + arcade.draw_rectangle_outline(420, 450, 60, 60, arcade.color.BLACK, 2) + arcade.draw_rectangle_outline(625, 450, 60, 60, arcade.color.BLACK, 2) + arcade.draw_line(390, 450, 450, 450, arcade.color.BLACK, 2) + arcade.draw_line(595, 450, 655, 450, arcade.color.BLACK, 2) + +def stars(): + arcade.draw_points(point_list, arcade.color.GHOST_WHITE, 2) + +def moon(): + arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) + arcade.draw_circle_filled(120, 650, 40, (27, 27, 27)) + +def main(): + arcade.open_window(Screen_Width, Screen_Height, "landscape") + + # background color + arcade.set_background_color((27, 27, 27)) + + arcade.start_render() + + # Start Drawing + stars() + + # Ground + arcade.draw_lrtb_rectangle_filled(0, 799, 300, 0, (26, 36, 33)) + + # House + arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.JET) + + # Chimney + arcade.draw_lrtb_rectangle_filled(600, 650, 625, 500, (20, 20, 20)) + + # Roof + arcade.draw_triangle_filled(300, 500, 500, 600, 700, 500, (43, 43, 43)) + + # Door + arcade.draw_lrtb_rectangle_filled(600, 650, 350, 250, arcade.color.DARK_BROWN) + + # Door Handle + arcade.draw_circle_filled(610, 290, 3, arcade.color.BLACK) + + # Door Window + arcade.draw_ellipse_outline(625, 320, 30, 50, arcade.color.BLACK) + + # Window at Ground Level + arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK, 2) + + draw_light_from_house() + draw_upper_windows() + moon() + + # Finish drawing + arcade.finish_render() + + # Keep the window up until someone closes it. + arcade.run() + + +# calling the main function +main() From 65e8c81926c27d161bf9db7b88b3178f6d451fde Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Wed, 1 Feb 2023 16:48:48 -0700 Subject: [PATCH 09/31] finished lab 3 --- Lab 03 - Draw Using Functions/lab_03.py | 81 ++++++++++++++----------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/Lab 03 - Draw Using Functions/lab_03.py b/Lab 03 - Draw Using Functions/lab_03.py index 73ea82943..26dc5df71 100644 --- a/Lab 03 - Draw Using Functions/lab_03.py +++ b/Lab 03 - Draw Using Functions/lab_03.py @@ -1,32 +1,46 @@ import arcade +import random from arcade.examples.sprite_explosion_particles import PARTICLE_FADE_RATE -Screen_Width = 800 +Screen_Width = 1000 Screen_Height = 800 -point_list = ((165, 495), (200, 760), (250, 700), (270, 650), (400, 670), - (450, 780), (490, 620), (510, 730), (525, 700), (560, 630), - (600, 760), (610, 690), (650, 650), (690, 730), (700, 700), - (724, 665), (740, 615), (770, 720), (775, 705), (180, 770)) +star_coordinate_list = [] def draw_light_from_house(): arcade.draw_ellipse_filled(625, 320, 28, 48, arcade.color.DARK_YELLOW) arcade.draw_rectangle_filled(420, 320, 123, 48, arcade.color.DARK_YELLOW) - arcade.draw_rectangle_filled(420, 450, 58, 58, arcade.color.DARK_YELLOW) - arcade.draw_rectangle_filled(625, 450, 58, 58, arcade.color.DARK_YELLOW) -def draw_upper_windows(): - arcade.draw_rectangle_outline(420, 450, 60, 60, arcade.color.BLACK, 2) - arcade.draw_rectangle_outline(625, 450, 60, 60, arcade.color.BLACK, 2) - arcade.draw_line(390, 450, 450, 450, arcade.color.BLACK, 2) - arcade.draw_line(595, 450, 655, 450, arcade.color.BLACK, 2) +def draw_upper_windows(x, y): + arcade.draw_rectangle_filled(x, y, 58, 58, arcade.color.DARK_YELLOW) + arcade.draw_rectangle_outline(x, y, 60, 60, arcade.color.BLACK, 2) + arcade.draw_line(x - 30, y, x + 30, y, arcade.color.BLACK, 2) + arcade.draw_line(x, y - 30, x, y + 30, arcade.color.BLACK, 2) -def stars(): +def draw_house(): + arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.JET) + arcade.draw_lrtb_rectangle_filled(600, 650, 625, 500, (20, 20, 20)) + arcade.draw_triangle_filled(300, 500, 500, 600, 700, 500, (43, 43, 43)) + arcade.draw_lrtb_rectangle_filled(600, 650, 350, 250, arcade.color.DARK_BROWN) + arcade.draw_circle_filled(610, 290, 3, arcade.color.BLACK) + arcade.draw_ellipse_outline(625, 320, 30, 50, arcade.color.BLACK) + arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK, 2) + +def stars(point_list): arcade.draw_points(point_list, arcade.color.GHOST_WHITE, 2) def moon(): arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) arcade.draw_circle_filled(120, 650, 40, (27, 27, 27)) +def ground(): + arcade.draw_lrtb_rectangle_filled(0, 999, 300, 0, (26, 36, 33)) + +def tree(x, y): + arcade.draw_rectangle_filled(x, y, 30, 60, (69, 41, 19)) + arcade.draw_triangle_filled(x - 30, y + 30, x, y + 70, x + 30, y + 30, arcade.color.DARK_GREEN) + arcade.draw_triangle_filled(x - 30, y + 60, x, y + 100, x + 30, y + 60, arcade.color.DARK_GREEN) + arcade.draw_triangle_filled(x - 30, y + 90, x, y + 130, x + 30, y + 90, arcade.color.DARK_GREEN) + def main(): arcade.open_window(Screen_Width, Screen_Height, "landscape") @@ -36,42 +50,35 @@ def main(): arcade.start_render() # Start Drawing - stars() - - # Ground - arcade.draw_lrtb_rectangle_filled(0, 799, 300, 0, (26, 36, 33)) - - # House - arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.JET) - - # Chimney - arcade.draw_lrtb_rectangle_filled(600, 650, 625, 500, (20, 20, 20)) + ground() - # Roof - arcade.draw_triangle_filled(300, 500, 500, 600, 700, 500, (43, 43, 43)) + for x in range(0, 100): + x_stars = random.randint(0, 1000) + y_stars = random.randint(400, 800) + x_and_y_object = (x_stars, y_stars) + star_coordinate_list.append(x_and_y_object) - # Door - arcade.draw_lrtb_rectangle_filled(600, 650, 350, 250, arcade.color.DARK_BROWN) - - # Door Handle - arcade.draw_circle_filled(610, 290, 3, arcade.color.BLACK) + stars(star_coordinate_list) - # Door Window - arcade.draw_ellipse_outline(625, 320, 30, 50, arcade.color.BLACK) - - # Window at Ground Level - arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK, 2) + # House + draw_house() draw_light_from_house() - draw_upper_windows() + draw_upper_windows(390, 450) + draw_upper_windows(505, 450) + draw_upper_windows(620, 450) moon() + tree(50, 290) + tree(120, 290) + tree(850, 290) + tree(920, 290) + # Finish drawing arcade.finish_render() # Keep the window up until someone closes it. arcade.run() - # calling the main function main() From ec077ebe753fd5ece8229b67b5dc66e0b7343ba6 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Wed, 1 Feb 2023 16:56:32 -0700 Subject: [PATCH 10/31] added another function to be sure --- Lab 03 - Draw Using Functions/lab_03.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lab 03 - Draw Using Functions/lab_03.py b/Lab 03 - Draw Using Functions/lab_03.py index 26dc5df71..7fd9b3603 100644 --- a/Lab 03 - Draw Using Functions/lab_03.py +++ b/Lab 03 - Draw Using Functions/lab_03.py @@ -28,9 +28,9 @@ def draw_house(): def stars(point_list): arcade.draw_points(point_list, arcade.color.GHOST_WHITE, 2) -def moon(): - arcade.draw_circle_filled(100, 650, 50, arcade.color.GHOST_WHITE) - arcade.draw_circle_filled(120, 650, 40, (27, 27, 27)) +def moon(x, y): + arcade.draw_circle_filled(x, y, 50, arcade.color.GHOST_WHITE) + arcade.draw_circle_filled(x + 20, y, 40, (27, 27, 27)) def ground(): arcade.draw_lrtb_rectangle_filled(0, 999, 300, 0, (26, 36, 33)) @@ -67,7 +67,7 @@ def main(): draw_upper_windows(390, 450) draw_upper_windows(505, 450) draw_upper_windows(620, 450) - moon() + moon(100, 650) tree(50, 290) tree(120, 290) From 38b37c6f276f49d7b0f84cc36d3b2a137d41e92d Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 7 Feb 2023 13:40:04 -0700 Subject: [PATCH 11/31] basic structure built --- Lab 04 - Camel/lab_04.py | 106 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/Lab 04 - Camel/lab_04.py b/Lab 04 - Camel/lab_04.py index e69de29bb..9488c0d37 100644 --- a/Lab 04 - Camel/lab_04.py +++ b/Lab 04 - Camel/lab_04.py @@ -0,0 +1,106 @@ +# import statements +import random + + +# natives move up function +def natives_move_up(): return random.randrange(0, 14) + + +# full speed function +def full_speed(): return random.randrange(10, 20) + + +# moderate speed function +def moderate_speed(): return random.randrange(5, 12) + + +# defining main function +def main(): + + #variables + done = False + miles_traveled = 0 + thirst = 0 + camel_tiredness = 0 + natives_traveled = -20 + drink = 3 + + print(natives_move_up()) + + # Initial statement + print("Welcome to Camel!") + print("You have stolen a camel to make your way across the great Mobi desert.") + print("The natives want their camel back and are chasing you down! Survive your") + print("desert trek and out run the natives.") + + # starting while loop + while not done: + print("A. Drink from your canteen.") + print("B. Ahead moderate speed.") + print("C. Ahead full speed.") + print("D. Stop for the night.") + print("E. Status check.") + print("Q. Quit.") + print("") + user_choice = input("What is your choice? ") + print("") + + # quit statement + if user_choice.upper() == "Q": + print("Y: yes") + print("N: no") + print("") + user_quit_choice = input("What is your choice? ") + + # quit check + if user_quit_choice.upper() == "Y": + print("You have excited the game") + done = True + + # status_check + elif user_choice == "e": + print("Miles traveled:", miles_traveled) + print("Drinks left in canteen:", drink) + print("The natives are", miles_traveled - natives_traveled, "miles behind you!") + print("") + + # stop_for_the_night + elif user_choice == "d": + camel_tiredness = 0 + natives_traveled = natives_traveled + natives_move_up() + print("The camel is happy! The natives move up", natives_traveled, "miles.") + print("") + + # full_speed + elif user_choice == "c": + print("You have traveled", full_speed, "miles.") + miles_traveled = miles_traveled + full_speed + natives_traveled = natives_traveled + natives_move_up + thirst = thirst + 1 + camel_tiredness = random.randrange(1, 3) + print("camel tiredness:", camel_tiredness) + print("The natives move up", natives_move_up, "miles.") + print("") + + # moderate_speed + elif user_choice == "b": + print("you have traveled %d miles" % (moderate_speed,)) + miles_traveled += full_speed + natives_traveled += natives_move_up + thirst += 1 + camel_tired = camel_tired + random.randrange(1, 3) + print("camel tiredness %d" % (camel_tired,)) + print("move the natives up to %d miles" % (natives_move_up,)) + print("") + + # drink_to_canteen + elif user_choice == "a": + print("you drink from your canteen") + drink = drink - 1 + thirst = 0 + print("") + + print(natives_move_up) + +# calling the main function +main() From 565f0cb78cb48a49767d57ac07c233de7850d5d3 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 7 Feb 2023 15:13:15 -0700 Subject: [PATCH 12/31] finished tweaking game --- Lab 04 - Camel/lab_04.py | 158 +++++++++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 40 deletions(-) diff --git a/Lab 04 - Camel/lab_04.py b/Lab 04 - Camel/lab_04.py index 9488c0d37..903e6023b 100644 --- a/Lab 04 - Camel/lab_04.py +++ b/Lab 04 - Camel/lab_04.py @@ -14,24 +14,31 @@ def full_speed(): return random.randrange(10, 20) def moderate_speed(): return random.randrange(5, 12) +# camel tiredness function +def camel_tiredness_function(): return random.randrange(1, 3) + + +# oasis chance function +def oasis_chance(): return random.randrange(1, 20) + + # defining main function def main(): - - #variables + # variables done = False - miles_traveled = 0 + miles_traveled = 190 thirst = 0 camel_tiredness = 0 natives_traveled = -20 - drink = 3 - - print(natives_move_up()) + canteen = 3 + oasis = random.randrange(1, 20) # Initial statement print("Welcome to Camel!") print("You have stolen a camel to make your way across the great Mobi desert.") print("The natives want their camel back and are chasing you down! Survive your") print("desert trek and out run the natives.") + print("") # starting while loop while not done: @@ -47,60 +54,131 @@ def main(): # quit statement if user_choice.upper() == "Q": - print("Y: yes") - print("N: no") + print("Y: Yes") + print("N: No") print("") user_quit_choice = input("What is your choice? ") # quit check if user_quit_choice.upper() == "Y": - print("You have excited the game") + print("You have exited the game") done = True - # status_check - elif user_choice == "e": + # status check + elif user_choice.upper() == "E": print("Miles traveled:", miles_traveled) - print("Drinks left in canteen:", drink) + print("Drinks left in canteen:", canteen) print("The natives are", miles_traveled - natives_traveled, "miles behind you!") print("") - # stop_for_the_night - elif user_choice == "d": + # stop for the night + elif user_choice.upper() == "D": camel_tiredness = 0 - natives_traveled = natives_traveled + natives_move_up() - print("The camel is happy! The natives move up", natives_traveled, "miles.") + natives_move = natives_move_up() + natives_traveled = natives_traveled + natives_move + print("The camel is happy! The natives move up", natives_move, "miles.") print("") - # full_speed - elif user_choice == "c": - print("You have traveled", full_speed, "miles.") - miles_traveled = miles_traveled + full_speed - natives_traveled = natives_traveled + natives_move_up + # full speed + elif user_choice.upper() == "C": + full_speed_user = full_speed() + full_speed_natives = natives_move_up() + miles_traveled = miles_traveled + full_speed_user + natives_traveled = natives_traveled + full_speed_natives + camel_tiredness = camel_tiredness + camel_tiredness_function() + thirst = thirst + 1 + full_speed_oasis = oasis_chance() + print("You have traveled", full_speed_user, "miles.") + print("Camel tiredness:", camel_tiredness) + print("The natives move up", full_speed_natives, "miles.") + if oasis == full_speed_oasis: + canteen = 3 + thirst = 0 + camel_tiredness = 0 + print("You found an oasis!") + print("Drinks left in canteen:", canteen) + print("Thirst:", thirst) + print("Camel tiredness:", camel_tiredness) + print("") + else: + print("") + + # moderate speed + elif user_choice.upper() == "B": + moderate_speed_user = moderate_speed() + moderate_speed_natives = natives_move_up() + miles_traveled = miles_traveled + moderate_speed_user + natives_traveled = natives_traveled + moderate_speed_natives + camel_tiredness = camel_tiredness + 1 thirst = thirst + 1 - camel_tiredness = random.randrange(1, 3) - print("camel tiredness:", camel_tiredness) - print("The natives move up", natives_move_up, "miles.") + moderate_speed_oasis = oasis_chance() + print("You have traveled", moderate_speed_user, "miles.") + print("Camel tiredness:", camel_tiredness) + print("The natives move up", moderate_speed_natives, "miles.") + if oasis == moderate_speed_oasis: + canteen = 3 + thirst = 0 + camel_tiredness = 0 + print("You found an oasis!") + print("Drinks left in canteen:", canteen) + print("Thirst:", thirst) + print("Camel tiredness:", camel_tiredness) + print("") + else: + print("") + + # Drink from canteen + elif user_choice.upper() == "A": + if canteen != 0: + print("You take a drink from your canteen.") + canteen = canteen - 1 + thirst = 0 + print("") + else: + print("You have no more water!") + print("") + + # you are thirsty + if 4 <= thirst < 6: + print("You are thirsty!") print("") - # moderate_speed - elif user_choice == "b": - print("you have traveled %d miles" % (moderate_speed,)) - miles_traveled += full_speed - natives_traveled += natives_move_up - thirst += 1 - camel_tired = camel_tired + random.randrange(1, 3) - print("camel tiredness %d" % (camel_tired,)) - print("move the natives up to %d miles" % (natives_move_up,)) + # you died of thirst + elif thirst >= 6: + print("You died of thirsty!") print("") + done = True + + if not done: + # your camel is getting tired + if 5 <= camel_tiredness < 8: + print("Your camel is getting tired.") + print("") + + # your camel is dead + elif camel_tiredness >= 8: + print("Your camel is dead.") + print("") + done = True - # drink_to_canteen - elif user_choice == "a": - print("you drink from your canteen") - drink = drink - 1 - thirst = 0 - print("") + if not done: + # if the natives have caught up + if natives_traveled >= miles_traveled: + print("The natives have caught you.") + print("") + done = True + + # the natives are getting close + elif natives_traveled >= miles_traveled - 10: + print("The natives are getting close!") + print("") + + if not done: + if miles_traveled >= 200: + print("You won and got the camel across the desert! Congrats on being alive!") + print("") + done = True - print(natives_move_up) # calling the main function main() From 2eb3e6f114cc5f807420c8a4e5d52c7ee9fb75f3 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 7 Feb 2023 15:14:52 -0700 Subject: [PATCH 13/31] cleaned up code --- Lab 04 - Camel/lab_04.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Lab 04 - Camel/lab_04.py b/Lab 04 - Camel/lab_04.py index 903e6023b..20431e20b 100644 --- a/Lab 04 - Camel/lab_04.py +++ b/Lab 04 - Camel/lab_04.py @@ -5,23 +5,18 @@ # natives move up function def natives_move_up(): return random.randrange(0, 14) - # full speed function def full_speed(): return random.randrange(10, 20) - # moderate speed function def moderate_speed(): return random.randrange(5, 12) - # camel tiredness function def camel_tiredness_function(): return random.randrange(1, 3) - # oasis chance function def oasis_chance(): return random.randrange(1, 20) - # defining main function def main(): # variables @@ -174,6 +169,7 @@ def main(): print("") if not done: + # winning statement if miles_traveled >= 200: print("You won and got the camel across the desert! Congrats on being alive!") print("") From fdfd387319ae0bf7b3370c71416925f362ff27a9 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Thu, 16 Feb 2023 09:01:58 -0700 Subject: [PATCH 14/31] square 1 done --- Lab 05 - Loopy Lab/lab_05.py | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/Lab 05 - Loopy Lab/lab_05.py b/Lab 05 - Loopy Lab/lab_05.py index e69de29bb..0d7ca08cd 100644 --- a/Lab 05 - Loopy Lab/lab_05.py +++ b/Lab 05 - Loopy Lab/lab_05.py @@ -0,0 +1,91 @@ +import arcade + + +def draw_section_outlines(): + # Draw squares on bottom + arcade.draw_rectangle_outline(150, 150, 300, 300, arcade.color.BLACK) + arcade.draw_rectangle_outline(450, 150, 300, 300, arcade.color.BLACK) + arcade.draw_rectangle_outline(750, 150, 300, 300, arcade.color.BLACK) + arcade.draw_rectangle_outline(1050, 150, 300, 300, arcade.color.BLACK) + + # Draw squares on top + arcade.draw_rectangle_outline(150, 450, 300, 300, arcade.color.BLACK) + arcade.draw_rectangle_outline(450, 450, 300, 300, arcade.color.BLACK) + arcade.draw_rectangle_outline(750, 450, 300, 300, arcade.color.BLACK) + arcade.draw_rectangle_outline(1050, 450, 300, 300, arcade.color.BLACK) + + +def draw_section_1(): + for row in range(30): + for column in range(30): + x = (row * 10) + 5 # Instead of zero, calculate the proper x location using 'column' + y = (column * 10) + 5 # Instead of zero, calculate the proper y location using 'row' + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) + +def draw_section_2(): + for row in range(30): + for column in range(30): + x = (row * 10) + 305 # Instead of zero, calculate the proper x location using 'column' + y = (column * 10) + 5 # Instead of zero, calculate the proper y location using 'row' + print(x, y) + if x: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) + else: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.BLACK) + + + +def draw_section_3(): + # Use the modulus operator and an if/else statement to select the color. + # Don't use multiple 'if' statements. + pass + + +def draw_section_4(): + # Use the modulus operator and just one 'if' statement to select the color. + pass + + +def draw_section_5(): + # Do NOT use 'if' statements to complete 5-8. Manipulate the loops instead. + pass + + +def draw_section_6(): + pass + + +def draw_section_7(): + pass + + +def draw_section_8(): + pass + + +def main(): + # Create a window + arcade.open_window(1200, 600, "Lab 05 - Loopy Lab") + arcade.set_background_color(arcade.color.AIR_FORCE_BLUE) + + arcade.start_render() + + # Draw the outlines for the sections + draw_section_outlines() + + # Draw the sections + draw_section_1() + draw_section_2() + draw_section_3() + draw_section_4() + draw_section_5() + draw_section_6() + draw_section_7() + draw_section_8() + + arcade.finish_render() + + arcade.run() + + +main() \ No newline at end of file From a912a6f2448bad5d29e5bf2cf144a364ae912b4b Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Fri, 17 Feb 2023 09:49:35 -0700 Subject: [PATCH 15/31] still working on 8 --- Lab 05 - Loopy Lab/lab_05.py | 66 +++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/Lab 05 - Loopy Lab/lab_05.py b/Lab 05 - Loopy Lab/lab_05.py index 0d7ca08cd..1187a245e 100644 --- a/Lab 05 - Loopy Lab/lab_05.py +++ b/Lab 05 - Loopy Lab/lab_05.py @@ -18,49 +18,75 @@ def draw_section_outlines(): def draw_section_1(): for row in range(30): for column in range(30): - x = (row * 10) + 5 # Instead of zero, calculate the proper x location using 'column' - y = (column * 10) + 5 # Instead of zero, calculate the proper y location using 'row' + x = (row * 10) + 5 + y = (column * 10) + 5 arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) + def draw_section_2(): for row in range(30): for column in range(30): - x = (row * 10) + 305 # Instead of zero, calculate the proper x location using 'column' - y = (column * 10) + 5 # Instead of zero, calculate the proper y location using 'row' - print(x, y) - if x: - arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) - else: + x = (row * 10) + 305 + y = (column * 10) + 5 + if (x - 5) % 20: arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.BLACK) - + else: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def draw_section_3(): - # Use the modulus operator and an if/else statement to select the color. - # Don't use multiple 'if' statements. - pass + for row in range(30): + for column in range(30): + x = (row * 10) + 605 + y = (column * 10) + 5 + if (y - 5) % 20: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.BLACK) + else: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def draw_section_4(): - # Use the modulus operator and just one 'if' statement to select the color. - pass + for row in range(30): + for column in range(30): + x = (row * 10) + 905 + y = (column * 10) + 5 + if (y - 5) % 20 | (x - 5) % 20: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.BLACK) + else: + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def draw_section_5(): - # Do NOT use 'if' statements to complete 5-8. Manipulate the loops instead. - pass + for row in range(30): + for column in range(row): + x = (row * 10) + 5 + y = (column * 10) + 305 + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def draw_section_6(): - pass + for row in range(30): + for column in range(30 - row): + x = (row * 10) + 305 + y = (column * 10) + 305 + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def draw_section_7(): - pass + for column in range(30): + for row in range(column + 1): + x = (row * 10) + 605 + y = (column * 10) + 305 + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def draw_section_8(): - pass + for row in range(30, -1, -1): + for column in range(row): + print(row, column) + x = (row * 10) + 905 + y = (column * 10) + 305 + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def main(): @@ -88,4 +114,4 @@ def main(): arcade.run() -main() \ No newline at end of file +main() From f9e929729b1f8ab9e2caae7c82b9664f1bdee81e Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Fri, 17 Feb 2023 11:18:08 -0700 Subject: [PATCH 16/31] cant figure out 8 --- Lab 05 - Loopy Lab/lab_05.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Lab 05 - Loopy Lab/lab_05.py b/Lab 05 - Loopy Lab/lab_05.py index 1187a245e..963908af5 100644 --- a/Lab 05 - Loopy Lab/lab_05.py +++ b/Lab 05 - Loopy Lab/lab_05.py @@ -81,12 +81,7 @@ def draw_section_7(): def draw_section_8(): - for row in range(30, -1, -1): - for column in range(row): - print(row, column) - x = (row * 10) + 905 - y = (column * 10) + 305 - arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) + pass def main(): From e3f12da301745362447076fba5290631b3077447 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Fri, 17 Feb 2023 11:30:17 -0700 Subject: [PATCH 17/31] finally figured out 8 --- Lab 05 - Loopy Lab/lab_05.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lab 05 - Loopy Lab/lab_05.py b/Lab 05 - Loopy Lab/lab_05.py index 963908af5..136fdc677 100644 --- a/Lab 05 - Loopy Lab/lab_05.py +++ b/Lab 05 - Loopy Lab/lab_05.py @@ -81,7 +81,11 @@ def draw_section_7(): def draw_section_8(): - pass + for column in range(32): + for row in range(32 - column): + x = (row * -10) + 1205 + y = (column * -10) + 605 + arcade.draw_rectangle_filled(x, y, 5, 5, arcade.color.WHITE) def main(): From a6f4f356824be84ecd105773293aaf9f18dae74d Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 28 Feb 2023 08:35:09 -0700 Subject: [PATCH 18/31] finished lab six --- Lab 06 - Text Adventure/lab_06.py | 272 ++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) diff --git a/Lab 06 - Text Adventure/lab_06.py b/Lab 06 - Text Adventure/lab_06.py index e69de29bb..1a824189b 100644 --- a/Lab 06 - Text Adventure/lab_06.py +++ b/Lab 06 - Text Adventure/lab_06.py @@ -0,0 +1,272 @@ +# Define a class called room and adding constructor function + + +class Room: + def __init__(self, description, north, south, east, west): + self.description = str(description) + self.north = north + self.south = south + self.east = east + self.west = west + + +# Defining the main function + + +def main(): + # Creating an empty array + room_list = [] + done = False + + # Creating rooms with attributes + + room0 = Room( + "It's dark. The only light is a candle on a desk next to a bed. To your east is a door. All other sides are " + "walls.", + None, None, 1, None) + room1 = Room( + "You have entered a long hallway with a chandelier above you. To your west you have a door to the dimly lit " + "bedroom. \nTo your east is what looks to be the dining room. The hallway continues north. There is an exit " + "to the south through a window.", + 4, None, 2, 0) + room2 = Room( + "You are in a dining room with a magnificent wooden table set for 12. You may go west to go back to the " + "hallway or \nnorth to go into the kitchen.", + 5, None, None, 1) + room3 = Room( + "You are in a brightly lit bedroom with two beds. There is a window to the north and west. To the south is" + " a wall. \nYou have a wooden door to the east.", + None, None, 4, None) + room4 = Room( + "You have entered the north side of the hallway. To the south is the rest of the hallway with a beautiful " + "chandelier. \nThere is a brightly lit bedroom to the west, a door to what seems to be the kitchen to your " + "east and a set of double \ndoors to the north.", + 6, 1, 5, 3) + room5 = Room( + "You are in the kitchen and its Hot! Someone must be cooking up a feast but no one is around. A door to the " + "south seems to \nlead you to the dining room. A door to the west leads back to the hallway.", + None, 2, None, 4) + room6 = Room( + "You are on a balcony overlooking a beautiful garden. There seems to be no way down. To your South is a set of" + "\ndouble doors back into the house.", + None, 4, None, None) + + # Append rooms to room_list + + room_list.append(room0) + room_list.append(room1) + room_list.append(room2) + room_list.append(room3) + room_list.append(room4) + room_list.append(room5) + room_list.append(room6) + + # Set starting room + + current_room = room_list[0] + + # Create while loop to loop through the game until player is done + + while not done: + + if current_room == room_list[0]: + print() + print(room_list[0].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + if current_room.south is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.south] + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + if current_room == room_list[1]: + print() + print(room_list[1].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + print() + user_choice = input("Are you sure you want to exit through the window?") + if user_choice.lower() == "y" or user_choice.lower() == "yes": + print("You jumped out of the window... goodbye!") + done = True + else: + print("You returned inside.") + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + if current_room == room_list[2]: + print() + print(room_list[2].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + if current_room.south is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.south] + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + if current_room == room_list[3]: + print() + print(room_list[3].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + if current_room.south is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.south] + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + if current_room == room_list[4]: + print() + print(room_list[4].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + if current_room.south is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.south] + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + if current_room == room_list[5]: + print() + print(room_list[5].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + if current_room.south is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.south] + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + if current_room == room_list[6]: + print() + print(room_list[6].description) + print("You may say \"go\" with a direction to change areas.") + user_choice = input("Which way would you like to go? ") + if user_choice.lower() == "go n" or user_choice.lower() == "go north": + if current_room.north is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.north] + elif user_choice.lower() == "go s" or user_choice.lower() == "go south": + if current_room.south is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.south] + elif user_choice.lower() == "go e" or user_choice.lower() == "go east": + if current_room.east is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.east] + elif user_choice.lower() == "go w" or user_choice.lower() == "go west": + if current_room.west is None: + print("You cant go that way.") + else: + current_room = room_list[current_room.west] + else: + print("I do not understand that command, please try again.") + + +main() From 4c74babfcf9e5865df276cb2ea33693b93f8df42 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 28 Feb 2023 08:36:15 -0700 Subject: [PATCH 19/31] cleaned up code --- Lab 06 - Text Adventure/lab_06.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Lab 06 - Text Adventure/lab_06.py b/Lab 06 - Text Adventure/lab_06.py index 1a824189b..5347a5747 100644 --- a/Lab 06 - Text Adventure/lab_06.py +++ b/Lab 06 - Text Adventure/lab_06.py @@ -1,6 +1,4 @@ # Define a class called room and adding constructor function - - class Room: def __init__(self, description, north, south, east, west): self.description = str(description) @@ -11,15 +9,12 @@ def __init__(self, description, north, south, east, west): # Defining the main function - - def main(): # Creating an empty array room_list = [] done = False # Creating rooms with attributes - room0 = Room( "It's dark. The only light is a candle on a desk next to a bed. To your east is a door. All other sides are " "walls.", @@ -52,7 +47,6 @@ def main(): None, 4, None, None) # Append rooms to room_list - room_list.append(room0) room_list.append(room1) room_list.append(room2) @@ -62,13 +56,10 @@ def main(): room_list.append(room6) # Set starting room - current_room = room_list[0] # Create while loop to loop through the game until player is done - while not done: - if current_room == room_list[0]: print() print(room_list[0].description) From 73d151563765e247746c51377ecf74147126a88f Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Tue, 28 Feb 2023 08:42:18 -0700 Subject: [PATCH 20/31] adding comments --- Lab 06 - Text Adventure/lab_06.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Lab 06 - Text Adventure/lab_06.py b/Lab 06 - Text Adventure/lab_06.py index 5347a5747..2451ea8af 100644 --- a/Lab 06 - Text Adventure/lab_06.py +++ b/Lab 06 - Text Adventure/lab_06.py @@ -60,6 +60,7 @@ def main(): # Create while loop to loop through the game until player is done while not done: + # room 1 start if current_room == room_list[0]: print() print(room_list[0].description) @@ -87,7 +88,9 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 1 end + # room 2 start if current_room == room_list[1]: print() print(room_list[1].description) @@ -118,7 +121,9 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 2 end + # room 3 start if current_room == room_list[2]: print() print(room_list[2].description) @@ -146,7 +151,9 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 3 end + # room 4 start if current_room == room_list[3]: print() print(room_list[3].description) @@ -174,7 +181,9 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 4 end + # room 5 start if current_room == room_list[4]: print() print(room_list[4].description) @@ -202,7 +211,9 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 5 end + # room 6 start if current_room == room_list[5]: print() print(room_list[5].description) @@ -230,7 +241,9 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 6 end + # room 7 start if current_room == room_list[6]: print() print(room_list[6].description) @@ -258,6 +271,8 @@ def main(): current_room = room_list[current_room.west] else: print("I do not understand that command, please try again.") + # room 7 end +# initiate main function and start the program main() From 218c20a8a612852ca1e5f4c4e4340b6a1d3e6c49 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Sat, 18 Mar 2023 11:30:05 -0600 Subject: [PATCH 21/31] initial for lab 7 --- Lab 07 - User Control/lab_07.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Lab 07 - User Control/lab_07.py b/Lab 07 - User Control/lab_07.py index e69de29bb..6bcf92660 100644 --- a/Lab 07 - User Control/lab_07.py +++ b/Lab 07 - User Control/lab_07.py @@ -0,0 +1,28 @@ +""" Lab 7 - User Control """ + +import arcade + +# --- Constants --- +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 + + +class MyGame(arcade.Window): + """ Our Custom Window Class""" + + def __init__(self): + """ Initializer """ + + # Call the parent class initializer + super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Lab 7 - User Control") + + def on_draw(self): + arcade.start_render() + + +def main(): + window = MyGame() + arcade.run() + + +main() \ No newline at end of file From 22548b30919488f2fe3de1b2c6b2510d4bea78e6 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Sat, 18 Mar 2023 22:39:44 -0600 Subject: [PATCH 22/31] updates --- Lab 07 - User Control/lab_07.py | 162 +++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 4 deletions(-) diff --git a/Lab 07 - User Control/lab_07.py b/Lab 07 - User Control/lab_07.py index 6bcf92660..b82e51357 100644 --- a/Lab 07 - User Control/lab_07.py +++ b/Lab 07 - User Control/lab_07.py @@ -1,10 +1,107 @@ """ Lab 7 - User Control """ - import arcade +import random # --- Constants --- -SCREEN_WIDTH = 800 -SCREEN_HEIGHT = 600 +SCREEN_WIDTH = 1000 +SCREEN_HEIGHT = 800 +MOVEMENT_SPEED = 2 + + +# draw light for the windows function +def draw_light_from_house(): + arcade.draw_ellipse_filled(625, 320, 28, 48, arcade.color.DARK_YELLOW) + arcade.draw_rectangle_filled(420, 320, 123, 48, arcade.color.DARK_YELLOW) + + +# draw upper windows function +def draw_upper_windows(x, y): + arcade.draw_rectangle_filled(x, y, 58, 58, arcade.color.DARK_YELLOW) + arcade.draw_rectangle_outline(x, y, 60, 60, arcade.color.BLACK, 2) + arcade.draw_line(x - 30, y, x + 30, y, arcade.color.BLACK, 2) + arcade.draw_line(x, y - 30, x, y + 30, arcade.color.BLACK, 2) + + +# draw house function +def draw_house(): + arcade.draw_lrtb_rectangle_filled(300, 700, 500, 250, arcade.color.JET) + arcade.draw_lrtb_rectangle_filled(600, 650, 625, 500, (20, 20, 20)) + arcade.draw_triangle_filled(300, 500, 500, 600, 700, 500, (43, 43, 43)) + arcade.draw_lrtb_rectangle_filled(600, 650, 350, 250, arcade.color.DARK_BROWN) + arcade.draw_circle_filled(610, 290, 3, arcade.color.BLACK) + arcade.draw_ellipse_outline(625, 320, 30, 50, arcade.color.BLACK) + arcade.draw_rectangle_outline(420, 320, 125, 50, arcade.color.BLACK, 2) + + +# draw moon function +def moon(x, y): + arcade.draw_circle_filled(x, y, 50, arcade.color.GHOST_WHITE) + arcade.draw_circle_filled(x + 20, y, 40, (27, 27, 27)) + + +# draw ground function +def ground(): + arcade.draw_lrtb_rectangle_filled(0, 999, 300, 0, (26, 36, 33)) + + +# draw trees function +def tree(x, y): + arcade.draw_rectangle_filled(x, y, 30, 60, (69, 41, 19)) + arcade.draw_triangle_filled(x - 30, y + 30, x, y + 70, x + 30, y + 30, arcade.color.DARK_GREEN) + arcade.draw_triangle_filled(x - 30, y + 60, x, y + 100, x + 30, y + 60, arcade.color.DARK_GREEN) + arcade.draw_triangle_filled(x - 30, y + 90, x, y + 130, x + 30, y + 90, arcade.color.DARK_GREEN) + + +class Ball: + def __init__(self, position_x, position_y, change_x, change_y, radius, color): + # Take the parameters of the init function above, + # and create instance variables out of them. + self.position_x = position_x + self.position_y = position_y + self.change_x = change_x + self.change_y = change_y + self.radius = radius + self.color = color + + # edge sound + self.edge_sound = arcade.load_sound(":resources:") + self.edge_sound_player = None + + if self.position_x < 8: + self.position_x = 8 + if not self.edge_sound_player or not self.edge_sound_player.playing: + self.edge_sound_player = arcade.play_sound(self.edge_sound) + arcade.play_sound(self.edge_sound) + + if self.position_y < 0: + self.position_y = 0 + if not self.edge_sound_player or not self.edge_sound_player.playing: + self.edge_sound_player = arcade.play_sound(self.edge_sound) + arcade.play_sound(self.edge_sound) + + if self.position_x > SCREEN_WIDTH - 25: + self.position_x = SCREEN_WIDTH - 25 + if not self.edge_sound_player or not self.edge_sound_player.playing: + self.edge_sound_player = arcade.play_sound(self.edge_sound) + arcade.play_sound(self.edge_sound) + + if self.position_y > SCREEN_HEIGHT - 50: + self.position_y = SCREEN_HEIGHT - 50 + if not self.edge_sound_player or not self.edge_sound_player.playing: + self.edge_sound_player = arcade.play_sound(self.edge_sound) + arcade.play_sound(self.edge_sound) + + def draw(self): + """ Draw the balls with the instance variables we have. """ + arcade.draw_circle_filled(self.position_x, + self.position_y, + self.radius, + self.color) + + def update(self): + # Move the ball + self.position_y += self.change_y + self.position_x += self.change_x class MyGame(arcade.Window): @@ -15,14 +112,71 @@ def __init__(self): # Call the parent class initializer super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Lab 7 - User Control") + # Create our ball + self.ball = Ball(50, 50, 0, 0, 15, arcade.color.WHITE) + + arcade.set_background_color((27, 27, 27)) + + # sounds + self.click_sound1 = arcade.load_sound(":resources:") + self.click_sound2 = arcade.load_sound(":resources:") def on_draw(self): arcade.start_render() + # Start Drawing + # draw ground + ground() + + # draw House + draw_house() + + # draw light + draw_light_from_house() + + # draw windows + draw_upper_windows(390, 450) + draw_upper_windows(505, 450) + draw_upper_windows(620, 450) + + # draw moon + moon(100, 650) + + # draw trees + tree(50, 290) + tree(120, 290) + tree(850, 290) + tree(920, 290) + + + self.ball.draw() + + def update(self, delta_time): + self.ball.update() + + def on_key_press(self, key, modifiers): + """ Called whenever the user presses a key. """ + if key == arcade.key.LEFT: + self.ball.change_x = -MOVEMENT_SPEED + elif key == arcade.key.RIGHT: + self.ball.change_x = MOVEMENT_SPEED + elif key == arcade.key.UP: + self.ball.change_y = MOVEMENT_SPEED + elif key == arcade.key.DOWN: + self.ball.change_y = -MOVEMENT_SPEED + + def on_key_release(self, key, modifiers): + """ Called whenever a user releases a key. """ + if key == arcade.key.LEFT or key == arcade.key.RIGHT: + self.ball.change_x = 0 + elif key == arcade.key.UP or key == arcade.key.DOWN: + self.ball.change_y = 0 + + def main(): window = MyGame() arcade.run() -main() \ No newline at end of file +main() From 0440992872ebab3bf036495a2dbda45156b29594 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Sun, 19 Mar 2023 14:12:09 -0600 Subject: [PATCH 23/31] cleaned up some minor stuff and played with more sounds --- Lab 07 - User Control/lab_07.py | 150 ++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 54 deletions(-) diff --git a/Lab 07 - User Control/lab_07.py b/Lab 07 - User Control/lab_07.py index b82e51357..8e1fe9554 100644 --- a/Lab 07 - User Control/lab_07.py +++ b/Lab 07 - User Control/lab_07.py @@ -1,11 +1,11 @@ """ Lab 7 - User Control """ import arcade -import random # --- Constants --- SCREEN_WIDTH = 1000 SCREEN_HEIGHT = 800 -MOVEMENT_SPEED = 2 +# faster gives cool ghost like graphics behind the models +MOVEMENT_SPEED = 4 # draw light for the windows function @@ -52,57 +52,72 @@ def tree(x, y): arcade.draw_triangle_filled(x - 30, y + 90, x, y + 130, x + 30, y + 90, arcade.color.DARK_GREEN) -class Ball: - def __init__(self, position_x, position_y, change_x, change_y, radius, color): +class PacMan: + def __init__(self, position_x, position_y, change_x, change_y, color): + # Take the parameters of the init function above, + # and create instance variables out of them. + self.position_x = position_x + self.position_y = position_y + self.change_x = change_x + self.change_y = change_y + self.color = color + + def draw(self): + # Draw the pacman. + arcade.draw_circle_filled(self.position_x, self.position_y, 25, self.color) + arcade.draw_triangle_filled(self.position_x, self.position_y, self.position_x + 20, self.position_y + 18, + self.position_x + 20, self.position_y - 18, arcade.color.BLACK) + arcade.draw_triangle_filled(self.position_x + 27, self.position_y, self.position_x + 20, self.position_y + 18, + self.position_x + 20, self.position_y - 18, arcade.color.BLACK) + arcade.draw_circle_filled(self.position_x + 5, self.position_y + 17, 3, arcade.color.BLACK) + + def update(self): + # Move the pacman + self.position_y += self.change_y + self.position_x += self.change_x + + +class Ghost: + def __init__(self, position_x, position_y, change_x, change_y, color): # Take the parameters of the init function above, # and create instance variables out of them. self.position_x = position_x self.position_y = position_y self.change_x = change_x self.change_y = change_y - self.radius = radius self.color = color # edge sound - self.edge_sound = arcade.load_sound(":resources:") - self.edge_sound_player = None - - if self.position_x < 8: - self.position_x = 8 - if not self.edge_sound_player or not self.edge_sound_player.playing: - self.edge_sound_player = arcade.play_sound(self.edge_sound) - arcade.play_sound(self.edge_sound) - - if self.position_y < 0: - self.position_y = 0 - if not self.edge_sound_player or not self.edge_sound_player.playing: - self.edge_sound_player = arcade.play_sound(self.edge_sound) - arcade.play_sound(self.edge_sound) - - if self.position_x > SCREEN_WIDTH - 25: - self.position_x = SCREEN_WIDTH - 25 - if not self.edge_sound_player or not self.edge_sound_player.playing: - self.edge_sound_player = arcade.play_sound(self.edge_sound) - arcade.play_sound(self.edge_sound) - - if self.position_y > SCREEN_HEIGHT - 50: - self.position_y = SCREEN_HEIGHT - 50 - if not self.edge_sound_player or not self.edge_sound_player.playing: - self.edge_sound_player = arcade.play_sound(self.edge_sound) - arcade.play_sound(self.edge_sound) + self.edge_sound = arcade.load_sound(":resources:sounds/hit4.wav") def draw(self): - """ Draw the balls with the instance variables we have. """ - arcade.draw_circle_filled(self.position_x, - self.position_y, - self.radius, - self.color) + # Draw the Ghost. + arcade.draw_rectangle_filled(self.position_x, self.position_y, 30, 30, self.color) + arcade.draw_circle_filled(self.position_x + 5, self.position_y + 5, 2, arcade.color.BLACK) + arcade.draw_circle_filled(self.position_x - 5, self.position_y + 5, 2, arcade.color.BLACK) def update(self): - # Move the ball + # Move the Ghost self.position_y += self.change_y self.position_x += self.change_x + # edge control, so we don't fly off the screen as well as edge sounds... the more the merrier. + if self.position_x < 15: + arcade.play_sound(self.edge_sound) + self.position_x = 15 + + if self.position_x > SCREEN_WIDTH - 15: + arcade.play_sound(self.edge_sound) + self.position_x = SCREEN_WIDTH - 15 + + if self.position_y < 15: + arcade.play_sound(self.edge_sound) + self.position_y = 15 + + if self.position_y > SCREEN_HEIGHT - 15: + arcade.play_sound(self.edge_sound) + self.position_y = SCREEN_HEIGHT - 15 + class MyGame(arcade.Window): """ Our Custom Window Class""" @@ -111,16 +126,23 @@ def __init__(self): """ Initializer """ # Call the parent class initializer - super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Lab 7 - User Control") - # Create our ball - self.ball = Ball(50, 50, 0, 0, 15, arcade.color.WHITE) + super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Lab 7 - User Control - Ghost") - arcade.set_background_color((27, 27, 27)) + # Make the mouse disappear when it is over the window. + # So we just see our object, not the pointer. + self.set_mouse_visible(False) + + # Create our Ghosts + self.ghost1 = Ghost(200, 200, 0, 0, arcade.color.LIGHT_BLUE) + self.pacman = PacMan(400, 200, 0, 0, arcade.color.YELLOW) + + # click sound for the mouse + self.click_sound = arcade.load_sound(":resources:sounds/laser5.wav") - # sounds - self.click_sound1 = arcade.load_sound(":resources:") - self.click_sound2 = arcade.load_sound(":resources:") + # background color for the program + arcade.set_background_color((27, 27, 27)) + # draw all the stuff! def on_draw(self): arcade.start_render() @@ -148,35 +170,55 @@ def on_draw(self): tree(850, 290) tree(920, 290) + # draw the mobile characters + self.ghost1.draw() + self.pacman.draw() - self.ball.draw() - + # update the characters def update(self, delta_time): - self.ball.update() + self.ghost1.update() + self.pacman.update() + # on keypress move the ghost def on_key_press(self, key, modifiers): """ Called whenever the user presses a key. """ if key == arcade.key.LEFT: - self.ball.change_x = -MOVEMENT_SPEED + self.ghost1.change_x = -MOVEMENT_SPEED elif key == arcade.key.RIGHT: - self.ball.change_x = MOVEMENT_SPEED + self.ghost1.change_x = MOVEMENT_SPEED elif key == arcade.key.UP: - self.ball.change_y = MOVEMENT_SPEED + self.ghost1.change_y = MOVEMENT_SPEED elif key == arcade.key.DOWN: - self.ball.change_y = -MOVEMENT_SPEED + self.ghost1.change_y = -MOVEMENT_SPEED + # on key release stop moving the ghost def on_key_release(self, key, modifiers): """ Called whenever a user releases a key. """ if key == arcade.key.LEFT or key == arcade.key.RIGHT: - self.ball.change_x = 0 + self.ghost1.change_x = 0 elif key == arcade.key.UP or key == arcade.key.DOWN: - self.ball.change_y = 0 + self.ghost1.change_y = 0 + + # mouse controls for the pacman + def on_mouse_motion(self, x, y, dx, dy): + """ Called to update our objects. + Happens approximately 60 times per second.""" + self.pacman.position_x = x + self.pacman.position_y = y + # mouse click controls to enact sound effects + def on_mouse_press(self, x, y, button, modifiers): + if button == arcade.MOUSE_BUTTON_LEFT: + arcade.play_sound(self.click_sound) + elif button == arcade.MOUSE_BUTTON_RIGHT: + arcade.play_sound(self.click_sound) +# throw everything into main to get called to start the program def main(): - window = MyGame() + MyGame() arcade.run() +# start the program main() From 55cb421772cc4d1565217d340338edfee71cb41c Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Wed, 22 Mar 2023 20:32:58 -0600 Subject: [PATCH 24/31] stuff --- Lab 08 - Sprites/lab_08.py | 109 +++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/Lab 08 - Sprites/lab_08.py b/Lab 08 - Sprites/lab_08.py index e69de29bb..2581905e5 100644 --- a/Lab 08 - Sprites/lab_08.py +++ b/Lab 08 - Sprites/lab_08.py @@ -0,0 +1,109 @@ +""" Sprite Sample Program """ + +import random +import arcade + +# --- Constants --- +SPRITE_SCALING_PLAYER = 0.5 +SPRITE_SCALING_COIN = 0.2 +COIN_COUNT = 50 + +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 + + +class MyGame(arcade.Window): + """ Our custom Window Class""" + + def __init__(self): + """ Initializer """ + # Call the parent class initializer + super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example") + + # Variables that will hold sprite lists + self.player_list = None + self.coin_list = None + + # Set up the player info + self.player_sprite = None + self.score = 0 + + # Don't show the mouse cursor + self.set_mouse_visible(False) + + arcade.set_background_color(arcade.color.AMAZON) + + def setup(self): + """ Set up the game and initialize the variables. """ + + # Sprite lists + self.player_list = arcade.SpriteList() + self.coin_list = arcade.SpriteList() + + # Score + self.score = 0 + + # Set up the player + # Character image from kenney.nl + self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER) + self.player_sprite.center_x = 50 + self.player_sprite.center_y = 50 + self.player_list.append(self.player_sprite) + + # Create the coins + for i in range(COIN_COUNT): + + # Create the coin instance + # Coin image from kenney.nl + coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN) + + # Position the coin + coin.center_x = random.randrange(SCREEN_WIDTH) + coin.center_y = random.randrange(SCREEN_HEIGHT) + + # Add the coin to the lists + self.coin_list.append(coin) + + def on_draw(self): + """ Draw everything """ + arcade.start_render() + self.coin_list.draw() + self.player_list.draw() + + # Put the text on the screen. + output = f"Score: {self.score}" + arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14) + + def on_mouse_motion(self, x, y, dx, dy): + """ Handle Mouse Motion """ + + # Move the center of the player sprite to match the mouse x, y + self.player_sprite.center_x = x + self.player_sprite.center_y = y + + def update(self, delta_time): + """ Movement and game logic """ + + # Call update on all sprites (The sprites don't do much in this + # example though.) + self.coin_list.update() + + # Generate a list of all sprites that collided with the player. + coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, + self.coin_list) + + # Loop through each colliding sprite, remove it, and add to the score. + for coin in coins_hit_list: + coin.remove_from_sprite_lists() + self.score += 1 + + +def main(): + """ Main method """ + window = MyGame() + window.setup() + arcade.run() + + +if __name__ == "__main__": + main() \ No newline at end of file From 5b493dc8e5a83c828db6aa1c10dd6111cee93c62 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Sat, 25 Mar 2023 15:23:15 -0600 Subject: [PATCH 25/31] adding movement --- Lab 08 - Sprites/lab_08.py | 71 ++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/Lab 08 - Sprites/lab_08.py b/Lab 08 - Sprites/lab_08.py index 2581905e5..98296d976 100644 --- a/Lab 08 - Sprites/lab_08.py +++ b/Lab 08 - Sprites/lab_08.py @@ -5,13 +5,29 @@ # --- Constants --- SPRITE_SCALING_PLAYER = 0.5 -SPRITE_SCALING_COIN = 0.2 +SPRITE_SCALING_BAD_OBJ = 0.3 +SPRITE_SCALING_GOOD_OBJ = 0.2 COIN_COUNT = 50 +ROCK_COUNT = 20 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 +# Good Sprite class +class Good_Sprite(arcade.Sprite): + + def update(self): + self.center_y -= 1 + + +# Bad Sprite class +class Bad_Sprite(arcade.Sprite): + + def update(self): + self.center_y -= 1 + + class MyGame(arcade.Window): """ Our custom Window Class""" @@ -20,9 +36,16 @@ def __init__(self): # Call the parent class initializer super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example") + # good sprite sound + self.goodSpriteSound = arcade.load_sound(":resources:sounds/coin3.wav") + + # bad sprite sound + self.badSpriteSound = arcade.load_sound(":resources:sounds/gameover5.wav") + # Variables that will hold sprite lists self.player_list = None self.coin_list = None + self.bad_sprite_list = None # Set up the player info self.player_sprite = None @@ -31,7 +54,7 @@ def __init__(self): # Don't show the mouse cursor self.set_mouse_visible(False) - arcade.set_background_color(arcade.color.AMAZON) + arcade.set_background_color(arcade.color.BLACK) def setup(self): """ Set up the game and initialize the variables. """ @@ -39,23 +62,22 @@ def setup(self): # Sprite lists self.player_list = arcade.SpriteList() self.coin_list = arcade.SpriteList() + self.bad_sprite_list = arcade.SpriteList() # Score self.score = 0 # Set up the player - # Character image from kenney.nl - self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER) + self.player_sprite = arcade.Sprite(":resources:images/animated_characters/male_person/malePerson_jump.png", + SPRITE_SCALING_PLAYER) self.player_sprite.center_x = 50 self.player_sprite.center_y = 50 self.player_list.append(self.player_sprite) - # Create the coins + # Create the coins // good sprites for i in range(COIN_COUNT): - # Create the coin instance - # Coin image from kenney.nl - coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN) + coin = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING_GOOD_OBJ) # Position the coin coin.center_x = random.randrange(SCREEN_WIDTH) @@ -64,11 +86,24 @@ def setup(self): # Add the coin to the lists self.coin_list.append(coin) + # Create the rocks // Bad sprites + for i in range(ROCK_COUNT): + # Create the rock instance + rock = arcade.Sprite(":resources:images/space_shooter/meteorGrey_med1.png", SPRITE_SCALING_BAD_OBJ) + + # Position the rock + rock.center_x = random.randrange(SCREEN_WIDTH) + rock.center_y = random.randrange(SCREEN_HEIGHT) + + # Add the coin to the lists + self.bad_sprite_list.append(rock) + def on_draw(self): """ Draw everything """ arcade.start_render() self.coin_list.draw() self.player_list.draw() + self.bad_sprite_list.draw() # Put the text on the screen. output = f"Score: {self.score}" @@ -87,16 +122,32 @@ def update(self, delta_time): # Call update on all sprites (The sprites don't do much in this # example though.) self.coin_list.update() + self.bad_sprite_list.update() - # Generate a list of all sprites that collided with the player. + # Generate a list of all good sprites that collided with the player. coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.coin_list) + # Generate a list of all bad sprites that collided with the player. + bad_sprite_hit_list = arcade.check_for_collision_with_list(self.player_sprite, + self.bad_sprite_list) + # Loop through each colliding sprite, remove it, and add to the score. + # Good sprite loop for coin in coins_hit_list: + arcade.play_sound(self.goodSpriteSound) coin.remove_from_sprite_lists() self.score += 1 + # Bad sprite loop + for rock in bad_sprite_hit_list: + arcade.play_sound(self.badSpriteSound) + rock.remove_from_sprite_lists() + self.score -= 1 + + if self.score == 0: + arcade.finish_render() + def main(): """ Main method """ @@ -106,4 +157,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From 1110ef44babca009168cb5401d900e51e9923157 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Sat, 25 Mar 2023 16:17:08 -0600 Subject: [PATCH 26/31] finished --- Lab 08 - Sprites/lab_08.py | 72 +++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/Lab 08 - Sprites/lab_08.py b/Lab 08 - Sprites/lab_08.py index 98296d976..25a075517 100644 --- a/Lab 08 - Sprites/lab_08.py +++ b/Lab 08 - Sprites/lab_08.py @@ -15,17 +15,58 @@ # Good Sprite class -class Good_Sprite(arcade.Sprite): +class GoodSprite(arcade.Sprite): + def reset_pos(self): + + # Reset the coin to a random spot above the screen + self.center_y = random.randrange(SCREEN_HEIGHT + 20, + SCREEN_HEIGHT + 100) + self.center_x = random.randrange(SCREEN_WIDTH) def update(self): + + # Move the coin self.center_y -= 1 + # See if the coin has fallen off the bottom of the screen. + # If so, reset it. + if self.top < 0: + self.reset_pos() + + self.angle += 1 + + # If we rotate past 360, reset it back a turn. + if self.angle > 359: + self.angle -= 360 + # Bad Sprite class -class Bad_Sprite(arcade.Sprite): +class BadSprite(arcade.Sprite): + def __init__(self, filename, sprite_scaling): + + super().__init__(filename, sprite_scaling) + + self.change_x = 0 + self.change_y = 0 def update(self): - self.center_y -= 1 + + # Move the coin + self.center_x += self.change_x + self.center_y += self.change_y + + # If we are out-of-bounds, then 'bounce' + if self.left < 0: + self.change_x *= -1 + + if self.right > SCREEN_WIDTH: + self.change_x *= -1 + + if self.bottom < 0: + self.change_y *= -1 + + if self.top > SCREEN_HEIGHT: + self.change_y *= -1 class MyGame(arcade.Window): @@ -77,7 +118,7 @@ def setup(self): # Create the coins // good sprites for i in range(COIN_COUNT): # Create the coin instance - coin = arcade.Sprite(":resources:images/items/coinGold.png", SPRITE_SCALING_GOOD_OBJ) + coin = GoodSprite(":resources:images/items/coinGold.png", SPRITE_SCALING_GOOD_OBJ) # Position the coin coin.center_x = random.randrange(SCREEN_WIDTH) @@ -89,11 +130,13 @@ def setup(self): # Create the rocks // Bad sprites for i in range(ROCK_COUNT): # Create the rock instance - rock = arcade.Sprite(":resources:images/space_shooter/meteorGrey_med1.png", SPRITE_SCALING_BAD_OBJ) + rock = BadSprite(":resources:images/space_shooter/meteorGrey_med1.png", SPRITE_SCALING_BAD_OBJ) # Position the rock rock.center_x = random.randrange(SCREEN_WIDTH) rock.center_y = random.randrange(SCREEN_HEIGHT) + rock.change_x = random.randrange(-3, 4) + rock.change_y = random.randrange(-3, 4) # Add the coin to the lists self.bad_sprite_list.append(rock) @@ -109,6 +152,11 @@ def on_draw(self): output = f"Score: {self.score}" arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14) + if len(self.coin_list) == 0: + # Draw Game Over + arcade.draw_text("GAME OVER", 325, 350, arcade.color.WHITE, 20) + # End Game Sound + def on_mouse_motion(self, x, y, dx, dy): """ Handle Mouse Motion """ @@ -116,6 +164,11 @@ def on_mouse_motion(self, x, y, dx, dy): self.player_sprite.center_x = x self.player_sprite.center_y = y + # Freeze Player + if len(self.coin_list) == 0: + self.player_sprite.center_x = 400 + self.player_sprite.center_y = 300 + def update(self, delta_time): """ Movement and game logic """ @@ -137,16 +190,17 @@ def update(self, delta_time): for coin in coins_hit_list: arcade.play_sound(self.goodSpriteSound) coin.remove_from_sprite_lists() - self.score += 1 + self.score += 10 # Bad sprite loop for rock in bad_sprite_hit_list: arcade.play_sound(self.badSpriteSound) rock.remove_from_sprite_lists() - self.score -= 1 + self.score -= 25 - if self.score == 0: - arcade.finish_render() + if len(self.coin_list) == 0: + for rock in self.bad_sprite_list: + rock.remove_from_sprite_lists() def main(): From 167a1e9335cc030707b821a4f0101fc36a5c5d0a Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Sat, 1 Apr 2023 14:02:27 -0600 Subject: [PATCH 27/31] completed all requirements --- Lab 09 - Sprites and Walls/lab_09.py | 250 +++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/Lab 09 - Sprites and Walls/lab_09.py b/Lab 09 - Sprites and Walls/lab_09.py index e69de29bb..295471e6b 100644 --- a/Lab 09 - Sprites and Walls/lab_09.py +++ b/Lab 09 - Sprites and Walls/lab_09.py @@ -0,0 +1,250 @@ +import random +import arcade +from pyglet.math import Vec2 + +SPRITE_SCALING = 0.5 +COIN_SCALING = 0.3 + +DEFAULT_SCREEN_WIDTH = 800 +DEFAULT_SCREEN_HEIGHT = 600 +SCREEN_TITLE = "SPRITE LOCKED IN A BOX" + +# coin number / anymore, and it will crash system :( +Number_Of_Coins = 100 + +# How many pixels to keep as a minimum margin between the character +# and the edge of the screen. +VIEWPORT_MARGIN = 150 + +# How fast the camera pans to the player. 1.0 is instant. +CAMERA_SPEED = 0.3 + +# How fast the character moves +PLAYER_MOVEMENT_SPEED = 7 + + +class MyGame(arcade.Window): + """ Main application class. """ + + def __init__(self, width, height, title): + """ + Initializer + """ + super().__init__(width, height, title, resizable=True) + + # good sprite sound + self.goodSpriteSound = arcade.load_sound(":resources:sounds/coin3.wav") + + # Sprite lists + self.score = None + self.player_list = None + self.wall_list = None + self.coin_list = None + + # Set up the player + self.player_sprite = None + + # Physics engine so we don't run into walls. + self.physics_engine = None + + # Track the current state of what key is pressed + self.left_pressed = False + self.right_pressed = False + self.up_pressed = False + self.down_pressed = False + + # Create the cameras. One for the GUI, one for the sprites. + # We scroll the 'sprite world' but not the GUI. + self.camera_sprites = arcade.Camera(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT) + self.camera_gui = arcade.Camera(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT) + + def setup(self): + """ Set up the game and initialize the variables. """ + + # Sprite lists + self.player_list = arcade.SpriteList() + self.wall_list = arcade.SpriteList() + self.coin_list = arcade.SpriteList() + + # Set up the player + self.player_sprite = arcade.Sprite(":resources:images/animated_characters/male_adventurer" + "/maleAdventurer_walk0.png", + scale=0.4) + self.player_sprite.center_x = 256 + self.player_sprite.center_y = 512 + self.player_list.append(self.player_sprite) + + # score + self.score = 0 + + # -- Set up the walls + # set up the outer border + # y loops the bottom and the top of the area we want to block in + for y in (0, 1536): + # loop through each box across + for x in range(0, 1600, 64): + wall = arcade.Sprite(":resources:images/tiles/stoneCenter.png", SPRITE_SCALING) + wall.left = x + wall.bottom = y + self.wall_list.append(wall) + + # create the left and right limits + for x in (0, 1536): + # loop each box + for y in range(64, 1600, 64): + wall = arcade.Sprite(":resources:images/tiles/stoneCenter.png", SPRITE_SCALING) + wall.left = x + wall.bottom = y + self.wall_list.append(wall) + + # set up random inside boxes + for x in range(200, 1536, 210): + for y in range(200, 1450, 64): + if random.randrange(3) > 0: + wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", SPRITE_SCALING) + wall.center_x = x + wall.center_y = y + self.wall_list.append(wall) + + # set up coins + # make sure they aren't in the walls / boxes + # very effective but inefficient / keeps crashing computer with to many coins due to complexity + for i in range(Number_Of_Coins): + # Coin instance / prob should have been less generic + coin_placed_successfully = False + coin = arcade.Sprite(":resources:images/items/coinGold.png", COIN_SCALING) + + # while loop to check and see if coin is not in box / wall and keep trying until successful + while not coin_placed_successfully: + # Position the coin + coin.center_x = random.randrange(1600) + coin.center_y = random.randrange(1600) + + # See if the coin is hitting a wall + wall_hit_list = arcade.check_for_collision_with_list(coin, self.wall_list) + + # See if the coin is hitting another coin / didn't think of this on my own but super smart + coin_hit_list = arcade.check_for_collision_with_list(coin, self.coin_list) + + # winner winner chicken dinner! + if len(wall_hit_list) == 0 and len(coin_hit_list) == 0: + # It is! + coin_placed_successfully = True + + # Add the coin to the lists + self.coin_list.append(coin) + + self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list) + + # Set the background color + arcade.set_background_color(arcade.color.DARK_GREEN) + + def on_draw(self): + """ Render the screen. """ + + # This command has to happen before we start drawing + self.clear() + + # Select the camera we'll use to draw all our sprites + self.camera_sprites.use() + + # Draw all the sprites. + self.wall_list.draw() + self.player_list.draw() + self.coin_list.draw() + + # Select the (un-scrolled) camera for our GUI + self.camera_gui.use() + # draw the score with the un-scrolled camera + arcade.draw_text(f"Score: {self.score}", 10, 10, arcade.color.WHITE, 24) + + def on_key_press(self, key, modifiers): + """Called whenever a key is pressed. """ + + if key == arcade.key.UP: + self.up_pressed = True + elif key == arcade.key.DOWN: + self.down_pressed = True + elif key == arcade.key.LEFT: + self.left_pressed = True + elif key == arcade.key.RIGHT: + self.right_pressed = True + + def on_key_release(self, key, modifiers): + """Called when the user releases a key. """ + + if key == arcade.key.UP: + self.up_pressed = False + elif key == arcade.key.DOWN: + self.down_pressed = False + elif key == arcade.key.LEFT: + self.left_pressed = False + elif key == arcade.key.RIGHT: + self.right_pressed = False + + def on_update(self, delta_time): + """ Movement and game logic """ + self.coin_list.update() + + # Calculate speed based on the keys pressed + self.player_sprite.change_x = 0 + self.player_sprite.change_y = 0 + + # Generate a list of all good sprites that collided with the player. + coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, + + self.coin_list) + # Loop through each colliding sprite, remove it, and add to the score. + # Good sprite loop + for coin in coins_hit_list: + arcade.play_sound(self.goodSpriteSound) + coin.remove_from_sprite_lists() + self.score += 10 + + if self.up_pressed and not self.down_pressed: + self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED + elif self.down_pressed and not self.up_pressed: + self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED + if self.left_pressed and not self.right_pressed: + self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED + elif self.right_pressed and not self.left_pressed: + self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED + + # Call update on all sprites (The sprites don't do much in this + # example though.) + self.physics_engine.update() + + # Scroll the screen to the player + self.scroll_to_player() + + def scroll_to_player(self): + """ + Scroll the window to the player. + + if CAMERA_SPEED is 1, the camera will immediately move to the desired position. + Anything between 0 and 1 will have the camera move to the location with a smoother + pan. + """ + + position = Vec2(self.player_sprite.center_x - self.width / 2, + self.player_sprite.center_y - self.height / 2) + self.camera_sprites.move_to(position, CAMERA_SPEED) + + def on_resize(self, width, height): + """ + Resize window + Handle the user grabbing the edge and resizing the window. + """ + self.camera_sprites.resize(int(width), int(height)) + self.camera_gui.resize(int(width), int(height)) + + +def main(): + """ Main function """ + window = MyGame(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, SCREEN_TITLE) + window.setup() + arcade.run() + + +if __name__ == "__main__": + main() From 47ed92eca257b122325055968cf1f1262dc4ae36 Mon Sep 17 00:00:00 2001 From: Rob Mixon Date: Fri, 7 Apr 2023 22:42:04 -0600 Subject: [PATCH 28/31] word search complete --- Lab 10 - Spell Check/lab_10.py | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/Lab 10 - Spell Check/lab_10.py b/Lab 10 - Spell Check/lab_10.py index e69de29bb..c02207f3d 100644 --- a/Lab 10 - Spell Check/lab_10.py +++ b/Lab 10 - Spell Check/lab_10.py @@ -0,0 +1,113 @@ +import re + + +# split lines into singular words with regex +def split_line(line): + return re.findall('[A-Za-z]+(?:\'[A-Za-z]+)?', line) + + +def main(): + # Open the file, and store it in a variable + dictionary_file = open("dictionary.txt") + + # instantiate empty list to store dictionary words in + dictionary_list = [] + # for loop through dictionary file and push each word to the list + for line in dictionary_file: + # remove whitespace + line = line.strip() + dictionary_list.append(line) + + # close file + dictionary_file.close() + + # track line number + line_num = 0 + + # step 8 to know what search method we are doing + print("--- Linear Search ---") + + # open file and store in variable to iterate through + file = open("AliceInWonderLand200.txt") + + # for loop through file + for line in file: + + # increase line number + line_num += 1 + + # strip whitespace off line variable + line = line.strip() + + # call split_line function to separate the words apart + word_list = split_line(line) + + # for loop through words in the line + for word in word_list: + + # beginning of the list + current_list_position = 0 + + # upper case word to compare + upperWord = word.upper() + + # loop through entire list until you find the word + while current_list_position < len(dictionary_list) and dictionary_list[current_list_position] != upperWord: + # go to next list variable + current_list_position += 1 + + # if we cant find the word in the dictionary then print the line and misspelled word + if upperWord not in dictionary_list: + print("line", line_num, "possible misspelled word:", word) + + dictionary_file.close() + + # print out what search method we are using + print("") + print("--- Binary Search ---") + + # open file and store in variable to iterate through + file = open("AliceInWonderLand200.txt") + + # reset line_num before looping through new file + line_num = 0 + + # for loop through file + for line in file: + + # increase line number + line_num += 1 + + # strip whitespace off line variable + line = line.strip() + + # call split_line function to separate the words apart + word_list = split_line(line) + + # for loop through words in the line + for word in word_list: + + # upper case word to compare + upperWord = word.upper() + + lower_bound = 0 + upper_bound = len(dictionary_list) - 1 + while lower_bound <= upper_bound: + middle_pos = (lower_bound + upper_bound) // 2 + if dictionary_list[middle_pos] == upperWord: + break + elif dictionary_list[middle_pos] < upperWord: + lower_bound = middle_pos + 1 + else: + upper_bound = middle_pos - 1 + else: + + # if we cant find the word in the dictionary then print the line and misspelled word + print("line", line_num, "possible misspelled word:", word) + + # close out file + file.close() + + +# call the main function to fire it all off +main() From a82d12e85669e2a8b170dbea3f59c3b4c924f38d Mon Sep 17 00:00:00 2001 From: Robert Mixon Date: Mon, 17 Apr 2023 08:26:45 -0600 Subject: [PATCH 29/31] working on final --- Lab 12 - Final Lab/Constants.py | 27 ++ Lab 12 - Final Lab/part_12.py | 366 ++++++++++++++++++++++++++ Lab 12 - Final Lab/spaceShips_001.png | Bin 0 -> 4082 bytes Lab 12 - Final Lab/spaceShips_002.png | Bin 0 -> 3641 bytes Lab 12 - Final Lab/spaceShips_003.png | Bin 0 -> 3521 bytes Lab 12 - Final Lab/spaceShips_004.png | Bin 0 -> 5074 bytes Lab 12 - Final Lab/spaceShips_005.png | Bin 0 -> 4729 bytes 7 files changed, 393 insertions(+) create mode 100644 Lab 12 - Final Lab/Constants.py create mode 100644 Lab 12 - Final Lab/spaceShips_001.png create mode 100644 Lab 12 - Final Lab/spaceShips_002.png create mode 100644 Lab 12 - Final Lab/spaceShips_003.png create mode 100644 Lab 12 - Final Lab/spaceShips_004.png create mode 100644 Lab 12 - Final Lab/spaceShips_005.png diff --git a/Lab 12 - Final Lab/Constants.py b/Lab 12 - Final Lab/Constants.py new file mode 100644 index 000000000..be2e39c70 --- /dev/null +++ b/Lab 12 - Final Lab/Constants.py @@ -0,0 +1,27 @@ +# title for game +title = "Definitely Not Space Invaders" + +# scaling for png +playerScaling = 0.4 +enemyScaling = 0.4 +laserScaling = 0.6 + +# screen sizing and edge control +screenWidth = 800 +screenHeight = 600 +enemyVerticalMargin = 10 + +# enemy controls +enemySpeed = 1 +enemyMoveDownAmount = 30 + +# player controls +maxPlayerBullets = 5 +livesRemaining = 3 + +# bullet controls +bulletSpeed = 3 + +# game state +gameOver = 1 +playGame = 0 diff --git a/Lab 12 - Final Lab/part_12.py b/Lab 12 - Final Lab/part_12.py index e69de29bb..e16cb04b8 100644 --- a/Lab 12 - Final Lab/part_12.py +++ b/Lab 12 - Final Lab/part_12.py @@ -0,0 +1,366 @@ +import random +import arcade +import Constants + +# This margin controls how close the enemy gets to the left or right side +# before reversing direction. +rightEnemyBorder = Constants.screenWidth - Constants.enemyVerticalMargin +leftEnemyBorder = Constants.enemyVerticalMargin + + +class InstructionView(arcade.View): + """ View to show instructions """ + + def on_show_view(self): + """ This is run once when we switch to this view """ + arcade.set_background_color(arcade.csscolor.DARK_SLATE_BLUE) + + # Reset the viewport, necessary if we have a scrolling game and we need + # to reset the viewport back to the start so we can see what we draw. + arcade.set_viewport(0, self.window.width, 0, self.window.height) + + def on_draw(self): + """ Draw this view """ + self.clear() + arcade.draw_text("Instructions Screen", self.window.width / 2, self.window.height / 2, + arcade.color.WHITE, font_size=50, anchor_x="center") + arcade.draw_text("Click to advance", self.window.width / 2, self.window.height / 2 - 75, + arcade.color.WHITE, font_size=20, anchor_x="center") + + def on_mouse_press(self, _x, _y, _button, _modifiers): + """ If the user presses the mouse button, start the game. """ + game_view = GameView() + game_view.setup() + self.window.show_view(game_view) + + +class GameView(arcade.View): + + def __init__(self): + # Call the parent class initializer + super().__init__() + + # Variables that will hold sprite lists + self.player_list = None + self.enemy_list = None + self.player_bullet_list = None + self.enemy_bullet_list = None + self.shield_list = None + + # Textures for the enemy + self.enemy_textures = None + + # State of the game + self.game_state = Constants.playGame + + # Set up the player info + self.player_sprite = None + self.score = 0 + + # Enemy movement + self.enemy_change_x = - Constants.enemySpeed + + # Don't show the mouse cursor + self.window.set_mouse_visible(False) + + # Load sounds. Sounds from arcade + self.gun_sound = arcade.load_sound(":resources:sounds/laser1.ogg") + self.hit_sound = arcade.load_sound(":resources:sounds/hit3.wav") + + def setup_level_one(self): + # Load the textures for the enemies, coming to you from Kenney.nl + self.enemy_textures = [] + texture = arcade.load_texture("spaceShips_001.png") + self.enemy_textures.append(texture) + texture = arcade.load_texture("spaceShips_002.png") + self.enemy_textures.append(texture) + + # Create rows and columns of enemies` + x_count = 7 + x_start = 380 + x_spacing = 60 + y_count = 5 + y_start = 420 + y_spacing = 40 + for x in range(x_start, x_spacing * x_count + x_start, x_spacing): + for y in range(y_start, y_spacing * y_count + y_start, y_spacing): + # Create the enemy instance + # enemy image from kenney.nl + enemy = arcade.Sprite() + enemy.scale = Constants.enemyScaling + enemy.texture = self.enemy_textures[1] + + # Position the enemy + enemy.center_x = x + enemy.center_y = y + + # Add the enemy to the lists + self.enemy_list.append(enemy) + + def make_shield(self, x_start): + """ + Make a shield, which is just a 2D grid of solid color sprites + stuck together with no margin so you can't tell them apart. + """ + shield_block_width = 5 + shield_block_height = 10 + shield_width_count = 20 + shield_height_count = 5 + y_start = 150 + for x in range(x_start, + x_start + shield_width_count * shield_block_width, + shield_block_width): + for y in range(y_start, + y_start + shield_height_count * shield_block_height, + shield_block_height): + shield_sprite = arcade.SpriteSolidColor(shield_block_width, + shield_block_height, + arcade.color.WHITE) + shield_sprite.center_x = x + shield_sprite.center_y = y + self.shield_list.append(shield_sprite) + + def setup(self): + """ + Set up the game and initialize the variables. + Call this method if you implement a 'play again' feature. + """ + + self.game_state = Constants.playGame + + # Sprite lists + self.player_list = arcade.SpriteList() + self.enemy_list = arcade.SpriteList() + self.player_bullet_list = arcade.SpriteList() + self.enemy_bullet_list = arcade.SpriteList() + self.shield_list = arcade.SpriteList(is_static=True) + + # Set up the player + self.score = 0 + + # Image from kenney.nl + self.player_sprite = arcade.Sprite(":resources:images/space_shooter/playerShip1_green.png", + Constants.playerScaling) + self.player_sprite.center_x = 50 + self.player_sprite.center_y = 40 + self.player_list.append(self.player_sprite) + + # Make each of the shields + for x in range(75, 800, 190): + self.make_shield(x) + + # Set the background color + arcade.set_background_color(arcade.color.BLACK) + + self.setup_level_one() + + def on_draw(self): + """ Render the screen. """ + + # This command has to happen before we start drawing + self.clear() + + # Draw all the sprites. + self.enemy_list.draw() + self.player_bullet_list.draw() + self.enemy_bullet_list.draw() + self.shield_list.draw() + self.player_list.draw() + + # Render the text + arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14) + + # Draw game over if the game state is such + if self.game_state == Constants.gameOver: + arcade.draw_text("GAME OVER", 250, 300, arcade.color.WHITE, 55) + self.set_mouse_visible(True) + + def on_mouse_motion(self, x, y, dx, dy): + """ + Called whenever the mouse moves. + """ + + # Don't move the player if the game is over + if self.game_state == Constants.gameOver: + return + + self.player_sprite.center_x = x + + def on_mouse_press(self, x, y, button, modifiers): + """ + Called whenever the mouse button is clicked. + """ + + # Only allow the user so many bullets on screen at a time to prevent + # them from spamming bullets. + if len(self.player_bullet_list) < Constants.maxPlayerBullets: + # Gunshot sound + arcade.play_sound(self.gun_sound) + + # Create a bullet + bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png", Constants.laserScaling) + + # The image points to the right, and we want it to point up. So + # rotate it. + bullet.angle = 90 + + # Give the bullet a speed + bullet.change_y = Constants.bulletSpeed + + # Position the bullet + bullet.center_x = self.player_sprite.center_x + bullet.bottom = self.player_sprite.top + + # Add the bullet to the appropriate lists + self.player_bullet_list.append(bullet) + + def update_enemies(self): + + # Move the enemy vertically + for enemy in self.enemy_list: + enemy.center_x += self.enemy_change_x + + # Check every enemy to see if any hit the edge. If so, reverse the + # direction and flag to move down. + move_down = False + for enemy in self.enemy_list: + if enemy.right > rightEnemyBorder and self.enemy_change_x > 0: + self.enemy_change_x *= -1 + move_down = True + if enemy.left < leftEnemyBorder and self.enemy_change_x < 0: + self.enemy_change_x *= -1 + move_down = True + + # Did we hit the edge above, and need to move the enemy down? + if move_down: + # Yes + for enemy in self.enemy_list: + # Move enemy down + enemy.center_y -= Constants.enemyMoveDownAmount + # Flip texture on enemy so it faces the other way + if self.enemy_change_x > 0: + enemy.texture = self.enemy_textures[0] + else: + enemy.texture = self.enemy_textures[1] + + def allow_enemies_to_fire(self): + """ + See if any enemies will fire this frame. + """ + # Track which x values have had a chance to fire a bullet. + # Since enemy list is build from the bottom up, we can use + # this to only allow the bottom row to fire. + x_spawn = [] + for enemy in self.enemy_list: + # Adjust the chance depending on the number of enemies. Fewer + # enemies, more likely to fire. + chance = 4 + len(self.enemy_list) * 4 + + # Fire if we roll a zero, and no one else in this column has had + # a chance to fire. + if random.randrange(chance) == 0 and enemy.center_x not in x_spawn: + # Create a bullet + bullet = arcade.Sprite(":resources:images/space_shooter/laserRed01.png", Constants.laserScaling) + + # Angle down. + bullet.angle = 180 + + # Give the bullet a speed + bullet.change_y = -Constants.bulletSpeed + + # Position the bullet so its top id right below the enemy + bullet.center_x = enemy.center_x + bullet.top = enemy.bottom + + # Add the bullet to the appropriate list + self.enemy_bullet_list.append(bullet) + + # Ok, this column has had a chance to fire. Add to list so we don't + # try it again this frame. + x_spawn.append(enemy.center_x) + + def process_enemy_bullets(self): + + # Move the bullets + self.enemy_bullet_list.update() + + # Loop through each bullet + for bullet in self.enemy_bullet_list: + # Check this bullet to see if it hit a shield + hit_list = arcade.check_for_collision_with_list(bullet, self.shield_list) + + # If it did, get rid of the bullet and shield blocks + if len(hit_list) > 0: + bullet.remove_from_sprite_lists() + for shield in hit_list: + shield.remove_from_sprite_lists() + continue + + # See if the player got hit with a bullet + if arcade.check_for_collision_with_list(self.player_sprite, self.enemy_bullet_list): + self.game_state = Constants.gameOver + + # If the bullet falls off the screen get rid of it + if bullet.top < 0: + bullet.remove_from_sprite_lists() + + def process_player_bullets(self): + + # Move the bullets + self.player_bullet_list.update() + + # Loop through each bullet + for bullet in self.player_bullet_list: + + # Check this bullet to see if it hit a enemy + hit_list = arcade.check_for_collision_with_list(bullet, self.shield_list) + # If it did, get rid of the bullet + if len(hit_list) > 0: + bullet.remove_from_sprite_lists() + for shield in hit_list: + shield.remove_from_sprite_lists() + continue + + # Check this bullet to see if it hit a enemy + hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list) + + # If it did, get rid of the bullet + if len(hit_list) > 0: + bullet.remove_from_sprite_lists() + + # For every enemy we hit, add to the score and remove the enemy + for enemy in hit_list: + enemy.remove_from_sprite_lists() + self.score += 10 + + # Hit Sound + arcade.play_sound(self.hit_sound) + + # If the bullet flies off-screen, remove it. + if bullet.bottom > Constants.screenHeight: + bullet.remove_from_sprite_lists() + + def on_update(self, delta_time): + """ Movement and game logic """ + + if self.game_state == Constants.gameOver: + return + + self.update_enemies() + self.allow_enemies_to_fire() + self.process_enemy_bullets() + self.process_player_bullets() + + if len(self.enemy_list) == 0: + self.setup_level_one() + + +def main(): + window = arcade.Window(Constants.screenWidth, Constants.screenHeight, Constants.title) + startView = InstructionView() + window.show_view(startView) + arcade.run() + + +if __name__ == "__main__": + main() diff --git a/Lab 12 - Final Lab/spaceShips_001.png b/Lab 12 - Final Lab/spaceShips_001.png new file mode 100644 index 0000000000000000000000000000000000000000..cc6f240f72ef1fd9a36671453588614c1119b413 GIT binary patch literal 4082 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 literal 0 HcmV?d00001 diff --git a/Lab 12 - Final Lab/spaceShips_002.png b/Lab 12 - Final Lab/spaceShips_002.png new file mode 100644 index 0000000000000000000000000000000000000000..4499e96374463b15f30e3da968c3f9f66fbcbd19 GIT binary patch literal 3641 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 LNkvXXu0mjf_$mL= literal 0 HcmV?d00001 diff --git a/Lab 12 - Final Lab/spaceShips_003.png b/Lab 12 - Final Lab/spaceShips_003.png new file mode 100644 index 0000000000000000000000000000000000000000..637c5a66f31db638d6bf0521ddf3b4cf71c575c9 GIT binary patch literal 3521 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 literal 0 HcmV?d00001 diff --git a/Lab 12 - Final Lab/spaceShips_004.png b/Lab 12 - Final Lab/spaceShips_004.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9c73afecb791ef2afffd364d2d0f56f839658f GIT binary patch literal 5074 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 literal 0 HcmV?d00001 diff --git a/Lab 12 - Final Lab/spaceShips_005.png b/Lab 12 - Final Lab/spaceShips_005.png new file mode 100644 index 0000000000000000000000000000000000000000..22b7d3c062f47335a24a366c265c90546f8a5838 GIT binary patch literal 4729 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 Hu0mjfi)zzB literal 0 HcmV?d00001 From 44af54c894fba25bf1fda5318aff20267462f19a Mon Sep 17 00:00:00 2001 From: Robert Mixon Date: Sat, 22 Apr 2023 14:40:46 -0600 Subject: [PATCH 30/31] finished up game --- Lab 12 - Final Lab/Constants.py | 4 +- Lab 12 - Final Lab/InstructionPage.png | Bin 0 -> 31818 bytes Lab 12 - Final Lab/part_12.py | 223 +++++++++++++++++-------- 3 files changed, 153 insertions(+), 74 deletions(-) create mode 100644 Lab 12 - Final Lab/InstructionPage.png diff --git a/Lab 12 - Final Lab/Constants.py b/Lab 12 - Final Lab/Constants.py index be2e39c70..d5c49769f 100644 --- a/Lab 12 - Final Lab/Constants.py +++ b/Lab 12 - Final Lab/Constants.py @@ -17,10 +17,10 @@ # player controls maxPlayerBullets = 5 -livesRemaining = 3 # bullet controls -bulletSpeed = 3 +playerBulletSpeed = 3 +enemyBulletSpeed = 3 # game state gameOver = 1 diff --git a/Lab 12 - Final Lab/InstructionPage.png b/Lab 12 - Final Lab/InstructionPage.png new file mode 100644 index 0000000000000000000000000000000000000000..43564611dfb0ee83d73bfe246ba592af8d8f64b7 GIT binary patch literal 31818 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 FKLGlm2G;-p literal 0 HcmV?d00001 diff --git a/Lab 12 - Final Lab/part_12.py b/Lab 12 - Final Lab/part_12.py index e16cb04b8..ebd3f901c 100644 --- a/Lab 12 - Final Lab/part_12.py +++ b/Lab 12 - Final Lab/part_12.py @@ -2,31 +2,51 @@ import arcade import Constants +# Boilerplate code came from https://api.arcade.academy/en/latest/examples/slime_invaders.html # This margin controls how close the enemy gets to the left or right side # before reversing direction. rightEnemyBorder = Constants.screenWidth - Constants.enemyVerticalMargin leftEnemyBorder = Constants.enemyVerticalMargin -class InstructionView(arcade.View): - """ View to show instructions """ +# title screen +class TitleView(arcade.View): def on_show_view(self): - """ This is run once when we switch to this view """ - arcade.set_background_color(arcade.csscolor.DARK_SLATE_BLUE) - - # Reset the viewport, necessary if we have a scrolling game and we need - # to reset the viewport back to the start so we can see what we draw. + # runs once we switch to this view + arcade.set_background_color((27, 27, 27)) arcade.set_viewport(0, self.window.width, 0, self.window.height) def on_draw(self): - """ Draw this view """ + # clear out anything else like old views self.clear() - arcade.draw_text("Instructions Screen", self.window.width / 2, self.window.height / 2, - arcade.color.WHITE, font_size=50, anchor_x="center") - arcade.draw_text("Click to advance", self.window.width / 2, self.window.height / 2 - 75, + + # Draw the view + arcade.draw_text("This is Definitely Not Space Invaders....", self.window.width / 2, self.window.height / 2, + arcade.color.WHITE, font_size=30, anchor_x="center") + arcade.draw_text("Click to Continue", self.window.width / 2, self.window.height / 2 - 75, arcade.color.WHITE, font_size=20, anchor_x="center") + # go to next screen through mouse click + def on_mouse_press(self, _x, _y, _button, _modifiers): + # show instructions next + self.window.show_view(InstructionView()) + + +# instruction view that's called from title view +class InstructionView(arcade.View): + + # runs once we switch to this view + def on_show_view(self): + arcade.set_viewport(0, self.window.width, 0, self.window.height) + + def on_draw(self): + # clear out anything else like old views + self.clear() + # Draw the view + instructionPage = arcade.load_texture("InstructionPage.png") + arcade.draw_lrwh_rectangle_textured(0, 0, Constants.screenWidth, Constants.screenHeight, instructionPage) + def on_mouse_press(self, _x, _y, _button, _modifiers): """ If the user presses the mouse button, start the game. """ game_view = GameView() @@ -34,6 +54,7 @@ def on_mouse_press(self, _x, _y, _button, _modifiers): self.window.show_view(game_view) +# Game view class GameView(arcade.View): def __init__(self): @@ -47,6 +68,12 @@ def __init__(self): self.enemy_bullet_list = None self.shield_list = None + # level variable + self.level = 1 + + # life variable + self.lives = 5 + # Textures for the enemy self.enemy_textures = None @@ -66,29 +93,37 @@ def __init__(self): # Load sounds. Sounds from arcade self.gun_sound = arcade.load_sound(":resources:sounds/laser1.ogg") self.hit_sound = arcade.load_sound(":resources:sounds/hit3.wav") + self.player_hit = arcade.load_sound(":resources:sounds/hurt1.wav") + self.lost_game = arcade.load_sound(":resources:sounds/lose2.wav") + self.level_up = arcade.load_sound(":resources:sounds/upgrade4.wav") - def setup_level_one(self): + def setup_levels(self): # Load the textures for the enemies, coming to you from Kenney.nl - self.enemy_textures = [] - texture = arcade.load_texture("spaceShips_001.png") - self.enemy_textures.append(texture) - texture = arcade.load_texture("spaceShips_002.png") - self.enemy_textures.append(texture) - - # Create rows and columns of enemies` - x_count = 7 + # enemy image from kenney.nl https://kenney.nl/assets/space-shooter-extension + texture1 = arcade.load_texture("spaceShips_001.png") + texture2 = arcade.load_texture("spaceShips_002.png") + texture3 = arcade.load_texture("spaceShips_003.png") + texture4 = arcade.load_texture("spaceShips_004.png") + texture5 = arcade.load_texture("spaceShips_005.png") + self.enemy_textures = [texture1, texture2, texture3, texture4, texture5] + + # Create rows and columns of enemies + x_count = 6 x_start = 380 x_spacing = 60 - y_count = 5 + y_count = 4 y_start = 420 y_spacing = 40 + + # randomize the enemy ships + randomEnemy = random.randint(0, 4) + for x in range(x_start, x_spacing * x_count + x_start, x_spacing): for y in range(y_start, y_spacing * y_count + y_start, y_spacing): # Create the enemy instance - # enemy image from kenney.nl enemy = arcade.Sprite() enemy.scale = Constants.enemyScaling - enemy.texture = self.enemy_textures[1] + enemy.texture = self.enemy_textures[randomEnemy] # Position the enemy enemy.center_x = x @@ -98,10 +133,8 @@ def setup_level_one(self): self.enemy_list.append(enemy) def make_shield(self, x_start): - """ - Make a shield, which is just a 2D grid of solid color sprites - stuck together with no margin so you can't tell them apart. - """ + # shield function + # just a bunch of little sprites stuck together shield_block_width = 5 shield_block_height = 10 shield_width_count = 20 @@ -115,17 +148,13 @@ def make_shield(self, x_start): shield_block_height): shield_sprite = arcade.SpriteSolidColor(shield_block_width, shield_block_height, - arcade.color.WHITE) + arcade.color.RED) shield_sprite.center_x = x shield_sprite.center_y = y self.shield_list.append(shield_sprite) def setup(self): - """ - Set up the game and initialize the variables. - Call this method if you implement a 'play again' feature. - """ - + # Initial setup of the game and when we restart the game self.game_state = Constants.playGame # Sprite lists @@ -138,25 +167,24 @@ def setup(self): # Set up the player self.score = 0 - # Image from kenney.nl + # Image from kenney.nl https://kenney.nl/assets/space-shooter-extension self.player_sprite = arcade.Sprite(":resources:images/space_shooter/playerShip1_green.png", Constants.playerScaling) self.player_sprite.center_x = 50 self.player_sprite.center_y = 40 self.player_list.append(self.player_sprite) - # Make each of the shields + # Make each of the shields initially for x in range(75, 800, 190): self.make_shield(x) # Set the background color arcade.set_background_color(arcade.color.BLACK) - self.setup_level_one() + # setup the initial level + self.setup_levels() def on_draw(self): - """ Render the screen. """ - # This command has to happen before we start drawing self.clear() @@ -167,19 +195,24 @@ def on_draw(self): self.shield_list.draw() self.player_list.draw() - # Render the text - arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14) + # Render the score + arcade.draw_text(f"Score: {self.score}", 5, 540, arcade.color.WHITE, 14) + + # Render the players lives + arcade.draw_text(f"lives: {self.lives}", 5, 560, arcade.color.WHITE, 14) - # Draw game over if the game state is such + # Render the level + arcade.draw_text(f"Level: {self.level}", 5, 580, arcade.color.WHITE, 14) + + # Draw game over if self.game_state == Constants.gameOver: - arcade.draw_text("GAME OVER", 250, 300, arcade.color.WHITE, 55) + self.clear() + arcade.set_background_color(arcade.csscolor.BLACK) + arcade.draw_text("GAME OVER", 175, 325, arcade.color.WHITE, 55) + arcade.draw_text("Click to Restart", 300, 275, arcade.color.WHITE, 24) self.set_mouse_visible(True) def on_mouse_motion(self, x, y, dx, dy): - """ - Called whenever the mouse moves. - """ - # Don't move the player if the game is over if self.game_state == Constants.gameOver: return @@ -187,25 +220,19 @@ def on_mouse_motion(self, x, y, dx, dy): self.player_sprite.center_x = x def on_mouse_press(self, x, y, button, modifiers): - """ - Called whenever the mouse button is clicked. - """ - - # Only allow the user so many bullets on screen at a time to prevent - # them from spamming bullets. - if len(self.player_bullet_list) < Constants.maxPlayerBullets: - # Gunshot sound + # Only allow the user so many bullets on screen at a time + if len(self.player_bullet_list) < Constants.maxPlayerBullets + (self.level * 0.4): + # Gun sound arcade.play_sound(self.gun_sound) # Create a bullet bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png", Constants.laserScaling) - # The image points to the right, and we want it to point up. So - # rotate it. + # Rotate image bullet.angle = 90 # Give the bullet a speed - bullet.change_y = Constants.bulletSpeed + bullet.change_y = Constants.playerBulletSpeed + (self.level * 0.1) # Position the bullet bullet.center_x = self.player_sprite.center_x @@ -214,6 +241,12 @@ def on_mouse_press(self, x, y, button, modifiers): # Add the bullet to the appropriate lists self.player_bullet_list.append(bullet) + # if game is over restart game with click + if self.game_state == Constants.gameOver: + game_view = GameView() + game_view.setup() + self.window.show_view(game_view) + def update_enemies(self): # Move the enemy vertically @@ -231,22 +264,14 @@ def update_enemies(self): self.enemy_change_x *= -1 move_down = True - # Did we hit the edge above, and need to move the enemy down? + # if we hit the edge then we move down if move_down: # Yes for enemy in self.enemy_list: # Move enemy down enemy.center_y -= Constants.enemyMoveDownAmount - # Flip texture on enemy so it faces the other way - if self.enemy_change_x > 0: - enemy.texture = self.enemy_textures[0] - else: - enemy.texture = self.enemy_textures[1] def allow_enemies_to_fire(self): - """ - See if any enemies will fire this frame. - """ # Track which x values have had a chance to fire a bullet. # Since enemy list is build from the bottom up, we can use # this to only allow the bottom row to fire. @@ -266,7 +291,7 @@ def allow_enemies_to_fire(self): bullet.angle = 180 # Give the bullet a speed - bullet.change_y = -Constants.bulletSpeed + bullet.change_y = -Constants.enemyBulletSpeed - (self.level * 0.3) # Position the bullet so its top id right below the enemy bullet.center_x = enemy.center_x @@ -297,13 +322,48 @@ def process_enemy_bullets(self): continue # See if the player got hit with a bullet - if arcade.check_for_collision_with_list(self.player_sprite, self.enemy_bullet_list): - self.game_state = Constants.gameOver + playerHitList = arcade.check_for_collision_with_list(bullet, self.player_list) + + # if so remove a life + if len(playerHitList) > 0: + bullet.remove_from_sprite_lists() + arcade.play_sound(self.player_hit) + self.lives -= 1 + + # if lives reach zero end game + if self.lives == 0: + arcade.play_sound(self.lost_game) + self.game_state = Constants.gameOver # If the bullet falls off the screen get rid of it if bullet.top < 0: bullet.remove_from_sprite_lists() + def processEnemyHittingObjects(self): + # Loop through each enemy + for enemy in self.enemy_list: + # Check this enemy to see if it hit a shield + shieldHitList = arcade.check_for_collision_with_list(enemy, self.shield_list) + + # If it did, get rid of the shield blocks + if len(shieldHitList) > 0: + for shield in shieldHitList: + shield.remove_from_sprite_lists() + continue + + # See if the player got hit with an enemy + playerHitList = arcade.check_for_collision_with_list(enemy, self.player_list) + + # if they collide with player + if len(playerHitList) > 0: + enemy.remove_from_sprite_lists() + arcade.play_sound(self.player_hit) + self.lives -= 1 + + if self.lives == 0: + arcade.play_sound(self.lost_game) + self.game_state = Constants.gameOver + def process_player_bullets(self): # Move the bullets @@ -350,17 +410,36 @@ def on_update(self, delta_time): self.allow_enemies_to_fire() self.process_enemy_bullets() self.process_player_bullets() + self.processEnemyHittingObjects() if len(self.enemy_list) == 0: - self.setup_level_one() + # increase level + self.level += 1 + + # play level up sound + arcade.play_sound(self.level_up) + + # clear lasers + self.player_bullet_list = arcade.SpriteList() + self.enemy_bullet_list = arcade.SpriteList() + + # Remake shields + for x in range(75, 800, 190): + self.make_shield(x) + + self.setup_levels() + + def set_mouse_visible(self, param): + pass +# what is initially called to start the game def main(): window = arcade.Window(Constants.screenWidth, Constants.screenHeight, Constants.title) - startView = InstructionView() - window.show_view(startView) + window.show_view(TitleView()) arcade.run() +# make sure main is called and not something else if __name__ == "__main__": main() From 03b74cf9f3f486ca190a4fd7a4191b970f2c19ba Mon Sep 17 00:00:00 2001 From: Robert Mixon Date: Mon, 11 Dec 2023 16:25:37 -0700 Subject: [PATCH 31/31] completed course --- Testing/Constants.py | 27 +++ Testing/InstructionPage.png | Bin 0 -> 31818 bytes Testing/part_12.py | 445 ++++++++++++++++++++++++++++++++++++ Testing/spaceShips_001.png | Bin 0 -> 4082 bytes Testing/spaceShips_002.png | Bin 0 -> 3641 bytes Testing/spaceShips_003.png | Bin 0 -> 3521 bytes Testing/spaceShips_004.png | Bin 0 -> 5074 bytes Testing/spaceShips_005.png | Bin 0 -> 4729 bytes Testing/test.py | 2 - 9 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 Testing/Constants.py create mode 100644 Testing/InstructionPage.png create mode 100644 Testing/part_12.py create mode 100644 Testing/spaceShips_001.png create mode 100644 Testing/spaceShips_002.png create mode 100644 Testing/spaceShips_003.png create mode 100644 Testing/spaceShips_004.png create mode 100644 Testing/spaceShips_005.png delete mode 100644 Testing/test.py diff --git a/Testing/Constants.py b/Testing/Constants.py new file mode 100644 index 000000000..d5c49769f --- /dev/null +++ b/Testing/Constants.py @@ -0,0 +1,27 @@ +# title for game +title = "Definitely Not Space Invaders" + +# scaling for png +playerScaling = 0.4 +enemyScaling = 0.4 +laserScaling = 0.6 + +# screen sizing and edge control +screenWidth = 800 +screenHeight = 600 +enemyVerticalMargin = 10 + +# enemy controls +enemySpeed = 1 +enemyMoveDownAmount = 30 + +# player controls +maxPlayerBullets = 5 + +# bullet controls +playerBulletSpeed = 3 +enemyBulletSpeed = 3 + +# game state +gameOver = 1 +playGame = 0 diff --git a/Testing/InstructionPage.png b/Testing/InstructionPage.png new file mode 100644 index 0000000000000000000000000000000000000000..43564611dfb0ee83d73bfe246ba592af8d8f64b7 GIT binary patch literal 31818 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 FKLGlm2G;-p literal 0 HcmV?d00001 diff --git a/Testing/part_12.py b/Testing/part_12.py new file mode 100644 index 000000000..ebd3f901c --- /dev/null +++ b/Testing/part_12.py @@ -0,0 +1,445 @@ +import random +import arcade +import Constants + +# Boilerplate code came from https://api.arcade.academy/en/latest/examples/slime_invaders.html +# This margin controls how close the enemy gets to the left or right side +# before reversing direction. +rightEnemyBorder = Constants.screenWidth - Constants.enemyVerticalMargin +leftEnemyBorder = Constants.enemyVerticalMargin + + +# title screen +class TitleView(arcade.View): + + def on_show_view(self): + # runs once we switch to this view + arcade.set_background_color((27, 27, 27)) + arcade.set_viewport(0, self.window.width, 0, self.window.height) + + def on_draw(self): + # clear out anything else like old views + self.clear() + + # Draw the view + arcade.draw_text("This is Definitely Not Space Invaders....", self.window.width / 2, self.window.height / 2, + arcade.color.WHITE, font_size=30, anchor_x="center") + arcade.draw_text("Click to Continue", self.window.width / 2, self.window.height / 2 - 75, + arcade.color.WHITE, font_size=20, anchor_x="center") + + # go to next screen through mouse click + def on_mouse_press(self, _x, _y, _button, _modifiers): + # show instructions next + self.window.show_view(InstructionView()) + + +# instruction view that's called from title view +class InstructionView(arcade.View): + + # runs once we switch to this view + def on_show_view(self): + arcade.set_viewport(0, self.window.width, 0, self.window.height) + + def on_draw(self): + # clear out anything else like old views + self.clear() + # Draw the view + instructionPage = arcade.load_texture("InstructionPage.png") + arcade.draw_lrwh_rectangle_textured(0, 0, Constants.screenWidth, Constants.screenHeight, instructionPage) + + def on_mouse_press(self, _x, _y, _button, _modifiers): + """ If the user presses the mouse button, start the game. """ + game_view = GameView() + game_view.setup() + self.window.show_view(game_view) + + +# Game view +class GameView(arcade.View): + + def __init__(self): + # Call the parent class initializer + super().__init__() + + # Variables that will hold sprite lists + self.player_list = None + self.enemy_list = None + self.player_bullet_list = None + self.enemy_bullet_list = None + self.shield_list = None + + # level variable + self.level = 1 + + # life variable + self.lives = 5 + + # Textures for the enemy + self.enemy_textures = None + + # State of the game + self.game_state = Constants.playGame + + # Set up the player info + self.player_sprite = None + self.score = 0 + + # Enemy movement + self.enemy_change_x = - Constants.enemySpeed + + # Don't show the mouse cursor + self.window.set_mouse_visible(False) + + # Load sounds. Sounds from arcade + self.gun_sound = arcade.load_sound(":resources:sounds/laser1.ogg") + self.hit_sound = arcade.load_sound(":resources:sounds/hit3.wav") + self.player_hit = arcade.load_sound(":resources:sounds/hurt1.wav") + self.lost_game = arcade.load_sound(":resources:sounds/lose2.wav") + self.level_up = arcade.load_sound(":resources:sounds/upgrade4.wav") + + def setup_levels(self): + # Load the textures for the enemies, coming to you from Kenney.nl + # enemy image from kenney.nl https://kenney.nl/assets/space-shooter-extension + texture1 = arcade.load_texture("spaceShips_001.png") + texture2 = arcade.load_texture("spaceShips_002.png") + texture3 = arcade.load_texture("spaceShips_003.png") + texture4 = arcade.load_texture("spaceShips_004.png") + texture5 = arcade.load_texture("spaceShips_005.png") + self.enemy_textures = [texture1, texture2, texture3, texture4, texture5] + + # Create rows and columns of enemies + x_count = 6 + x_start = 380 + x_spacing = 60 + y_count = 4 + y_start = 420 + y_spacing = 40 + + # randomize the enemy ships + randomEnemy = random.randint(0, 4) + + for x in range(x_start, x_spacing * x_count + x_start, x_spacing): + for y in range(y_start, y_spacing * y_count + y_start, y_spacing): + # Create the enemy instance + enemy = arcade.Sprite() + enemy.scale = Constants.enemyScaling + enemy.texture = self.enemy_textures[randomEnemy] + + # Position the enemy + enemy.center_x = x + enemy.center_y = y + + # Add the enemy to the lists + self.enemy_list.append(enemy) + + def make_shield(self, x_start): + # shield function + # just a bunch of little sprites stuck together + shield_block_width = 5 + shield_block_height = 10 + shield_width_count = 20 + shield_height_count = 5 + y_start = 150 + for x in range(x_start, + x_start + shield_width_count * shield_block_width, + shield_block_width): + for y in range(y_start, + y_start + shield_height_count * shield_block_height, + shield_block_height): + shield_sprite = arcade.SpriteSolidColor(shield_block_width, + shield_block_height, + arcade.color.RED) + shield_sprite.center_x = x + shield_sprite.center_y = y + self.shield_list.append(shield_sprite) + + def setup(self): + # Initial setup of the game and when we restart the game + self.game_state = Constants.playGame + + # Sprite lists + self.player_list = arcade.SpriteList() + self.enemy_list = arcade.SpriteList() + self.player_bullet_list = arcade.SpriteList() + self.enemy_bullet_list = arcade.SpriteList() + self.shield_list = arcade.SpriteList(is_static=True) + + # Set up the player + self.score = 0 + + # Image from kenney.nl https://kenney.nl/assets/space-shooter-extension + self.player_sprite = arcade.Sprite(":resources:images/space_shooter/playerShip1_green.png", + Constants.playerScaling) + self.player_sprite.center_x = 50 + self.player_sprite.center_y = 40 + self.player_list.append(self.player_sprite) + + # Make each of the shields initially + for x in range(75, 800, 190): + self.make_shield(x) + + # Set the background color + arcade.set_background_color(arcade.color.BLACK) + + # setup the initial level + self.setup_levels() + + def on_draw(self): + # This command has to happen before we start drawing + self.clear() + + # Draw all the sprites. + self.enemy_list.draw() + self.player_bullet_list.draw() + self.enemy_bullet_list.draw() + self.shield_list.draw() + self.player_list.draw() + + # Render the score + arcade.draw_text(f"Score: {self.score}", 5, 540, arcade.color.WHITE, 14) + + # Render the players lives + arcade.draw_text(f"lives: {self.lives}", 5, 560, arcade.color.WHITE, 14) + + # Render the level + arcade.draw_text(f"Level: {self.level}", 5, 580, arcade.color.WHITE, 14) + + # Draw game over + if self.game_state == Constants.gameOver: + self.clear() + arcade.set_background_color(arcade.csscolor.BLACK) + arcade.draw_text("GAME OVER", 175, 325, arcade.color.WHITE, 55) + arcade.draw_text("Click to Restart", 300, 275, arcade.color.WHITE, 24) + self.set_mouse_visible(True) + + def on_mouse_motion(self, x, y, dx, dy): + # Don't move the player if the game is over + if self.game_state == Constants.gameOver: + return + + self.player_sprite.center_x = x + + def on_mouse_press(self, x, y, button, modifiers): + # Only allow the user so many bullets on screen at a time + if len(self.player_bullet_list) < Constants.maxPlayerBullets + (self.level * 0.4): + # Gun sound + arcade.play_sound(self.gun_sound) + + # Create a bullet + bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png", Constants.laserScaling) + + # Rotate image + bullet.angle = 90 + + # Give the bullet a speed + bullet.change_y = Constants.playerBulletSpeed + (self.level * 0.1) + + # Position the bullet + bullet.center_x = self.player_sprite.center_x + bullet.bottom = self.player_sprite.top + + # Add the bullet to the appropriate lists + self.player_bullet_list.append(bullet) + + # if game is over restart game with click + if self.game_state == Constants.gameOver: + game_view = GameView() + game_view.setup() + self.window.show_view(game_view) + + def update_enemies(self): + + # Move the enemy vertically + for enemy in self.enemy_list: + enemy.center_x += self.enemy_change_x + + # Check every enemy to see if any hit the edge. If so, reverse the + # direction and flag to move down. + move_down = False + for enemy in self.enemy_list: + if enemy.right > rightEnemyBorder and self.enemy_change_x > 0: + self.enemy_change_x *= -1 + move_down = True + if enemy.left < leftEnemyBorder and self.enemy_change_x < 0: + self.enemy_change_x *= -1 + move_down = True + + # if we hit the edge then we move down + if move_down: + # Yes + for enemy in self.enemy_list: + # Move enemy down + enemy.center_y -= Constants.enemyMoveDownAmount + + def allow_enemies_to_fire(self): + # Track which x values have had a chance to fire a bullet. + # Since enemy list is build from the bottom up, we can use + # this to only allow the bottom row to fire. + x_spawn = [] + for enemy in self.enemy_list: + # Adjust the chance depending on the number of enemies. Fewer + # enemies, more likely to fire. + chance = 4 + len(self.enemy_list) * 4 + + # Fire if we roll a zero, and no one else in this column has had + # a chance to fire. + if random.randrange(chance) == 0 and enemy.center_x not in x_spawn: + # Create a bullet + bullet = arcade.Sprite(":resources:images/space_shooter/laserRed01.png", Constants.laserScaling) + + # Angle down. + bullet.angle = 180 + + # Give the bullet a speed + bullet.change_y = -Constants.enemyBulletSpeed - (self.level * 0.3) + + # Position the bullet so its top id right below the enemy + bullet.center_x = enemy.center_x + bullet.top = enemy.bottom + + # Add the bullet to the appropriate list + self.enemy_bullet_list.append(bullet) + + # Ok, this column has had a chance to fire. Add to list so we don't + # try it again this frame. + x_spawn.append(enemy.center_x) + + def process_enemy_bullets(self): + + # Move the bullets + self.enemy_bullet_list.update() + + # Loop through each bullet + for bullet in self.enemy_bullet_list: + # Check this bullet to see if it hit a shield + hit_list = arcade.check_for_collision_with_list(bullet, self.shield_list) + + # If it did, get rid of the bullet and shield blocks + if len(hit_list) > 0: + bullet.remove_from_sprite_lists() + for shield in hit_list: + shield.remove_from_sprite_lists() + continue + + # See if the player got hit with a bullet + playerHitList = arcade.check_for_collision_with_list(bullet, self.player_list) + + # if so remove a life + if len(playerHitList) > 0: + bullet.remove_from_sprite_lists() + arcade.play_sound(self.player_hit) + self.lives -= 1 + + # if lives reach zero end game + if self.lives == 0: + arcade.play_sound(self.lost_game) + self.game_state = Constants.gameOver + + # If the bullet falls off the screen get rid of it + if bullet.top < 0: + bullet.remove_from_sprite_lists() + + def processEnemyHittingObjects(self): + # Loop through each enemy + for enemy in self.enemy_list: + # Check this enemy to see if it hit a shield + shieldHitList = arcade.check_for_collision_with_list(enemy, self.shield_list) + + # If it did, get rid of the shield blocks + if len(shieldHitList) > 0: + for shield in shieldHitList: + shield.remove_from_sprite_lists() + continue + + # See if the player got hit with an enemy + playerHitList = arcade.check_for_collision_with_list(enemy, self.player_list) + + # if they collide with player + if len(playerHitList) > 0: + enemy.remove_from_sprite_lists() + arcade.play_sound(self.player_hit) + self.lives -= 1 + + if self.lives == 0: + arcade.play_sound(self.lost_game) + self.game_state = Constants.gameOver + + def process_player_bullets(self): + + # Move the bullets + self.player_bullet_list.update() + + # Loop through each bullet + for bullet in self.player_bullet_list: + + # Check this bullet to see if it hit a enemy + hit_list = arcade.check_for_collision_with_list(bullet, self.shield_list) + # If it did, get rid of the bullet + if len(hit_list) > 0: + bullet.remove_from_sprite_lists() + for shield in hit_list: + shield.remove_from_sprite_lists() + continue + + # Check this bullet to see if it hit a enemy + hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list) + + # If it did, get rid of the bullet + if len(hit_list) > 0: + bullet.remove_from_sprite_lists() + + # For every enemy we hit, add to the score and remove the enemy + for enemy in hit_list: + enemy.remove_from_sprite_lists() + self.score += 10 + + # Hit Sound + arcade.play_sound(self.hit_sound) + + # If the bullet flies off-screen, remove it. + if bullet.bottom > Constants.screenHeight: + bullet.remove_from_sprite_lists() + + def on_update(self, delta_time): + """ Movement and game logic """ + + if self.game_state == Constants.gameOver: + return + + self.update_enemies() + self.allow_enemies_to_fire() + self.process_enemy_bullets() + self.process_player_bullets() + self.processEnemyHittingObjects() + + if len(self.enemy_list) == 0: + # increase level + self.level += 1 + + # play level up sound + arcade.play_sound(self.level_up) + + # clear lasers + self.player_bullet_list = arcade.SpriteList() + self.enemy_bullet_list = arcade.SpriteList() + + # Remake shields + for x in range(75, 800, 190): + self.make_shield(x) + + self.setup_levels() + + def set_mouse_visible(self, param): + pass + + +# what is initially called to start the game +def main(): + window = arcade.Window(Constants.screenWidth, Constants.screenHeight, Constants.title) + window.show_view(TitleView()) + arcade.run() + + +# make sure main is called and not something else +if __name__ == "__main__": + main() diff --git a/Testing/spaceShips_001.png b/Testing/spaceShips_001.png new file mode 100644 index 0000000000000000000000000000000000000000..cc6f240f72ef1fd9a36671453588614c1119b413 GIT binary patch literal 4082 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 literal 0 HcmV?d00001 diff --git a/Testing/spaceShips_002.png b/Testing/spaceShips_002.png new file mode 100644 index 0000000000000000000000000000000000000000..4499e96374463b15f30e3da968c3f9f66fbcbd19 GIT binary patch literal 3641 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 LNkvXXu0mjf_$mL= literal 0 HcmV?d00001 diff --git a/Testing/spaceShips_003.png b/Testing/spaceShips_003.png new file mode 100644 index 0000000000000000000000000000000000000000..637c5a66f31db638d6bf0521ddf3b4cf71c575c9 GIT binary patch literal 3521 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 literal 0 HcmV?d00001 diff --git a/Testing/spaceShips_004.png b/Testing/spaceShips_004.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9c73afecb791ef2afffd364d2d0f56f839658f GIT binary patch literal 5074 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 literal 0 HcmV?d00001 diff --git a/Testing/spaceShips_005.png b/Testing/spaceShips_005.png new file mode 100644 index 0000000000000000000000000000000000000000..22b7d3c062f47335a24a366c265c90546f8a5838 GIT binary patch literal 4729 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 Hu0mjfi)zzB literal 0 HcmV?d00001 diff --git a/Testing/test.py b/Testing/test.py deleted file mode 100644 index a1422d8d2..000000000 --- a/Testing/test.py +++ /dev/null @@ -1,2 +0,0 @@ -print("It was a dark and stormy night.") -print("Suddenly a shot rang out!") \ No newline at end of file