class Main: """Entry point for CoG.""" def __init__(self): """Constructor of Main class.""" pygame.init() self.clock = pygame.time.Clock() self.window = Menu() self.run() def run(self): """Runs CoG.""" running = True events = Events() while running: for event in events: self.window.pass_event(event) if event.level == "host": if event.type == pygame.KEYDOWN: if event.mod & pygame.KMOD_CTRL: if event.key == pygame.K_ESCAPE: running = False self.window.draw() pygame.display.update() self.clock.tick(60)
class Qi_base(Kingdom): def __init__(self): super().__init__() self.img = img self.name = "qi_base" self.x = 980 self.y = 318 self.tile = [[1100, 176], [1020, 210], [1060, 210], [1100, 210], [860, 244], [900, 244], [940, 244], [980, 244], [1020, 244], [1060, 244], [1100, 244], [860, 279], [900, 279], [940, 279], [980, 279], [1020, 279], [1060, 279], [1100, 279], [860, 313], [900, 313], [940, 313], [980, 313], [1020, 313], [1060, 313], [1100, 313], [860, 349], [900, 349], [940, 349], [980, 349], [1020, 349], [1060, 349], [1100, 349]] self.rgb = rgb(254, 234, 178) self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(warrior, "kingdom") self.menu.add_btn(boat, "kingdom") def draw(self, win): super().draw(win) if self.selected: self.menu.x = self.x self.menu.y = self.y self.menu.update() self.menu.draw(win)
class Wei_base(Kingdom): def __init__(self): super().__init__() self.img = img self.name = "wei_base" self.x = 660 self.y = 318 self.tile = [[460, 244], [500, 244], [540, 244], [580, 244], [620, 244], [660, 244], [700, 244], [460, 279], [500, 279], [540, 279], [580, 279], [620, 279], [660, 279], [700, 279], [500, 313], [540, 313], [580, 313], [620, 313], [660, 313], [700, 313], [500, 349], [540, 349], [580, 349], [620, 349], [660, 349], [700, 349], [500, 383], [540, 383], [580, 383], [620, 383], [660, 383], [500, 417], [540, 417], [580, 417], [620, 417], [660, 417]] self.rgb = rgb(254, 245, 134) self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(catapult, "kingdom") self.menu.add_btn(balista, "kingdom") def draw(self, win): super().draw(win) if self.selected: self.menu.x = self.x self.menu.y = self.y self.menu.update() self.menu.draw(win)
class Zao_base(Kingdom): def __init__(self): super().__init__() self.img = img self.name = "zao_base" self.x = 700 self.y = 145 self.tile = [[20, 40], [60, 40], [100, 40], [140, 40], [180, 40], [220, 40], [260, 40], [300, 40], [340, 40], [380, 40], [420, 40], [460, 40], [500, 40], [540, 40], [580, 40], [620, 40], [660, 40], [700, 40], [740, 40], [20, 74], [60, 74], [100, 74], [140, 74], [180, 74], [220, 74], [260, 74], [300, 74], [340, 74], [380, 74], [420, 74], [460, 74], [500, 74], [540, 74], [580, 74], [620, 74], [660, 74], [700, 74], [740, 74], [20, 108], [60, 108], [100, 108], [140, 108], [180, 108], [220, 108], [260, 108], [300, 108], [340, 108], [540, 108], [580, 108], [620, 108], [660, 108], [700, 108], [740, 108], [540, 142], [580, 142], [620, 142], [660, 142], [700, 142], [740, 142], [540, 176], [580, 176], [620, 176], [660, 176], [700, 176], [740, 176], [540, 210], [580, 210], [620, 210], [660, 210], [700, 210], [740, 210], [780, 210], [820, 210], [740, 244], [780, 244], [820, 244], [740, 279], [780, 279], [820, 279], [740, 313], [780, 313], [820, 313], [740, 349], [780, 349], [820, 349], [820, 383]] self.rgb = rgb(250, 160, 150) self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(warrior, "kingdom") self.menu.add_btn(riboku, "kingdom") def draw(self, win): super().draw(win) if self.selected: self.menu.x = self.x self.menu.y = self.y self.menu.update() self.menu.draw(win)
class Chu3_base(Kingdom): def __init__(self): super().__init__() self.img = img self.name = "chu3_base" self.x = 820 self.y = 564 self.tile = [[860,383],[900,383],[940,383],[980,383],[1020,383],[1060,383],[1100,383],[820,417],[860,417],[900,417],[940,417],[980,417],[1020,417],[1060,417],[1100,417],[500,453],[540,453],[580,453],[620,453],[660,453],[820,453],[860,453],[900,453],[940,453],[980,453],[1020,453],[1060,453],[1100,453],[500,489],[540,489],[580,489],[620,489],[660,489],[820,489],[860,489],[900,489],[940,489],[980,489],[1020,489],[1060,489],[1100,489],[140,523],[180,523],[220,523],[260,523],[300,523],[340,523],[380,523],[420,523],[460,523],[500,523],[540,523],[580,523],[620,523],[660,523],[780,523],[820,523],[860,523],[900,523],[940,523],[980,523],[1020,523],[1060,523],[1100,523],[20,559],[60,559],[100,559],[140,559],[180,559],[220,559],[260,559],[300,559],[340,559],[380,559],[420,559],[460,559],[500,559],[540,559],[580,559],[620,559],[660,559],[700,559],[740,559],[780,559],[820,559],[860,559],[900,559],[940,559],[980,559],[1020,559],[1060,559],[1100,559],[20,593],[60,593],[100,593],[140,593],[180,593],[220,593],[260,593],[300,593],[340,593],[380,593],[420,593],[460,593],[500,593],[540,593],[580,593],[620,593],[660,593],[700,593],[740,593],[780,593],[820,593],[860,593],[900,593],[940,593],[980,593],[1020,593],[1060,593],[1100,593],[20,627],[60,627],[100,627],[140,627],[180,627],[220,627],[260,627],[300,627],[340,627],[380,627],[420,627],[460,627],[500,627],[540,627],[580,627],[620,627],[660,627],[700,627],[740,627],[780,627],[820,627],[860,627],[900,627],[940,627],[980,627],[1020,627],[1060,627],[1100,627],[20,661],[60,661],[100,661],[140,661],[180,661],[220,661],[260,661],[300,661],[340,661],[380,661],[420,661],[460,661],[500,661],[540,661],[580,661],[620,661],[660,661],[700,661],[740,661],[780,661],[820,661],[860,661],[900,661],[940,661],[980,661],[1020,661],[1060,661],[1100,661]] self.rgb = rgb(176, 134, 105) self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(boat, "kingdom2") def draw(self, win): super().draw(win) if self.selected: self.menu.x = self.x self.menu.y = self.y self.menu.update() self.menu.draw(win)
class Han_base(Kingdom): def __init__(self): super().__init__() self.img = img self.name = "han_base" self.x = 740 self.y = 388 self.tile = [[700,383],[740,383],[780,383],[700,417],[740,417],[780,417],[700,453],[740,453],[780,453],[700,489],[740,489],[780,489],[700,523],[740,523]] self.rgb = rgb(253, 143, 66) self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(warrior, "kingdom2") def draw(self, win): super().draw(win) if self.selected: self.menu.x = self.x self.menu.y = self.y self.menu.update() self.menu.draw(win)
class Yan_base(Kingdom): def __init__(self): super().__init__() self.img = img self.name = "yan_base" self.x = 940 self.y = 111 self.tile = [[780,40],[820,40],[860,40],[900,40],[940,40],[980,40],[1020,40],[1060,40],[1100,40],[780,74],[820,74],[860,74],[900,74],[940,74],[980,74],[1020,74],[1060,74],[1100,74],[780,108],[820,108],[860,108],[900,108],[940,108],[980,108],[1020,108],[1060,108],[1100,108],[780,142],[820,142],[860,142],[900,142],[940,142],[980,142],[1020,142],[1060,142],[1100,142],[780,176],[820,176],[860,176],[900,176],[940,176],[980,176],[1020,176],[1060,176],[860,210],[900,210],[940,210],[980,210]] self.rgb = rgb(170, 250, 140) self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(warrior, "kingdom") self.menu.add_btn(boat, "kingdom") def draw(self, win): super().draw(win) if self.selected: self.menu.x = self.x self.menu.y = self.y self.menu.update() self.menu.draw(win)
class Tower: """ Abstract class for towers """ def __init__(self, x, y): self.x = x self.y = y self.width = self.height = 96 self.sell_price = [0,0,0] self.price = [0,0,0] self.level = 1 self.range = 200 self.original_range = self.range # Not sure if this should be in here self.selected = False # define menu and buttons self.menu = Menu(self.x, self.y, self, menu_bg, [2000, 5000, 9000, 12000, "MAX"]) self.menu.add_button(upgrade_button, "Upgrade") self.moving = False self.tower_imgs = [] self.damage = 1 self.place_color = (0,0,255, 100) def draw(self, win): """ draws the tower :param win: surface :return: None """ img = self.tower_imgs[self.level - 1] win.blit(img, (self.x-img.get_width()//2, self.y-img.get_height()//2)) # draw menu if self.selected: self.menu.draw(win) def draw_radius(self, win): # draw range circle if selected if self.selected: surface = pygame.Surface((self.range*2, self.range*2), pygame.SRCALPHA, 32) pygame.draw.circle(surface, (128, 128, 128, 100), (self.range, self.range), self.range, 0) win.blit(surface, (self.x - self.range, self.y - self.range)) def draw_placement(self, win): # draw range circle surface = pygame.Surface((self.range*2, self.range*2), pygame.SRCALPHA, 32) pygame.draw.circle(surface, self.place_color, (58, 58), 58, 0) # 58 = 96/2 + 10 win.blit(surface, (self.x - 58, self.y - 58)) def click(self, X, Y): """ returns if tower has been clicked on and select tower if it was clicked :param X: int :param Y: int :return: bool """ img = self.tower_imgs[self.level - 1] if X <= self.x - img.get_width()//2 + self.width and X >= self.x - img.get_width()//2: if Y <= self.y + self.height - img.get_height()//2 and Y >= self.y - img.get_height()//2: return True return False def sell(self): """ call to sell the tower, returns sel price :retutn: int """ return self.sell_price[self.level - 1] def upgrade(self): """ upgrades the tower for a given cost :return: None """ if self.level < len(self.tower_imgs): self.level += 1 self.damage += 1 def get_upgrade_cost(self): """ gets the upgrade cost :return: int """ return self.menu.get_item_cost() def move(self, x, y): """ moves tower to given x and y :param x: int :param y: int :return: None """ self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update() def collide(self, otherTower): x2 = otherTower.x y2 = otherTower.y dis = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) return True if dis <= 116 else False # width and height of the towers are equals to 96 and adding 10 from both sides = 116
class Tower: """ Abstract class for towers """ def __init__(self, x, y): self.x = x self.y = y self.width = 0 self.height = 0 self.sell_price = [0, 0, 0] self.price = [0, 0, 0] self.level = 1 self.selected = False # define menu and buttons self.menu = Menu(self, self.x, self.y, menu_bg, [2000, "MAX"]) self.menu.add_btn(upgrade_btn, "Upgrade") self.tower_imgs = [] self.damage = 1 self.place_color = (0, 0, 255, 100) def draw(self, win): """ draws the tower :param win: surface :return: None """ img = self.tower_imgs[self.level - 1] win.blit( img, (self.x - img.get_width() // 2, self.y - img.get_height() // 2)) # draw menu if self.selected: self.menu.draw(win) def draw_radius(self, win): if self.selected: # draw range circle surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) pygame.draw.circle(surface, (128, 128, 128, 100), (self.range, self.range), self.range, 0) win.blit(surface, (self.x - self.range, self.y - self.range)) def draw_placement(self, win): # draw range circle surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) pygame.draw.circle(surface, self.place_color, (50, 50), 50, 0) win.blit(surface, (self.x - 50, self.y - 50)) def click(self, X, Y): """ returns if tower has been clicked on and selects tower if it was clicked :param X: int :param Y: int :return: bool """ img = self.tower_imgs[self.level - 1] if X <= self.x - img.get_width( ) // 2 + self.width and X >= self.x - img.get_width() // 2: if Y <= self.y + self.height - img.get_height( ) // 2 and Y >= self.y - img.get_height() // 2: return True return False def sell(self): """ call to sell the tower, returns sell price :return: int """ return self.sell_price[self.level - 1] def upgrade(self): """ upgrades the tower for a given cost :return: None """ if self.level < len(self.tower_imgs): self.level += 1 self.damage += 1 def get_upgrade_cost(self): """ returns the upgrade cost, if 0 then can't upgrade anymore :return: int """ return self.price[self.level - 1] def move(self, x, y): """ moves tower to given x and y :param x: int :param y: int :return: None """ self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update() def collide(self, otherTower): x2 = otherTower.x y2 = otherTower.y dis = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) if dis >= 100: return False else: return True
class Tower(GameObjects): """ Base structural class for our towers @param (STR) name: name of object @param (TUPLE) coord: (x, y) coordinates of object """ def __init__(self, name, coord): super().__init__(name, coord) # Tower coordinates self.x = self.coord[0] self.y = self.coord[1] # Allows for upgrade references self.level = 1 # Upgrade Cost self.cost = TowerConstants.UPGRADE_COST[name] # Selling logistics self.original_price = TowerConstants.ORIGINAL_PRICE[name] self.sell_price = [self.original_price, self.cost[0], self.cost[1]] # Tower dimensions self.width = self.dimensions[0] self.height = self.dimensions[1] # Clicking on a tower self.selected = False # Tower images self.tower_images = [] # Specific range for each tower self.range = TowerConstants.TOWER_RADIUS_RANGE[name] # Leveling up animation self.level_up_animation = False self.level_animation = 0 self.level_up = level_up # Menu logistics self.menu = Menu(self, menu_background) self.menu.add_button("upgrade", upgrade_button) self.menu.add_button("sell", sell_button) # Damage for towers that deal damage self.base_damage = 0 self.damage = self.base_damage # For moving the archer tower when purchasing from the shops self.dragged = False # Padding for clicking purposes self.extra_padding = 10 # Keeps track of kill count self.kill_count = 0 self.font = game_font def draw(self, window): """ Draws the tower, menu, and level-up animation upon condition @param (SURFACE) window: surface for rendering the drawing --> return: None """ if self.selected: self.menu.draw(window) #Drawing menu window.blit(kill_count_table, (self.x + self.width // 2 - 15, self.y - self.height // 2 + 35)) kills = self.font.render( str(self.kill_count) + " Kills", 1, (255, 255, 255)) window.blit( kills, (self.x + self.width // 2 + 5, self.y - self.height // 2 + 43)) tower_image = self.tower_images[self.level - 1] if not self.level_up_animation: #Always draw the tower except when leveling up window.blit(tower_image, (self.x - tower_image.get_width() // 2, self.y - tower_image.get_height() // 2)) else: #Leveling up animation procedure window.blit(self.level_up[self.level_animation // 2], (self.x - tower_image.get_width() - 75, self.y - 225)) self.level_animation += 1 if self.level_animation == len(level_up) * 2: self.level_up_animation = False self.level_animation = 0 def click(self, X, Y): """ returns True if tower has been selected else False @param (INT) X: mouse position's x-coordinate @param (INT) Y: mouse position's y-coordinate --> return: Bool """ tower_image = self.tower_images[self.level - 1] if X <= self.x + tower_image.get_width( ) // 2 - 2 * self.extra_padding and X >= self.x - tower_image.get_width( ) // 2 + self.extra_padding // 2: if self.name in TowerConstants.MAGIC_TOWER_NAMES or self.name in TowerConstants.SUP_TOWER_NAMES: if Y <= self.y + self.height // 2 - ( 2 * self.extra_padding ) and Y >= self.y - self.height // 2 + (2 * self.extra_padding): return True else: if Y <= self.y + self.height // 2 - ( 4 * self.extra_padding ) and Y >= self.y - self.height // 2 + (2 * self.extra_padding): return True return False def get_sell_cost(self): """ Sells the tower at a specific level at a reduced cost using our self.sell_price list of prices --> return: Int """ return round(0.75 * self.sell_price[self.level - 1]) def upgrade(self): """ Upgrades our tower and increment certain tower characteristics --> return: None """ if self.level < len(self.tower_images): self.level_up_animation = True self.level += 1 self.base_damage += 3 self.damage = self.base_damage #Since level does not upgrade in menu we have to manually do it here self.menu.tower_level += 1 def get_upgrade_cost(self): """ Returns our upgrade cost for the next tower level --> return: Int """ return self.cost[self.level - 1] def move(self, X, Y): """ Moves our tower to the coordinate (x, y) and updates menu coordinates @param (INT) X: mouse position's x-coordinate @param (INT) Y: mouse position's y-coordinate --> return: None """ self.menu.x, self.menu.y = X, Y self.x, self.y = X, Y self.menu.update_buttons() def get_closest_distance_to_path(self, path): """ Gets the closest distance from a tower at any point to the path @param (LIST) path: list of tuples containing path coordinates --> return: Float """ min_distance_to_line = float("inf") for p in path: game_path = p[:] game_path.sort(key=lambda coord: calculate_distance(self, coord)) point_A = game_path[ 0] # Closest point out of all the points on the path to to the tower try: point_after_A = p[p.index(point_A) + 1] point_before_A = p[p.index(point_A) - 1] closest_to_A = min( point_after_A, point_before_A, key=lambda point: calculate_distance(point_A, point)) except: if p.index(point_A) == 0: closest_to_A = p[p.index(point_A) + 1] elif p.index(point_A) == len(p) - 1: closest_to_A = p[p.index(point_A) - 1] finally: if closest_to_A[0] != point_A[0]: m = (closest_to_A[1] - point_A[1]) / (closest_to_A[0] - point_A[0]) else: m = 2 b = point_A[1] - m * point_A[0] closest_distance = abs(-m * self.x + self.y - b) / math.sqrt((-m)**2 + 1) min_distance_to_line = min(closest_distance, min_distance_to_line) return min_distance_to_line
class Tower: def __init__(self, x, y): self.x = x self.y = y self.width = 0 self.height = 0 self.range = 0 self.price = [0, 0, 0] self.level = 1 self.selected = False # define menu and buttons self.menu = Menu(self, self.x, self.y, menu_bg, [2000, "MAX"]) self.menu.add_btn(upgrade_btn, "Upgrade") self.imgs = [] self.damage = 1 self.place_color = (0, 0, 255, 100) def draw(self, win): # TODO: dodaj wiecej spritow zeby pokazac ulepszanie wiez, ustawione normalnie na self.level - 1 img = self.imgs[0] win.blit(img, (self.x - img.get_width() / 2, self.y - img.get_height() / 2)) # draw menu if self.selected: self.menu.draw(win) def draw_radius(self, win): if self.selected: # draw range circle circle_surface = pygame.Surface((self.range * 2, self.range * 2), pygame.SRCALPHA, 32) pygame.draw.circle(circle_surface, (128, 128, 128, 100), (self.range, self.range), self.range, 0) win.blit(circle_surface, (self.x - self.range, self.y - self.range)) def draw_placement(self, win): # draw range circle surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) pygame.draw.circle(surface, self.place_color, (50, 50), 50, 0) win.blit(surface, (self.x - 50, self.y - 50)) def click(self, X, Y): """Returns if tower has been clicked on and selects tower if it was clicked""" # tu zmienione również z self.level - 1 na 0 z powodu brakow spritow img = self.imgs[0] if X <= self.x - img.get_width( ) // 2 + self.width and X >= self.x - img.get_width() // 2: if Y <= self.y + self.height - img.get_height( ) // 2 and Y >= self.y - img.get_height() // 2: return True return False def upgrade(self): """Upgrades towers to higher tier at given cost""" # instead of next sprites is only block by number if self.level < len(self.price): self.level += 1 self.damage += 1 return True else: return False def get_upgrade_cost(self): return self.price[self.level - 1] def move(self, x, y): """ moves tower to given x and y :param x: int :param y: int :return: None """ self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update() def collide(self, otherTower): x2 = otherTower.x y2 = otherTower.y dis = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) if dis >= 100: return False else: return True
class Tower(PositionalObject, ILocation, IUpgradable): """ Abstract class for towers """ def __init__(self, x, y): super().__init__() self.x = x self.y = y self.width = 0 self.height = 0 self.price = 0 self.level = 1 self.range = 0 self.selected = False self.is_collide = False # define menu and buttons self.menu = Menu(self, self.x, self.y, menu_background, [2000, "Max"]) self.menu.add_btn(button_background, "Upgrade") self.tower_imgs = [] self.damage = 1 self.sell_price = [] self.place_color = (0, 255, 0, 100) def get_position(self): return self.x, self.y def draw(self, win): """ Draws the tower :param win: surface :return: None """ img = self.tower_imgs[self.level - 1] win.blit( img, (self.x - img.get_width() // 2, self.y - img.get_height() // 2)) # draw menu if self.selected: self.menu.draw(win) def draw_radius(self, win): if self.selected: # Draw range circle surface = pygame.Surface((self.range * 2, self.range * 2), pygame.SRCALPHA, 32) pygame.draw.circle(surface, (128, 128, 128, 100), (self.range, self.range), self.range, 0) win.blit(surface, (self.x - self.range, self.y - self.range)) def draw_placement(self, win): surface = pygame.Surface((self.range * 2, self.range * 2), pygame.SRCALPHA, 32) pygame.draw.circle(surface, self.place_color, (45, 45), 45, 0) win.blit(surface, (self.x - 45, self.y - 45)) def click(self, x, y): """ Returns if tower has been clicked on and selects tower if it was clicked :param x: int :param y: int :return: bool """ img = self.tower_imgs[self.level - 1] if self.x - img.get_width( ) // 2 <= x <= self.x + self.width - img.get_width() // 2: if self.y - img.get_height( ) // 2 <= y <= self.y + self.height - img.get_height() // 2: return True return False def sell(self): """ Call to sell the tower, returns sell cost :return: int """ return self.sell_price[self.level - 1] def get_upgrade_cost(self): """ Return the upgrade cost, if 0 then can't upgrade anymore :return: """ return self.price def upgrade(self): """ Upgrades the tower for given cost :return: None """ if self.level < len(self.tower_imgs): self.level += 1 self.damage += 1 def move(self, x, y): """ Moves tower to given x and y position :param x: int :param y: int :return: None """ self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update() def collide(self, other_tower): x2 = other_tower.x y2 = other_tower.y dis = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) if dis >= 90: return False else: return True
class Tower: ''' abstract class for towers ''' def __init__(self, x, y): self.x = x self.y = y self.width = 0 self.height = 0 self.level = 1 self.sell_cost = [0, 0, 0] self.price = [5000, 7000, 12000, 'MAX'] self.selected = False self.item_cost = [5000, 7000, 12000, 'MAX'] self.menu = Menu(self, self.x, self.y, menu_bg, self.item_cost) self.tower_imgs = tower_imgs1[:] self.damage = 1 self.range = 0 self.inRange = 0 self.left = 1 self.menu.add_button(upgrade_button, 'upgrade_button', 0) self.place_color = (36, 120, 132, 100) self.effected = True def draw(self, win): imgs = self.tower_imgs[self.level - 1] win.blit(imgs, (self.x - imgs.get_width()//2, self.y - imgs.get_height()//2)) def draw_menu(self, win): # draw menu if self.selected: self.menu.draw(win) pass def draw_radius(self, win): # draw range circle if self.selected: # print(self.range*4, self.range*4) circle_surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) # circle_surface.set_alpha(128) # circle_surface.fill(0,255,0)) pygame.draw.circle(circle_surface, (44, 195, 206, 20), (self.range, self.range), self.range, 0) win.blit(circle_surface, (self.x - self.range, self.y - self.range)) # pygame.draw.circle(win, (255, 0, 0), (self.x, self.y), 200, 3) def draw_placement(self, win): # draw range circle circle_surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) pygame.draw.circle(circle_surface, self.place_color, (50, 50), 45, 0) win.blit(circle_surface, (self.x - 50, self.y - 50)) # print('draw placement range') def draw_shadow(self, win): circle_surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) pygame.draw.circle(circle_surface, (0, 0, 0, 50), (50, 50), 50) win.blit(circle_surface, (self.x - 50, self.y - 45)) def click(self, X, Y): ''' return true if tower be clicked, else false :param x: int :param y: int :return: bool ''' img = self.tower_imgs[self.level-1] if X <= self.x - img.get_width() // 2 + 120 and X >= self.x - img.get_width() // 2: if Y <= self.y + 120 - img.get_height() // 2 and Y >= self.y - img.get_height() // 2: return True return False pass def sell(self): ''' call to sell the tower, returns sell price :return: int ''' pass def upgrade(self): ''' upgrade the tower by cost :return: ''' if self.level <= 2: self.level += 1 self.damage += self.damage * 0.5 self.range += self.range * 0.25 self.effected = True pass def get_upgrade_cost(self): return self.price[self.level - 1] def move(self, x, y): ''' moves tower to given x and y :param x: int :param y: int :return: ''' self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update() def collide(self, otherTower): x2 = otherTower.x y2 = otherTower.y dis = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) if dis >= 100: return False else: return True def occupyTheRoad(self): ''' for each two node points in path judge whether the position where tower to be constructed is in a range of t that might occupy the road for monsters :param self: tower object :param path: path node list :param t: range that a tower cant be constructed this amount away from the path of monsters :return: true or false ''' t = 50 for nodeIndex in range(len(path) - 1): x1 = path[nodeIndex][0] y1 = path[nodeIndex][1] x2 = path[nodeIndex + 1][0] y2 = path[nodeIndex + 1][1] # the line where the segment from is Ax+By+C=0 # B=1 A = -((y2 - y1) / (x2 - x1)) C = x1 * ((y2 - y1) / (x2 - x1)) - y1 disToSegment = abs(A * self.x + self.y + C) / math.sqrt(A ** 2 + 1) disToNodePoint1 = math.sqrt((self.x - x1) ** 2 + (self.y - y1) ** 2) disToNodePoint2 = math.sqrt((self.x-x2) ** 2 + (self.y - y2) ** 2) maxDis_NotToIgnore = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2 + t ** 2) if disToSegment < t and disToNodePoint1 <= maxDis_NotToIgnore and disToNodePoint2 <= maxDis_NotToIgnore: return True return False
class Tower: """ Abstract class for towers """ def __init__(self, x, y): self.x = x self.y = y self.width = 0 self.height = 0 self.sell_price = [0, 0, 0] self.price = [100, 300, 9999] self.level = 1 self.selected = False self.menu = Menu(self, self.x, self.y, menu_bg, self.price) self.menu.add_btn(upgrade_btn, "Upgrade") self.menu.add_btn(sell_btn, "Sell") self.base_imgs = [] self.animation_imgs = [] self.damage = 1 self.speed = 4 def draw(self, win): """ draws the tower :param win: surface :return: None """ img = self.base_imgs[self.level - 1] # find the closest tile self.x = min(tile_x, key=lambda x: abs(x - self.x)) self.y = min(tile_y, key=lambda y: abs(y - self.y)) tile_key = (self.x, self.y) if self.name == "fortress": if dict_tile_fortress[tile_key] == 0: win.blit(img, (self.x - img.get_width() // 2, self.y - img.get_height() // 2)) else: if dict_tile[tile_key] == 0: win.blit(img, (self.x - img.get_width() // 2, self.y - img.get_height() // 2)) # draw menu if self.selected: self.menu.draw(win) def draw_radius(self, win): if self.selected: # draw range circle size = (self.range * 2, self.range * 2) radius = self.range surface = pygame.Surface(size, pygame.SRCALPHA, 32) pygame.draw.circle(surface, rgb(204, 255, 255), (radius, radius), radius, 0) win.blit(surface, (self.x - radius, self.y - radius)) def draw_rectangle(self, win): if self.selected: # draw range rectangle surface = pygame.Surface((self.range * 4, self.range * 4), pygame.SRCALPHA, 32) pygame.draw.rect(surface, rgb(204, 255, 255), (self.range * 2, self.range * 2, self.range * 2, self.range * 1.8), 0) win.blit(surface, (self.x - 3 * self.range, self.y - 2.6 * self.range)) def click(self, X, Y): """ returns if tower has been clicked on and selects tower if it was clicked :param X: int :param Y: int :return: bool """ img = self.base_imgs[self.level - 1] if X <= self.x - img.get_width( ) // 2 + self.width and X >= self.x - img.get_width() // 2: if Y <= self.y + self.height - img.get_height( ) // 2 and Y >= self.y - img.get_height() // 2: return True return False def sell(self): """ call to sell the tower, returns sell price :return: int """ return self.sell_price[self.level - 1] def upgrade(self): """ upgrades the tower for a given cost :return: None """ if self.name == "fortress": if self.level < len(self.animation_imgs): self.level += 1 self.max_health += self.max_health self.health += self.health elif self.name == "ouhon": if self.level < len(self.base_imgs): self.level += 1 self.freeze_power += 0.5 else: if self.level < len(self.base_imgs): self.level += 1 self.damage += 1 def get_upgrade_cost(self): """ returns the upgrade cost, if 0 then can't upgrade anymore :return: int """ return self.price[self.level - 1] def move(self, x, y): """ moves tower to given x and y :param x: int :param y: int :return: None """ self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update() def collide(self, otherTower): x2 = otherTower.x y2 = otherTower.y # find closest tile x2 = min( tile_x, key=lambda x: abs(x - x2) ) # set x2 at the x coordinate of tyle_x which has the minimum distance from x2 y2 = min( tile_y, key=lambda y: abs(y - y2) ) # set y2 the y coordinate of tyle_y which has the minimum distance from y2 tile_key = (x2, y2) # distance between the object and the closest tile dis = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) # check if first tower of the game collides with forbidden tile if self == otherTower: if self.name == "fortress": # tile is available if dict_tile_fortress[tile_key] == 0: return False # collide == False # tile is not available (collision with outside path) else: return True # collide == True else: # tile is available if dict_tile[tile_key] == 0: return False # collide == False # tile is not available (collision with path) else: return True # collide == True # check if moving object collides with towers, fortress or forbidden tile else: if self.name == "fortress": # tile is possibly available if dict_tile_fortress[tile_key] == 0: # when not already occupied by another fortress if dis >= 10: return False # collide == False # tile is already occupied by another fortress else: return True # collide == True # tile is not available (collision with outside path) else: return True # collide == True else: # tile is possibly available if dict_tile[tile_key] == 0: # when not already occupied by another object if dis >= 10: return False # collide == False # tile is already occupied by another object else: return True # collide == True # tile is not available (collision with path) else: return True # collide == True
class Tower: def __init__(self, x, y): # For visuals: self.tower_imgs = [] self.x = x self.y = y self.width, self.height = (settings.tower_width, settings.tower_height) # Attributes: self.cost = 0 self.type = "" self.upgrade_cost = [2000, 5000, "MAX"] self.sell_cost = [2000, 5000, 12000] self.level = 1 self.range = 150 self.curr_range = self.range self.in_range = False # For interactions: self.selected = False self.moving = False # Define menu self.menu = Menu(self.x - 100, self.y, self) self.menu.add_item(loader.upgrade_img, "upgrade") def draw(self, screen, paused): """ draws the tower according to state(moving/placed) :param screen: Surface :return: None """ if self.moving: self._draw_moving(screen) return # draw range circle: if self.selected: circle = pygame.Surface((self.curr_range * 2, self.curr_range * 2), pygame.SRCALPHA, 32) pygame.draw.circle(circle, (128, 128, 128, 100), (self.curr_range, self.curr_range), self.curr_range, 0) screen.blit(circle, (self.x - self.curr_range, self.y - self.curr_range)) # Draw tower: img = self.tower_imgs[self.level - 1] screen.blit(img, (self.x - self.width // 2, self.y - self.height // 2)) # Draw menu: if self.selected: self.menu.draw(screen) def draw_placement(self, screen): # draw range circle surface = pygame.Surface((self.height * 2, self.height * 2), pygame.SRCALPHA, 32) pygame.draw.circle(surface, (200, 0, 0, 100), (self.height, self.height), self.height - 30, 0) screen.blit(surface, (self.x - self.height, self.y - self.height)) def click(self, x, y): """ Returns if tower has been clicked and selects tower. :param x: :param y: :return: bool """ if (self.width // 2 + self.x) >= x >= (self.x - self.width // 2) \ and (self.height // 2 + self.y) >= y >= (self.y - self.height // 2): self.selected = True return True self.selected = False return False def sell(self): """ call to sell tower :return: int """ pass def upgrade(self, money): """ upgrade tower for defined cost and return if successful :return: price """ if self.level < len(self.upgrade_cost): price = self.upgrade_cost[self.level - 1] if money >= price: self.level += 1 return price return 0 def move(self, x, y): """ Allows to move tower :param x: :param y: :return: """ self.x = x self.y = y self.menu.update(x, y) def _check_inrange(self, x, y): """ Checks if postion is in range of tower and updates :param x: int :param y: int :return: None """ dis = math.dist((self.x, self.y), (x, y)) if dis <= self.curr_range: return dis return 0 def _draw_moving(self, screen): # draw range circle: circle = pygame.Surface((self.curr_range * 2, self.curr_range * 2), pygame.SRCALPHA, 32) pygame.draw.circle(circle, (0, 128, 128, 100), (self.curr_range, self.curr_range), self.curr_range, 0) screen.blit(circle, (self.x - self.curr_range, self.y - self.curr_range)) # Draw tower: img = self.tower_imgs[self.level - 1] screen.blit(img, (self.x - self.width // 2, self.y - self.height // 2)) def has_collided(self, other): """ returns true if tower is on another. :param other: Tower :return: bool """ x2 = other.x y2 = other.y dist = math.sqrt((x2 - self.x)**2 + (y2 - self.y)**2) if dist >= self.height - 30: return False else: return True
class Tower: """ Klasa abstrakcyjna dla wież """ def __init__(self,x,y): self.x = x self.y = y self.width = 0 self.height = 0 self.sell_price = [0,0,0] self.price = [0,0,0] self.level = 1 self.selected = False #definiuje menu i przyciski self.menu = Menu(self, self.x, self.y, menu_bg, [2000, "MAX"]) self.menu.add_btn(upgrade_btn, "Upgrade") self.tower_imgs = [] self.damage = 1 def draw(self, win): """ Rysowanie wieży :param win: surface :return: None """ img = self.tower_imgs[self.level - 1] win.blit (img, (self.x-img.get_width()//2, self.y-img.get_height()//2)) #rysowanie menu if self.selected: self.menu.draw(win) def draw_radius(self, win): if self.selected: # rysowanie okręgu zasięgu surface = pygame.Surface((self.range*4, self.range*4), pygame.SRCALPHA, 32) pygame.draw.circle(surface, (128,128,128, 100), (self.range,self.range), self.range, 0) win.blit(surface, (self.x - self.range, self.y - self.range)) def click(self, X, Y): """ Zwraca gdy kliknięto na wieżę i zaznacza wieżę gdy jest kliknięta :param x: int :param y: int :return: bool """ img = self.tower_imgs[self.level - 1] if X <= self.x -img.get_width()//2 + self.width and X >= self.x - img.get_width()//2: if Y <= self.y + self.height -img.get_height()//2 and Y >= self.y - img.get_height()//2: return True return False def sell(self): """ wezwanie do sprzedazy wiezy, zwraca koszt sprzedaży :return:int """ return self.sell_price[self.level-1] def upgrade(self): """ ulepsza wieżę za określony koszt :return: None """ if self.level + 1 < len(self.tower_imgs): self.level += 1 self.damage += 1 def get_upgrade_cost(self): """ zwraca koszt ulepszenia, jeśli 0, to nie może ulepszać :return: int """ return self.price[self.level-1] def move(self, x, y): """ Przesuwa wieze do podanego x i y :param x: int :param y: int :return: None """ self.x = x self.y = y self.menu.x = x self.menu.y = y self.menu.update()