Scaling an Image/Rectangle in Pygame

2019-07-19 20:01发布

问题:

Is it possible to "scale" a rectangle inside of pygame. Kinda like when you scale your windows on your desktop, I'm wondering how you could do so in pygame. Your cursor will control the size of the rectangle.

I used skrx method and I tried to do it for 2 rectangles:

if evnt.type == MOUSEBUTTONDOWN:
        if winVirus.collidepoint(evnt.pos):
            rectVSelect = True
        elif winCrime.collidepoint(evnt.pos):
            rectCSelect = True
    elif evnt.type == MOUSEBUTTONUP:
        rectVSelect = False
        rectCSelect = False
    if evnt.type == MOUSEMOTION:
        if rectVSelect:
            winVirus.w += evnt.rel[0]
            winVirus.h += evnt.rel[1]
            winVirus.w = max(winVirus.w, 50)
            winVirus.h = max(winVirus.h, 50)  
        elif rectCSelect:
            winCrime.w += evnt.rel[0]
            winCrime.h += evnt.rel[1]
            winCrime.w = max(winVirus.w, 50)
            winCrime.h = max(winVirus.h, 50)

but for the second rectangle, it would move properly there seems to be a problem with "winCrime". winVirus" works perfectly fine.

回答1:

You can simply change the width and the height of the rect (the w and h attributes). When the mouse gets moved (a MOUSEMOTION event is added to the queue) and if the rect is selected, add the relative movement event.rel to the width and the height.

import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
rect = pg.Rect(100, 100, 161, 100)
rect_selected = False

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.MOUSEBUTTONDOWN:
            # Set rect_selected to True when the user clicks on the rect.
            if rect.collidepoint(event.pos):
                rect_selected = True
        elif event.type == pg.MOUSEBUTTONUP:
            rect_selected = False
        elif event.type == pg.MOUSEMOTION:
            if rect_selected:
                # Simply adjust the width and the height of the screen
                # by subtracting the relative mouse movement.
                rect.w += event.rel[0]
                rect.h += event.rel[1]
                # 10*10 px is the minimal size, so that the rect can
                # still be clicked.
                rect.w = max(rect.w, 10)
                rect.h = max(rect.h, 10)

    screen.fill((30, 30, 30))
    pg.draw.rect(screen, (0, 100, 250), rect)
    pg.display.flip()
    clock.tick(30)

If you want to do this with several rects, you can just assign the clicked rect to a variable (selected_rect in this case) and then scale it.

import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
rect1 = pg.Rect(100, 100, 161, 100)
rect2 = pg.Rect(300, 200, 161, 100)
selected_rect = None

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.MOUSEBUTTONDOWN:
            # Set selected_rect to the colliding rect.
            for rect in (rect1, rect2):
                if rect.collidepoint(event.pos):
                    selected_rect = rect
        elif event.type == pg.MOUSEBUTTONUP:
            selected_rect = None  # De-select.
        elif event.type == pg.MOUSEMOTION:
            if selected_rect is not None:  # Scale if a rect is selected.
                selected_rect.w += event.rel[0]
                selected_rect.h += event.rel[1]
                selected_rect.w = max(selected_rect.w, 10)
                selected_rect.h = max(selected_rect.h, 10)

    screen.fill((30, 30, 30))
    pg.draw.rect(screen, (0, 100, 250), rect1)
    pg.draw.rect(screen, (0, 200, 120), rect2)
    pg.display.flip()
    clock.tick(30)


回答2:

This is a working example. You are going to have to adapt it to your situation.

import pygame

rect = pygame.Rect(50, 50, 100, 100)
screen = pygame.display.set_mode((200, 200))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEMOTION and event.buttons[0]:
            p = event.pos[0] - event.rel[0], event.pos[1] - event.rel[1]
            if pygame.Rect(rect.left, rect.top - 2, rect.width, 4).collidepoint(*p): # top
                rect = pygame.Rect(rect.left, rect.top + event.rel[1], rect.width, rect.height - event.rel[1])
            elif pygame.Rect(rect.left, rect.bottom - 2, rect.width, 4).collidepoint(*p): # bottom
                rect = pygame.Rect(rect.left, rect.top, rect.width, rect.height + event.rel[1])
            if pygame.Rect(rect.left - 2, rect.top, 4, rect.height).collidepoint(*p): # left
                rect = pygame.Rect(rect.left + event.rel[0], rect.top, rect.width - event.rel[0], rect.height)
            elif pygame.Rect(rect.right - 2, rect.top, 4, rect.height).collidepoint(*p): # right
                rect = pygame.Rect(rect.left, rect.top, rect.width + event.rel[0], rect.height)

    screen.fill((0, 0, 0))
    pygame.draw.rect(screen, (255, 255, 255), rect)
    pygame.display.update()