Проблемы с рабочим щитом в Pygame Platformer - PullRequest
0 голосов
/ 04 февраля 2020

Давненько возился с Pygame, и я хотел сделать 2D-игру, в которой у игрока есть доступ к щиту, который блокирует пули противника, только если они того же цвета, что и сам щит. Я застрял над этой проблемой уже несколько недель и надеялся, что кто-нибудь здесь сможет мне помочь, если это возможно. Это мой первый пост на этом сайте, поэтому извините, если он не самый лучший. Это сокращенная версия кода, расположенного ниже….

import pygame
import random

pygame.init()

win = pygame.display.set_mode((600, 600))

pygame.display.set_caption("First Game")

walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
             pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
             pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.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('L5.png'), pygame.image.load('L6.png'),
            pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]

walkRight2 = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'),
              pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'),
              pygame.image.load('R6E.png'), pygame.image.load('R5E.png'), pygame.image.load('R4E.png')]
walkLeft2 = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'),
             pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'),
             pygame.image.load('L6E.png'), pygame.image.load('L5E.png'), pygame.image.load('L4E.png')]

bg = pygame.image.load('Bg_1.png').convert()


clock = pygame.time.Clock()

class player(object):
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5
        self.isjump = False
        self.jumpcount = 10
        self.left = False
        self.right = False
        self.walkcount = 0
        self.standing = True
        self.hitbox = (self.x + 20, self.y + 15, self.width - 40, self.height - 20)
        self.right_shield = (self.x + 15, self.y, self.width - 35, self.height)
        self.left_shield = (self.x + 17, self.y, self.width - 35, self.height)
        self.lifes = 35
    def draw(self, win):
        if self.walkcount + 1 >= 27:
            self.walkcount = 0

        if not (self.standing):
            if self.left == True:
                win.blit(walkLeft[self.walkcount // 3], (self.x, self.y))
                self.walkcount += 1
            elif self.right == True:
                win.blit(walkRight[self.walkcount // 3], (self.x, self.y))
                self.walkcount += 1
        else:
            if self.right == True:
                win.blit(walkRight[0], (self.x, self.y))
            else:
                win.blit(walkLeft[0], (self.x, self.y))
        self.hitbox = (self.x + 20, self.y + 15, self.width - 40, self.height - 20)
        self.right_shield = (self.x + 15, self.y, self.width - 35, self.height)
        self.left_shield = (self.x + 17, self.y, self.width - 35, self.height)
    def hit(self, win):
        global run
        global bad_guys_kiled
        if self.lifes > 0:
            self.lifes -= 1
            if self.lifes % 2 == 0:
                pass
        if self.lifes <= 0:
            run = False
            print("You have ran out of lifes!")
            print("Thank you for playing!")

class enemy(object):
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5
        self.boss_vel = 2
        self.left = True
        self.right = False
        self.walkcount = 0
        self.isjump = False
        self.jumpcount = 10
        self.standing = True
        self.hitbox = (self.x + 20, self.y + 10, self.width - 40, self.height - 20)
        self.shootloop1 = 0
        self.bullets2 = []
        self.bullets3 = []
        self.lifes = 2
        self.half_health = False
    def draw(self, win):
        global half_health
        global bad_guys_kiled
        if bad_guys_kiled <= 25:
            if self.walkcount + 1 >= 27:
                self.walkcount = 0
            if not (self.standing):
                if self.left == True:
                    win.blit(walkLeft2[self.walkcount // 3], (self.x, self.y))
                    self.walkcount += 1
                elif self.right == True:
                    win.blit(walkRight2[self.walkcount // 3], (self.x, self.y))
                    self.walkcount += 1
            else:
                if self.right == True:
                    win.blit(walkRight2[0], (self.x, self.y))
                else:
                    win.blit(walkRight2[0], (self.x, self.y))
            self.hitbox = (self.x + 20, self.y + 10, self.width - 40, self.height - 20)
            enemy_health = (self.x + 25, self.y + 5, self.width - 40, self.height - 70)
            pygame.draw.rect(win, (0, 255, 0), enemy_health)
            if self.half_health == True:
                pygame.draw.rect(win, (255, 0, 0), (self.x + 50, self.y + 5, self.width - 75, self.height - 70))
    def draw2(self, win):
        global half_health
        global bad_guys_kiled
        if self.walkcount + 1 >= 27:
            self.walkcount = 0
        if not (self.standing):
            if self.left == True:
                win.blit(walkLeft2[self.walkcount // 3], (self.x, self.y))
                self.walkcount += 1
            elif self.right == True:
                win.blit(walkRight2[self.walkcount // 3], (self.x, self.y))
                self.walkcount += 1
        else:
            if self.right == True:
                win.blit(walkRight2[0], (self.x, self.y))
            else:
                win.blit(walkRight2[0], (self.x, self.y))
        self.hitbox = (self.x + 20, self.y + 10, self.width - 40, self.height - 20)

        enemy_health = (self.x + 25, self.y + 5, self.width - 40, self.height - 70)
        pygame.draw.rect(win, (0, 255, 0), enemy_health)
        if self.half_health == True:
            pygame.draw.rect(win, (255, 0, 0), (self.x + 50, self.y + 5, self.width - 75, self.height - 70))
    def walk(self, win):
        global shield
        global drop_spot
        global drop
        global shield_health
        global bad_guys_kiled
        global temp_num
        global temp_number
        global colours
        global shield_colour
        global shield_number
        global bullet_colour
        global test_number
        bullet_colour = random.choice(colours)
        if bullet_colour == "blue":
            colour_number = (0, 0, 255)
            test_number = 0
        else:
            colour_number = (255, 0, 0)
            test_number = 1
        if temp_num == False:
            temp_number = random.randint(4, 34)
            temp_num = True
        if self.shootloop1 > 0:
            self.shootloop1 += 1
        if self.shootloop1 > int(temp_number):
            self.shootloop1 = 0
        if bad_guys_kiled <= 25 and not (main_menu):
            for bullet in self.bullets2:
                if man.left:
                    if int(shield_number) == int(test_number):
                        if bullet.y - bullet.radius < man.right_shield[1] + man.right_shield[3] and bullet.y + bullet.radius > man.right_shield[1]:
                            if bullet.x + bullet.radius > man.right_shield[0] and bullet.x - bullet.radius < man.right_shield[0] + man.right_shield[2]:
                                try:
                                    self.bullets2.pop(self.bullets2.index(bullet))
                                except ValueError:
                                    pass
                elif man.right:
                    if int(shield_number) == int(test_number):
                        if bullet.y - bullet.radius < man.left_shield[1] + man.left_shield[3] and bullet.y + bullet.radius > man.left_shield[1]:
                            if bullet.x + bullet.radius > man.left_shield[0] and bullet.x - bullet.radius < man.left_shield[0] + man.left_shield[2]:
                                try:
                                    self.bullets2.pop(self.bullets2.index(bullet))
                                except ValueError:
                                    pass
                elif int(shield_number) != int(test_number):
                    if bullet.y - bullet.radius < man.hitbox[1] + man.hitbox[3] and bullet.y + bullet.radius > man.hitbox[1]:
                        if bullet.x + bullet.radius > man.hitbox[0] and bullet.x - bullet.radius < man.hitbox[0] + man.hitbox[2]:
                            man.hit(win)
                            try:
                                self.bullets2.pop(self.bullets2.index(bullet))
                            except ValueError:
                                pass
                if bullet.x < 800 and bullet.x > -50:
                    bullet.x += bullet.vel
                else:
                    try:
                        self.bullets2.pop(self.bullets2.index(bullet))
                    except ValueError:
                        pass
            if self.left:
                facing = -1
            elif self.right:
                facing = 1
            if len(self.bullets2) < 7 and self.shootloop1 == 0:
                self.bullets2.append(projectile(round(self.x + self.width // 2), round(self.y + self.height // 2), 6, (colour_number),facing))
                self.shootloop1 = 1
            if self.x != -50:
                self.x -= self.vel
                self.right = False
                self.left = True
                self.standing = False
            else:
                for x in range(1, 200):
                    if self.x >= 700:
                        self.x = 650
                    self.half_health = False
                    self.x += self.vel
                    self.right = False
                    self.left = True
                    self.standing = False
        else:
            for bullet in self.bullets2:
                try:
                    self.bullets2.pop(self.bullets2.index(bullet))
                except ValueError:
                    pass

    def hit(self, win):
        global bad_guys_kiled
        global drop
        global drop_spot
        global drop_count
        global min
        global max
        global score
        Hit_noise.play()
        if self.lifes > 0:
            self.lifes -= 1
            self.half_health = True
        if self.lifes <= 0:
            random_number = random.randint(min, max)
            if bad_guys_kiled <= 25:
                if random_number == 1:
                    if drop_count != 1:
                        drop = True
                        drop_count += 1
                        drop_spot = [self.x + 20]
                        drop_spot += [self.y + 10]
                        drop_spot += [self.width - 40]
                        drop_spot += [self.height - 40]
                    else:
                        try:
                            max -= 1
                        except ValueError:
                            max = 20
            if bad_guys_kiled >= 25:
                drop_spot = []

            self.half_health = False
            self.x = self.x + 700
            self.lifes = 2
            bad_guys_kiled += 1
            score += 1

class projectile(object):
    def __init__(self, x, y, radius, colour, facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.colour = colour
        self.facing = facing
        self.vel = 8 * facing
    def draw(self, win):
        pygame.draw.circle(win, self.colour, (self.x, self.y), self.radius)
def redraw_game_window():
    global drop_spot
    global drop
    global bad_guys_kiled
    global jump_block
    global main_menu
    global run
    global count
    global score
    global shield
    global man_movement_block
    global shield_colour
    global bullet_colour
    global test_number
    global shield_number
    win.blit(bg, (0, 0))
    man.draw(win)
    print("man = ",shield_number)
    print("bullet =",test_number)
    text_score = font.render("Score:" + str(score), 1, (0, 0, 0))
    text_shield = font.render("Shield Colour:" + "temp", 1, (0, 0, 0))
    text_player_health = font.render("Player Health:" + str(man.lifes), 1, (0, 0, 0))
    win.blit(text_score, (450, 10))
    win.blit(text_shield, (225, 10))
    win.blit(text_player_health, (20, 10))

    if bad_guys_kiled <= 25:
        if drop == True:
            try:
                pygame.draw.rect(win, (0, 0, 255), (drop_spot[0], drop_spot[1], drop_spot[2], drop_spot[3]))
            except IndexError:
                pass
    if man.left == True and shield_colour == "blue":
        pygame.draw.rect(win, (0, 0, 255), (man.x + 17, man.y, man.width - 35, man.height), 2)
    elif not(main_menu) and shield_colour == "blue":
        pygame.draw.rect(win, (0, 0, 255), (man.x + 15, man.y, man.width - 35, man.height), 2)
    if man.right == True and shield_colour == "red":
        pygame.draw.rect(win, (255, 0, 0), (man.x + 17, man.y, man.width - 35, man.height), 2)
    elif not(main_menu) and shield_colour == "red":
        pygame.draw.rect(win, (255, 0, 0), (man.x + 15, man.y, man.width - 35, man.height), 2)
    if bad_guys_kiled <= 25 :
        bad_guy1.draw(win)
        bad_guy2.draw(win)
        bad_guy3.draw(win)

    for bullet in bullets:
        bullet.draw(win)
    for bullet in bad_guy1.bullets2:
        bullet.draw(win)
    for bullet in bad_guy2.bullets2:
        bullet.draw(win)
    for bullet in bad_guy3.bullets2:
        bullet.draw(win)

    pygame.display.update()

def game_credits():
    pygame.draw.rect(win, (40, 26, 13), (0, 0, 650, 650))
    text_help = font.render("CONTROLS", 1, (0, 255, 0))
    text_help1 = font.render("UP ARROW = JUMP", 1, (255, 255, 255))
    text_help2 = font.render("LEFT ARROW = LEFT", 1, (255, 255, 255))
    text_help3 = font.render("RIGHT ARROW = RIGHT", 1, (255, 255, 255))
    text_help4 = font.render("ZERO ON NUMPAD = FIRE", 1, (255, 255, 255))
    text_help5 = font.render("P = PAUSE", 1, (255, 255, 255))
    text_help6 = font.render("O = UNPAUSE ", 1, (255, 255, 255))
    text_help7 = font.render("(PRESSING P WILL NOT ", 1, (255, 255, 255))
    text_help8 = font.render("UNPAUSE THE GAME !)", 1, (255, 255, 255))
    text_help9 = font.render("B = SHIELD", 1, (255, 255, 255))
    win.blit(text_help, (22, 50))
    win.blit(text_help1, (22, 100))
    win.blit(text_help2, (22, 150))
    win.blit(text_help3, (22, 200))
    win.blit(text_help4, (22, 250))
    win.blit(text_help5, (22, 300))
    win.blit(text_help6, (22, 350))
    win.blit(text_help7, (22, 400))
    win.blit(text_help8, (22, 450))
    win.blit(text_help9, (22, 500))
# Main Loop #
Air_raid = pygame.mixer.Sound("Air raid.wav")
Godzilla_roar = pygame.mixer.Sound("Godzilla roar.wav")
Victory_noise = pygame.mixer.Sound("Victory noise.wav")
Gun_shot = pygame.mixer.Sound("Gun shot.wav")
Hit_noise = pygame.mixer.Sound("Hit noise.wav")
man = player(300, 450, 64, 64)
bad_guy1 = enemy(0, 450, 64, 64)
bad_guy2 = enemy(250, 450, 64, 64)
bad_guy3 = enemy(500, 450, 64, 64)
count = 0
bullets = []
shootloop = 0
bad_guys_kiled = 0
temp_num = False
temp_number = 0
drop = False
drop_spot = []
drop_count = 0
min = 1
max = 20
main_menu = False
main_spawn = False
score = 0
man_movement_block = False
shield_count = 0
colours = ["blue", "red"]
shield_colour = "blue"
bullet_colour = None
shield_number = 0
test_number = 0
font = pygame.font.SysFont("Calibri Light", 25, True)
run = True
while run == True:
    temp_number = random.randint(4, 34)
    if man.y >= 500:
        man.y = 450
    clock.tick(27)
    shield = True
    if shootloop > 0:
        shootloop += 1
    if shootloop > 5:
        shootloop = 0
    if shield_count > 0:
        shield_count += 1
    if shield_count > 5:
        shield_count = 0
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    for bullet in bullets:
        if bad_guys_kiled <= 25:
            if bullet.y - bullet.radius < bad_guy1.hitbox[1] + bad_guy1.hitbox[3] and bullet.y + bullet.radius > bad_guy1.hitbox[1]:
                if bullet.x + bullet.radius > bad_guy1.hitbox[0] and bullet.x - bullet.radius < bad_guy1.hitbox[0] + bad_guy1.hitbox[2]:
                    bad_guy1.hit(win)
                    bullets.pop(bullets.index(bullet))
            if bullet.y - bullet.radius < bad_guy2.hitbox[1] + bad_guy2.hitbox[3] and bullet.y + bullet.radius > bad_guy2.hitbox[1]:
                if bullet.x + bullet.radius > bad_guy2.hitbox[0] and bullet.x - bullet.radius < bad_guy2.hitbox[0] + bad_guy2.hitbox[2]:
                    bad_guy2.hit(win)
                    try:
                        bullets.pop(bullets.index(bullet))
                    except ValueError:
                        pass
            if bullet.y - bullet.radius < bad_guy3.hitbox[1] + bad_guy3.hitbox[3] and bullet.y + bullet.radius > bad_guy3.hitbox[1]:
                if bullet.x + bullet.radius > bad_guy3.hitbox[0] and bullet.x - bullet.radius < bad_guy3.hitbox[0] + bad_guy3.hitbox[2]:
                    bad_guy3.hit(win)
                    try:
                        bullets.pop(bullets.index(bullet))
                    except ValueError:
                        pass

        try:
            if man.hitbox[1] - (man.hitbox[3] / 2) < drop_spot[1] + (drop_spot[3] / 2) and man.hitbox[1] + (man.hitbox[3] / 2) > drop_spot[1]:
                if man.hitbox[0] + (man.hitbox[3] / 2) > drop_spot[0] and man.hitbox[0] - (man.hitbox[3] / 2) < drop_spot[0] + drop_spot[2]:
                    Gun_shot.stop()
                    if man.lifes <= 35:
                        man.lifes += 10
                    else:
                        Gun_shot.stop()
                        pass
                    try:
                        bullets.pop(bullets.index(bullet))
                        drop = False
                        drop_count = 0
                        drop_spot = []
                    except ValueError:
                        pass
        except:
            pass
        if bullet.x < 650 and bullet.x > -20:
            bullet.x += bullet.vel
        else:
            try:
                bullets.pop(bullets.index(bullet))
            except ValueError:
                pass
    keys = pygame.key.get_pressed()
    if keys[pygame.K_KP0] and not (main_menu):
        if man.left:
            facing = -1
        elif man.right:
            facing = 1
        else:
            facing = -1
        if len(bullets) < 5 and shootloop == 0:
            Gun_shot.play()
            bullets.append(projectile(round(man.x + man.width // 2), round(man.y + man.height // 2), 6, (0, 0, 255), facing))
            shootloop = 1
    if keys[pygame.K_LEFT] and man.x > man.vel and not(man_movement_block):
        man.x -= man.vel
        man.left = True
        man.right = False
        man.standing = False
    elif keys[pygame.K_RIGHT] and man.x < 620 - man.vel - man.width:
        man.x += man.vel
        man.right = True
        man.left = False
        man.standing = False
    elif keys[pygame.K_b] and shield_count == 0:
        if shield_colour == "blue":
            shield_colour = "red"
            shield_number = 1
        else:
            shield_colour = "blue"
            shield_number = 0
        shield_count = 1
    if not (man.isjump):
        if keys[pygame.K_UP]:
            man.isjump = True
            man.walkcount = 0

    else:
        if man.jumpcount >= -10:
            neg = 1
            if man.jumpcount < 0:
                neg = -1
            man.y -= (man.jumpcount ** 2) / 2 * neg
            man.jumpcount -= 1
        else:
            man.isjump = False
            man.jumpcount = 10

    bad_guy1.walk(win)
    bad_guy2.walk(win)
    bad_guy3.walk(win)

    redraw_game_window()

pygame.quit()

1 Ответ

0 голосов
/ 20 февраля 2020

Проблема вызвана кодом в методе walk класса enemy, где вы проверяете наличие столкновений между пулями противника и игроком.

if man.left:
    ... # block bullets with the shield when the player is pointing left
elif man.right:
    ... # block bullets with the shield when the player is pointing right
elif int(shield_number) != int(test_number):
    ... # if the player has been hit, call man.hit

Поскольку вы использовали elif, код, который проверяет, был ли игрок поражен (и вызывает man.hit), будет выполняться только в том случае, если оба значения man.left и man.right имеют значение false, что никогда не происходит. Простое изменение его с elif на if должно решить вашу проблему.

if man.left:
    ... # block bullets with the shield when the player is pointing left
elif man.right:
    ... # block bullets with the shield when the player is pointing right

if int(shield_number) != int(test_number):
    ... # if the player has been hit, call man.hit
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...