Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
    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 []