diff --git a/.gitignore b/.gitignore index b7f3878..12dd376 100644 --- a/.gitignore +++ b/.gitignore @@ -217,4 +217,4 @@ __marimo__/ # Data data/ -test.py \ No newline at end of file +der_test.py \ No newline at end of file diff --git a/scripts/animation.py b/scripts/animation.py new file mode 100644 index 0000000..3179657 --- /dev/null +++ b/scripts/animation.py @@ -0,0 +1,125 @@ +class Animation: + def __init__(self, images, image_duration=5, loop=True): + """ + Initialisiert eine Animation mit einer Liste von Bildern. + + Anforderungen (damit die Tests bestehen): + - images speichern + - image_duration speichern + - loop speichern + - frame startet bei 0 + - done startet bei False + """ + # TODO: Implementieren + self.images = images + self.image_duration = image_duration + self.loop = loop + self.frame = 0 + self.done = False + + def copy(self): + """ + Erstellt eine Kopie der Animation. + + Anforderungen: + - Rückgabewert ist ein neues Animation-Objekt (nicht dasselbe Objekt) + - gleiche images / image_duration / loop + - neue Animation startet wieder bei frame = 0 und done = False + """ + # TODO: Implementieren + copy_animation = Animation(self.images, self.image_duration, self.loop) + return copy_animation + def update(self): + """ + Aktualisiert die Animation um einen Frame weiter. + + Anforderungen: + - Wenn loop=True: + frame wird erhöht und springt am Ende wieder auf 0 + - Wenn loop=False: + frame wird erhöht, aber bleibt am Ende stehen + done wird True, sobald das letzte Bild erreicht ist (siehe Tests) + """ + # TODO: Implementieren + # SCHRITT A: Modulo (Der Loop-Trick) + # Sorgt dafür, dass wir nie über 14 hinausgehen (0 bis 14) + if self.loop: + gesamt_dauer = len(self.images) * self.image_duration # 5 * 5 = 25 Frames pro Durchlauf + self.frame = (self.frame+1) % gesamt_dauer + else: + self.frame = min(self.frame + 1, len(self.images) * self.image_duration -1) + if self.frame >= self.image_duration * (len(self.images) - 1): + self.done = True + def img(self): + """ + Gibt das aktuelle Bild der Animation zurück. + + Anforderungen: + - Das aktuelle Bild hängt von frame und image_duration ab. + - Beispiel: image_duration=2 + frame 0,1 -> images[0] + frame 2,3 -> images[1] + frame 4,5 -> images[2] + """ + # TODO: Implementieren + pass + +if __name__ == "__main__": + + import unittest + + class TestAnimation(unittest.TestCase): + + def setUp(self): + self.images = ["img1", "img2", "img3"] + + def test_initialization(self): + anim = Animation(self.images, image_duration=2, loop=False) + self.assertEqual(anim.images, self.images) + self.assertEqual(anim.image_duration, 2) + self.assertFalse(anim.loop) + self.assertEqual(anim.frame, 0) + self.assertFalse(anim.done) + + def test_copy(self): + anim = Animation(self.images, image_duration=3, loop=False) + anim_copy = anim.copy() + + self.assertIsNot(anim, anim_copy) + self.assertEqual(anim_copy.images, self.images) + self.assertEqual(anim_copy.image_duration, 3) + self.assertFalse(anim_copy.loop) + self.assertEqual(anim_copy.frame, 0) + + def test_looping_update(self): + anim = Animation(self.images, image_duration=1, loop=True) + + for _ in range(3): + anim.update() + + # 3 Bilder * 1 Frame pro Bild = 3 Frames total -> wieder bei 0 + self.assertEqual(anim.frame, 0) + + def test_non_looping_update_and_done(self): + anim = Animation(self.images, image_duration=1, loop=False) + + anim.update() + anim.update() + anim.update() + + # Ohne Loop bleibt er beim letzten Frame (2) stehen + # und done soll True sein (siehe Logik in der Aufgabenbeschreibung) + self.assertTrue(anim.done) + self.assertEqual(anim.frame, 2) + + def test_img_selection(self): + anim = Animation(self.images, image_duration=2, loop=True) + + anim.update() # frame 1 + self.assertEqual(anim.img(), "img1") + + anim.update() # frame 2 + self.assertEqual(anim.img(), "img2") + + + unittest.main() diff --git a/scripts/tilemap.py b/scripts/tilemap.py index 2a03c03..b27d6d1 100644 --- a/scripts/tilemap.py +++ b/scripts/tilemap.py @@ -13,9 +13,14 @@ class Tilemap: def render(self, surface:pg.Surface, offset:tuple=(0,0)): for tile in self.offgrid_tiles: surface.blit(self.game.assets[tile['type']][tile['variant']], (tile['pos'][0] - offset[0], tile['pos'][1] - offset[1])) - for location in self.tilemap: - tile = self.tilemap[location] - surface.blit(self.game.assets[tile['type']][tile['variant']], (tile['pos'][0] * self.tile_size - offset[0], tile['pos'][1] * self.tile_size - offset[1])) + for x in range(offset[0] // self.tile_size, (offset[0] + surface.get_width()) // self.tile_size + 1): + for y in range(offset[1] // self.tile_size, (offset[1] + surface.get_height()) // self.tile_size + 1): + location_key = f"{x};{y}" + if location_key in self.tilemap: + tile = self.tilemap[location_key] + surface.blit(self.game.assets[tile['type']][tile['variant']], (tile['pos'][0] * self.tile_size - offset[0], + tile['pos'][1] * self.tile_size - offset[1])) + def tiles_around(self, pos): tiles = [] @@ -25,6 +30,7 @@ class Tilemap: if check_location in self.tilemap: tiles.append(self.tilemap[check_location]) return tiles + def physics_rects_around(self, pos): # Erzeuge eine leere Liste für die Rechtecke rects = [] diff --git a/test.py b/test.py deleted file mode 100644 index e69de29..0000000