def __init__(self): self.pos = Point(0.0, 0.0) self.vel = Point(0.0, 0.0) self.theta = 0.0 self.theta_vel = 0.0 self.radius = 0.0 self.orig = [] self.pts = [] self.alive = True self.wrap = Point(True, True)
def init_edge(self): side = randint(0, 3) if side == 0: self.pos = Point(25, random() * ScreenSize.height) elif side == 1: self.pos = Point(ScreenSize.width - 25, random() * ScreenSize.height) elif side == 2: self.pos = Point(random() * ScreenSize.width, 25) else: self.pos = Point(random() * ScreenSize.width, ScreenSize.height - 25)
def __init__(self, sprite): self.color = [255, 255, 255] self.fade = 15 self.alive = True self.sides = [] for start, end in zip(sprite.orig[1:], sprite.orig[:-1]): side = Sprite() side.orig = [start, end] side.pos = Point(sprite.pos.x, sprite.pos.y) side.vel = Point((random() * 4) - 2, (random() * 4) - 2) side.theta = sprite.theta self.sides.append(side)
def __init__(self): Sprite.__init__(self) self.speed = 0.27 self.decay = 0.98 self.pos = Point(350, 200) self.time_to_respawn = 0 self.init_shape()
def set_points(self, xpts, ypts, connect=False): self.orig = [Point(x, y) for x, y in zip(xpts, ypts)] if connect: self.orig.append(self.orig[0]) # Calculate bounding circle radius for pt in self.orig: dist = math.sqrt((pt.x**2) + (pt.y**2)) if dist > self.radius: self.radius = dist
def fire_bullet(self, pt): self.time_to_fire = 30 # Fire bullet toward specific point if self.size == Saucer.Small: # Add a little bit of error dest = Point(pt.x, pt.y) dest.x += randint(-20, 20) dest.y += randint(-20, 20) # Calculate theta and velocity toward point theta = math.atan2(dest.x - self.pos.x, self.pos.y - dest.y) vel = Point(math.sin(theta) * 5.0, -math.cos(theta) * 5.0) return Bullet(self.pos.x + vel.x, self.pos.y + vel.y, theta) # Fire bullet in random direction else: theta = random() * (2.0 * math.pi) vel = Point(math.sin(theta) * 10.0, -math.cos(theta) * 10.0) return Bullet(self.pos.x + vel.x, self.pos.y + vel.y, theta)
def contains(self, pt): # Even # of edge crossings = outside polygon # Odd # of edge crossing = inside polygon n = len(self.pts) inside = False p1 = Point(self.pts[0].x, self.pts[0].y) # Count edge crossings by casting a ray from inside the polygon for i in range(n + 1): p2 = self.pts[i % n] if pt.y > min(p1.y, p2.y) and pt.y <= max( p1.y, p2.y) and pt.x <= max(p1.x, p2.x): if p1.y != p2.y: xinters = (pt.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x if p1.x == p2.x or pt.x <= xinters: inside = not inside p1.x, p1.y = p2.x, p2.y return inside
def update(self): # Update position based on velocity self.pos.x += self.vel.x self.pos.y += self.vel.y # Update angle based on velocity self.rotate(self.theta_vel) # Wrap position within screen bounds if self.wrap.x: self.pos.x = wrap_x(self) if self.wrap.y: self.pos.y = wrap_y(self) # Update vertices based on pos and angle self.pts = [] for pt in self.orig: newx = (pt.x * math.cos(self.theta)) - ( pt.y * math.sin(self.theta)) + self.pos.x newy = (pt.x * math.sin(self.theta)) + ( pt.y * math.cos(self.theta)) + self.pos.y self.pts.append(Point(newx, newy))
def vapor_bounds_range(self): bounds = [] size = int(abs(self.vel.x) + abs(self.vel.y)) if size < 6: size = 6 for dy in range(size): pts = [] gap = 3 y = self.orig[1].y + dy for x in range(int(self.orig[1].x + gap), int(self.orig[2].x - gap), 1): newx = (x * math.cos(self.theta)) - ( y * math.sin(self.theta)) + self.pos.x newy = (x * math.sin(self.theta)) + ( y * math.cos(self.theta)) + self.pos.y pts.append(Point(newx, newy)) bounds.append(pts) return bounds
def respawn(self): self.time_to_respawn = 100 self.pos = Point(350, 200) self.vel = Point(0, 0)