class Game: def __init__(self, win): self.width = 1350 self.height = 700 self.win = win self.enemys = [] self.attack_towers = [] self.support_towers = [] self.lives = 10 self.money = 2000 self.bg = pygame.image.load(os.path.join("game_assets", "bg.png")) self.bg = pygame.transform.scale(self.bg, (self.width, self.height)) self.timer = time.time() self.life_font = pygame.font.SysFont("comicsans", 65) self.selected_tower = None self.menu = VerticalMenu(self.width - side_img.get_width() + 70, 250, side_img) self.menu.add_btn(buy_archer, "buy_archer", 500) self.menu.add_btn(buy_archer_2, "buy_archer_2", 750) self.menu.add_btn(buy_damage, "buy_damage", 1000) self.menu.add_btn(buy_range, "buy_range", 1000) self.moving_object = None self.wave = 0 self.current_wave = waves[self.wave][:] self.pause = True self.music_on = True self.playPauseButton = PlayPauseButton(play_btn, pause_btn, 10, self.height - 85) self.soundButton = PlayPauseButton(sound_btn, sound_btn_off, 90, self.height - 85) def gen_enemies(self): """ generate the next enemy or enemies to show :return: enemy """ if sum(self.current_wave) == 0: if len(self.enemys) == 0: self.wave += 1 self.current_wave = waves[self.wave] self.pause = True self.playPauseButton.paused = self.pause else: wave_enemies = [Scorpion(), Wizard(), Club(), Sword()] for x in range(len(self.current_wave)): if self.current_wave[x] != 0: self.enemys.append(wave_enemies[x]) self.current_wave[x] = self.current_wave[x] - 1 break def run(self): pygame.mixer.music.play(loops=-1) run = True clock = pygame.time.Clock() while run: clock.tick(500) if self.pause == False: # gen monsters if time.time() - self.timer >= random.randrange(1,6)/3: self.timer = time.time() self.gen_enemies() pos = pygame.mouse.get_pos() # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) tower_list = self.attack_towers[:] + self.support_towers[:] collide = False for tower in tower_list: if tower.collide(self.moving_object): collide = True tower.place_color = (255, 0, 0, 100) self.moving_object.place_color = (255, 0, 0, 100) else: tower.place_color = (0, 0, 255, 100) if not collide: self.moving_object.place_color = (0, 0, 255, 100) # main event loop for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.MOUSEBUTTONUP: # if you're moving an object and click if self.moving_object: not_allowed = False tower_list = self.attack_towers[:] + self.support_towers[:] for tower in tower_list: if tower.collide(self.moving_object): not_allowed = True if not not_allowed and self.point_to_line(self.moving_object): if self.moving_object.name in attack_tower_names: self.attack_towers.append(self.moving_object) elif self.moving_object.name in support_tower_names: self.support_towers.append(self.moving_object) self.moving_object.moving = False self.moving_object = None else: # check for play or pause if self.playPauseButton.click(pos[0], pos[1]): self.pause = not(self.pause) self.playPauseButton.paused = self.pause if self.soundButton.click(pos[0], pos[1]): self.music_on = not(self.music_on) self.soundButton.paused = self.music_on if self.music_on: pygame.mixer.music.unpause() else: pygame.mixer.music.pause() # look if you click on side menu side_menu_button = self.menu.get_clicked(pos[0], pos[1]) if side_menu_button: cost = self.menu.get_item_cost(side_menu_button) if self.money >= cost: self.money -= cost self.add_tower(side_menu_button) # look if you clicked on attack tower or support tower btn_clicked = None if self.selected_tower: btn_clicked = self.selected_tower.menu.get_clicked(pos[0], pos[1]) if btn_clicked: if btn_clicked == "Upgrade": cost = self.selected_tower.get_upgrade_cost() if self.money >= cost: self.money -= cost self.selected_tower.upgrade() if not(btn_clicked): for tw in self.attack_towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False # look if you clicked on support tower for tw in self.support_towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False # loop through enemies if not self.pause: to_del = [] for en in self.enemys: en.move() if en.x < -15: to_del.append(en) # delete all enemies off the screen for d in to_del: self.lives -= 1 self.enemys.remove(d) # loop through attack towers for tw in self.attack_towers: self.money += tw.attack(self.enemys) # loop through attack towers for tw in self.support_towers: tw.support(self.attack_towers) # if you lose if self.lives <= 0: print("You Lose") run = False self.draw() def point_to_line(self, tower): """ returns if you can place tower based on distance from path :param tower: Tower :return: Bool """ # find two closest points return True def draw(self): self.win.blit(self.bg, (0,0)) # draw placement rings if self.moving_object: for tower in self.attack_towers: tower.draw_placement(self.win) for tower in self.support_towers: tower.draw_placement(self.win) self.moving_object.draw_placement(self.win) # draw attack towers for tw in self.attack_towers: tw.draw(self.win) # draw support towers for tw in self.support_towers: tw.draw(self.win) # draw enemies for en in self.enemys: en.draw(self.win) # redraw selected tower if self.selected_tower: self.selected_tower.draw(self.win) # draw moving object if self.moving_object: self.moving_object.draw(self.win) # draw menu self.menu.draw(self.win) # draw play pause button self.playPauseButton.draw(self.win) # draw music toggle button self.soundButton.draw(self.win) # draw lives text = self.life_font.render(str(self.lives), 1, (255,255,255)) life = pygame.transform.scale(lives_img,(50,50)) start_x = self.width - life.get_width() - 10 self.win.blit(text, (start_x - text.get_width() - 10, 13)) self.win.blit(life, (start_x, 10)) # draw money text = self.life_font.render(str(self.money), 1, (255, 255, 255)) money = pygame.transform.scale(star_img, (50, 50)) start_x = self.width - life.get_width() - 10 self.win.blit(text, (start_x - text.get_width() - 10, 75)) self.win.blit(money, (start_x, 65)) # draw wave self.win.blit(wave_bg, (10,10)) text = self.life_font.render("Wave #" + str(self.wave), 1, (255,255,255)) self.win.blit(text, (10 + wave_bg.get_width()/2 - text.get_width()/2, 25)) pygame.display.update() def add_tower(self, name): x, y = pygame.mouse.get_pos() name_list = ["buy_archer", "buy_archer_2", "buy_damage", "buy_range"] object_list = [ArcherTowerLong(x,y), ArcherTowerShort(x,y), DamageTower(x,y), RangeTower(x,y)] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + "NOT VALID NAME")
class Game: path = [] def __init__(self, win, username): self.__width = 1250 self.__height = 700 self.win = win self.enemies = [] self.attack_towers = [] self.support_towers = [] self.traps = [] self.__lives = 10 self.__money = 200000 self.__enemy_kill = 0 self.bg = pygame.image.load( os.path.join("../game_assets/background_3.png")).convert_alpha() self.bg = pygame.transform.scale(self.bg, (self.__width, self.__height)) self.game_map = None self.__timer = time.time() self.life_font = pygame.font.SysFont("life count", 30) self.username_font = pygame.font.SysFont( pygame.font.get_default_font(), 40) self.selected_tower = None self.object_orientation = [] self.moving_object = None self.moving_effect = None self.wave = 15 self.__current_wave = waves[self.wave][:] self.pause = True self.music_on = True self.username = username self.play_pause_button = PlayPauseButton(play_btn.convert_alpha(), pause_btn.convert_alpha(), 10, self.__height - 85) self.sound_button = PlayPauseButton(sound_btn.convert_alpha(), sound_btn_off.convert_alpha(), 90, self.__height - 85) self.stop_trap_btn = PlayPauseButton(stop_trap_img.convert_alpha(), stop_trap_img.convert_alpha(), 1000, self.__height - 90) self.destroy_trap_btn = PlayPauseButton( destroying_trap_img.convert_alpha(), destroying_trap_img.convert_alpha(), 915, self.__height - 90) self.menu = VerticalMenu(self.__width - side_img.get_width() + 80, 190, side_img) self.menu.add_btn(tower_icon_img.images[3].convert_alpha(), "buy_archer_1", 500) self.menu.add_btn(tower_icon_img.images[0].convert_alpha(), "buy_archer_2", 750) self.menu.add_btn(tower_icon_img.images[2].convert_alpha(), "buy_damage", 1000) self.menu.add_btn(tower_icon_img.images[1].convert_alpha(), "buy_range", 1000) self.is_input_chit = False self.current_chit_code = "" def game_map(self): return self.game_map def set_game_map(self, value): self.game_map = value if self.game_map == Map.FIRST_MAP: self.bg = pygame.image.load( os.path.join( "../game_assets/background_1.png")).convert_alpha() self.bg = pygame.transform.scale(self.bg, (self.__width, self.__height)) elif self.game_map == Map.SECOND_MAP: self.bg = pygame.image.load( os.path.join( "../game_assets/background_3.png")).convert_alpha() self.bg = pygame.transform.scale(self.bg, (self.__width, self.__height)) elif self.game_map == Map.THIRD_MAP: self.bg = pygame.image.load( os.path.join( "../game_assets/background_2.png")).convert_alpha() self.bg = pygame.transform.scale(self.bg, (self.__width, self.__height)) elif self.game_map == Map.FOURTH_MAP: self.bg = pygame.image.load( os.path.join( "../game_assets/background_4.png")).convert_alpha() self.bg = pygame.transform.scale(self.bg, (self.__width, self.__height)) Game.path = Path.get_path(self.game_map) @property def enemy_kill(self): return self.__enemy_kill @enemy_kill.setter def enemy_kill(self, value): self.__enemy_kill = value @property def lives(self): return self.__lives @lives.setter def lives(self, value): self.__lives = value @property def money(self): return self.__money @money.setter def money(self, value): self.__money = value def generate_enemies(self): """ Generate the next enemy or enemies :return: enemy """ if sum(self.__current_wave) == 0: if len(self.enemies) == 0: if self.wave == 10 and self.__money > 2000 and self.__enemy_kill > 100: self.__current_wave = bonus_wave elif (self.wave + 1) % 5 == 0 and self.__lives == 10: self.__current_wave = challenge_waves[self.wave // 5] else: self.wave += 1 self.__current_wave = waves[self.wave] self.pause = True self.play_pause_button.pause = self.pause else: wave_enemies = [ Scorpion(Game.path, self.game_map), Wizard(Game.path, self.game_map), Club(Game.path, self.game_map), Troll(Game.path, self.game_map), Sword(Game.path, self.game_map), Goblin(Game.path, self.game_map) ] for x in range(len(self.__current_wave)): if self.__current_wave[x] != 0: self.enemies.append(wave_enemies[x]) self.__current_wave[x] = self.__current_wave[x] - 1 break def run(self): # load music if self.game_map == Map.FIRST_MAP: pygame.mixer.music.load( os.path.join("../game_assets", "bensound-funnysong.wav")) elif self.game_map == Map.SECOND_MAP: pygame.mixer.music.load( os.path.join("../game_assets", "Fender_Bender.mp3")) elif self.game_map == Map.THIRD_MAP: pygame.mixer.music.load( os.path.join("../game_assets", "Shibuya.mp3")) elif self.game_map == Map.FOURTH_MAP: pygame.mixer.music.load( os.path.join("../game_assets", "Snow_Princess.mp3")) pygame.mixer.music.play(loops=-1) run = True clock = pygame.time.Clock() while run: clock.tick(100) if not self.pause: # generate monsters if time.time() - self.__timer >= random.randrange( 1, 5) / 3: # change speed of spanning enemies self.__timer = time.time() try: self.generate_enemies() except IndexError: return True pos = pygame.mouse.get_pos() # check for moving effect if self.moving_effect: self.moving_effect.move(pos[0], pos[1]) if self.point_to_line(): self.moving_effect.place_color = (255, 0, 0, 100) else: self.moving_effect.place_color = (0, 255, 0, 100) # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) tower_list = self.attack_towers[:] + self.support_towers[:] collide = False if not self.point_to_line(): collide = True self.moving_object.place_color = (255, 0, 0, 100) else: if not collide: self.moving_object.place_color = (0, 255, 0, 100) for tower in tower_list: if tower.collide(self.moving_object): collide = True tower.place_color = (255, 0, 0, 100) self.moving_object.place_color = (255, 0, 0, 100) else: tower.place_color = (0, 255, 0, 100) if not collide: self.moving_object.place_color = (0, 255, 0, 100) # main events loop for event in pygame.event.get(): if event.type == pygame.QUIT: run = False # get pressed key if event.type == pygame.KEYDOWN: if event.key == 96: # ~ if self.is_input_chit: self.is_input_chit = False self.current_chit_code = "" else: self.is_input_chit = True if event.key == 13: # Enter self.is_input_chit = False if self.current_chit_code == "money": self.__money += 1000 elif self.current_chit_code == "lives": self.__lives += 5 elif self.current_chit_code == "killall": for enemy in self.enemies: enemy.to_dying() self.current_chit_code = "" if self.is_input_chit: pressed_keys = event.dict['unicode'] if event.key == pygame.K_BACKSPACE: self.current_chit_code = self.current_chit_code[: -1] if pressed_keys in string.ascii_letters or pressed_keys in string.digits: if len(self.current_chit_code) <= 17: self.current_chit_code += pressed_keys """if event.key == 96: # ~ self.key_phrase_input = True self.pause = True self.moving_effect = None if event.key == 13: if len(self.__key_phrase) == len(self.input_key_phrase) and self.__key_phrase == self.input_key_phrase: self.__money += 1000 self.key_phrase_input = False self.input_key_phrase.clear() if self.key_phrase_input and event.key != 96: self.input_key_phrase.append(event.key)""" if event.type == pygame.MOUSEBUTTONUP: # points.append(pos) # print(points) if self.moving_effect: if event.button == 3: self.moving_effect = None else: destroy = False if not self.point_to_line(): self.traps.append(self.moving_effect) self.__money -= self.moving_effect.cost destroy = True if destroy: self.moving_effect = None # if your moving an object and click if self.moving_object: not_allowed = False tower_list = self.attack_towers[:] + self.support_towers[:] for tower in tower_list: if tower.collide(self.moving_object): not_allowed = True # check if you try to place something on vertical menu surface is_behind_menu = all( [1110 < pos[0] < 1250, 120 < pos[1] < 670]) if is_behind_menu: not_allowed = True not_place_tower = False if not not_allowed and self.point_to_line(): if self.moving_object.name in attack_tower_names: self.attack_towers.append(self.moving_object) elif self.moving_object.name in support_tower_names: self.support_towers.append(self.moving_object) not_place_tower = True # delete moving object if you click right mouse button if event.button == 3: # right mouse click if self.attack_towers and self.attack_towers[ -1] is self.moving_object: self.__money += self.moving_object.price self.attack_towers = self.attack_towers[:-1] elif self.support_towers and self.support_towers[ -1] is self.moving_object: self.__money += self.moving_object.price self.support_towers = self.support_towers[:-1] if not_place_tower: self.moving_object.moving = False self.moving_object = None else: if self.stop_trap_btn.click(pos[0], pos[1]): if self.__money >= 150: self.add_trap("stop_trap") elif self.destroy_trap_btn.click(pos[0], pos[1]): if self.__money >= 200: self.add_trap("destroy_trap") # check for play or pause if self.play_pause_button.click(pos[0], pos[1]): self.pause = not self.pause ArcherTowerLong.is_game_pause = self.pause self.play_pause_button.pause = self.pause if self.sound_button.click(pos[0], pos[1]): self.music_on = not self.music_on self.sound_button.pause = self.music_on if self.music_on: pygame.mixer.music.unpause() else: pygame.mixer.music.pause() # look is you click on side menu side_menu_button = self.menu.get_clicked( pos[0], pos[1]) if side_menu_button: cost = self.menu.get_item_cost(side_menu_button) if self.__money >= cost: self.__money -= cost self.add_tower(side_menu_button) # look is you click on attack tower btn_clicked = None if self.selected_tower: btn_clicked = self.selected_tower.menu.get_clicked( pos[0], pos[1]) if btn_clicked: if btn_clicked == "Upgrade": cost = self.selected_tower.get_upgrade_cost( ) if isinstance( cost, int) and self.__money >= cost: self.__money -= cost self.selected_tower.upgrade() if not btn_clicked: for tw in self.attack_towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False # look is you click on support tower for tw in self.support_towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False if not self.pause: # loop through traps for trap in self.traps: trap.stop_enemy(self.enemies) for trap in self.traps: if trap.is_destroyed: trap.destroy(self.traps, self.enemies) # loop through enemies to_del = [] for en in self.enemies: if en.is_die: if en.animate_die(self.enemies): self.__enemy_kill += 1 elif en.is_stopped_by_trap: en.animate_attack() en.stop_by_trap.is_attacked = True else: en.move() if self.game_map == Map.SECOND_MAP or self.game_map == Map.THIRD_MAP: if en.y > 715: to_del.append(en) elif self.game_map == Map.FIRST_MAP: if en.x < -15: to_del.append(en) elif self.game_map == Map.FOURTH_MAP: if en.x > 1265: to_del.append(en) for enemy in self.enemies: enemy.attack(self.traps) # delete all enemies off the screen for d in to_del: self.__lives -= 1 self.enemies.remove(d) # if you lose if self.__lives <= 0: print("You lose") run = False # loop through attack towers for tw in self.attack_towers: self.__money += tw.attack(self.enemies) # loop through support towers for tw in self.support_towers: tw.support(self.attack_towers) self.draw() if self.__lives <= 0: return False pygame.quit() @staticmethod def point_to_line(): """ Returns if you can place tower based on distance from path :return: Bool """ # find two closest points tower_x, tower_y = pygame.mouse.get_pos() first_closest_point = Game.path[0] for position, point in enumerate(Game.path[1:]): dis = math.sqrt((point[0] - tower_x)**2 + (point[1] - tower_y)**2) if math.sqrt((first_closest_point[0] - tower_x)**2 + (first_closest_point[1] - tower_y)**2) > dis: first_closest_point = (point[0], point[1], position) if (first_closest_point[0], first_closest_point[1]) != Game.path[0]: prev_point, next_point = Game.path[ first_closest_point[2] - 1], Game.path[first_closest_point[2] + 1] first_distance = math.sqrt((prev_point[0] - tower_x)**2 + (prev_point[1] - tower_y)**2) second_distance = math.sqrt((next_point[0] - tower_x)**2 + (next_point[1] - tower_y)**2) if first_distance > second_distance: second_closest_point = prev_point else: second_closest_point = next_point else: second_closest_point = Game.path[1] # |ax + by + c|/(sqrt(a^2 + b^2)) a = second_closest_point[1] - first_closest_point[1] b = -(second_closest_point[0] - first_closest_point[0]) c = second_closest_point[0] * first_closest_point[ 1] - second_closest_point[1] * first_closest_point[0] denominator = math.sqrt(a**2 + b**2) distance = abs(a * tower_x + b * tower_y + c) / denominator if distance < 60: return False return True def draw(self): # draw background self.win.blit(self.bg, (0, 0)) # for point in points: # pygame.draw.circle(self.win, (255, 0, 0), point, 3) # draw placement rings if self.moving_object: for tower in self.attack_towers: tower.draw_placement(self.win) for tower in self.support_towers: tower.draw_placement(self.win) self.moving_object.draw_placement(self.win) # redraw selected tower if self.selected_tower: self.selected_tower.draw(self.win) # redraw moving trap if self.moving_effect: self.moving_effect.draw_placement(self.win) # sort such objects for y coordinate and draw them in such sequence object_list = self.attack_towers[:] + self.support_towers[:] + self.enemies[:] + self.traps[:] object_list.sort(key=lambda x: x.y, reverse=False) for element in object_list: element.draw(self.win) """# loop through traps and draw health bar for trap in self.traps: if trap.is_attacked: trap.draw_health_bar(self.win) # loop through enemies and draw health bar for enemy in self.enemies: enemy.draw_health_bar(self.win)""" """# draw attack towers for tw in self.attack_towers: tw.draw(self.win) # draw support towers for tw in self.support_towers: tw.draw(self.win) # draw enemies for en in self.enemies: en.draw(self.win)""" # draw vertical menu self.menu.draw(self.win) # draw moving object if self.moving_object: self.moving_object.draw_placement(self.win) self.moving_object.draw(self.win) # draw moving effect if self.moving_effect: self.moving_effect.draw_placement(self.win) self.moving_effect.draw(self.win) # draw play/pause button self.play_pause_button.draw(self.win) # draw traps buttons self.stop_trap_btn.draw(self.win) text = self.stop_trap_btn.font.render("150", 1, (255, 255, 255)) self.win.blit(text, (self.stop_trap_btn.x + 35, self.stop_trap_btn.y + self.stop_trap_btn.height // 2 + 25)) # self.kill_trap_btn.draw(self.win) self.destroy_trap_btn.draw(self.win) text = self.destroy_trap_btn.font.render("200", 1, (255, 255, 255)) self.win.blit(text, (self.destroy_trap_btn.x + 35, self.destroy_trap_btn.y + self.destroy_trap_btn.height // 2 + 25)) # draw music toggle button self.sound_button.draw(self.win) if self.game_map == Map.FOURTH_MAP: statistic_color = (0, 0, 0) else: statistic_color = (255, 255, 255) # draw lives text = self.life_font.render(str(self.__lives), 1, statistic_color) life = lives_img start_x = self.__width - life.get_width() - 10 self.win.blit(text, (start_x - text.get_width(), 20)) self.win.blit(life, (start_x, 8)) # draw username username = self.username_font.render(self.username, 1, (255, 255, 255)) username_bg_transformed = pygame.transform.scale( username_bg, (username.get_width() + 100, username.get_height() + 25)) start_x = self.__width - life.get_width() - text.get_width() - 30 self.win.blit(username_bg_transformed, (start_x - username_bg_transformed.get_width(), 5)) self.win.blit(username, (start_x - username_bg_transformed.get_width() + 55, 23)) # draw currency text = self.life_font.render(str(self.__money), 1, statistic_color) start_x = self.__width - life.get_width() - 10 self.win.blit(text, (start_x - text.get_width(), 55)) self.win.blit(star_img, (start_x, 40)) # draw kills number_of_kills = self.life_font.render(str(self.__enemy_kill), 1, statistic_color) start_x = self.__width - life.get_width() - 10 self.win.blit(number_of_kills, (start_x - number_of_kills.get_width(), 85)) self.win.blit(enemy_head, (start_x + 8, 80)) # draw wave self.win.blit(wave_bg, (10, 10)) text = self.life_font.render("Wave #" + str(self.wave), 1, (255, 255, 255)) self.win.blit( text, (10 + wave_bg.get_width() / 2 - text.get_width() / 2, 40)) # draw chit code input table if self.is_input_chit: self.win.blit(chit_code_table, (self.__width // 2 - 150, self.__height - 60)) if self.is_input_chit and self.current_chit_code: output_chit_string = self.life_font.render(self.current_chit_code, 1, (0, 0, 0)) self.win.blit(output_chit_string, (self.__width // 2 - 100, self.__height - 40)) pygame.display.update() def add_tower(self, name): x, y = pygame.mouse.get_pos() name_list = ["buy_archer_1", "buy_archer_2", "buy_damage", "buy_range"] object_list = [ ArcherTowerLong(x, y), ArcherTowerShort(x, y), DamageTower(x, y), RangeTower(x, y) ] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + "NOT VALID NAME") def add_trap(self, name): x, y = pygame.mouse.get_pos() name_list = ["stop_trap", "kill_trap", "destroy_trap"] object_list = [StopTrap(x, y), KillTrap(x, y), DestroyTrap(x, y)] try: obj = object_list[name_list.index(name)] self.moving_effect = obj except Exception as e: print(str(e) + "NOT VALID NAME") def get_score(self): return self.wave, self.enemy_kill def clear_settings(self): self.__money = 2000 self.__lives = 10 self.wave = 0 self.enemies.clear() self.attack_towers.clear() self.support_towers.clear() self.traps.clear() self.__enemy_kill = 0 self.__timer = time.time() self.selected_tower = None self.object_orientation.clear() self.moving_object = None self.moving_effect = None self.__current_wave = waves[0][:] self.pause = True self.music_on = True self.is_input_chit = False self.current_chit_code = "" self.play_pause_button.pause = True self.sound_button.pause = True
class Game: def __init__(self, win): self.width = 1366 self.height = 768 self.win = win self.enemies = [] self.attack_towers = [] self.support_towers = [] self.lives = 10 self.money = 2000 self.bg = pygame.image.load(os.path.join("game_assets", "bg.png")) # self.bg = pygame.transform.scale(self.bg, (self.width, self.height)) self.timer = time.time() self.life_font = pygame.font.SysFont("comicsans", 50) self.selected_tower = None self.paused = True self.music_off = True self.wave = 0 self.current_wave = waves[self.wave][:] self.moving_object = None self.menu = VerticalMenu(self.width - side_img.get_width() + 30, 140, side_img) self.menu.add_button(buy_archer, "buy_archer", 500) self.menu.add_button(buy_archer2, "buy_archer2", 700) self.menu.add_button(buy_damage, "buy_damage", 1000) self.menu.add_button(buy_range, "buy_range", 1000) self.playPauseButton = PlayPauseButton(play_button, pause_button, 10, self.height - 85) self.musicButton = PlayPauseButton(unmute_button, mute_button, 84, self.height - 85) def run(self): run = True clock = pygame.time.Clock() while run: clock.tick(30) if self.paused == False: # gen monsters if time.time() - self.timer >= random.randrange(2, 5) / 2: self.timer = time.time() self.gen_enemies() pos = pygame.mouse.get_pos() # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) collide = False tower_list = self.attack_towers[:] + self.support_towers[:] for tower in tower_list: if tower.collide(self.moving_object): collide = True tower.place_color = (255, 0, 0, 100) self.moving_object.place_color = (255, 0, 0, 100) else: tower.place_color = (0, 0, 255, 100) if not (collide): self.moving_object.place_color = (0, 0, 255, 100) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.MOUSEBUTTONDOWN: # print(pos[0], pos[1]) # if you are moving an object and click if self.moving_object: not_allowed = False tower_list = self.attack_towers[:] + self.support_towers[:] for tower in tower_list: if tower.collide(self.moving_object): not_allowed = True if not not_allowed and self.point_to_line( self.moving_object): if self.moving_object.name in attack_tower_names: self.attack_towers.append(self.moving_object) elif self.moving_object.name in support_tower_names: self.support_towers.append(self.moving_object) self.moving_object.moving = False self.moving_object = None # print([tower.name for tower in self.attack_towers[:]]) print("Done") else: print("Not allowed!") else: # check for play or pause if self.playPauseButton.click(pos[0], pos[1]): self.paused = not (self.paused) self.playPauseButton.paused = self.paused # check for mute or unmute if self.musicButton.click(pos[0], pos[1]): self.music_off = not (self.music_off) self.musicButton.paused = self.music_off if self.music_off: pygame.mixer.music.pause() else: pygame.mixer.music.unpause() # look if you click on side menu side_menu_button = self.menu.get_clicked( pos[0], pos[1]) if side_menu_button: cost = self.menu.get_item_cost(side_menu_button) if self.money >= cost: self.money -= cost self.add_tower(side_menu_button) # look if you clicked on a attack tower or support tower button_clicked = None if self.selected_tower: button_clicked = self.selected_tower.menu.get_clicked( pos[0], pos[1]) if button_clicked: if button_clicked == "Upgrade": cost = self.selected_tower.get_upgrade_cost( ) if self.money >= cost: self.money -= cost self.selected_tower.upgrade() if not button_clicked: for tw in self.attack_towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False # look if you clicked on a support tower for tw in self.support_towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False if not (self.paused): # loop through enemies to_del = [] for en in self.enemies: en.move() if en.x > 1340: to_del.append(en) # delete all enemies off the screen for d in to_del: self.lives -= 1 self.enemies.remove(d) # loop through attack towers for tw in self.attack_towers: self.money += tw.attack(self.enemies) # loop through support towers for tw in self.support_towers: tw.support( self.attack_towers ) # sending attack towers to see if they are in range of the support tower # if you lose if self.lives <= 0: print("You Lost") run = False self.draw() """ for point in PATH: pygame.draw.circle(self.win, (255,0,0), (point[0], point[1]), 5) pygame.display.update() """ def draw(self): self.win.blit(self.bg, (0, 0)) # draw placement rings if self.moving_object: for tower in self.attack_towers: tower.draw_placement(self.win) for tower in self.support_towers: tower.draw_placement(self.win) self.moving_object.draw_placement(self.win) # draw attack towers for tw in self.attack_towers: tw.draw(self.win) # draw support towers for tw in self.support_towers: tw.draw(self.win) # draw enemies for en in self.enemies: en.draw(self.win) # redraw selected tower if self.selected_tower: self.selected_tower.draw(self.win) # draw moving object if self.moving_object: self.moving_object.draw(self.win) # draw menu self.menu.draw(self.win) # draw play pause button self.playPauseButton.draw(self.win) # draw music toggle button self.musicButton.draw(self.win) # draw lives text = self.life_font.render(str(self.lives), 1, (255, 0, 0)) life = lives_img start_x = self.width - life.get_width() - 5 self.win.blit(text, (start_x - text.get_width() - 10, 15)) self.win.blit(life, (start_x, 10)) # draw money text = self.life_font.render(str(self.money), 1, (255, 255, 0)) money = pygame.transform.scale(coin_img, (35, 35)) start_x = self.width - life.get_width() - 5 self.win.blit(text, (start_x - text.get_width() - 10, 65)) self.win.blit(money, (start_x + 5, 60)) # draw wave self.win.blit(wave_bg, (10, 10)) text = self.life_font.render("Wave #" + str(self.wave), 1, (255, 255, 255)) self.win.blit( text, (10 + wave_bg.get_width() // 2 - text.get_width() // 2, 20)) pygame.display.update() def point_to_line(self, tower): """ returns if you can place tower based on distance from path :param tower: Tower :return: Bool """ # find two closest points closest = [] for point in PATH: dis = math.sqrt((tower.x - point[0])**2 + (tower.y - point[1])**2) closest.append([dis, point]) closest.sort(key=lambda x: x[0]) closest1 = closest[0][1] # (x1, y1) closest2 = closest[1][1] # (x2, y2) i = 2 while True: closest2 = closest[i][1] if abs(PATH.index(closest1) - PATH.index(closest2)) != 1: i += 1 else: break try: slope = (closest2[1] - closest1[1]) / (closest2[0] - closest1[0] ) # (y2-y1) / (x2-x1) A = slope B = -1 C = closest1[1] - slope * closest1[0] except ZeroDivisionError: slope = 0 A = -1 B = slope C = closest1[0] - slope * closest1[1] dis = abs(A * tower.x + B * tower.y + C) / math.sqrt(A**2 + B**2) # print(dis, closest1, closest2, (tower.x, tower.y)) return True if dis >= tower.width // 2 + 10 else False def gen_enemies(self): """ generate the next enemy or enemies to show :return: enemy """ if sum(self.current_wave) == 0: if len(self.enemies) == 0: self.wave += 1 self.current_wave = waves[self.wave] self.paused = True self.playPauseButton.paused = self.paused else: wave_enemies = [Scorpion(), Wizard(), Club(), Boss()] for x in range(len(self.current_wave)): if self.current_wave[x] != 0: self.enemies.append(wave_enemies[x]) self.current_wave[x] = self.current_wave[x] - 1 break def add_tower(self, name): x, y = pygame.mouse.get_pos() name_list = ["buy_archer", "buy_archer2", "buy_damage", "buy_range"] object_list = [ ArcherTowerLong(x, y), ArcherTowerShort(x, y), DamageTower(x, y), RangeTower(x, y) ] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + "NOT VALID NAME!")
class Game(): def __init__(self, win): # Basics self.win = win self.width = 1200 self.height = 700 self.lives = 20 self.money = 35 self.bg = pygame.image.load( os.path.join("game_assets/background/", "kingdom.png")) self.bg = pygame.transform.scale(self.bg, (self.width, self.height)) self.clicks = [] # use to see clicks self.timer = time.time() self.go_lose = False self.go_win = False # Actors self.enemys = [] self.attack_towers = [] self.support_towers = [] self.fortress = [] self.fortress_sold = [] self.selected_tower = None self.moving_object = None self.draw_drop = False self.drop_x = 0 self.drop_y = 0 self.reward = 0 # Side Tower menu self.menu = VerticalMenu(self.width - 45, 46, side_img) self.menu.add_btn(buy_shin, "buy_shin", 40) self.menu.add_btn(buy_moubu, "buy_moubu", 120) self.menu.add_btn(buy_kanki, "buy_kanki", 80) self.menu.add_btn(buy_ouhon, "buy_ouhon", 150) self.menu.add_btn(buy_fortress, "buy_fortress", 200) self.menu.add_btn(buy_kyoukai, "buy_kyoukai", 100) self.menu.add_btn(buy_ten, "buy_ten", 100) self.menu.add_btn(buy_ryo, "buy_ryo", 100) # Buttons and options self.life_font = self.money_font = pygame.font.Font( "game_assets/fonts/SF Atarian System.ttf", 32) self.wave_font = pygame.font.Font( "game_assets/fonts/SF Atarian System.ttf", 18) self.wave_font2 = pygame.font.Font( "game_assets/fonts/SF Atarian System.ttf", 72) self.playPauseButton = PlayPauseButton(play_btn, pause_btn, self.width / 2 - 118, 0, False) self.soundButton = PlayPauseButton(sound_btn, sound_btn_off, self.width / 2 + 88, 0, True) self.sideButton = PlayPauseButton(side_btn, side_btn, self.width - 33, 272, False) self.speedButton = ReturnButton(speed1_btn, speed2_btn, speed3_btn, self.width / 2 - 170, 0) self.speed = 1 self.shake_money = False self.shake_life = False self.change_sound = False # Fortress self.fortress_sound = False self.to_resist = [] self.first_contact = True # Wave and Gen enemies self.wave = 0 self.current_wave = waves[self.wave][:] self.spawn_rate = spawn_rates[:] self.current_spawn_rate = 1.5 self.kingdom = [ Quin_base(), Zao_base(), Yan_base(), Qi_base(), Wei_base(), Han_base(), Chu_base(), Chu2_base(), Chu3_base() ] self.current_kingdom = self.kingdom[0] self.next_spawn = False # Game level self.level = "" self.lvl = {"Easy": 0, "Medium": 1, "Hard": 2} self.coef_rate = 1 # Graphs self.start_ticks = 0 # Plot-1 self.df = pd.DataFrame() self.data_dict = { 'seconds': [], 'waves': [], 'money': [], 'lives': [], 'money_earnt': [], 'money_spent': [], 'shin': [], 'moubu': [], 'kanki': [], 'ouhon': [], 'ten': [], 'kyoukai': [], 'ryo': [], 'fortress': [], 'towers': [] } self.counters = { 'shin': 0, 'moubu': 0, 'kanki': 0, 'ouhon': 0, 'ten': 0, 'kyoukai': 0, 'ryo': 0, 'fortress': 0 } self.money_earnt = 0 self.money_spent = 0 # Plot-2 self.df_enemies = pd.DataFrame( data={ 'waves': [], 'spawned': [], 'killed': [], "Zao Warrior": [], "Yan Warrior": [], "Qi Warrior": [], "Wei Catapult": [], "Wei Balista": [], "Han Warrior": [], "Chu Warrior": [], "Chu Elephant": [], "Chu Boat": [], "Yan Boat": [], "Qi Boat": [], "Zao Riboku": [] }) self.not_killed = { "zao_warrior": 0, "yan_warrior": 0, "qi_warrior": 0, "wei_catapult": 0, "wei_balista": 0, "han_warrior": 0, "chu_warrior": 0, "chu_elephant": 0, "chu_boat": 0, "yan_boat": 0, "qi_boat": 0, "zao_riboku": 0 } self.counter_gold = {"Gold Earnt": [], "Enemies (Type)": []} self.list_enemy_spawned = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] self.not_kill_count = 0 self.spawn_count = 0 def gen_enemies(self): """ generate the next enemy or enemies to show :return: enemy, kingdom """ wave_compo = [(Zao_warrior(), Zao_base()), (Yan_warrior(), Yan_base()), (Qi_warrior(), Qi_base()), (Wei_catapult(), Wei_base()), (Wei_balista(), Wei_base()), (Han_warrior(), Han_base()), (Chu_warrior(), Chu_base()), (Chu_elephant(), Chu2_base()), (Chu_boat(), Chu3_base()), (Yan_boat(), Yan_base()), (Qi_boat(), Qi_base()), (Zao_riboku(), Zao_base())] # Wave has finished if sum(self.current_wave) == 0: self.next_spawn = True # go to next wave if len(self.enemys) == 0: self.wave += 1 # Go to next wave if self.wave < len(waves): next_wave = waves[self.wave][:] # play sound, write wave number and shade if self.wave > 0: # change music (epic AOE) at wave 10 if not self.change_sound and self.wave >= break_round - 1: pygame.mixer.music.stop() self.change_sound = True play_next_song() if not self.change_sound: play_sound(0, "next_round.wav") next_intro = [ w_comp[0] for w_comp, w in zip(wave_compo, next_wave) if w > 0 ] self.fade( self.width, self.height, rgb(0, 0, 0), 0, 50, 60, next_intro ) # (width, height, color, start=0, end=300, delay=1) # reset self.fortress_sound = False self.playPauseButton.on = False self.current_wave = next_wave # update dict for enemies graphs spawned = self.spawn_count not_killed = self.not_kill_count killed = spawned - not_killed self.df_enemies = self.df_enemies.append( { 'waves': self.wave, 'spawned': spawned, 'killed': killed, "Zao Warrior": waves[self.wave - 1][0], "Yan Warrior": waves[self.wave - 1][1], "Qi Warrior": waves[self.wave - 1][2], "Wei Catapult": waves[self.wave - 1][3], "Wei Balista": waves[self.wave - 1][4], "Han Warrior": waves[self.wave - 1][5], "Chu Warrior": waves[self.wave - 1][6], "Chu Elephant": waves[self.wave - 1][7], "Chu Boat": waves[self.wave - 1][8], "Yan Boat": waves[self.wave - 1][9], "Qi Boat": waves[self.wave - 1][10], "Zao Riboku": waves[self.wave - 1][11] }, ignore_index=True) self.spawn_count = 0 self.not_kill_count = 0 # No wave left, go_win else: time.sleep(0.7) self.go_win = True pygame.mixer.music.stop() pygame.mixer.music.load( os.path.join("game_assets/sounds/", "ending.mp3")) pygame.mixer.music.play(loops=0) time.sleep(0.4) print("You Win") # Generates enemies of current wave, if wave is still going on else: # check if wave has just one type of enemy nb_0 = self.current_wave.count(0) if nb_0 == len(self.current_wave) - 1: one_type = True else: one_type = False # loop throw current wave to spawn enemies on by one for x in range(len(self.current_wave)): enemy_nb = self.current_wave[x] enemy_type = wave_compo[x][0] kingdom = wave_compo[x][1] # change to next enemy spawn if enemy_nb == 0: self.next_spawn = True self.current_spawn_rate = enemy_type.rate * self.coef_rate # spawn one enemy if enemy_nb != 0: enemy_type.scale_health(self.wave) enemy_type.shield = self.shield self.enemys.append(enemy_type) self.current_kingdom = kingdom self.current_wave[x] = self.current_wave[x] - 1 self.list_enemy_spawned[x] += 1 self.spawn_count += 1 self.next_spawn = False # if wave has just one type of enemy, break for better spawn rates if one_type: break def run(self): # start playing the background music pygame.mixer.music.load( os.path.join("game_assets/sounds/", "loop0.wav")) pygame.mixer.music.set_volume(0.4) pygame.mixer.music.play(loops=-1) # loop forever wave_compo = [(Zao_warrior(), Zao_base()), (Yan_warrior(), Yan_base()), (Qi_warrior(), Qi_base()), (Wei_catapult(), Wei_base()), (Wei_balista(), Wei_base()), (Han_warrior(), Han_base()), (Chu_warrior(), Chu_base()), (Chu_elephant(), Chu2_base()), (Chu_boat(), Chu3_base()), (Yan_boat(), Yan_base()), (Qi_boat(), Qi_base()), (Zao_riboku(), Zao_base())] first_intro = [ w_comp[0] for w_comp, w in zip(wave_compo, waves[0]) if w > 0 ] self.fade( self.width, self.height, rgb(0, 0, 0), 0, 255, 10, first_intro) # (width, height, color, start=0, end=300, delay=1) # Before game initialisation : if self.wave == 0: self.initialise() # main run run = True clock = pygame.time.Clock() self.start_ticks = pygame.time.get_ticks() #starter tick while run: self.update_stat() clock.tick(400) # generates enemies at given rate if not pause if not self.playPauseButton.on_pause: if time.time() - self.timer >= self.current_spawn_rate: self.timer = time.time() self.gen_enemies() pos = pygame.mouse.get_pos() # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) tower_list = self.attack_towers[:] + self.support_towers[:] + self.fortress[:] collide = False for tower in tower_list: if tower.collide(self.moving_object): collide = True # main event loop for event in pygame.event.get(): if event.type == pygame.QUIT: self.go_lose = True if event.type == SONG_END and self.change_sound and not self.go_win and self.wave != break_round - 1: play_next_song() if event.type == pygame.MOUSEBUTTONUP: # if you're moving an object and click it if self.moving_object: if self.moving_object.name in fortress_names: tower_list = self.fortress[:] else: tower_list = self.attack_towers[:] + self.support_towers[:] not_allowed = False # check if first tower of the game collides with forbidden tile if not tower_list: if self.moving_object.collide(self.moving_object): not_allowed = True play_sound(1, "buzz.wav", 600) # check if moving object collides with towers, fortress or forbidden tile for tower in tower_list: if tower.collide(self.moving_object): not_allowed = True play_sound(1, "buzz.wav", 600) # add moving object if no collision with towers, fortress or forbidden tile if not not_allowed: self.add_obj(self.moving_object) self.update_counter(self.moving_object, 1) self.moving_object.moving = False self.moving_object = None play_sound(1, "put_tower.wav", 600) # if you click another object (not moving obj) else: # toggle play/pause if self.playPauseButton.click(pos[0], pos[1]): play_sound(1, "beep_menu.wav", 300) self.playPauseButton.toggle(opposite=True) # toggle music if self.soundButton.click(pos[0], pos[1]): self.soundButton.toggle() if self.soundButton.on: pygame.mixer.music.unpause() else: pygame.mixer.music.pause() # toggle side menu if self.sideButton.click(pos[0], pos[1]): play_sound(1, "toggle.wav", 600) self.sideButton.toggle() self.sideButton.play = pygame.transform.flip( self.sideButton.play, True, False) # if you click on side menu and buttons if self.sideButton.on: side_menu_button = self.menu.get_clicked( pos[0], pos[1]) if side_menu_button: self.menu.blink = True cost = self.menu.get_item_cost( side_menu_button) if self.money >= cost: play_sound(1, "buy.wav", 600) self.spend(cost) self.add_tower(side_menu_button) else: self.shake_money = True play_sound(1, "buzz.wav", 600) # if you click on speed-up, speed-down if self.speedButton.click(pos[0], pos[1]): play_sound(1, "beep_menu.wav", 300) if self.speed < 3: self.speed += 1 else: self.speed = 1 self.speedButton.speed = self.speed btn_clicked = None # if you click on attack tower or support tower if self.selected_tower: btn_clicked = self.selected_tower.menu.get_clicked( pos[0], pos[1]) # if you click on Upgrade button or Sell button if btn_clicked: # if you click on Upgrade button if btn_clicked == "Upgrade": cost = self.selected_tower.get_upgrade_cost( ) if self.money >= cost: self.spend(cost) self.selected_tower.upgrade() play_sound(1, "buy.wav", 600) else: self.shake_money = True play_sound(1, "buzz.wav", 600) # if you click on Sell button if btn_clicked == "Sell": refund = self.selected_tower.sell() self.gain(refund) self.update_counter( self.selected_tower, -1) play_sound(1, "sell.wav", 200) try: self.del_obj(self.selected_tower) except Exception as e: print("Sell Exception: " + str(e)) if not btn_clicked: # check if you click on tower, fortress or kingdom, and select it obj_list = [ self.attack_towers, self.support_towers, self.fortress, self.kingdom ] for elem in obj_list: self.check_click(pos, elem) # if you click on reward if self.draw_drop: if self.click(gold_bag, self.drop_x, self.drop_y, pos[0], pos[1]): play_sound(0, "coin.wav", 200) self.gain(self.reward) self.draw_drop = False # self.clicks.append(pos) # print(self.clicks) # do atoher actions: enemies(move), fortress(resist/collapse), towers(effect), lose lives if not self.playPauseButton.on_pause: to_del = [] # loop through enemies for en in self.enemys: # move enemies along the path, displayed at chosen game speed en.speed = self.speed en.move() if en.x < 46: to_del.append(en) play_sound(1, "beep.wav", 600) # block enemies next to a fortress for ft in self.fortress: # fortress loses health if en.collide(ft): self.fortress_sound = True ft.collided.append(en) if self.first_contact: play_sound(1, "melee.wav", 1600) self.first_contact = False self.to_resist.append(en) ft.resist(en) # check if the fortress has collapsed if not ft.resist(en): play_sound(1, "collapse.wav", 1600) ft.collapse = True self.first_contact = True # delete all enemies off the screen for d in to_del: self.lose_life(d) # loop through attack towers for tw in self.attack_towers: # attack, at chosen game speed tw.speed = self.speed money_before = self.money self.money += tw.attack(self.enemys) value = self.money - money_before self.money_earnt += value en = tw.attacked_enemy if en is not None: expl = Explosion(en.x, en.y, 'sm') all_sprites.add(expl) self.update_counter_gold(en, value) # check if you got a random gold_drop if tw.gold_drop > 0: self.dropped(tw) # loop through support towers and do effect for tw in self.support_towers: tw.support(self.attack_towers) # loop through fortress, remove it if collapsed and move again enemies for ft in self.fortress: if ft.collapse: self.fortress_sound = False self.fortress.remove(ft) for en in self.to_resist: en.block = False for ft in self.fortress_sold: for en in self.to_resist: if en in ft.collided: en.block = False self.fortress_sold.remove(ft) # play fortress sound if fortress is still activated if self.fortress_sound: if random.randint(0, 60) == 10: play_sound(1, "melee.wav", 1600) # if you lose, go_lose if self.lives <= 0: self.game_over() # stop run if game is over (win or lose) if self.go_win or self.go_lose: # load Plot-1 and Plot-2 windows self.df = pd.DataFrame(data=self.data_dict) self.df_gold = pd.DataFrame(data=self.counter_gold) self.df_gold = self.df_gold.groupby( by=["Enemies (Type)"]).sum() self.df_gold['Enemies (Type)'] = self.df_gold.index self.fade( self.width, self.height, rgb(0, 0, 0), 0, 300, 4) # (width, height, color, start=0, end=300, delay=1) try: self.plot_towers(self.df) self.plot_enemies(self.df_enemies, self.list_enemy_spawned, self.not_killed, self.df_gold) plt.show() except Exception as e: print("Graph Exception: " + str(e)) # game has finished run = False # actualise pictures all_sprites.update() self.draw() # re init self.shake_money = False self.shake_life = False self.menu.blink = False def draw(self): self.win.blit(self.bg, (0, 0)) # for p in self.clicks: # pygame.draw.circle(self.win, rgb(255, 0, 0), (p[0], p[1]), 5, 0) # draw kingdom's base for kingdoms in self.kingdom: kingdoms.draw(self.win) # draw random gold_drop if self.draw_drop: self.win.blit(gold_bag, (self.drop_x, self.drop_y)) # draw towers and fortress, sorted by y position for no overlaying towers = self.attack_towers[:] + self.support_towers[:] + self.fortress[:] self.draw_towers(towers) # draw enemies for en in self.enemys: en.draw(self.win) # draw menu if self.sideButton.on: self.menu.draw(self.win) # draw side button if self.sideButton.on: self.sideButton.x = self.width - 116 self.sideButton.y = 272 else: self.sideButton.x = self.width - 33 self.sideButton.y = 272 self.sideButton.draw(self.win) # draw speed-up, speed-down button self.speedButton.draw(self.win) # draw play pause button self.playPauseButton.draw(self.win) # draw music toggle button self.soundButton.draw(self.win) # draw wave self.win.blit(wave_bg, (self.width - 90, self.height - 48)) text = self.wave_font.render("Wave " + str(self.wave + 1), 2, rgb(255, 255, 255)) self.win.blit(text, (self.width - 90 + wave_bg.get_width() / 2 - text.get_width() / 2, self.height - 47)) # draw alert self.draw_alert(self.current_kingdom) # draw lives start_x = 10 start_y = 0 text = self.life_font.render(str(self.lives), 2, rgb(255, 255, 255)) add_shake = 0 if self.shake_life: add_shake = 18 add_x = text.get_width() + 10 add_y = 3 self.win.blit(text, (start_x + add_shake, start_y)) self.win.blit(lives_img, (start_x + add_x + add_shake, start_y + add_y)) # draw money text = self.money_font.render(str(self.money), 2, rgb(255, 255, 255)) add_shake = 0 if self.shake_money: add_shake = 18 start_x = self.width - money_img.get_width() - text.get_width() - 15 start_y = 0 add_x = 0 + add_shake self.win.blit(text, (start_x + add_x, start_y)) add_x = text.get_width() + 10 + add_shake self.win.blit(money_img, (start_x + add_x, start_y)) # draw moving object if self.moving_object: self.moving_object.draw(self.win) all_sprites.draw(self.win) pygame.display.update() def draw_alert(self, kingdom): """ display blinking alert next to the kingdom when enemies spawn :param kingdom: Kingdom :return: None """ x = kingdom.x - 72 y = kingdom.y - 28 timer = time.time() - self.timer rate = self.current_spawn_rate if not self.next_spawn: # randomly flashing if timer >= random.randrange(0, 1 + math.ceil(rate)) / rate: self.win.blit(alert_red, (x, y)) else: self.win.blit(alert_white, (x, y)) def draw_towers(self, tower_list): """ display towers and fortress, without overlaying :param tower_list: [attack_towers, support_towers, fortress] list of list of towers :return: None """ tower_list.sort(key=lambda tw: tw.y) for tw in tower_list: tw.draw(self.win) def click(self, img, x, y, X, Y): """ returns if img has been clicked on :param x, y, X, Y : int :return: bool """ if X <= x + img.get_width() and X >= x: if Y <= y + img.get_height() and Y >= y: return True return False def add_tower(self, name): """ add tower if clicked on its button """ x, y = pygame.mouse.get_pos() name_list = [ "buy_shin", "buy_moubu", "buy_kanki", "buy_ouhon", "buy_fortress", "buy_kyoukai", "buy_ten", "buy_ryo" ] object_list = [ ShinTower(x, y), MoubuTower(x, y), KankiTower(x, y), OuhonTower(x, y), Fortress(x, y), KyoukaiTower(x, y), TenTower(x, y), RyoTower(x, y) ] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + "NOT VALID NAME") def add_obj(self, obj): """ add tower or fortress to its corresponding list """ if obj.name in attack_tower_names: self.attack_towers.append(obj) elif obj.name in support_tower_names: self.support_towers.append(obj) elif obj.name in fortress_names: self.fortress.append(obj) self.first_contact = True exp = Explosion(obj.x, obj.y, "tower") all_sprites.add(exp) def del_obj(self, obj): """ removes tower or fortress """ if obj.name in attack_tower_names: self.attack_towers.remove(obj) elif obj.name in support_tower_names: self.support_towers.remove(obj) elif obj.name in fortress_names: self.fortress_sound = False self.fortress_sold.append(obj) self.fortress.remove(obj) def check_click(self, pos, elem): """ select obj if clicked """ for obj in elem: if obj.click(pos[0], pos[1]): obj.selected = True if elem != self.kingdom: self.selected_tower = obj else: obj.selected = False def update_counter(self, obj, sign): """ update dict for graphs """ self.counters[obj.name] = self.counters[obj.name] + sign def update_counter_gold(self, obj, value): """ update dict for enemy graphs """ self.counter_gold["Gold Earnt"].append(value) self.counter_gold["Enemies (Type)"].append(obj.nickname) def spend(self, cost): """ update money """ self.money -= cost self.money_spent += cost def gain(self, cost): """ update money """ self.money += cost self.money_earnt += cost def lose_life(self, enemy): """ update enemy counters, lose 1 live, do animation """ self.not_killed[enemy.name] += 1 self.not_kill_count += 1 self.lives -= 1 self.shake_life = True expl = Explosion(enemy.x, enemy.y, 'lg') all_sprites.add(expl) self.enemys.remove(enemy) def dropped(self, tower): """ gives reward and drop coordinates """ self.reward = tower.gold_drop self.drop_x = tower.coord[0] - gold_bag.get_width() / 2 self.drop_y = tower.coord[1] - gold_bag.get_height() / 2 - 35 self.draw_drop = True def getUniqueEnemies(self, l): """ create a list of unique enemies based on their type """ result = [] temp = [] for item in l: if item.type not in temp: result.append(item) temp.append(item.type) return result def flipDict(self, d): """ flip keys and values """ result = {} for key, value in d.items(): if value not in result: result[value] = [key] else: result[value].append(key) return result def game_over(self): """ transition to end game """ play_sound(1, "beep.wav", 600) self.shake_life = False self.draw() time.sleep(0.7) pygame.mixer.music.pause() play_sound(0, "game_over.wav") time.sleep(2.4) print("You Lose") self.go_lose = True pygame.mixer.music.load( os.path.join("game_assets/sounds/", "melody.wav")) pygame.mixer.music.play(loops=-1) def fade(self, width, height, color, start=0, end=300, delay=1, en_intro=[]): """ transition to next scene """ fade = pygame.Surface((width, height)) fade.fill(color) if self.wave == break_round - 1: delay = round(delay * 1.5) for alpha in range(start, end): fade.set_alpha(alpha) # draw wave number wave_text = self.drawWaveNumber(fade, self.wave_font2) # draw enemies intro images and texts under the wave text: self.drawEnemiesIntro(wave_text, en_intro) pygame.display.update() pygame.time.delay(delay) # longer transition for the upcoming special wave if self.wave == break_round - 1: pygame.time.delay(5000) def drawWaveNumber(self, srfc, font): """ draw wave texts based on game status (run, go_win, go_lose) and return the text """ self.win.blit(srfc, (0, 0)) if self.go_win: text = font.render("Win", 2, rgb(255, 255, 255)) elif self.go_lose: text = font.render("Game Over", 2, rgb(255, 255, 255)) else: text = font.render("Wave " + str(self.wave + 1), 2, rgb(255, 255, 255)) self.win.blit(text, (self.width / 2 - text.get_width() / 2, self.height / 2 - text.get_height() / 2)) return text def drawEnemiesIntro(self, text, l): """ draw images next to each others, and texts under the images """ # create flipped dict with enemies type as keys, enemies nickname as values, and list key = [en.nickname for en in l] value = [en.type for en in l] ini_dict = dict(zip(key, value)) flipped = self.flipDict(ini_dict) en_txt = [[key, value] for key, value in flipped.items()] # create a list of unique enemy types en_obj = self.getUniqueEnemies(l) # draw loop : draw images next to each others, and texts under images type_nb = len(en_obj) img_width = 120 # en.intro.get_width() img_height = 120 pad = 10 x = self.width / 2 - ((type_nb / 2) * img_width + (type_nb - 1) * pad) y = self.height / 2 + text.get_height() / 2 for en, txt in zip(en_obj, en_txt): # draw images self.win.blit(en.intro, (x, y)) # draw texts for i, t in enumerate(txt[1]): text_en = self.wave_font.render(t, 2, rgb(255, 255, 255)) self.win.blit(text_en, (x + img_width / 2 - text_en.get_width() / 2, y + img_height + pad + i * text_en.get_height())) x += img_width + 2 * pad def initialise(self): """ Initialise based on diffculty """ # add additional money based on game level (+10, +20, +30) coef = 3 - self.lvl[self.level] self.money = self.money + self.money * coef # reduce spaw rates based on game level (-0%, -20%, -40%) TO DO coef = 1 - 0.2 * self.lvl[self.level] self.coef_rate = coef # balance enemies strengh based on game level coef = self.lvl[self.level] / 5 self.shield = 2 + coef def update_stat(self): """ update dict every 2 seconds for end game statistics """ seconds = (pygame.time.get_ticks() - self.start_ticks) / 1000 # seconds ticking towers_nb = sum( self.counters.values()) # calculate total towers number # store data every 2 seconds (+- 0.01) list_keys = list(self.data_dict.keys()) list_items = [ round(seconds), self.wave + 1, self.money, self.lives, self.money_earnt, self.money_spent, self.counters['shin'], self.counters['moubu'], self.counters['kanki'], self.counters['ouhon'], self.counters['ten'], self.counters['kyoukai'], self.counters['ryo'], self.counters['fortress'], towers_nb ] rest = math.fmod(seconds, 2) if rest <= 0.01: for key, item in zip(list_keys, list_items): self.data_dict[key].append(item) def plot_towers(self, df): """ plot end game statistics : 4 graphs (money, attack towers, lives, support towers) """ # Plot-1 configuration fig, axes = plt.subplots(2, 2, figsize=(14, 14)) sns.set(style="whitegrid") # axe (0,0) : Seaborn lineplot data_preproc = pd.DataFrame({ 'Waves (Nb)': df['waves'].values, 'Money Spent': df['money_spent'].values, 'Money Earnt': df['money_earnt'].values, 'Money': df['money'].values }) data = pd.melt(data_preproc, ['Waves (Nb)']) data = data.rename(columns={"value": "Money ($)"}) sns.lineplot(x='Waves (Nb)', y='Money ($)', hue='variable', data=data, ci=None, markers=True, style='variable', palette=['#E33B24', '#2EB4F6', '#797979'], ax=axes[0, 0]) axes[0, 0].legend(loc='upper left') # axe (0,1) : Matplotlib stackplot x = df['waves'].values y = [ df['shin'].values, df['moubu'].values, df['kanki'].values, df['ouhon'].values ] label = ["Shin", "Moubu", "Kanki", "Ouhon"] color = ['#2EB4F6', '#F2801B', '#6412CA', '#AAAAAA'] axes[0, 1].stackplot(x, y, labels=label, baseline='zero', colors=color) axes[0, 1].legend(loc='upper left') axes[0, 1].set_xlabel('Waves (Nb)') axes[0, 1].set_ylabel('Attack Towers (Nb)') # axe (1,0) : Seaborn lineplot color = '#E33B24' data = pd.DataFrame({ 'Waves (Nb)': df['waves'].values, 'Lives (Nb)': df['lives'].values }) sns.lineplot(x='Waves (Nb)', y='Lives (Nb)', data=data, ci=None, markers=True, color=color, ax=axes[1, 0]) # axe (1,1) : Matplotlib stackplot x = df['waves'].values y = [ df['kyoukai'].values, df['ten'].values, df['ryo'].values, df['fortress'].values ] label = ["Kyoukai", "Ten", "Ryo", "Fortress"] color = ['#E33B24', '#2EB4F6', '#EECE1A', '#AAAAAA'] axes[1, 1].stackplot(x, y, labels=label, baseline='zero', colors=color) axes[1, 1].legend(loc='upper left') axes[1, 1].set_xlabel('Waves (Nb)') axes[1, 1].set_ylabel('Support Towers (Nb)') def plot_enemies(self, df, spawned, alive, df_gold): """ plot end game statistics : 4 graphs (enemies killes, not killed, money earnt) """ # Plot-2 configuration fig, axes = plt.subplots(2, 2, figsize=(14, 14)) sns.set(style="whitegrid") # data not_killed = [x[1] for x in alive.items()] killed = [x - y for (x, y) in zip(spawned, not_killed)] waves = df['waves'].values spawned_count = df['spawned'].values kill_count = df['killed'].values # colors color_red = '#E33B24' color_blue = '#2EB4F6' color_green = '#6EF95F' # axe (0,0) : Seaborn barplot x_red = spawned x_blue = killed y = enemy_nickname data_red = pd.DataFrame({'Enemies': y, 'Number': x_red}) data_blue = pd.DataFrame({'Enemies': y, 'Number': x_blue}) sns.barplot(x='Number', y='Enemies', data=data_red, ci=None, color=color_red, orient='h', ax=axes[0, 0]) sns.barplot(x='Number', y='Enemies', data=data_blue, ci=None, color=color_blue, orient='h', ax=axes[0, 0]) axes[0, 0].legend(loc='lower right', labels=['Not Killed', 'Killed']) axes[0, 0].set_xlabel('Enemies (Nb)') axes[0, 0].set_ylabel('Enemies (Type)') # axe (0,1) : Seaborn barplot df2 = df.drop(['spawned', 'killed'], axis=1) df2 = df2.sort_values('waves', ascending=False) df2.set_index('waves').plot(kind='barh', stacked=True, ax=axes[0, 1]) axes[0, 1].set_xlabel('Enemies (Nb)') axes[0, 1].set_ylabel('Waves (Nb)') # axe (1,0) : Seaborn barplot x_red = spawned_count x_blue = kill_count y = waves data_red = pd.DataFrame({'Waves': y, 'Number': x_red}) data_blue = pd.DataFrame({'Waves': y, 'Number': x_blue}) sns.barplot(x='Number', y='Waves', data=data_red, ci=None, color=color_red, orient='h', ax=axes[1, 0]) sns.barplot(x='Number', y='Waves', data=data_blue, ci=None, color=color_green, orient='h', ax=axes[1, 0]) axes[1, 0].legend(loc='upper right', labels=['Not Killed', 'Killed']) axes[1, 0].set_xlabel('Enemies (Nb)') axes[1, 0].set_ylabel('Waves (Nb)') # axe (1,1) : Seaborn barplot sns.barplot(x='Gold Earnt', y='Enemies (Type)', data=df_gold, ci=None, orient='h', ax=axes[1, 1]) axes[1, 1].legend(loc='lower right')
class Game: def __init__(self): self.width = 1600 self.height = 1000 self.win = pygame.display.set_mode((self.width, self.height)) self.enemys = [] self.units = [] self.attack_towers = [] self.support_towers = [] self.lives = 10 self.points = 30 self.money = 5000 self.bg = pygame.transform.scale(pygame.image.load(os.path.join("game_assets/support_stuff", "map.png")), (1600, 1000)) self.timer = time.time() self.font = pygame.font.SysFont("comicsans", 70) self.clicks = [] self.selected_tower = None self.wave = 0 self.current_wave = waves[self.wave][:] self.pause = True self.music_on = True self.playPauseButton = PlayPauseButton(play_btn, pause_btn, 10, self.height - 85) self.soundButton = PlayPauseButton(sound_btn, sound_btn_off, 10 + self.playPauseButton.width, self.height - 85) self.menu = VerticalMenu(self.width - vertical_img.get_width() - 5, 200, vertical_img) self.menu.add_btn(longRangeshortcut, "longRangeTower", 500) self.menu.add_btn(rangeShortcut, "rangeTower", 750) self.menu.add_btn(damageShortcut, "damageTower", 1000) self.moving_object = None def gen_enemies(self): if sum(self.current_wave) == 0: if len(self.enemys) == 0: self.wave += 1 if self.wave >= len(waves): self.wave = 0 self.current_wave = waves[self.wave][:] self.pause = True self.playPauseButton.paused = self.pause else: wave_enemies = [Skeleton(), Warrior(), Wizard(), Boss()] for x in range(len(self.current_wave)): if self.current_wave[x] != 0: self.enemys.append(wave_enemies[x]) self.current_wave[x] = self.current_wave[x] - 1 break def run(self): pygame.mixer.music.play(loops=-1) run = True clock = pygame.time.Clock() while run: clock.tick(60) # generowanie potworow: if self.pause == False: if time.time() - self.timer > random.randrange(1, 5): self.timer = time.time() self.gen_enemies() pos = pygame.mouse.get_pos() # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) tower_list = self.attack_towers[:] + self.support_towers[:] collide = False for tower in tower_list: if tower.collide(self.moving_object): collide = True tower.place_color = (255, 0, 0, 100) self.moving_object.place_color = (255, 0, 0, 100) else: tower.place_color = (0, 0, 255, 100) if not collide: self.moving_object.place_color = (0, 0, 255, 100) # main event loop for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.MOUSEBUTTONDOWN: # if youre moving an object and click if self.moving_object: not_allowed = False tower_list = self.attack_towers[:] + self.support_towers[:] for tower in tower_list: if tower.collide(self.moving_object): not_allowed = True if not not_allowed: if self.moving_object.name in attack_tower_names: self.attack_towers.append(self.moving_object) elif self.moving_object.name in support_tower_names: self.support_towers.append(self.moving_object) self.moving_object.moving = False self.moving_object = None else: # look if you click on side menu side_menu_button = self.menu.get_clicked(pos[0], pos[1]) if side_menu_button: cost = self.menu.get_item_cost(side_menu_button) if self.money >= cost: self.money -= cost self.add_tower(side_menu_button) else: print("You don't have enough money") # odkomentowac i zakomentowac inne przy ustalaniu nowego path na mapie # self.clicks.append(pos) # print(pos) # sprawdzanie przyciskow pauza/graj: if self.soundButton.click(pos[0], pos[1]): self.music_on = not (self.music_on) self.soundButton.paused = self.music_on if self.music_on: pygame.mixer.music.unpause() else: pygame.mixer.music.pause() # sprawdzanie przyciskow grania muzyki if self.playPauseButton.click(pos[0], pos[1]): self.pause = not (self.pause) self.playPauseButton.paused = self.pause # look if you clicked on attack tower or support tower btn_clicked = None if self.selected_tower: btn_clicked = self.selected_tower.menu.get_clicked(pos[0], pos[1]) if btn_clicked: if btn_clicked == "Upgrade": cost = self.selected_tower.get_upgrade_cost() if self.money >= cost: if self.selected_tower.upgrade() == True: self.money -= cost if not (btn_clicked): for t in self.attack_towers: if t.click(pos[0], pos[1]): t.selected = True self.selected_tower = t else: t.selected = False # look if you clicked on support tower for t in self.support_towers: if t.click(pos[0], pos[1]): t.selected = True self.selected_tower = t else: t.selected = False if not (self.pause): # loop through enemies to_del = [] for en in self.enemys: en.move() if en.x > 1250 and en.y < 225: to_del.append(en) # delete all the enemies for d in to_del: self.lives -= 1 self.enemys.remove(d) # TODO: jesli sie uda zrobic przeciwnika to trzeba zupdatowac atak o dodawanie pieniedzy # loop through attack towers for t in self.attack_towers: if isinstance(t, EnemyBase): t.attack(self.units) else: self.money += t.attack(self.enemys) # loop through support towers for t in self.support_towers: t.support(self.attack_towers) # when you lose if self.lives <= 0: print("You lose") run = False self.draw() pygame.quit() def point_to_line(self, tower): """ returns if you can place tower based on distance from path :param tower: Tower :return: Bool """ # find two closest points return True def draw(self): self.win.blit(self.bg, (0, 0)) if self.moving_object: for tower in self.attack_towers: tower.draw_placement(self.win) for tower in self.support_towers: tower.draw_placement(self.win) self.moving_object.draw_placement(self.win) # draw clicks for p in self.clicks: pygame.draw.circle(self.win, (255, 0, 0), (p[0], p[1]), 5, 0) # draw enemies for en in self.enemys: en.draw(self.win) # draw attack towers for at in self.attack_towers: at.draw(self.win) # draw support towers for st in self.support_towers: st.draw(self.win) # draw vertical menu self.menu.draw(self.win) # draw moving object if self.moving_object: self.moving_object.draw(self.win) # draw play pause button self.playPauseButton.draw(self.win) # draw sound on/off button self.soundButton.draw(self.win) # draw money text = self.font.render(str(self.money), 1, (255, 255, 255)) money = pygame.transform.scale(money_img, (55, 55)) start_x = self.width - 35 self.win.blit(text, (10, 10)) self.win.blit(money, (115, 5)) # draw lives lenght = 300 move_by = lenght / 10 health_bar = round(move_by * self.lives) pygame.draw.rect(self.win, (255, 0, 0), (1270, 33, lenght, 10), 0) pygame.draw.rect(self.win, (0, 255, 0), (1270, 33, health_bar, 10), 0) # life = pygame.transform.scale(lives_img, (32, 32)) # start_x = self.width - life.get_width() - 5 # for x in range(self.lives): # self.win.blit(life, (start_x - life.get_width() * x + 5, 10)) pygame.display.update() def add_tower(self, name): x, y = pygame.mouse.get_pos() name_list = ["longRangeTower", "rangeTower", "damageTower"] object_list = [LongRangeTower(x, y), DamageTower(x, y), RangeTower(x, y)] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + "NOT VALID NAME")
class Multiplayer: def __init__(self): # super().__init__() self.width = 1600 self.height = 1000 self.win = pygame.display.set_mode((self.width, self.height)) self.player1 = Game() self.player1.win = self.win self.player2 = Game() self.player2.win = self.win self.current_player = self.player1 self.playersTurn = 0 self.pointsGained = 0 self.timer = time.time() self.font = pygame.font.SysFont("comicsans", 35) self.selected_tower = None self.switchButton = PlayPauseButton(play_btn, pause_btn, 100, 20) self.playPauseButton = PlayPauseButton(play_btn, pause_btn, 10, self.height - 85) self.soundButton = PlayPauseButton(sound_btn, sound_btn_off, 10 + self.playPauseButton.width, self.height - 85) self.startRoundButton = PlayPauseButton(pause_btn, play_btn, 100, 100) self.current_wave = [] self.pause = True self.switch = False self.start = False self.music_on = True self.startRoundButton.paused = self.start # this line is made so the image will be drawn correctly self.menu = VerticalMenu(self.width - vertical_img.get_width() - 5, 200, vertical_img) self.menu.add_btn(longRangeshortcut, "longRangeTower", 500) self.menu.add_btn(rangeShortcut, "rangeTower", 750) self.menu.add_btn(damageShortcut, "damageTower", 1000) self.moving_object = None def switch_players(self): self.current_player.points += 30 + self.pointsGained self.pointsGained = 0 if self.playersTurn == 0: self.current_player = self.player2 self.playersTurn = 1 else: self.current_player = self.player1 self.playersTurn = 0 self.start = False self.startRoundButton.paused = False def gen_enemies(self): if len(self.current_wave) > 0: if self.playersTurn == 1: self.current_wave[0].path.reverse() self.current_wave[0].x = self.current_wave[0].path[0][0] self.current_wave[0].y = self.current_wave[0].path[0][1] self.current_player.enemys.append(self.current_wave[0]) self.current_wave.pop(0) else: self.start = False def run(self): pygame.mixer.music.play(loops=-1) run = True clock = pygame.time.Clock() while run: clock.tick(60) # generowanie potworow: if self.start == True and self.pause == True: if time.time() - self.timer > random.randrange(1, 5): self.timer = time.time() self.gen_enemies() pos = pygame.mouse.get_pos() # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) tower_list = self.current_player.attack_towers[:] + self.current_player.support_towers[:] collide = False for tower in tower_list: if tower.collide(self.moving_object): collide = True tower.place_color = (255, 0, 0, 100) self.moving_object.place_color = (255, 0, 0, 100) else: tower.place_color = (0, 0, 255, 100) if not collide: self.moving_object.place_color = (0, 0, 255, 100) # main event loop for event in pygame.event.get(): if event.type == pygame.QUIT: run = False # jak sie klika przyciski na klawiaturze to dodaje do fali i odejmuje z punktow gracza if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: if self.current_player.points >= 5: self.current_player.points -= 5 self.current_wave.append(Skeleton()) if event.key == pygame.K_w: if self.current_player.points >= 10: self.current_player.points -= 10 self.current_wave.append(Warrior()) if event.key == pygame.K_e: if self.current_player.points >= 15: self.current_player.points -= 15 self.current_wave.append(Wizard()) if event.key == pygame.K_r: if self.current_player.points >= 150: self.current_player.points -= 150 self.current_wave.append(Boss()) if event.type == pygame.MOUSEBUTTONDOWN: # przycik pauzy gry if self.playPauseButton.click(pos[0], pos[1]): self.pause = not (self.pause) self.playPauseButton.paused = self.pause # przycisk zamiany graczy if self.switchButton.click(pos[0], pos[1]): if len(self.current_wave) == 0 and len( self.current_player.enemys) == 0 and self.current_player.points == 0: self.switch_players() # przycisk startu fali przeciwnikow if self.startRoundButton.click(pos[0], pos[1]): if self.current_player.points == 0 and len(self.current_player.enemys) == 0: self.start = not (self.start) self.startRoundButton.paused = self.start # if youre moving an object and click if self.moving_object: not_allowed = False tower_list = self.current_player.attack_towers[:] + self.current_player.support_towers[:] for tower in tower_list: if tower.collide(self.moving_object): not_allowed = True if not not_allowed: if self.moving_object.name in attack_tower_names: self.current_player.attack_towers.append(self.moving_object) elif self.moving_object.name in support_tower_names: self.current_player.support_towers.append(self.moving_object) self.moving_object.moving = False self.moving_object = None else: # look if you click on side menu side_menu_button = self.menu.get_clicked(pos[0], pos[1]) if side_menu_button: cost = self.menu.get_item_cost(side_menu_button) if self.current_player.money >= cost: self.current_player.money -= cost self.add_tower(side_menu_button) else: print("You don't have enough money") # odkomentowac i zakomentowac inne przy ustalaniu nowego path na mapie # self.clicks.append(pos) # print(pos) # sprawdzanie przyciskow wlaczania muzyki: if self.current_player.soundButton.click(pos[0], pos[1]): self.music_on = not (self.music_on) self.current_player.soundButton.paused = self.music_on if self.music_on: pygame.mixer.music.unpause() else: pygame.mixer.music.pause() # look if you clicked on attack tower or support tower btn_clicked = None if self.selected_tower: btn_clicked = self.selected_tower.menu.get_clicked(pos[0], pos[1]) if btn_clicked: if btn_clicked == "Upgrade": cost = self.selected_tower.get_upgrade_cost() if self.current_player.money >= cost: if self.selected_tower.upgrade() == True: self.current_player.money -= cost if not (btn_clicked): for t in self.current_player.attack_towers: if t.click(pos[0], pos[1]): t.selected = True self.selected_tower = t else: t.selected = False # look if you clicked on support tower for t in self.current_player.support_towers: if t.click(pos[0], pos[1]): t.selected = True self.selected_tower = t else: t.selected = False if self.pause: # loop through enemies to_del = [] for en in self.current_player.enemys: en.move() if en.nextGoal == True: self.pointsGained += 5 en.worth += 1 en.nextGoal = False if self.playersTurn == 0: if en.x > 1250 and en.y < 225: to_del.append(en) elif self.playersTurn == 1: if en.x < 115 and en.y > 600: to_del.append(en) # delete all the enemies for d in to_del: self.current_player.lives -= 1 self.current_player.enemys.remove(d) # loop through attack towers for t in self.current_player.attack_towers: self.current_player.money += t.attack(self.current_player.enemys) # loop through support towers for t in self.current_player.support_towers: t.support(self.current_player.attack_towers) # when you lose if self.current_player.lives <= 0: print("You lose") run = False self.draw() pygame.quit() def draw(self): self.win.blit(self.current_player.bg, (0, 0)) if self.moving_object: for tower in self.current_player.attack_towers: tower.draw_placement(self.win) for tower in self.current_player.support_towers: tower.draw_placement(self.win) self.moving_object.draw_placement(self.win) # draw enemies for en in self.current_player.enemys: en.draw(self.win) # draw attack towers for at in self.current_player.attack_towers: at.draw(self.win) # draw support towers for st in self.current_player.support_towers: st.draw(self.win) # draw vertical menu self.menu.draw(self.win) # draw moving object if self.moving_object: self.moving_object.draw(self.win) # draw sound on/off button self.current_player.soundButton.draw(self.win) # TODO: trzeba trzeba ladnie ulozyc zycia i pieniadze # draw money text = self.font.render(str(self.current_player.money), 1, (255, 255, 255)) money = pygame.transform.scale(money_img, (35, 35)) start_x = self.width - 35 self.win.blit(text, (start_x - text.get_width() - 1, 10)) self.win.blit(money, (start_x, 10)) # draw lives # TODO: dokonczyc pokazywanie i tracenie zyc(Pjotero) lenght = 300 move_by = lenght / 10 health_bar = round(move_by * self.current_player.lives) pygame.draw.rect(self.win, (255, 0, 0), (1270, 33, lenght, 10), 0) pygame.draw.rect(self.win, (0, 255, 0), (1270, 33, health_bar, 10), 0) # draw switch players button self.switchButton.draw(self.win) # draw play/pause button self.playPauseButton.draw(self.win) # draw start round button self.startRoundButton.draw(self.win) # draw current players points to spent if there is no way if len(self.current_player.enemys) == 0: text = self.font.render(str(self.current_player.points), 1, (0, 0, 0)) self.win.blit(text, (85, 100)) # draw which player now plays if self.current_player == self.player1: text = self.font.render("player 1", 1, (0, 0, 0)) else: text = self.font.render("player 2", 1, (0, 0, 0)) start_x = 100 self.win.blit(text, (start_x - text.get_width() - 1, 10)) pygame.display.update() def add_tower(self, name): x, y = pygame.mouse.get_pos() name_list = ["longRangeTower", "rangeTower", "damageTower"] object_list = [LongRangeTower(x, y), DamageTower(x, y), RangeTower(x, y)] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + "NOT VALID NAME")
class Game: def __init__(self,tencentprice,aliprice,jdprice,appleprice,googleprice,twitterprice): self.tencentprice = tencentprice self.aliprice = aliprice self.jdprice = jdprice self.appleprice = appleprice self.googleprice = googleprice self.twitterprice = twitterprice self.width = 1080 self.height = 720 self.win = pygame.display.set_mode((self.width, self.height)) self.enemys = [] self.towers = [] self.support_tower = [] self.lives = 10 # self.towers = 10 self.money = 5000 self.score = 0 self.rank = rank() self.StartMenu = StartMenu(startmenu_img) self.bg = bg self.bg = pygame.transform.scale(self.bg, (self.width, self.height)) self.bg_index = 0 self.timer = time.time() self.selected_tower = None self.menu = VerticalMenu(self.width, 0, verticalMenu) self.menu.add_button(buy_archer, 'buy_archer', appleprice) self.menu.add_button(buy_archer_2, 'buy_archer_2', googleprice) self.menu.add_button(buy_damage, 'buy_damage', 0) self.menu.add_button(buy_range, 'buy_range', twitterprice) # self.moving_object = False self.moving_object = None self.wave = 0 self.current_wave = waves[self.wave][:] self.pause = False self.playPauseButton = PlayPauseButton(play_btn, pause_btn, 20, self.height - 85) self.font = pygame.font.Font(r'../Fonts/DINCond-BlackExpert.otf', 28) self.path = [] self.score_list = [] self.situation = False # self.clicks = [] self.lives = 10 def gen_enemies(self): ''' generate the next enemy or enemies to show :return: enemy ''' if sum(self.current_wave) == 0: if len(self.enemys) == 0: self.wave += 1 self.current_wave = waves[self.wave] self.pause = True self.playPauseButton.pause = self.pause else: wave_enemies = [Scorpion(self.jdprice,self.jdprice / 20), Club(self.tencentprice,self.tencentprice / 10), TMall(self.aliprice , self.aliprice / 5)] for x in range(len(self.current_wave)): if self.current_wave[x] != 0: self.enemys.append(wave_enemies[x]) self.current_wave[x] = self.current_wave[x] - 1 break def run(self): self.rank.getScores('scoreRank.txt') run = True clock = pygame.time.Clock() while run: clock.tick(30) if self.situation: if self.pause == False: # generate monstors if time.time() - self.timer >= random.randrange(1, 6) / 5: self.timer = time.time() self.gen_enemies() pos = pygame.mouse.get_pos() # check for moving object if self.moving_object: self.moving_object.move(pos[0], pos[1]) tower_list = self.towers[:] + self.support_tower[:] collide = False for tower in tower_list: if tower.collide(self.moving_object) or self.moving_object.occupyTheRoad(): collide = True tower.place_color = (232, 131, 152, 100) self.moving_object.place_color = (232, 131, 152, 150) else: tower.place_color = (36, 120, 132, 100) if not collide: self.moving_object.place_color = (36, 120, 132, 100) # main event loop for event in pygame.event.get(): pygame.time.delay(30) if event.type == pygame.QUIT: run = False if event.type == pygame.MOUSEBUTTONUP: # if you`re moving an object and click if event.button == 1: # 表示点击鼠标左键 Click_sound.play() if self.moving_object: not_allowed = False tower_list = self.towers[:] + self.support_tower[:] for tower in tower_list: if tower.collide(self.moving_object) or self.moving_object.occupyTheRoad(): not_allowed = True if not not_allowed: if self.moving_object.name in attack_tower_names: self.towers.append(self.moving_object) construction_sound.play() elif self.moving_object.name in support_tower_names: self.support_tower.append(self.moving_object) construction_sound.play() self.moving_object.moving = False self.moving_object = None else: # check for play or pause if self.playPauseButton.click(pos[0], pos[1]): self.pause = not self.pause self.playPauseButton.pause = self.pause # look if you clicked on attack tower or support tower side_menu_button = self.menu.get_click(pos[0], pos[1]) if side_menu_button: cost = self.menu.get_item_cost(side_menu_button) if self.money >= cost: self.money -= cost self.add_tower(side_menu_button) # print(side_menu_button) # check if clicked on the attack tower or support tower btn_clicked = None if self.selected_tower: btn_clicked = self.selected_tower.menu.get_click(pos[0], pos[1]) if btn_clicked: if btn_clicked == "upgrade_button" and self.selected_tower.level<=2: if self.money >= self.selected_tower.menu.item_cost[self.selected_tower.level - 1]: self.money -= self.selected_tower.menu.item_cost[self.selected_tower.level - 1] self.selected_tower.upgrade() construction_sound.play() pass if not btn_clicked: # look the range of the attack_towers for tw in self.towers: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False # look the range of the support_towers for tw in self.support_tower: if tw.click(pos[0], pos[1]): tw.selected = True self.selected_tower = tw else: tw.selected = False # self.clicks.append(pos) # print(self.clicks) if not self.pause: # loop through enemies to_del = [] for en in self.enemys: en.move() if en.y > 720: to_del.append(en) # delete all enemies off the screen for d in to_del: self.lives -= 1 lifeLost_sound.play() self.enemys.remove(d) # loop through towers for tw in self.towers: # tw.attack(self.enemys) add = tw.attack(self.enemys) self.money += add self.score += add if self.lives <= 0: gameLost_sound.play() self.rank.update(self.score, 'scoreRank.txt') self.drawScoreBorad() self.situation = False for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pos = pygame.mouse.get_pos() if event.type == pygame.MOUSEBUTTONUP: # print(pos[0],pos[1]) if pos[0] >= 350 and pos[0] <= 350 + 450 and pos[1] <= 280 + 80 and pos[1] >= 280: self.situation = True self.wave = 0 self.lives = 10 self.score = 0 self.money = 5000 print('You Lose') # run = False self.draw() else: self.drawScoreBorad() for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pos = pygame.mouse.get_pos() if event.type == pygame.MOUSEBUTTONUP: # print(pos[0],pos[1]) if pos[0] >= 350 and pos[0] <= 350 + 450 and pos[1] <= 280 + 80 and pos[1] >= 280: self.situation = True self.wave = 0 self.lives = 10 self.score = 0 self.money = 5000 self.enemys = [] self.towers = [] self.support_tower = [] # check if moving object pygame.quit() def drawScoreBorad(self): self.win.blit(self.bg, (0, 0)) self.StartMenu.draw(self.win) # generate score list self.score_list = self.rank.scores self.StartMenu.draw_score_list(self.win, self.score_list, self.score) # pygame.draw.rect(self.win, (255, 255, 255), (350, 280, 450, 80), 1) pygame.display.update() pass def draw(self): self.win.blit(self.bg, (0, 0)) # for p in self.clicks: # pygame.draw.circle(self.win, (255, 0, 0), (p[0], p[1]), 5, 0) # draw attack towers if self.moving_object: for tower in self.towers: tower.draw_placement(self.win) for tower in self.support_tower: tower.draw_placement(self.win) self.moving_object.draw_placement(self.win) # draw the enemies for en in self.enemys: en.draw(self.win) # draw the towers for tw in self.towers: tw.draw_shadow(self.win) tw.draw(self.win) # draw the range towers for st in self.support_tower: st.support(self.towers) st.draw_shadow(self.win) st.draw(self.win) st.draw_entity(self.win, self.towers) # draw moving object if self.moving_object: self.moving_object.draw(self.win) # redraw selected tower if self.selected_tower: self.selected_tower.draw(self.win) # draw play pause button self.playPauseButton.draw(self.win) # draw lives, grades, money live = lives_img start_x = self.width - live.get_width() - 55 self.win.blit(live, (start_x + live.get_width() - 125, 10)) text = text_font.render(str(self.lives), 1, (25, 29, 15)) self.win.blit(text, (start_x + live.get_width() - 50, 15)) # money money = coin_img start_x = self.width - money.get_width() - 55 self.win.blit(money, (start_x + money.get_width() - 450, 10)) text = text_font.render(str(self.money), 1, (25, 29, 15)) self.win.blit(text, (start_x + money.get_width() - 385, 15)) # grade grade = grade_img start_x = self.width - grade.get_width() - 55 self.win.blit(grade, (start_x + grade.get_width() - 285, 10)) text = text_font.render(str(self.score), 1, (25, 29, 15)) self.win.blit(text, (start_x + grade.get_width() - 225, 15)) # draws vertical menu self.menu.draw(self.win) # draw waves text = self.font.render('Wave # ' + str(self.wave), 1, (255, 255, 255)) self.win.blit(text, (10, 20)) pygame.display.update() def add_tower(self, name): x, y = pygame.mouse.get_pos() name_list = ['buy_archer', 'buy_archer_2', 'buy_damage', 'buy_range'] object_list = [ArcherTower(x, y, self.appleprice / 8 ,self.appleprice / 1500), ArcherTowerShort(x, y, self.googleprice / 12 ,self.googleprice / 1000), DamageTower(x, y), RangeTower(x, y ,self.twitterprice / 1000)] try: obj = object_list[name_list.index(name)] self.moving_object = obj obj.moving = True except Exception as e: print(str(e) + 'NOT VALID NAME')