问题
I am making a capture the flag type game. From the code below, I have the fundamentals set up. However, I don't know how I stop the flag from moving when the character hits a wall. Can anyone help me with this? As you can see if you run the code, the flag is effectively picked up by the character and carried but the flag will not stop if the character hits a wall. I want the flag to stay on the right side of the character as well. Thanks for any help. (CODE HAS BEEN UPDATED SINCE ORIGINAL POST)
import pygame
def start():
pygame.init()
BLUE = (0, 0, 128)
RED = (204, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
screen = pygame.display.set_mode((1920,1080), flags=pygame.FULLSCREEN)
pygame.display.set_caption("Recovery")
clock = pygame.time.Clock()
bigJoe = pygame.image.load("bigJoe.png")
characterSelected = bigJoe
game(BLACK, WHITE, BLUE, RED, screen, clock, characterSelected, bigJoe)
def game(BLACK, WHITE, BLUE, RED, screen, clock, characterSelected, bigJoe):
if characterSelected == bigJoe:
gameCharacter = "gameJoe.png"
all_sprite_list = pygame.sprite.Group()
playerList = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
flagList = pygame.sprite.Group()
playerFlag = pygame.sprite.Group()
flag = Flag(1810,540)
flagList.add(flag)
'''Design of Map Below'''
topWall = Wall(0, 0, 1920, 5, BLUE)
bottomWall = Wall(0, 1075, 1920, 5, BLUE)
leftWall = Wall(0, 0, 5, 1080, BLUE)
rightWall = Wall(1915, 0, 5, 1080, BLUE)
baseWall1 = Wall(5, 300, 150, 75, WHITE)
baseWall2 = Wall(5, 375, 100, 330, WHITE)
baseWall3 = Wall(5, 705, 150, 75, WHITE)
baseSquare = Wall(30, 530, 40, 40, RED)
wall1 = Wall(400, 400, 200, 300, RED)
wall_list.add(topWall, bottomWall, leftWall, rightWall, baseWall1, wall1, baseWall2, baseWall3)
all_sprite_list.add(topWall, bottomWall, leftWall, rightWall, baseWall1, wall1, baseWall2, baseWall3, baseSquare, flag)
'''Adding Character to Game'''
player = Player(110, 550, gameCharacter)
flag.player = playerFlag
player.wall = wall_list
all_sprite_list.add(player)
playerFlag.add(player, flag)
playerList.add(player)
flag.player = player
flag.carried = playerFlag
flag.walls = wall_list
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-3, 0)
flag.moveFlag(-3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(3, 0)
flag.moveFlag(3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -3)
flag.moveFlag(0, -3,)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 3)
flag.moveFlag(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(3, 0)
flag.moveFlag(3, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-3, 0)
flag.moveFlag(-3, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 3)
flag.moveFlag(0, 3)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -3)
flag.moveFlag(0, -3)
all_sprite_list.update()
screen.fill(BLACK)
all_sprite_list.draw(screen)
pygame.display.flip()
clock.tick(75)
start()
On a separate file
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gameCharacter):
super().__init__()
self.image = pygame.image.load(gameCharacter)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
self.wall = None
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_x > 0:
self.rect.right = wall.rect.left
else:
self.rect.left = wall.rect.right
self.rect.y += self.change_y
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_y > 0:
self.rect.bottom = wall.rect.top
else:
self.rect.top = wall.rect.bottom
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height,color):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Flag(pygame.sprite.Sprite):
def __init__(self, x, y,):
super().__init__()
self.image = pygame.image.load("flag.png")
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
def moveFlag(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
hit = False
allowMove = True
flagCharacterList = pygame.sprite.spritecollide(self, self.carried, False)
for i in flagCharacterList:
if len(flagCharacterList) == 2:
hit = True
else:
hit = False
block_hit_list = pygame.sprite.groupcollide(self.walls, self.carried, False, False)
for block in block_hit_list:
if len(block_hit_list) == 1:
allowMove = False
else:
allowMove = True
if hit and allowMove:
self.rect.x += self.change_x
self.rect.y += self.change_y
回答1:
The flag doesn't move bit itself. bit the player carries the flag. Possibly the player can carry more than 1 flag.
Remove the collision detection from the method Flag.update:
class Flag(pygame.sprite.Sprite):
def __init__(self, x, y,):
super().__init__()
#self.image = pygame.image.load("flag.png")
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
def moveFlag(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
Add an attribute self.flags to the player and move all the flags contained in the list by the same amount as the player:
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gameCharacter):
# [...]
self.flags = []
# [...]
def update(self):
current_pos = (self.rect.x, self.rect.y)
self.rect.x += self.change_x
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_x > 0:
self.rect.right = wall.rect.left
else:
self.rect.left = wall.rect.right
self.rect.y += self.change_y
wallHitList = pygame.sprite.spritecollide(self, self.wall, False)
for wall in wallHitList:
if self.change_y > 0:
self.rect.bottom = wall.rect.top
else:
self.rect.top = wall.rect.bottom
for flag in self.flags:
flag.rect.x += self.rect.x - current_pos[0]
flag.rect.y += self.rect.y - current_pos[1]
flag.move() is not needed any more. But if the player hits the flag, then the flag is add player.flags. That caused, that the plyer carries the flag:
def game(BLACK, WHITE, BLUE, RED, screen, clock, characterSelected, bigJoe):
# [...]
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: player.changespeed(-3, 0)
elif event.key == pygame.K_RIGHT: player.changespeed(3, 0)
elif event.key == pygame.K_UP: player.changespeed(0, -3)
elif event.key == pygame.K_DOWN: player.changespeed(0, 3)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT: player.changespeed(3, 0)
elif event.key == pygame.K_RIGHT: player.changespeed(-3, 0)
elif event.key == pygame.K_UP: player.changespeed(0, 3)
elif event.key == pygame.K_DOWN: player.changespeed(0, -3)
if flag not in player.flags:
if pygame.sprite.collide_rect(flag, player):
player.flags.append(flag)
flag.rect.left = player.rect.right
# [...]
来源:https://stackoverflow.com/questions/62073323/pygame-movement-of-flag-and-character-with-walls