【问题标题】:Pygame - Alien Invasion: Making aliens shoot backPygame - 外星人入侵:让外星人反击
【发布时间】:2021-11-12 00:26:31
【问题描述】:

我目前正试图让我的外星人在游戏过程中向玩家投掷“炸弹”。我目前的目标是让所有外星人投下炸弹,然后最终让随机外星人在一定级别后投下炸弹。

Currently is seems that all bombs are coming from the starting location of my first alien.

外星人入侵.py

import sys, pygame

from settings import Settings
from ship import Ship
from bombs import Bomb
from alien import Alien

class AlienInvasion:
    """Overall class to manage game assets and behavior."""

    def __init__(self):
        """Initlize the game, and create game resources."""
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode((self.settings.screen_width, 
                                            self.settings.screen_height))
        self.settings.screen_width = self.screen.get_rect().width
        self.settings.screen_height = self.screen.get_rect().height

        pygame.display.set_caption("Alien Invasion")

        self.ship = Ship(self)
        self.alien = Alien(self)

        self.bullets = pygame.sprite.Group()
        self.bombs = pygame.sprite.Group()

        self.aliens = pygame.sprite.Group()
        self._create_fleet()

        #Set our background color
        self.bg_color = (230, 230, 230)
        

    def run_game(self):
        """Start main loop for our game."""
        while True:
            self._check_events()


            self.ship.update() 

            self._drop_bombs()
            self._update_bombs()
            
            self._update_aliens()
                
            self._update_screen()

    def _check_events(self):
        """Respond to kepresses and mouse events."""
        #for each event in game capture that event
        for event in pygame.event.get():
            #if player preses close, quit game
            if event.type == pygame.QUIT:
                sys.exit()
            # if event is a key press
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        """respond to keydown events"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_ESCAPE:
            sys.exit()

    def _check_keyup_events(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _drop_bombs(self):
        """drop bombs from alien ships"""
        new_bomb = Bomb(self)
        for alien in self.aliens:
            self.bombs.add(new_bomb)

    def _update_bombs(self):
        """update bombs positions and gets rid of old bombs"""
        self.screen_rect = self.screen.get_rect()
        self.bombs.update()
        for bomb in self.bombs.copy():
            if bomb.rect.bottom >= self.screen_rect.bottom:
                self.bombs.remove(bomb)


    def _update_aliens(self):
        """update the position of the aliens"""
        self._check_fleet_edges()
        self.aliens.update()

        self._check_aliens_bottom()

    def _create_fleet(self):
        """create our fleet of aliens"""
        # creat an alien and fine the number that fits in a row
        # spacing between each alien is equal to one alien
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_aliens_x = available_space_x // (2 * alien_width)

        # determine the number of rows that fit on the screen
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - 
                                (5 * alien_height) - ship_height)
        number_rows = available_space_y // (2 * alien_height)

        # create a full fleet of aliens
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._create_alien(alien_number, row_number)


    def _create_alien(self, alien_number, row_number):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = 2 * alien_height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _check_fleet_edges(self):
        """respond if any aliens reach the edge"""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _check_aliens_bottom(self):
        """check if any aliens have reached the bottom of the screen"""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                self._ship_hit()
                break

    def _change_fleet_direction(self):
        """drop entire fleet and change direction"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _update_screen(self):
        """Update images on screen and flip to the new screen."""
        #fill our background with our bg_color
        self.screen.fill(self.settings.bg_color)

        #draw ship to screen
        self.ship.blitme()

        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self.aliens.draw(self.screen)


        for bomb in self.bombs.sprites():
            bomb.draw_bomb()


        #Make the most recently drawn screen visible.
        #this clears our previous screen and updates it to a new one
        #this gives our programe smooth movemnt
        pygame.display.flip()

if __name__ == '__main__':
    #Make a game instance, and run the game
    ai = AlienInvasion()
    ai.run_game()

外星人.py

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    """A class to represent a sinlge alien in the fleet"""

    def __init__(self, ai_game):
        """initlize alien and set its starting position"""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.screen_rect = ai_game.screen.get_rect()

        # load alien image at set its rect
        self.image = pygame.image.load('images/alien.bmp')
        self.rect = self.image.get_rect()

        # start each new alien at the top left of the screen
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        # store aliens exact position (decimal)
        self.x = float(self.rect.x)

    def check_edges(self):
        """return true if alien is at edge of screen"""
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right or self.rect.left <= 0:
            return True

    def update(self):
        """move the alien to the right or left"""
        self.x += (self.settings.alien_speed *
                        self.settings.fleet_direction)
        self.rect.x = self.x

炸弹.py

from pygame.sprite import Sprite

class Bomb(Sprite):
    """create a bullet that is dropped by aliens"""

    def __init__(self, ai_game):
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.color = self.settings.bullet_color

        self.rect = pygame.Rect(0, 0, self.settings.bullet_width,
            self.settings.bullet_height)
        self.rect.midbottom = ai_game.alien.rect.midbottom

        self.y = float(self.rect.y)

    def update(self):
        """move bullet down screen"""
        self.y += self.settings.bullet_speed
        self.rect.y = self.y

    def draw_bomb(self):
        """draw bullet to screen"""
        pygame.draw.rect(self.screen, self.color, self.rect)

settings.py

class Settings:
    """A class to store our settings for Alien Invasion game."""

    def __init__(self):
        """Initlize the games settings."""
        # screen settings
        self.screen_width = 1600
        self.screen_height = 900
        self.bg_color = (230, 230, 230)

        # ship settings
        self.ship_limit = 3

        # bullet settings
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        self.bullets_allowed = 3

        # alien settings
        self.fleet_drop_speed = 10

        # how quickly the game speeds up
        self.speedup_scale = 1.1

        # how muct alien poits value increses
        self.score_scale = 1.5

        self.initialize_dynamic_settings()

    def initialize_dynamic_settings(self):
        """settings that change through the game"""
        self.ship_speed = 1.5
        self.bullet_speed = 1.5
        self.alien_speed = 0.5

        self.fleet_direction = 1

        # scoring
        self.alien_points = 50

    def increse_speed(self):
        """increse speed settings"""
        self.ship_speed *= self.speedup_scale
        self.bullet_speed *= self.speedup_scale
        self.alien_speed *= self.speedup_scale

        self.alien_points = int(self.alien_points * self.score_scale)

ship.py

from pygame.sprite import Sprite

class Ship(Sprite):
    """A class for managing our ship."""

    def __init__(self, ai_game):
        """Initlize the ship and set its starting position."""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.screen_rect = ai_game.screen.get_rect()

        # load ship image and get its rect.(rect stands for rectangle)
        self.image = pygame.image.load('images/ship.bmp')
        self.rect = self.image.get_rect()

        # Start each new ship at the bottom center of the screen.
        self.rect.midbottom = self.screen_rect.midbottom

        # store a decimal value for the ship's horizontal position
        self.x = float(self.rect.x)

        # movement flags
        # we start our flag at false so the ship doesnt move by itself
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """Update ships position based on our movement flags"""
        # update ship's x value, not its rectange
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.x += self.settings.ship_speed
        if self.moving_left and self.rect.left > 0:
            self.x -= self.settings.ship_speed

        # update rect object for self.x
        self.rect.x = self.x

    def blitme(self):
        """Draw the ship at its current location."""
        self.screen.blit(self.image, self.rect)

    def center_ship(self):
        """center ship"""
        self.rect.midbottom = self.screen_rect.midbottom
        self.x = float(self.rect.x)

我将如何让每个外星人投下自己的炸弹?

希望这对你们来说遵循最小的可重现示例。

【问题讨论】:

  • 如果所有对象都具有相同名称的相同功能 - 即。 draw 而不是 draw_bombblitme - 然后您可以将它们都保留在列表中并使用 for-loop 对所有对象执行相同的功能。然后Alien 可以将Bomb 添加到此列表中,for-loop 将像其他对象一样绘制。

标签: python python-3.x pygame


【解决方案1】:

您需要在炸弹的__init__ 中包含炸弹的 x y 位置:

class Bomb(sprite):
    def __init__(self, ai_game, x, y):
        # [...]

        self.rect = pygame.Rect(x, y, self.settings.bullet_width,
            self.settings.bullet_height)

        self.y = y

现在在创建炸弹(_drop_bombs)时,您需要包含外星人的 x 和 y 位置:

class AlienInvasion:
    # [...]

    def _drop_bombs(self):
        """drop bombs from alien ships"""
        for alien in self.aliens:
            new_bomb = Bomb(self, alien.x, alien.y)  # top left of alien
            # do alien.x + 5 or something to drop the bomb in the middle
            self.bombs.add(new_bomb)

我还建议将外星人的 x 和 y 位置包含在 __init__ 中,而不是事后修改。

【讨论】:

    猜你喜欢
    • 2020-06-25
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多