Merge pull request 'Development' (#57) from Development into main

Reviewed-on: InfoProjekt/game#57
This commit is contained in:
Spafi 2024-03-03 12:28:45 +00:00
commit 6fce7e0fd2
95 changed files with 960 additions and 0 deletions

BIN
.idea/InfoProjekt.xlsx generated Normal file

Binary file not shown.

44
.idea/ideas.txt generated Normal file
View file

@ -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 (?)

51
.idea/storyline.txt generated Normal file
View file

@ -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

53
READ.ME Normal file
View file

@ -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

BIN
art/image files/exit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

BIN
art/image files/field.kra Normal file

Binary file not shown.

BIN
art/image files/field.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

BIN
art/image files/mauer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

BIN
art/image files/options.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

BIN
art/image files/set1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
art/images/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

BIN
art/images/blau1.kra Normal file

Binary file not shown.

BIN
art/images/blau1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
art/images/blau2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
art/images/blau3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
art/images/book.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
art/images/dirt1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
art/images/dirt2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

BIN
art/images/fireball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

BIN
art/images/fullheart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

BIN
art/images/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
art/images/halfheart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

BIN
art/images/label.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

BIN
art/images/noheart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

BIN
art/images/oldman.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

BIN
art/images/reddy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

BIN
art/images/river1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
art/images/rot1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
art/images/rot2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
art/images/rot3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
art/images/start.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
art/images/textbox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

BIN
art/images/viertelheart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

230
classes.py Normal file
View file

@ -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)

7
config.json Normal file
View file

@ -0,0 +1,7 @@
{
"screen":
{
"res":[1280, 720],
"fullscreen": false
}
}

BIN
fonts/3D-Pixel.ttf Normal file

Binary file not shown.

BIN
fonts/8bitlim.ttf Normal file

Binary file not shown.

BIN
fonts/8bitlimo.ttf Normal file

Binary file not shown.

BIN
fonts/8bitlimr.ttf Normal file

Binary file not shown.

BIN
fonts/8blimro.ttf Normal file

Binary file not shown.

BIN
fonts/ARCADECLASSIC.TTF Normal file

Binary file not shown.

BIN
fonts/Beyond Wonderland.ttf Normal file

Binary file not shown.

BIN
fonts/Digitag.ttf Normal file

Binary file not shown.

BIN
fonts/DisposableDroidBB.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
fonts/Endalian Script.ttf Normal file

Binary file not shown.

BIN
fonts/FREAKSOFNATURE.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
fonts/Halo3.ttf Normal file

Binary file not shown.

BIN
fonts/INVASION2000.TTF Normal file

Binary file not shown.

BIN
fonts/Karma Future.otf Normal file

Binary file not shown.

BIN
fonts/Karma Suture.otf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
fonts/Merchant Copy.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/MoriaCitadel.TTF Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/Seattle Avenue.ttf Normal file

Binary file not shown.

BIN
fonts/SeattleAvenue.otf Normal file

Binary file not shown.

BIN
fonts/astron boy italic.otf Normal file

Binary file not shown.

BIN
fonts/astron boy video.otf Normal file

Binary file not shown.

BIN
fonts/astron boy wonder.otf Normal file

Binary file not shown.

BIN
fonts/astron boy.otf Normal file

Binary file not shown.

BIN
fonts/dpcomic.ttf Normal file

Binary file not shown.

BIN
fonts/ka1.ttf Normal file

Binary file not shown.

BIN
fonts/kirbyss.ttf Normal file

Binary file not shown.

BIN
fonts/manaspc.ttf Normal file

Binary file not shown.

BIN
fonts/medieval.ttf Normal file

Binary file not shown.

BIN
fonts/nasalization-rg.otf Normal file

Binary file not shown.

BIN
fonts/neuropol.otf Normal file

Binary file not shown.

BIN
fonts/papercut.ttf Normal file

Binary file not shown.

BIN
fonts/pcsenior.ttf Normal file

Binary file not shown.

BIN
fonts/pdark.ttf Normal file

Binary file not shown.

BIN
fonts/yoster.ttf Normal file

Binary file not shown.

214
main.py Normal file
View file

@ -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()

BIN
test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 KiB

BIN
test1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
test2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

361
viecher.py Normal file
View file

@ -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)