예제 #1
0
    def _update(self, block):
        surf = Surface((const.res, const.res))
        fill = {Tiles.Empty: (0, 0, 0),
                Tiles.Solid: (0, 0, 255),
                Tiles.Start: (0, 255, 0),
                Tiles.End: (255, 0, 255),
                Tiles.Deadly: (255, 0, 0),
                Tiles.EnemySpawn: (0, 255, 255)}[block.getType()]
        pygame.draw.rect(surf, fill, (block.relX, block.relY, block.w, block.h))
        pygame.draw.rect(surf, (255, 255, 255), (block.relX, block.relY, block.w, block.h), 1)

        isSpawn = block.getAttr("spawnNum")
        if isSpawn:
            text = pygame.font.SysFont("arial", 25).render(str(isSpawn), 1, (0, 0, 0))
            surf.blit(text, (int(surf.get_width() / 2 - text.get_width() / 2),
                             int(surf.get_height() / 2 - text.get_height() / 2)))
        self._display.update(surf, Object(pos=(block.mapX * const.res, block.mapY * const.res)))
예제 #2
0
class Viewport(ScaledObject, Scaled):
    """
    A `Scaleable` view onto some object.
    """
    def __init__(self,
                 size,
                 scale,
                 target=None,
                 boundBox=Object(),
                 maxBounds=None):
        """
        `size` - The size (width and height).
        `scale` - The scale at which to render the view.
        `target` - (Optional) An object that the position of the `Viewport` should follows. If
                   not set, the `Viewport` will not move automatically.
        `boundBox` - (Optional) A sub-view of the `Viewport`, inside which the `target` should
                     always remain. If not set, it will be set to the Viewport's size.
        `maxBounds` - (Optional) A Rectangle inside of which the `Viewport` should always remain.
                      If not set, there will be no max/min bounds on the position of the `Viewport`.
        """
        super().__init__(size=size, scale=scale)

        self._target = target
        self._boundBox = ScaledOffsetObject(rect=boundBox, scale=self.getScale)
        self._maxBounds = maxBounds

        self._display = Display(Surface(size))
        self._displaySurfaceCache = self._display.getImage()
        self._surfaceCache = None

        self._lastScale = None

    def getAbsolutePos(self, pos):
        """
        Returns the `pos` converted into terms of the `Viewport`.

        This is important when the scale is not 1 because the on-screen position will not
        match the actual position being passed in at arbitrary scales.
        """
        return self.x + (pos[0] * self.getScale()), self.y + (pos[1] *
                                                              self.getScale())

    def tick(self):
        """
        Adjusts the position of the `Viewport` to keep the `target` inside `boundBox`, and
        to keep the `Viewport` inside `maxBounds`.
        """

        # Adjusts x and y to relative to the target.
        if self._target:
            if self.x > self._target.x - self._boundBox.x:
                self.x = self._target.x - self._boundBox.x
            if self.x < self._target.x + self._target.w + self._boundBox.w - self.w:
                self.x = self._target.x + self._target.w + self._boundBox.w - self.w

            if self.y > self._target.y - self._boundBox.y:
                self.y = self._target.y - self._boundBox.y
            if self.y < self._target.y + self._target.h + self._boundBox.h - self.h:
                self.y = self._target.y + self._target.h + self._boundBox.h - self.h

        # Adjusts x and y relative to the maximum/minimum bounds.
        if self._maxBounds:
            if self.x < self._maxBounds.x:
                self.x = self._maxBounds.x
            if self.x + self.w > self._maxBounds.w:
                self.x = self._maxBounds.w - self.w
            if (self.x < 0) and (self.x + self.w > self._maxBounds.w):
                self.x = self._target.x + self._target.w / 2 - self.w / 2

            if self.y < self._maxBounds.y:
                self.y = self._maxBounds.y
            if self.y + self.h > self._maxBounds.h:
                self.y = self._maxBounds.h - self.h
            if (self.y < 0) and (self.y + self.h > self._maxBounds.h):
                self.y = self._target.y + self._target.h / 2 - self.h / 2

    def draw(self, surface, total_surface):
        """
        Calculate the scaling and display to the inputted surface.

        `surface` - The `Surface` being drawn to.
        `total_surface` - The `Surface` being copied from.
        """
        scale = self.getScale()

        # Optimization, no need to do scaling when the scale is 1.
        if scale == 1:
            self._display.update(
                total_surface, Display.translate(total_surface.get_rect(),
                                                 self))
        else:
            # Optimization, caches the `Surface` object so long as the scale isn't changing.
            if scale != self._lastScale:
                self._surfaceCache = Surface((self.w, self.h))
            self._surfaceCache.blit(total_surface, (-self.x, -self.y))

            scaleTo = self.unscaled()
            transform.scale(self._surfaceCache, (scaleTo.w, scaleTo.h),
                            self._displaySurfaceCache)
            self._lastScale = scale

        self._display.draw(surface)
예제 #3
0
class Viewport(ScaledObject, Scaled):
    """
    A `Scaleable` view onto some object.
    """
    def __init__(self, size, scale, target=None, boundBox=Object(), maxBounds=None):
        """
        `size` - The size (width and height).
        `scale` - The scale at which to render the view.
        `target` - (Optional) An object that the position of the `Viewport` should follows. If
                   not set, the `Viewport` will not move automatically.
        `boundBox` - (Optional) A sub-view of the `Viewport`, inside which the `target` should
                     always remain. If not set, it will be set to the Viewport's size.
        `maxBounds` - (Optional) A Rectangle inside of which the `Viewport` should always remain.
                      If not set, there will be no max/min bounds on the position of the `Viewport`.
        """
        super().__init__(size=size, scale=scale)

        self._target = target
        self._boundBox = ScaledOffsetObject(rect=boundBox, scale=self.getScale)
        self._maxBounds = maxBounds

        self._display = Display(Surface(size))
        self._displaySurfaceCache = self._display.getImage()
        self._surfaceCache = None

        self._lastScale = None

    def getAbsolutePos(self, pos):
        """
        Returns the `pos` converted into terms of the `Viewport`.

        This is important when the scale is not 1 because the on-screen position will not
        match the actual position being passed in at arbitrary scales.
        """
        return self.x + (pos[0] * self.getScale()), self.y + (pos[1] * self.getScale())

    def tick(self):
        """
        Adjusts the position of the `Viewport` to keep the `target` inside `boundBox`, and
        to keep the `Viewport` inside `maxBounds`.
        """

        # Adjusts x and y to relative to the target.
        if self._target:
            if self.x > self._target.x - self._boundBox.x:
                self.x = self._target.x - self._boundBox.x
            if self.x < self._target.x + self._target.w + self._boundBox.w - self.w:
                self.x = self._target.x + self._target.w + self._boundBox.w - self.w

            if self.y > self._target.y - self._boundBox.y:
                self.y = self._target.y - self._boundBox.y
            if self.y < self._target.y + self._target.h + self._boundBox.h - self.h:
                self.y = self._target.y + self._target.h + self._boundBox.h - self.h

        # Adjusts x and y relative to the maximum/minimum bounds.
        if self._maxBounds:
            if self.x < self._maxBounds.x:
                self.x = self._maxBounds.x
            if self.x + self.w > self._maxBounds.w:
                self.x = self._maxBounds.w - self.w
            if (self.x < 0) and (self.x + self.w > self._maxBounds.w):
                self.x = self._target.x + self._target.w / 2 - self.w / 2

            if self.y < self._maxBounds.y:
                self.y = self._maxBounds.y
            if self.y + self.h > self._maxBounds.h:
                self.y = self._maxBounds.h - self.h
            if (self.y < 0) and (self.y + self.h > self._maxBounds.h):
                self.y = self._target.y + self._target.h / 2 - self.h / 2

    def draw(self, surface, total_surface):
        """
        Calculate the scaling and display to the inputted surface.

        `surface` - The `Surface` being drawn to.
        `total_surface` - The `Surface` being copied from.
        """
        scale = self.getScale()

        # Optimization, no need to do scaling when the scale is 1.
        if scale == 1:
            self._display.update(total_surface, Display.translate(total_surface.get_rect(), self))
        else:
            # Optimization, caches the `Surface` object so long as the scale isn't changing.
            if scale != self._lastScale:
                self._surfaceCache = Surface((self.w, self.h))
            self._surfaceCache.blit(total_surface, (-self.x, -self.y))

            scaleTo = self.unscaled()
            transform.scale(self._surfaceCache, (scaleTo.w, scaleTo.h), self._displaySurfaceCache)
            self._lastScale = scale

        self._display.draw(surface)