#!/usr/bin/python3 import os import pygame import numpy from tools import pg # if you import pg from tools, you dont need to init pygame. from tools.file_dict import FileDict from physics.parabelfunc import berechneflugbahn # integrated settings (I dont trust my own settings class.) DEFAULT_WINDOW_SIZE = (800, 600) FPS = 60 SAVE_SETTINGS_ON_EXIT = True class Cowyeet: def __init__(self): self.DEFAULT_WINDOW_SIZE = DEFAULT_WINDOW_SIZE self.FPS = FPS self.SAVE_SETTINGS_ON_EXIT = SAVE_SETTINGS_ON_EXIT pygame.init() # pygame initialization self.screen = pygame.display.set_mode(DEFAULT_WINDOW_SIZE) pygame.display.set_caption("Cowyeet 2.0") self.settings = self.load_settings() self.draw_loading_screen() # variables self.nero = (40, 40, 40) # colors (color names by https://www.color-blindness.com/color-name-hue/) self.dim_gray = (100, 100, 100) self.summer_sky = (50, 200, 220) self.white_smoke = (240, 240, 240) self.buttons = [] # misc self.text_buttons = [] self.active_buttons = [] self.last_frame_mouse_pressed = False self.page = "main_menu" self.level = None self.level_data = None self.lvl_width = None self.level_surface = None self.cow_throwable = False self.cow_flying = False self.cow_position = (0, 0) self.cow_flight_path = [] self.cow_flight_step = 0 self.pressed_keys = [] self.pressed_special_keys = pygame.key.get_mods() # pygame objects self.clock = pygame.time.Clock() # misc self.mouse = pygame.mouse self.keyboard = pygame.key self.bigger_default_font = pygame.font.SysFont("ubuntu", 32) # fonts self.choose_level_text = self.bigger_default_font.render("Choose a level:", True, self.white_smoke) # texts self.texture_not_found = pygame.image.load("textures/texture_not_found.png") self.texture_not_found = pygame.transform.scale(self.texture_not_found, (40 * self.settings["level_size_multiplier"], 40 * self.settings["level_size_multiplier"])) self.icon_texture = self.load_texture("textures/icon.png") self.full_icon_texture = self.load_texture("textures/icon_full.png") self.full_icon_texture = pygame.transform.scale(self.full_icon_texture, (260, 90)) self.catapult_frame_texture = self.load_texture("textures/catapult/frame.png") self.catapult_frame_texture = pygame.transform.scale(self.catapult_frame_texture, (66 * 5 * self.settings["level_size_multiplier"], 31 * 5 * self.settings["level_size_multiplier"])) self.catapult_arm_texture = self.load_texture("textures/catapult/arm.png") self.catapult_arm_texture = pygame.transform.scale(self.catapult_arm_texture, (25 * 5 * self.settings["level_size_multiplier"], 53 * 5 * self.settings["level_size_multiplier"])) self.cow = self.load_texture("textures/cow/head.png") self.cow = pygame.transform.scale(self.cow, (64 * 5 * self.settings["level_size_multiplier"], 64 * 5 * self.settings["level_size_multiplier"])) self.stone_block_texture = self.load_block_texture("textures/terrain/stone_01.png") self.dirt_block_texture = self.load_block_texture("textures/terrain/dirt_01.png") self.grass_block_texture = self.load_block_texture("textures/terrain/grass_01.png") self.rock_block_texture = self.load_block_texture("textures/terrain/rock_01.png") # buttons self.buttons.append( pg.TextButton("Start", self.center, self.screen, lambda: self.page_switch("level_selector"), text_color=self.white_smoke, bg_color=self.dim_gray, font=self.bigger_default_font)) self.start_button = len(self.buttons) - 1 self.text_buttons.append(self.start_button) self.buttons.append( pg.TextButton("1", (128, 128), self.screen, lambda: self.start_level(1), text_color=self.white_smoke, bg_color=self.dim_gray, font=self.bigger_default_font, padding=(17, 8))) self.lvl_one_button = len(self.buttons) - 1 self.text_buttons.append(self.lvl_one_button) # /buttons # /variables # loading completed self.screen = pygame.display.set_mode(self.settings["win_size"], flags=pygame.RESIZABLE, vsync=1) self.window_size_reload(self.settings["win_size"]) pygame.display.set_icon(self.icon_texture) self.screen.fill(self.nero) pygame.display.update() self.page_switch("main_menu") self.running = True def load_settings(self): if os.path.isfile("settings.txt"): # If the settings exist, load them into a dict. Else create the settings with the default values. settings = FileDict("settings.txt") else: settings = FileDict() settings.path = "settings.txt" settings["win_size"] = DEFAULT_WINDOW_SIZE settings["level_size_multiplier"] = 1 settings.save() return settings def draw_loading_screen(self): default_font = pygame.font.SysFont("ubuntu", 16) loading_text = default_font.render("Loading...", True, (240, 240, 240)) self.screen.fill((40, 40, 40)) self.screen.blit(loading_text, (400 - loading_text.get_width() / 2, 300 - loading_text.get_height() / 2)) pygame.display.update() def load_texture(self, path: str): if os.path.isfile(path): return pygame.image.load(path) else: return self.texture_not_found def load_block_texture(self, path: str): texture = self.load_texture(path) return pygame.transform.scale(texture, (40 * self.settings["level_size_multiplier"], 40 * self.settings["level_size_multiplier"])) def center_x(self, width: int): return self.screen.get_width() / 2 - width / 2 def center_y(self, height: int): return self.screen.get_height() / 2 - height / 2 def center(self, size): width, height = size return self.center_x(width), self.center_y(height) def set_rot_point(self, img, pos): w, h = img.get_size() w, h = w * 2, h * 2 img2 = pygame.Surface((w, h), pygame.SRCALPHA) img2.blit(img, (w / 2 - pos[0], h / 2 - pos[1])) return img2, (w, h) def start_level(self, lvl: int): self.page_switch("ingame") self.level = lvl self.load_level(lvl) self.cow_throwable = True def load_level(self, lvl): self.level_data = __import__("data.levels." + str(lvl), fromlist="data.levels") self.lvl_width, lvl_height = self.level_data.level_size self.level_surface = pygame.Surface((self.lvl_width * 40 * self.settings["level_size_multiplier"], lvl_height * 40 * self.settings["level_size_multiplier"]), pygame.SRCALPHA, 32) x = 0 y = 0 for row in self.level_data.data_array: x = 0 for block in row: rx = x * 40 * self.settings["level_size_multiplier"] ry = y * 40 * self.settings["level_size_multiplier"] self.blit_block(block, (rx, ry)) x += 1 y += 1 def blit_block(self, block, position: tuple): if not block == 0: if block == 1: self.level_surface.blit(self.stone_block_texture, position) elif block == 2: self.level_surface.blit(self.dirt_block_texture, position) elif block == 3: self.level_surface.blit(self.grass_block_texture, position) elif block == 4: self.level_surface.blit(self.rock_block_texture, position) else: self.level_surface.blit(self.texture_not_found, position) def yeet_cow(self): if self.cow_throwable: self.cow_throwable = False lvl_x, lvl_y = self.level_data.level_size lvl_x *= 40 lvl_x *= self.settings["level_size_multiplier"] lvl_y *= 40 lvl_y *= self.settings["level_size_multiplier"] self.cow_flight_path = berechneflugbahn(lvl_x, lvl_y, lvl_x + 100, 34, 128, xstep=10) self.cow_flying = True self.cow_flight_step = 0 def main_menu_page(self): self.screen.blit(self.full_icon_texture, (self.center_x(self.full_icon_texture.get_width()), 128)) self.buttons[self.start_button].blit() def level_selector_page(self): self.buttons[self.lvl_one_button].blit() self.screen.blit(self.choose_level_text, (self.screen.get_width() / 2 - self.choose_level_text.get_width() / 2, 16)) def ingame_page(self): self.screen.fill(self.summer_sky) self.screen.blit(self.level_surface, (0, self.screen.get_height() - self.level_surface.get_height())) lvl_size = self.settings["level_size_multiplier"] cx, cy = self.level_data.catapult_pos cx = cx * 40 * lvl_size cy = self.screen.get_height() - self.level_surface.get_height() + cy * 40 * lvl_size - self.catapult_frame_texture.get_height() self.screen.blit(self.catapult_frame_texture, (cx, cy)) self.screen.blit(self.catapult_arm_texture, (cx + 27 * 5 * lvl_size, cy - 35 * 5 * lvl_size)) if self.cow_flying: self.cow_flight_step += 1 x = self.cow_flight_path[self.cow_flight_step * 2] y = self.cow_flight_path[self.cow_flight_step * 2 + 1] self.cow_position = (x, self.screen.get_height() - y - 64 * 5 * self.settings["level_size_multiplier"]) if self.cow_flight_step * 2 == len(self.cow_flight_path) - 2: self.cow_flying = False self.cow_throwable = True self.screen.blit(self.cow, self.cow_position) def page_selector(self): if self.page == "main_menu": self.main_menu_page() elif self.page == "level_selector": self.level_selector_page() elif self.page == "ingame": self.ingame_page() def page_switch(self, new_page: str=None): if not new_page is None: self.page = new_page if self.page == "main_menu": self.active_buttons = [self.start_button] elif self.page == "level_selector": self.active_buttons = [self.lvl_one_button] elif self.page == "ingame": self.active_buttons = [] # for button in buttons: # button.active = False # # for button in active_buttons: # button.active = True def close(self): self.running = False def window_size_reload(self, new_size): for button in self.text_buttons: self.buttons[button].update() self.settings["win_size"] = new_size def get_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: self.close() return if event.type == pygame.MOUSEBUTTONDOWN: pressed = self.mouse.get_pressed() pos = self.mouse.get_pos() for button in self.active_buttons: self.buttons[button].check(pos, pressed) self.last_frame_mouse_pressed = True elif event.type == pygame.VIDEORESIZE: self.window_size_reload(event.size) elif event.type == pygame.KEYDOWN: key = event.key if key == pygame.K_c and self.pressed_special_keys & pygame.KMOD_CTRL: self.close() elif key == pygame.K_SPACE: if self.page == "ingame": self.yeet_cow() def loop(self): self.screen.fill(self.nero) self.pressed_keys = self.keyboard.get_pressed() self.pressed_special_keys = self.keyboard.get_mods() self.get_events() if not self.running: return self.page_selector() pygame.display.update() self.clock.tick(self.FPS) if __name__ == "__main__": game = Cowyeet() while game.running: game.loop() pygame.quit() if game.SAVE_SETTINGS_ON_EXIT: game.settings.save() print("Bye!")