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

146 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 上次我们在(一)中创建了游戏的背景,现在我们这里将要实现用键盘控制飞船的移动、射击子弹,但是在此之前我们还有一个非常重要的部分--重构。

重构

在大型项目中,经常需要添加新代码重构旧的代码,简单来说就把一些代码整理成函数,用函数之前的代码就变成了一句函数。这里我们就需要把之前的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