问题描述
我正在尝试使用 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
属性定义。属性 x
和 y
定义了 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)