我如何在 pygame 中生成多个敌人

How do I spawn multiple enemies in pygame

我正在开发一款游戏,该游戏涉及用户控制宇宙飞船(代码中的玩家)并射击在地表随机产生的外星人(代码中的敌人)。

截至目前,我一次只成功制作了一个外星人出生点。我如何添加 6 个外星人同时在子弹击中后重生(在表面的随机位置)?

import pygame
import random
import math

# for initialising pygame (req for every pygame app)
pygame.init()

# making the basic window (dimensions must be written inside a tuple )
screen = pygame.display.set_mode((500, 500))

# background
background = pygame.image.load('C:/Users/aryan/Downloads/background.jpg')

# load and set the logo
logo = pygame.image.load('C:/Users/aryan/Downloads/bp.png')  # directory of logo
pygame.display.set_icon(logo)
pygame.display.set_caption("space wars")  # program name

# define a variable to control the main loop
running = True

# player
playerimg = pygame.image.load('C:/Users/aryan/Downloads/spaceship.png')
playerX = 218  # x and y coordinates of image
playerY = 350
playerxchange = 0  # this will be the change in movement in x direction of our image
playerychange = 0  # this will be the change in movement in y direction of our image


def player(x, y):
    screen.blit(playerimg, (x, y))  # blit draws our image on the surface(basically the background)
    # syntax for blit(imagename, (xcoordinate,ycoordinate))


# enemy
enemyimg = pygame.image.load('C:/Users/aryan/Downloads/enemy.png')
enemyX = random.randint(0, 464)
enemyY = random.randint(0, 30)
enemyxchange = 0.2
enemyychange = 40

# game over
overimg = pygame.image.load('C:/Users/aryan/Downloads/gameover.png')

# bullet
bulletimg = pygame.image.load('C:/Users/aryan/Downloads/bullet.png')
bulletX = 0
bulletY = 350
bulletxchange = 0
bulletychange = 1
bullet_state = "ready"              # "ready" you cant see bullet on screen
                                    # "fire" you can see bullet firing

bullets = []                        # bullets is a list that contains the coordinates of every bullet

score = 0

font30 = pygame.font.SysFont(None, 30)

    # Functions
def enemy(x, y):
    screen.blit(enemyimg, (x, y))  # blit draws our image on the surface(basically the background)
    # syntax for blit(imagename, (xcoordinate,ycoordinate))


def firebullet(x, y):
    global bullet_state
    bullet_state = "ready"
    bullets.append([x + 12, y + 6]) # Creating a new bullet


def iscollision(enemyX, enemyY, bulletX, bulletY):
    distance = math.sqrt(math.pow(enemyX-bulletX, 2)+ math.pow(enemyY-bulletY,2))     # distance formula
    if distance <= 20:
        return True
    else:
        return False

def TextScore(game):
    text2 = font30.render("Your Score is: " + str(game), True, (37, 97, 188))
    screen.blit(text2, (10, 45))



# main loop
while running:
    screen.fill((120, 120, 120))  # in order (r, g, b) . (0, 0, 0) is black (255, 0, 0) is red...
    screen.blit(background, (0, 0))
    # event handling, gets all event from the event queue
    for event in pygame.event.get():
        # only do something if the event is of type QUIT
        if event.type == pygame.QUIT:
            # change the value to False, to exit the main loop
            running = False

        # checking keystroke
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                playerxchange += 0.3  # change in movement will be 0.2 towards the right
            if event.key == pygame.K_LEFT:
                playerxchange -= 0.3  # change in movement will be 0.2 towards the right
            if event.key == pygame.K_UP:
                playerychange -= 0.3
            if event.key == pygame.K_DOWN:
               playerychange += 0.3
            if event.key == pygame.K_SPACE:
                bullet_state = "fire"
                firebullet(playerX, playerY)
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN or event.key == pygame.K_UP:
                playerxchange = 0
                playerychange = 0

    playerY += playerychange
    playerX += playerxchange  # the value of playerx changes by +- 0.1 depending on keystroke

    if playerX <= -64:  # this teleports the spaceship from left end to right end
        playerX = 564
    elif playerX >= 564:  # this teleports spaceship from right end to left
        playerX = -64

    if playerY >= 436:  # this prevents spaceship from leaving vertically
        playerY = 436
    if playerY <= 0:
        playerY = 0

    # enemy movement
    enemyX += enemyxchange

    if enemyY >= 476:
        enemyY = 476
        enemyYchange = 0
        enemyXchange = 0

    if enemyX <= 0:
        enemyxchange = 0.2
        enemyY += enemyychange
    elif enemyX >= 465:
        enemyxchange = -0.2
        enemyY += enemyychange

    # bullet movement
    if bullet_state == "fire":
        firebullet(playerX, playerY)


    for bullet in bullets:
        screen.blit(bulletimg, (bullet[0], bullet[1]))  # Print a bullet
        bullet[0] -= bulletxchange  # Updates its position
        bullet[1] -= bulletychange
        if bullet[1] < 0:
            bullets.remove(bullet)

    # collision
    for bullet in bullets:       # Use a for-loop to iterate through all the bullets in the list.
        collision = iscollision(enemyX, enemyY, bullet[0], bullet[1])
        if collision:               # Test if a single bullet collides with the enemy inside the loop.
            score += 1
            print(score)
            bullets.remove(bullet)  # Remove the bullet from the list when it collides with the enemy.
            enemyX = random.randint(0, 476)     # if collision takes place, alien respawns
            enemyY = random.randint(0, 30)



    TextScore(score)
    player(playerX, playerY)  # player method is called AFTER screen.fill otherwise the screen will fill after image has been blitted
    enemy(enemyX, enemyY)

    pygame.display.update()  # necessary for events to keep updating

使用 movedraw 方法创建 Enemy class(参见 Classes):

class Enemy:
    def __init__(self):
        self.x = random.randint(0, 476)
        self.y = 20
        self.moveX = 0.2
        self.moveY = 40
        
    def move(self):
        self.x += self.moveX 

        if self.y >= 476:
            self.y = 476
            self.moveY = 0
            self.moveX = 0

        if self.x <= 0:
            self.moveX = 0.2
            self.y += self.moveY
        elif self.x >= 465:
            self.moveX = -0.2
            self.y += self.moveY

    def draw(self):
        screen.blit(enemyimg, (self.x, self.y))

创建一些敌人并将它们存储在列表(enemy_list )中而不是全局变量enemyXenemyYenemyxchangeenemyychange:

enemyimg = pygame.image.load('C:/Users/aryan/Downloads/enemy.png')

enemy_list = []
for i in range(5):
    new_enemy = Enemy()
    enemy_list.append(new_enemy)

movedraw 循环中的敌人。对于碰撞测试,您需要检查是否有任何子弹击中了任何敌人。因此,碰撞测试必须在嵌套循环中完成。请注意,通过项目符号的循环必须是内部循环,因为项目符号已从列表中删除:

# main loop
while running:
    # [...]

    for enemy in enemy_list:
        enemy.move() 

    # [...]

     # collision
    for enemy in enemy_list:
        for bullet in bullets:       # Use a for-loop to iterate through all the bullets in the list.
            collision = iscollision(enemy.x, enemy.y, bullet[0], bullet[1])
            if collision:               # Test if a single bullet collides with the enemy inside the loop.
                score += 1
                print(score)
                bullets.remove(bullet)  # Remove the bullet from the list when it collides with the enemy.
                enemy.x = random.randint(0, 476)     # if collision takes place, alien respawns
                enemy.y = random.randint(0, 30)

    # [...]

    for enemy in enemy_list:
        enemy.draw()

完整代码:

import pygame
import random
import math

# for initialising pygame (req for every pygame app)
pygame.init()

# making the basic window (dimensions must be written inside a tuple )
screen = pygame.display.set_mode((500, 500))

# background
background = pygame.image.load('C:/Users/aryan/Downloads/background.jpg')

# load and set the logo
logo = pygame.image.load('C:/Users/aryan/Downloads/bp.png')  # directory of logo
pygame.display.set_icon(logo)
pygame.display.set_caption("space wars")  # program name

# define a variable to control the main loop
running = True

# player
playerimg = pygame.image.load('C:/Users/aryan/Downloads/spaceship.png')
playerX = 218  # x and y coordinates of image
playerY = 350
playerxchange = 0  # this will be the change in movement in x direction of our image
playerychange = 0  # this will be the change in movement in y direction of our image


def player(x, y):
    screen.blit(playerimg, (x, y))  # blit draws our image on the surface(basically the background)
    # syntax for blit(imagename, (xcoordinate,ycoordinate))

class Enemy:
    def __init__(self):
        self.x = random.randint(0, 476)
        self.y = 20
        self.moveX = 0.2
        self.moveY = 40

    def move(self):
        self.x += self.moveX 

        if self.y >= 476:
            self.y = 476
            self.moveY = 0
            self.moveX = 0

        if self.x <= 0:
            self.moveX = 0.1
            self.y += self.moveY
        elif self.x >= 465:
            self.moveX = -0.1
            self.y += self.moveY

    def draw(self):
        screen.blit(enemyimg, (self.x, self.y))

# enemy
enemyimg = pygame.image.load('C:/Users/aryan/Downloads/enemy.png')

enemy_list = []
for i in range(5):
    new_enemy = Enemy()
    enemy_list.append(new_enemy)

# game over
overimg = pygame.image.load('C:/Users/aryan/Downloads/gameover.png')

# bullet
bulletimg = pygame.image.load('C:/Users/aryan/Downloads/bullet.png')
bulletX = 0
bulletY = 350
bulletxchange = 0
bulletychange = 1
bullet_state = "ready"              # "ready" you cant see bullet on screen
                                    # "fire" you can see bullet firing

bullets = []                        # bullets is a list that contains the coordinates of every bullet

score = 0

font30 = pygame.font.SysFont(None, 30)


def firebullet(x, y):
    global bullet_state
    bullet_state = "ready"
    bullets.append([x + 12, y + 6]) # Creating a new bullet


def iscollision(enemyX, enemyY, bulletX, bulletY):
    distance = math.sqrt(math.pow(enemyX-bulletX, 2)+ math.pow(enemyY-bulletY,2))     # distance formula
    if distance <= 20:
        return True
    else:
        return False

def TextScore(game):
    text2 = font30.render("Your Score is: " + str(game), True, (37, 97, 188))
    screen.blit(text2, (10, 45))



# main loop
while running:
    screen.fill((120, 120, 120))  # in order (r, g, b) . (0, 0, 0) is black (255, 0, 0) is red...
    screen.blit(background, (0, 0))
    # event handling, gets all event from the event queue
    for event in pygame.event.get():
        # only do something if the event is of type QUIT
        if event.type == pygame.QUIT:
            # change the value to False, to exit the main loop
            running = False

        # checking keystroke
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                playerxchange += 0.3  # change in movement will be 0.2 towards the right
            if event.key == pygame.K_LEFT:
                playerxchange -= 0.3  # change in movement will be 0.2 towards the right
            if event.key == pygame.K_UP:
                playerychange -= 0.3
            if event.key == pygame.K_DOWN:
               playerychange += 0.3
            if event.key == pygame.K_SPACE:
                bullet_state = "fire"
                firebullet(playerX, playerY)
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN or event.key == pygame.K_UP:
                playerxchange = 0
                playerychange = 0

    playerY += playerychange
    playerX += playerxchange  # the value of playerx changes by +- 0.1 depending on keystroke

    if playerX <= -64:  # this teleports the spaceship from left end to right end
        playerX = 564
    elif playerX >= 564:  # this teleports spaceship from right end to left
        playerX = -64

    if playerY >= 436:  # this prevents spaceship from leaving vertically
        playerY = 436
    if playerY <= 0:
        playerY = 0

    for enemy in enemy_list:
        enemy.move() 


    # bullet movement
    if bullet_state == "fire":
        firebullet(playerX, playerY)


    for bullet in bullets:
        screen.blit(bulletimg, (bullet[0], bullet[1]))  # Print a bullet
        bullet[0] -= bulletxchange  # Updates its position
        bullet[1] -= bulletychange
        if bullet[1] < 0:
            bullets.remove(bullet)

    # collision
    for enemy in enemy_list:
        for bullet in bullets:       # Use a for-loop to iterate through all the bullets in the list.
            collision = iscollision(enemy.x, enemy.y, bullet[0], bullet[1])
            if collision:               # Test if a single bullet collides with the enemy inside the loop.
                score += 1
                print(score)
                bullets.remove(bullet)  # Remove the bullet from the list when it collides with the enemy.
                enemy.x = random.randint(0, 476)     # if collision takes place, alien respawns
                enemy.y = random.randint(0, 30)


    TextScore(score)
    player(playerX, playerY)  # player method is called AFTER screen.fill otherwise the screen will fill after image has been blitted
    for enemy in enemy_list:
        enemy.draw()

    pygame.display.update()  # necessary for events to keep updating

如果您想生成不重叠的敌人,请查看以下问题的答案: