diff --git a/.gitignore b/.gitignore index 8d7e475..f900edf 100644 --- a/.gitignore +++ b/.gitignore @@ -1665,3 +1665,11 @@ .venv/lib/python3.12/site-packages/pygame.libs/libvorbisenc-bb396c4a.so.2.0.12 .venv/lib/python3.12/site-packages/pygame.libs/libvorbisfile-8aced0b7.so.3.3.8 .venv/lib/python3.12/site-packages/pygame.libs/libwebp-3bee5bfa.so.7.1.8 +__pycache__/Tilemap.cpython-312.pyc +__pycache__/Tileset.cpython-312.pyc +__pycache__/Tiletype.cpython-312.pyc +__pycache__/Utils.cpython-312.pyc +modules/__pycache__/Tilemap.cpython-312.pyc +modules/__pycache__/Tileset.cpython-312.pyc +modules/__pycache__/Tiletype.cpython-312.pyc +modules/__pycache__/Utils.cpython-312.pyc diff --git a/Tilemap.py b/Tilemap.py new file mode 100644 index 0000000..64c3aa0 --- /dev/null +++ b/Tilemap.py @@ -0,0 +1,62 @@ +import pygame +import random +import Tileset + +class Tilemap(object): + def __init__(self) -> None: + self.tileset = Tileset.TileSet("tileset.png", (255,0,255), 32, 32) + self.tileset.add_tile("grass", 0, 0) + self.tileset.add_tile("mud", 32, 0) + self.tileset.add_tile("water", 64,0) + self.tileset.add_tile("block", 0, 32) + + self.camera_x = 0 + self.camera_y = 0 + + self.width = 30 + self.height = 25 + + self.tiles = list() + + for i in range(0, self.height): + self.tiles.append(list()) + for j in range(0, self.width): + x = random.randint(0,4) + if x == 0: + self.tiles[i].append("grass") + elif x == 1: + self.tiles[i].append("water") + elif x == 2: + self.tiles[i].append("mud") + else: + self.tiles[i].append("block") + + def render(self, screen): + + for y in range(0, int(screen.get_height() / self.tileset.tile_height) + 1): + ty = y + self.camera_y + if ty >= self.height or ty < 0: + continue + + line = self.tiles[ty] + + for x in range(0, int(screen.get_width() / self.tileset.tile_width)+ 1): + tx = x + self.camera_x + if tx >= self.width or tx < 0: + continue + tilename = line[tx] + tile = self.tileset.get_tile(tilename) + + if tile is not None: + screen.blit(self.tileset.image, (x * self.tileset.tile_width, y * self.tileset.tile_height), tile.rect) + + def handle_input(self, key): + if key == pygame.K_LEFT: + self.camera_x += 1 + if key == pygame.K_RIGHT: + self.camera_x -= 1 + + if key == pygame.K_UP: + self.camera_y += 1 + if key == pygame.K_DOWN: + self.camera_y -= 1 \ No newline at end of file diff --git a/Tileset.py b/Tileset.py new file mode 100644 index 0000000..783fd78 --- /dev/null +++ b/Tileset.py @@ -0,0 +1,19 @@ +import pygame +import Tiletype +import Utils + +class TileSet(object): + def __init__(self, image, colorkey, tile_width, tile_height) -> None: + self.image = Utils.load_image(image, colorkey) + self.tile_width = tile_width + self.tile_height = tile_height + self.tile_types = dict() + + def add_tile(self, name, start_x, start_y): + self.tile_types[name] = Tiletype.TileType(name, start_x, start_y, self.tile_width, self.tile_height) + + def get_tile(self, name): + try: + return self.tile_types[name] + except KeyError: + return None diff --git a/Tiletype.py b/Tiletype.py new file mode 100644 index 0000000..4fa1568 --- /dev/null +++ b/Tiletype.py @@ -0,0 +1,6 @@ +import pygame + +class TileType(object): + def __init__(self, name, start_x, start_y, width, height) -> None: + self.name = name + self.rect = pygame.rect.Rect(start_x, start_y, width, height) \ No newline at end of file diff --git a/Utils.py b/Utils.py new file mode 100644 index 0000000..c3abcbf --- /dev/null +++ b/Utils.py @@ -0,0 +1,22 @@ +import pygame + +# Hilfsfunktion, um ein Bild zu laden: +def load_image(filename, colorkey=None): + # Pygame das Bild laden lassen. + image = pygame.image.load(filename) + + # Das Pixelformat der Surface an den Bildschirm (genauer: die screen-Surface) anpassen. + # Dabei die passende Funktion verwenden, je nach dem, ob wir ein Bild mit Alpha-Kanal haben oder nicht. + if image.get_alpha() is None: + image = image.convert() + else: + image = image.convert_alpha() + + # Colorkey des Bildes setzen, falls nicht None. + # Bei -1 den Pixel im Bild an Position (0, 0) als Colorkey verwenden. + if colorkey is not None: + if colorkey is -1: + colorkey = image.get_at((0,0)) + image.set_colorkey(colorkey, pygame.RLEACCEL) + + return image \ No newline at end of file diff --git a/main.py b/main.py index e1da01d..0d04e39 100644 --- a/main.py +++ b/main.py @@ -1,17 +1,62 @@ import pygame +import Tilemap pygame.init() -MAINSCREEN_SIZE = (800,600) - -pygame.display.set_caption("Test-Sidescroller") -pygame.display.set_mode(MAINSCREEN_SIZE) - -gamestate = True +WEISS = (255,255,255) +SCHWARZ = (0,0,0) -while(gamestate): - for event in pygame.event.get(): - if (event.type == pygame.QUIT): - print("Programm wird geschlossen!") - gamestate = False \ No newline at end of file +def main(): + # Initialisieren aller Pygame-Module und + # Fenster erstellen (wir bekommen eine Surface, die den Bildschirm repräsentiert). + pygame.init() + screen = pygame.display.set_mode((800, 600)) + + # Titel des Fensters setzen, Mauszeiger nicht verstecken und Tastendrücke wiederholt senden. + pygame.display.set_caption("Pygame-Tutorial: Tilemap") + pygame.mouse.set_visible(1) + pygame.key.set_repeat(1, 30) + + # Clock Objekt erstellen, das wir benötigen, um die Framerate zu begrenzen. + clock = pygame.time.Clock() + + # Wir erstellen eine Tilemap. + map = Tilemap.Tilemap() + + # Die Schleife, und damit unser Spiel, läuft solange running == True. + running = True + while running: + # Framerate auf 30 Frames pro Sekunde beschränken. + # Pygame wartet, falls das Programm schneller läuft. + clock.tick(30) + + # screen Surface mit Schwarz (RGB = 0, 0, 0) füllen. + screen.fill((0, 0, 0)) + + # Alle aufgelaufenen Events holen und abarbeiten. + for event in pygame.event.get(): + # Spiel beenden, wenn wir ein QUIT-Event finden. + if event.type == pygame.QUIT: + running = False + + # Wir interessieren uns auch für "Taste gedrückt"-Events. + if event.type == pygame.KEYDOWN: + # Wenn Escape gedrückt wird posten wir ein QUIT-Event in Pygames Event-Warteschlange. + if event.key == pygame.K_ESCAPE: + pygame.event.post(pygame.event.Event(pygame.QUIT)) + + # Alle Tastendrücke auch der Tilemap mitteilen. + map.handle_input(event.key) + + # Die Tilemap auf die screen-Surface rendern. + map.render(screen) + + # Inhalt von screen anzeigen + pygame.display.flip() + + +# Überprüfen, ob dieses Modul als Programm läuft und nicht in einem anderen Modul importiert wird. +if __name__ == '__main__': + # Unsere Main-Funktion aufrufen. + main() \ No newline at end of file diff --git a/tileset.png b/tileset.png new file mode 100644 index 0000000..325a2fa Binary files /dev/null and b/tileset.png differ