首页 > 解决方案 > 游戏敌人随机消失

问题描述

我正在自学 python 3,并使用 pygame 创建基于 python 的游戏,但遇到了两个问题。

为了在这里发帖,我把我的游戏降到了最低限度,但仍然有很多,对此我深表歉意。您实际上必须能够运行我的游戏才能看到问题,因此以下是复制问题所需的最低代码。我去掉了所有非必需品、墙壁、武器、字符类型和图像,并用块替换它们,这样你就可以在 Python 3 中复制、粘贴和运行它。

这个游戏是一个“生存每一轮”类型的游戏。

每个级别,一次应该有更多的敌人在屏幕上允许。当玩家射击它们时,它们会被移除,但会生成另一个代替它的位置。

我有两个主要问题。

  1. 我的代码中目前(应该)从精灵列表中删除敌人精灵的唯一部分是他们是否被玩家射击,或者他们与玩家接触。大约每 20 个左右的敌人,一个就会消失,我不知道为什么。

  2. 据我所知,我设置了敌人生成点,以便它们仅在任何方向至少 500 像素距离时才会生成,但它们仍然偶尔会生成在玩家上方。

复制这些的最好方法是玩前几个关卡,并特别注意敌人的消失或超近距离的产卵。它似乎是 rng 所以可能需要一些尝试。

我在代码中加入了注释,试图让你不必扫描整个东西。

import pygame,math,random,sys
#Colors
black       = (0,0,0)
white       = (255,255,255)
red         = (188,13,13)
orange      = (188,13,13)
yellow      = (188,188,13)
green       = (101,188,13)
blue_green  = (13,188,100)
blue        = (13,101,188)
purple      = (100,13,188)
magenta     = (188,13,101)
background1 = (93,58,23)
texture_1_1 = (116,71,25)
texture_1_2 = (75,57,31)
texture_1_3 = (105,77,49)
class Elven_Arrow_up(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface([4,4])
        self.image.fill(black)
        self.rect = self.image.get_rect()
    def update(self):
        self.rect.y -= 4
class Elven_Arrow_down(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface([4,4])
        self.image.fill(black)
        self.rect = self.image.get_rect()
    def update(self):
        self.rect.y += 4
class Elven_Arrow_left(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface([4,4])
        self.image.fill(black)
        self.rect = self.image.get_rect()
    def update(self):
        self.rect.x -= 4
class Elven_Arrow_right(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface([4,4])
        self.image.fill(black)
        self.rect = self.image.get_rect()
    def update(self):
        self.rect.x += 4
class Player(pygame.sprite.Sprite):
    def __init__(self,health,speed, x, y):
        super().__init__()
        self.health = health
        self.speed = speed
        self.image = pygame.Surface([32,32])
        self.image.fill(blue)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.change_x = 0
        self.change_y = 0
    def changespeed(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
class Enemy (pygame.sprite.Sprite):
    def __init__(self,speed,health,points):
        super().__init__()
        self.image = pygame.Surface([32,32])
        self.image.fill(red)
        self.rect = self.image.get_rect()
        self.speed = speed
        self.health = health
        self.points = points
    def update(self):
        dirvect = pygame.math.Vector2(player.rect.x - self.rect.x,
                                      player.rect.y - self.rect.y)
        dirvect.normalize()
        dirvect.scale_to_length(self.speed)
        self.rect.move_ip(dirvect)
class GameState():
    def __init__(self):
        self.state = 'intro'
    def intro(self):
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                done = True
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                self.state = 'level'
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    self.state = 'level'
        screen.fill(white)
        score_font = pygame.font.SysFont('Calibri', 25, True, False)
        score_text = score_font.render('Click the Space Bar to Begin.',True,black)
        screen.blit(score_text,(screen_width/2 - 180,screen_height/2 + 250))
        pygame.display.flip()
    def game_over(self):
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                done = True
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                global enemy_list
                global all_sprites_list
                global player
                global score
                global max_num_of_enemies
                global level
                global score_needed
                global score_needed_constant
                global score_needed_add
                global score_needed_add_constant
                max_num_of_enemies = max_num_of_enemies_constant
                enemy_list = pygame.sprite.Group()
                all_sprites_list = pygame.sprite.Group()
                player = Player(10,3,screen_width/2-3,screen_width/2,cinder_image)
                all_sprites_list.add(player)
                score_needed = score_needed_constant
                score_needed_add = score_needed_add_constant
                score = 0
                self.state = 'intro'
        screen.fill(black)
        score_font = pygame.font.SysFont('Calibri', 25, True, False)
        score_text = score_font.render("Click to continue.",True,white)
        level_text = score_font.render("You got to Level: " + str(level),True,white)
        screen.blit(score_text,(screen_width/2 + 200,screen_height/2 + 350))
        screen.blit(level_text,(10,10))
        pygame.display.flip()

#Below this line ends the level, removes all sprites from display lists, and returns the player to the center of the screen
    def level_complete(self):
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                done = True
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:    
                    global enemy_list
                    global all_sprites_list
                    global player
                    global score
                    global max_num_of_enemies
                    global max_num_of_enemies_constant
                    global level
                    enemy_list = pygame.sprite.Group()
                    all_sprites_list = pygame.sprite.Group()
                    all_sprites_list.add(player)
                    player.change_x = 0
                    player.change_y = 0
                    player.rect.x = screen_width/2
                    player.rect.y = screen_width/2
                    player.update()
                    self.state = 'level'
        screen.fill(blue)
        score_font = pygame.font.SysFont('Calibri', 25, True, False)
        continue_text = score_font.render("Release all keys, and Press the Spacebar to Continue.",True,white)
        level_text = score_font.render("You Completed level " + str(level-1) + "",True,white)
        screen.blit(continue_text,(50,screen_height - 30))
        screen.blit(level_text,(screen_width/2-100,screen_height/2))
        pygame.display.flip()
#Above this line ends the level, removes all sprites from display, and returns the player to the center of the screen

#Below this line is the main game loop.
    def level(self):
        global Enemy
        global enemy_list
        global score
        global player
        global all_sprites_list
        global max_num_of_enemies
        global level
        global score_needed
        global score_needed_add
        pygame.mouse.set_visible(1)
        
#Below this line spawns enemy's, if there are less enemy's than the max number of enemies AND they are far enough from the player
        if len(enemy_list.sprites()) < max_num_of_enemies: 
            x = random.randrange(-500,screen_width+500)
            y = random.randrange(-500,screen_height+500) 
            spawn = True
            for enemy in enemy_list:
                ex, ey = enemy.rect.center
                distance = math.hypot(ex - x, ey - y)
                if distance < minimum_distance: 
                    spawn = False
                    break
            if spawn:
                speed = 1.5
                health = 1
                points = 1
                enemy = Enemy(speed,health,points)
                enemy.rect.center = x, y
                enemy_list.add(enemy)
                all_sprites_list.add(enemy)
#Above this line spawns enemy's, if there are less enemy's than the max number of enemies AND they are far enough from the player

#Below this line determines when the level will end, increases the number of enemies allowed on the screen, and sends you to the level complete page
        if level < 1:
            level = 1
        elif score >= score_needed:
            level +=1
            max_num_of_enemies += 3
            score_needed += score_needed_add
            score_needed_add += 5
            player.health += 1
            self.state = 'level_complete'

#Above this line determines when the level will end, increases the number of enemies allowed on the screen, and sends you to the level complete page
        for event in pygame.event.get():
            if event.type == pygame.QUIT: 
                done = True
                pygame.quit()
                sys.exit()
            if player.health <= 0:
                self.state = 'game_over'
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_a:
                    player.changespeed(-3, 0)
                elif event.key == pygame.K_d:
                    player.changespeed(3, 0)
                elif event.key == pygame.K_w:
                    player.changespeed(0, -3)
                elif event.key == pygame.K_s:
                    player.changespeed(0, 3)
                elif event.key == pygame.K_LEFT:
                    projectile = Elven_Arrow_left()
                    projectile.rect.x = player.rect.x + 3
                    projectile.rect.y = player.rect.y + 8
                    projectile_list.add(projectile)
                    all_sprites_list.add(projectile)
                elif event.key == pygame.K_RIGHT:
                    projectile = Elven_Arrow_right()
                    projectile.rect.x = player.rect.x + 3
                    projectile.rect.y = player.rect.y + 8
                    projectile_list.add(projectile)
                    all_sprites_list.add(projectile)
                elif event.key == pygame.K_UP:
                    projectile = Elven_Arrow_up()
                    projectile.rect.x = player.rect.x + 3
                    projectile.rect.y = player.rect.y + 8
                    projectile_list.add(projectile)
                    all_sprites_list.add(projectile)
                elif event.key == pygame.K_DOWN:
                    projectile = Elven_Arrow_down()
                    projectile.rect.x = player.rect.x + 3
                    projectile.rect.y = player.rect.y + 8
                    projectile_list.add(projectile)
                    all_sprites_list.add(projectile)
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_a:
                    player.changespeed(3, 0)
                elif event.key == pygame.K_d:
                    player.changespeed(-3, 0)
                elif event.key == pygame.K_w:
                    player.changespeed(0, 3)
                elif event.key == pygame.K_s:
                    player.changespeed(0, -3)
        all_sprites_list.update()
        if player.rect.y > screen_height + 10:
            player.rect.y = -10
        elif player.rect.y < -10:
            player.rect.y = screen_height + 10
        if player.rect.x > screen_width + 10:
            player.rect.x = -10
        elif player.rect.x < -10:
            player.rect.x = screen_width + 10
            
#Below this line removes an enemy if they are shot by the player, and gives them a point
        for projectile in projectile_list:
            player_hit_list = pygame.sprite.spritecollide(projectile,enemy_list,True)
            for enemy in player_hit_list:
                projectile_list.remove(projectile)
                all_sprites_list.remove(projectile)
                score += 1
#Above this line removes an enemy if they are shot by the player, and gives them a point
                
            if projectile.rect.y < -10:
                projectile_list.remove(projectile)
                all_sprites_list.remove(projectile)
            elif projectile.rect.y > screen_height + 10:
                projectile_list.remove(projectile)
                all_sprites_list.remove(projectile)
            elif projectile.rect.x < -10:
                projectile_list.remove(projectile)
                all_sprites_list.remove(projectile)
            elif projectile.rect.x > screen_width + 10:
                projectile_list.remove(projectile)
                all_sprites_list.remove(projectile)
                
#Below this line removes an enemy if they make contact with the player.
        for block in enemy_list:
            enemy_hit_list = pygame.sprite.spritecollide(player, enemy_list, True)
            for block in enemy_hit_list:
                enemy_list.remove(block)
                all_sprites_list.remove(block)
                player.health -= block.points
#Above this line removes an enemy if they make contact with the player.

        screen.fill(background1)
        for i in texture_list1:
            texture1 = pygame.draw.rect(screen,texture_1_1,[i[0],i[1],10,10])
        for i in texture_list2:
            texture1 = pygame.draw.rect(screen,texture_1_2,[i[0],i[1],10,10])
        for i in texture_list3:
            texture1 = pygame.draw.rect(screen,texture_1_3,[i[0],i[1],10,10])    
        all_sprites_list.draw(screen)
        score_font = pygame.font.SysFont('Calibri', 25, True, False)
        score_text = score_font.render("Score: " + str(score),True,blue_green)
        noob_text = score_font.render("w,a,s,d to move, arrow keys to shoot. Good luck.",True,white)
        level_text = score_font.render("Level: " + str(level),True,blue_green)
        screen.blit(score_text,[10,10])
        screen.blit(level_text,[screen_width - 150,10])
        if score < 10:
            screen.blit(noob_text,[100,10])
        if player.health >= health_status[0]:
            health_text = score_font.render("Health: " + str(player.health),True,blue_green)
        elif player.health >= health_status[1]:
            health_text = score_font.render("Health: " + str(player.health),True,green)
        elif player.health >= health_status[2]:
            health_text = score_font.render("Health: " + str(player.health),True,yellow)
        elif player.health >= health_status[3]:
            health_text = score_font.render("Health: " + str(player.health),True,orange)
        elif player.health >= health_status[4]:
            health_text = score_font.render("Health: " + str(player.health),True,red)
        screen.blit(health_text, [10,40])
        pygame.display.flip()
#Above this line is the main game loop
        
    def state_manager(self):
        if self.state == 'intro':
            self.intro()
        if self.state == 'game_over':
            self.game_over()
        if self.state == 'level':
            self.level()
        if self.state == 'level_complete':
            self.level_complete()
pygame.init()
screen_width  = 1000
screen_height = 800
screen = pygame.display.set_mode([screen_width, screen_height])
game_state = GameState()
enemy_list = pygame.sprite.Group()
projectile_list = pygame.sprite.Group()
item_list = pygame.sprite.Group()
texture_list1 = []
texture_list2 = []
texture_list3 = []
all_sprites_list = pygame.sprite.Group()
player = Player(10,3,screen_width/2 - 3,screen_height/2)
all_sprites_list.add(player)
for i in range(50):
    x=random.randrange(screen_width)
    y=random.randrange(screen_width)
    texture_list1.append([x,y])
for i in range(50):
    x=random.randrange(screen_width)
    y=random.randrange(screen_width)
    texture_list2.append([x,y])
for i in range(50):
    x=random.randrange(screen_width)
    y=random.randrange(screen_width)
    texture_list3.append([x,y])
#Below this line sets the starting points, and constants through the game.
score = 0
health_status = (8,6,4,2,-100)
level = 1
minimum_distance = 500
score_needed_constant = 15
score_needed = score_needed_constant
score_needed_add_constant = 15
score_needed_add = score_needed_add_constant
max_num_of_enemies_constant = 8
max_num_of_enemies = max_num_of_enemies_constant
#Above this line sets the starting points, and constants through the game.

#Below this line starts, and ends the game loop
done = False
clock = pygame.time.Clock()
while not done:
    game_state.state_manager()
#Above this line starts, and ends the game loop

    clock.tick(60)

标签: pythonpython-3.xpygame

解决方案


推荐阅读