外星人入侵:使用Python开发游戏(二)——交互模块

内容

本文重点介绍game_functions.py模块,其中存储了各个模块间的交互行为和游戏的运行逻辑。

回顾

回顾一下主模块alien.invasion.py中的循环代码块

def run_game():
    '''初始化游戏并创建一个屏幕对象'''
    #初始化pygame,设置屏幕对象
   #-----snip----------
    #创建一艘飞船
    ship = Ship(ai_settings,screen)
    #创建一个用于存储子弹的编组,以便能够管理所有发射出去的子弹
    bullets = Group()
    #创建一个外星人编组
    aliens = Group()

    #创建外星人群
    gf.create_fleet(ai_settings,screen,ship,aliens)

    while True:
       gf.check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets)#检查用户输入
       if stats.game_active:
            #更新飞船位置
            ship.update()
            gf.update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets)#更新子弹位置
            gf.update_aliens(ai_settings,screen,stats,sb,ship,aliens,bullets)
       gf.update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button)

1.初始化一艘飞船:ship=Ship(screen)
——加载’images\ship.bmp’路径中的飞船图像,在gf.update_screen()方法中调用飞船对象的ship.blitme()方法经行图像绘制。
ps:位置参数#将飞船放在屏幕底部中间

    self.rect.centerx = self.screen_rect.centerx#屏幕矩形的中间坐标值
    self.rect.bottom = self.screen_rect.bottom#屏幕底部的坐标值

在这里插入图片描述
2.控制飞船移动
在主循环中使用事件检测机制(调用gf.check_events()方法),当有←/→/↑/↓方向键按下时,设置飞船对象相应的移动方向为True

if  event.key == pygame.K_RIGHT: #→键按下
        #向右移动飞船
        ship.moving_right = True
    elif event.key == pygame.K_LEFT: #←键按下
        #向左移动飞船
        ship.moving_left = True
    elif event.key == pygame.K_UP:#↑键按下
        ship.moving_up = True
    elif event.key == pygame.K_DOWN:#↓键按下
        ship.moving_down = True

根据移动方向,改变飞船坐标位置(调用飞船对象中的方法),同时注意检测飞船移动范围不能超过游戏界面的范围。

    def update(self):
        '''根据移动标志调整飞船位置'''
        if self.moving_right and self.rect.right < self.screen_rect.right:#检查是否超出屏幕范围(右边界)
            # self.rect.centerx +=1
            self.center += self.ai_settings.ship_speed_factor

        if self.moving_left and self.rect.left > 0:  #此时两个按键同时按下的话飞船保持不动 #检查是否超出屏幕范围(左边界)
            # self.rect.centerx -=1
            self.center -= self.ai_settings.ship_speed_factor
        
        if self.moving_up and self.bottom > self.rect.height:  #此时两个按键同时按下的话飞船保持不动 #检查是否超出屏幕范围(上边界)
            # self.rect.centerx -=1
            self.bottom -= self.ai_settings.ship_speed_factor
        if self.moving_down and self.rect.bottom < self.screen_rect.bottom:  #此时两个按键同时按下的话飞船保持不动 #检查是否超出屏幕范围(下边界)
            # self.rect.centerx -=1
            self.bottom += self.ai_settings.ship_speed_factor
        
        #根据self.center跟新rect对象
        self.rect.centerx = self.center
        self.rect.bottom = self.bottom

相应的,当某个方向键松开后也要对相应的移动方向进行“清除”处理

'''响应键松开'''
    if  event.key == pygame.K_RIGHT: #→键松开     
            ship.moving_right = False
    elif event.key == pygame.K_LEFT: #←键松开
            ship.moving_left = False 

    elif event.key == pygame.K_UP:#↑键按下
        ship.moving_up = False
    elif event.key == pygame.K_DOWN:#↓键按下
        ship.moving_down = False

更新完飞船的坐标后,再调用update()方法就可以在屏幕刷新飞船的新位置了

self.rect.centerx = self.center
self.rect.bottom = self.bottom

在这里插入图片描述

3.创建外星人
初始化部分调用了gf.create_fleet()创造了一群规则排列的外星人

def create_fleet(ai_settings,screen,ship,aliens):
    '''创建外星人群'''
    alien = Alien(ai_settings,screen)
    alien_width = alien.rect.width

    # avaliable_space_X = ai_settings.screen_width - 2*alien_width#屏幕两边留空
    # number_aliens_x = int(avaliable_space_X / (2*alien_width))#一行中可以排布的外星人数量
    #等价于下面重构的函数
    number_aliens_x = get_bumber_aliens_X(ai_settings,alien_width) #一行有多少个外星人
    number_rows = get_bumber_rows(ai_settings,ship.rect.height,alien.rect.height)#有多少行外星人
    
    #创建外星人群体
    #创建第一行外星人
    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
        # #创建一个外星人并将其加入当前行
        # alien = Alien(ai_settings,screen)
        # alien.x = alien_width+2*alien_width*alien_number
        # alien.rect.x = alien.x
        # aliens.add(alien)
        #等价于下面重构的函数
            create_alien(ai_settings,screen,aliens,alien_number,row_number)

首先创建一个外星人以获取其宽度,然后计算屏幕可以容纳多少行,列的外星人数量并以此构建外星人群体(注意留出一部分飞船的移动空间)

avaliable_space_X = ai_settings.screen_width - 2*alien_width
avaliable_space_y = (ai_settings.screen_height-(3*alien_height)-ship_height)

每个外星人坐标的设置

alien.x = alien_width+2*alien_width*alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height +2* row_bumber * alien.rect.height

在这里插入图片描述

3.控制外星人的移动
外星人的移动规则很简单,初始化后向右移动,一旦有外星人碰到界面的右边界则整体向下移动,然后向左移动,同理,一旦有外星人碰到界面左边界则整体继续向下移动,然后向右移动,依次反复进行。
分析:游戏外星人的移动方向可以简记为 fleet_direction(+1==>右移动,-1==>左移动)
所以对外星人位置的更新实现为:
对x坐标值更新:

    def update(self):
        '''向左/右移动外星人'''
        # self.x += self.ai_settings.alien_speed_factor#移动速度
        self.x += (self.ai_settings.alien_speed_factor*self.ai_settings.fleet_direction)
        self.rect.x = self.x

对y坐标值更新:(只有当有外星人触碰到游戏边界时才会发生)

def change_fleet_direction(ai_settings,aliens):
    '''将外星人群体下移,并改变移动方向'''
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1

def check_fleet_edges(ai_settings,aliens):
    '''有外星人到达边缘时采取相应的措施'''
    for alien in aliens.sprites():
        if alien.check_edges():#检测该外星人是否达到边缘
            change_fleet_direction(ai_settings,aliens)#改变移动方向
            break

同样的,更新完每个外星人的x,y坐标后,对群组aliens调用aliens.draw(screen)#在屏幕上绘制编组中的每一个外星人,实现外星人位置的更新。
在这里插入图片描述

4.飞船的射击行为
设计功能“玩家按空格键时发射子弹(小矩形),子弹在屏幕中向上穿行,碰到外星人,或者抵达屏幕上边界后消失
当检测到空格按下时,创建一个子弹实例

elif event.key == pygame.K_SPACE:#按下空格
fire_bullet(ai_settings,screen,ship,bullets)
def fire_bullet(ai_settings,screen,ship,bullets):
    '''如果子弹数量未达到限制,则发射一颗子弹'''
    #创建一个新的子弹对象并存储到bullets中
    if len(bullets) < ai_settings.bullets_allowed:#子弹数目限制
            new_bullet = Bullet(ai_settings,screen,ship)#创建一个子弹实例
            bullets.add(new_bullet)#将子弹实例添加到子弹群组中

注意子弹实例在创建时会记录当前飞船的位置:
bullet.py

	#将子弹移到正确的位置上
    self.rect.centerx = ship.rect.centerx
    self.rect.top = ship.rect.top

子弹射出后,只能向上移动

def update(self):
	'''向上移动子弹'''
	self.y -=self.speed_factor
	self.rect.y = self.y #更新子弹的位置

更新子弹坐标的方法

def update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets):
    '''更新子弹的位置后立即检测是否与外星人发生碰撞,并删除消失的子弹'''
    #更新子弹的位置
    bullets.update()#对编组调用update()方法时,会对每个成员都调用update()方法!!!
    #删除消失的子弹
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet) 

    check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets)

其中,check_bullet_alien_collisions()用来检测和响应子弹和外星人的碰撞,当见车到碰撞时,删除该子弹和外星人对象。

def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets):
    '''响应子弹和外星人的碰撞'''
    #检查是否有子弹击中了外星人
    #如果是,就删除相应的子弹和外星人
    collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
    #解析:便利编组中的每一颗子弹,再遍历编组中的每一个外星人,当有子弹和外星人的Rect重叠时,返回一个字典:键为子弹,值为碰撞的外星人[一个列表],后面两个参数TRUE指删除发生碰撞的子弹和外星人
    if collisions:
        for aliens in collisions.values():
            stats.score += ai_settings.alien_points * len(aliens)
            sb.prep_score()
        check_high_score(stats,sb)
    
    if len(aliens) == 0:#外星人被消灭完了,提升游戏等级和难度,开始新的一轮游戏
        start_new_level(ai_settings,screen,stats,sb,ship,aliens,bullets)

在这里插入图片描述

5.游戏结束的标志
游戏完结的情况:1.飞船与外星人碰撞2.外星人触碰到屏幕底端边界,同时每个玩家有三辆飞船,当飞船用完后,游戏完全结束。
1+2:出现1,2或任意一种情况都表示当前的飞船被击落了,调用ship_hit()方法进行界面重置,并更新剩余的飞船数量,当可用飞船数量为0时,游戏结束,设置游戏为非活跃状态(game_active=False)

if pygame.sprite.spritecollideany(ship,aliens):#发生碰撞,飞船被击落--
    #解析spritecollideany()检查编组成员是否与精灵发生重叠,返回找到的发生碰撞的第一个外星人
    # print('Ship hit!')#发生碰撞进行一系列处理
    ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)
check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets)#检查外星人到达底端
def check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets):
    '''检查是否有外星人到达了屏幕底端'''
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:#外星人抵达屏幕下界
            ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)#重置游戏
            break#只要有一个外星人到达屏幕底端就可以推出for循环了
def ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets):
    '''响应被外星人撞到的飞船,清空子弹和外星人,重新开始游戏'''
    # stats.ships_left -=1
    if stats.ships_left > 0:
        stats.ships_left -=1

        #跟新飞船剩余数量
        sb.prep_ships()
        #清空外星人和子弹列表
        aliens.empty()
        bullets.empty()

        create_fleet(ai_settings,screen,ship,aliens)
        ship.center_ship()#将飞船放到屏幕底端中央

        sleep(0.5)#暂停一下
    else:
        stats.game_active = False#飞船用完后,游戏结束
        pygame.mouse.set_visible(True)#让鼠标显现出来

在这里插入图片描述

6.其他的装饰部分
该项目还包含了:当前得分、历史最高分、可用飞船数量,游戏难度等级的可视化显示部分以及游戏开始按钮的点击检测,但不是关键先省略之,详细内容可参考上传到csdn上的代码,附带详细的注释和解析。
附上最终的游戏截图:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值