PYTHON入门级游戏开发:宇宙飞船游戏两万字详析

news2024/11/18 9:28:41

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

由于内容比较多,这里会分为五篇文章来讲解,从页面的创建、飞船控制、射击、外星人创建、射杀外星人五片来展开。

做一个窗口和设置响应用户

import sys

import pygame
''' '''
""" 我们先创建一个新的文件,保存的名字就叫做主函数吧,main.py。首先我们应该导入两个模块sys和pygame,pygame是用来开发游戏所需要的功能的,sys是我们退出的时候,我们需要用到的 """"
 
from settings import Settings
#这个是我们在后面创建一个settings用来管理设置,后年会补充
class AlienInvasion:
    """我们先创建一个类,用它来管理游戏资源和行为的类。"""

    def __init__(self):
        """这个我们开始游戏的主循环"""
        pygame.init()
        #在这个类中,我们先定义一个函数,调用函数pygame.init()初始化背景设置,让他能够正常的工作

        self.settings = Settings()

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
            #在主程序文件中打入settings类调用pygames in it(),创建一个settings实力并付给self.settings,这个时候我们把它的属性宽度和高度复给主函数



        pygame.display.set_caption("Alien Invasion")


    def run_game(self):
        """开始游戏的主循环了,在这个循环中,我们不断的进行一个循环,并且管理屏幕更新的代码。比如说按键或移动鼠标的时候就是要响应一次,作为一次响应事件,就是一个循环。
 """
        while True:
            
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
            #在循环中,如果我们检测到了退出的指令,我们就用       sys.exit()来退出
         
            self.screen.fill(self.settings.bg_color)
           #调用方法fill(),用这种背景色填充屏幕。方法fill()用于处理surface只接受一个实参一种颜色

            pygame.display.flip()
# 让最近绘制的屏幕可见,在这里我们通过不断的循环都会绘制一个空的屏幕,并且插去就的屏幕,所以让新的屏幕可见就行,成了动画
if __name__ == '__main__':
    # 创建游戏实例,并且开始运行游戏

    ai = AlienInvasion()
    ai.run_game()

这里重新建立一个文件,可以命名为settings.py

class Settings:
    """我们开始编写一个名为settings的模块,在这个模块中,所有的设置都储存在这里,以免在代码中到处添加设置。创建另外一个文件,命名为settings.py。
"""

    def __init__(self):
        """这里我们建立一个函数"""
        # 如果只是一个默认的屏幕,就太没有意思了,在现在我们把屏幕的颜色改成白色
颜色是由RGB指定的,比如说25500表示红色;02550表示绿色;这里我们把背景色设为白色

        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

这里重新建立一个文件,可以命名为ship.py。我们在这里会先创立一ship的模块.,我们用这个模块来管理飞船的大部分行为。

import pygame
 
 
class Ship:
    """管理飞船的类"""
 
    def __init__(self, ai_game):
        """初始化飞船并且初始化的他的位置"""
        self.screen = ai_game.screen
        #在定义这个类之前,我要导入模块pygame
在一处的话,将屏幕付给了sheep的一个属性,方便这个类的所有方法后面的轻松访问

        
        self.screen_rect = ai_game.screen.get_rect()

        # 加载飞船图像
        self.image = pygame.image.load('images/ship.bmp')
        #在这里我们需要把飞船的图像添加进去,一般来说,图像的格式都是JPGGIF多一点在这里我们用的是bmp的格式. 我把飞船的图片放在下面,注意在你建立文档的时候,一定要把图片放在一个名为images的文件夹下,并且我其他项目是同一个文件夹。


        self.rect = self.image.get_rect()

       
        self.rect.midbottom = self.screen_rect.midbottom
        #我们都把它放在屏幕底部的中央因为这里我们要把非常放在底部的中央,所以我们应该用的属性叫做 midbottom


    def blitme(self):
        
        self.screen.blit(self.image, self.rect)
        #现在我们要把这个飞船的图像调用出来,括号里面的是非常的位置

这个是我们要导入的图片
在这里插入图片描述

这个是我们最终建立好的游戏界面
在这里插入图片描述

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

上次我们在(一)中创建了游戏的背景,现在我们这里将要实现用键盘控制飞船的移动、射击子弹,但是在此之前我们还有一个非常重要的部分–重构。

重构

在大型项目中,经常需要添加新代码重构旧的代码,简单来说就把一些代码整理成函数,用函数之前的代码就变成了一句函数。这里我们就需要把之前的run_game()拆分成两个辅助方法,基本上辅助方法要以单个下划线打头。
我们直接回顾上此的代码

   def run_game(self):
      
        while True:
  #这里把管理事件的代码移动到这两个函数里面了,代码在下面
            self._check_events()
            self._update_screen()

    def _check_events(self):
#这个是之前按键和鼠标的代码
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

    def _update_screen(self):
    #更新图像,切换到新屏幕
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()

        pygame.display.flip()

飞船的控制

这里我开始把按键链接到电脑,每一次按下一个按键,pygame上都会注册一个事件,这里每次按下都会注册一个KEYDOWN事件,如果检测到这个事件就会移动

def _check_events(self):
     
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                      sys.exit()
            elif event.type == pygame.KEYDOWN: #检测到了按键被按下      
               if event.type == pygame.K_RIGHT:#按下的键是右键
                    self.ship.rect.x +=1#这里的距离+1,即右边移
  

左右持续移动

        # 添加左右的移动的标志,立flag是好个方法,简化代码过程
        self.moving_right = False
        self.moving_left = False

但检测到左右移动键按下后,flag变成1

      if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
         elif event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT:
                 self.ship.moving_right = False

这个时候我们在主运行加入移动函数,update()

    def run_game(self):
        """Start the main loop for the game."""
        while True:
            self._check_events()
            self.ship.update()#控制移动
            self._update_screen()

下面这个就是移动函数

    def update(self):
       if self.moving_right:
          self.ship.rect.x +=1#右移动加一
       if self.moving_left:
          self.ship.rect.x -=1#左移动减一
              

调整数独、限制活动范围
这里我们就整体展现下ship加工部分了。

import pygame
 
class Ship:
 
    def __init__(self, ai_game):
        self.screen = ai_game.screen


        self.settings = ai_game.settings#这里添加一个settings属性,等会要在update用


        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):
    
       
        if self.moving_right and self.rect.right < self.screen_rect.right:
        #飞船未飞出右边的边缘
            self.x += self.settings.ship_speed
            #移动的速度会不断地加一个像素的大小,注意:主函数中已经设置了速度为self.ship_speed=1.5
        if self.moving_left and self.rect.left > 0:
        #如果飞船未飞出左侧,左侧是0
            self.x -= self.settings.ship_speed
        #根据self.x更新rect对象
        self.rect.x = self.x

再次重构
因为一句添加了不少内容,所以

    def _check_events(self):
        """Respond to keypresses and mouse events."""
        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
        
    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

按Q键退出

    def _check_keydown_events(self, event):
        """Respond to keypresses."""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True

#这里我们设置的按键Q退出,接受到Q键反应接受后执行sys模块的退出指令
        elif event.key == pygame.K_q:
            sys.exit()

全屏运行

    def __init__(self):
        """Initialize the game, and create game resources."""
        pygame.init()
        self.settings = Settings()
        #游戏开始时传入的是(00)以及参数pygame.FULLSCREEN,这个指令是覆盖整个屏幕
        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

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

第三部分我们讲解一下飞船需要射出子弹,那么子弹的部分是怎么操作呢?接下来我直接把项目的四个文件展示出来,以注释的形式在旁边讲解。因为有很多代码在前面都已经打过注释 了,这次我们就只在新加的代码旁边打注释了

任务三:按空格键的时候发射子弹,一个屏幕上最多发射三颗子弹,子弹向上飞行,到屏幕后消失

主文件()

import sys

import pygame

from settings import Settings
from ship import Ship
#这里我们创建了管理子弹的类,要引入主文件使用
from bullet import Bullet

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.ship = Ship(self)
        #这里创建用于储存子弹控制的编组
        self.bullets = pygame.sprite.Group()

    def run_game(self):
        while True:
            self._check_events()
            self.ship.update()
            #把子弹的函数加入主文件
            self._update_bullets()
            self._update_screen()

    def _check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            #这里是键盘按到空格键会返回KEYDOWN,此时调用开火函数
            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:
            #创建一个子弹新的bullet,把它加入到编组bullet储存
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        # 更新子弹的位置函数
        self.bullets.update()

        #不断循环删除子弹,子弹这里是他的y轴超出了屏幕,我们就删除
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                 self.bullets.remove(bullet)

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        pygame.display.flip()


if __name__ == '__main__':
    ai = AlienInvasion()
    ai.run_game()

子弹的控制类

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
        
        # 用float储存这个位置
        self.y = float(self.rect.y)

    def update(self):
        """子弹向上飞"""
        # 每一次子弹向上移动,y轴在不断地自减
        self.y -= self.settings.bullet_speed
        # 把最新的位置给子弹
        self.rect.y = self.y

    def draw_bullet(self):
        """画出子弹,参数是用self里面储存的参数填充的"""
        pygame.draw.rect(self.screen, self.color, self.rect)

设置类文件

class Settings:
    def __init__(self):
        # Screen settings
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

        # Ship settings
        self.ship_speed = 1.5

        # 这里在设置子弹的一系列的参数,等会直接调用这个类
        self.bullet_speed = 1.0
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        #最大的子弹数为3
        self.bullets_allowed = 3

飞船的参数设置文件

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()

        # Load the ship image and get its rect.
        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
        self.moving_right = False
        self.moving_left = False

    def update(self):
        # 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

        # Update rect object from self.x.
        self.rect.x = self.x

    def blitme(self):
        self.screen.blit(self.image, self.rect)

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

在经过创立屏幕、飞船移动和设置子弹,我们这里开始设置外形人的创建和移动。我们这里主要的任务是:创建一众外星人让它们充满屏幕,让他们向下和两边移动,这里继承了上面四个文件外我们还多键一个文件来管理外星人的类,也就是五个文件。这里后三个文件没有太大的变化,我们主要调整了前两个文件

主文件

import sys

import pygame

from settings import Settings
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.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()
        self._creat_fleet()

    def run_game(self):

        while True:
            self._check_events()
            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)

    def _update_aliens(self):
        """
        判断外星人有没有到边,到了就调整位置
        """
        self._check_fleet_edges()
        self.aliens.update()

    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

        #外星人图像并且rect属性         
        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):
       #判断是否超过屏幕
        """看看飞船有没有超过屏幕,如果屏幕大于右边的屏幕的数后者小于零是超越屏幕的左边"""
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right or self.rect.left <= 0:
            return True

    def update(self):
        """这里用乘积的办法,每次就是用所在的x坐标减去方向*1or-1"""
        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.bullet_speed = 1.0
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        self.bullets_allowed = 3

        # 外星人左右移动的速度1,向下移动的速度10
        self.alien_speed = 1.0
        self.fleet_drop_speed = 10
        # 这里其实是在设置每次外形人飞船的位置,1为右移一位,-1为左移
        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)

        self.moving_right = False
        self.moving_left = False

    def update(self):


        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)

手把手讲解超详细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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1338487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 13 - Media框架(28)- ACodec(五)

前面几节我们了解了OMXNodeInstance是如何处理setPortMode、allocateBuffer、useBuffer的&#xff0c;这一节我们再回到ACodec&#xff0c;来看看 ACodec start 的其他部分。 我们首先来回顾一下&#xff0c;ACodec start 的状态切换以及处理的事务&#xff0c;我们用一张不太准…

23、Qt使用fftw3.3.5

一、下载 FFTW Installation on Windows 二、使用fftw 新建一个Qt项目&#xff0c;把“fftw3.h”和“libfftw3-3.dll”两个文件拷贝到项目目录下 在.pro中添加如下代码 LIBS -L$$PWD/ -llibfftw3-3 右击项目名称&#xff0c;选择“添加现有文件”&#xff0c;选择“fftw3.h…

【Echarts】使用echarts和echarts-wordcloud生成词云图

一、下载echarts和echarts-wordcloud 地址&#xff1a;https://download.csdn.net/download/qq_25285531/88663006 可直接下载放在项目中使用 二、词云数据 词云数据是对象的格式&#xff0c;可以从后端获取&#xff0c;这里以下面数据为例 $list3 array(array(name >…

《当初恋撞上人生》

《当初恋撞上人生》是很久以前起早的一个作品&#xff0c;然而断断续续、伤伤感感一直没写下去&#xff0c;最近打开看了一下&#xff0c;总算概述还完整&#xff0c;暂且贴出来也好。不想哪天一改&#xff0c;失了原本初心与色彩。 简章如下&#xff1a; 《初恋撞上人生》简述…

视频批量转码:一键转换多个视频mp4格式到FLV视频

在数字媒体时代&#xff0c;视频格式的多样性给处理工作带来了诸多不便。满足不同的播放需求&#xff0c;经常要视频从一种格式转换为另一种格式。其中&#xff0c;将mp4格式转换为FLV格式的需求很常见。现在一起来看下云炫AI智剪如何高效的将视频批量转码方法&#xff0c;一键…

CSS 文字弹跳效果

鼠标移过去 会加快速度 <template><div class"bounce"><p class"text" :style"{animationDuration: animationDuration}">欢迎使用UniApp Vue3&#xff01;</p></div> </template><script> export d…

运动轨迹仿真

重型运载火箭轨迹/总体参数一体化优化方法 硬核推导火箭运动方程&#xff0c;并用python仿真实现 rocket-simulation:MATLAB-火箭仿真软件 MatRockSim:Matlab 火箭飞行模拟器 【开源】飞鹰一号探空火箭——箭体设计、制造回顾与仿真对比 偏航角&#xff0c;滚动角&#xf…

HOJ 项目部署-前端定制 默认勾选显示标签、 在线编辑器主题和字号大小修改、增加一言功能 题目AC后礼花绽放

# 项目拉取地址&#xff1a; https://gitee.com/himitzh0730/hoj.git # 切换到hoj-vue目录执行以下命令 #安装依赖 npm install #运行服务 npm run serve #修改代码后构建项目到dist文件夹&#xff0c;到服务器docker-compose.yml中修改hoj-frontend文件映射即可 npm run build…

FPGA-AMBA协议、APB协议、AHB规范、AXI4协议规范概述及它们之间的关系

FPGA-AMBA协议、APB协议、AHB协议、AXI&#xff14;协议规范概述 笔记记录&#xff0c;AMBA协议、APB协议、AHB规范、AXI&#xff14;协议规范概述&#xff0c;只是概述描述&#xff0c;具体详细的协议地址传输、数据传输等内容将在下一章节详细说明。 文章目录 FPGA-AMBA协议…

自动化测试工程师怎样能规划好自己的职业生涯?

确定职业目标&#xff1a;首先&#xff0c;自动化测试工程师需要明确自己的职业目标&#xff0c;是希望在测试领域深入发展&#xff0c;还是希望向其他方向转型。如果希望在测试领域深入发展&#xff0c;可以专注于自动化测试技术的不断提升&#xff0c;以及测试管理的相关技能…

python3下载手机安卓版,python下载手机版最新

大家好&#xff0c;小编为大家解答python3下载手机安卓版的问题。很多人还不知道python下载手机版最新&#xff0c;现在让我们一起来看看吧&#xff01; 1、先去python官网下载python3的源码包&#xff0c;网址&#xff1a;https://www.python.org/ 1)进去之后点击导航栏的Down…

生成超清分辨率视频,南洋理工开源Upscale-A-Video

大模型在生成高质量图像方面表现出色,但在生成视频任务中&#xff0c;经常会面临视频不连贯、图像模糊、掉帧等问题。 这主要是因为生成式抽样过程中的随机性,会在视频序列中引入无法预测的帧跳动。同时现有方法仅考虑了局部视频片段的时空一致性,无法保证整个长视频的整体连贯…

物联网协议Coap之Californium CoapServer解析

目录 前言 一、CoapServer对象 1、类对象定义 2、ServerInterface接口 3、CoapServer对象 二、CoapServer服务运行分析 1、CoapServer对象实例化 1.1 调用构造方法 1.2 生成全局配置 1.3 创建Resource对象 1.4-1.8、配置消息传递器、添加CoapResource 1.9-1.12 创建线…

C# ASP.NET 实验室 检验中心 医疗LIS源码

LIS系统能够自动处理大量的医学数据&#xff0c;包括样本采集、样本处理、检测分析、报告生成等。它能够快速、准确地进行化验检测&#xff0c;提高医院的运营效率。LIS系统还提供了丰富的数据分析功能&#xff0c;能够对医院化验室的业务流程进行全面、细致的监控。 LIS系统优…

Hooked协议掀起WEB3新浪潮

随着区块链技术和加密货币的兴起&#xff0c;币圈已经成为全球范围内的一个热门领域。在这个充满机遇与挑战的行业中&#xff0c;Hook机制正逐渐成为一种重要的技术手段&#xff0c;为投资者、开发者以及相关机构提供了更多的选择和可能性。本文将详细介绍币圈中的Hook机制&…

Qt/C++音视频开发61-多屏渲染/一个解码渲染到多个窗口/画面实时同步

一、前言 多屏渲染就是一个解码线程对应多个渲染界面&#xff0c;通过addrender这种方式添加多个绘制窗体&#xff0c;我们经常可以在展会或者卖电视机的地方可以看到很多电视播放的同一个画面&#xff0c;原理应该类似&#xff0c;一个地方负责打开解码播放&#xff0c;将画面…

【每日一坑】高Q电感的“SRF”是什么?

先上截图 SRF Self-Resonant Frequency 自我共振频率 电感器中端子电极与绕组导体等之间存在微小的分布容量&#xff0c;因此在特定频率下会发生共振。 此时的频率称为自我共振频率&#xff0c;超过自我共振频率时&#xff0c;电感器将无法发挥其功能。 在为高频电路或高频…

图解集线器、中继器、交换机、网桥、路由器、光猫到底有啥区别?

集线器、中继器、交换机、网桥、光猫这些都是网络设备&#xff0c;但它们在功能、工作层次、数据传输方式、带宽占用方式等方面存在差异 集线器 集线器的英文称为“Hub”。“Hub”是“中心”的意思&#xff08;就像是GitHub&#xff09;&#xff0c;集线器的主要功能是对接收…

张江智荟毁约offer

毕业8年后&#xff0c;找工作被国企歧视学历&#xff01;已经收到了offer&#xff0c;在入职前一周被通知要撤回offer&#xff0c;拒绝录用&#xff0c;理由居然是他们只要本科211以上的人 这是我今天&#xff08;2023-12-26&#xff09;亲身经历的事&#xff0c;听说过面试前…

重磅!最新版北大核心期刊目录出炉,1987种期刊入选!26本期刊已经官宣!

近日&#xff0c;北京大学图书馆网站发布消息&#xff0c;称2023版《中文核心期刊要目总览》已开放采购&#xff0c;这也意味着&#xff0c;备受学界关注的第10版北大核心期刊目录已经出炉。此前&#xff0c;官网已经发布消息称评审工作结束&#xff0c;结果已经通过邮件告知相…