diff --git a/.idea/InfoProjekt.xlsx b/.idea/InfoProjekt.xlsx new file mode 100644 index 0000000..570d52e Binary files /dev/null and b/.idea/InfoProjekt.xlsx differ diff --git a/.idea/ideas.txt b/.idea/ideas.txt new file mode 100644 index 0000000..131e8a8 --- /dev/null +++ b/.idea/ideas.txt @@ -0,0 +1,44 @@ +Anmerkungen in Klammern + ? - unsicher + name? - Name noch unklar, bzw. steht zur Diskussion + ! - festgelegt / Einigung + +Game: + Rogue-like Game mit Story + Pixel + + viele Gegner: + Skelette Schwert + Zombies Knüppel + Ratten - + Kröten(?) - + Gläubige(?) Bogen / Schwert + +Story: + Theme + mittelalterlich(?) + fairy-tale-like(?) + medieval(!) + + Homeless guy in Berlin (oder so) im Winter in einer Stadtbibliothek, weil warm und Shelter. + er hasst eigentlich Bücher, aber aus Langeweile durchstöbert er die Bibo + findet cool aussehendes antikes/magisches Buch, nimmt es aus dem Regal, blättert es auf und wird ohnmächtig + -> Erwacht als magische Person in magischer Welt wieder + Buch dient als Skillbaum (verschiedene Kapitel) + Kampfmagier (name?) + Heilender Magier -> Priester(name?) + Elementmagier(?) + Hexenkraft / Hexenwerke / Hexenmagie / Flüche (?) + Kampf + Faust + Zauberstab - range und strength von Skills und Level(?) abhängig + + NPCS + Priester / Mönch (eher Mönch) + Henker + armer Bauer + "Hexe" + + Ziel(e) + -> Zurückkommen + -> Happy werden (?) \ No newline at end of file diff --git a/.idea/storyline.txt b/.idea/storyline.txt new file mode 100644 index 0000000..eb8c93e --- /dev/null +++ b/.idea/storyline.txt @@ -0,0 +1,51 @@ +Szene 1 - Startszene: + +Screen - Berlin, 1983, Winter +Draußen in Stadt mit Häusern, kalt und schneeig, +"*Brrr* I'm freezing. I guess I have to warm up myself in the library." +-> bis in der library am Feuer oder so weiterhin frieren +irgendwo info wasd to move around + +wenn am Feuer: +"Now I'm feeling better. The winter days are so boring. Maybe I find a way to intertain myself in here?" + +Wenn iwie am richtigen Buch, was iwie hervorsticht + +"I really hate reading books, but this one looks interesting. Maybe I should have a look inside." + +anklicken? + +Animation er nimmt Buch (und klappt auf?) +Wow * blackscreen Ende Szene 1 + +----------------------------------------- + +Szene 2 - Aufwachen in einer neuen Welt: + +Zerfallene Bibo, selber Ort parallel Universe + +"Huh where am I? What happened??" + + +geht aus Haus raus, wird von Monstern angegriffen, +wenn 1 Hit kommt ältere Dame, tötet/verjagt Monster und Gespräch. +Faselt irgendwie hä warum du nicht dich verteidigen oh du cooles Buch du auserwählter oder so. +Sagt soll zum Dorf gehen wegen Baum und gibt ihm noch irgendwas, muss aber selbst woanders hin. +und Achtung vor Monstern! + +------------------------------------------ + +auf Weg dann neue Welle Monster, lernt sich iwie zu verteidigen(Buch) + +------------------------------------------ +Im Dorf beim Dorfältesten melden, +Hallo du uns helfen musst wegen Böse bitte bitte, wir dir auch mit Unterkunft und Essen und so helfen. +Innerer Konflikt weil ihm in altem Leben auch nicht von Allgemeinheit geholfen, und er siehts nicht ein... + +------------------------------------------ +erst durch erneuter Begegnung mit alter Dame wegen nem Happening einsicht... +------------------------------------------ +dann Kämpfi gegen böse um zum Boss zu kommen und boss kämpfi... +------------------------------------------ +am Ende er als Held gefeiert +und irgendwie Auswahl, ob da bleiben oder Weg zurück suchen aber im alten Leben was ändern \ No newline at end of file diff --git a/READ.ME b/READ.ME new file mode 100644 index 0000000..156111f --- /dev/null +++ b/READ.ME @@ -0,0 +1,53 @@ +Brief Explanation of all files and classes and pygame + + +Button CLass: +Button(position_x, position_y, width, height, font key phrase/word (see dictionary), the function which should be executed, and if the function should be executed while holding the button or only once per press) + +fonts = { + 'medieval': 'medieval.ttf', + 'minecraft': 'Minecraft Evenings.otf', + '3dpixel': '3D-Pixel.ttf', + '8bit': '8bitlim.ttf', + '8bito': '8blimro.ttf', + 'arcade': 'ARCADECLASSIC.ttf', + 'modern_game': 'astron boy video.otf', + 'modern': 'astron boy.otf', + 'wonder': 'Beyond Wonderland.ttf', + 'curved': 'Digitag.ttf', + 'simple': 'DisposableDroidBB.ttf', + 'rounded': 'dpcomic.ttf', + 'playfull': 'Endalian Script.ttf', + 'blocky': 'FREAKSOFNATURE.ttf', + 'catchy': 'Future TimeSplitters.otf', + 'simple_wide': 'Halo3.ttf', + 'simple_fat': 'INVASION2000.ttf', + 'very_gamy': 'ka1.ttf', + 'simple_round': 'Karma Suture.otf', + 'mono': 'manaspc.ttf', + 'damaged': 'Merchant Copy.ttf', + 'big_natural': 'MorialCitadel.TTF', + 'spacy': 'nasalization-rg.otf', + 'sci-fi': 'neuropol.otf', + 'hollow_big_edge': 'papercut.ttf', + 'space_shuttle': 'pdark.ttf', + 'thin': 'PixelFJVerdana12pt.ttf', + 'random': 'Seattle Avenue.ttf', + 'pixel': 'yoster.ttf' +} + +Pygame window: (0, 0) is in the top left corner, the height and width are stored in HEIGHT and WIDTH + +GameObjects for rooms, scenes and maybe MorialCitadel + +Scene: + type - normal, dungeon, cutscene + objects - contain rooms, npcs, mobs, the character etc. + +Room: + type - normal, shop, special (?), boss + objects - npcs, mobs, the character etc. + exits - position of exits --> [top:bool, right:bool, down:bool, left:bool]; 1 to 4 exits per room + locked - bool if the room is unlocked; locked upon first entering unless all mobs are dead + + diff --git a/art/image files/exit.png b/art/image files/exit.png new file mode 100644 index 0000000..0fcda62 Binary files /dev/null and b/art/image files/exit.png differ diff --git a/art/image files/field.kra b/art/image files/field.kra new file mode 100644 index 0000000..f99eaf6 Binary files /dev/null and b/art/image files/field.kra differ diff --git a/art/image files/field.png b/art/image files/field.png new file mode 100644 index 0000000..008cb35 Binary files /dev/null and b/art/image files/field.png differ diff --git a/art/image files/mauer.png b/art/image files/mauer.png new file mode 100644 index 0000000..41ca7f1 Binary files /dev/null and b/art/image files/mauer.png differ diff --git a/art/image files/mauer_down-left.png b/art/image files/mauer_down-left.png new file mode 100644 index 0000000..e08c486 Binary files /dev/null and b/art/image files/mauer_down-left.png differ diff --git a/art/image files/mauer_down-right.png b/art/image files/mauer_down-right.png new file mode 100644 index 0000000..b6ac2ee Binary files /dev/null and b/art/image files/mauer_down-right.png differ diff --git a/art/image files/mauer_down.png b/art/image files/mauer_down.png new file mode 100644 index 0000000..9444e8e Binary files /dev/null and b/art/image files/mauer_down.png differ diff --git a/art/image files/mauer_left.png b/art/image files/mauer_left.png new file mode 100644 index 0000000..dd36a63 Binary files /dev/null and b/art/image files/mauer_left.png differ diff --git a/art/image files/mauer_right.png b/art/image files/mauer_right.png new file mode 100644 index 0000000..616d840 Binary files /dev/null and b/art/image files/mauer_right.png differ diff --git a/art/image files/mauer_top-left.png b/art/image files/mauer_top-left.png new file mode 100644 index 0000000..a08eac8 Binary files /dev/null and b/art/image files/mauer_top-left.png differ diff --git a/art/image files/mauer_top-right.png b/art/image files/mauer_top-right.png new file mode 100644 index 0000000..8f12ed8 Binary files /dev/null and b/art/image files/mauer_top-right.png differ diff --git a/art/image files/mauer_top.png b/art/image files/mauer_top.png new file mode 100644 index 0000000..9840b47 Binary files /dev/null and b/art/image files/mauer_top.png differ diff --git a/art/image files/new_game.png b/art/image files/new_game.png new file mode 100644 index 0000000..b5fc60a Binary files /dev/null and b/art/image files/new_game.png differ diff --git a/art/image files/options.png b/art/image files/options.png new file mode 100644 index 0000000..8d334fa Binary files /dev/null and b/art/image files/options.png differ diff --git a/art/image files/set1.png b/art/image files/set1.png new file mode 100644 index 0000000..bed3214 Binary files /dev/null and b/art/image files/set1.png differ diff --git a/art/images/arrow.png b/art/images/arrow.png new file mode 100644 index 0000000..ede5aaf Binary files /dev/null and b/art/images/arrow.png differ diff --git a/art/images/blau1.kra b/art/images/blau1.kra new file mode 100644 index 0000000..ea14ba2 Binary files /dev/null and b/art/images/blau1.kra differ diff --git a/art/images/blau1.png b/art/images/blau1.png new file mode 100644 index 0000000..8c831a4 Binary files /dev/null and b/art/images/blau1.png differ diff --git a/art/images/blau2.png b/art/images/blau2.png new file mode 100644 index 0000000..ad3a521 Binary files /dev/null and b/art/images/blau2.png differ diff --git a/art/images/blau3.png b/art/images/blau3.png new file mode 100644 index 0000000..6432f79 Binary files /dev/null and b/art/images/blau3.png differ diff --git a/art/images/book.png b/art/images/book.png new file mode 100644 index 0000000..580c3aa Binary files /dev/null and b/art/images/book.png differ diff --git a/art/images/dirt1.png b/art/images/dirt1.png new file mode 100644 index 0000000..fad8f07 Binary files /dev/null and b/art/images/dirt1.png differ diff --git a/art/images/dirt2.png b/art/images/dirt2.png new file mode 100644 index 0000000..b73418f Binary files /dev/null and b/art/images/dirt2.png differ diff --git a/art/images/dreiviertelheart.png b/art/images/dreiviertelheart.png new file mode 100644 index 0000000..0b455eb Binary files /dev/null and b/art/images/dreiviertelheart.png differ diff --git a/art/images/fireball.png b/art/images/fireball.png new file mode 100644 index 0000000..c893360 Binary files /dev/null and b/art/images/fireball.png differ diff --git a/art/images/fullheart.png b/art/images/fullheart.png new file mode 100644 index 0000000..07dd926 Binary files /dev/null and b/art/images/fullheart.png differ diff --git a/art/images/grass.png b/art/images/grass.png new file mode 100644 index 0000000..578e8b7 Binary files /dev/null and b/art/images/grass.png differ diff --git a/art/images/halfheart.png b/art/images/halfheart.png new file mode 100644 index 0000000..fa33606 Binary files /dev/null and b/art/images/halfheart.png differ diff --git a/art/images/label.png b/art/images/label.png new file mode 100644 index 0000000..9631a74 Binary files /dev/null and b/art/images/label.png differ diff --git a/art/images/noheart.png b/art/images/noheart.png new file mode 100644 index 0000000..a02db39 Binary files /dev/null and b/art/images/noheart.png differ diff --git a/art/images/oldman.png b/art/images/oldman.png new file mode 100644 index 0000000..fbda3fb Binary files /dev/null and b/art/images/oldman.png differ diff --git a/art/images/reddy.png b/art/images/reddy.png new file mode 100644 index 0000000..40954a2 Binary files /dev/null and b/art/images/reddy.png differ diff --git a/art/images/river1.png b/art/images/river1.png new file mode 100644 index 0000000..33fbb7f Binary files /dev/null and b/art/images/river1.png differ diff --git a/art/images/rot1.png b/art/images/rot1.png new file mode 100644 index 0000000..209753c Binary files /dev/null and b/art/images/rot1.png differ diff --git a/art/images/rot2.png b/art/images/rot2.png new file mode 100644 index 0000000..4b76d59 Binary files /dev/null and b/art/images/rot2.png differ diff --git a/art/images/rot3.png b/art/images/rot3.png new file mode 100644 index 0000000..a892101 Binary files /dev/null and b/art/images/rot3.png differ diff --git a/art/images/start.png b/art/images/start.png new file mode 100644 index 0000000..3d7f7c5 Binary files /dev/null and b/art/images/start.png differ diff --git a/art/images/textbox.png b/art/images/textbox.png new file mode 100644 index 0000000..be01aef Binary files /dev/null and b/art/images/textbox.png differ diff --git a/art/images/viertelheart.png b/art/images/viertelheart.png new file mode 100644 index 0000000..de0043d Binary files /dev/null and b/art/images/viertelheart.png differ diff --git a/art/sprite files/oldmanattack.png b/art/sprite files/oldmanattack.png new file mode 100644 index 0000000..fb1085e Binary files /dev/null and b/art/sprite files/oldmanattack.png differ diff --git a/art/sprite files/oldmanwalk.png b/art/sprite files/oldmanwalk.png new file mode 100644 index 0000000..f578cc3 Binary files /dev/null and b/art/sprite files/oldmanwalk.png differ diff --git a/classes.py b/classes.py new file mode 100644 index 0000000..ec2c32c --- /dev/null +++ b/classes.py @@ -0,0 +1,230 @@ +import pygame + +pygame.font.init() +fonts = { + 'medieval': 'medieval.ttf', + 'minecraft': 'Minecraft Evenings.otf', + '3dpixel': '3D-Pixel.ttf', + '8bit': '8bitlim.ttf', + '8bito': '8blimro.ttf', + 'arcade': 'ARCADECLASSIC.ttf', + 'modern_game': 'astron boy video.otf', + 'modern': 'astron boy.otf', + 'wonder': 'Beyond Wonderland.ttf', + 'curved': 'Digitag.ttf', + 'simple': 'DisposableDroidBB.ttf', + 'rounded': 'dpcomic.ttf', + 'playfull': 'Endalian Script.ttf', + 'blocky': 'FREAKSOFNATURE.ttf', + 'catchy': 'Future TimeSplitters.otf', + 'simple_wide': 'Halo3.ttf', + 'simple_fat': 'INVASION2000.ttf', + 'very_gamy': 'ka1.ttf', + 'simple_round': 'Karma Suture.otf', + 'mono': 'manaspc.ttf', + 'damaged': 'Merchant Copy.ttf', + 'big_natural': 'MorialCitadel.TTF', + 'spacy': 'nasalization-rg.otf', + 'sci-fi': 'neuropol.otf', + 'hollow_big_edge': 'papercut.ttf', + 'space_shuttle': 'pdark.ttf', + 'thin': 'PixelFJVerdana12pt.ttf', + 'random': 'Seattle Avenue.ttf', + 'pixel': 'yoster.ttf' +} + +class Button(): + def __init__(self, x, y, width, height, font, font_size, buttonText='Button', onclickFunction=None, onePress=False): + self.font = pygame.font.Font(f'fonts/{fonts[font]}', font_size) + self.x = x + self.y = y + self.width = width + self.height = height + self.onclickFunction = onclickFunction + self.onePress = onePress + self.alreadyPressed = False + + with open('art/images/textbox.png', 'r') as tb: + self.box = pygame.image.load(tb) + self.box = pygame.transform.scale(self.box, (width, height)) + + + self.buttonRect = pygame.Rect(self.x, self.y, self.width, self.height) + + self.buttonSurf = self.font.render(buttonText, True, '#baab80') + + def process(self, screen, clock, running, background, isblack, WIDTH, HEIGHT): + mousePos = pygame.mouse.get_pos() + if self.buttonRect.collidepoint(mousePos): + if pygame.mouse.get_pressed(num_buttons=3)[0]: + if self.onePress: + self.onclickFunction() + elif not self.alreadyPressed: + if 'play' in str(self.onclickFunction): + self.onclickFunction(screen, clock, running, background, isblack, WIDTH, HEIGHT) + self.alreadyPressed = True + else: + self.onclickFunction() + self.alreadyPressed = True + else: + self.alreadyPressed = False + self.box.blit(self.buttonSurf, [ + self.buttonRect.width/2 - self.buttonSurf.get_rect().width/2, + self.buttonRect.height/2 - self.buttonSurf.get_rect().height/2 + ]) + screen.blit(self.box, self.buttonRect) + + +class DropDown(): + def __init__(self, x, y, width, height, font, font_size, color_menu, color_option, main, options): + self.rect = pygame.Rect(x, y, width, height) + self.font = pygame.font.Font(f'fonts/{fonts[font]}', font_size) + self.main = main + self.options = options + self.draw_menu = False + self.menu_active = False + self.active_option = -1 + + with open('art/images/textbox.png', 'r') as tb: + self.box = pygame.image.load(tb) + self.box = pygame.transform.scale(self.box, (width, height)) + + def draw(self, screen): + #pygame.draw.rect(screen, self.color_menu[self.menu_active], self.rect, 0) + surface = self.font.render(self.main, 1, (0, 0, 0)) + self.box.blit(surface, [ + self.rect.width/2 - surface.get_rect().width/2, + self.rect.height/2 - surface.get_rect().height/2 + ]) + screen.blit(self.box, surface.get_rect(center = self.rect.center)) + + if self.draw_menu: + for i, text in enumerate(self.options): + rect = self.rect.copy() + rect.y += (i+1) * self.rect.height + rect.x = self.rect.x + #pygame.draw.rect(screen, self.color_option[1 if i == self.active_option else 0], rect, 0) + #msg = self.font.render(text, 1, (0, 0, 0)) + #screen.blit(msg, msg.get_rect(center = rect.center)) + surface = self.font.render(text, 1, (0, 0, 0)) + self.box.blit(surface, [ + rect.width/2 - surface.get_rect().width/2, + rect.height/2 - surface.get_rect().height/2 + ]) + screen.blit(self.box, rect) + + def update(self, event_list): + mpos = pygame.mouse.get_pos() + self.menu_active = self.rect.collidepoint(mpos) + self.active_option = -1 + for i in range(len(self.options)): + rect = self.rect.copy() + rect.y += (i+1) * self.rect.height + if rect.collidepoint(mpos): + self.active_option = i + break + + if not self.menu_active and self.active_option == -1: + self.draw_menu = False + #self.draw_menu = True + #return -1 + if pygame.mouse.get_pressed(num_buttons=3)[0]: + if self.menu_active: + self.draw_menu = not self.draw_menu + elif self.draw_menu and self.active_option >= 0: + self.draw_menu = False + return self.active_option + return -1 + + +class GameObjects(): + def __init__(self, name:str, _type:str, bg, objects:list, WIDTH, HEIGHT) -> None: + self.name = name + self.type = _type + self.background = bg + if bg != None: + with open(bg, 'r') as bg: + self.background = pygame.transform.scale(pygame.image.load(bg), [WIDTH, HEIGHT]) + self.objects = objects + + +class Scene(GameObjects): + def __init__(self, name:str, _type:str, bg, objects:list | None, WIDTH, HEIGHT, level:list) -> None: + super().__init__(name, _type, bg, objects, WIDTH, HEIGHT) + self.level = level + self.current_level = 0 + + def update(self, change:bool): + if change: + self.current_level += 1 + self.level[self.current_level].update() + if isinstance(self.objects, list): + for obj in self.objects: + obj.update() + + def draw(self, screen): + if isinstance(self.objects, list): + for obj in self.objects: + obj.draw(screen) + self.level[self.current_level].draw(screen) + + +class Stage(GameObjects): + def __init__(self, name: str, _type: str, bg, objects: list, WIDTH, HEIGHT, stage:str, rooms:list) -> None: + super().__init__(name, _type, bg, objects, WIDTH, HEIGHT) + self.stage = stage + self.rooms = rooms + self.current = 0 + + def update(self): + for room in self.rooms: + if room.id == self.current: + room.update() + keys = pygame.key.get_pressed() + if keys[pygame.K_RIGHT]: + self.current += 1 + if self.current >= len(self.rooms): + return 1 + + def draw(self, screen): + for room in self.rooms: + if room.id == self.current: + room.draw(screen) + +class Room(GameObjects): + def __init__(self, name:str, _type:str, bg, objects:list, WIDTH, HEIGHT, exits:list, id:int) -> None: + super().__init__(name, _type, bg, objects, WIDTH, HEIGHT) + self.exits = exits + self.id = id + if self.type == 'normal' or self.type == 'boss': + self.locked = True + else: + self.locked = False + + self.objects.append(self.genWalls(WIDTH, HEIGHT)) + + def genWalls(self, WIDTH, HEIGHT): + walls = [] + walls.append(pygame.Rect(0, 0, 4, HEIGHT)) + walls.append(pygame.Rect(WIDTH - 4, 0, 4, HEIGHT)) + walls.append(pygame.Rect(0, 0, WIDTH, 4)) + walls.append(pygame.Rect(0, HEIGHT - 4, WIDTH, 4)) + return walls + + def update(self): + pass + + def draw(self, screen): + screen.blit(self.background, (32, 32)) + if isinstance(self.objects, list): + for obj in self.objects[0]: + obj.draw(screen) + +class Obstacle(GameObjects): + def __init__(self, name: str, _type: str, bg, collision: bool, x: int, y: int, hidden: bool=False, objects: list = None, WIDTH=None, HEIGHT=None) -> None: + super().__init__(name, _type, bg, objects, WIDTH, HEIGHT) + self.collision = collision + self.rect = pygame.Rect((x, y), self.background.get_size()) + + def draw(self, screen): + screen.blit(self.background, self.rect) \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..76e9637 --- /dev/null +++ b/config.json @@ -0,0 +1,7 @@ +{ + "screen": + { + "res":[1280, 720], + "fullscreen": false + } +} \ No newline at end of file diff --git a/fonts/3D-Pixel.ttf b/fonts/3D-Pixel.ttf new file mode 100644 index 0000000..15a051c Binary files /dev/null and b/fonts/3D-Pixel.ttf differ diff --git a/fonts/8bitlim.ttf b/fonts/8bitlim.ttf new file mode 100644 index 0000000..f8051e4 Binary files /dev/null and b/fonts/8bitlim.ttf differ diff --git a/fonts/8bitlimo.ttf b/fonts/8bitlimo.ttf new file mode 100644 index 0000000..fbd4d88 Binary files /dev/null and b/fonts/8bitlimo.ttf differ diff --git a/fonts/8bitlimr.ttf b/fonts/8bitlimr.ttf new file mode 100644 index 0000000..c66935d Binary files /dev/null and b/fonts/8bitlimr.ttf differ diff --git a/fonts/8blimro.ttf b/fonts/8blimro.ttf new file mode 100644 index 0000000..1f9da76 Binary files /dev/null and b/fonts/8blimro.ttf differ diff --git a/fonts/ARCADECLASSIC.TTF b/fonts/ARCADECLASSIC.TTF new file mode 100644 index 0000000..394a9f7 Binary files /dev/null and b/fonts/ARCADECLASSIC.TTF differ diff --git a/fonts/Beyond Wonderland.ttf b/fonts/Beyond Wonderland.ttf new file mode 100644 index 0000000..8cf093b Binary files /dev/null and b/fonts/Beyond Wonderland.ttf differ diff --git a/fonts/Digitag.ttf b/fonts/Digitag.ttf new file mode 100644 index 0000000..ea523e9 Binary files /dev/null and b/fonts/Digitag.ttf differ diff --git a/fonts/DisposableDroidBB.ttf b/fonts/DisposableDroidBB.ttf new file mode 100644 index 0000000..84f98c5 Binary files /dev/null and b/fonts/DisposableDroidBB.ttf differ diff --git a/fonts/DisposableDroidBB_bld.ttf b/fonts/DisposableDroidBB_bld.ttf new file mode 100644 index 0000000..9748e29 Binary files /dev/null and b/fonts/DisposableDroidBB_bld.ttf differ diff --git a/fonts/DisposableDroidBB_bldital.ttf b/fonts/DisposableDroidBB_bldital.ttf new file mode 100644 index 0000000..5544fe4 Binary files /dev/null and b/fonts/DisposableDroidBB_bldital.ttf differ diff --git a/fonts/DisposableDroidBB_ital.ttf b/fonts/DisposableDroidBB_ital.ttf new file mode 100644 index 0000000..596d523 Binary files /dev/null and b/fonts/DisposableDroidBB_ital.ttf differ diff --git a/fonts/Endalian Script.ttf b/fonts/Endalian Script.ttf new file mode 100644 index 0000000..1304f00 Binary files /dev/null and b/fonts/Endalian Script.ttf differ diff --git a/fonts/FREAKSOFNATURE.ttf b/fonts/FREAKSOFNATURE.ttf new file mode 100644 index 0000000..335c851 Binary files /dev/null and b/fonts/FREAKSOFNATURE.ttf differ diff --git a/fonts/FREAKSOFNATUREMASSIVE.ttf b/fonts/FREAKSOFNATUREMASSIVE.ttf new file mode 100644 index 0000000..f9b49d8 Binary files /dev/null and b/fonts/FREAKSOFNATUREMASSIVE.ttf differ diff --git a/fonts/Future TimeSplitters.otf b/fonts/Future TimeSplitters.otf new file mode 100644 index 0000000..f28a9a9 Binary files /dev/null and b/fonts/Future TimeSplitters.otf differ diff --git a/fonts/Halo3.ttf b/fonts/Halo3.ttf new file mode 100644 index 0000000..daeb3f2 Binary files /dev/null and b/fonts/Halo3.ttf differ diff --git a/fonts/INVASION2000.TTF b/fonts/INVASION2000.TTF new file mode 100644 index 0000000..87f629b Binary files /dev/null and b/fonts/INVASION2000.TTF differ diff --git a/fonts/Karma Future.otf b/fonts/Karma Future.otf new file mode 100644 index 0000000..c05849b Binary files /dev/null and b/fonts/Karma Future.otf differ diff --git a/fonts/Karma Suture.otf b/fonts/Karma Suture.otf new file mode 100644 index 0000000..31279ea Binary files /dev/null and b/fonts/Karma Suture.otf differ diff --git a/fonts/Merchant Copy Doublesize.ttf b/fonts/Merchant Copy Doublesize.ttf new file mode 100644 index 0000000..6651f4b Binary files /dev/null and b/fonts/Merchant Copy Doublesize.ttf differ diff --git a/fonts/Merchant Copy Wide.ttf b/fonts/Merchant Copy Wide.ttf new file mode 100644 index 0000000..74527d2 Binary files /dev/null and b/fonts/Merchant Copy Wide.ttf differ diff --git a/fonts/Merchant Copy.ttf b/fonts/Merchant Copy.ttf new file mode 100644 index 0000000..a095272 Binary files /dev/null and b/fonts/Merchant Copy.ttf differ diff --git a/fonts/Minecraft Evenings.otf b/fonts/Minecraft Evenings.otf new file mode 100644 index 0000000..ada43f1 Binary files /dev/null and b/fonts/Minecraft Evenings.otf differ diff --git a/fonts/MoriaCitadel.TTF b/fonts/MoriaCitadel.TTF new file mode 100644 index 0000000..7a63981 Binary files /dev/null and b/fonts/MoriaCitadel.TTF differ diff --git a/fonts/PixelFJVerdana12pt.ttf b/fonts/PixelFJVerdana12pt.ttf new file mode 100644 index 0000000..5531267 Binary files /dev/null and b/fonts/PixelFJVerdana12pt.ttf differ diff --git a/fonts/Seattle Avenue.ttf b/fonts/Seattle Avenue.ttf new file mode 100644 index 0000000..21f3099 Binary files /dev/null and b/fonts/Seattle Avenue.ttf differ diff --git a/fonts/SeattleAvenue.otf b/fonts/SeattleAvenue.otf new file mode 100644 index 0000000..57f51c1 Binary files /dev/null and b/fonts/SeattleAvenue.otf differ diff --git a/fonts/astron boy italic.otf b/fonts/astron boy italic.otf new file mode 100644 index 0000000..25f5c1f Binary files /dev/null and b/fonts/astron boy italic.otf differ diff --git a/fonts/astron boy video.otf b/fonts/astron boy video.otf new file mode 100644 index 0000000..78a3c9d Binary files /dev/null and b/fonts/astron boy video.otf differ diff --git a/fonts/astron boy wonder.otf b/fonts/astron boy wonder.otf new file mode 100644 index 0000000..72c7e49 Binary files /dev/null and b/fonts/astron boy wonder.otf differ diff --git a/fonts/astron boy.otf b/fonts/astron boy.otf new file mode 100644 index 0000000..d27810f Binary files /dev/null and b/fonts/astron boy.otf differ diff --git a/fonts/dpcomic.ttf b/fonts/dpcomic.ttf new file mode 100644 index 0000000..a0776ae Binary files /dev/null and b/fonts/dpcomic.ttf differ diff --git a/fonts/ka1.ttf b/fonts/ka1.ttf new file mode 100644 index 0000000..d1df852 Binary files /dev/null and b/fonts/ka1.ttf differ diff --git a/fonts/kirbyss.ttf b/fonts/kirbyss.ttf new file mode 100644 index 0000000..018853f Binary files /dev/null and b/fonts/kirbyss.ttf differ diff --git a/fonts/manaspc.ttf b/fonts/manaspc.ttf new file mode 100644 index 0000000..0c56733 Binary files /dev/null and b/fonts/manaspc.ttf differ diff --git a/fonts/medieval.ttf b/fonts/medieval.ttf new file mode 100644 index 0000000..5337005 Binary files /dev/null and b/fonts/medieval.ttf differ diff --git a/fonts/nasalization-rg.otf b/fonts/nasalization-rg.otf new file mode 100644 index 0000000..ce4625f Binary files /dev/null and b/fonts/nasalization-rg.otf differ diff --git a/fonts/neuropol.otf b/fonts/neuropol.otf new file mode 100644 index 0000000..5732517 Binary files /dev/null and b/fonts/neuropol.otf differ diff --git a/fonts/papercut.ttf b/fonts/papercut.ttf new file mode 100644 index 0000000..4f47ef4 Binary files /dev/null and b/fonts/papercut.ttf differ diff --git a/fonts/pcsenior.ttf b/fonts/pcsenior.ttf new file mode 100644 index 0000000..0bb46c4 Binary files /dev/null and b/fonts/pcsenior.ttf differ diff --git a/fonts/pdark.ttf b/fonts/pdark.ttf new file mode 100644 index 0000000..0eace6e Binary files /dev/null and b/fonts/pdark.ttf differ diff --git a/fonts/yoster.ttf b/fonts/yoster.ttf new file mode 100644 index 0000000..bbbeb51 Binary files /dev/null and b/fonts/yoster.ttf differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..840dfae --- /dev/null +++ b/main.py @@ -0,0 +1,214 @@ +import pygame +import sys +import json +import time +import random +from classes import * +from viecher import * +fps = 60 + +def setUp(config): + pygame.init() + if config["fullscreen"]: + screen = pygame.display.set_mode(config["res"], pygame.FULLSCREEN) + else: + screen = pygame.display.set_mode(config["res"]) + clock = pygame.time.Clock() + + return screen, clock, True, True, "start.png", [] + +def readConfig(): + with open('config.json', 'r') as c: + json_data = c.read() + return json.loads(json_data) + +def quitGame(): + #save progress somehow, if needed + pygame.quit() + quit() + +def genRooms(WIDTH, HEIGHT, type:str): + room_objects = [Obstacle('dirt', 'boulder', 'art/images/dirt2.png', False, 32, 32, WIDTH=WIDTH - 64, HEIGHT=HEIGHT - 64)] + room_objects.append(Obstacle('river', 'water', 'art/images/river1.png', True, 32, 32, WIDTH=WIDTH - 64, HEIGHT=HEIGHT - 64)) + rooms = [ + Room(type, 'normal', f'art/images/{type}.png', [[room_objects[i] for i in range(0, random.randint(0, len(room_objects)))]], WIDTH - 64, HEIGHT - 64, [True, True, True, False], 0), + Room(type, 'normal', f'art/images/{type}.png', [], WIDTH - 64, HEIGHT - 64, [True, True, True, False], 1), + Room(type, 'normal', f'art/images/{type}.png', [], WIDTH - 64, HEIGHT - 64, [True, True, True, False], 2), + ] + return rooms + +def play(screen, clock, running, background, isblack, WIDTH, HEIGHT): + main = [MainCharacter('Herbert', 100, 'oldman.png', 500, 500, 20, 5, 1, 1, 50)] + mobs = [Skeleton(i, random.randint(40, 60), 'reddy.png', random.randint(20,1000), random.randint(20,700), 5, 1, 1, 1, 200) for i in range(0,random.randint(2, 8))] + others = [] + npcs = [NPC('name', 100, 'reddy.png', 1, 200, 200)] + objects = [main, mobs, npcs, others] + freeze = False #Gameplay is freezed in certain situations + + while running: + screen.fill('#000000') + events = pygame.event.get() + for event in events: + if event.type == pygame.QUIT: + quitGame() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_e: #when book is open gameplay is freezed + freeze = not freeze + # RENDER YOUR GAME HERE + """with open(background, 'r') as i: + bg = pygame.image.load(i) + bg = pygame.transform.scale(bg, (WIDTH, HEIGHT)) + # fill the screen with an image to clear the screen + screen.blit(bg, (0, 0)) +""" + if not freeze: + for thing in objects[0]: + thing.book.hidden = not freeze + if not thing.update(pygame.key.get_pressed(), objects): + menu(screen, clock, running, background, isblack, WIDTH, HEIGHT) + thing.draw(screen) + + for mob in objects[1]: + mob.update(objects) + mob.draw(screen) + + for npc in objects[2]: + npc.update(pygame.key.get_pressed(), objects) + npc.draw(screen) + + for thing in objects[3]: + thing.update(objects) + thing.draw(screen) + else: + objects[0][0].book.hidden = not freeze + objects[0][0].book.draw(screen) + objects[0][0].book.update() + # flip() the display to put your work on screen + pygame.display.flip() + + clock.tick(fps) # limits FPS to 60 + +def options(screen, clock, running, background, isblack, WIDTH, HEIGHT): + objects = [] + # List that is displayed while selecting the window resolution level + resolution = [("1920x1080", "1920x1080"), + ("1920x1200", "1920x1200"), + ("1280x720", "1280x720"), + ("2560x1440", "2560x1440"), + ("3840x2160", "3840x2160")] + + # This function displays the currently selected options + + def printSettings(): + print("\n\n") + # getting the data using "get_input_data" method of the Menu class + settingsData = settings.get_input_data() + + for key in settingsData.keys(): + print(f"{key}\t:\t{settingsData[key]}") + + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + # RENDER YOUR GAME HERE + with open(background, 'r') as i: + bg = pygame.image.load(i) + bg = pygame.transform.scale(bg, (WIDTH, HEIGHT)) + # fill the screen with an image to clear the screen + screen.blit(bg, (0, 0)) + for obj in objects: + obj.process(screen) + + # flip() the display to put your work on screen + pygame.display.flip() + + clock.tick(60) # limits FPS to 60 + +def menu(screen, clock, running, background, isblack, WIDTH, HEIGHT): + objects = [] + objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2, 160, 64, 'medieval', 48, "Play", play)) + #objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 - 72, 160, 64, 'medieval', 48, "Options", uwu)) + objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 + 72, 160, 64, 'medieval', 48, "Exit game", quitGame)) + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + quitGame() + # RENDER YOUR GAME HERE + with open(f'art/images/{background}', 'r') as i: + bg = pygame.image.load(i) + bg = pygame.transform.scale(bg, (WIDTH, HEIGHT)) + # fill the screen with an image to clear the screen + screen.blit(bg, (0, 0)) + for obj in objects: + obj.process(screen, clock, running, background, isblack, WIDTH, HEIGHT) + + # flip() the display to put your work on screen + pygame.display.flip() + + clock.tick(60) # limits FPS to 60 + +def test(screen, clock, running, background, isblack, WIDTH, HEIGHT): + level = [] + rooms = genRooms(WIDTH, HEIGHT, 'grass') + level.append(Stage('blau', 'normal', None, [], WIDTH, HEIGHT, 'blue', rooms)) + + level.append(Stage('rot', 'normal', None, [], WIDTH, HEIGHT, 'red', [ + Room('red1', 'normal', 'art/images/grass.png', [], WIDTH, HEIGHT, [True, True, True, False], 0), + Room('red2', 'normal', 'art/images/grass.png', [], WIDTH, HEIGHT, [True, True, True, False], 1), + Room('red3', 'normal', 'art/images/grass.png', [], WIDTH, HEIGHT, [True, True, True, False], 2), + ])) + + scene = Scene('test', 'normal', None, None, WIDTH, HEIGHT, level) + + # RENDER YOUR GAME HERE + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + quitGame() + screen.fill('#000000') + scene.update(False) + scene.draw(screen) + # flip() the display to put your work on screen + pygame.display.flip() + + clock.tick(60) # limits FPS to 60 + +def main(): + config = readConfig() + screen, clock, running, isblack, background, objects = setUp(config["screen"]) + WIDTH, HEIGHT = screen.get_size() + #objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 - 72, 160, 64, 'medieval', 48, "Play", play)) + #objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2, 160, 64, 'medieval', 48, "Options", uwu)) + #objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 + 72, 160, 64, 'medieval', 48, "Exit game", quitGame)) + menu(screen, clock, running, background, isblack, WIDTH, HEIGHT) + test(screen, clock, running, background, isblack, WIDTH, HEIGHT) + + """while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + #menu(screen, clock, running, background, isblack, WIDTH, HEIGHT) + if not isblack: + with open(background, 'r') as i: + bg = pygame.image.load(i) + bg = pygame.transform.scale(bg, (WIDTH, HEIGHT)) + # fill the screen with a color to wipe away anything from last frame + screen.blit(bg, (0, 0)) + + # RENDER YOUR GAME HERE + + else: + for obj in objects: + obj.process(screen, clock, running, background, isblack, WIDTH, HEIGHT) + # flip() the display to put your work on screen + pygame.display.flip() + + clock.tick(60) # limits FPS to 60""" + + pygame.quit() + +if __name__ == '__main__': + main() diff --git a/test.png b/test.png new file mode 100644 index 0000000..4a92572 Binary files /dev/null and b/test.png differ diff --git a/test1.png b/test1.png new file mode 100644 index 0000000..a36957b Binary files /dev/null and b/test1.png differ diff --git a/test2.png b/test2.png new file mode 100644 index 0000000..9a57c79 Binary files /dev/null and b/test2.png differ diff --git a/viecher.py b/viecher.py new file mode 100644 index 0000000..4dfcf6c --- /dev/null +++ b/viecher.py @@ -0,0 +1,361 @@ +import pygame as pg +vec = pg.math.Vector2 +fps = 60 + + +pg.font.init() +fonts = { + 'medieval': 'medieval.ttf', + 'minecraft': 'Minecraft Evenings.otf', + '3dpixel': '3D-Pixel.ttf', + '8bit': '8bitlim.ttf', + '8bito': '8blimro.ttf', + 'arcade': 'ARCADECLASSIC.ttf', + 'modern_game': 'astron boy video.otf', + 'modern': 'astron boy.otf', + 'wonder': 'Beyond Wonderland.ttf', + 'curved': 'Digitag.ttf', + 'simple': 'DisposableDroidBB.ttf', + 'rounded': 'dpcomic.ttf', + 'playfull': 'Endalian Script.ttf', + 'blocky': 'FREAKSOFNATURE.ttf', + 'catchy': 'Future TimeSplitters.otf', + 'simple_wide': 'Halo3.ttf', + 'simple_fat': 'INVASION2000.ttf', + 'very_gamy': 'ka1.ttf', + 'simple_round': 'Karma Suture.otf', + 'mono': 'manaspc.ttf', + 'damaged': 'Merchant Copy.ttf', + 'big_natural': 'MorialCitadel.TTF', + 'spacy': 'nasalization-rg.otf', + 'sci-fi': 'neuropol.otf', + 'hollow_big_edge': 'papercut.ttf', + 'space_shuttle': 'pdark.ttf', + 'thin': 'PixelFJVerdana12pt.ttf', + 'random': 'Seattle Avenue.ttf', + 'pixel': 'yoster.ttf' +} + +class Objects(): + def __init__(self, name, ms, sprite, x, y) -> None: + self.name = name + self.speed = ms + with open(f'art/images/{sprite}') as i: + self.sprite = pg.image.load(i) + self.x = x + self.y = y + self.hidden = False + self.rect = pg.Rect(self.x, self.y, self.sprite.get_width(), self.sprite.get_height()) + + def draw(self, screen): + if self.hidden: + return + self.rect.x, self.rect.y = self.x, self.y + screen.blit(self.sprite, self.rect) + +class NPC(Objects): + def __init__(self, name, ms, sprite, convo_act, x, y) -> None: + self.talking = False + self.hidden = True + super().__init__(name, ms, sprite, x, y) + self.conversation = Convo('Hello, you can shoot fireballs with f now.', convo_act, 'person') + + def talk(self, objects): + self.talking = True + objects[0][0].talking = True + self.conversation.hidden = False + + def draw(self, screen): + super().draw(screen) + if self.talking == True: + self.conversation.draw(screen) + + def update(self, keys, objects): + if self.talking: + self.conversation.update(keys, objects) + +class Convo(): + def __init__(self, text, convo_act, person, x = 140, y = 600, width = 1000, height = 100, font='simple', font_size = 20) -> None: + self.x = x + self.y = y + self.width = width + self.height = height + self.hidden = False + self.font = pg.font.Font(f'fonts/{fonts[font]}', font_size) + with open('art/images/label.png', 'r') as tb: + self.box = pg.image.load(tb) + self.box = pg.transform.scale(self.box, (width, height)) + self.labelRect = pg.Rect(self.x, self.y, self.width, self.height) + self.labelSurf = self.font.render(text, True, '#1E90FF') + + + def draw(self, screen): + if self.hidden: + return + self.box.blit(self.labelSurf, [ + self.labelRect.width/2 - self.labelSurf.get_rect().width/2, + self.labelRect.height/2 - self.labelSurf.get_rect().height/2 + ]) + screen.blit(self.box, self.labelRect) + + def update(self, keys, objects): + if keys[pg.K_SPACE]: + objects[0][0].book.addspell('fireball') + self.talking = False + objects[0][0].talking = False + self.hidden = True + + + + +class Fighter(Objects): + def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr) -> None: + super().__init__(name, ms, sprite, x, y) + self.health = health + self.damage = damage + self.level = level + self.attack_speed = asp + self.attack_range = atr + self.lastHurt = pg.time.get_ticks() + self.lastAttack = pg.time.get_ticks() + self.hurtCooldown = 0 + + +class MainCharacter(Fighter): + def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr) -> None: + super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr) + self.book = Book(0, 0, [], None, None) + self.talking = False + self.level = Level(1000, 38, level, 150, 40, f'will to live: {level}%', 'simple', 20) + self.health = Hearts(health, sprite=['fullheart.png', 'fullheart.png', 'fullheart.png', 'fullheart.png', 'fullheart.png'], x=900, y= 50, hurtCooldown=self.hurtCooldown) + + def draw(self, screen): + if self.hidden: + return + self.rect.x, self.rect.y = self.x, self.y + screen.blit(self.sprite, self.rect) + self.health.draw(screen) + self.level.draw(screen) + self.book.draw(screen) + + def hurt(self, damage, objects): + if not self.talking: + self.health.hurt(damage) + + def walk(self, keys, objects): + moveto = vec(0, 0) + if keys[pg.K_w] or keys[pg.K_UP]: + moveto += vec(0, -1) + if keys[pg.K_a] or keys[pg.K_LEFT]: + moveto += vec(-1, 0) + if keys[pg.K_s] or keys[pg.K_DOWN]: + moveto += vec(0, 1) + if keys[pg.K_d] or keys[pg.K_RIGHT]: + moveto += vec(1, 0) + if not moveto == vec(0, 0): + moveto.scale_to_length(self.speed) + self.x += moveto[0] / fps + self.y += moveto[1] / fps + touches = pg.sprite.spritecollideany(self, objects[1] + objects[2]) + if touches is not None: + self.x -= moveto[0]*1.5 / fps #change later + self.y -= moveto[1]*1.5 / fps #change later + if isinstance(touches, NPC): + touches.talk(objects) + + def attack(self, obj, moveto = vec(0,1)): + if self.lastAttack + self.attack_speed * 1000 < pg.time.get_ticks(): + if self.book.current_sp == 'fireball': + weapon = Fireball('fb1', 100, self.x, self.y, moveto, 5) + else: + return + obj[3].append(weapon) + self.lastAttack = pg.time.get_ticks() + + def update(self, keys, objects): + if not self.talking: + self.walk(keys, objects) + if keys[pg.K_f]: + self.attack(objects) + if self.health.health <= 0: + return False + else: + return True + +class Hearts(): + def __init__(self, health, sprite, x, y, hurtCooldown) -> None: + self.x = x + self.y = y + self.health = health + self.lastHurt = pg.time.get_ticks() + self.hurtCooldown = hurtCooldown + self.hidden = False + self.sprite=[] + for parts in sprite: + with open(f'art/images/{parts}') as i: + self.sprite.append(pg.image.load(i)) + self.rect = [] + for each in self.sprite: + self.rect.append(pg.Rect(self.x, self.y, each.get_width(), each.get_height())) + + def hurt(self,damage): + if self.lastHurt + self.hurtCooldown < pg.time.get_ticks(): + self.health -= damage + self.lastHurt = pg.time.get_ticks() + self.update() + + def draw(self, screen): + if self.hidden: + return + for i in range(0, 5): + self.rect[i].x, self.rect[i].y = self.x + i * 20, self.y + screen.blit(self.sprite[i], self.rect[i]) + + def update(self): + sprite = [] + for i in range(0, 5): + if self.health >= 4 + 4 * i: + sprite.append('fullheart.png') + elif self.health == 3 + 4 * i: + sprite.append('dreiviertelheart.png') + elif self.health >= 2 + 4 * i: + sprite.append('halfheart.png') + elif self.health >= 1 + 4 * i: + sprite.append('viertelheart.png') + elif self.health <= 4 * i: + sprite.append('noheart.png') + self.sprite = [] + for parts in sprite: + with open(f'art/images/{parts}') as i: + self.sprite.append(pg.image.load(i)) + + +class Level(): + def __init__(self, x, y, level, width, height, text, font, font_size) -> None: + self.x = x + self.y = y + self.level = level + self.width = width + self.height = height + self.font = pg.font.Font(f'fonts/{fonts[font]}', font_size) + self.hidden = False + with open('art/images/label.png', 'r') as tb: + self.box = pg.image.load(tb) + self.box = pg.transform.scale(self.box, (width, height)) + self.labelRect = pg.Rect(self.x, self.y, self.width, self.height) + self.labelSurf = self.font.render(text, True, '#1E90FF') + + def draw(self, screen): + self.box.blit(self.labelSurf, [ + self.labelRect.width / 2 - self.labelSurf.get_rect().width / 2, + self.labelRect.height / 2 - self.labelSurf.get_rect().height / 2 + ]) + screen.blit(self.box, self.labelRect) + +class Book(): + def __init__(self, x, y, spells, current_spell, current_shield) -> None: + with open(f'art/images/book.png') as i: + self.sprite = pg.image.load(i) + self.sprite = pg.transform.scale(self.sprite, (1280, 720)) + self.x = x + self.y = y + self.hidden = True + self.rect = pg.Rect(self.x, self.y, self.sprite.get_width(), self.sprite.get_height()) + self.sp_list = spells + self.current_sp = current_spell + + def draw(self, screen): + if self.hidden: + return + self.rect.x, self.rect.y = self.x, self.y + screen.blit(self.sprite, self.rect) + + def addspell(self, spell): + if spell not in self.sp_list: + self.sp_list.append(spell) + self.current_sp = spell + def update(self): + pass + + +class Mobs(Fighter): + def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr, drops) -> None: + super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr) + self.drops = drops * (self.level / 2) + +class Skeleton(Mobs): + def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr, drops=0) -> None: + super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr, drops) + + def chase(self, obj): + x = obj[0][0].x + y = obj[0][0].y + moveto = vec(x, y) - vec(self.x, self.y) + if not (moveto).length() <= self.attack_range: + moveto.scale_to_length(self.speed) + self.x += moveto[0] / fps + self.y += moveto[1] / fps + else: + self.attack(moveto, obj) + + def attack(self, moveto, obj): + if self.lastAttack + self.attack_speed * 1000 < pg.time.get_ticks(): + obj[3].append(Arrow("arrow", 200, self.x, self.y, moveto, self.damage)) + self.lastAttack = pg.time.get_ticks() + + def hurt(self, damage, objects): + self.health -= damage + if self.health <= 0: + self.hidden = True + objects[1].remove(self) + + def update(self, obj): + self.chase(obj) + + +class Weapons(Objects): + def __init__(self, name, ms, sprite, x, y, moveto, damage) -> None: + super().__init__(name, ms, sprite, x, y) + self.moveto = moveto + self.damage = damage + pos = vec(1,0) + angle = pos.angle_to(moveto) + with open(f'art/images/{sprite}') as i: + self.sprite = pg.transform.rotate(pg.image.load(i), -angle) + + def die(self, objects, kills): + touches = pg.sprite.spritecollideany(self, objects[0] + objects[1]) + if touches is not None and isinstance(touches, kills): + touches.hurt(self.damage, objects) + self.hidden = True + objects[3].remove(self) + +class Spells(Weapons): + def __init__(self, name, ms, sprite, x, y, moveto, damage) -> None: + super().__init__(name, ms, sprite, x, y, moveto, damage) + +class Fireball(Spells): + def __init__(self, name, ms, x, y, moveto, damage, sprite = 'fireball.png') -> None: + super().__init__(name, ms, sprite, x, y, moveto, damage) + + def move(self): + self.moveto.scale_to_length(self.speed) + self.x += self.moveto[0] / fps + self.y += self.moveto[1] / fps + + def update(self, objects): + self.move() + self.die(objects, Mobs) + +class Arrow(Weapons): + def __init__(self, name, ms, x, y, moveto, damage, sprite = 'arrow.png') -> None: + super().__init__(name, ms, sprite, x, y, moveto, damage) + + def move(self): + self.moveto.scale_to_length(self.speed) + self.x += self.moveto[0] / fps + self.y += self.moveto[1] / fps + + def update(self, objects): + self.move() + self.die(objects, MainCharacter)