class Animation: def __init__(self, images: list, image_duration: int = 5, loop: bool = 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: list = images self.image_duration: int = image_duration self.loop: bool = loop self.frame: int = 0 self.done: bool = False def copy(self) -> "Animation": """ 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) -> None: """ 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 """ Gibt das aktuelle Bild der Animation zurück. """ return self.images[int(self.frame / self.image_duration)] 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()