在Pygame中使用鼠标进行不准确的物体移动

时间:2017-07-10 09:03:49

标签: python pygame

我正试图制作这款游戏​​的近乎抄本:

https://yppedia.puzzlepirates.com/Carpentry

它使用pentominos,它是由5个块组成的对象。我有一个Piece类,它将每个块存储在一个列表中。当我点击一个块来移动它时,我也会移动每个共享同一个父对象的块,所以我可以用鼠标拖动整个块。

我遇到的问题是,当我点击其中一个块时,该部分会从光标移开。拖动很好,但我希望它能更准确地跟踪光标。

我正在使用Mouse类,因此我可以在鼠标点击和Blocks之间实现简单的碰撞,但我认为这是我遇到问题的原因。

编辑:我可以通过硬编码更改每个块的x和y位置来解决这个问题,但理想情况下我更喜欢更模块化的解决方案,因为我认为我误解了鼠标在pygame中的位置。

import pygame
import sys
import collections
import random

pygame.init()
FPS = 25
fpsClock = pygame.time.Clock()

# -----------SCREEN----------------#
WIN_WIDTH = 680  # width of window
WIN_HEIGHT = 500  # height of window
DISPLAY = (WIN_WIDTH, WIN_HEIGHT)  # variable for screen display
DEPTH = 32  # standard
FLAGS = 0  # standard
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption('Carpentry')
# ---------------------------------#

# ---------------colours-----------#
WOOD = (182, 155, 76)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
# ---------------------------------#

blocks = pygame.sprite.Group()
pieces = []

class Block(pygame.sprite.Sprite):
    def __init__(self, x, y, parent):
        super().__init__()
        self.image = pygame.Surface([15, 15])
        self.colour = WOOD
        self.parent = parent
        self.image.fill(self.colour)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.original_x = x
        self.original_y = y
        self.drag = False

class Mouse(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface([15, 15])
        self.colour = RED
        self.image.fill(self.colour)
        self.rect = self.image.get_rect()
        self.rect.x = pygame.mouse.get_pos()[0]
        self.rect.y = pygame.mouse.get_pos()[1]

    def update_mouse(self):
        self.rect.x = pygame.mouse.get_pos()[0]
        self.rect.y = pygame.mouse.get_pos()[1]

class Piece:
    def __init__(self):
        self.blocks = []
        self.c = 0

    def insert(self, template):
        for direction in template:
            self.blocks.append([])
            x = 0
            y = 0
            for line in direction:
                for character in line:
                    if character == "O":
                        my_block = Block(x, y, self)
                        self.blocks[self.c].append(my_block)
                        blocks.add(my_block)

                    x += 15
                y += 15
                x = 0
            self.c += 1

J_TEMPLATE = [['..O..',
               '..O..',
               '..O..',
               '.OO..',
               '.....']]
templates = {}

my_piece = Piece()
my_piece.insert(J_TEMPLATE)
pieces.append(my_piece)

mouse = Mouse()
while True:
    screen.fill(BLACK)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                bool = pygame.sprite.spritecollide(mouse, blocks, False)
                if len(bool) > 0:
                    target = bool[0]
                    target.drag = True
                    for block in blocks:
                        if block.parent == target.parent: #if blocks are part of the same piece
                            block.drag = True
                else:
                    for block in blocks:
                        block.drag = False
    mouse.update_mouse()
    for block in blocks:
        if block.drag == True:
            block.rect.x = mouse.rect.x + block.original_x
            block.rect.y = mouse.rect.y + block.original_y

    blocks.draw(screen)
    pygame.display.update()
    fpsClock.tick(FPS)

1 个答案:

答案 0 :(得分:1)

我是这样做的:如果单击了一个块,将其父片段分配给变量并计算块的偏移量,如下所示:block.offset = block.rect.topleft - Vec(event.pos)。在文件顶部,您需要导入from pygame.math import Vector2 as Vec。现在,您可以检查pygame.MOUSEMOTION个事件并将块移动到新的event.pos + block.offset

Mouse