def get_separating_axis(poly1: list, poly2: list) -> dict: axes = get_axes(poly1, poly2) sep_dist = float('-inf') sep_axis = None t = 0 for axis in axes: amin, amax = get_projection(poly1, axis) bmin, bmax = get_projection(poly2, axis) ax = Vector(*axis) pygame.draw.line(pygame.display.get_surface(), (192, 32, 32), (ax * amin) + (400, 300), (ax * amax) + (400, 300)) pygame.draw.line(pygame.display.get_surface(), (32, 32, 192), (ax * bmin) + (400, 300), (ax * bmax) + (400, 300)) t += 1 dist = max(amin, bmin) - min(bmax, amax) # dist = max(bmin, amin) - min(amax, bmax) if (amax < bmin) or (bmax < amin): return {0: False, 1: Vector(*axis), 2: dist} if 0 > dist > sep_dist: sep_dist = dist sep_axis = axis return {0: True, 1: Vector(*sep_axis), 2: sep_dist}
def __init__(self, actors: list): self.actors = [] self.visible = [] self.minimum = Vector.zero() self.maximum = Vector.one() self.view = View(self) self.add_actors(actors)
def play(cls, game: type) -> None: dispatcher = Dispatcher([ SceneOption.BackButton(Vec(100, 540), Vec(100, 40), "Back", None) ]) room = Room([cls.Starship(Vector(300, 200), 0, Vector(50, 50))]) textcolor = (0, 0, 92) fillcolor = (0, 0, 16) BitmapFont.set_colors(BitmapFont.large, fillcolor, textcolor) while game.scene is cls: Display.clear(fillcolor) surface = Display.surface() events = pygame.event.get() keys = pygame.key.get_pressed() dispatcher.process_events(events, keys, game) room.update(events, keys, room.view, game) BitmapFont.render(surface, "Game", BitmapFont.large, (0, 0)) room.view.render(surface) for actor in room.actors: actor.default_render(surface, room.view) for gui in dispatcher.listeners: gui.basic_render(surface) Display.on_screen(60)
def __init__(self, room: 'Room'): super(View, self).__init__(Vector.zero(), 0.0, Vector(*self.size), View.refpoints) self.motion = Vector.zero() self.room = room self.anchor = Anchor.top_left self.paths = {} self.set_path('transition', View.transition, AssignMode.direct_value, 0) self.parallaxes = [ BackScroller(View.starfield, self.size, [77, 14]), BackScroller(View.starfield, self.size, [28, 56]), ]
def get_position(self, ratio: float, from_angle: float = 0.0) -> Vector: """Returns a position in this path relative to given ratio.""" ratio %= 1.0 ratio += from_angle / 360.0 ratio %= 1.0 angle = 360.0 * ratio return Vector.length_angle(self.radius, angle)
def __init__(self, position: Vector, rotation: float, scale: Vector, refpoints: list): super(Polygon, self).__init__() self.position = position self.rotation = rotation self.scale = scale self.refpoints = refpoints self.points = [Vector(*point) for point in refpoints] self.draw_points = [v.ixy for v in self.points]
def __init__(self, bgi: pygame.Surface, surface_size: tuple, view_position=(0, 0)): self.back = bgi self.view_w, self.view_h = surface_size self.view_x, self.view_y = view_position self.image_w, self.image_h = bgi.get_size() self.origin_x = 0 self.origin_y = 0 self.widths = [] self.heights = [] self.update(Vector.zero())
def circle_poly(cls, circle: 'Circle', poly: 'Polygon') -> dict: test_distance = -1 closest_vector = None vector_offset = poly.position - circle.position vectors = poly.points if len(vectors) == 2: temp = (vectors[1] - vectors[0]).perpend() round(temp) vectors.append(vectors[1] + temp) # find closest vertex for i in range(len(vectors)): vec = poly.position + vectors[i] dist = (circle.position - vec).hypot if test_distance == -1 or dist < test_distance: test_distance = dist closest_vector = vec normal_axis = (closest_vector - circle.position).normalize() # project polygon's points min1 = normal_axis.dot(vectors[0]) max1 = min1 for j in range(1, len(vectors)): med = normal_axis.dot(vectors[j]) min1 = min(min1, med) max1 = max(med, max1) # project the circle max2 = circle.radius min2 = -circle.radius offset = normal_axis.dot(vector_offset) min1 += offset max1 += offset a = min1 - max2 b = min2 - max1 if a > 0 or b > 0: return SAT_NO_COLLISION # find the normal axis for each point and project for i in range(len(vectors)): normal_axis = cls.find_normal_axis(vectors, i) min1 = normal_axis.dot(vectors[0]) max1 = min1 for j in range(1, len(vectors)): med = normal_axis.dot(vectors[j]) min1 = min(min1, med) max1 = max(med, max2) max2 = circle.radius min2 = -circle.radius offset = normal_axis.dot(vector_offset) min1 += offset max1 += offset a = min1 - max2 b = min2 - max1 if a > 0 or b > 0: return SAT_NO_COLLISION return { SAT.overlapped: True, SAT.sep_axis: Vector(normal_axis.x * (max2 - min1) * -1, normal_axis.y * (max2 - min1) * -1), SAT.face_normal: normal_axis }
def __init__(self, image: pygame.Surface, scrollratio: Vector): self.image = image self.scrollratio = scrollratio self.scrollpos = Vector.zero()
def update(self, events: list, keys: tuple, view: 'View', game: type) -> None: """Updates all objects.""" indices = range(len(self.actors)) # events for event in events: if event.type == c.KEYDOWN: cmd = Room.get_command(event) for i in indices: self.actors[i].on_command(cmd, game, self) elif event.type == c.KEYUP: for i in indices: self.actors[i].on_keyup(event.key, game, self) elif event.type == c.MOUSEMOTION: rpos = Vector(*event.pos) apos = self.view.abs_point(event.pos) rel = Vector(*event.rel) for i in indices: self.actors[i].on_mouse_move(apos, rpos, rel, game, self) elif event.type == c.MOUSEBUTTONDOWN: rpos = Vector(*event.pos) apos = self.view.abs_point(event.pos) for i in indices: { 1: self.actors[i].on_left_click, 2: self.actors[i].on_middle_click, 3: self.actors[i].on_right_click, 4: self.actors[i].on_roll_up, 5: self.actors[i].on_roll_down, }[event.button](apos, rpos, game, self) # motion self.view.animate(game) for i in indices: self.actors[i].on_keydown(keys, game, self) self.actors[i].animate(game) self.actors[i].update(view) # collision for j in indices: a = self.actors[j] for k in indices[j + 1:]: b = self.actors[k] info = a.collide_with(b) BitmapFont.set_colors(BitmapFont.small, (0, 0, 0), (255, 255, 255)) BitmapFont.render(pygame.display.get_surface(), "{}".format(list(info.values())), BitmapFont.small, Vector(0, 300)) if info[SAT.overlapped]: a.on_collision(b, info, game, self) b.on_collision(a, info, game, self) # select visible for actor in self.actors: info = self.view.collide_with(actor) if info[SAT.overlapped]: if actor not in self.visible: self.visible.append(actor) actor.on_enter_view(self.view, game, self) else: if actor in self.visible: self.visible.remove(actor) actor.on_leave_view(self.view, game, self) for actor in self.actors: actor.on_prerender(game, self)
def __init__(self, refpoints): super(Actor, self).__init__(Vector.zero(), 0.0, Vector.one(), refpoints) self.motion = Vector.zero() self.command = None self.paths = {}
def abs_point(self, point: tuple) -> Vector: x, y = self.position return Vector(point[0] + x, point[1] + y)
def rel_point(self, point: tuple) -> Vector: x, y = self.position return Vector(point[0] - x, point[1] - y)