Feb-28-2021, 03:02 PM
(This post was last modified: Feb-28-2021, 03:51 PM by deanhystad.)
I was having a tough time understanding the lasers. Took the name too literally and expected a line that grows in length and didn't see how your rectangles would ever do something like that. But your lasers are projectiles which is fairly easy. The thing you are missing is the after() method.
import math import tkinter as tk import random window_height = 400 window_width = 720 class Laser: instances = [] colors = ('red', 'yellow', 'blue', 'orange', 'green', 'purple', 'pink', 'brown', 'grey') @classmethod def update(cls): """Move all the lasers. Remove offscreen lasers""" cls.instances = [laser for laser in cls.instances if laser.move()] def __init__(self, x, y, dx, dy): self.id = canvas.create_line(x, y, x, y, width=3, fill=random.choice(self.colors)) self.x = x self.y = y self.dx = dx self.dy = dy self.length = 0 self.instances.append(self) def move(self): """Update laser position. Return True if visible""" self.length = min(30, self.length+1) self.x += self.dx self.y += self.dy x = self.x - self.length * self.dx y = self.y - self.length * self.dy if 0 <= x <= window_width and 0 <= y <= window_height: canvas.coords(self.id, int(x), int(y), int(self.x), int(self.y)) return True canvas.delete(self.id) return False def update_lasers(): """Periodically update the lasers""" Laser.update() root.after(10, update_lasers) def fire(*args): """Fire a rainbow starburst of lasers""" step = random.randint(1, 60) for angle in range(step//2, 360, step): angle = math.radians(angle) Laser(360, 200, math.sin(angle), math.cos(angle)) root = tk.Tk() canvas = tk.Canvas(root, width=window_width, height=window_height) canvas.pack() root.bind("<space>", fire) update_lasers() root.mainloop()