I'm making a simple arcade game for 2 players to play on 1 keyboard (one with arrows keys, the other with wasd) and have stumbled upon some issues when making appropriate players stop moving when collision between two player-controlable squares is detected. They seem to sort of merge into each other and also when they are moving the opposite directions they always move one way instead of stopping completely. Do you have any ideas on how to fix the issues? (Don't bother about the top collisions, they will be used for something else.)
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)
CodePudding user response:
The movement of the players can be calculated by subtracting the left from the right moment:
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
# [...]
To prevent the players from sticking together, you need to check whether P1
is to the left or right of P2
. Stop the player moving towards the other player:
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
# [...]