def test_correct_deleting(self): with patch('application.Application') as perm_mock: perm_mock.game_engine = None cells = Unity.identifier(self.labyrinth)[0] way = deque(cells) pos = way[3] pos2 = way[2] game_state = GameState(perm_mock) creep2 = Creep(pos2[0], pos2[1], way, 1) creep = Creep(pos[0], pos[1], way, 1) game_state.world.creeps.append(creep) game_state.world.creeps.append(creep2) i = 0 while i < 4: creep.way.popleft() if i < 3: creep2.way.popleft() i += 1 game_state.world.creeps[0].health = 0 tower = Tower(0, 32, 'laser') tower.is_blast = True tower.level = 2 tower.attacked_creep = game_state.world.creeps[0] game_state.world.towers.append(tower) game_state.check_creeps(game_state.world, game_state.gamer) self.assertEqual(len(game_state.world.creeps), 2)
def test_tower_being_attacked_with_insufficient_troops(self): soldiers = SoldiersGroup("Blue", 50) opponents = SoldiersGroup("Red", 70) tower = Tower(opponents) tower.attack(soldiers) self.assertTrue(tower.warriors_group == 20 and tower.warriors_group.team == opponents)
def test_remove_a_ring_from_the_pin_one_and_insert_into_pin_two(self): tower = Tower(3) tower.move_ring(1,2) pinTwo = tower.pins[1] number_of_rings = len(pinTwo.rings) self.assertEqual(number_of_rings, 1)
def test_connect(self): tower = Tower(50, 57, 30, 1000) user = usr.User(1) tower.connect(user) self.assertEqual(tower.num_users(), 1) print(tower.users) self.assertTrue(tower.users[id])
def __init__(self, canvas, numDiscs = 3): super(HanoiGame, self).__init__(canvas, numDiscs) discs = range(1, numDiscs + 1) self.left_tower = Tower('Torre Esquerda', TowerPosition.Left) self.central_tower = Tower('Torre Central', TowerPosition.Center, sorted(discs, reverse=True)) self.right_tower = Tower('Torre Direita', TowerPosition.Right) self.disc_1_mutex = True self.moveCount = 0
def test_upgrade(self): tower = Tower(10, 20, 'freeze') self.assertEqual(tower.level, 1) self.assertEqual(tower.radius.size, 48) self.assertEqual(tower.damage, 1) tower.upgrade() self.assertEqual(tower.level, 2) self.assertEqual(tower.radius.size, 80) self.assertEqual(tower.damage, 2)
def place_randomly_in_range(self, board, x_min, x_max, y_min, y_max): tower = Tower(randrange(x_min, x_max), randrange(y_min, y_max)) count = board._num_towers while not board.add_tower(tower): assert count == board._num_towers, "place along path False error" tower = Tower(randrange(0, board._width), randrange(0, board._height)) assert count + 1 == board._num_towers, "place along path True error" return True
def __init__(self, team, pos, layer, creatureLayer): """ Creates a new ice tower instance (including libAVG nodes). team: the team, the tower belongs to. pos: the position of the tower. layer: the layer the tower should be placed on. """ Tower.__init__(self, team, pos, layer, creatureLayer)
def __init__(self, team, pos, layer, creatureLayer): """ Creates a new ice tower instance (including libAVG nodes). team: the team, the tower belongs to. pos: the position of the tower. layer: the layer the tower should be placed on. """ self.snowballAnimsList = [] Tower.__init__(self, team, pos, layer, creatureLayer) self.destroyCircleColor = "00BFFF"
def test_intersects(self): with patch('application.Application') as perm_mock: perm_mock.game_engine = None game_state = GameState(perm_mock) creep = Creep(20, 50, game_state.world.ways[0], 2) tower = Tower(40, 50, 'laser') tower.level = 2 self.assertEqual(game_state.intersects(tower, creep), True) tower = Tower(150, 300, 'freeze') self.assertEqual(game_state.intersects(tower, creep), False)
def __init__(self, pos): Tower.__init__(self, pos) self.name = "Landmine" self.image.fill((50, 50, 50)) self.fire_rate = 0.25 self.damage = 75 self.description = "A simple, single-use landmine." self.cost = 10 self.frame = TowerFrame(self)
def test_stop_blast(self): with patch('application.Application') as perm_mock: perm_mock.game_engine = None game_state = GameState(perm_mock) tower = Tower(50, 62, 'laser') creep = Creep(50, 62, game_state.world.ways[0], 1) tower.attacked_creep = creep game_state.world.towers.append(tower) game_state.stop_blast(game_state.world.towers, creep) self.assertEqual(game_state.world.towers[0].is_blast, False) self.assertEqual(game_state.world.towers[0].attacked_creep, None)
def build_tower(self, pos, tower): tile_pos = self.tile_coord(pos) for tower in self.game_towers: # check if tower already exists if tile_pos[0] == tower.tile_x and tile_pos[1] == tower.tile_y: return if self.money >= self.tower_type*300: new_tower = Tower(tile_x = tile_pos[0], tile_y = tile_pos[1], activate = True, angle = 0, t_type = self.tower_type) # Add the tower to the update group and set its display rect self.update_unit_rect(new_tower) new_tower._update_image() self.money = self.money - (500*self.tower_type) self.game_towers.append(new_tower) # add to list of towers
def __init__(self, pos): Tower.__init__(self, pos) self.name = "Slow Tower" self.image.fill((255, 170, 0)) self.fire_rate = 0 self.damage = 0 self.radius = 50 self.speed_mod = 0.75 self.description = "A tower which slows all enemies in its radius." self.cost = 75 self.extra_attributes = {"Slow Amount: ": str((1-self.speed_mod) * 100) + "%"} self.frame = TowerFrame(self, self.extra_attributes)
def __init__(self, pos): Tower.__init__(self, pos) self.name = "Rapid-fire Tower" self.image.fill((120, 0, 255)) self.projectile = Surface((5, 5)).convert() self.projectile.fill((120, 0, 255)) self.projectile_speed = 10 self.fire_rate = 0.25 self.damage = 7 self.description = "A tower with moderate range and very quick attack speed." self.cost = 50 self.frame = TowerFrame(self)
def __init__(self, pos): Tower.__init__(self, pos) self.name = "Multi Shot Tower" self.image.fill((150, 0, 150)) self.fire_rate = 1.5 self.damage = 20 self.radius = 150 self.max_targets = 3 self.description = "A tower which hits multiple enemy units." self.cost = 125 self.target = [] self.extra_attributes = {"Max Targets": str(self.max_targets)} self.frame = TowerFrame(self, self.extra_attributes)
def main(): tower = Tower() initial_rod = "one" final_rod = "two" tower.initialise_tower(initial_rod) tower.print_tower() tower.solve(initial_rod, final_rod)
def __init__(self, pos): Tower.__init__(self, pos) self.name = "Amp Field" self.image.fill((255, 255, 0)) self.fire_rate = 0 self.damage = 0 self.radius = 20 self.damage_mod = 1.5 self.description = "A block which increases the damage taken by all enemies on it." self.cost = 25 self.extra_attributes = { "Damage Amp: ": str((self.damage_mod - 1) * 100) + "%" } self.frame = TowerFrame(self, self.extra_attributes)
def mainThread(): table = Table() table.addpiece(1, 0, Pawn(1, 0, pawn_color, table.table_map)) table.addpiece(1, 1, Pawn(1, 1, pawn_color, table.table_map)) table.addpiece(1, 2, Pawn(1, 2, pawn_color, table.table_map)) table.addpiece(1, 3, Pawn(1, 3, pawn_color, table.table_map)) table.addpiece(1, 4, Pawn(1, 4, pawn_color, table.table_map)) table.addpiece(1, 5, Pawn(1, 5, pawn_color, table.table_map)) table.addpiece(1, 6, Pawn(1, 6, pawn_color, table.table_map)) table.addpiece(1, 7, Pawn(1, 7, pawn_color, table.table_map)) table.addpiece(0, 0, Tower(0, 0, tower_color, table.table_map)) table.addpiece(0, 1, Horse(0, 1, horse_color, table.table_map)) table.addpiece(0, 2, Bishop(0, 2, bishop_color, table.table_map)) table.addpiece(0, 3, King(0, 3, king_color, table.table_map)) table.addpiece(0, 4, Queen(0, 4, quin_color, table.table_map)) table.addpiece(0, 5, Bishop(0, 5, bishop_color, table.table_map)) table.addpiece(0, 6, Horse(0, 6, horse_color, table.table_map)) table.addpiece(0, 7, Tower(0, 7, tower_color, table.table_map)) table.addpiece(6, 0, Pawn(6, 0, pawn_color, table.table_map, True)) table.addpiece(6, 1, Pawn(6, 1, pawn_color, table.table_map, True)) table.addpiece(6, 2, Pawn(6, 2, pawn_color, table.table_map, True)) table.addpiece(6, 3, Pawn(6, 3, pawn_color, table.table_map, True)) table.addpiece(6, 4, Pawn(6, 4, pawn_color, table.table_map, True)) table.addpiece(6, 5, Pawn(6, 5, pawn_color, table.table_map, True)) table.addpiece(6, 6, Pawn(6, 6, pawn_color, table.table_map, True)) table.addpiece(6, 7, Pawn(6, 7, pawn_color, table.table_map, True)) table.addpiece(7, 0, Tower(7, 0, tower_color, table.table_map)) table.addpiece(7, 1, Horse(7, 1, horse_color, table.table_map)) table.addpiece(7, 2, Bishop(7, 2, bishop_color, table.table_map)) table.addpiece(7, 3, King(7, 3, king_color, table.table_map)) table.addpiece(7, 4, Queen(7, 4, quin_color, table.table_map)) table.addpiece(7, 5, Bishop(7, 5, bishop_color, table.table_map)) table.addpiece(7, 6, Horse(7, 6, horse_color, table.table_map)) table.addpiece(7, 7, Tower(7, 7, tower_color, table.table_map)) while True: for evento in py.event.get(): if evento.type == py.QUIT: py.quit() display.fill((255,255,255)) table.render(display, py, font) py.display.flip() time.tick(64)
def enter(): global soldier, space_world, soldier_bullet_team, tower, ship_bullet_team, alien_team space_world = Space_World() soldier = Soldier() tower = Tower() soldier_bullet_team = [Soldier_Bullet() for i in range(10)] ship_bullet_team = [Ship_Bullet() for i in range(30)] alien_team = [Alien() for i in range(30)] soldier.get_space(space_world) tower.get_space(space_world) for alien in alien_team: alien.get_tower(tower)
def test_initialize_tower_with_three_rings(self): tower = Tower(3) pinOne = tower.pins[0] number_of_rings = len(pinOne.rings) self.assertEqual(number_of_rings, 3)
def test_tower_creation(self): new_tower = Tower(SoldiersGroup(Player('Blue'))) print("done") self.assertTrue( new_tower.waiting_for_update is False and new_tower.update_time == 0 and new_tower.level == 1 and new_tower.warriors_group == SoldiersGroup(Player('Blue')))
def handle_mouse_events(self, mouse): for tower in self.world.towers: if tower.pressed(mouse) and self.world.current_tower_type == tower.type and not self.world.put_mine: if self.is_enough_money(self.world.upgrade_cost, self.gamer) and tower.can_be_upgraded(): self.gamer.money -= self.world.upgrade_cost tower.upgrade() else: pass #printCostMessage() for cell in self.world.tower_places: if cell.pressed(mouse) and not self.world.put_mine: if self.is_enough_money(self.world.buy_cost, self.gamer): self.gamer.money -= self.world.buy_cost self.world.tower_places.remove(cell) self.world.towers.append(Tower(cell.x, cell.y, self.world.current_tower_type)) else: pass #printCostMessage() if self.world.put_mine: inter = False mine = Mine((mouse[0] // 32) * 32, (mouse[1] // 32) * 32) for tower in self.world.towers: if mine.intersects(tower): inter = True for creep in self.world.creeps: if mine.intersects(creep): inter = True for tow_pl in self.world.tower_places: if mine.intersects(tow_pl): inter = True if not inter: if self.is_enough_money(20, self.gamer): self.world.mines.append(mine) self.gamer.money -= 20 self.world.put_mine = False
def run_game(): pygame.init() pygame.mixer.init() ai_settings = Settings() screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height)) pygame.mixer.music.load('sounds/bg_music2.mp3') pygame.mixer.music.play() pygame.mixer.music.set_volume(0.5) pygame.display.set_caption("Perestroika") bracing = Bracing(screen) GlobalState() blocks = Group() tower = Tower() trucks = Group() record = None for r in Record.filter(user="******"): record = r if record is None: record = Record(user="******", score=0) record.save() GlobalState().record = record builder = Builder(screen) block = Block(bracing) block.make_static() button = Button(screen) while True: gf.check_events(bracing, blocks, tower, builder, block, trucks, button) builder.update() bracing.update() blocks.update(bracing) block.update(bracing) trucks.update() gf.update_screen(screen, bracing, blocks, builder, block, trucks, button) GlobalState().ticks += 1
class Hanoi(object): def __init__(self, n): # stack starts on tower A self.towerA = Tower(n, "A") self.towerB = Tower(0, "B") self.towerC = Tower(0, "C") def _move(self, ndiscs, towerFrom, towerAux, towerTo): if ndiscs == 0: return else: # move n-1 discs to the auxiliary tower self._move(ndiscs - 1, towerFrom, towerTo, towerAux) # move nth disc from the source tower to the destination tower val = towerFrom.pop() towerTo.add(val) # move n-1 discs from the auxiliary tower to the destination tower self._move(ndiscs - 1, towerAux, towerFrom, towerTo) def run(self): self._move(self.towerA.size(), self.towerA, self.towerB, self.towerC)
def __init__(self, pos): Tower.__init__(self, pos) self.name = "Mortar Tower" self.image = Surface((40, 40)).convert() self.image.fill((0, 0, 255)) self.projectile = Surface((15, 15)).convert() self.projectile.fill((255, 150, 0)) self.projectile_speed = 3 self.radius = 300 self.fire_rate = 3 self.damage = 15 self.description = "A long-range tower that fires mortars which " \ "explode on impact, dealing damage to all nearby enemies." self.cost = 75 self.frame = TowerFrame(self)
def read_input(self, input_file): inputs = open(input_file) self.points = int(inputs.readline()) position = 0 for line in inputs.readlines(): informations = line.split(' ') tower = Tower() tower.name = informations.pop(0) tower.cost = float(informations.pop(0)) tower.points = sorted([int(point) for point in informations if point.isdigit()]) tower.position = position position += 1 self.append_tower(tower) self.__towers = sorted(self.__towers, key=lambda tower: tower.cost) self.__generate_distances() self.__generate_pheromones()
def test_wave_is_over(self): with patch('application.Application') as perm_mock: perm_mock.game_engine = None game_state = GameState(perm_mock) game_state.world.creeps[0].rect = (20, 20, 50, 100) game_state.world.finish = [20, 20] game_state.check_creeps(game_state.world, game_state.gamer) self.assertEqual(game_state.wave_is_over(game_state.world), True) creep = Creep(20, 50, game_state.world.ways[0], 2) tower = Tower(30, 50, 'laser') tower.level = 2 creep.health = 0 game_state.world.creeps.append(creep) game_state.world.towers.append(tower) game_state.blast_and_kill(game_state.world.creeps[0], game_state.world, game_state.gamer) self.assertEqual(game_state.wave_is_over(game_state.world), True)
def test_blast(self): with patch('application.Application') as perm_mock: perm_mock.game_engine = None game_state = GameState(perm_mock) creep = Creep(50, 62, game_state.world.ways[0], 1) tower = Tower(50, 62, 'laser') game_state.blast(tower, creep) self.assertEqual(creep.health, 99)
def addTower(self,x,y,ttype): gold = [50,100,500] if x < len(self.map.map) and y < len(self.map.map[0]) and self.map.map[y][x].isWall and self.isFree(x,y): g = gold[ttype-1] if self.player.gold >= g: self.player.getGold(-g) if ttype == 1: # Arrow tower #Tower(self,x,y,damage,trange,firerate,projSpeed,ttype): newtower = Tower(x*self.squareSize,y*self.squareSize,10,200,10,20,1) self.buttons[0].activated = False elif ttype == 2: newtower = Tower(x*self.squareSize,y*self.squareSize,10,150,15,20,2) self.buttons[1].activated = False elif ttype == 3: newtower = LaserTower(x*self.squareSize,y*self.squareSize,4,100,3) self.buttons[2].activated = False self.towers.append(newtower)
def add_tower(self): """ add a tower to the game """ (ex, ey) = self.__MAP.get_entrance_coords( ) #STUB: add tower on entrance by default cell = self.__MAP.get_cell_from_grid((ex, ey)) tower = Tower(self, (ex * self.__MAP.get_cell_width(), ey * self.__MAP.get_cell_height()), cell) cell.add_tower(tower) self.__tower_list.append(tower) return
def reset(self, money=200, wave=1): """ ([int], [int]) -> None Reset money, wave number, and other similar game world properties. """ self.money = money self.wave = wave self.turrets = [] self.intersections = [] self.enemies = [] self.tower = Tower(IMG_PATH_TOWER, self.screenW / 2, self.screenH / 2) self.mode = self.modes[0]
def map_sprites(): global decorations decorations = pygame.sprite.Group() decorations.add(Pond(400, 325)) decorations.add(Road_2(150, 0)) decorations.add(Road_2(350, 0)) decorations.add(Road_2(550, 0)) decorations.add(Road_2(750, 0)) decorations.add(Road(0, 75)) decorations.add(Road(0, 375)) decorations.add(Road(0, 675)) decorations.add(Box(5, 5)) decorations.add(Box(495, 20)) decorations.add(Box(295, 320)) decorations.add(Box(95, 130)) decorations.add(Box(605, 320)) decorations.add(Box(205, 620)) decorations.add(Box(695, 430)) decorations.add(Box(945, 620)) decorations.add(Box(405, 730)) decorations.add(Box(805, 745)) decorations.add(Tower(0, 275)) decorations.add(Tower(200, 125)) decorations.add(Tower(950, 275)) decorations.add(Tower(300, 575)) decorations.add(Fan(700, 125)) decorations.add(Fan(950, 125)) decorations.add(Fan(0, 625)) decorations.add(Fan(600, 625)) decorations.add(Fan(300, 0)) decorations.add(Fan(200, 750)) decorations.add(Tree(400, 125)) decorations.add(Tree(500, 625)) decorations.add(Flower(405, 325)) decorations.add(Flower(530, 325)) decorations.add(Flower(465, 300)) decorations.add(Flower(405, 460)) decorations.add(Flower(530, 460)) decorations.add(Flower(465, 480)) decorations.add(Arrow(875, 25))
def test_stop_blast(self): tower = Tower(10, 20, 'laser') tower.attacked_creep = Creep(10, 20, [0, 0], 1) tower.is_blast = True tower.stop_blast() self.assertEqual(tower.is_blast, False) self.assertEqual(tower.attacked_creep, None)
def main(): tower = Tower(join(dirname(__file__), 'tower.txt')) tower_example = Tower(join(dirname(__file__), 'example.txt')) print('Part 1') print('Bottom program: {}'.format(tower_example.get_bottom())) print('Solution to part 1: {}'.format(tower.get_bottom())) print() print('Part 2') solution = tower_example.weight_to_balance() print('Correct weight: {}'.format(solution)) solution2 = tower.weight_to_balance() print('Solution to part 2: {}'.format(solution2))
def create_tower(self, x1, x2, y1, y2): """Create a tower instance for the solver Args: x1 (int): x1 coordinate x2 (int): x2 coordinate y1 (int): y1 coordinate y2 (int): y2 coordinate Returns: Tower: A Tower instance """ # Argument checks are done by Tower.__init__ return Tower(self, x1, x2, y1, y2)
class HanoiGame(HanoiGameGui): def __init__(self, canvas, numDiscs = 3): super(HanoiGame, self).__init__(canvas, numDiscs) discs = range(1, numDiscs + 1) self.left_tower = Tower('Torre Esquerda', TowerPosition.Left) self.central_tower = Tower('Torre Central', TowerPosition.Center, sorted(discs, reverse=True)) self.right_tower = Tower('Torre Direita', TowerPosition.Right) self.disc_1_mutex = True self.moveCount = 0 def move(self): if self.disc_1_mutex: self.forward_move(1) self.disc_1_mutex = False else: disc_on_left = self.left_tower.top() disc_on_center = self.central_tower.top() disc_on_right = self.right_tower.top() values = [v for v in [disc_on_left, disc_on_center, disc_on_right] if v != 1 and v > 0] minValue = min(values) self.forward_move(minValue) self.disc_1_mutex = True self.moveCount += 1 def able_tower(self, d, tower): if len(tower) == 0: return True value = tower[len(tower) - 1] if d > value: return False return True def forward_move(self, d): if d in self.right_tower: self.next_move(d, self.left_tower, self.central_tower) elif d in self.central_tower: self.next_move(d, self.right_tower, self.left_tower) elif d in self.left_tower: self.next_move(d, self.right_tower, self.central_tower) def next_move(self, d, tower_a, tower_b): #first movement if len(tower_a) == 0 and len(tower_b) == 0: self.move_disc(d, tower_b) return #if any tower is unable to receive the disk, it goes the other way if not self.able_tower(d, tower_a): self.move_disc(d, tower_b) return if not self.able_tower(d, tower_b): self.move_disc(d, tower_a) return disc_on_a = tower_a.top() disc_on_b = tower_b.top() if (disc_on_a - 1) == d: self.move_disc(d, tower_a) elif (disc_on_b - 1) == d: self.move_disc(d, tower_b) elif d == 1: tower = self.disc1_new_tower(tower_a, tower_b) print('disc1 new tower', tower) self.move_disc(d, tower) def disc1_new_tower(self, tower_a, tower_b): current_tree = [] disc1_current_tower = self.get_tower(1) i = len(disc1_current_tower) - 1 current_tree.append(disc1_current_tower[i]) while disc1_current_tower[i - 1] - disc1_current_tower[i] == 1: i-=1 current_tree.append(disc1_current_tower[i]) max_current_tree = max(current_tree) len_current_tree = len(current_tree) len_is_odd = len_current_tree % 2 != 0 building_tower = self.get_tower(max_current_tree + 1) if len_is_odd: if building_tower == tower_a: return tower_a return tower_b else: if building_tower == tower_a: return tower_b return tower_a def get_tower(self, d): if d in self.right_tower: return self.right_tower elif d in self.central_tower: return self.central_tower elif d in self.left_tower: return self.left_tower def move_disc(self, d, tower): if d in self.left_tower: self.left_tower.pop() if d in self.central_tower: self.central_tower.pop() if d in self.right_tower: self.right_tower.pop() #self.write_movement(d, tower) super(HanoiGame, self).moveDiscToTower(d, tower) tower.append(d) def write_movement(self, d, tower): print(d, '=>', tower)
class Game(object): modes = ['Waiting', 'In Play'] def __init__(self, fps=60, fullscreen=False): """ (int, int, int, bool) -> Game Instantiate Game object with expected properties of a tower defense game. """ pygame.init() # Parameter-based properties self.fps = fps self.fullscreen = fullscreen # Determine width and height self.screenW = pygame.display.list_modes()[0][0] self.screenH = pygame.display.list_modes()[0][1] if not self.fullscreen: self.screenW = floor(0.8 * self.screenW) self.screenH = floor(0.8 * self.screenH) # Display and framerate properties self.caption = GAME_NAME + ' - Left Mouse Button to select/place turret, drag by moving the mouse' self.displaySurf = None if self.fullscreen: self.flags = FULLSCREEN | DOUBLEBUF | HWACCEL else: self.flags = DOUBLEBUF | HWACCEL self.fpsClock = pygame.time.Clock() self.initializeDisplay() # Define and reset gameplay properties and objects self.money, self.wave, self.turrets, self.enemies, self.intersections, \ self.measuredFPS, self.tower, self.mode = [None] * 8 self.reset() # HUD object hudSize = 300 hudRect = pygame.Rect(self.screenW - hudSize, 0, hudSize, self.screenH) hudColour = GREY self.hud = HUD(hudRect, hudColour, Turret(), FourShotTurret(), GlueTurret(), FireTurret(), LongRange(), EightShotTurret()) # Collision-related properties self.pathRects = [] # Level appearance and elements self.intersectionSurface = pygame.Surface(self.displaySurf.get_size(), SRCALPHA | RLEACCEL, 32).convert_alpha() self.pathColour = ORANGE self.grassColour = LGREEN self.pathWidth = 50 # Mouse and events self.mouseX, self.mouseY = 0, 0 self.clicking = False self.dragging = False self.events = [] # Health increment self.healthIncrement = 1 # Menu object self.menu = Menu() # Background self.background = pygame.image.load(getDataFilepath(IMG_PATH_GRASS)).convert() self.pathImage = pygame.image.load(getDataFilepath(IMG_PATH_DIRT)).convert() # Sounds self.backgroundMusic = Sound(getDataFilepath('retro.wav'), True) self.hitSound = Sound(SOUND_PATH_SHOT, False) self.inPlay = True def reset(self, money=200, wave=1): """ ([int], [int]) -> None Reset money, wave number, and other similar game world properties. """ self.money = money self.wave = wave self.turrets = [] self.intersections = [] self.enemies = [] self.tower = Tower(IMG_PATH_TOWER, self.screenW / 2, self.screenH / 2) self.mode = self.modes[0] def incrementEnemyHealth(self, increment): for enemy in self.enemies: enemy.health *= increment def generateEnemies(self, x=1, separation=70): """ ([int], [int]) -> None Generate "x" number of enemies with the given separation for the tower defense game. """ # Return immediately if there are no intersections loaded. if not self.intersections: print('WARNING: Enemies not loaded! Intersections must be loaded first.') return # Clear the list of enemies to start with. self.enemies = [] # Gather information and create temporary variables. firstTurnX = self.intersections[0][0] firstTurnY = self.intersections[0][1] secondTurnX = self.intersections[1][0] secondTurnY = self.intersections[1][1] gap = x * separation xlist = [] ylist = [] direction = NODIR # Determine the starting direction and co-ordinate lists for the enemies. if firstTurnX == secondTurnX and firstTurnY > secondTurnY: xlist = [firstTurnX] ylist = xrange(firstTurnY, firstTurnY + gap, separation) direction = UP elif firstTurnX == secondTurnX: xlist = [firstTurnX] ylist = xrange(firstTurnY - gap, firstTurnY, separation) direction = DOWN elif firstTurnY == secondTurnY and firstTurnX > secondTurnX: xlist = xrange(firstTurnX, firstTurnX + gap, separation) ylist = [firstTurnY] direction = LEFT elif firstTurnY == secondTurnY: xlist = xrange(firstTurnX - gap, firstTurnX, separation) ylist = [firstTurnY] direction = RIGHT # Create enemies with the information determined above. w = Enemy(IMG_PATH_ENEMY1, 0, 0).w h = Enemy(IMG_PATH_ENEMY1, 0, 0).h assigned = False for x in xlist: for y in ylist: enemyType = random.randint(1, 5) if enemyType == 2 and not assigned: self.enemies.append(Enemy(IMG_PATH_ENEMY2, x - w // 2, y - h // 2, direction, 3, 200)) assigned = True elif enemyType == 3 and not assigned and self.wave >= 2: self.enemies.append(Enemy(IMG_PATH_ENEMY3, x - w // 2, y - h // 2, direction, 2, 300)) assigned = True elif enemyType == 4 and not assigned and self.wave >= 2: self.enemies.append(Plane(IMG_PATH_ENEMY4, x - w // 2, y - h // 2, direction, 6, 100)) assigned = True elif enemyType == 5 and not assigned and self.wave >= 10: self.enemies.append(HugeTank(IMG_PATH_ENEMY5, x - w // 2, y - h // 2, direction, 2, 500)) assigned = True else: self.enemies.append(Enemy(IMG_PATH_ENEMY1, x - w // 2, y - h // 2, direction, health=100)) assigned = True self.enemies[-1].setNextIntersection(self.intersections[0]) self.enemies[-1].initialDistanceFromWorld = distance((self.enemies[-1].x, self.enemies[-1].y), (firstTurnX, firstTurnY)) assigned = False if self.wave % 5 == 0: self.healthIncrement += 1 self.incrementEnemyHealth(self.healthIncrement) # Sort the list of enemies in terms of ascending distance away from the initial intersection. self.enemies.sort(key=lambda x: x.initialDistanceFromWorld) def makeStrSubstitutions(self, string): """ (str) -> str Return the input string but with human-readable keywords exchanged for co-ordinates and directions. """ substitutions = {'RIGHT': RIGHT, 'LEFT': LEFT, 'UP': UP, 'DOWN': DOWN, 'WIDTH': self.hud.left, 'HEIGHT': self.screenH} result = string[:] for word in string.split(): if word in substitutions: result = result.replace(word, str(substitutions[word])) return result def stretchIntersections(self): """ (None) -> None Stretch or compress intersection co-ordinates as necessary to fit them to screen. """ # Return immediately if there are no intersections if not self.intersections: return # Gather info about the needed scaling for horizontal and vertical co-ordinates of each intersection temp = self.intersections[:] temp.sort(key=lambda x: x[0]) horizontalStretch = (self.screenW - self.hud.width) / float(temp[-1][0] + self.pathWidth // 2) temp = self.intersections[:] temp.sort(key=lambda x: x[1]) verticalStretch = self.screenH / float(temp[-1][1] + self.pathWidth) # Make it happen and leave the intersection direction intact for i in xrange(len(self.intersections)): self.intersections[i] = ceil(self.intersections[i][0] * horizontalStretch), \ ceil(self.intersections[i][1] * verticalStretch), self.intersections[i][2] self.tower.x *= horizontalStretch self.tower.y *= verticalStretch def loadIntersections(self, filename): """ (None) -> tuple Load the saved intersections from file based on the current wave. Return the loaded intersection 3-tuples. """ self.intersections = [] data = open(getDataFilepath(filename), 'r') for line in data: intersection = self.makeStrSubstitutions(line).split() intersection = int(intersection[0]), int(intersection[1]), int(intersection[2]) self.intersections.append(intersection) self.stretchIntersections() return self.intersections def loadTowerLoc(self, filename): """ (None) -> None Load the co-ordinates of the tower to defend. """ data = open(getDataFilepath(filename), 'r').read().split() x = int(self.makeStrSubstitutions(data[-3])) y = int(self.makeStrSubstitutions(data[-2])) self.tower.x, self.tower.y = x - self.tower.w // 2, y - self.tower.h // 2 newRect = self.tower.getRect().clamp(pygame.Rect(0, 0, self.screenW - self.hud.width, self.screenH)) self.tower.x = newRect.x self.tower.y = newRect.y def incrementWave(self): """ (None) -> None Set up the level for the next wave. """ self.wave += 1 self.generateEnemies(4 * self.wave) for turret in self.turrets: turret.bullets = [] turret.angle = 0 def drawText(self, text, x=0, y=0): """ (str, [int], [int]) -> None Draw the given string such that the text matches up with the given top-left co-ordinates. Acts as a wrapper for the HUD drawText(). """ self.hud.drawText(self.displaySurf, text=text, left=x, top=y) def handleAI(self): """ (None) -> None Force the enemies to turn at each intersection. """ if not self.enemies or not self.intersections: return for enemy in self.enemies: nextTurn = enemy.getNextIntersection() if not enemy.getReducedRect().collidepoint(nextTurn[0:2]): continue if nextTurn[-1] == LEFT: enemy.startMovingLeft() elif nextTurn[-1] == RIGHT: enemy.startMovingRight() elif nextTurn[-1] == UP: enemy.startMovingUp() elif nextTurn[-1] == DOWN: enemy.startMovingDown() else: enemy.stop() intersectionIndex = self.intersections.index(nextTurn) if intersectionIndex + 1 < len(self.intersections): enemy.setNextIntersection(self.intersections[intersectionIndex + 1]) def drawIntersections(self, surface): """ (Surface) -> None Draw a sequence of paths joining all of the intersections onto the given surface. Update the list of path Rect objects for collision detection. """ if not self.intersections: return points, intersectionRects, joinRects, result = [], [], [], [] half = floor(self.pathWidth / 2.0) for intersection in self.intersections: points.append((intersection[0], intersection[1])) for point in points: intersectionRects.append(pygame.Rect(point[0] - half, point[1] - half, 2 * half, 2 * half)) for i in xrange(len(points) - 1): result.append(intersectionRects[i].union(intersectionRects[i + 1])) surface.blit(self.pathImage, (result[-1].x, result[-1].y), result[-1]) self.pathRects = result def onPath(self, other): """ (int, int) -> bool Return True if the x and y co-ordinates represent a spot on the paths, False otherwise. """ result = False if not self.pathRects: return result for rect in self.pathRects: if (isinstance(other, tuple) and rect.collidepoint(other)) or rect.colliderect(other): result = True return result def onGrass(self, other): """ (int, int) -> bool Return True if the x and y co-ordinates represent a spot on the grass, False otherwise. """ return not self.onPath(other) def hoveringSidebar(self): """ (None) -> bool Return True if the mouse is hovering over the HUD sidebar, False otherwise. """ return self.mouseX >= self.hud.left def initializeDisplay(self): """ (None) -> Surface Initialize the display Surface and update the caption and display settings. Only call once in __init__. """ self.displaySurf = pygame.display.set_mode((self.screenW, self.screenH), self.flags) pygame.display.set_caption(self.caption) return self.displaySurf def redrawAndProceedTick(self): """ (None) -> None Redraw the screen, and delay to enforce the FPS. Call on every update. """ pygame.display.flip() self.fpsClock.tick_busy_loop(self.fps) self.measuredFPS = self.fpsClock.get_fps() def terminate(self): """ (None) -> None Set the game to exit as soon as possible. """ print('Game closing...') self.inPlay = False def handleQuitEvents(self, events): """ (list-of-Events) -> None Exit the game if Escape is pressed or if the close button is used. """ for event in events: if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.terminate() def updateState(self): """ (None) -> None Update the state of the game based on the user selection on the sidebar. """ if self.hud.shouldPause(): self.backgroundMusic.pause() if self.menu.drawPauseMenu(self.displaySurf): self.__init__(self.fps, self.fullscreen) self.execute() self.menu.drawPauseMenu(self.displaySurf) self.backgroundMusic.play(-1) if self.hud.shouldStart(): self.mode = self.modes[1] self.canRun() def updateEnemies(self): """ (None) -> None Update and draw all enemies and the central tower. """ levelComplete = True for enemy in self.enemies: if self.mode == self.modes[0]: enemy.pause() elif self.mode == self.modes[1]: enemy.unpause() if enemy.alive(): levelComplete = False enemy.update() self.tower.update(self.displaySurf, enemy) enemy.draw(self.displaySurf, enemy.x, enemy.y) if levelComplete and self.mode == self.modes[1]: self.mode = self.modes[0] self.incrementWave() def enemyIndex(self, enemy): try: return self.enemies.index(enemy) except IndexError: print('WARNING: Tried to access nonexistent enemy.') return 0 @staticmethod def inRange(enemy, turret): """ (Enemy, Turret) -> None Return True if the enemy is in range of the given turret, False otherwise. """ return distance(enemy.getRect().center, turret.getRect().center) < turret.range and enemy.active def setTarget(self, enemy, turret): """ (Enemy, Turret) -> None Lock onto a new enemy with the given turret. """ if not isinstance(turret, FourShotTurret) and turret.canShoot: turret.angle = getAngle(deltaX(enemy.x, turret.x), deltaY(enemy.y, turret.y)) turret.lockOn = True def provideReward(self, turret): """ (None, Turret) -> None Provide the player with a reward for each kill. """ self.money += turret.reward def updateTurrets(self): """ (None) -> None Update and draw all turrets and bullets. """ for turret in self.turrets: # Check if the turret is highlighted turret.highlighted = False if turret.getRect().collidepoint(self.mouseX, self.mouseY): turret.highlighted = True # Check for lock-on with enemies foundTarget = False for enemy in self.enemies: if self.inRange(enemy, turret): self.setTarget(enemy, turret) foundTarget = True break if not foundTarget: turret.lockOn = False turret.bullets = [] # Update and draw the turret turret.update(self.displaySurf) # Check for bullet collision with enemies for bullet in turret.bullets: for enemy in self.enemies: bulletEnemyCollision = bullet.getRect().colliderect(enemy.getRect()) if bulletEnemyCollision and not isinstance(turret, FourShotTurret): self.hitSound.play() bullet.dispose() turret.test = True if not isinstance(turret, GlueTurret) or \ (isinstance(enemy, Plane) and not isinstance(turret, FireTurret)): enemy.health -= bullet.damagePotential else: enemy.topSpeed *= bullet.slowFactor enemy.dispose() if enemy.health <= 0: self.provideReward(turret) elif bulletEnemyCollision: self.hitSound.play() enemy.health -= bullet.damagePotential enemy.dispose() bullet.dispose() if enemy.health <= 0: self.provideReward(turret) def updateHud(self): """ (None) -> None Update and draw the HUD sidebar. """ self.hud.update(self.tower.health, self.money, self.wave) self.hud.draw(self.displaySurf) def updateInputs(self): """ (None) -> None Get keyboard and mouse status and check for quit events. """ self.mouseX, self.mouseY = pygame.mouse.get_pos() self.clicking = pygame.mouse.get_pressed()[0] self.events = pygame.event.get() self.handleQuitEvents(self.events) def addTurret(self, index): """ (int) -> None Add a turret with the given index to the list of turrets. """ newTurret = copy.copy(self.hud.turrets[index]) newTurret.x = DEFAULT_VALUE newTurret.y = DEFAULT_VALUE self.turrets.append(newTurret) def handleDragging(self): """ (None) -> None Facilitate dragging of turrets from the HUD sidebar to the game field. """ overlapping = False index = self.hud.highlighted() clicked = False rects = [turret.getRect() for turret in self.turrets[0:-1]] if len(self.turrets) > 1: for rect in rects: if self.turrets[-1].getRect().colliderect(rect): overlapping = True for event in self.events: if event.type == MOUSEBUTTONDOWN: clicked = True if self.dragging and clicked and self.onGrass(self.turrets[-1].getRect()) and not overlapping: self.dragging = False self.turrets[-1].canShoot = True self.money -= self.turrets[-1].price if index >= 0 and clicked and not self.dragging and self.money >= self.hud.turrets[index].price: self.dragging = True self.addTurret(index) if self.dragging and not clicked: self.turrets[-1].x = self.mouseX - self.turrets[-1].width // 2 self.turrets[-1].y = self.mouseY - self.turrets[-1].height // 2 self.turrets[-1].canShoot = False def update(self): """ (None) -> None Update the entire game state and draws all objects on the screen. """ self.displaySurf.blit(self.background, ORIGIN) self.updateInputs() self.handleAI() self.updateEnemies() self.updateTurrets() self.updateHud() self.handleDragging() self.redrawAndProceedTick() self.updateState() def execute(self): """ (None) -> None Execute the Tower Defense game. """ # Play background music and enter the title screen self.backgroundMusic.play(-1) self.menu.drawTitleMenu(self.displaySurf) filename = self.menu.drawSelectLevelScreen(self.displaySurf) # Load the first level properties self.loadTowerLoc(filename) self.loadIntersections(filename) self.generateEnemies(5) # Blit the tower and paths onto the background Surface self.drawIntersections(self.intersectionSurface) self.background.blit(self.intersectionSurface, ORIGIN) self.tower.draw(self.background) # Play! while self.inPlay: self.update() self.menu.drawLosePanel (self.displaySurf) self.menu.drawCredits(self.displaySurf) pygame.quit() def getRect(self): """ (None) -> Rect Return a pygame Rect object defining the display surface boundaries. """ return self.displaySurf.get_rect() def canRun (self): if self.tower.health <= 0: self.terminate ()
def sell_tower(self, pos, tower): tile_pos = self.tile_coord(pos) for tower in self.game_towers: if tile_pos[0] == tower.tile_x and tile_pos[1] == tower.tile_y and Tower.get_status(tower): tower.deactivate() # deactivate tower self.money += tower.price # refund money