《Python编程入门到实践》第十二章 武装飞船

《外星人入侵》游戏要实现的是:玩家控制一艘出现在屏幕底部中央的飞船,可以使用箭头左右移动飞船,还可以使用空格来进行射击,游戏开始时候一群外星人出现在天空,他们在屏幕中向下移动,玩家的任务是射杀这些外星人,玩家将所有外星人都消灭干净后,会出现一群新的外星人,他们移动的速度会更快,只要外星人撞到了玩家的飞船或者是到达了屏幕底部,玩家就损失一艘飞船,损失三艘以后,游戏结束。

1. 安装Pygame

直接在pycharm里file-setting-添加(我的是无效的)
在这里插入图片描述
我的环境是anaconda+pycharm,安装流程如下
step1:下载pygame http://www.pygame.org/download.shtml
step2:将下载的whl文件剪贴到anaconda\Lib\site-packages目录下,Windows+R打开cmd依次进入文件所在目录,最后输入

pip install pygame-1.9.4-cp37-cp37m-win_amd64.whl

step3:此时应该已经安装完成,可以在cmd中输入 pip list 找一下其中有没有pygame。或者在输入import pygame
在这里插入图片描述

2. 开始游戏项目

2.1 创建Pygame窗口以及响应用户输入

#alien_invasion.py
import pygame
from settings import Settings
from  ship import Ship
import sys

def run_game():
    #初始化一个游戏并创建一个屏幕对象
    pygame.init()
    ai_settings = Settings()
    screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
    pygame.display.set_caption('Alien Invasion')
    ship = Ship(screen)
    #开始游戏的主循环
    while True:
        #监视键盘和鼠标事件
        for enevt in pygame.event.get():
            if enevt.type == pygame.QUIT:
                sys.exit()
        screen.fill(ai_settings.bg_color)
        ship.blitme()
        pygame.display.flip()

run_game()

在这里插入图片描述
在这里插入图片描述
在此处代码的实参应为元组而不是int
所以应修改为:
在这里插入图片描述

2.2 设置背景颜色

在Pygame中颜色以RGB值来指定的即红绿蓝,每个值0~255。(255,0,0)表示红色,类推即可。

bg_color = (230,230,230) 

2.3 创建设置类

把游戏添加的新功能引入一些新设置都存在一个Settings类里,便于添加和修改

#settings.py
class Settings():
    def __init__(self):
        self.screen_width = 1000
        self.screen_height = 600
        self.bg_color = (230,230,230)

2.4 添加飞船图像

在Pygame中使用.bmp位图最简单(因为是默认加载位图),加载图像以后用blit()绘制

2.5 创建飞船ship类

# ship.py
import pygame

class Ship():
    def __init__(self,screen):
        self.screen = screen
    #加载飞船图像并获取其外接矩形
        self.image = pygame.image.load('images/ship.bmp')
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()
    #将每艘新飞船放在屏幕底部中央
        self.rect.centerx = self.screen_rect.centerx
        self.rect.bottom = self.screen_rect.bottom
    def blitme(self):
    #在指定位置绘制飞船
        self.screen.blit(self.image,self.rect)

2.6 在屏幕上绘制飞船

 pygame.display.flip()

在这里插入图片描述

2.7重构:模块game_functions

重构旨在简化既有代码的结构,使其更容易扩展

#game_functions.py
import sys
import pygame

def check_events():
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

def update_screen(ai_settings,screen,ship):
    """更新屏幕上的图像并切换到新的屏幕"""
      #每次循环时都重新绘制屏幕
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    #让最近绘制的屏幕可见
    pygame.display.flip()

对应的alien_invasion.py改变为:

from settings import Settings
from  ship import Ship
import game_functions as gf
from  settings import Settings
import sys

def run_game():
    #初始化一个游戏并创建一个屏幕对象
    pygame.init()
    ai_settings = Settings()
    screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
    pygame.display.set_caption('Alien Invasion')
    ship = Ship(screen)
    #开始游戏的主循环
    while True:
        gf.check_events()
        gf.update_screen(ai_settings,screen,ship)

run_game()

2.8 驾驶飞船

1)响应按键:每当用户按键时,都将在Pygame中注册一个事件,事件都是通过方法pygame.event.get()获取的,因此在函数check_events()中,我们需要指定要检查哪些类型的事件,每次按键都被注册为一个KEYDOWN事件,检测到KEYDOWN事件时我们需要检查按下的是否是特定的键。

#game_functions.py
def check_events(ship):
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                #向右移动飞船
                ship.rect.centerx += 1

此时check_events()包含形参ship且有检测KEYDOWN时间作出相应,判断是否右移再响应。
2)允许不断移动

#game_functions.py
def check_events(ship):
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                #向右移动飞船
                ship.moving_right = True
        elif event.type == pygame.KEYUP: #松开按键即不再右移
            if event.key == pygame.K_RIGHT:
                ship.moving_right = False

3)左右移动

#game_functions.py
def check_events(ship):
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                #向右移动飞船
                ship.moving_right = True
            elif event.key == pygame.K_LEFT:
                ship.moving_left = True

        elif event.type == pygame.KEYUP: #松开按键即不再右移
            if event.key == pygame.K_RIGHT:
                ship.moving_right = False
            elif event.key == pygame.K_LEFT: #松开按键即不再右移
                ship.moving_left = False

4)调整飞船的速度
在这里的修改要注意的是rect的centerx等属性只能存储整数值,因此需要使用函数float()将self.rect.centerx的值转换为小数,将结果存到self.center中。在Ship中需要传入实参ai_settings.

5)限制飞船的活动范围
出现的错误:
在这里插入图片描述
错误的原因:
screen 是一个没有 rect 属性的pygame.Surface
代码的书写中有错误!!要细心呐!
在这里插入图片描述
6)重构check_events()

#game_functions.py
def check_keydown_events(event,ship):
    if event.key == pygame.K_RIGHT:
    #向右移动飞船
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
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(ship):
    """"响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event,ship)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event,ship)

def update_screen(ai_settings,screen,ship):
    """更新屏幕上的图像并切换到新的屏幕"""
      #每次循环时都重新绘制屏幕
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    #让最近绘制的屏幕可见
    pygame.display.flip()

7)简单回顾
alien_invasion.py: 创建一系列整个游戏都要用到的对象,存储在ai_settings中的设置、存储在screen中主显示surface以及一个飞船实例。包括游戏的主循环,调用check_events()、ship.update()以及update_screen()的while循环
settings.py: 初始化控制游戏外观和飞船速度的属性
game_functions.py: 在这个文件里包含一系列函数,游戏的大部分工作都是由它们完成的,函数check_events()检测相关事件,比如按键和松开,并使用付出函数来处理这些事件,目前这些函数管理飞船的移动。模块还包括update_screen(),用于每次执行主循环的时候都重回屏幕
ship.py: 管理飞船位置的方法以及在屏幕上绘制飞船的方法。

2.9 射击

1)添加子弹设置

#Settings.py
        self.bullet_speed_factor = 1
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60,60,60)
        self.bullets_allowed = 3

2)创建Bullet类

import  pygame
from  pygame.sprite import Sprite

class Bullet(Sprite):
    """一个对飞船发射的子弹进行管理的类"""
    def __init__(self,ai_settings,screen,ship):
        """在飞船所处的位置创建一个子弹对象"""
        super(Bullet,self).__init__()
        self.screen = screen

        #在(0.0)处创建一个表示子弹的巨型,再设置正确的位置
        self.rect = pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_width)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top
        #存储用小数表示子弹的位置
        self.y = float(self.rect.y)
        self.color = ai_settings.bullet_color
        self.speed_factor = ai_settings.bullet_speed_factor

    def update(self):
        """向上移动子弹"""
        #更新表示子弹位置的小数值
        self.y -= self.speed_factor
        #更新表示子弹的rect位置
        self.rect.y = self.y

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

3)将子弹存储到编组中
4)开火
5)删除已消失的子弹
6)限制子弹数量
7)创建函数update_bullets()

def update_bullets(bullets):
    """更新子弹的位置并删除已消失的子弹"""
    #更新子弹的位置
    bullets.update()
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

8)创建函数fire_bullet()

def fire_bullet(ai_settings,screen,ship,bullets):
    if len(bullets)<ai_settings.bullets_allowed:
        new_bullet =Bullet(ai_settings,screen,ship)
        bullets.add(new_bullet)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值