Создание "рамки", которая скрывает все, кроме того, что содержится в Pygame

Я только начал с pyGame и хотел бы создать рамку, которая обрезает все, что я показываю на экране. т.е. независимо от того, что содержит мой мир, этот кадр должен охватывать все, кроме того, что он содержит.

Думайте об этом как о рамке, используемой для обрезки изображений на iphone (см. Рисунок ниже). В конце концов я хочу сделать фрейм интерактивным, чтобы я мог перемещать его или изменять его размер, но пока статический фрейм подойдет. И я понятия не имею, с чего начать.. любая помощь приветствуется!

[пример рамки для обрезки [1

1 ответ

Решение

Есть несколько способов сделать это; один из способов - нарисовать черное Surface на весь экран, но есть "дыра" в этом черном Surface,

Простой способ создать эту "дыру" - просто нарисовать прямоугольник с правой colorkey, Что colorkey?

При перетаскивании этой поверхности на место назначения все пиксели того же цвета, что и цветовой ключ, будут прозрачными.

Звучит полезно, поэтому давайте попробуем:

import random
import pygame as pg

IMAGE = pg.Surface((50, 50), pg.SRCALPHA)
pg.draw.polygon(IMAGE, (240, 120, 0), [(0, 50), (25, 0), (50, 50)])

class Actor(pg.sprite.Sprite):

    def __init__(self, grp, bounds, pos):
        self._layer = 0
        pg.sprite.Sprite.__init__(self, grp)
        self.image = IMAGE
        self.rect = self.image.get_rect(center=pos)
        self.vec = pg.math.Vector2()
        # just a random directon for movement
        self.vec.from_polar((10, random.randrange(0, 360)))
        self.bounds = bounds

    def update(self):
        self.rect.move_ip(*self.vec)
        # try staying on screen
        if not self.bounds.contains(self.rect):
            self.vec.from_polar((10, random.randrange(0, 360)))

class Cursor(pg.sprite.Sprite):
    def __init__(self, grp, bounds):
        self._layer = 1000
        pg.sprite.Sprite.__init__(self, grp)
        self.image = pg.Surface((bounds.width, bounds.height))
        self.image.set_colorkey(pg.Color('yellow'))
        # we start with the entire screen black
        # if the screen should be fully visible at the start, we could use yellow instead
        self.image.fill(pg.Color('black'))
        self.rect = self.image.get_rect()
        # here we store the position of the mouse when we start drawing the hole
        self.start = None
        # here we store the entire rect of the hole so we can later move it around
        self.inner_rect = None

    def mousedown(self):
        self.start = pg.mouse.get_pos()

    def mouseup(self):
        self.start = None

    def move(self, rel):
        self.inner_rect.move_ip(rel)
        self.recreate()

    def update(self):
        if not self.start:
            return
        pos = pg.mouse.get_pos()
        p = pos[0] - self.start[0], pos[1] - self.start[1]
        self.inner_rect = pg.Rect(self.start, p)
        self.recreate()

    def recreate(self):
        # here we update our hole
        self.image.fill(pg.Color('black'))
        pg.draw.rect(self.image, pg.Color('yellow'), self.inner_rect)
        pg.draw.rect(self.image, pg.Color('white'), self.inner_rect, 2)

def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.LayeredUpdates()
    cursor = Cursor(all_sprites, screen.get_rect())
    for _ in range(20):
        Actor(all_sprites, screen.get_rect(), (random.randrange(600), random.randrange(440)))

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            if event.type == pg.MOUSEBUTTONDOWN:
                if event.button == 1:
                    cursor.mousedown()
            if event.type == pg.MOUSEBUTTONUP:
                if event.button == 1:
                    cursor.mouseup()    
            if event.type == pg.MOUSEMOTION:
                if pg.mouse.get_pressed()[2]:
                    cursor.move(event.rel)

        all_sprites.update()
        screen.fill(pg.Color('darkblue'))
        all_sprites.draw(screen)

        pg.display.flip()
        clock.tick(60)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

Используйте левую кнопку мыши, чтобы начать рисовать рамку, и используйте правую кнопку мыши, чтобы переместить ее.

Как видите, у нас есть черный Surface с желтым цветом Когда мы хотим сделать видимой часть экрана, мы рисуем желтый прямоугольник, который, в свою очередь, будет прозрачным, делая сцену под ним видимой.

Другие вопросы по тегам