zl程序教程

您现在的位置是:首页 >  后端

当前栏目

手把手讲解超详细python入门游戏项目‘打外星飞船’(五)

Python游戏项目入门 详细 讲解 手把手 飞船
2023-09-11 14:20:37 时间

手把手讲解超详细python入门游戏项目‘打外星飞船’(五)

这是最后一个项目了,前面我们讲了整个游戏页面的控制、飞船、子弹、外星人的创建,这里我们讨论一下子弹射杀外星人和整个游戏的结束,我们这里的文件一共有六个:主函数、飞船、外星飞船、子弹、设置参数、跟踪游戏统计信息六个文件。在这里我们要实现的任务是:子弹碰到外形飞船是让飞船消失,同时飞船碰到外星人飞船或者外星人飞船碰到屏幕低端结束游戏。

主函数

import sys
from time import sleep

import pygame

from settings import Settings
#我们需要创建一个文件去储存游戏统计信息,这里引入主函数
from game_stats import GameStats
from ship import Ship
from bullet import Bullet
from alien import Alien


class AlienInvasion:
    """控制游戏所有类和函数的类"""

    def __init__(self):
        """初始化游戏并且调用相关的函数资源"""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        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.stats = GameStats(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

        self._create_fleet()

    def run_game(self):
        """我们开始了游戏的主循环"""
        while True:
            self._check_events()

            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            self._update_screen()

    def _check_events(self):
        """这个是读取键盘和鼠标指令的函数"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            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):
        """接收键盘上左右移动等指令"""
        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_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    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 _fire_bullet(self):
        """创键一个新的子弹并把他加入子弹组"""
        if len(self.bullets) < self.settings.bullets_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        """变换子弹的位置并且删除旧的子弹"""
        #变换位置
        self.bullets.update()

        # 删除旧的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                 self.bullets.remove(bullet)

        self._check_bullet_alien_collisions()

    def _check_bullet_alien_collisions(self):
        """响应子弹和外星人碰撞,删除碰撞的两者的函数"""
        # 检查是否有子弹击中外星人,有就删除子弹和外星人
        collisions = pygame.sprite.groupcollide(
                self.bullets, self.aliens, True, True)

        if not self.aliens:
            # 删除现有的子弹并创建一群外星人
            self.bullets.empty()
            self._create_fleet()

    def _update_aliens(self):
        """
       判断是否是已经到了边缘,同时更新飞船的位置
        """
        self._check_fleet_edges()
        self.aliens.update()

        # 检查是否飞船和外星人飞船是否相碰
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        #检查外星人飞船是否到了底部
        self._check_aliens_bottom()

    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:
                # Treat this the same as if the ship got hit.
                self._ship_hit()
                break

    def _ship_hit(self):
        """响应飞船被外星人撞到时候"""
        if self.stats.ships_left > 0:
            # Decrement ships_left.
            self.stats.ships_left -= 1
            
            # 清除所有的子弹和外星人
            self.aliens.empty()
            self.bullets.empty()
            
            # 创建新的飞船,把他放到屏幕中央开始游戏
            self._create_fleet()
            self.ship.center_ship()
            
            # 暂停一会,让玩家可以看到飞船碰撞
            sleep(0.5)
        else:
            self.stats.game_active = False

    def _create_fleet(self):
        # 计算行列的外星人可以容纳多少个,并创建数行数列的外星人
        
        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)
        
       
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height -
                                (3 * alien_height) - ship_height)
        number_rows = available_space_y // (2 * alien_height)
        
        # 创建外星人的移动
        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 = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _check_fleet_edges(self):
        """如果有任何飞船到达边缘要及时反应"""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break
            
    def _change_fleet_direction(self):
        """让外星人飞船左右移动"""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _update_screen(self):
        """更新屏幕上的图片"""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)

        pygame.display.flip()


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

外星人文件

import pygame
from pygame.sprite import Sprite
 
class Alien(Sprite):
    """外星人移动管里类"""

    def __init__(self, ai_game):
        """初始化外星人并把放置他们的位置"""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings

        #下载图片
        self.image = pygame.image.load('images/alien.bmp')
        self.rect = self.image.get_rect()

        # 每次在左上角开始飞船
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        # 储存飞船的位置.
        self.x = float(self.rect.x)

    def check_edges(self):
        """返回flag如果飞船到达边缘"""
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right or self.rect.left <= 0:
            return True

    def update(self):
        """向左或者向右移动飞船"""
        self.x += (self.settings.alien_speed *
                        self.settings.fleet_direction)
        self.rect.x = self.x

子弹文件

import pygame
from pygame.sprite import Sprite
 
class Bullet(Sprite):
    """管理子弹的类"""

    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.midtop = ai_game.ship.rect.midtop
        
        # 储存子弹
        self.y = float(self.rect.y)

    def update(self):
        """子弹超过屏幕后移除子弹"""
        # Update the decimal position of the bullet.
        self.y -= self.settings.bullet_speed
        # Update the rect position.
        self.rect.y = self.y

    def draw_bullet(self):
        """在屏幕上画出子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)

参数设置类文件

class Settings:
    """设置一系列参数"""

    def __init__(self):
        """初始化游戏的参数"""
        # 屏幕的大小
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

        # 飞船的速度等参数
        self.ship_speed = 1.5
        self.ship_limit = 3

        # 子弹的设置
        self.bullet_speed = 1.5
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        self.bullets_allowed = 3

        # 外星人飞船的设置
        self.alien_speed = 1.0
        self.fleet_drop_speed = 10
        # fleet_direction of 1 represents right; -1 represents left.
        self.fleet_direction = 1

飞船文件

import pygame
 
class Ship:
    """管理飞船的类"""
 
    def __init__(self, ai_game):
        """初始化飞船并且调动他的位置."""
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.screen_rect = ai_game.screen.get_rect()

        # 调用飞船图片并且储存他的位置
        self.image = pygame.image.load('images/ship.bmp')
        self.rect = self.image.get_rect()

        # 每个飞船都在屏幕的中央出现
        self.rect.midbottom = self.screen_rect.midbottom

      
        self.x = float(self.rect.x)

        # 移动flag
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """移动飞船根据flag"""
        # Update the ship's x value, not the rect.
        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

        # 储存飞船目前的位置
        self.rect.x = self.x

    def blitme(self):
        """在目前位置画出飞船"""
        self.screen.blit(self.image, self.rect)

    def center_ship(self):
        """把飞船放在屏幕中央"""
        self.rect.midbottom = self.screen_rect.midbottom
        self.x = float(self.rect.x)

跟踪游戏统计文件

class GameStats:
    """跟踪游戏统计信息"""
    
    def __init__(self, ai_game):
        """初始化游戏信息"""
        self.settings = ai_game.settings
        self.reset_stats()

        #游戏启动处于活动状态
        self.game_active = True
        
    def reset_stats(self):
        """初始化在游戏运行期间可能变化的统计信息"""
        self.ships_left = self.settings.ship_limit

这个是最后的配置的外星人和飞船图片
请添加图片描述
请添加图片描述