def get_near_point_to_point(self, point): x_s, y_s = self.base_size # x sie and y size points = [near_point_on_vector(point, Vector(self.x, self.y, self.x + x_s, self.y)), near_point_on_vector(point, Vector(self.x + x_s, self.y, self.x + x_s, self.y + y_s)), near_point_on_vector(point, Vector(self.x + x_s, self.y + y_s, self.x, self.y + y_s)), near_point_on_vector(point, Vector(self.x, self.y + y_s, self.x, self.y))] min_dist = min(distance(point, i_point) for i_point in points) return {distance(point, i_point): i_point for i_point in points}[min_dist]
def detected_enemy(self): busy = list() for enemy_id, enemy in self.all_enemies_on_map.items(): for turret_id, turret in self.all_turrets.items(): if distance(turret.pos(), enemy.pos()) < turret.range( ) and turret_id not in busy: turret.set_target(enemy_id) busy.append(turret_id)
def move(self) -> None: from math import atan, degrees if self.freeze_flag: speed = self.speed / 2 if time() - self.time_last_freeze >= self.freeze_time: self.freeze_flag = False else: speed = self.speed if distance( (self.x, self.y), self.game_map[self.i].end()) <= speed * 2: if self.i + 1 == len(self.game_map): self.current_status = 'ENEMY_STATUS_TO_GET_TO_BASE' else: if distance( (self.x, self.y), self.game_map[self.i].end()) > speed: self.x += speed * (self.game_map[self.i].len_x / self.game_map[self.i].len()) self.y += speed * (self.game_map[self.i].len_y / self.game_map[self.i].len()) self.i += 1 self.x += speed * (self.game_map[self.i].len_x / self.game_map[self.i].len()) self.y += speed * (self.game_map[self.i].len_y / self.game_map[self.i].len()) try: k = 0 if self.game_map[self.i].begin()[0] - self.game_map[self.i].end()[0] == 0 and \ self.game_map[self.i].begin()[1] - self.game_map[self.i].end()[1] < 0: self.angle = (180 + randint(-2, 2)) % 360 else: tan = (self.game_map[self.i].begin()[1] - self.game_map[self.i].end()[1]) / \ (self.game_map[self.i].begin()[0] - self.game_map[self.i].end()[0]) if ((self.game_map[self.i].begin()[1] - self.game_map[self.i].end()[1]) > 0 and (self.game_map[self.i].begin()[0] - self.game_map[self.i].end()[0]) > 0) or \ ((self.game_map[self.i].begin()[1] - self.game_map[self.i].end()[1]) <= 0 < ( self.game_map[self.i].begin()[0] - self.game_map[self.i].end()[0])): k = -180 self.angle = (90 + int(degrees(atan(tan))) + randint(-2, 2) + k) % 360 except ZeroDivisionError: self.angle = randint(-2, 2) % 360
def shoot(self, enemies): if self.target_id == -1 or self.target_id not in enemies: return if distance(enemies[self.target_id].pos(), self.pos()) >= self.range_of_attack: self.target_id = -1 return if time() - self.last_shoot_time >= 10 / self.rate: self.last_shoot_time = time() self.shoot_flag = True enemies[self.target_id].get_damage(self.damage) enemies[self.target_id].freeze(self.freezing_time / 10)
def shoot(self, enemies): if self.target_id == -1 or self.target_id not in enemies: return if distance(enemies[self.target_id].pos(), self.pos()) >= self.range_of_attack: enemies[self.target_id].burn(self.burning_time / 10, self.damage / 60) self.target_id = -1 return # enemies[self.target_id].get_damage(self.damage // 60) enemies[self.target_id].burn_flag = True enemies[self.target_id].get_damage(self.damage / 60)
def collision(self, pos, r, tower_type, screen) -> bool: screen_width = screen.get_width() screen_height = screen.get_height() if self.money < COSTS[tower_type] or self.menu.rect is None: return True test = [] for vec in self.game_map.get_map(): test.append(distance_to_vector(pos, vec)) if distance_to_vector(pos, vec) - self.game_map.line_width <= r: return True x, y = pos if x + r in range(self.menu.rect[0], self.menu.rect[2] + self.menu.rect[0] + 1) and \ y + r in range(self.menu.rect[1], self.menu.rect[3] + self.menu.rect[1] + 1): return True if x not in range(r, screen_width - r + 1) or y not in range( r, screen_height - r + 1): return True if x + r in range(self.game_map.base.x, self.game_map.base.x + 150) and \ y + r in range(self.game_map.base.y, self.game_map.base.y + 100): return True for _, turret in self.all_turrets.items(): if distance(pos, (turret.x, turret.y)) <= r * 2: return True return False
def collision_with_cursor(self, cur_pos): return distance(self.pos(), cur_pos) <= self.radius
def start(self, screen) -> (int, pygame.Surface): pygame.mixer.music.load( os.path.join(os.path.abspath(os.curdir), 'sounds', 'game.wav')) pygame.mixer.music.set_volume(0.1) pygame.mixer.music.play(100000) second = pygame.USEREVENT base_explosion = None clock = pygame.time.Clock() pygame.time.set_timer(second, 1000) self.menu = GameMenu() want_to_build_type = None want_to_build_flag = False while True: # main game-loop screen.fill(pygame.Color(255, 0, 0)) state = None for event in pygame.event.get(): # event handler cycle begin state = self.menu.event_handler(event) if event.type == QUIT: return 8, screen if base_explosion is None: if event.type == second: # next wave event pygame.time.set_timer(second, 1000) self.time -= 1 if self.time == 0: self.next_wave_sender() self.time = 20 if event.type == KEYDOWN: # hot-keys if event.key == K_c: # cheat button (add money) self.money += 10000 if event.key == K_F4 and event.mod in (512, 256): return 8, screen if event.key == K_ESCAPE: return 0, screen if base_explosion is None: if event.key == K_SPACE: self.next_wave_sender() self.time = 20 pygame.time.set_timer(second, 1000) if event.key == K_s and self.focus_on is not None: self.money += self.all_turrets[ self.focus_on].sell() del self.all_turrets[self.focus_on] self.focus_on = None if event.type == MOUSEMOTION: self.current_pos = event.pos if event.type == MOUSEBUTTONDOWN: self.mouse_button_pressed = True if self.focus_on is not None: self.all_turrets[self.focus_on].disable_trigger() flag = True for turret_id, turret in self.all_turrets.items(): if distance( event.pos, (turret.x, turret.y)) <= turret.radius_size: self.focus_on = turret_id flag = False break if flag: print(*self.menu.rect) collision_x = (self.menu.rect[0] <= event.pos[0] <= self.menu.rect[2] + self.menu.rect[0]) collision_y = (self.menu.rect[1] <= event.pos[1] <= self.menu.rect[3] + self.menu.rect[1]) if not (collision_x and collision_y): self.focus_on = None if self.focus_on is not None: self.all_turrets[self.focus_on].enable_trigger() if event.type == MOUSEBUTTONUP and self.mouse_button_pressed: self.mouse_button_pressed = False if want_to_build_flag: if not self.collision(event.pos, 20, want_to_build_type, screen): self.build_tower(want_to_build_type, event.pos) want_to_build_flag = False want_to_build_type = None # event handler cycle end if base_explosion is None: wave_timers = tuple(self.wave_queue.items()) for key, val in wave_timers: if global_time() - val[0] >= 1: self.enemies_sender(key) self.detected_enemy() self.move_enemies() # handling state that returns a menu if state == 1: pygame.time.set_timer(second, 1000) self.time = 20 self.next_wave_sender() if state == 2: want_to_build_flag = True want_to_build_type = ALL_TOWERS[0] if state == 3: want_to_build_flag = True want_to_build_type = ALL_TOWERS[1] if state in (5, 6, 7, 8, 9): # reserved for upgrades self.turret_upgrade(state - 5) self.game_map.update(screen, self.base_hp) self.update_enemies(screen) self.update_turrets(screen) self.update_animation(screen) self.menu.update(screen, self.time, self.money, self.focus_on, self.all_turrets, self.kills, self.current_wave) if want_to_build_flag: prototype( screen, self.current_pos, TOWERS[want_to_build_type].radius_size, TOWERS[want_to_build_type].range_of_attack, self.collision(self.current_pos, TOWERS[want_to_build_type].radius_size, want_to_build_type, screen)) if self.base_hp <= 0 and base_explosion is None: base_explosion = BaseExplosion(boom_map2, 9, 9, self.game_map.base.x, self.game_map.base.y) for tower_id in [__ for __, _ in self.all_turrets.items()]: self.add_explosion(self.all_turrets[tower_id].pos()) del self.all_turrets[tower_id] self.focus_on = None for enemy_id in [ __ for __, _ in self.all_enemies_on_map.items() ]: self.add_explosion(self.all_enemies_on_map[enemy_id].pos()) del self.all_enemies_on_map[enemy_id] if base_explosion is not None: if base_explosion.update(screen): return 9, screen # fps wait and flip the display clock.tick(self.fps) pygame.display.flip()