def line(x1, y1, x2, y2, other=None): """ Return a list of objects colliding with a line segment. Arguments: - ``x1`` -- The horizontal position of the first endpoint of the line segment. - ``y1`` -- The vertical position of the first endpoint of the line segment. - ``x2`` -- The horizontal position of the second endpoint of the line segment. - ``y2`` -- The vertical position of the second endpoint of the line segment. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room x = min(x1, x2) y = min(y1, y2) w = abs(x2 - x1) h = abs(y2 - y1) others = room.get_objects_at(x , y, w, h) collisions = [] mask_id = ("line_masks", w, h) mask = r.cache.get(mask_id) if mask is None: mask = [[False for j in six.moves.range(h)] for i in six.moves.range(w)] m = h / w b = y1 - m * x1 for i in six.moves.range(len(mask)): j = int(round(m * i + b)) if 0 <= j < len(mask[i]): mask[i][j] = True r.cache.add(mask_id, mask) for obj in others: if (r.o_is_other(obj, other) and masks_collide(x, y, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def line(x1, y1, x2, y2, other=None): """ Return a list of objects colliding with a line segment. Arguments: - ``x1`` -- The horizontal position of the first endpoint of the line segment. - ``y1`` -- The vertical position of the first endpoint of the line segment. - ``x2`` -- The horizontal position of the second endpoint of the line segment. - ``y2`` -- The vertical position of the second endpoint of the line segment. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.Object.collision` for more information. """ room = sge.game.current_room x = min(x1, x2) y = min(y1, y2) w = abs(x2 - x1) h = abs(y2 - y1) others = room.get_objects_at(x, y, w, h) collisions = [] mask_id = ("line_masks", w, h) mask = r.cache.get(mask_id) if mask is None: mask = [[False for j in six.moves.range(h)] for i in six.moves.range(w)] m = h / w b = y1 - m * x1 for i in six.moves.range(len(mask)): j = int(round(m * i + b)) if 0 <= j < len(mask[i]): mask[i][j] = True r.cache.add(mask_id, mask) for obj in others: if (r.o_is_other(obj, other) and masks_collide(x, y, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def line(x1, y1, x2, y2, other=None): """ Return a list of objects colliding with a line segment. Arguments: - ``x1`` -- The horizontal position of the first endpoint of the line segment. - ``y1`` -- The vertical position of the first endpoint of the line segment. - ``x2`` -- The horizontal position of the second endpoint of the line segment. - ``y2`` -- The vertical position of the second endpoint of the line segment. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room x = min(x1, x2) y = min(y1, y2) w = abs(x2 - x1) + 1 h = abs(y2 - y1) + 1 if w <= 1 or h <= 1: return rectangle(x, y, w, h) others = room.get_objects_at(x, y, w, h) collisions = [] mask_id = ("line_masks", x1 - x, y1 - y, x2 - x, y2 - y, w, h) mask = r.cache.get(mask_id) if mask is None: sp = sge.gfx.Sprite(width=w, height=h) sp.draw_line(x1 - x, y1 - y, x2 - x, y2 - y, sge.gfx.Color("white")) mask = s_get_precise_mask(sp, 0, 1, 1, 0) r.cache.add(mask_id, mask) for obj in others: if (obj.tangible and r.o_is_other(obj, other) and masks_collide( x, y, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def ellipse(x, y, w, h, other=None): """ Return a list of objects colliding with an ellipse. Arguments: - ``x`` -- The horizontal position of the imaginary rectangle containing the ellipse. - ``y`` -- The vertical position of the imaginary rectangle containing the ellipse. - ``w`` -- The width of the ellipse. - ``h`` -- The height of the ellipse. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room others = room.get_objects_at(x, y, w, h) collisions = [] mask_id = ("ellipse_masks", x, y, w, h) mask = r.cache.get(mask_id) if mask is None: mask = [[False for j in six.moves.range(int(h))] for i in six.moves.range(int(w))] a = len(mask) / 2 b = len(mask[0]) / 2 if mask else 0 for i in six.moves.range(len(mask)): for j in six.moves.range(len(mask[i])): if ((i - a) / a)**2 + ((j - b) / b)**2 <= 1: mask[i][j] = True r.cache.add(mask_id, mask) for obj in others: if (obj.tangible and r.o_is_other(obj, other) and masks_collide( x, y, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def ellipse(x, y, w, h, other=None): """ Return a list of objects colliding with an ellipse. Arguments: - ``x`` -- The horizontal position of the imaginary rectangle containing the ellipse. - ``y`` -- The vertical position of the imaginary rectangle containing the ellipse. - ``w`` -- The width of the ellipse. - ``h`` -- The height of the ellipse. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room others = room.get_objects_at(x, y, w, h) collisions = [] mask_id = ("ellipse_masks", x, y, w, h) mask = r.cache.get(mask_id) if mask is None: mask = [[False for j in six.moves.range(h)] for i in six.moves.range(w)] a = len(mask) / 2 b = len(mask[0]) / 2 if mask else 0 for i in six.moves.range(len(mask)): for j in six.moves.range(len(mask[i])): if ((i - a) / a) ** 2 + ((j - b) / b) ** 2 <= 1: mask[i][j] = True r.cache.add(mask_id, mask) for obj in others: if (r.o_is_other(obj, other) and masks_collide(x, y, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def circle(x, y, radius, other=None): """ Return a list of objects colliding with a circle. Arguments: - ``x`` -- The horizontal position of the center of the circle. - ``y`` -- The vertical position of the center of the circle. - ``radius`` -- The radius of the circle. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room diameter = radius * 2 others = room.get_objects_at(x - radius, y - radius, diameter, diameter) collisions = [] mask_id = ("circle_masks", x, y, radius) mask = r.cache.get(mask_id) if mask is None: mask = [[False for j in six.moves.range(int(diameter))] for i in six.moves.range(int(diameter))] for i in six.moves.range(len(mask)): for j in six.moves.range(len(mask[i])): if (i - x)**2 + (j - y)**2 <= radius**2: mask[i][j] = True r.cache.add(mask_id, mask) for obj in others: if (obj.tangible and r.o_is_other(obj, other) and masks_collide(x - radius, y - radius, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def circle(x, y, radius, other=None): """ Return a list of objects colliding with a circle. Arguments: - ``x`` -- The horizontal position of the center of the circle. - ``y`` -- The vertical position of the center of the circle. - ``radius`` -- The radius of the circle. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room diameter = radius * 2 others = room.get_objects_at(x - radius, y - radius, diameter, diameter) collisions = [] mask_id = ("circle_masks", x, y, radius) mask = r.cache.get(mask_id) if mask is None: mask = [[False for j in six.moves.range(diameter)] for i in six.moves.range(diameter)] for i in six.moves.range(len(mask)): for j in six.moves.range(len(mask[i])): if (i - x) ** 2 + (j - y) ** 2 <= radius ** 2: mask[i][j] = True r.cache.add(mask_id, mask) for obj in others: if (r.o_is_other(obj, other) and masks_collide(x - radius, y - radius, mask, obj.mask_x, obj.mask_y, obj.mask)): collisions.append(obj) return collisions
def rectangle(x, y, w, h, other=None): """ Return a list of objects colliding with a rectangle. Arguments: - ``x`` -- The horizontal position of the rectangle. - ``y`` -- The vertical position of the rectangle. - ``w`` -- The width of the rectangle. - ``h`` -- The height of the rectangle. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room others = room.get_objects_at(x, y, w, h) collisions = [] mask_id = ("rectangle_masks", x, y, w, h) mask = r.cache.get(mask_id) if mask is None: mask = [[True for j in six.moves.range(int(h))] for i in six.moves.range(int(w))] r.cache.add(mask_id, mask) for obj in others: if obj.tangible and r.o_is_other(obj, other): if obj.collision_precise or obj.collision_ellipse: if masks_collide(x, y, mask, obj.mask_x, obj.mask_y, obj.mask): collisions.append(obj) else: if rectangles_collide(x, y, w, h, obj.bbox_left, obj.bbox_top, obj.bbox_width, obj.bbox_height): collisions.append(obj) return collisions
def rectangle(x, y, w, h, other=None): """ Return a list of objects colliding with a rectangle. Arguments: - ``x`` -- The horizontal position of the rectangle. - ``y`` -- The vertical position of the rectangle. - ``w`` -- The width of the rectangle. - ``h`` -- The height of the rectangle. - ``other`` -- What to check for collisions with. See the documentation for :meth:`sge.dsp.Object.collision` for more information. """ room = sge.game.current_room others = room.get_objects_at(x, y, w, h) collisions = [] mask_id = ("rectangle_masks", x, y, w, h) mask = r.cache.get(mask_id) if mask is None: mask = [[True for j in six.moves.range(h)] for i in six.moves.range(w)] r.cache.add(mask_id, mask) for obj in others: if r.o_is_other(obj, other): if obj.collision_precise or obj.collision_ellipse: if masks_collide(x, y, mask, obj.mask_x, obj.mask_y, obj.mask): collisions.append(obj) else: if rectangles_collide(x, y, w, h, obj.bbox_left, obj.bbox_top, obj.bbox_width, obj.bbox_height): collisions.append(obj) return collisions
def collision(self, other=None, x=None, y=None): """ Return a list of objects colliding with this object. Arguments: - ``other`` -- What to check for collisions with. Can be one of the following: - A :class:`sge.Object` object. - A list of :class:`sge.Object` objects. - A class derived from :class:`sge.Object`. - :const:`None`: Check for collisions with all objects. - ``x`` -- The horizontal position to pretend this object is at for the purpose of the collision detection. If set to :const:`None`, :attr:`x` will be used. - ``y`` -- The vertical position to pretend this object is at for the purpose of the collision detection. If set to :const:`None`, :attr:`y` will be used. """ room = sge.game.current_room if self.tangible and self in room.objects: collisions = [] # Change x and y to be offset values; these are easier to use. if x is not None: x -= self.x else: x = 0 if y is not None: y -= self.y else: y = 0 if self.collision_precise: ax = self.mask_x + x ay = self.mask_y + y w = len(self.mask) h = len(self.mask[0]) if self.mask else 0 else: ax = self.bbox_left + x ay = self.bbox_top + y w = self.bbox_width h = self.bbox_height others = room.get_objects_at(ax, ay, w, h) for obj in others: if obj is not self and obj.tangible and o_is_other(obj, other): if (self.collision_precise or self.collision_ellipse or obj.collision_precise or obj.collision_ellipse): # Use masks. if sge.collision.masks_collide(self.mask_x + x, self.mask_y + y, self.mask, obj.mask_x, obj.mask_y, obj.mask): collisions.append(obj) else: # Use bounding boxes. if sge.collision.rectangles_collide( self.bbox_left + x, self.bbox_top + y, self.bbox_width, self.bbox_height, obj.bbox_left, obj.bbox_top, obj.bbox_width, obj.bbox_height): collisions.append(obj) return collisions else: return []