外星人入侵(五)

添加play按钮

  • 首先修改game_stats.py中的游戏状态属性,一开始为非活动状态 self.game_active=False
  • 创建一个button.py的类
    用于创建带标签的实心矩形,可以自定义创建任何按钮,下面是代码
#导入模块pygame.ftfont,它能让pygame将文本渲染到屏幕
import pygame.ftfont

class Button():
    #msg是要在按钮中显示的文本
    def __init__(self, ai, screen, msg):
        """初始化按钮的属性"""
        self.screen=screen
        self.screen_rect=screen.get_rect()

        #设置按钮的尺寸和颜色以及文本的颜色和字体
        self.width,self.height=200,50
        self.button_color=(0,255,0)
        self.text_color=(255,255,255)

        #传入实参None为默认字体,字体大小48号
        self.font=pygame.ftfont.SysFont(None,48)

        #创建按钮,并且将rect对象并居中
        self.rect=pygame.Rect(0,0,self.width,self.height)
        self.rect.center=self.screen_rect.center

        #接受实参self,以及要渲染为图像的文本
        self.prep_msg(msg)

    def prep_msg(self,msg):
        """将msg渲染为图形,并使按钮居中"""
        #调用font.render(文本,反锯齿开关(使文本的边缘更加平滑),文本颜色渲染,按钮颜色渲染)将储存在msg的文本装换为图像
        self.msg_image=self.font.render(msg,True,self.text_color,self.button_color)
        #使图像居中
        self.msg_image_rect=self.msg_image.get_rect()
        self.msg_image_rect.center=self.rect.center

    def draw_button(self):
        #绘制一个用颜色填充的按钮,在绘制文本
        self.screen.fill(self.button_color,self.rect)
        self.screen.blit(self.msg_image,self.msg_image_rect)

首先导入模块pygame.ftfont,它能让pygame将文本渲染到屏幕上,

  • 在屏幕上绘制按钮
    为方便,就直接粘贴源码了
    alien.invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
from game_stats import GameState

from button import Button


def run_game():
    #初始化游戏并创建一个屏幕对象
    pygame.init()
    #实例化settings对象
    ai=Settings()
    #创建游戏窗口大小
    screen=pygame.display.set_mode((ai.screen_width,ai.screen_height))
    #创建游戏标题
    pygame.display.set_caption("外星人大战")

    #创建按钮
    play_button=Button(ai,screen,"Play")

    bg_color=(230,230,230)
    #实例化飞船对象ship,传入屏幕实参
    ship=Ship(ai,screen)

    #创建一个用于存储游戏统计信息的实例
    stats=GameState(ai)
    #创造一个用于存储子弹和外星人的编组
    bullets=Group()
    aliens=Group()
    gf.create_fleet(ai,screen,ship,aliens)

    #开始游戏的主循环
    while True:

        gf.check_events(ai, screen, stats, play_button, ship, bullets)
        if stats.game_active:


            ship.update()
            gf.update_bullets(ai,screen,ship,aliens,bullets)

            gf.update_aliens(ai,stats,screen,ship,aliens,bullets)

        gf.update_screen(ai,screen,stats,ship,aliens,bullets,play_button)


if __name__ == '__main__':
    run_game()

主要是在主程序中实例化了按钮,以及按键事件监控和屏幕更新函数中修改了传入的实参,之后需要在game_functions.py中添加函数,实现开始按钮的作用

  • 开始游戏
    game_functions,py中实现相应的函数的创建与修改
import sys
from time import sleep

import pygame

from bullet import Bullet
from alien import Alien

def check_keydown_events(event, ai, screen, ship, bullets):

    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_SPACE:
        fire_bullet(ai, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()

def check_keyup_events(event, ship):

    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False

def check_events(ai, screen, stats,play_button,ship, bullets):

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai, screen, ship, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)
        elif event.type==pygame.MOUSEBUTTONDOWN:
            mouse_x,mouse_y=pygame.mouse.get_pos()
            check_play_button(stats,play_button,mouse_x,mouse_y)
def check_play_button(stats,play_button,mouse_x,mouse_y):
    """在玩家单击play按钮是开始游戏"""
    if play_button.rect.collidepoint(mouse_x,mouse_y):
        stats.game_active=True

def fire_bullet(ai, screen, ship, bullets):

    if len(bullets) < ai.bullet_nums:
        new_bullet = Bullet(ai, screen, ship)
        bullets.add(new_bullet)

def update_screen(ai_settings, screen,stats, ship, aliens, bullets,play_button):

    screen.fill(ai_settings.bg_color)


    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    aliens.draw(screen)

    #如果游戏处于非活动状态,就绘制按钮play
    if not stats.game_active:
        play_button.draw_button()

    pygame.display.flip()

def update_bullets(ai, screen, ship, aliens, bullets):

    bullets.update()

    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(ai, screen, ship, aliens, bullets)

def check_bullet_alien_collisions(a, screen, ship, aliens, bullets):

    collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

    if len(aliens) == 0:
        bullets.empty()
        create_fleet(ai, screen, ship, aliens)

def check_fleet_edges(ai, aliens):

    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai, aliens)
            break

def change_fleet_direction(ai, aliens):

    for alien in aliens.sprites():
        alien.rect.y += ai.fleet_drop_speed
    ai.fleet_direction *= -1

def ship_hit(ai, stats, screen, ship, aliens, bullets):

    if stats.ships_left > 0:
        # Decrement ships_left.
        stats.ships_left -= 1
    else:
        stats.game_active = False


    aliens.empty()
    bullets.empty()


    create_fleet(ai, screen, ship, aliens)
    ship.center_ship()

    # Pause.
    sleep(0.5)

def check_aliens_bottom(ai, stats, screen, ship, aliens, bullets):

    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:

            ship_hit(ai, stats, screen, ship, aliens, bullets)
            break

def update_aliens(ai, stats, screen, ship, aliens, bullets):

    check_fleet_edges(ai, aliens)
    aliens.update()


    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai, stats, screen, ship, aliens, bullets)


    check_aliens_bottom(ai, stats, screen, ship, aliens, bullets)

def get_number_aliens_x(ai, alien_width):

    available_space_x = ai.screen_width - 2 * alien_width
    number_aliens_x = int(available_space_x / (2 * alien_width))
    return number_aliens_x

def get_number_rows(ai, ship_height, alien_height):

    available_space_y = (ai.screen_height -
                            (3 * alien_height) - ship_height)
    number_rows = int(available_space_y / (2 * alien_height))
    return number_rows

def create_alien(ai, screen, aliens, alien_number, row_number):

    alien = Alien(ai, screen)
    alien_width = alien.rect.width
    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
    aliens.add(alien)

def create_fleet(ai, screen, ship, aliens):

    alien = Alien(ai, screen)
    number_aliens_x = get_number_aliens_x(ai, alien.rect.width)
    number_rows = get_number_rows(ai, ship.rect.height,
                                  alien.rect.height)


    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
            create_alien(ai, screen, aliens, alien_number,
                         row_number)

在监听事件中,监听鼠标是否点击play按钮,绘制开始按钮,并激活游戏状态

话不多说,上效果图
这里写图片描述

重置游戏

  • 重置游戏与隐藏光标
    game_functions.py,
    为了便于显示,加注释的为新更新的部分代码
import sys
from time import sleep

import pygame

from bullet import Bullet
from alien import Alien

def check_keydown_events(event, ai, screen, ship, bullets):

    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
    elif event.key == pygame.K_SPACE:
        fire_bullet(ai, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()

def check_keyup_events(event, ship):

    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

def check_events(ai, screen, stats, play_button, ship, aliens, bullets):

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai, screen, ship, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)
        elif event.type==pygame.MOUSEBUTTONDOWN:
            mouse_x,mouse_y=pygame.mouse.get_pos()
            check_play_button(ai, screen, stats, play_button, ship, aliens, bullets, mouse_x, mouse_y)
def check_play_button(ai,screen,stats,play_button,ship,aliens,bullets,mouse_x,mouse_y):
    """在玩家单击play按钮是开始游戏"""
    if not stats.game_active and play_button.rect.collidepoint(mouse_x,mouse_y):
        #隐藏光标
        pygame.mouse.set_visible(False)

        #重置游戏统计信息
        stats.reset_stats()

        stats.game_active=True

        #清空外星人列表和子弹列表
        aliens.empty()
        bullets.empty()

        #创建一群新的外星人,并让飞船居中
        create_fleet(ai,screen,ship,aliens)
        ship.center_ship()


def fire_bullet(ai, screen, ship, bullets):

    if len(bullets) < ai.bullet_nums:
        new_bullet = Bullet(ai, screen, ship)
        bullets.add(new_bullet)

def update_screen(ai_settings, screen,stats, ship, aliens, bullets,play_button):

    screen.fill(ai_settings.bg_color)


    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    aliens.draw(screen)

    #如果游戏处于非活动状态,就绘制按钮play
    if not stats.game_active:
        play_button.draw_button()

    pygame.display.flip()

def update_bullets(ai, screen, ship, aliens, bullets):

    bullets.update()

    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(ai, screen, ship, aliens, bullets)

def check_bullet_alien_collisions(a, screen, ship, aliens, bullets):

    collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

    if len(aliens) == 0:
        bullets.empty()
        create_fleet(ai, screen, ship, aliens)

def check_fleet_edges(ai, aliens):

    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai, aliens)
            break

def change_fleet_direction(ai, aliens):

    for alien in aliens.sprites():
        alien.rect.y += ai.fleet_drop_speed
    ai.fleet_direction *= -1

def ship_hit(ai, stats, screen, ship, aliens, bullets):

    if stats.ships_left > 0:
        # Decrement ships_left.
        stats.ships_left -= 1
    else:
        stats.game_active = False
        #光标显示
        pygame.mouse.set_visible(True)


    aliens.empty()
    bullets.empty()


    create_fleet(ai, screen, ship, aliens)
    ship.center_ship()

    # Pause.
    sleep(0.5)

def check_aliens_bottom(ai, stats, screen, ship, aliens, bullets):

    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:

            ship_hit(ai, stats, screen, ship, aliens, bullets)
            break

def update_aliens(ai, stats, screen, ship, aliens, bullets):

    check_fleet_edges(ai, aliens)
    aliens.update()


    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai, stats, screen, ship, aliens, bullets)


    check_aliens_bottom(ai, stats, screen, ship, aliens, bullets)

def get_number_aliens_x(ai, alien_width):

    available_space_x = ai.screen_width - 2 * alien_width
    number_aliens_x = int(available_space_x / (2 * alien_width))
    return number_aliens_x

def get_number_rows(ai, ship_height, alien_height):

    available_space_y = (ai.screen_height -
                            (3 * alien_height) - ship_height)
    number_rows = int(available_space_y / (2 * alien_height))
    return number_rows

def create_alien(ai, screen, aliens, alien_number, row_number):

    alien = Alien(ai, screen)
    alien_width = alien.rect.width
    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
    aliens.add(alien)

def create_fleet(ai, screen, ship, aliens):

    alien = Alien(ai, screen)
    number_aliens_x = get_number_aliens_x(ai, alien.rect.width)
    number_rows = get_number_rows(ai, ship.rect.height,
                                  alien.rect.height)


    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x+1):
            create_alien(ai, screen, aliens, alien_number,
                         row_number)

  • 主程序随之相应调整
    alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
from game_stats import GameState
from button import Button


def run_game():
    #初始化游戏并创建一个屏幕对象
    pygame.init()
    #实例化settings对象
    ai=Settings()
    #创建游戏窗口大小
    screen=pygame.display.set_mode((ai.screen_width,ai.screen_height))
    #创建游戏标题
    pygame.display.set_caption("外星人大战")

    #创建按钮
    play_button=Button(ai,screen,"Play")

    bg_color=(230,230,230)
    #实例化飞船对象ship,传入屏幕实参
    ship=Ship(ai,screen)

    #创建一个用于存储游戏统计信息的实例
    stats=GameState(ai)
    #创造一个用于存储子弹和外星人的编组
    bullets=Group()
    aliens=Group()
    gf.create_fleet(ai,screen,ship,aliens)

    #开始游戏的主循环
    while True:

        gf.check_events(ai, screen, stats, play_button, ship, aliens, bullets)
        if stats.game_active:


            ship.update()
            gf.update_bullets(ai,screen,ship,aliens,bullets)

            gf.update_aliens(ai,stats,screen,ship,aliens,bullets)

        gf.update_screen(ai,screen,stats,ship,aliens,bullets,play_button)


if __name__ == '__main__':
    run_game()

这里写图片描述

拓展

  • 这里还有一个bug没有解决,不过也是考验大家的一点小问题了,后面会解决的,有能力的可以先解决,那就是飞船上去碰撞后,死亡原地复活,没有重置到屏幕底端,导致与重新刷新的外星人碰撞,碰撞检测下再次死亡,结果,游戏崩溃卡死,这里先留下一个小问题,后面笔者会解决的,不过不影响游戏的运行,bug图如下
    这里写图片描述

猜你喜欢

转载自blog.csdn.net/jia666666/article/details/81281955
今日推荐