Day 11 武装飞船

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

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)添加子弹设置
2)创建Bullet类
3)将子弹存储到编组中
4)开火
5)删除已消失的子弹
6)限制子弹数量
7)创建函数update_bullets()
8)创建函数fire_bullet()

热门文章

暂无图片
编程学习 ·

Spring Boot 整合 Redis

Redis 基于内存进行存储,支持key-value的存储形式,底层是C 基于key-value形式的数据字典,没有数据表的概念,直接用键值对的形式完成数据管理 支持五种数据类型:字符串列表集合有序集合哈希安装Redis 1.下载Redis:https://redis.io/download 2.解压并在本地硬盘人任意位置…
暂无图片
编程学习 ·

【考试记录】Apsara Clouder基础技能认证:实现调用API接口

从今天开始,准备把阿里的认证尽可能多的考出来。原因有这么几个:研究生要毕业了,除了把论文写好,还有找工作的压力,所以想尽可能多的考出几个证来证明自己的学习能力;研究生毕业后想找个教师的工作,所以得以身作则,多学习知识,这样教学生才能有底气。知道自己现在能力…
暂无图片
编程学习 ·

[UML] 类图之间的关系 | 3.泛化关系

[UML] 类图之间的关系 | 3.泛化关系 3.泛化关系泛化(Generalization)关系也就是**继承关系**,用于描述父类与子类之间的关系,父类又称为基类或超类,子类又称为派生类 在UML中,泛化关系用带空心三角形的直线来表示 在代码实现时,使用面向对象的继承机制来实现泛化关系,在J…
暂无图片
编程学习 ·

Java工具类-使用RSA验签

1 私钥签名public static String signByKey(String content,String privateKey) {PKCS8EncodedKeySpec sp = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(privateKey));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey key = keyF…
暂无图片
编程学习 ·

Java从小白到老白学习笔计【一】

命令提示符(cmd) 启动 win + r 切换盘符 盘符名称: 进入文件夹 cd 文件夹名称 进入多级文件夹 cd 文件夹1\文件夹2\文件夹3 返回上一级 cd… 直接回根路径 cd 查看当前内容 dir 清屏 cls 退出 exit String 首字母大写,不是关键字 加号代表字符串的连接操作 任何…
暂无图片
编程学习 ·

flutter textfield设置高度后内容无法居中

Container(height: 50,width: MediaQuery.of(context).size.width * 2 / 3,alignment: Alignment.center,child: TextField(autofocus: true,decoration: InputDecoration(//这行代码是关键,设置这个之后,居中contentPadding: EdgeInsets.all(2),hintText: 请输入手机号,pref…
暂无图片
编程学习 ·

如何理解numpy中的c_函数

其实,c_并不是一个函数,它只是CClass类的一个实例,而CClass是定义了切片方法__getitem__的类,所以c_就可以使用切片,仿佛就像一个函数一样。源代码是这样的#头部声明c_变量__all__ = [ravel_multi_index, unravel_index, mgrid, ogrid, r_, c_,s_, index_exp, ix_, ndenum…
暂无图片
编程学习 ·

zookeeper的安装及配置

zookeeper的安装及配置解压zookeeper压缩包 tar -xvf zookeeper-3.4.10.tar -C ~/softwares softwares是在~下自行创建的一个目录创建软连接 ln -s zookeeper-3.4.10/ zookeeper(方便以后更换)配置环境 进入~/.bashrc文件,配置环境变量 vi ~/.bashrc ####ZOOKEEPER_CONF####…
暂无图片
编程学习 ·

Obliv-C使用详解

前期说明 Obliv-C是一款GCC包装器,其作者在C语言的基础上对其进行了一定的类C处理,添加了一些规则限制,用于模拟实现混淆电路 Obliv-C不需要手动混淆,只需要调用其中的函数便可实现混淆电路,其不涉及真实硬件电路仿真,即无法导出函数对应的基本元电路(也可能是博主没有成…
暂无图片
编程学习 ·

LeetCode刷题之动态规划的解题方法及相关练习

从集合的角度来考虑DP问题,用某一个数来代表一类数线性DP: 快乐的LeetCode — 53.最大子序和快乐的LeetCode — 120. 三角形最小路径和多口味LeetCode — 63. 不同路径 II多味的LeetCode — 91. 解码方法区间DP问题 多味的LeetCode — 198. 打家劫舍多味的LeetCode — 300. 最…
暂无图片
编程学习 ·

Android MVVM Demo

AndroidMvvm练习AndroidMVVM 是Google推出的,网上介绍也有很多,我就不废话了,公司项目中使用的mvvm,我整理个小demo练习记录一下1.DataBinding配置dataBinding {enabled = true}在XML中使用, 原先的布局还是照常写<layout xmlns:android="http://schemas.android.c…
暂无图片
编程学习 ·

Spring MVC的运行原理(简答)

a)(浏览器)用户发送请求 b)前端控制器(dispatcherServlet)接收(他会委托其他模块进行真正的业务和数据处理 ) c)向handlermapping发送url查找相应的方法(handlermapping中储存的是url 和方法的键值对) d)返回处理器(“地址”)。 e)前端控制器发送处理器“地址”给处理…
暂无图片
编程学习 ·

windows10设置jdk环境变量

先安装好jdk 电脑–>属性–>高级系统设置–>新建 点击Path,编辑 添加这两项,确定 win+R打开cmd java -version检查jdk环境变量是否配置成功
暂无图片
编程学习 ·

关于this对象

this对象是是在运行时基于函数的执行环境绑定的 var object = {name: "My Object",getName: function(){return this.name; } } let b = object.getName; console.log(object.getName()); // "My Object" console.log(b()); // undefined 在全局函数中,…
暂无图片
编程学习 ·

Python简单数据库系统-优惠券系统(含UI)

Python简单数据库系统-优惠券系统(含UI) 目录Python简单数据库系统-优惠券系统(含UI)简介需要的东西函数主体券号和密码初始化状态UI出票系统验证系统总结 简介 疫情结束后各大企业尤其是饮食业都在想着法子用优惠券的方式吸引大众消费,于是对优惠券这个小型数据库系统产生…
暂无图片
编程学习 ·

华为rip动态路由理论+实操,带你玩转RIP协议

文章目录一、动态路由rip原理1.1动态路由概述1.2动态路由协议分类1.3RIP路由协议1.3.1RIP基本概念1.3.2RIP协议的特性1.3.3RIP度量值与更新时间1.3.4水平分割1.3.5RIP v1和RIP v2的区别1.3.6RIP兼容模式二、RIP实验2.1实验环境2.2实验拓扑图2.3实验过程2.3.1R1配置2.3.2R2配置2…
暂无图片
编程学习 ·

java如何遍历Map

1.利用map.keySet()普通遍历public static void main(String[] args) {Map<Integer,String> map=new HashMap<>();map.put(1,"努力");map.put(2,"勤奋");map.put(3,"懒惰");for(Integer key:map.keySet()){System.out.println("…