如何使对象居中,使矩形围绕我的角色?

问题描述

我正在尝试使用 pygame 制作一个小游戏(只是为了好玩),但我无法正确处理对象之间的碰撞。所以我决定绘制碰撞并注意到碰撞不在我的角色周围。这就是我的意思: The rectangles are the collisions

这是我的代码

import pygame

pygame.init()
winWidth = 400
winHeigth = 400
win = pygame.display.set_mode((winWidth,winHeigth))
pygame.display.set_caption("Pokemon copy")

Items = []

walkUp = [pygame.image.load('Up1.png'),pygame.image.load('Up2.png'),pygame.image.load('Up3.png'),pygame.image.load('Up4.png'),pygame.image.load('Up5.png'),pygame.image.load('idleUp.png'),pygame.image.load('Up6.png'),pygame.image.load('Up6.png')]
walkDown = [pygame.image.load('D1.png'),pygame.image.load('D2.png'),pygame.image.load('D3.png'),pygame.image.load('D4.png'),pygame.image.load('D5.png'),pygame.image.load('idle.png'),pygame.image.load('D2.png')]
walkRight = [pygame.image.load('R1.png'),pygame.image.load('R2.png'),pygame.image.load('R3.png'),pygame.image.load('R4.png'),pygame.image.load('R1.png'),pygame.image.load('idleRight.png')]
walkLeft = [pygame.image.load('L1.png'),pygame.image.load('L2.png'),pygame.image.load('L3.png'),pygame.image.load('L4.png'),pygame.image.load('L1.png'),pygame.image.load('idleLeft.png')]
bg = pygame.image.load('Test.png')
idle = [pygame.image.load('idle.png'),pygame.image.load("idleUp.png"),pygame.image.load("idleLeft.png"),pygame.image.load("idleRight.png")]

myfont = pygame.font.SysFont("monospace",15)

clock = pygame.time.Clock()


class trainer():
    def __init__(self,x,y):
        self.x = x
        self.y = y
        self.width = 32
        self.heigth = 32
        self.enemy = pygame.image.load('idleE.png')
        self.rect = self.enemy.get_rect()

    def draw(self,win):
        win.blit(self.enemy,(self.x,self.y))


class player():
    def __init__(self,y,width,heigth):
        self.x = x
        self.y = y
        self.width = width
        self.heigth = heigth
        self.vel = 5
        self.left = False
        self.right = False
        self.up = False
        self.down = False
        self.walkCount = 0
        self.stamina = 100
        self.Event = pygame.USEREVENT+1
        self.prevIoUs = "right"
        self.player = pygame.image.load("idle.png")
        self.rect = self.player.get_rect(center=(self.x,self.y))
        self.pos = self.x,self.y

    def draw(self,win):
        if self.walkCount + 1 >= 27:
            self.walkCount = 0
        if self.up:
            self.rect.center = self.x,self.y
            win.blit(walkUp[self.walkCount//3],self.y))
            self.walkCount += 1
        elif self.down:
            self.rect.center = self.x,self.y
            win.blit(walkDown[self.walkCount//3],self.y))
            self.walkCount += 1
        elif self.right:
            self.rect.center = self.x,self.y
            win.blit(walkRight[self.walkCount//3],self.y))
            self.walkCount += 1
        elif self.left:
            self.rect.center = self.x,self.y
            win.blit(walkLeft[self.walkCount//3],self.y))
            self.walkCount += 1
        else:
            if self.prevIoUs == "up":
                win.blit(idle[1],self.y))
            elif self.prevIoUs == "down":
                win.blit(idle[0],self.y))
            elif self.prevIoUs == "left":
                win.blit(idle[2],self.y))
            elif self.prevIoUs == "right":
                win.blit(idle[3],self.y))

    def Collision(self,Potion):
        if self.rect.colliderect(Potion.rect):
            return True
        else:
            return False

    def getPos(self):
        return self.x,self.y


class usableItems():
    def __init__(self,y):
        self.usable = True
        self.x = x
        self.y = y


class potion(usableItems):
    def __init__(self,usable,y):
        super().__init__(x,y)
        self.heal = 20
        self.potion = pygame.image.load("Potion.png")
        self.rect = self.potion.get_rect(center=(self.x,self.y))

    def draw(self,win):
        self.rect.center = self.x,self.y
        win.blit(self.potion,self.y))


def write(text,color):
    text = myfont.render(text,4,pygame.Color(color))
    text_rect = text.get_rect(center=(winWidth//2,y))
    return text,text_rect


def inventory():
    Inventory = True
    while Inventory:
        clock.tick(27)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Inventory = False

        keys = pygame.key.get_pressed()

        if keys[pygame.K_ESCAPE]:
            Inventory = False

        redrawInventoryWindow(Items)


def redrawInventoryWindow(items):
    win.fill((0,0))
    if len(items) == 0:
        message = "You currently have no items!"
        text,text_rect = write(message,10,70,(255,255,255))
        win.blit(text,text_rect)
    else:
        distance = 10
        for item in items:
            text2,text_rect2 = write(item,distance,255))
            distance += 25
            win.blit(text2,text_rect2)
    pygame.display.update()


def redrawGameWindow(character,trainer1,Potion):
    win.fill((255,255))
    text = "Stamina: " + str(int(character.stamina)) + "/100"
    label = myfont.render(text,1,(0,0))
    win.blit(label,winHeigth - 50))
    character.draw(win)
    pygame.draw.rect(win,0),character,3,1)
    trainer1.draw(win)
    Potion.draw(win)
    pygame.draw.rect(win,(200,55,Potion,2)
    pygame.display.update()


def game():
    character = player(50,50,32,32)
    trainer1 = trainer(300,360)
    Potion = potion(True,150,150)
    run = True
    while run:
        clock.tick(27)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

        keys = pygame.key.get_pressed()

        if keys[pygame.K_i]:
            inventory()

        elif keys[pygame.K_LCTRL] and character.stamina > 0:
            vel = 7.5
            pygame.time.set_timer(character.Event,1000)
            character.stamina -= 1

        elif not keys[pygame.K_LCTRL] and character.stamina < 100:
            vel = 5
            pygame.time.set_timer(character.Event,1000)
            character.stamina += 0.5
        else:
            vel = 5

        if keys[pygame.K_LEFT] and character.x > 0:
            character.prevIoUs = "left"
            character.x -= vel
            character.left = True
            character.right = False
            character.up = False
            character.down = False

        elif keys[pygame.K_RIGHT] and character.x < winWidth - character.width:
            character.prevIoUs = "right"
            character.x += vel
            character.right = True
            character.left = False
            character.up = False
            character.down = False

        elif keys[pygame.K_UP] and character.y > 0:
            character.prevIoUs = "up"
            character.y -= vel
            character.up = True
            character.down = False
            character.left = False
            character.right = False

        elif keys[pygame.K_DOWN] and character.y < winHeigth - character.heigth:
            character.prevIoUs = "down"
            character.y += vel
            character.down = True
            character.up = False
            character.left = False
            character.right = False

        else:
            character.right = False
            character.left = False
            character.up = False
            character.down = False
            character.walkCount = 0

        if character.Collision(Potion):
            if keys[pygame.K_DOWN]:
                character.y -= vel
            elif keys[pygame.K_UP]:
                character.y += vel
            elif keys[pygame.K_LEFT]:
                character.x += vel
            elif keys[pygame.K_RIGHT]:
                character.x -= vel
            vel = 0

        redrawGameWindow(character,Potion)

    pygame.quit()


game()

请注意,我对编程还很陌生,所以我知道我的代码还有很多需要改进的地方。

解决方法

您的矩形是正确的,但 精灵 绘制在错误的位置。 Sprites 的位置由 rect 属性定义。属性 xy 定义了 Sprite 的中心。但是,方法 blit 的参数 dest 指定了 source pygame.Surface 所在的左上角。绘制。见blit

在这个表面上绘制一个源表面。可以使用 dest 参数定位绘图。 dest 参数可以是表示 blit 左上角位置的一对坐标,也可以是一个 Rect,其中矩形的左上角将用作 blit 的位置。

您必须更改所有 draw 方法:

class trainer():
    # [...]

        def draw(self,win):
        self.rect.center = self.x,self.y
        win.blit(self.enemy,self.rect)
class player():
    # [...]

    def draw(self,self.y
        if self.walkCount + 1 >= 27:
            self.walkCount = 0
        if self.up:
            win.blit(walkUp[self.walkCount//3],self.rect)
            self.walkCount += 1
        elif self.down:
            win.blit(walkDown[self.walkCount//3],self.rect)
            self.walkCount += 1

        # continue for all "win.blit()"
class potion(usableItems):
    # [...]

    def draw(self,self.y
        win.blit(self.potion,self.rect)