前言:python 除了生孩子 ,啥都会 。包括打飞机 !今天小詹的一位读者就来教你如何用 python 打飞机 !

简述

相信小詹是一个单纯的孩子 ,也相信大家明白小詹说的打飞机是指啥意思 ,对吧 ?嗯 ,没毛病 。就是 pygame 实现一个打飞机的游戏 ,优秀的我啊 !

我们知道 pygame 框架可以用于管理图形 、动画声音等 ,能够利用它来轻松地开发复杂的游戏 ,可以让我们更加专注于面向对象编程 。此项目是基于 pygame 框架搭建的一个小游戏 ,在此文中将实现此项目的 50% ,后续会有跟进 ,源代码已经放在我的 GitHub 中 ,并在进行中将会不断对代码结构进行优化 ,对样式进行优化 。在本例中将会接触简单的面向对象编程和继承 。面向对象编程是提取项目中某种事物的关键属性进行抽象 ,抽象模型中包括数据和行为 ,类是对象的抽象 ,对象是类的实例 。

源代码获取方式见置顶留言 。

先送上一波效果图(被压缩的时间略短)

效果图

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

游戏用例图(第一次画用例图,不是很准确……)

用例图

分析该项目 ,飞船 、子弹 、外星人可以分别划分为具有共同属性的一类 ,类中定义各自的属性 ,包括图像 、形状 、位置 、更新位置 、绘制图像等 ;在主函数中将对象实例化 ,对对象中的成员变量和函数进行调用实现移动 、击杀等操作 ;本节实现飞船和子弹类和基本功能 。

在构建子弹类时 ,用到了继承的概念 ,当在参与大型项目开发设计时 ,继承是一个非常关键的概念 。继承是对已有类的一种复用 ,子类继承父类 ,可以对父类中的方法和数据进行重写 ,也可以新定义只属于子类的成员变量 。当项目中有许多类具有相同的基本属性时 ,可以考虑将这些基本属性抽象为一个父类 ,子类通过继承父类而拥有父类中的数据和方法 ,这会提高代码的可读性 ,也省去很多重复的代码 。

当前新建以下几个文件 :alien-invasion.py 主函数

ship.py 飞船类

bullet.py 子弹类

game_functions.py 许多主函数会调用的函数

settings.py 配置文件 ,常量

其目录结构如下 :

代码运行步骤 :

方法 1——git clone https://github.com/AlisaBen/easycoding

powershell进入到工程目录下(/fun_python>)

cd ./alien_invasion

python alien_invasion.py

方法2——按照下面代码部分新建文件 ,并复制代码

在文件的同级目录下新建images目录

找飞船和子弹的图片分别命名为外星飞船.png和生气.png.emmm…画风有点不对 ,怪我了 ,阔以自己找图片替代 ,对应修改飞船类和子弹类的文件名就好 ~

进入到代码的根目录下

python alien_invasion.py

代码

alien-invasion.pyrun_game()定义了主函数 ,首先绘制屏幕 , 对象 screen 是一个 surface ,在 pygame 中,surface 是屏幕的一部分 ,显示游戏元素 。每个元素 ,外星人或者飞船 ,子弹都是一个surface 。

ship = Ship(game_settings,screen)就是一个对象是类的实例的例子 ,arguments 是类初始化需要传入的参数 ,ship就是Ship类型的对象 ,可以访问Ship类中的数据和方法 。

每个游戏循环中 ,更新飞船位置 ,子弹位置 ,子弹编组 ,重新渲染游戏界面 。

子弹编组用来管理屏幕中的所有子弹 ,其实用列表来管理子弹对象也是可以实现的 ,但是 pygame 自带的 Group 已经定义了一些函数 ,更加方便 。import pygame

from settings import Settings

from ship import Ship

import game_functions as gf

from pygame.sprite import Group

def run_game():

pygame.init()

# 获取配置

game_settings = Settings()

# 绘制屏幕

screen = pygame.display.set_mode((game_settings.screen_width,game_settings.screen_height))

backgound_color = (220,230,230)

pygame.display.set_caption("Alien Invasion")

# 飞船实例化

ship = Ship(game_settings,screen)

# 子弹编组,管理屏幕中所有的子弹,保存继承Sprite类的Bullet实例

bullets = Group()

while True:

# 检测飞船事件:左移右移发射子弹

gf.check_events(ship,game_settings,screen,bullets) # 修改飞船移动标志

ship.update() # 根据飞船移动标志重新计算飞船中心位置

# 更新所有子弹位置

gf.update_bullets(bullets)

# 绘制飞船子弹

gf.update_screen(game_settings,screen,ship,bullets)

run_game()

ship.py类飞船类中主要涉及类初始化 ,飞船位置更新和渲染飞船surface 。

在初始化中主要定义一些代表飞船属性的成员变量 ,如图像 ,飞船矩形外形 ,飞船中心 ,飞船左移标志和右移标志等 。

涉及 pygame 的图像load()方法和get_rect()方法 ,主要是为了之后飞船和外星人进行碰撞计算 ,其实可以直接self.image = pygame.image.load('images/外星飞船.png')加载图像 ,但是图像太大 ,就pygame.transform.smoothscale方法修改图像大小 。import pygame

class Ship(object):

"""docstring for Ship"""

def __init__(self, game_settings,screen):

super(Ship, self).__init__()

self.game_settings = game_settings

self.screen = screen # screen游戏界面

self.image = pygame.image.load('images/外星飞船.png').convert_alpha() # 加载飞船图像

# 修改图像大小

self.width,self.height = self.image.get_size()

self.image = pygame.transform.smoothscale(self.image,(self.width//2,self.height//2))

self.rect = self.image.get_rect()

self.screen_rect = screen.get_rect()

# 获取游戏界面的中心x坐标和底部位置便可确定飞船位置

self.rect.centerx = self.screen_rect.centerx

self.rect.bottom = self.screen_rect.bottom - game_settings.screen_height / 5

self.center = float(self.rect.centerx) # centerx中只能表示整数

# 移动标志

self.moving_right = False

self.moving_left = False

def update(self):

"""

根据移动标志调整飞船位置

更改为根据self.center更新位置

"""

if self.moving_right and self.rect.right < self.screen_rect.right:

# self.rect.centerx += 1

self.center += self.game_settings.ship_speed_factor

if self.moving_left and self.rect.left > 0:

# self.rect.centerx -= 1

self.center -= self.game_settings.ship_speed_factor

# 更新centerx,因为绘制图形是根据self.rect()

# self.rect()定位需要根据centerx,bottom

self.rect.centerx = self.center

def blitme(self):

"""在self.rect位置绘制图像"""

self.screen.blit(self.image,self.rect)

bullet.py

在子弹类中尤为需要说明的是该类继承了Sprite精灵类 ,继承精灵类中的方法 。import pygame

from pygame.sprite import Sprite

# 继承Sprite类,完善自己的代码

class Bullet(Sprite):

"""docstring for Bullet"""

def __init__(self, game_settings,screen,ship):

super(Bullet, self).__init__()

self.screen = screen

# # 在0,0位置创建bullet,并设置宽高

# self.rect = pygame.Rect(0,0,game_settings.bullet_width,game_settings.bullet_height)

# # 调整子弹位置到飞船所在位置,调整top相同,中心x坐标相同

# self.rect.centerx = ship.rect.centerx

# self.rect.top = ship.rect.top

# # 将y坐标存储为小数值,以便能够微调子弹的速度

# self.y = float(self.rect.y)

# self.color = game_settings.bullet_color

# self.speed_factor = game_settings.bullet_speed_factor

# 把子弹换成一个好玩的图片,把图片转换成位图

self.image = pygame.image.load('images/生气.png').convert_alpha()

# 修改图像大小

self.width,self.height = self.image.get_size()

self.image = pygame.transform.smoothscale(self.image,(self.width//10,self.height//10))

self.rect = self.image.get_rect()

# 调整子弹位置到飞船所在位置,调整top相同,中心x坐标相同

self.rect.centerx = ship.rect.centerx

self.rect.top = ship.rect.top

# 将y坐标存储为小数值,以便能够微调子弹的速度

self.y = float(self.rect.y)

self.speed_factor = game_settings.bullet_speed_factor

def update(self):

"""向上移动子弹"""

# 更新一次坐标y向上移动speed_factor个像素

self.y -= self.speed_factor

# 更新子弹的rect位置

self.rect.y = self.y

def draw_bullet(self):

# """

# API:rect(Surface,color,Rect,width=0)->Rect

# draw a rectangular shape on the Surgace

# The width argument is the thickness to draw the outer edge.

# If width is zero then the rectangle will be filled.

# """

# pygame.draw.rect(self.screen,self.color,self.rect)

"""在self.rect位置绘制图像"""

self.screen.blit(self.image,self.rect)

game_functions.py该文件的作用主要是集成主函数逻辑函数 ,判断飞船事件 ,更新子弹编组和更新屏幕

fill函数填充屏幕严肃 ,参数rgb

需要说明的是 bullets 子弹编组需要更新判断子弹是否超出屏幕 ,以从编组中删除 ,否则会影响效率

鼠标和键盘监听事件pygame.event.get();事件键pygame.K_RIGHT pygame.K_LEFT pygame.K_SPACE 事件类型pygame.KEYDOWN pygame.KEYUPimport pygame

import sys

from bullet import Bullet

def check_keydown_events(event,ship,game_settings,screen,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(game_settings,screen,ship,bullets)

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

"""

如果没有超过当前屏幕显示的最多子弹数,实例化子弹,添加到子弹编组中

"""

if(len(bullets) < game_settings.bullet_allowed):

bullet = Bullet(game_settings,screen,ship)

bullets.add(bullet)

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,game_settings,screen,bullets):

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

elif event.type == pygame.KEYDOWN:

check_keydown_events(event,ship,game_settings,screen,bullets)

elif event.type == pygame.KEYUP:

check_keyup_events(event,ship)

def update_screen(game_settings,screen,ship,bullets):

screen.fill(game_settings.background_color)

ship.blitme()

"""

API:pygame.sprite.Group.sprites

sprites() -> sprite_list

bullet迭代器

"""

for bullet in bullets.sprites():

bullet.draw_bullet()

pygame.display.flip()

def update_bullets(bullets):

bullets.update()

# 超出屏幕边界移除子弹

# 子弹编组副本

for bullet in bullets.copy():

if bullet.rect.bottom <= 0:

bullets.remove(bullet)

# 注释掉,调试用,耗时

# print(len(bullets))

settings.py配置文件

将常量变量继承在配置文件中 ,当需要修改常量提高游戏体验时 ,直接修改该文件即可class Settings(object):

"""docstring for Settings"""

def __init__(self):

super(Settings, self).__init__()

self.screen_width = 1200

self.screen_height = 800

self.background_color = (230,230,230)

self.ship_speed_factor = 1.5 # 飞船一个while循环走1.5像素

# 子弹配置

self.bullet_width = 3

self.bullet_height = 15

self.bullet_color = (120,120,120)

self.bullet_speed_factor = 3

self.bullet_allowed = 5 # 最大子弹数

pygame接口文档总结

API接口描述pygame.init()init() -> None

pygame.display.set_mode()set_mode(resolution=(0,0), flags=0, depth=0) -> SurfaceInitialize a window or screen for display

pygame.display.set_caption()set_caption(title, icontitle=None) -> None

pygame.event.get()

pygame.image.load()load(filename) -> Surface

get_rect()

blit()

pygame.transform.smoothscale()smoothscale(Surface, (width, height), DestSurface = None) -> Surface

pygame.display.flip()flip() -> NoneUpdate the full display Surface to the screen

python打飞机源代码-如何用 Python 打飞机 ?相关推荐

  1. pythonturtle画飞机_如何用 Python 画一个纸飞机?| 原力计划

    以下文章来源于一粒微小的尘埃 ,作者一粒微小的尘埃 [CSDN 编者按]如果你是一个 80 后,可能对于卓依婷的歌曲<纸飞机>并不陌生.歌词里说:" 飞在风里的纸飞机,载满我对你 ...

  2. 用python绘制柱状图标题-如何用Python绘制3D柱形图

    本文主要讲解如何使用python绘制三维的柱形图,如下图 源代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 ...

  3. python三维柱形图_如何用Python绘制3D柱形图

    本文主要讲解如何使用python绘制三维的柱形图,如下图 源代码如下: import numpy as np import matplotlib.pyplot as plt from mpl_tool ...

  4. 用python画耳朵_如何用python画猪头

    用python画猪头的方法:首先设置画布和画笔,代码为[a.screensize(400,300)a.setup(width=400,height=300)]:然后画脸型,代码为[.goto(-100 ...

  5. python怎么读_如何用Python读写文件

    前面我们已经介绍了很多Python相关的基础知识,大家是不是对Python已经有了进一步认识了呢?作为人工智能时代的热门编程语言,开始接触并学习Python的孩子越来越多,家长们都不想让自己的孩子落于 ...

  6. python大数据分析实例-如何用Python分析大数据(以Twitter数据挖掘为例)

    原标题:如何用Python分析大数据(以Twitter数据挖掘为例) 来源:艾翻译(http://www.itran.cc/) 原文标题:Twitter Data Mining: A Guide to ...

  7. 有道python网课怎么样-如何用python“优雅的”调用有道翻译?

    前言 其实在以前就盯上有道翻译了的,但是由于时间问题一直没有研究(我的骚操作还在后面,记得关注),本文主要讲解如何用python调用有道翻译,讲解这个爬虫与有道翻译的js"斗争"的 ...

  8. python画树叶-手把手|如何用Python绘制JS地图?

    原标题:手把手|如何用Python绘制JS地图? 关于转载授授权 大数据文摘作品,欢迎个人转发朋友圈,自媒体.媒体.机构转载务必申请授权,后台留言"机构名称+文章标题+转载",申请 ...

  9. python写乘法口诀-如何用python编写乘法口诀表

    如何用python编写乘法口诀表?首先要明确一下思路,我们可以确定x,y两个变量,弄清楚其变化的规律,再使用循环嵌套实现.下面是如何用Python编写乘法口诀表的具体方法. 第一种:使用for遍历循环 ...

最新文章

  1. NETCore Bootstrap Admin 通用后台管理权限 [1]: 前后台分离系统简介
  2. yum搭建lnmp的最简单方法
  3. 单片机c语言出租车计时程序,基于单片机的出租车计费(c语言).doc
  4. 关于安装完Node.js 出现node is not dedined 问题
  5. 第八届蓝桥杯第三题承压计算
  6. Android系统中属性值的设置和使用
  7. ## 数据结构之单向链表的基本操作详细总结 爆肝总结超详细万字长文C语言版
  8. 计算机科学技术学习引论
  9. mysql性能调优面试题_面试题大全-mysql性能优化方案
  10. ML-Agents案例之跳墙游戏
  11. Modem analyze by T32 tool.
  12. 什么是html5页面ui,H5页面UI设计和APP设计有什么区别?
  13. 切片器可以设置日期格式?_在Power BI中设置切片器的默认值,你会吗?
  14. LIC(最长子序列)
  15. html批量转码工具,文件转码工具(文件GBK与UTF编码批量转码工具)
  16. wma格式怎么转换mp3
  17. 旷视科技2023校园招聘提前批正式启动!
  18. qemu内存模型(3) 内存布局初始化
  19. Linux命令:ifconfig出现command not found 的解决办法
  20. YSZI的微信公众号导航软件按装方法

热门文章

  1. mysql文档摘要续4
  2. Tiny210编译和烧写u-boot步骤
  3. 数据回发时,维护ASP.NET Tree控件位置
  4. windows修改环境变量神器—Rapid Environment Editor
  5. Unity3D深入浅出 -组件与节点之间的调用关系
  6. asp.net使用easyUI 前后台数据交互
  7. 2017-03-02学习心得之Java代码
  8. Hibernate:不容易理解的 lock 和 merge
  9. 一个项目从开工到交付使用需要经历的过程
  10. HDU 2079 选课时间(题目已修改,注意读题) 母函数 || 多重背包