From 0ce4e48105290aff883cf095e720063c2e712aa4 Mon Sep 17 00:00:00 2001 From: jescubido <102789017+jescubido@users.noreply.github.com> Date: Thu, 11 May 2023 14:48:07 -0700 Subject: [PATCH 01/30] Update cannon.py --- week13/cannon.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index cb9c6b8..9047e9e 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -5,11 +5,8 @@ pg.init() pg.font.init() -<<<<<<< HEAD WHITE = (260, 255, 260) -======= WHITE = (260, 260, 260) ->>>>>>> cc6f46ba090608d1075080735c9786c9a64ae21a BLACK = (0, 0, 0) RED = (260, 0, 0) From 086647a5d5f182c0616e27618f0e8ad001c88266 Mon Sep 17 00:00:00 2001 From: jescubido Date: Thu, 11 May 2023 15:36:29 -0700 Subject: [PATCH 02/30] fix invalid color argument --- week13/cannon.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 9047e9e..11d0e36 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -5,10 +5,10 @@ pg.init() pg.font.init() -WHITE = (260, 255, 260) -WHITE = (260, 260, 260) +WHITE = (255, 255, 255) +WHITE = (255, 255, 255) BLACK = (0, 0, 0) -RED = (260, 0, 0) +RED = (255, 0, 0) SCREEN_SIZE = (800, 600) From 51b25457f9bffbf2e48335a1454942e4e1d5bff3 Mon Sep 17 00:00:00 2001 From: Val Date: Fri, 12 May 2023 21:41:18 -0700 Subject: [PATCH 03/30] moved ScoreTable position to screen center --- .vscode/settings.json | 6 ++++++ week13/cannon.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5c80254 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "[python]": { + "editor.defaultFormatter": "ms-python.autopep8" + }, + "python.formatting.provider": "none" +} diff --git a/week13/cannon.py b/week13/cannon.py index 11d0e36..c0fb89f 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -212,7 +212,7 @@ def draw(self, screen): score_surf.append(self.font.render("Balls used: {}".format(self.b_used), True, WHITE)) score_surf.append(self.font.render("Total: {}".format(self.score()), True, RED)) for i in range(3): - screen.blit(score_surf[i], [10, 10 + 30*i]) + screen.blit(score_surf[i], [310, 10 + 30*i]) class Manager: @@ -323,7 +323,7 @@ def collide(self): screen = pg.display.set_mode(SCREEN_SIZE) -pg.display.set_caption("The gun of Khiryanov") +pg.display.set_caption("Cannon Game") done = False clock = pg.time.Clock() From 760c0792030f9a307a5b020ea4600476492bfd87 Mon Sep 17 00:00:00 2001 From: Val Date: Fri, 12 May 2023 21:54:02 -0700 Subject: [PATCH 04/30] renaming cannon to gun1 for mult cannon & prep for modifications --- week13/cannon.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index c0fb89f..0d392d2 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -221,7 +221,7 @@ class Manager: ''' def __init__(self, n_targets=1): self.balls = [] - self.gun = Cannon() + self.gun1 = Cannon() self.targets = [] self.score_t = ScoreTable() self.n_targets = n_targets @@ -246,7 +246,7 @@ def process(self, events, screen): if pg.mouse.get_focused(): mouse_pos = pg.mouse.get_pos() - self.gun.set_angle(mouse_pos) + self.gun1.set_angle(mouse_pos) self.move() self.collide() @@ -267,15 +267,15 @@ def handle_events(self, events): done = True elif event.type == pg.KEYDOWN: if event.key == pg.K_UP: - self.gun.move(-5) + self.gun1.move(-5) elif event.key == pg.K_DOWN: - self.gun.move(5) + self.gun1.move(5) elif event.type == pg.MOUSEBUTTONDOWN: if event.button == 1: - self.gun.activate() + self.gun1.activate() elif event.type == pg.MOUSEBUTTONUP: if event.button == 1: - self.balls.append(self.gun.strike()) + self.balls.append(self.gun1.strike()) self.score_t.b_used += 1 return done @@ -287,7 +287,7 @@ def draw(self, screen): ball.draw(screen) for target in self.targets: target.draw(screen) - self.gun.draw(screen) + self.gun1.draw(screen) self.score_t.draw(screen) def move(self): @@ -303,7 +303,7 @@ def move(self): self.balls.pop(i) for i, target in enumerate(self.targets): target.move() - self.gun.gain() + self.gun1.gain() def collide(self): ''' From 9d09265e907aedf65bf366cfefa8439d959a26a8 Mon Sep 17 00:00:00 2001 From: Val Date: Fri, 12 May 2023 22:16:04 -0700 Subject: [PATCH 05/30] moving movement events outside the loop for fluid vertical movement --- week13/cannon.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 0d392d2..e86a726 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -262,14 +262,10 @@ def handle_events(self, events): Handles events from keyboard, mouse, etc. ''' done = False + for event in events: if event.type == pg.QUIT: done = True - elif event.type == pg.KEYDOWN: - if event.key == pg.K_UP: - self.gun1.move(-5) - elif event.key == pg.K_DOWN: - self.gun1.move(5) elif event.type == pg.MOUSEBUTTONDOWN: if event.button == 1: self.gun1.activate() @@ -277,6 +273,13 @@ def handle_events(self, events): if event.button == 1: self.balls.append(self.gun1.strike()) self.score_t.b_used += 1 + + key_pressed = pg.key.get_pressed(); + if key_pressed[pg.K_UP]: + self.gun1.move(-5) + if key_pressed[pg.K_DOWN]: + self.gun1.move(5) + return done def draw(self, screen): From 5556ef1813a1096f18520bff1af8c6c694762e09 Mon Sep 17 00:00:00 2001 From: Val Date: Fri, 12 May 2023 23:03:42 -0700 Subject: [PATCH 06/30] BLUE constant | hardcoded parameters for Cannon | x/y movement | creating second cannon --- week13/cannon.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index e86a726..61492a1 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -9,6 +9,7 @@ WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) +BLUE = (0, 0, 255) SCREEN_SIZE = (800, 600) @@ -78,7 +79,7 @@ class Cannon(GameObject): ''' Cannon class. Manages it's renderring, movement and striking. ''' - def __init__(self, coord=[30, SCREEN_SIZE[1]//2], angle=0, max_pow=50, min_pow=10, color=RED): + def __init__(self, coord, angle, max_pow, min_pow, color): ''' Constructor method. Sets coordinate, direction, minimum and maximum power and color of the gun. ''' @@ -120,12 +121,18 @@ def set_angle(self, target_pos): ''' self.angle = np.arctan2(target_pos[1] - self.coord[1], target_pos[0] - self.coord[0]) - def move(self, inc): + def moveYCOORD(self, inc): ''' Changes vertical position of the gun. ''' if (self.coord[1] > 30 or inc > 0) and (self.coord[1] < SCREEN_SIZE[1] - 30 or inc < 0): self.coord[1] += inc + def moveXCOORD(self, inc): + ''' + Changes horizontal position of the gun. + ''' + if (self.coord[0] - inc > 0 or inc > 0) and (self.coord[0] < SCREEN_SIZE[0] + inc or inc < 0): + self.coord[0] += inc def draw(self, screen): ''' @@ -221,7 +228,8 @@ class Manager: ''' def __init__(self, n_targets=1): self.balls = [] - self.gun1 = Cannon() + self.player = Cannon([30, SCREEN_SIZE[1]//2], angle=0, max_pow=50, min_pow=10, color=RED) + self.enemy = Cannon([770, SCREEN_SIZE[1]//2], angle=270, max_pow=50, min_pow=10, color=BLUE) self.targets = [] self.score_t = ScoreTable() self.n_targets = n_targets @@ -246,7 +254,7 @@ def process(self, events, screen): if pg.mouse.get_focused(): mouse_pos = pg.mouse.get_pos() - self.gun1.set_angle(mouse_pos) + self.player.set_angle(mouse_pos) self.move() self.collide() @@ -268,17 +276,21 @@ def handle_events(self, events): done = True elif event.type == pg.MOUSEBUTTONDOWN: if event.button == 1: - self.gun1.activate() + self.player.activate() elif event.type == pg.MOUSEBUTTONUP: if event.button == 1: - self.balls.append(self.gun1.strike()) + self.balls.append(self.player.strike()) self.score_t.b_used += 1 key_pressed = pg.key.get_pressed(); if key_pressed[pg.K_UP]: - self.gun1.move(-5) - if key_pressed[pg.K_DOWN]: - self.gun1.move(5) + self.player.moveYCOORD(-5) + elif key_pressed[pg.K_DOWN]: + self.player.moveYCOORD(5) + elif key_pressed[pg.K_LEFT]: + self.player.moveXCOORD(-5) + elif key_pressed[pg.K_RIGHT]: + self.player.moveXCOORD(5) return done @@ -290,7 +302,8 @@ def draw(self, screen): ball.draw(screen) for target in self.targets: target.draw(screen) - self.gun1.draw(screen) + self.player.draw(screen) + self.enemy.draw(screen) self.score_t.draw(screen) def move(self): @@ -306,7 +319,7 @@ def move(self): self.balls.pop(i) for i, target in enumerate(self.targets): target.move() - self.gun1.gain() + self.player.gain() def collide(self): ''' From f173f44cb561eb8a3315b1b5c947529dd3276305 Mon Sep 17 00:00:00 2001 From: Val Date: Sat, 13 May 2023 21:43:27 -0700 Subject: [PATCH 07/30] removed improper synatax: semicolon --- week13/cannon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/week13/cannon.py b/week13/cannon.py index 61492a1..d6e5c91 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -282,7 +282,7 @@ def handle_events(self, events): self.balls.append(self.player.strike()) self.score_t.b_used += 1 - key_pressed = pg.key.get_pressed(); + key_pressed = pg.key.get_pressed() if key_pressed[pg.K_UP]: self.player.moveYCOORD(-5) elif key_pressed[pg.K_DOWN]: From dcf347ed94f34cc59191a522aadcd9f254034906 Mon Sep 17 00:00:00 2001 From: Val Date: Sun, 14 May 2023 11:47:51 -0700 Subject: [PATCH 08/30] distinguishing player & enemy actions --- week13/cannon.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/week13/cannon.py b/week13/cannon.py index d6e5c91..b31c616 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -271,6 +271,7 @@ def handle_events(self, events): ''' done = False + # Player actions for event in events: if event.type == pg.QUIT: done = True @@ -292,6 +293,9 @@ def handle_events(self, events): elif key_pressed[pg.K_RIGHT]: self.player.moveXCOORD(5) + # Enemy Actions + + return done def draw(self, screen): From 07e9400b65b386cd0656ae50ef3a7deb9ed3b99e Mon Sep 17 00:00:00 2001 From: Val Date: Sun, 14 May 2023 13:51:49 -0700 Subject: [PATCH 09/30] enemy movement targetting, and attack | pep8 auto format --- week13/cannon.py | 75 +++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index b31c616..8c19d1b 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -17,19 +17,21 @@ def rand_color(): return (randint(0, 255), randint(0, 255), randint(0, 255)) + class GameObject: def move(self): pass - + def draw(self, screen): - pass + pass class Shell(GameObject): ''' The ball class. Creates a ball, controls it's movement and implement it's rendering. ''' + def __init__(self, coord, vel, rad=20, color=None): ''' Constructor method. Initializes ball's parameters and initial values. @@ -79,6 +81,7 @@ class Cannon(GameObject): ''' Cannon class. Manages it's renderring, movement and striking. ''' + def __init__(self, coord, angle, max_pow, min_pow, color): ''' Constructor method. Sets coordinate, direction, minimum and maximum power and color of the gun. @@ -90,7 +93,7 @@ def __init__(self, coord, angle, max_pow, min_pow, color): self.color = color self.active = False self.pow = min_pow - + def activate(self): ''' Activates gun's charge. @@ -110,16 +113,18 @@ def strike(self): ''' vel = self.pow angle = self.angle - ball = Shell(list(self.coord), [int(vel * np.cos(angle)), int(vel * np.sin(angle))]) + ball = Shell(list(self.coord), [ + int(vel * np.cos(angle)), int(vel * np.sin(angle))]) self.pow = self.min_pow self.active = False return ball - + def set_angle(self, target_pos): ''' Sets gun's direction to target position. ''' - self.angle = np.arctan2(target_pos[1] - self.coord[1], target_pos[0] - self.coord[0]) + self.angle = np.arctan2( + target_pos[1] - self.coord[1], target_pos[0] - self.coord[0]) def moveYCOORD(self, inc): ''' @@ -127,6 +132,7 @@ def moveYCOORD(self, inc): ''' if (self.coord[1] > 30 or inc > 0) and (self.coord[1] < SCREEN_SIZE[1] - 30 or inc < 0): self.coord[1] += inc + def moveXCOORD(self, inc): ''' Changes horizontal position of the gun. @@ -139,8 +145,10 @@ def draw(self, screen): Draws the gun on the screen. ''' gun_shape = [] - vec_1 = np.array([int(5*np.cos(self.angle - np.pi/2)), int(5*np.sin(self.angle - np.pi/2))]) - vec_2 = np.array([int(self.pow*np.cos(self.angle)), int(self.pow*np.sin(self.angle))]) + vec_1 = np.array([int(5*np.cos(self.angle - np.pi/2)), + int(5*np.sin(self.angle - np.pi/2))]) + vec_2 = np.array([int(self.pow*np.cos(self.angle)), + int(self.pow*np.sin(self.angle))]) gun_pos = np.array(self.coord) gun_shape.append((gun_pos + vec_1).tolist()) gun_shape.append((gun_pos + vec_1 + vec_2).tolist()) @@ -153,12 +161,14 @@ class Target(GameObject): ''' Target class. Creates target, manages it's rendering and collision with a ball event. ''' + def __init__(self, coord=None, color=None, rad=30): ''' Constructor method. Sets coordinate, color and radius of the target. ''' if coord == None: - coord = [randint(rad, SCREEN_SIZE[0] - rad), randint(rad, SCREEN_SIZE[1] - rad)] + coord = [randint(rad, SCREEN_SIZE[0] - rad), + randint(rad, SCREEN_SIZE[1] - rad)] self.coord = coord self.rad = rad @@ -187,12 +197,13 @@ def move(self): """ pass + class MovingTargets(Target): def __init__(self, coord=None, color=None, rad=30): super().__init__(coord, color, rad) self.vx = randint(-2, +2) self.vy = randint(-2, +2) - + def move(self): self.coord[0] += self.vx self.coord[1] += self.vy @@ -202,6 +213,7 @@ class ScoreTable: ''' Score table class. ''' + def __init__(self, t_destr=0, b_used=0): self.t_destr = t_destr self.b_used = b_used @@ -215,9 +227,12 @@ def score(self): def draw(self, screen): score_surf = [] - score_surf.append(self.font.render("Destroyed: {}".format(self.t_destr), True, WHITE)) - score_surf.append(self.font.render("Balls used: {}".format(self.b_used), True, WHITE)) - score_surf.append(self.font.render("Total: {}".format(self.score()), True, RED)) + score_surf.append(self.font.render( + "Destroyed: {}".format(self.t_destr), True, WHITE)) + score_surf.append(self.font.render( + "Balls used: {}".format(self.b_used), True, WHITE)) + score_surf.append(self.font.render( + "Total: {}".format(self.score()), True, RED)) for i in range(3): screen.blit(score_surf[i], [310, 10 + 30*i]) @@ -226,10 +241,13 @@ class Manager: ''' Class that manages events' handling, ball's motion and collision, target creation, etc. ''' + def __init__(self, n_targets=1): self.balls = [] - self.player = Cannon([30, SCREEN_SIZE[1]//2], angle=0, max_pow=50, min_pow=10, color=RED) - self.enemy = Cannon([770, SCREEN_SIZE[1]//2], angle=270, max_pow=50, min_pow=10, color=BLUE) + self.player = Cannon([30, SCREEN_SIZE[1]//2], + angle=0, max_pow=50, min_pow=10, color=RED) + self.enemy = Cannon([770, SCREEN_SIZE[1]//2], + angle=0, max_pow=50, min_pow=10, color=BLUE) self.targets = [] self.score_t = ScoreTable() self.n_targets = n_targets @@ -241,10 +259,9 @@ def new_mission(self): ''' for i in range(self.n_targets): self.targets.append(MovingTargets(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), - 30 - max(0, self.score_t.score())))) + 30 - max(0, self.score_t.score())))) self.targets.append(Target(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), - 30 - max(0, self.score_t.score())))) - + 30 - max(0, self.score_t.score())))) def process(self, events, screen): ''' @@ -255,7 +272,7 @@ def process(self, events, screen): if pg.mouse.get_focused(): mouse_pos = pg.mouse.get_pos() self.player.set_angle(mouse_pos) - + self.move() self.collide() self.draw(screen) @@ -270,8 +287,12 @@ def handle_events(self, events): Handles events from keyboard, mouse, etc. ''' done = False - - # Player actions + + # Prep enemy tank + self.enemy.set_angle([90,0]) + self.enemy.activate() + self.enemy.gain() + for event in events: if event.type == pg.QUIT: done = True @@ -282,20 +303,22 @@ def handle_events(self, events): if event.button == 1: self.balls.append(self.player.strike()) self.score_t.b_used += 1 - + # Once the player shots, the enemy will too + if event.type == pg.MOUSEBUTTONUP: + self.balls.append(self.enemy.strike()) + key_pressed = pg.key.get_pressed() if key_pressed[pg.K_UP]: self.player.moveYCOORD(-5) + self.enemy.moveYCOORD(-5) elif key_pressed[pg.K_DOWN]: self.player.moveYCOORD(5) + self.enemy.moveYCOORD(5) elif key_pressed[pg.K_LEFT]: self.player.moveXCOORD(-5) elif key_pressed[pg.K_RIGHT]: self.player.moveXCOORD(5) - - # Enemy Actions - - + return done def draw(self, screen): From 557cc7e52218a7370a06b9ef4168cb3fead8bd61 Mon Sep 17 00:00:00 2001 From: Val Date: Mon, 15 May 2023 22:02:33 -0700 Subject: [PATCH 10/30] cannon collisions & checking for hit --- week13/cannon.py | 80 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 8c19d1b..5f6a52d 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -5,6 +5,8 @@ pg.init() pg.font.init() +font = pg.font.SysFont("Arial", 40) + WHITE = (255, 255, 255) WHITE = (255, 255, 255) BLACK = (0, 0, 0) @@ -126,19 +128,29 @@ def set_angle(self, target_pos): self.angle = np.arctan2( target_pos[1] - self.coord[1], target_pos[0] - self.coord[0]) - def moveYCOORD(self, inc): + # handle y movement of cannons + def move_y_coord(self, inc): ''' Changes vertical position of the gun. ''' if (self.coord[1] > 30 or inc > 0) and (self.coord[1] < SCREEN_SIZE[1] - 30 or inc < 0): self.coord[1] += inc - - def moveXCOORD(self, inc): + # handle x movement of cannons + def move_x_coord(self, inc): ''' Changes horizontal position of the gun. ''' if (self.coord[0] - inc > 0 or inc > 0) and (self.coord[0] < SCREEN_SIZE[0] + inc or inc < 0): self.coord[0] += inc + + # handle collisions from ball to cannon + def check_collision(self, ball): + """ + Checks whether the cannon collides with a ball. + """ + x_collision = self.coord[0] - ball.rad <= ball.coord[0] <= self.coord[0] + self.coord[0] + y_collision = self.coord[1] - ball.rad <= ball.coord[1] <= self.coord[1] + self.coord[1] + return x_collision and y_collision def draw(self, screen): ''' @@ -155,7 +167,7 @@ def draw(self, screen): gun_shape.append((gun_pos + vec_2 - vec_1).tolist()) gun_shape.append((gun_pos - vec_1).tolist()) pg.draw.polygon(screen, self.color, gun_shape) - + class Target(GameObject): ''' @@ -244,6 +256,10 @@ class Manager: def __init__(self, n_targets=1): self.balls = [] + # create losing bool and losing_timer num + self.losing = False + self.losing_timer = None + # create player and enemy cannon self.player = Cannon([30, SCREEN_SIZE[1]//2], angle=0, max_pow=50, min_pow=10, color=RED) self.enemy = Cannon([770, SCREEN_SIZE[1]//2], @@ -262,12 +278,33 @@ def new_mission(self): 30 - max(0, self.score_t.score())))) self.targets.append(Target(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), 30 - max(0, self.score_t.score())))) + + # function for rendering loser screen + def render_lose_text(self): + text_surface = font.render("YOU LOSE!", True, RED) + text_rect = text_surface.get_rect(center=(SCREEN_SIZE[0] // 2, SCREEN_SIZE[1] // 2)) + screen.blit(text_surface, text_rect) def process(self, events, screen): ''' Runs all necessary method for each iteration. Adds new targets, if previous are destroyed. ''' done = self.handle_events(events) + + # if collide makes losing true + if self.losing: + # load in loser screen + screen.fill(BLACK) + self.render_lose_text() + pg.display.update() + + # allow a 2 second timer for it to run before quitting the game + if self.losing_timer is None: + self.losing_timer = pg.time.get_ticks() + if pg.time.get_ticks() - self.losing_timer >= 2000: + return True + + return False if pg.mouse.get_focused(): mouse_pos = pg.mouse.get_pos() @@ -288,7 +325,7 @@ def handle_events(self, events): ''' done = False - # Prep enemy tank + # prep enemy tank self.enemy.set_angle([90,0]) self.enemy.activate() self.enemy.gain() @@ -303,21 +340,22 @@ def handle_events(self, events): if event.button == 1: self.balls.append(self.player.strike()) self.score_t.b_used += 1 - # Once the player shots, the enemy will too + # once the player shots, the enemy will too if event.type == pg.MOUSEBUTTONUP: self.balls.append(self.enemy.strike()) + # player and enemy movement key_pressed = pg.key.get_pressed() if key_pressed[pg.K_UP]: - self.player.moveYCOORD(-5) - self.enemy.moveYCOORD(-5) + self.player.move_y_coord(-5) + self.enemy.move_y_coord(-5) elif key_pressed[pg.K_DOWN]: - self.player.moveYCOORD(5) - self.enemy.moveYCOORD(5) + self.player.move_y_coord(5) + self.enemy.move_y_coord(5) elif key_pressed[pg.K_LEFT]: - self.player.moveXCOORD(-5) + self.player.move_x_coord(-5) elif key_pressed[pg.K_RIGHT]: - self.player.moveXCOORD(5) + self.player.move_x_coord(5) return done @@ -329,8 +367,10 @@ def draw(self, screen): ball.draw(screen) for target in self.targets: target.draw(screen) + # draw player and enemy cannon self.player.draw(screen) self.enemy.draw(screen) + self.score_t.draw(screen) def move(self): @@ -363,7 +403,19 @@ def collide(self): for j in reversed(targets_c): self.score_t.t_destr += 1 self.targets.pop(j) - + + # Checks collisions between enemy's shells and player's cannon + player_collisions = [] + player_cannon = self.player + for i, ball in enumerate(self.balls): + if player_cannon.check_collision(ball): + player_collisions.append(i) + + # handle enemy cannon shell hitting player + player_collisions.sort() + for i in reversed(player_collisions): + self.losing = True + self.balls.pop(i) screen = pg.display.set_mode(SCREEN_SIZE) pg.display.set_caption("Cannon Game") @@ -382,4 +434,4 @@ def collide(self): pg.display.flip() -pg.quit() +pg.quit() \ No newline at end of file From 9fe2d1552eed74700aa3a34c3c9c24e7874552c3 Mon Sep 17 00:00:00 2001 From: Valen Date: Mon, 15 May 2023 22:19:05 -0700 Subject: [PATCH 11/30] Update README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a50973..e732d07 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,40 @@ -# python_programming_class -Python for programmers class +# Group Project: cannon.py +Python for Programmers -> CS2520 + +This week's group assignment involves refactoring and extending a previous project completed in class, with an emphasis on modular programming and object-oriented programming (OOP). You will work in a group of 2-4 students to modify the code, making it more adaptable and easily modifiable for various requirements or design preferences. The primary objective of this assignment is to create a well-organized and easily modifiable codebase utilizing structural, modular, and object-oriented programming techniques. + +__##Project Description__ +The Cannon Game project is a continuation of the project that we did in class. The assignment tasks are as follows: + +1. Implement various types of projectiles. +2. Develop several target types with different movement patterns. +3. Transform the cannon into a moving tank. (VAL DELEON) +4. Create "bombs" that will be dropped by targets onto the cannon. +5. Implement multiple cannons that can shoot at each other. (VAL DELEON) + +To get started, create a fork of the original project and work collaboratively to refactor the codebase. Organize the code into clear, concise, and reusable functions and modules that can be easily combined and modified as needed. Ensure that the code adheres to best practices and coding conventions for easy comprehension. + +Modular programming and OOP are important aspects of this assignment. Divide your code into separate, well-defined modules that perform specific tasks or represent specific components of your project. Each module should be self-contained and have a clear interface for interaction with other modules. + +In addition to modular programming, apply OOP principles by creating classes that represent the various components of the Cannon Game, such as projectiles, targets, tanks, and bombs. Use inheritance, encapsulation, and polymorphism to create a clear hierarchy of classes and promote code reusability and maintainability. + +Throughout the assignment, you are expected to communicate effectively with your group members using Git as a version control system. Git will help you collaborate, track changes, and resolve conflicts that may arise during development. Publish your final project on a GitHub page, complete with all necessary documentation and a clear README file. + +__##Assignment Rubric:__ +Code Organization (20 points) +Code is organized into modules, functions, and classes (10 points) +Proper use of structural, modular, and object-oriented programming techniques (10 points) +Functionality (20 points) +Code allows for easy modifications (10 points) +Project can be adapted to various requirements (10 points) +Collaboration (30 points) +Effective use of Git for collaboration (10 points) +Clear commit messages, documenting changes (10 points) +Active communication and teamwork (10 points) +Documentation (30 points) +Clear README file with instructions (10 points) +Well-documented code with comments (10 points) +Final project published on GitHub page (10 points) +Total: 100 points + +For a satisfactory grade, students should refactor the project using structural, modular, and object-oriented programming techniques, collaborate effectively, and present their work on a well-documented GitHub page. From 461cf2e514138c143745ab4fac63e7a87c56814a Mon Sep 17 00:00:00 2001 From: Valen Date: Mon, 15 May 2023 22:20:21 -0700 Subject: [PATCH 12/30] Update README.md --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e732d07..529f6cb 100644 --- a/README.md +++ b/README.md @@ -21,20 +21,20 @@ In addition to modular programming, apply OOP principles by creating classes tha Throughout the assignment, you are expected to communicate effectively with your group members using Git as a version control system. Git will help you collaborate, track changes, and resolve conflicts that may arise during development. Publish your final project on a GitHub page, complete with all necessary documentation and a clear README file. __##Assignment Rubric:__ -Code Organization (20 points) -Code is organized into modules, functions, and classes (10 points) -Proper use of structural, modular, and object-oriented programming techniques (10 points) -Functionality (20 points) -Code allows for easy modifications (10 points) -Project can be adapted to various requirements (10 points) -Collaboration (30 points) -Effective use of Git for collaboration (10 points) -Clear commit messages, documenting changes (10 points) -Active communication and teamwork (10 points) -Documentation (30 points) -Clear README file with instructions (10 points) -Well-documented code with comments (10 points) -Final project published on GitHub page (10 points) -Total: 100 points ++ Code Organization (20 points) ++ Code is organized into modules, functions, and classes (10 points) ++ Proper use of structural, modular, and object-oriented programming techniques (10 points) ++ Functionality (20 points) ++ Code allows for easy modifications (10 points) ++ Project can be adapted to various requirements (10 points) ++ Collaboration (30 points) ++ Effective use of Git for collaboration (10 points) ++ Clear commit messages, documenting changes (10 points) ++ Active communication and teamwork (10 points) ++ Documentation (30 points) ++ Clear README file with instructions (10 points) ++ Well-documented code with comments (10 points) ++ Final project published on GitHub page (10 points) +__Total: 100 points__ For a satisfactory grade, students should refactor the project using structural, modular, and object-oriented programming techniques, collaborate effectively, and present their work on a well-documented GitHub page. From c0ba0185ec13287aba74e3f20df08e0e1c143767 Mon Sep 17 00:00:00 2001 From: Valen Date: Mon, 15 May 2023 22:20:55 -0700 Subject: [PATCH 13/30] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 529f6cb..2bcdb75 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ The Cannon Game project is a continuation of the project that we did in class. T 1. Implement various types of projectiles. 2. Develop several target types with different movement patterns. -3. Transform the cannon into a moving tank. (VAL DELEON) +3. Transform the cannon into a moving tank. [VAL DELEON] 4. Create "bombs" that will be dropped by targets onto the cannon. -5. Implement multiple cannons that can shoot at each other. (VAL DELEON) +5. Implement multiple cannons that can shoot at each other. [VAL DELEON] To get started, create a fork of the original project and work collaboratively to refactor the codebase. Organize the code into clear, concise, and reusable functions and modules that can be easily combined and modified as needed. Ensure that the code adheres to best practices and coding conventions for easy comprehension. From d452677d08a35b6906a11d9777675a46e8786f3a Mon Sep 17 00:00:00 2001 From: Valen Date: Mon, 15 May 2023 22:21:24 -0700 Subject: [PATCH 14/30] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2bcdb75..4b0102b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Python for Programmers -> CS2520 This week's group assignment involves refactoring and extending a previous project completed in class, with an emphasis on modular programming and object-oriented programming (OOP). You will work in a group of 2-4 students to modify the code, making it more adaptable and easily modifiable for various requirements or design preferences. The primary objective of this assignment is to create a well-organized and easily modifiable codebase utilizing structural, modular, and object-oriented programming techniques. -__##Project Description__ +__Project Description__ The Cannon Game project is a continuation of the project that we did in class. The assignment tasks are as follows: 1. Implement various types of projectiles. @@ -20,7 +20,7 @@ In addition to modular programming, apply OOP principles by creating classes tha Throughout the assignment, you are expected to communicate effectively with your group members using Git as a version control system. Git will help you collaborate, track changes, and resolve conflicts that may arise during development. Publish your final project on a GitHub page, complete with all necessary documentation and a clear README file. -__##Assignment Rubric:__ +__Assignment Rubric:__ + Code Organization (20 points) + Code is organized into modules, functions, and classes (10 points) + Proper use of structural, modular, and object-oriented programming techniques (10 points) From b316a4d3d8e04e5b072af37afdcc7f34765508b9 Mon Sep 17 00:00:00 2001 From: Valen Date: Mon, 15 May 2023 22:21:45 -0700 Subject: [PATCH 15/30] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b0102b..4622d3a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Python for Programmers -> CS2520 This week's group assignment involves refactoring and extending a previous project completed in class, with an emphasis on modular programming and object-oriented programming (OOP). You will work in a group of 2-4 students to modify the code, making it more adaptable and easily modifiable for various requirements or design preferences. The primary objective of this assignment is to create a well-organized and easily modifiable codebase utilizing structural, modular, and object-oriented programming techniques. -__Project Description__ +__Project Description:__ The Cannon Game project is a continuation of the project that we did in class. The assignment tasks are as follows: 1. Implement various types of projectiles. From 977eab9f2ccaa753278dcc0f7b1c83f5924480be Mon Sep 17 00:00:00 2001 From: Valen Date: Tue, 16 May 2023 15:08:35 -0700 Subject: [PATCH 16/30] disclaimer on cannon mods --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4622d3a..c991016 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ The Cannon Game project is a continuation of the project that we did in class. T 3. Transform the cannon into a moving tank. [VAL DELEON] 4. Create "bombs" that will be dropped by targets onto the cannon. 5. Implement multiple cannons that can shoot at each other. [VAL DELEON] ++ *DISCLAIMER for 5*: If player gets hit by its own Shells, this will also invoke the losing screen To get started, create a fork of the original project and work collaboratively to refactor the codebase. Organize the code into clear, concise, and reusable functions and modules that can be easily combined and modified as needed. Ensure that the code adheres to best practices and coding conventions for easy comprehension. From 3d17ad077db3aacb8f003d0b558b7d7a5b38353c Mon Sep 17 00:00:00 2001 From: Valen Date: Tue, 16 May 2023 15:08:55 -0700 Subject: [PATCH 17/30] added period --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c991016..ee5e9fa 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The Cannon Game project is a continuation of the project that we did in class. T 3. Transform the cannon into a moving tank. [VAL DELEON] 4. Create "bombs" that will be dropped by targets onto the cannon. 5. Implement multiple cannons that can shoot at each other. [VAL DELEON] -+ *DISCLAIMER for 5*: If player gets hit by its own Shells, this will also invoke the losing screen ++ *DISCLAIMER for 5*: If player gets hit by its own Shells, this will also invoke the losing screen. To get started, create a fork of the original project and work collaboratively to refactor the codebase. Organize the code into clear, concise, and reusable functions and modules that can be easily combined and modified as needed. Ensure that the code adheres to best practices and coding conventions for easy comprehension. From 4bfa9d6664010ae8c78e9a1c74b32d3f44a282ab Mon Sep 17 00:00:00 2001 From: Vanisa Suadprathon <115329466+vaniboo1738@users.noreply.github.com> Date: Tue, 16 May 2023 15:14:28 -0700 Subject: [PATCH 18/30] Update README.md adding name to tasks --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ee5e9fa..76b10b0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ __Project Description:__ The Cannon Game project is a continuation of the project that we did in class. The assignment tasks are as follows: 1. Implement various types of projectiles. -2. Develop several target types with different movement patterns. +2. Develop several target types with different movement patterns. [VANISA SUADPRATHON] 3. Transform the cannon into a moving tank. [VAL DELEON] 4. Create "bombs" that will be dropped by targets onto the cannon. 5. Implement multiple cannons that can shoot at each other. [VAL DELEON] From 8569d9182964b212a0a30aac45566c3d6b279b98 Mon Sep 17 00:00:00 2001 From: jescubido <102789017+jescubido@users.noreply.github.com> Date: Tue, 16 May 2023 22:08:39 -0700 Subject: [PATCH 19/30] randomly change radius of projectile --- week13/cannon.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 5f6a52d..0733e0a 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -34,7 +34,7 @@ class Shell(GameObject): The ball class. Creates a ball, controls it's movement and implement it's rendering. ''' - def __init__(self, coord, vel, rad=20, color=None): + def __init__(self, coord, vel, rad=None, color=None): ''' Constructor method. Initializes ball's parameters and initial values. ''' @@ -43,6 +43,8 @@ def __init__(self, coord, vel, rad=20, color=None): if color == None: color = rand_color() self.color = color + if rad == None: + rad = randint(10,40) self.rad = rad self.is_alive = True @@ -434,4 +436,4 @@ def collide(self): pg.display.flip() -pg.quit() \ No newline at end of file +pg.quit() From 6b513de05d5790c2c1fbd5ad9276fd1b428fce00 Mon Sep 17 00:00:00 2001 From: jescubido <102789017+jescubido@users.noreply.github.com> Date: Tue, 16 May 2023 22:10:17 -0700 Subject: [PATCH 20/30] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76b10b0..0417cd1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This week's group assignment involves refactoring and extending a previous proje __Project Description:__ The Cannon Game project is a continuation of the project that we did in class. The assignment tasks are as follows: -1. Implement various types of projectiles. +1. Implement various types of projectiles. [JARISSE ESCUBIDO] 2. Develop several target types with different movement patterns. [VANISA SUADPRATHON] 3. Transform the cannon into a moving tank. [VAL DELEON] 4. Create "bombs" that will be dropped by targets onto the cannon. From 39b6cadfac81bb10a9d10d79f988b93fcb47bc61 Mon Sep 17 00:00:00 2001 From: Vanisa Suadprathon <115329466+vaniboo1738@users.noreply.github.com> Date: Tue, 16 May 2023 22:25:53 -0700 Subject: [PATCH 21/30] Update cannon.py created targets --- week13/cannon.py | 224 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 207 insertions(+), 17 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 0733e0a..cf2a114 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -1,5 +1,6 @@ import numpy as np import pygame as pg +import math from random import randint, gauss pg.init() @@ -34,7 +35,7 @@ class Shell(GameObject): The ball class. Creates a ball, controls it's movement and implement it's rendering. ''' - def __init__(self, coord, vel, rad=None, color=None): + def __init__(self, coord, vel, rad=20, color=None): ''' Constructor method. Initializes ball's parameters and initial values. ''' @@ -43,8 +44,6 @@ def __init__(self, coord, vel, rad=None, color=None): if color == None: color = rand_color() self.color = color - if rad == None: - rad = randint(10,40) self.rad = rad self.is_alive = True @@ -171,18 +170,21 @@ def draw(self, screen): pg.draw.polygon(screen, self.color, gun_shape) -class Target(GameObject): +''' +This is the original code. However, the class name has changed as there will be more +targets. Changing the class name will allow for more differntiation and will make it easier +to program other targets. +''' +class Circle_Target(GameObject): ''' Target class. Creates target, manages it's rendering and collision with a ball event. ''' - def __init__(self, coord=None, color=None, rad=30): ''' Constructor method. Sets coordinate, color and radius of the target. ''' if coord == None: - coord = [randint(rad, SCREEN_SIZE[0] - rad), - randint(rad, SCREEN_SIZE[1] - rad)] + coord = [randint(rad, SCREEN_SIZE[0] - rad), randint(rad, SCREEN_SIZE[1] - rad)] self.coord = coord self.rad = rad @@ -211,17 +213,194 @@ def move(self): """ pass +''' +Creating a still rectangular targets. These targets will differ from the other targets since the +colors will be randomized and will have no motion at all. +''' +class Still_Rect_Target(GameObject): + ''' + Rectangle Target class. Creates rectangular target, manages it's rendering and collision with a ball event. + ''' + def __init__(self, coord=None, color=None, width=60, height=30): + if coord is None: + coord = [randint(width, SCREEN_SIZE[0] - width), randint(height, SCREEN_SIZE[1] - height)] + self.coord = coord + self.width = width + self.height = height -class MovingTargets(Target): - def __init__(self, coord=None, color=None, rad=30): - super().__init__(coord, color, rad) - self.vx = randint(-2, +2) - self.vy = randint(-2, +2) + if color is None: + color = rand_color() + self.color = color + + def check_collision(self, ball): + ''' + Checks whether the ball bumps into rectangular target. + ''' + if isinstance(ball, Shell): + ball_pos = np.array(ball.coord) + closest_point = np.clip(ball_pos, self.coord - np.array([self.width / 2, self.height / 2]), self.coord + np.array([self.width / 2, self.height / 2])) + distance = np.linalg.norm(ball_pos - closest_point) + return distance <= ball.rad + + return False + + def draw(self, screen): + ''' + Draws the target on the screen + ''' + pg.draw.rect(screen, self.color, (self.coord[0] - self.width / 2, self.coord[1] - self.height / 2, self.width, self.height)) + + def move(self): + """ + This type of target can't move at all. + :return: None + """ + pass + +''' +This class is similar to the previous rectangular target class above. However, this class will have a standardized color +and the target will constantly be moving, unless hit by projectile. The color of this target will be WHITE to differentiate +itself from the other targets, especially the other rectangular one. +''' +class Moving_Rect_Target(GameObject): + ''' + Rectangle Target class. Creates still rectangular target, manages it's rendering and collision with a ball event. + ''' + def __init__(self, coord=None, color=None, width=60, height=30): + if coord is None: + coord = [randint(width, SCREEN_SIZE[0] - width), randint(height, SCREEN_SIZE[1] - height)] + self.coord = coord + self.width = width + self.height = height + + if color is None: + color = WHITE + self.color = color + + def check_collision(self, ball): + ''' + Checks whether the ball bumps into rectangular target. + ''' + if isinstance(ball, Shell): + ball_pos = np.array(ball.coord) + closest_point = np.clip(ball_pos, self.coord - np.array([self.width / 2, self.height / 2]), self.coord + np.array([self.width / 2, self.height / 2])) + distance = np.linalg.norm(ball_pos - closest_point) + return distance <= ball.rad + return False + + def draw(self, screen): + ''' + Draws the target on the screen + ''' + pg.draw.rect(screen, WHITE, (self.coord[0] - self.width / 2, self.coord[1] - self.height / 2, self.width, self.height)) def move(self): + """ + This type of target can't move at all. + :return: None + """ + pass + +''' +Creating a triangular target that will make it difficult to hit the other targets. Additionally, it will +also make it slightly more easier to hit them as well. The goal is for the projectiles to bounce off/on the +triangle. The player can use the triangle to reach other targets. Along with this, the triangle's movement will +be in a circular motion which will be implemented in the moving target class. +''' + +class Triangular_Target(GameObject): + ''' + Target class. Creates triangular target, manages it's rendering and collision with a ball event. + ''' + def __init__(self, coord=None, color=None, rad=30): + ''' + Constructor method. Sets coordinate, color and radius of the target. + ''' + if coord == None: + coord = [randint(100, SCREEN_SIZE[0]-100), randint(100, SCREEN_SIZE[1]-100)] + self.coord = coord + if color == None: + color = rand_color() + self.color = color + self.rad = rad + self.exists = True + + def check_collision(self, ball): + ''' + Checks if ball collides with the triangular target. Implements elastic collision. + ''' + dist = np.sqrt((ball.coord[0] - self.coord[0])**2 + (ball.coord[1] - self.coord[1])**2) + if dist < self.rad + ball.rad: + norm_vec = np.array([self.coord[0] - ball.coord[0], self.coord[1] - ball.coord[1]]) + tang_vec = np.array([-norm_vec[1], norm_vec[0]]) + ball_vel = np.array(ball.vel) + ball_vel_norm = np.dot(norm_vec, ball_vel) / np.linalg.norm(norm_vec) + ball_vel_tang = np.dot(tang_vec, ball_vel) / np.linalg.norm(tang_vec) + ball_vel_norm_new = - ball_vel_norm + ball_vel_new = ball_vel_norm_new * norm_vec / np.linalg.norm(norm_vec) + ball_vel_tang * tang_vec / np.linalg.norm(tang_vec) + ball.vel = ball_vel_new.astype(int) + + def draw(self, screen): + ''' + Draws the target on the screen. + ''' + if self.exists: + vertices = [(self.coord[0], self.coord[1] - self.rad), + (self.coord[0] - self.rad, self.coord[1] + self.rad), + + (self.coord[0] + self.rad, self.coord[1] + self.rad)] + pg.draw.polygon(screen, self.color, vertices) + + + +#These classes will control the movements of the targets. +class MovingTargets_Circle(Circle_Target): + def __init__(self, coord=None, color=None, rad=30): + super().__init__(coord, color, rad) + self.vx = randint(-2, +2) + self.vy = randint(-2, +2) + + def move(self): + self.coord[0] += self.vx + self.coord[1] += self.vy + +#controls the moving (white) rectangles. Will also bounce off of the screen, similar to the projectiles. +class MovingTargets_Rect(Moving_Rect_Target): + def __init__(self, coord=None, color=None, rad=30): + super().__init__(coord, color, rad) + self.vx = randint(-2, +2) + self.vy = randint(-2, +2) + + def move(self): self.coord[0] += self.vx self.coord[1] += self.vy + ''' + This set of if statements are used to control the motion of the target. It will match its + coordinates to those of the screen's edges and corners so that when it reaches it, it will + bounce off instead of falling off the screen. + ''' + if self.coord[0] < self.width / 2 or self.coord[0] > SCREEN_SIZE[0] - self.width / 2: + self.vx = -self.vx + if self.coord[1] < self.height / 2 or self.coord[1] > SCREEN_SIZE[1] - self.height / 2: + self.vy = -self.vy + +''' +Controls the movement of the triangular target. This target differs from the other targets as +it follows a circular motion. This is implemented using cos and sin functions that follow the +motions of a circle. +''' +class MovingTargets_Tri(Triangular_Target): + def __init__(self, coord=None, color=None, rad=60, radius=100, speed=0.05): + super().__init__(coord, color, rad) + self.radius = radius + self.angle = 0 + self.speed = speed + + def move(self): + self.coord[0] = self.radius * np.cos(self.angle) + SCREEN_SIZE[0] // 2 + self.coord[1] = self.radius * np.sin(self.angle) + SCREEN_SIZE[1] // 2 + self.angle += self.speed class ScoreTable: ''' @@ -273,13 +452,24 @@ def __init__(self, n_targets=1): def new_mission(self): ''' - Adds new targets. + Adds new targets. Only 3 of the MovingTargets classes are used. This is because the only moving targets + will be the moving circular targets provided by the original code, the white rectangles that will bounce + off of the screen, and the triangle target that moves in a cirle. ''' for i in range(self.n_targets): - self.targets.append(MovingTargets(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), - 30 - max(0, self.score_t.score())))) - self.targets.append(Target(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), - 30 - max(0, self.score_t.score())))) + #adds the moving circle, rectangle, and triangle targets into the game + self.targets.append(MovingTargets_Circle(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), + 30 - max(0, self.score_t.score())))) + self.targets.append(MovingTargets_Rect(coord=[randint(30, SCREEN_SIZE[0] - 30), + randint(30, SCREEN_SIZE[1] - 30)])) + self.targets.append(MovingTargets_Tri(coord=[randint(30, SCREEN_SIZE[0] - 30), + randint(30, SCREEN_SIZE[1] - 30)])) + + #adds the still circle and rectangle targets into the game + self.targets.append(Circle_Target(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), + 30 - max(0, self.score_t.score())))) + self.targets.append(Still_Rect_Target(coord=[randint(30, SCREEN_SIZE[0] - 30), + randint(30, SCREEN_SIZE[1] - 30)])) # function for rendering loser screen def render_lose_text(self): From 003ca0719d2b17c634da997d63fbf06e72e0dbf9 Mon Sep 17 00:00:00 2001 From: Valen Date: Tue, 16 May 2023 22:54:39 -0700 Subject: [PATCH 22/30] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0417cd1..e613906 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The Cannon Game project is a continuation of the project that we did in class. T 1. Implement various types of projectiles. [JARISSE ESCUBIDO] 2. Develop several target types with different movement patterns. [VANISA SUADPRATHON] 3. Transform the cannon into a moving tank. [VAL DELEON] -4. Create "bombs" that will be dropped by targets onto the cannon. +4. Create "bombs" that will be dropped by targets onto the cannon. [GEORGE FRANSIS] 5. Implement multiple cannons that can shoot at each other. [VAL DELEON] + *DISCLAIMER for 5*: If player gets hit by its own Shells, this will also invoke the losing screen. From d3db8f30062b640f33a05ce39bdcccc0034c6125 Mon Sep 17 00:00:00 2001 From: jescubido Date: Tue, 16 May 2023 22:56:46 -0700 Subject: [PATCH 23/30] restore override changes --- week13/cannon.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/week13/cannon.py b/week13/cannon.py index cf2a114..2ce43e7 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -35,7 +35,7 @@ class Shell(GameObject): The ball class. Creates a ball, controls it's movement and implement it's rendering. ''' - def __init__(self, coord, vel, rad=20, color=None): + def __init__(self, coord, vel, rad=None, color=None): ''' Constructor method. Initializes ball's parameters and initial values. ''' @@ -44,6 +44,8 @@ def __init__(self, coord, vel, rad=20, color=None): if color == None: color = rand_color() self.color = color + if rad == None: + rad = randint(10,40) self.rad = rad self.is_alive = True From e5803d6ecd2603030eec3a757cafe38ae3f15239 Mon Sep 17 00:00:00 2001 From: jescubido Date: Tue, 16 May 2023 22:59:53 -0700 Subject: [PATCH 24/30] remove targets --- week13/cannon.py | 69 ++++++++---------------------------------------- 1 file changed, 11 insertions(+), 58 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 2ce43e7..4993fd8 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -35,7 +35,7 @@ class Shell(GameObject): The ball class. Creates a ball, controls it's movement and implement it's rendering. ''' - def __init__(self, coord, vel, rad=None, color=None): + def __init__(self, coord, vel, rad=20, color=None): ''' Constructor method. Initializes ball's parameters and initial values. ''' @@ -44,8 +44,6 @@ def __init__(self, coord, vel, rad=None, color=None): if color == None: color = rand_color() self.color = color - if rad == None: - rad = randint(10,40) self.rad = rad self.is_alive = True @@ -216,57 +214,14 @@ def move(self): pass ''' -Creating a still rectangular targets. These targets will differ from the other targets since the -colors will be randomized and will have no motion at all. +Creating rectangular targets. This class will have a standardized color and the target +will constantly be moving, unless hit by projectile. The color of this target will be WHITE to differentiate +itself from the other targets. ''' -class Still_Rect_Target(GameObject): - ''' - Rectangle Target class. Creates rectangular target, manages it's rendering and collision with a ball event. - ''' - def __init__(self, coord=None, color=None, width=60, height=30): - if coord is None: - coord = [randint(width, SCREEN_SIZE[0] - width), randint(height, SCREEN_SIZE[1] - height)] - self.coord = coord - self.width = width - self.height = height - if color is None: - color = rand_color() - self.color = color - - def check_collision(self, ball): - ''' - Checks whether the ball bumps into rectangular target. - ''' - if isinstance(ball, Shell): - ball_pos = np.array(ball.coord) - closest_point = np.clip(ball_pos, self.coord - np.array([self.width / 2, self.height / 2]), self.coord + np.array([self.width / 2, self.height / 2])) - distance = np.linalg.norm(ball_pos - closest_point) - return distance <= ball.rad - - return False - - def draw(self, screen): - ''' - Draws the target on the screen - ''' - pg.draw.rect(screen, self.color, (self.coord[0] - self.width / 2, self.coord[1] - self.height / 2, self.width, self.height)) - - def move(self): - """ - This type of target can't move at all. - :return: None - """ - pass - -''' -This class is similar to the previous rectangular target class above. However, this class will have a standardized color -and the target will constantly be moving, unless hit by projectile. The color of this target will be WHITE to differentiate -itself from the other targets, especially the other rectangular one. -''' -class Moving_Rect_Target(GameObject): +class Rect_Target(GameObject): ''' - Rectangle Target class. Creates still rectangular target, manages it's rendering and collision with a ball event. + Rectangle Target class. Creates rectangular target, manages it's rendering and collision with a ball event. ''' def __init__(self, coord=None, color=None, width=60, height=30): if coord is None: @@ -366,8 +321,8 @@ def move(self): self.coord[0] += self.vx self.coord[1] += self.vy -#controls the moving (white) rectangles. Will also bounce off of the screen, similar to the projectiles. -class MovingTargets_Rect(Moving_Rect_Target): +#controls the moving rectangles. Will also bounce off of the screen, similar to the projectiles. +class MovingTargets_Rect(Rect_Target): def __init__(self, coord=None, color=None, rad=30): super().__init__(coord, color, rad) self.vx = randint(-2, +2) @@ -393,7 +348,7 @@ def move(self): motions of a circle. ''' class MovingTargets_Tri(Triangular_Target): - def __init__(self, coord=None, color=None, rad=60, radius=100, speed=0.05): + def __init__(self, coord=None, color=None, rad=30, radius=100, speed=0.05): super().__init__(coord, color, rad) self.radius = radius self.angle = 0 @@ -467,11 +422,9 @@ def new_mission(self): self.targets.append(MovingTargets_Tri(coord=[randint(30, SCREEN_SIZE[0] - 30), randint(30, SCREEN_SIZE[1] - 30)])) - #adds the still circle and rectangle targets into the game + #adds the still circle targets into the game self.targets.append(Circle_Target(rad=randint(max(1, 30 - 2*max(0, self.score_t.score())), 30 - max(0, self.score_t.score())))) - self.targets.append(Still_Rect_Target(coord=[randint(30, SCREEN_SIZE[0] - 30), - randint(30, SCREEN_SIZE[1] - 30)])) # function for rendering loser screen def render_lose_text(self): @@ -628,4 +581,4 @@ def collide(self): pg.display.flip() -pg.quit() +pg.quit() \ No newline at end of file From 9db919f98f6bbffc1a92f310bd57c43e65178def Mon Sep 17 00:00:00 2001 From: jescubido Date: Tue, 16 May 2023 23:03:50 -0700 Subject: [PATCH 25/30] fix color condition --- week13/cannon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 4993fd8..dec9c4c 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -230,8 +230,8 @@ def __init__(self, coord=None, color=None, width=60, height=30): self.width = width self.height = height - if color is None: - color = WHITE + if color == None: + color = rand_color() self.color = color def check_collision(self, ball): From df039bc5009d6724bc4f75a2b5c9389cf74ed3f2 Mon Sep 17 00:00:00 2001 From: jescubido Date: Tue, 16 May 2023 23:11:57 -0700 Subject: [PATCH 26/30] create rectangle projectile --- week13/cannon.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/week13/cannon.py b/week13/cannon.py index dec9c4c..3b10857 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -79,6 +79,68 @@ def draw(self, screen): ''' pg.draw.circle(screen, self.color, self.coord, self.rad) +class RectangleProjectile(GameObject): + ''' + The ball class. Creates a ball, controls it's movement and implement it's rendering. + ''' + + def __init__(self, coord, vel, height=20, width=30, color=None): + ''' + Constructor method. Initializes ball's parameters and initial values. + ''' + self.coord = coord + self.vel = vel + if color == None: + color = rand_color() + self.color = color + self.height = height + self.width = width + self.is_alive = True + + def check_corners(self, refl_ort=0.8, refl_par=0.9): + ''' + Reflects ball's velocity when ball bumps into the screen corners. Implemetns inelastic rebounce. + ''' + for i in range(2): + if self.coord[i] < self.height: + self.coord[i] = self.height + self.vel[i] = -int(self.vel[i] * refl_ort) + self.vel[1-i] = int(self.vel[1-i] * refl_par) + elif self.coord[i] > SCREEN_SIZE[i] - self.height: + self.coord[i] = SCREEN_SIZE[i] - self.height + self.vel[i] = -int(self.vel[i] * refl_ort) + self.vel[1-i] = int(self.vel[1-i] * refl_par) + for i in range(2): + if self.coord[i] < self.width: + self.coord[i] = self.width + self.vel[i] = -int(self.vel[i] * refl_ort) + self.vel[1-i] = int(self.vel[1-i] * refl_par) + elif self.coord[i] > SCREEN_SIZE[i] - self.width: + self.coord[i] = SCREEN_SIZE[i] - self.width + self.vel[i] = -int(self.vel[i] * refl_ort) + self.vel[1-i] = int(self.vel[1-i] * refl_par) + + def move(self, time=1, grav=0): + ''' + Moves the ball according to it's velocity and time step. + Changes the ball's velocity due to gravitational force. + ''' + self.vel[1] += grav + for i in range(2): + self.coord[i] += time * self.vel[i] + self.check_corners() + if self.vel[0]**2 + self.vel[1]**2 < 2**2 and self.coord[1] > SCREEN_SIZE[1] - 2*self.height: + self.is_alive = False + self.check_corners() + if self.vel[0]**2 + self.vel[1]**2 < 2**2 and self.coord[1] > SCREEN_SIZE[1] - 2*self.width: + self.is_alive = False + + def draw(self, screen): + ''' + Draws the ball on appropriate surface. + ''' + pg.draw.rect(screen, self.color, self.coord, self.height, self.width) + class Cannon(GameObject): ''' @@ -118,6 +180,8 @@ def strike(self): angle = self.angle ball = Shell(list(self.coord), [ int(vel * np.cos(angle)), int(vel * np.sin(angle))]) + rectangle = RectangleProjectile(list(self.coord), [ + int(vel * np.cos(angle)), int(vel * np.sin(angle))]) self.pow = self.min_pow self.active = False return ball From 8a7db8b93d2e361cee0b8a1470f15f15342caa65 Mon Sep 17 00:00:00 2001 From: jescubido Date: Tue, 16 May 2023 23:14:53 -0700 Subject: [PATCH 27/30] fix comments and add rectangle to cannon --- week13/cannon.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 3b10857..d25ecd4 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -81,12 +81,12 @@ def draw(self, screen): class RectangleProjectile(GameObject): ''' - The ball class. Creates a ball, controls it's movement and implement it's rendering. + The rectangle class. Creates a rectangle, controls it's movement and implement it's rendering. ''' def __init__(self, coord, vel, height=20, width=30, color=None): ''' - Constructor method. Initializes ball's parameters and initial values. + Constructor method. Initializes rectangle's parameters and initial values. ''' self.coord = coord self.vel = vel @@ -99,7 +99,7 @@ def __init__(self, coord, vel, height=20, width=30, color=None): def check_corners(self, refl_ort=0.8, refl_par=0.9): ''' - Reflects ball's velocity when ball bumps into the screen corners. Implemetns inelastic rebounce. + Reflects rectangle's velocity when rectangle bumps into the screen corners. Implements inelastic rebounce. ''' for i in range(2): if self.coord[i] < self.height: @@ -122,8 +122,8 @@ def check_corners(self, refl_ort=0.8, refl_par=0.9): def move(self, time=1, grav=0): ''' - Moves the ball according to it's velocity and time step. - Changes the ball's velocity due to gravitational force. + Moves the rectangle according to it's velocity and time step. + Changes the rectangle's velocity due to gravitational force. ''' self.vel[1] += grav for i in range(2): @@ -137,7 +137,7 @@ def move(self, time=1, grav=0): def draw(self, screen): ''' - Draws the ball on appropriate surface. + Draws the rectangle on appropriate surface. ''' pg.draw.rect(screen, self.color, self.coord, self.height, self.width) @@ -174,7 +174,7 @@ def gain(self, inc=2): def strike(self): ''' - Creates ball, according to gun's direction and current charge power. + Creates ball and rectangle, according to gun's direction and current charge power. ''' vel = self.pow angle = self.angle @@ -184,7 +184,7 @@ def strike(self): int(vel * np.cos(angle)), int(vel * np.sin(angle))]) self.pow = self.min_pow self.active = False - return ball + return rectangle def set_angle(self, target_pos): ''' From 91412cc2f92bc239a8c5f4bc7b917b790e037add Mon Sep 17 00:00:00 2001 From: jescubido Date: Tue, 16 May 2023 23:17:26 -0700 Subject: [PATCH 28/30] change return statement --- week13/cannon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/week13/cannon.py b/week13/cannon.py index d25ecd4..218d85f 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -184,7 +184,7 @@ def strike(self): int(vel * np.cos(angle)), int(vel * np.sin(angle))]) self.pow = self.min_pow self.active = False - return rectangle + return ball or rectangle def set_angle(self, target_pos): ''' From 6e4b2103905668ffdcb6e33128575046f40b6689 Mon Sep 17 00:00:00 2001 From: Valen Date: Tue, 16 May 2023 23:53:09 -0700 Subject: [PATCH 29/30] Target Bombs - Buggy Code --- week13/cannon.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/week13/cannon.py b/week13/cannon.py index 218d85f..47e3247 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -405,6 +405,19 @@ def move(self): self.vx = -self.vx if self.coord[1] < self.height / 2 or self.coord[1] > SCREEN_SIZE[1] - self.height / 2: self.vy = -self.vy + + ''' + COMMENT AND UNCOMMENT AS NEEDED - BUGGY CODE + ''' + # Draw the circle dropped from the target + # Position below the target + circle_pos = (self.coord[0], self.coord[1] + self.rad + 10) + circle_radius = 5 # Radius of the circle + circle_color = (255, 0, 0) # Color of the circle (red) + pg.draw.circle(screen, circle_color, circle_pos, circle_radius) + ''' + END BUGGY CODE + ''' ''' Controls the movement of the triangular target. This target differs from the other targets as @@ -627,6 +640,18 @@ def collide(self): for i in reversed(player_collisions): self.losing = True self.balls.pop(i) + + ''' + COMMENT AND UNCOMMENT AS NEEDED - BUGGY CODE + ''' + # check collision between player cannon and moving bomb target (MovingTarget) + for j, target in enumerate(self.targets): + if player_cannon.check_collision(target): + self.losing = True + break + ''' + END BUGGY CODE + ''' screen = pg.display.set_mode(SCREEN_SIZE) pg.display.set_caption("Cannon Game") @@ -645,4 +670,4 @@ def collide(self): pg.display.flip() -pg.quit() \ No newline at end of file +pg.quit() From 098f2a647a13ba2131270fe77ff87b42e1f67322 Mon Sep 17 00:00:00 2001 From: Val Date: Tue, 16 May 2023 23:54:45 -0700 Subject: [PATCH 30/30] Commented out buggy code --- week13/cannon.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/week13/cannon.py b/week13/cannon.py index 47e3247..4913ed4 100644 --- a/week13/cannon.py +++ b/week13/cannon.py @@ -409,12 +409,12 @@ def move(self): ''' COMMENT AND UNCOMMENT AS NEEDED - BUGGY CODE ''' - # Draw the circle dropped from the target - # Position below the target - circle_pos = (self.coord[0], self.coord[1] + self.rad + 10) - circle_radius = 5 # Radius of the circle - circle_color = (255, 0, 0) # Color of the circle (red) - pg.draw.circle(screen, circle_color, circle_pos, circle_radius) + # # Draw the circle dropped from the target + # # Position below the target + # circle_pos = (self.coord[0], self.coord[1] + self.rad + 10) + # circle_radius = 5 # Radius of the circle + # circle_color = (255, 0, 0) # Color of the circle (red) + # pg.draw.circle(screen, circle_color, circle_pos, circle_radius) ''' END BUGGY CODE ''' @@ -644,11 +644,11 @@ def collide(self): ''' COMMENT AND UNCOMMENT AS NEEDED - BUGGY CODE ''' - # check collision between player cannon and moving bomb target (MovingTarget) - for j, target in enumerate(self.targets): - if player_cannon.check_collision(target): - self.losing = True - break + # # check collision between player cannon and moving bomb target (MovingTarget) + # for j, target in enumerate(self.targets): + # if player_cannon.check_collision(target): + # self.losing = True + # break ''' END BUGGY CODE '''