class AstroRockets: def __init__(self, size, title, background): self.width = size[0] self.height = size[1] self.background = background self.clock = pygame.time.Clock() self.FPS = 60 self.running = True self.win = pygame.display.set_mode(size) pygame.display.set_caption(title) # ###################### # # ### Ignore this 🔼 ### # # ###################### # def start(self): self.p1 = Rocket(self.width / 2 - 250, self.height / 2, (255, 0, 0)) self.p2 = Rocket(self.width / 2 + 250, self.height / 2, (0, 0, 255)) self.p2.heading = 180 self.p2.drift_heading = 180 self.levels = [(Wall(5, 5, 1, self.height), Wall(5, 5, self.width, 1), Wall(self.width - 5, 5, 1, self.height), Wall(5, self.height - 5, self.width, 1), Wall(100, 100, 300, 135), Wall(900, 450, 150, 250)), (Wall(5, 5, 1, self.height / 2 - 150), Wall(5, self.height / 2 + 150, 1, self.height / 2 - 150), Wall(5, 5, self.width, 1), Wall(self.width - 5, 5, 1, self.height / 2 - 150), Wall(self.width - 5, self.height / 2 + 150, 1, self.height / 2 - 150), Wall(5, self.height - 5, self.width, 1))] self.current_level = randint(0, len(self.levels) - 1) def logic(self): keys = pygame.key.get_pressed() # speed = 5 acceleration = 0.3 turn_speed = 3 friction = 0.974 recoil = -5 # Player 1 controls if keys[pygame.K_w]: self.p1.accelerate(acceleration) self.p1.speed *= friction if keys[pygame.K_s]: if not self.p1.bullet_is_shot: b = Bullet(self.p1.x, self.p1.y, self.p1.drift_heading, self.p1.color) self.p1.bullets.append(b) self.p1.bullet_is_shot = True self.p1.shoot_timer = 0 self.p1.accelerate(recoil) if keys[pygame.K_a]: self.p1.drift_heading -= turn_speed if keys[pygame.K_d]: self.p1.drift_heading += turn_speed # Player 2 controls if keys[pygame.K_UP]: self.p2.accelerate(acceleration) self.p2.speed *= friction if keys[pygame.K_DOWN]: if not self.p2.bullet_is_shot: b = Bullet(self.p2.x, self.p2.y, self.p2.drift_heading, self.p2.color) self.p2.bullets.append(b) self.p2.bullet_is_shot = True self.p2.shoot_timer = 0 self.p2.accelerate(recoil) if keys[pygame.K_LEFT]: self.p2.drift_heading -= turn_speed if keys[pygame.K_RIGHT]: self.p2.drift_heading += turn_speed self.p1.update() self.p2.update() despawn_time = 200 for bullet in self.p1.bullets: bullet.update() if bullet.x < 0: bullet.x = self.width elif bullet.x > self.width: bullet.x = 0 if bullet.y < 0: bullet.y = self.height elif bullet.y > self.height: bullet.y = 0 bullet.update_collider() if self.collision_circle(bullet.x, bullet.y, bullet.radius, self.p2.x, self.p2.y, self.p2.collider_size): print("RED WINS!!") sleep(3) self.running = False if bullet.despawn_timer > despawn_time: self.p1.bullets.remove(bullet) for bullet in self.p2.bullets: bullet.update() if bullet.x < 0: bullet.x = self.width elif bullet.x > self.width: bullet.x = 0 if bullet.y < 0: bullet.y = self.height elif bullet.y > self.height: bullet.y = 0 bullet.update_collider() if self.collision_circle(bullet.x, bullet.y, bullet.radius, self.p1.x, self.p1.y, self.p1.collider_size): print("BLUE WINS!!") sleep(3) self.running = False if bullet.despawn_timer > despawn_time: self.p2.bullets.remove(bullet) # Player 1 boundary collisions if self.p1.x < 0: self.p1.x = self.width elif self.p1.x > self.width: self.p1.x = 0 if self.p1.y < 0: self.p1.y = self.height elif self.p1.y > self.height: self.p1.y = 0 # Player 2 boundary collisions if self.p2.x < 0: self.p2.x = self.width elif self.p2.x > self.width: self.p2.x = 0 if self.p2.y < 0: self.p2.y = self.height elif self.p2.y > self.height: self.p2.y = 0 self.p1.update_collider() self.p2.update_collider() # Handle collisions between rockets and walls for wall in self.levels[self.current_level]: # Player 1 if wall.collider.colliderect(self.p1.wall_collider): self.p1.x = self.p1.old_x self.p1.y = self.p1.old_y self.p1.speed = 0 # Player 2 if wall.collider.colliderect(self.p2.wall_collider): self.p2.x = self.p2.old_x self.p2.y = self.p2.old_y self.p2.speed = 0 # Handle collisions between bullets and walls for wall in self.levels[self.current_level]: # Player 1 for bullet in self.p1.bullets: if bullet.wall_collider.colliderect(wall.collider): self.p1.bullets.remove(bullet) # Player 2 for bullet in self.p2.bullets: if bullet.wall_collider.colliderect(wall.collider): self.p2.bullets.remove(bullet) self.p1.update_old_coords() self.p2.update_old_coords() def render(self): self.p1.render(self.win) self.p2.render(self.win) for bullet in self.p1.bullets: bullet.render(self.win) for bullet in self.p2.bullets: bullet.render(self.win) for wall in self.levels[self.current_level]: wall.render(self.win) # Gameplay functions def dist(self, x1, y1, x2, y2): """Finds the distance between 2 points on a 2D plane using the Pythagorean Theorem. a^2 + b^2 = c^2 Arguments: x1 {int} y1 {int} x2 {int} y2 {int} Returns: int -- distance between the two points """ a = x1 - x2 b = y1 - y2 c = sqrt((a**2) + (b**2)) return c def collision_circle(self, x1, y1, r1, x2, y2, r2): """Finds out whether two circlea are overlapping using dist() function Arguments: x1 {int} -- x position of first circle y1 {int} -- y position of first circle r1 {int} -- radius of first circle x2 {int} -- x position of second circle y2 {int} -- y position of second circle r2 {int} -- radius of second circle Returns: bool -- Are the 2 circle overlapping """ d = self.dist(x1, y1, x2, y2) if d <= r1 + r2: return True
class AstroRockets: def __init__(self, size, title, background): self.width = size[0] self.height = size[1] self.background = background self.clock = pygame.time.Clock() self.FPS = 60 self.running = True self.game_over = False self.win = pygame.display.set_mode(size) pygame.display.set_caption(title) # ##################### # # #### Ignore this #### # # ##################### # def start(self): self.p1 = Rocket(self.width / 2 - 250, self.height / 2, (255, 0, 0)) self.p2 = Rocket(self.width / 2 + 250, self.height / 2, (0, 0, 255)) self.p2.heading = 180 self.p2.drift_heading = 180 self.levels = [(Wall(5, 5, 1, self.height), Wall(5, 5, self.width, 1), Wall(self.width - 5, 5, 1, self.height), Wall(5, self.height - 5, self.width, 1), Wall(100, 100, 300, 135), Wall(900, 450, 150, 250)), (Wall(5, 5, 1, self.height / 2 - 150), Wall(5, self.height / 2 + 150, 1, self.height / 2 - 150), Wall(5, 5, self.width, 1), Wall(self.width - 5, 5, 1, self.height / 2 - 150), Wall(self.width - 5, self.height / 2 + 150, 1, self.height / 2 - 150), Wall(5, self.height - 5, self.width, 1))] self.current_level = randint(0, len(self.levels) - 1) self.powerup_ids = [ "none", # id = 0 "scatter_shot", # id = 1 "missile" # id = 2 ] self.powerups = [] self.powerup_spawn_timer = 0 def logic(self): # Randomly spawn powerups if self.powerup_spawn_timer % 600 == 0: if randint(0, 100) <= 50: # 50% chance of a powerups spawning powerup_id = self.powerup_ids[randint( 1, len(self.powerup_ids) - 1)] x = randint(5, self.width - 5) y = randint(5, self.height - 5) if powerup_id == "scatter_shot": powerup = ScatterShot(x, y) self.powerups.append(powerup) if powerup_id == "missile": powerup = Missile(x, y) self.powerups.append(powerup) keys = pygame.key.get_pressed() # speed = 5 acceleration = 0.25 turn_speed = 3 friction = 0.978 recoil = -5 despawn_time = 300 scattershot_count = 16 scattershot_speed = 12 missile_speed = 10 missile_fade = 150 # Player 1 controls if keys[pygame.K_w]: self.p1.accelerate(acceleration) if keys[pygame.K_s]: if not self.p1.bullet_is_shot: b = Bullet(self.p1.x, self.p1.y, self.p1.drift_heading, self.p1.color) self.p1.bullets.append(b) self.p1.bullet_is_shot = True self.p1.shoot_timer = 0 self.p1.accelerate(recoil) if keys[pygame.K_a]: self.p1.drift_heading -= turn_speed if keys[pygame.K_d]: self.p1.drift_heading += turn_speed # PowerUp Shooting for Player 1 if keys[pygame.K_e]: if self.powerup_ids[self.p1.current_powerup] == "none": print("No Powerup Collected!") elif self.powerup_ids[self.p1.current_powerup] == "scatter_shot": for i in range(scattershot_count): bullet_hdg = ( (360 / scattershot_count) * i) + self.p1.drift_heading b = Bullet(self.p1.x, self.p1.y, bullet_hdg, ScatterShot(0, 0).color) b.speed = scattershot_speed self.p1.bullets.append(b) elif self.powerup_ids[self.p1.current_powerup] == "missile": m = Bullet(self.p1.x, self.p1.y, self.p1.drift_heading, Missile(0, 0).color) m.speed = missile_speed self.p1.bullets.append(m) self.p1.accelerate(recoil) self.p1.assign_powerup(0) # Player 2 controls if keys[pygame.K_UP]: self.p2.accelerate(acceleration) if keys[pygame.K_DOWN]: if not self.p2.bullet_is_shot: b = Bullet(self.p2.x, self.p2.y, self.p2.drift_heading, self.p2.color) self.p2.bullets.append(b) self.p2.bullet_is_shot = True self.p2.shoot_timer = 0 self.p2.accelerate(recoil) if keys[pygame.K_LEFT]: self.p2.drift_heading -= turn_speed if keys[pygame.K_RIGHT]: self.p2.drift_heading += turn_speed # PowerUp Shooting for Player 2 if keys[pygame.K_RSHIFT] or keys[pygame.K_QUESTION]: if self.powerup_ids[self.p2.current_powerup] == "none": print("No Powerup Collected!") elif self.powerup_ids[self.p2.current_powerup] == "scatter_shot": for i in range(scattershot_count): bullet_hdg = ( (360 / scattershot_count) * i) + self.p2.drift_heading b = Bullet(self.p2.x, self.p2.y, bullet_hdg, ScatterShot(0, 0).color) b.speed = scattershot_speed self.p2.bullets.append(b) elif self.powerup_ids[self.p2.current_powerup] == "missile": m = Bullet(self.p2.x, self.p2.y, self.p2.drift_heading, Missile(0, 0).color) m.speed = missile_speed self.p2.bullets.append(m) self.p2.accelerate(recoil) self.p2.assign_powerup(0) self.p1.update() self.p1.speed *= friction self.p2.update() self.p2.speed *= friction # Update Player 1's Bullets for bullet in self.p1.bullets: bullet.update() if bullet.x < 0: bullet.x = self.width elif bullet.x > self.width: bullet.x = 0 if bullet.y < 0: bullet.y = self.height elif bullet.y > self.height: bullet.y = 0 bullet.update_collider() # Collision between player 2 and player 1's bullets if self.collision_circle(bullet.x, bullet.y, bullet.radius, self.p2.x, self.p2.y, self.p2.collider_size): if bullet.color != Missile(0, 0).color: print("RED WINS!!") sleep(3) self.running = False # Automatic despawn if bullet.despawn_timer > despawn_time: if bullet.color != Missile(0, 0).color: self.p1.bullets.remove(bullet) # Update Player 2's Bullets for bullet in self.p2.bullets: bullet.update() if bullet.x < 0: bullet.x = self.width elif bullet.x > self.width: bullet.x = 0 if bullet.y < 0: bullet.y = self.height elif bullet.y > self.height: bullet.y = 0 bullet.update_collider() # Collisions between player 1 and player 2's bullets if self.collision_circle(bullet.x, bullet.y, bullet.radius, self.p1.x, self.p1.y, self.p1.collider_size): if bullet.color != Missile(0, 0).color: print("BLUE WINS!!") sleep(3) self.running = False # Automatic despawn if bullet.despawn_timer > despawn_time: if bullet.color != Missile(0, 0).color: self.p2.bullets.remove(bullet) # Player 1 boundary collisions if self.p1.x < 0: self.p1.x = self.width elif self.p1.x > self.width: self.p1.x = 0 if self.p1.y < 0: self.p1.y = self.height elif self.p1.y > self.height: self.p1.y = 0 # Player 2 boundary collisions if self.p2.x < 0: self.p2.x = self.width elif self.p2.x > self.width: self.p2.x = 0 if self.p2.y < 0: self.p2.y = self.height elif self.p2.y > self.height: self.p2.y = 0 self.p1.update_collider() self.p2.update_collider() # Handle collisions between rockets and walls, and powerups and walls for wall in self.levels[self.current_level]: # Player 1 if wall.collider.colliderect(self.p1.wall_collider): self.p1.x = self.p1.old_x self.p1.y = self.p1.old_y self.p1.speed = 0 # Player 2 if wall.collider.colliderect(self.p2.wall_collider): self.p2.x = self.p2.old_x self.p2.y = self.p2.old_y self.p2.speed = 0 for powerup in self.powerups: if wall.collider.colliderect(powerup.wall_collider): x = randint(5, self.width - 5) y = randint(5, self.height - 5) powerup.x = x powerup.y = y # Handle collisions between bullets and walls for wall in self.levels[self.current_level]: # Player 1 for bullet in self.p1.bullets: if bullet.wall_collider.colliderect(wall.collider): if bullet.color == Missile(0, 0).color: self.p1.missile_exploded = True self.p1.missile_explosion_x = bullet.x self.p1.missile_explosion_y = bullet.y if self.dist( bullet.x, bullet.y, self.p1.x, self.p1.y ) <= self.p1.collider_size + self.p1.missile_explosion_radius: print("BLUE WINS") self.game_over = True if self.dist( bullet.x, bullet.y, self.p2.x, self.p2.y ) <= self.p2.collider_size + self.p2.missile_explosion_radius: print("RED WINS") self.game_over = True self.p1.bullets.remove(bullet) # Player 2 for bullet in self.p2.bullets: if bullet.wall_collider.colliderect(wall.collider): if bullet.color == Missile(0, 0).color: self.p2.missile_exploded = True self.p2.missile_explosion_x = bullet.x self.p2.missile_explosion_y = bullet.y if self.dist( bullet.x, bullet.y, self.p1.x, self.p1.y ) <= self.p1.collider_size + self.p1.missile_explosion_radius: print("BLUE WINS") self.game_over = True if self.dist( bullet.x, bullet.y, self.p2.x, self.p2.y ) <= self.p2.collider_size + self.p2.missile_explosion_radius: print("RED WINS") self.game_over = True self.p2.bullets.remove(bullet) # Handle collisions between rockets and powerups for powerup in self.powerups: # Player 1 if self.collision_circle(self.p1.x, self.p1.y, self.p1.collider_size, powerup.x, powerup.y, powerup.radius): self.p1.assign_powerup(powerup.id) self.powerups.remove(powerup) # Player 2 if self.collision_circle(self.p2.x, self.p2.y, self.p2.collider_size, powerup.x, powerup.y, powerup.radius): self.p2.assign_powerup(powerup.id) self.powerups.remove(powerup) self.p1.update_old_coords() self.p2.update_old_coords() # Missile Explosion Fade Player 1 if self.p1.missile_exploded: self.p1.missile_timer += 1 if self.p1.missile_timer > missile_fade: self.p1.missile_exploded = False if self.game_over: self.running = False # Missile Explosion Fade Player 2 if self.p2.missile_exploded: self.p2.missile_timer += 1 if self.p2.missile_timer > missile_fade: self.p2.missile_exploded = False if self.game_over: self.running = False self.powerup_spawn_timer += 1 def render(self): self.win.fill(self.background) self.p1.render(self.win) self.p2.render(self.win) for bullet in self.p1.bullets: bullet.render(self.win) for bullet in self.p2.bullets: bullet.render(self.win) for wall in self.levels[self.current_level]: wall.render(self.win) for powerup in self.powerups: powerup.render(self.win) if self.p1.missile_exploded: pygame.draw.ellipse(self.win, (255, 255, 255), (self.p1.missile_explosion_x - self.p1.missile_explosion_radius, self.p1.missile_explosion_y - self.p1.missile_explosion_radius, self.p1.missile_explosion_radius * 2, self.p1.missile_explosion_radius * 2)) if self.p2.missile_exploded: pygame.draw.ellipse(self.win, (255, 255, 255), (self.p2.missile_explosion_x - self.p2.missile_explosion_radius, self.p2.missile_explosion_y - self.p2.missile_explosion_radius, self.p2.missile_explosion_radius * 2, self.p2.missile_explosion_radius * 2)) pygame.display.update() # Gameplay functions # def get_spawn_location(self): # """Finds a suitable random spawn location for a powerup, staying within the # boundaries and avoiding all walls. # Returns: # tuple -- Contains the x and y coordinates for the suitable location # """ # x = randint(5, self.width - 5) # y = randint(5, self.height - 5) # size = ScatterShot(0, 0).radius # rect = pygame.Rect(x - size, y - size, size * 2, size * 2) # for wall in self.levels[self.current_level]: # if wall.collider.colliderect(rect): # self.get_spawn_location() # return (x, y) def dist(self, x1, y1, x2, y2): """Finds the distance between 2 points on a 2D plane using the Pythagorean Theorem. a^2 + b^2 = c^2 Arguments: x1 {int} y1 {int} x2 {int} y2 {int} Returns: int -- distance between the two points """ a = x1 - x2 b = y1 - y2 c = sqrt((a**2) + (b**2)) return c def collision_circle(self, x1, y1, r1, x2, y2, r2): """Finds out whether two circlea are overlapping using dist() function Arguments: x1 {int} -- x position of first circle y1 {int} -- y position of first circle r1 {int} -- radius of first circle x2 {int} -- x position of second circle y2 {int} -- y position of second circle r2 {int} -- radius of second circle Returns: bool -- Are the 2 circle overlapping """ d = self.dist(x1, y1, x2, y2) if d <= r1 + r2: return True