Pygame - проблема создания нескольких астероидных объектов в игре астероидов - PullRequest
2 голосов
/ 28 апреля 2020

Я работаю над игрой, созданной для репликации астероидов с моими собственными дополнениями здесь и там. Проблема, с которой я столкнулся, заключается в непонимании того, как именно я должен go создать несколько астероидных объектов одного и того же класса. У меня есть базовый c код для астероидов с точки зрения инициализации и обновления, который в настоящее время просто создает и отслеживает один астероид. Я посмотрел другие посты и примеры того, как вы могли бы go создать несколько объектов одного класса, но ни один из них не соответствовал настройке моего кода. Любая помощь приветствуется.

#Import Modules
import pygame
import math
import random

#Movement Function
def calculate_new_xy(old_xy,speed,direction):
    new_x = old_xy[0] + (speed*math.cos(direction))
    new_y = old_xy[1] + (speed*math.sin(direction))
    return new_x, new_y

#Draw Text Function
def drawText(msg, color, x, y, s, center=True):
    screen_text = pygame.font.SysFont("Impact", s).render(msg, True, color)
    if center:
        rect = screen_text.get_rect()
        rect.center = (x, y-50)
    else:
        rect = (x, y)
    display.blit(screen_text, rect)

#Initialize Variables

#Colors
white = (255, 255, 255)
red = (255, 0, 0)
black = (0, 0, 0)

#Display Height/Width
display_width = 800
display_height = 600

#Asteroid Class
class Asteroid:
    #Initialize values
    def __init__(self, pos=(0, 0)):
        #Asteroid sprite
        self.asteroid = pygame.image.load("asteroid.png").convert()
        self.image = self.asteroid
        #Rectangle
        self.rect = self.image.get_rect()
        self.rect.center = pos
        #Initialize random starting angle
        self.angle = random.randint(0, 360)
        #Asteroid random Speed
        self.speed = random.randint(2, 5)
        #Asteroid random direction
        self.direction = math.radians(random.randint(0, 360))

    #Update asteroid object
    def update(self):
        #Constantly rotate asteroid
        self.angle -= 3 % 360

        #Get image angle and position
        self.image = pygame.transform.rotate(self.asteroid, self.angle*-1)

        #Use rectangle to get center of image
        #Save ship's current center.
        x, y = self.rect.center
        #Replace old rect with new rect.
        self.rect = self.image.get_rect()
        #Put the new rect's center at old center.
        self.rect.center = (x, y)

        #Move Asteroid
        self.rect.center = calculate_new_xy(self.rect.center,self.speed,self.direction)

        #Screen Border
        #Moves the player to the opposite side of the screen if they go outside the border
        if self.rect.x > display_width:
            self.rect.x = -50
        elif self.rect.x < -50:
            self.rect.x = display_width
        elif self.rect.y > display_height:
            self.rect.y = -50
        elif self.rect.y < -50:
            self.rect.y = display_height


#Player Class
class Player(pygame.sprite.Sprite):

    #Initialize ship sprite, angle lines, and rectangle
    def __init__(self, pos=(0, 0), size=(200, 200)):
        #Player sprite
        self.ship = pygame.image.load("ship.png").convert()
        self.image = self.ship
        #Rectangle
        self.rect = self.image.get_rect()
        self.rect.center = pos
        #Initialize angle
        self.angle = 0

    #Update player object
    def update(self):
        #Rotation
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_LEFT]: self.angle -= 3 % 360
        if pressed[pygame.K_RIGHT]: self.angle += 3 % 360

        #Get image angle and position
        self.image = pygame.transform.rotate(self.ship, self.angle*-1)

        #Use rectangle to get center of image
        #Save ship's current center.
        x, y = self.rect.center
        #Replace old rect with new rect.
        self.rect = self.image.get_rect()
        #Put the new rect's center at old center.
        self.rect.center = (x, y)

        #Convert angle to radians
        self.direction = math.radians(self.angle-90)

        #Increase speed if Up is pressed
        if pressed[pygame.K_UP]: self.speed = 5
        else: self.speed = 0

        #Move Ship
        self.rect.center = calculate_new_xy(self.rect.center,self.speed,self.direction)

        #Screen Border
        #Moves the player to the opposite side of the screen if they go outside the border
        if self.rect.x > display_width:
            self.rect.x = -50
        elif self.rect.x < -50:
            self.rect.x = display_width
        elif self.rect.y > display_height:
            self.rect.y = -50
        elif self.rect.y < -50:
            self.rect.y = display_height

#Main Function
def main():
    #Player starting position
    player = Player(pos=(400, 300))
    #Asteroid starting position
    asteroids = Asteroid(pos=(400, 300))

    #Initialize Game state
    gameState = "Menu"
    while True:
        for event in pygame.event.get():
            #closes game
            if event.type == pygame.QUIT:
                done = True
                pygame.quit()
                exit()
        #Game Menu
        while gameState == "Menu":
            #Fill background
            display.fill((0,0,0))
            #Display menu text
            drawText("ASTEROIDS", white, display_width / 2, display_height / 2, 150)
            drawText("Press any key to START", white, display_width / 2, display_height / 2 + 120, 40)
            #Check game start or end
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    done = True
                    pygame.quit()
                    exit()
                if event.type == pygame.KEYDOWN:
                    gameState = "Playing"
            pygame.display.update()
            #Low frame rate for menu
            clock.tick(5)

        #Update player
        player.update()

        #Udate asteroids
        asteroids.update()

        #Display background
        display.fill((0,0,0))

        #Draw player
        display.blit(player.image, player.rect)

        #Draw asteroids
        display.blit(asteroids.image, asteroids.rect)

        #Makes updates to the game screen
        pygame.display.update()

        #Frame rate
        clock.tick(60)

#Initialize Game
if __name__ == '__main__':
    #initialize pygame
    pygame.init()

    #initialize display settings
    display = pygame.display.set_mode((display_width,display_height))
    pygame.display.set_caption('Asteroids')

    #initialize game clock
    clock = pygame.time.Clock()

    #start main function
    main()

1 Ответ

2 голосов
/ 28 апреля 2020

Есть два способа сделать это в Pygame

1) использовать группу спрайтов

2) использовать список

Вы не настроили свой класс для группы спрайтов, поэтому я начну со списка

У вас есть asteroids = Asteroid(pos=(400, 300)), что хорошо, потому что для того, чтобы сделать больше, вам нужно всего лишь asteroids = [Asteroid(pos=(400, 300))], теперь у вас есть список с 1 астероидом. Чтобы сделать больше, вы можете позвонить Asteroid больше раз, чтобы

asteroids = [Asteroid(pos=(400, 300)) for x in range(10)]

Теперь у вас есть 10 астероидов, но они начинаются в той же позиции, поэтому

asteroids = [Asteroid(pos=(400 + (x*30), 300)) for x in range(10)]

Теперь у нас есть 10 астероидов 30 пикселей друг от друга

Чтобы обновить и нарисовать их, l oop через список

#Update asteroids
for asteroid in asteroids:
    asteroid.update()


#same for draw
#Draw asteroids
for asteroid in asteroids:
    display.blit(asteroid.image, asteroid.rect)

, если у вас много астероидов, было бы неплохо объединить эти петли, это все еще в порядке.


SpriteGroups

Чтобы настроить класс для спрайт-группы, он нужен для наследования класса Sprite

class Asteroid(pygame.sprite.Sprite):
    #Initialize values
    def __init__(self, pos=(0, 0)):
        pygame.sprite.Sprite.__init__(self) #initialize the Sprite class

, после чего вы можете создать группу спрайтов.

#Asteroid starting position
asteroids = pygame.sprite.Group()
for x in range(10):
    asteroids.add(Asteroid(pos=(400 + (x*30), 300))) #all 30 pixels apart

и для их обновления вы можете сделать то же, что делаете сейчас

#Update asteroids
asteroids.update()

Рисовать, даже проще, чем вы делаете сейчас

#Draw asteroids
asteroids.draw(display)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...