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 __init__(self, method, pos, color=rgb(143, 8, 8)): pygame.sprite.Sprite.__init__(self) self.digital_font = pygame.font.Font( "game_assets/fonts/SF Atarian System.ttf", 22) self.font_color = color self.meth = method self.pos = pos
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 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 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 __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 __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 __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_health_bar(self, win): """ draw health bar above enemy :param win: surface :return: None """ length = 30 health_bar = length * (1 - ( (self.max_health - self.health) / self.max_health)) if self.name == "zao_riboku": add_y = -10 else: add_y = 0 pygame.draw.rect(win, rgb(255, 26, 26), (self.x - 13, self.y - 55 + add_y, length, 5), 0) # attacked rectangle pygame.draw.rect(win, rgb(102, 255, 51), (self.x - 13, self.y - 55 + add_y, health_bar, 5), 0) # health rectangle pygame.draw.rect(win, rgb(77, 77, 77), (self.x - 13, self.y - 55 + add_y, health_bar, 5), 1) # rectangle border
def __init__(self): super().__init__() self.img = img self.name = "quin_base" self.x = 22 self.y = 319 self.tile = [[380, 108], [420, 108], [460, 108], [500, 108], [20, 142], [60, 142], [100, 142], [140, 142], [180, 142], [220, 142], [260, 142], [300, 142], [340, 142], [380, 142], [420, 142], [460, 142], [500, 142], [20, 176], [60, 176], [100, 176], [140, 176], [180, 176], [220, 176], [260, 176], [300, 176], [340, 176], [380, 176], [420, 176], [460, 176], [500, 176], [20, 210], [60, 210], [100, 210], [140, 210], [180, 210], [220, 210], [260, 210], [300, 210], [340, 210], [380, 210], [420, 210], [460, 210], [500, 210], [20, 244], [60, 244], [100, 244], [140, 244], [180, 244], [220, 244], [260, 244], [300, 244], [340, 244], [380, 244], [420, 244], [20, 279], [60, 279], [100, 279], [140, 279], [180, 279], [220, 279], [260, 279], [300, 279], [340, 279], [380, 279], [420, 279], [20, 313], [60, 313], [100, 313], [140, 313], [180, 313], [220, 313], [260, 313], [300, 313], [340, 313], [380, 313], [420, 313], [460, 313], [20, 349], [60, 349], [100, 349], [140, 349], [180, 349], [220, 349], [260, 349], [300, 349], [340, 349], [380, 349], [420, 349], [460, 349], [20, 383], [60, 383], [100, 383], [140, 383], [180, 383], [220, 383], [260, 383], [300, 383], [340, 383], [380, 383], [420, 383], [460, 383], [20, 417], [60, 417], [100, 417], [140, 417], [180, 417], [220, 417], [260, 417], [300, 417], [340, 417], [380, 417], [420, 417], [460, 417], [20, 453], [60, 453], [100, 453], [140, 453], [180, 453], [220, 453], [260, 453], [300, 453], [340, 453], [380, 453], [420, 453], [460, 453], [20, 489], [60, 489], [100, 489], [140, 489], [180, 489], [220, 489], [260, 489], [300, 489], [340, 489], [380, 489], [420, 489], [460, 489], [20, 523], [60, 523], [100, 523]] self.rgb = rgb(150, 240, 250) self.sound = "quin.wav"
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): """ draws btns and menu bg :param win: surface :return: None """ add_blink = 6 if self.blink: win.blit(self.bg, (self.x - self.bg.get_width() / 2 - 8, self.y - 10 + add_blink)) else: win.blit(self.bg, (self.x - self.bg.get_width() / 2 - 8, self.y - 10)) for item in self.buttons: item.draw(win) text = self.font.render("$ " + str(item.cost), 1, rgb(255, 255, 255)) win.blit(text, (item.x + item.width / 2 - text.get_width() / 2, item.y + item.height + 1))
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 start_game(): # Assign the Display Variables background1 = pygame.image.load(BACKGROUND_IMAGE_NAME1) background2 = pygame.image.load(BACKGROUND_IMAGE_NAME2) background3 = pygame.image.load(BACKGROUND_IMAGE_NAME3) arrow_yellow = pygame.image.load(ARROW_YELLOW) arrow_white = pygame.image.load(ARROW_WHITE) gif_l = split_animated_gif(COINS_GIF) arrow_l = [ 20, 58, 97, 136, 175, 215, 255, 293, 333, 373, 411, 449, 489, 529, 569, 606 ] arrow_pos = -1 pushed = False coin_gif = False # Init Money and Jakpot STARTING_MONEY = 100 JACKPOT_INIT = 1000 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption(GAME_TITLE) # Create the slot machine object and hashes to be used by the game slot_machine = SlotMachine(JACKPOT_INIT, STARTING_MONEY) spin_results = slot_machine.results icon_images = [] # The current icon images or spin result icons # Create the text labels y_txt = 424 y_msg = 140 digital_fonts_hash = [ { "method": slot_machine.get_bet, "pos": (265, y_txt + pad_y) }, { "method": slot_machine.get_current_cash, "pos": (83, y_txt + pad_y) }, { "method": slot_machine.get_current_jackpot, "pos": (438, y_txt + pad_y) }, ] digital_fonts = pygame.sprite.Group() current_message_digifont = DigitalFont(slot_machine.get_current_message, (100, y_msg + pad_y), rgb(0, 0, 0)) for digital_font in digital_fonts_hash: digital_fonts.add( DigitalFont(digital_font["method"], digital_font["pos"])) # Set the constants BUTTON_BOTTOM_POS = background1.get_height() + pad_y - 165 # Create the bet buttons bet_buttons_hash = [{ "image_file_name": "ten_button.png", "bet_value": 10, "pos": (70, BUTTON_BOTTOM_POS) }, { "image_file_name": "twenty_button.png", "bet_value": 20, "pos": (140, BUTTON_BOTTOM_POS) }, { "image_file_name": "fifty_button.png", "bet_value": 50, "pos": (490, BUTTON_BOTTOM_POS) }, { "image_file_name": "hundred_button.png", "bet_value": 100, "pos": (560, BUTTON_BOTTOM_POS) }] bet_buttons = pygame.sprite.Group() for bet_button in bet_buttons_hash: bet_buttons.add( SlotMachineBetButton(bet_button["image_file_name"], bet_button["bet_value"], bet_button["pos"])) # Create the action buttons pad_btn = 30 spin_button = SlotMachineActionButton("spin_button.png", slot_machine.spin, (270, BUTTON_BOTTOM_POS)) spin_psh_button = SlotMachineActionButton("spin_psh2_button.png", slot_machine.spin, (270, BUTTON_BOTTOM_POS)) reset_button = SlotMachineActionButton("reset_button.png", slot_machine.reset, (210, BUTTON_BOTTOM_POS + pad_btn)) quit_button = SlotMachineActionButton("quit_button.png", slot_machine.reset, (422, BUTTON_BOTTOM_POS + pad_btn)) action_buttons = pygame.sprite.Group(spin_button, reset_button, quit_button) # Create all the symbols/icons to be shown in the reels all_symbols = pygame.sprite.Group() icons = slot_machine.icons for icon in icons: all_symbols.add(icon) # Set the game clock clock = pygame.time.Clock() # The reel positions is saved as an array with tuples y_reel = 258 reel_positions = [(78, y_reel + pad_y), (260, y_reel + pad_y), (438, y_reel + pad_y)] # Add the spin result symbols to icon images for symbol in all_symbols: for symbol_name in spin_results: if (symbol.name == symbol_name): icon_images.append(symbol) # Set the variables to be used by the game loop start_time = 0 spinning = False # Set the previous spin results prev_results = slot_machine.results #Play the bg music pygame.mixer.music.load("game_assets/sounds/slot/background_msc.mp3") pygame.mixer.music.play(-1) # Set the current slot machine values as previous values prev_bet, prev_jackpot, prev_current_msg, prev_cash = slot_machine.bet, slot_machine.current_jackpot, slot_machine.current_message, slot_machine.current_cash # Create functions used to get the previous slot machine values def prev_get_bet(): return prev_bet def prev_get_current_cash(): return prev_cash def prev_get_current_jackpot(): return prev_jackpot def prev_get_current_msg(): return prev_current_msg def get_case(): # Init every time get_case is called fail = False cash = False win = False x = 0 # build the case dictionnary, associate it to the symbole li = [symbol.name for symbol in all_symbols] d = {x: slot_machine.results.count(x) for x in slot_machine.results} max_key = max(d, key=d.get) for i, elem in enumerate(li): if elem == max_key: x = i # three unique items if len(d) == 3: if "Ryo" in d: pos = 13 cash = True else: if "Riboku" not in d: pos = 1 else: pos = 0 fail = True # one pair elif len(d) == 2: if "Ryo" in d: pos = 14 win = True else: if x > 0: pos = x * 2 - 1 cash = True else: pos = 0 fail = True # one trio elif len(d) == 1: if "Riboku" not in d: win = True else: fail = True if "Ryo" in d: pos = 15 else: pos = x * 2 return pos, fail, cash, win # Set the text values as the previous values # The reason this is done is to not let the user see how much he won until the spin animation is done prev_bet_digifont = DigitalFont(prev_get_bet, (265, y_txt + pad_y)) prev_cash_digifont = DigitalFont(prev_get_current_cash, (83, y_txt + pad_y)) prev_jackpot_digifont = DigitalFont(prev_get_current_jackpot, (438, y_txt + pad_y)) prev_message_digifont = DigitalFont(prev_get_current_msg, (100, y_msg + pad_y), rgb(0, 0, 0)) # Create the sprite group digifonts # The prev digifonts are the ones to be shown to the user while the spin animation is still running. prev_digifonts = pygame.sprite.Group(prev_bet_digifont, prev_jackpot_digifont, prev_cash_digifont, prev_message_digifont) # Continue looping while the player hasn't ended the game continue_playing = True currentFrame = 0 while (continue_playing): # Tick clock.tick(FRAME_RATE) # Check for events for event in pygame.event.get(): # Stop the loop when the user chooses to quit the game if (event.type == pygame.QUIT): continue_playing = False # When the user pushes the mouse button down, Check which sprites are involved elif (event.type == pygame.MOUSEBUTTONDOWN): # Check if a bet button is clicked then set the bet value to the value of that button for bet_button in bet_buttons: if (bet_button.rect.collidepoint(event.pos)): slot_machine.set_bet(bet_button.bet_value) # Check if spin button is clicked if (spin_button.rect.collidepoint(event.pos)): # Make sure you cant click the spin button while the reels are spinning if not spinning: # Execute the function inside the spin button. It would be slot_machine.spin() spin_button.execute_func() # If the message in the slot machine says the user cannot spin the reels, nothing happens. But if it is not then do the spin and set the spin results in the icon images if slot_machine.current_message != SlotMachine.CANNOT_SPIN: spin_results = slot_machine.results # Set the result's icon into icon_images icon_images = [] for symbol in all_symbols: for symbol_name in spin_results: if (symbol.name == symbol_name): icon_images.append(symbol) # booleans to set the arrow position corresponding to the result case and draw gif pushed = True coin_gif = False # Set the start time to current time. Making the spin animation run start_time = time.time() # Set spinning to true to make sure the user can't click spin again while spinning spinning = True else: slot_machine.bet_no_cash_snd.play() # If it is the reset button, call the function associated with the button and play the reset sound elif (reset_button.rect.collidepoint(event.pos)): slot_machine.reset_snd.play() reset_button.execute_func() # If the quit button is clicked, stop the loop elif (quit_button.rect.collidepoint(event.pos)): continue_playing = False # Display the sprites # Display the background images pad_left = -5 screen.blit(background2, (0, 0)) # casino background screen.blit(background3, (WIDTH - background3.get_width() + 2 * pad_left, 0)) # payoff table screen.blit(background1, (0, HEIGHT / 2 - background1.get_height() / 2)) # machine slot image # Update the action buttons and position them on the screen action_buttons.update() for action_button in action_buttons: screen.blit(action_button.image, action_button.pos) # Update the texts digital_fonts.update() # Update the bet buttons and position them on the screen bet_buttons.update() for bet_button in bet_buttons: screen.blit(bet_button.image, bet_button.pos) # This section is the one responsible for the reel animation # While the current time - the time the spin button is clicked is less than one # Change the images in the reel and show the previous/current texts if time.time() - start_time < 1 and spinning: # display the spin pushed button on top screen.blit(spin_psh_button.image, spin_psh_button.pos) # Display the current icons in the reel so it does not change until the pulling the lever sound is finished for i in range(3): screen.blit(prev_results[i].image, reel_positions[i]) # Display the current texts for digital_font in prev_digifonts: screen.blit(digital_font.get_rendered_surface(), digital_font.pos) elif time.time() - start_time < 2 and spinning: # Display a random icon in each reel and play the spinning sound for i in range(3): screen.blit(icons[random.randint(0, len(icons) - 1)].image, reel_positions[i]) slot_machine.spinning_snd.play() # Display the current texts for digital_font in prev_digifonts: screen.blit(digital_font.get_rendered_surface(), digital_font.pos) # Display the arrow indicator rolling if arrow_pos >= len(arrow_l) - 1: arrow_pos = 0 arrow_pos += 1 x = WIDTH - background3.get_width( ) + 3 * pad_left - arrow_white.get_width() y = 12 y += arrow_l[arrow_pos] screen.blit(arrow_white, (x, y)) else: # set the arrow position corresponding to the result case if pushed: arrow_pos, fail, cash, win = get_case() pushed = False # The animation is done and display the resulted values for i in range(3): screen.blit(icon_images[i].image, reel_positions[i]) screen.blit(current_message_digifont.get_rendered_surface(), current_message_digifont.pos) # Spinning is now false. The user can hit spin again spinning = False # play jackpot or failure sounds if arrow_pos != -1: # except initial images if fail: play_sound(0, "slot/fail_snd.wav") fail = False elif cash: play_sound(0, "slot/cash_snd.wav") cash = False coin_gif = True elif win: play_sound(0, "slot/jackpot.wav") win = False coin_gif = True # Set the prev results to the current images to be used again on animation prev_results = icon_images # Stop the spinning sound if playing slot_machine.spinning_snd.stop() # Render the current texts in the screen for digital_font in digital_fonts: screen.blit(digital_font.get_rendered_surface(), digital_font.pos) # Display arrow indicator, moves to the corresponding position x = WIDTH - background3.get_width( ) + 3 * pad_left - arrow_yellow.get_width() y = 12 y += arrow_l[arrow_pos] screen.blit(arrow_yellow, (x, y)) if coin_gif: screen.blit(gif_l[currentFrame], (x - 250, 0)) screen.blit(gif_l[currentFrame], (x - 250, 300)) currentFrame = (currentFrame + 1) % len(gif_l) # Reset the prev values prev_bet, prev_jackpot, prev_current_msg, prev_cash = slot_machine.bet, slot_machine.current_jackpot, slot_machine.current_message, slot_machine.current_cash # Refresh the display pygame.display.flip() money_diff = slot_machine.current_cash - STARTING_MONEY return money_diff
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 draw(self): # draw background and text self.win.blit(self.bg, (0, 0)) text = self.font.render(self.game_level, 2, rgb(255, 255, 255)) self.win.blit(text, (self.width / 2 - text.get_width() / 2, self.height - 10 - text.get_height())) # draw mini-game button self.win.blit(casino_btn, (self.slot[0], self.slot[1])) # draw Start, Lore, Info, Level buttons self.win.blit(start_btn, (self.btn[0], self.btn[1])) self.win.blit(lore_btn, (self.lore[0], self.lore[1])) self.win.blit(info_btn, (self.info[0], self.info[1])) if self.game_level == "Easy": level_btn = pygame.image.load( os.path.join("game_assets/menu/", "level1_btn.png")) elif self.game_level == "Medium": level_btn = pygame.image.load( os.path.join("game_assets/menu/", "level2_btn.png")) elif self.game_level == "Hard": level_btn = pygame.image.load( os.path.join("game_assets/menu/", "level3_btn.png")) self.win.blit(level_btn, (self.level[0], self.level[1])) # draw lore imgs if self.shows["lore"]: # right img x = self.lore[0] + pad_x y = self.lore[1] self.win.blit(lore_img, (x, y)) # left img x = self.lore[0] - pad_x - lore2_img.get_width( ) + lore_btn.get_width() y = self.lore[1] self.win.blit(lore2_img, (x, y)) # draw character infos, attack Towers (left), support Towers (right) if self.shows["info"] and not self.shows['img']: for button, img in zip(self.character_infos, self.info_imgs): self.win.blit(img, (button[0], button[1])) # draw characters corr = 0 for name, img in zip(self.img_names, self.character_imgs): if self.shows[name]: x = img[1][0] y = img[1][1] self.win.blit(img[0], (x, y)) if self.right: corr = img[0].get_width() + 10 size = (900, 50) text = img[2] x = img[3][0] + corr y = img[3][1] self.blit_text(size, text, (x, y), self.font_20, rgb(255, 255, 255)) for i, (button, info) in enumerate( zip(self.character_infos, self.info_imgs)): if self.left: if i >= 4: pass else: self.win.blit(info, (button[0], button[1])) if self.right: if i < 4: pass else: self.win.blit(info, (button[0], button[1])) # draw level buttons if self.shows["level"]: x = self.easy[0] y = self.easy[1] add_y = easy_btn.get_height() + pad_y self.win.blit(easy_btn, (x, y + 0 * add_y)) self.win.blit(medium_btn, (x, y + 1 * add_y)) self.win.blit(hard_btn, (x, y + 2 * add_y)) pygame.display.update()
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()