Pygame.colliderect() 在碰撞时适当地停止 2 个可移动玩家(独立)的移动
Pygame.colliderect() appropriately stopping movement of 2 movable players (independant) upon collision
我正在制作一款简单的街机游戏,供 2 名玩家在 1 个键盘上玩(一个使用箭头键,另一个使用 wasd),并且在两个玩家发生碰撞时让适当的玩家停止移动时偶然发现了一些问题-检测到可控方块。它们似乎有点融合在一起,而且当它们向相反的方向移动时,它们总是朝一个方向移动而不是完全停止。您对如何解决这些问题有任何想法吗? (别管顶撞,它们会被用来做别的事情。)
import pygame
from pygame.locals import *
pygame.init()
vec = pygame.math.Vector2
width = 500
height = 500
FPS = 60
l_blue = (173,216,230)
blue = (0,32,255)
red = (200,0,0)
ACC = 1
GRND_ACC = 0.75
JUMP = 15
GRAV = 0.5
FRIC = -0.15
screen = pygame.display.set_mode((width, height))
screen.fill(l_blue)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.size = 30
self.surf = pygame.Surface((self.size, self.size))
self.surf.fill(blue)
self.rect = self.surf.get_rect()
self.jumps = 0
self.jumplimit = 2
self.pos = vec(width / 2, height)
self.vel = vec(0,0)
self.acc = vec(0,0)
self.number = 1
def move(self):
self.acc = vec(0,GRAV)
pressed_keys = pygame.key.get_pressed()
if self.number == 1:
if pressed_keys[K_LEFT]:
if self.jumps == 0:
self.acc.x = - GRND_ACC
else:
self.acc.x = -ACC
if pressed_keys[K_RIGHT]:
if self.jumps == 0:
self.acc.x = GRND_ACC
else:
self.acc.x = ACC
if self.number == 2:
if pressed_keys[ord('a')]:
if self.jumps == 0:
self.acc.x = -GRND_ACC
else:
self.acc.x = -ACC
if pressed_keys[ord('d')]:
if self.jumps == 0:
self.acc.x = GRND_ACC
else:
self.acc.x = ACC
self.acc.x += self.vel.x * FRIC
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
if self.pos.x > width + self.size / 2:
self.pos.x = - self.size / 2
if self.pos.x < -self.size / 2:
self.pos.x = width + self.size / 2
if self.pos.y > height:
self.pos.y = height
self.jumps = 0
if self.pos.y < self.size / 2:
self.pos.y = self.size / 2
self.rect.midbottom = self.pos
P1_HU.pos.x = P1.pos.x
P1_HU.pos.y = P1.pos.y - self.size + 2
P2_HU.pos.x = P2.pos.x
P2_HU.pos.y = P2.pos.y - self.size + 2
P1_HU.rect.midbottom = P1_HU.pos
P2_HU.rect.midbottom = P2_HU.pos
def jump(self):
self.vel.y = -JUMP
class Hitbox_Up(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.surf = pygame.Surface((P1.size - 4, 4))
self.surf.fill(red)
self.rect = self.surf.get_rect()
self.pos = vec(0,0)
P1 = Player()
P2 = Player()
P1_HU = Hitbox_Up()
P2_HU = Hitbox_Up()
P2.surf.fill(red)
P2.number = 2
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
all_sprites.add(P2)
all_sprites.add(P1_HU)
all_sprites.add(P2_HU)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP and P1.jumps < P2.jumplimit:
P1.jumps += 1
P1.jump()
if event.key == pygame.K_w and P2.jumps < P2.jumplimit:
P2.jumps += 1
P2.jump()
screen.fill(l_blue)
if P1.rect.colliderect(P2.rect) or P2.rect.colliderect(P1.rect):
if P1.acc.x > 0:
if P2.acc.x < 0:
P2.acc.x = 0
P2.vel.x = 0
P1.pos.x = P2.pos.x - P1.size
P2.pos.x = P1.pos.x + P2.size
P1.vel.x = 0
P1.acc.x = 0
elif P1.acc.x < 0 :
if P2.acc.x > 0:
P2.acc.x = 0
P2.vel.x = 0
P1.vel.x = 0
P1.acc.x = 0
P1.pos.x = P2.pos.x + P1.size
P2.pos.x = P1.pos.x - P2.size
else:
if P2.acc.x > 0:
P2.pos.x = P1.pos.x - P2.size
P1.pos.x = P2.pos.x + P1.size
else:
P2.pos.x = P1.pos.x + P2.size
P1.pos.x = P2.pos.x - P1.size
P1.move()
P2.move()
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
pygame.display.update()
pygame.time.Clock().tick(FPS)
玩家的移动可以通过右矩减去左矩来计算:
class Player(pygame.sprite.Sprite):
# [...]
def move(self):
self.acc = vec(0,GRAV)
pressed_keys = pygame.key.get_pressed()
acc_x = 0
if self.number == 1:
acc_x = pressed_keys[K_RIGHT] - pressed_keys[K_LEFT]
elif self.number == 2:
acc_x = pressed_keys[K_d] - pressed_keys[K_a]
if self.jumps == 0:
self.acc.x = acc_x * GRND_ACC
else:
self.acc.x = acc_x * ACC
# [...]
为了防止玩家粘在一起,你需要检查P1
是在P2
的左边还是右边。阻止玩家向另一个玩家移动:
while True:
# [...]
if P1.rect.colliderect(P2.rect):
if P1.rect.x < P2.rect.x:
if P1.acc.x >= 0 and P2.acc.x <= 0:
P1.rect.right = P2.rect.left = round((P1.rect.right + P2.rect.left) / 2)
if P1.acc.x > 0:
P1.acc.x, P1.vel.x = 0, 0
P1.rect.right = P2.rect.left
if P2.acc.x < 0:
P2.acc.x, P2.vel.x = 0, 0
P2.rect.left = P1.rect.right
else:
if P1.acc.x <= 0 and P2.acc.x >= 0:
P1.rect.left = P2.rect.right = round((P1.rect.left + P2.rect.right) / 2)
if P1.acc.x < 0:
P1.acc.x, P1.vel.x = 0, 0
P1.rect.left = P2.rect.right
if P2.acc.x > 0:
P2.acc.x, P2.vel.x = 0, 0
P2.rect.right = P1.rect.left
P1.pos.x = P1.rect.centerx
P2.pos.x = P2.rect.centerx
# [...]
我正在制作一款简单的街机游戏,供 2 名玩家在 1 个键盘上玩(一个使用箭头键,另一个使用 wasd),并且在两个玩家发生碰撞时让适当的玩家停止移动时偶然发现了一些问题-检测到可控方块。它们似乎有点融合在一起,而且当它们向相反的方向移动时,它们总是朝一个方向移动而不是完全停止。您对如何解决这些问题有任何想法吗? (别管顶撞,它们会被用来做别的事情。)
import pygame
from pygame.locals import *
pygame.init()
vec = pygame.math.Vector2
width = 500
height = 500
FPS = 60
l_blue = (173,216,230)
blue = (0,32,255)
red = (200,0,0)
ACC = 1
GRND_ACC = 0.75
JUMP = 15
GRAV = 0.5
FRIC = -0.15
screen = pygame.display.set_mode((width, height))
screen.fill(l_blue)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.size = 30
self.surf = pygame.Surface((self.size, self.size))
self.surf.fill(blue)
self.rect = self.surf.get_rect()
self.jumps = 0
self.jumplimit = 2
self.pos = vec(width / 2, height)
self.vel = vec(0,0)
self.acc = vec(0,0)
self.number = 1
def move(self):
self.acc = vec(0,GRAV)
pressed_keys = pygame.key.get_pressed()
if self.number == 1:
if pressed_keys[K_LEFT]:
if self.jumps == 0:
self.acc.x = - GRND_ACC
else:
self.acc.x = -ACC
if pressed_keys[K_RIGHT]:
if self.jumps == 0:
self.acc.x = GRND_ACC
else:
self.acc.x = ACC
if self.number == 2:
if pressed_keys[ord('a')]:
if self.jumps == 0:
self.acc.x = -GRND_ACC
else:
self.acc.x = -ACC
if pressed_keys[ord('d')]:
if self.jumps == 0:
self.acc.x = GRND_ACC
else:
self.acc.x = ACC
self.acc.x += self.vel.x * FRIC
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
if self.pos.x > width + self.size / 2:
self.pos.x = - self.size / 2
if self.pos.x < -self.size / 2:
self.pos.x = width + self.size / 2
if self.pos.y > height:
self.pos.y = height
self.jumps = 0
if self.pos.y < self.size / 2:
self.pos.y = self.size / 2
self.rect.midbottom = self.pos
P1_HU.pos.x = P1.pos.x
P1_HU.pos.y = P1.pos.y - self.size + 2
P2_HU.pos.x = P2.pos.x
P2_HU.pos.y = P2.pos.y - self.size + 2
P1_HU.rect.midbottom = P1_HU.pos
P2_HU.rect.midbottom = P2_HU.pos
def jump(self):
self.vel.y = -JUMP
class Hitbox_Up(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.surf = pygame.Surface((P1.size - 4, 4))
self.surf.fill(red)
self.rect = self.surf.get_rect()
self.pos = vec(0,0)
P1 = Player()
P2 = Player()
P1_HU = Hitbox_Up()
P2_HU = Hitbox_Up()
P2.surf.fill(red)
P2.number = 2
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
all_sprites.add(P2)
all_sprites.add(P1_HU)
all_sprites.add(P2_HU)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP and P1.jumps < P2.jumplimit:
P1.jumps += 1
P1.jump()
if event.key == pygame.K_w and P2.jumps < P2.jumplimit:
P2.jumps += 1
P2.jump()
screen.fill(l_blue)
if P1.rect.colliderect(P2.rect) or P2.rect.colliderect(P1.rect):
if P1.acc.x > 0:
if P2.acc.x < 0:
P2.acc.x = 0
P2.vel.x = 0
P1.pos.x = P2.pos.x - P1.size
P2.pos.x = P1.pos.x + P2.size
P1.vel.x = 0
P1.acc.x = 0
elif P1.acc.x < 0 :
if P2.acc.x > 0:
P2.acc.x = 0
P2.vel.x = 0
P1.vel.x = 0
P1.acc.x = 0
P1.pos.x = P2.pos.x + P1.size
P2.pos.x = P1.pos.x - P2.size
else:
if P2.acc.x > 0:
P2.pos.x = P1.pos.x - P2.size
P1.pos.x = P2.pos.x + P1.size
else:
P2.pos.x = P1.pos.x + P2.size
P1.pos.x = P2.pos.x - P1.size
P1.move()
P2.move()
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
pygame.display.update()
pygame.time.Clock().tick(FPS)
玩家的移动可以通过右矩减去左矩来计算:
class Player(pygame.sprite.Sprite):
# [...]
def move(self):
self.acc = vec(0,GRAV)
pressed_keys = pygame.key.get_pressed()
acc_x = 0
if self.number == 1:
acc_x = pressed_keys[K_RIGHT] - pressed_keys[K_LEFT]
elif self.number == 2:
acc_x = pressed_keys[K_d] - pressed_keys[K_a]
if self.jumps == 0:
self.acc.x = acc_x * GRND_ACC
else:
self.acc.x = acc_x * ACC
# [...]
为了防止玩家粘在一起,你需要检查P1
是在P2
的左边还是右边。阻止玩家向另一个玩家移动:
while True:
# [...]
if P1.rect.colliderect(P2.rect):
if P1.rect.x < P2.rect.x:
if P1.acc.x >= 0 and P2.acc.x <= 0:
P1.rect.right = P2.rect.left = round((P1.rect.right + P2.rect.left) / 2)
if P1.acc.x > 0:
P1.acc.x, P1.vel.x = 0, 0
P1.rect.right = P2.rect.left
if P2.acc.x < 0:
P2.acc.x, P2.vel.x = 0, 0
P2.rect.left = P1.rect.right
else:
if P1.acc.x <= 0 and P2.acc.x >= 0:
P1.rect.left = P2.rect.right = round((P1.rect.left + P2.rect.right) / 2)
if P1.acc.x < 0:
P1.acc.x, P1.vel.x = 0, 0
P1.rect.left = P2.rect.right
if P2.acc.x > 0:
P2.acc.x, P2.vel.x = 0, 0
P2.rect.right = P1.rect.left
P1.pos.x = P1.rect.centerx
P2.pos.x = P2.rect.centerx
# [...]