大学最后的考试终于结束了,迎来了暑假和大四的漫长的“自由”假期。当然要自己好好“玩玩”了。

我最近在学习Python,本意是在机器学习深度学习上使用Python进行编程的而学习的。偶然接触了pygame,觉得很感兴趣,所以打算使用pygame制作一个小游戏作为对Python学习和练习。

废话不多说了,先介绍一下pygame。

简要介绍:

请原谅本人比较懒,直接上百度百科进行介绍:(点我打开链接

Pygame是跨平台Python模块,专为电子游戏设计。

包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。基于这样一个设想,所有需要的游戏功能和理念都(主要是图像方面)都完全简化为游戏逻辑本身,所有的资源结构都可以由高级语言提供,如Python。

Pygame 原为代替突然停止的 pySDL

Pygame 作者是 Pete Shinners 协议为 GNU Lesser General Public License

简单点概括,pygame是个专门用来做游戏开发的库,提供了一些较方便的API。

设计目标:

1、设计一个飞机大战的游戏,玩家能控制一架飞机在游戏界面内通过界面上下左右移动;

2、飞机能发射子弹,自动前进,当走出游戏界面之外时,其自动删除;

3、敌机随机产生,并自动前进,当走出游戏界面之外时,其自动删除;

4、如果敌机碰到子弹则,敌机破坏;

5、如果敌机碰到我方飞机,则游戏结束;

游戏运行截图:

源码下载:

网友分享的打飞机小游戏源码:打开链接(不需要积分)

我自己写的小游戏源码:打开链接(功能稍微要简单一些,收1分的积分做辛苦费╮(╯▽╰)╭)

环境搭建:

我是在Ubuntu环境下进行开发的,所以使用以下指令既可以自动安装配置好环境:

  1. sudo apt-get install python-pygame

安装完成后,为检验是否配置成功。先进入Python交互环境,试着import pygame看看会不会报错。

程序架构构思:

1、首先,可以想到程序中可以分为3个类,即:玩家的飞机、敌机、子弹,所以功能都可以在这几个类中定义方法来实现;

2、背景可以调用pygame中的相关类和方法读出图片,随后在其上添加飞机、敌机、子弹的贴图即可,效果音也可以调用相关类和方法实现;

3、由于存在复数个敌机和子弹,所以分别建立一个列表变量来管理,比如说,如果发生碰撞就要破坏,即从列表中删除对应的元素;

4、建立一个死循环不断重复检测状态并刷新显示,为了控制帧率,还需要适当的延时,而不是一直运行程序。

代码讲解:

我在上传的程序中分为了两个文件:



myGame.py:主程序

myGameRole.py:定义相关的类,供myGame.py调用

resources:使用到的图片以及音频文件

myGame.py:

1、音频文件的初始化:



a、首先是对pygame进行初始化。

  1. pygame.init()

b、随后调用pygame.mixer中的方法读入音频wav文件。

  1. bullet_sound = pygame.mixer.Sound('resources/sound/bullet.wav')
  2. enemy_down_sound = pygame.mixer.Sound('resources/sound/enemy1_down.wav')
  3. game_over_sound = pygame.mixer.Sound('resources/sound/game_over.wav')

c、设置音量大小,参数范围从0~1。

  1. bullet_sound.set_volume(0.3)
  2. enemy_down_sound.set_volume(0.3)
  3. game_over_sound.set_volume(0.3)

d、游戏背景音载入后循环播放。还有pygame.mixer.music.play()中第一个参数表示播放次数,选择-1表示循环播放,其后的参数表示播放起始和结束位置,可以用它预设的参数,即全部播放。

  1. # 载入游戏音乐并循环播放
  2. pygame.mixer.music.load('resources/sound/game_music.wav')
  3. pygame.mixer.music.play(-1, 0)
  4. pygame.mixer.music.set_volume(0.25)

2、图片的初始化



以上的程序实现创建窗口并贴图上去和显示刷新。

a、创建一个窗口,SCREEN_WIDTHSCREEN_HEIGHT 指定窗口大小,后面的图片都在这个窗口内显示。

  1. SCREEN_WIDTH = 480
  2. SCREEN_HEIGHT = 800
  3. # 创建窗口
  4. screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

b、指定图片存放的路径,读出图片。

  1. # 读出背景图片
  2. background = pygame.image.load('resources/image/background.png').convert()

c、指定图片的位置,将之前读出的图片贴在指定位置上,坐标表示图片的左上角位置。程序中放在死循环内,让其不断刷新。

  1. screen.blit(background,(0, 0))

d、更新图片显示,把所有贴图后最后的结果显示。

  1. # 整个界面刷新
  2. pygame.display.update()

3、按键检测:

从下面的方法中可以得到返回值,其中包含了按键的键值。

  1. pygame.event.get()

程序中通过遍历比较得到的键值是多少,一系列的if…elif…就是这个目的。如果检测到了对应的按键,就调用类中的相关方法执行相应的操作。

myGameRole.py

1、飞机类:(截图太大了,所以直接贴上代码了)

  1. # 玩家飞机类
  2. class Player(object):
  3. def __init__(self, screen):
  4. # 储存子弹列表
  5. self.bulletList = []
  6. # 飞机图片
  7. planeImageName = 'resources/image/hero1.png'
  8. # 导入飞机图片
  9. self.image = pygame.image.load(planeImageName)
  10. # 图片大小
  11. self.image_width = 100
  12. self.image_height = 124
  13. # 设置默认坐标
  14. self.x = 180
  15. self.y = 600
  16. # 设置速度
  17. self.speed = 20
  18. self.window = screen
  19. # 设置飞机名称
  20. self.name = 'player'
  21. def getPos(self):
  22. return [self.x, self.y, self.image_width, self.image_height]
  23. def crash(self):
  24. # 图片
  25. crashImageName = 'resources/image/hero_blowup_n3.png'
  26. # 导入图片
  27. self.image = pygame.image.load(crashImageName)
  28. # 发射子弹,创建一个新的子弹对象
  29. def shoot(self):
  30. bullet = Bullet(self.window, self)
  31. self.bulletList.append(bullet)
  32. # 清除不使用的子弹列表元素
  33. def bulletClear(self):
  34. num = len(self.bulletList)
  35. for i in range(0,num):
  36. if self.bulletList[i].y <= 0:
  37. del self.bulletList[i]
  38. break
  39. # 飞机上移
  40. def moveUp(self):
  41. if self.y <= 0:
  42. self.y = 0
  43. else:
  44. self.y -= self.speed
  45. # 飞机下移
  46. def moveDown(self):
  47. if self.y >= SCREEN_HEIGHT - self.image_height:
  48. self.y = SCREEN_HEIGHT - self.image_height
  49. else:
  50. self.y += self.speed
  51. # 飞机左移
  52. def moveLeft(self):
  53. if self.x <= 0:
  54. self.x = 0
  55. else:
  56. self.x -= self.speed
  57. # 飞机右移
  58. def moveRight(self):
  59. if self.x >= SCREEN_WIDTH - self.image_width:
  60. self.x = SCREEN_WIDTH - self.image_width
  61. else:
  62. self.x += self.speed
  63. # 绘制图形
  64. def draw(self):
  65. self.window.blit(self.image, (self.x, self.y))
  66. # 按键操作处理
  67. def keyHandle(self, keyValue):
  68. if keyValue == 'left':
  69. self.moveLeft()
  70. elif keyValue == 'right':
  71. self.moveRight()
  72. elif keyValue == 'up':
  73. self.moveUp()
  74. elif keyValue == 'down':
  75. self.moveDown()
  76. elif keyValue == 'space':
  77. # bullet = Bullet(self.x, self.y)
  78. self.shoot()

一个一个方法来介绍,不重复贴太多代码了,可以在前面查看:

a、其中建立了一些初始化用的变量,比如用来保存读入的图片,初始的坐标位置等等,其中都有注释。传入的screen参数就是之前创建的游戏运行的窗口,为方便操作,建立玩家类时就传入,以后直接在内部方法中调用而不需从外部获取。

  1. def __init__(self, screen):

b、返回当前的位置坐标。

  1. def getPos(self):

c、飞机破坏,读取对应图片,并贴在窗口中响应的位置上。

  1. def crash(self):

d、实际中就是新建一个子弹类的对象,并添加到一个列表中,此后对于子弹对象通过列表管理。

  1. # 发射子弹,创建一个新的子弹对象
  2. def shoot(self):

e、检测子弹列表中的所有子弹对象是否出界,若出界直接从列表中删除。

  1. # 清除不使用的子弹列表元素
  2. def bulletClear(self):

f、飞机上下左右移动,实质就是操作该player对象的x,y坐标。

  1. # 飞机上移
  2. def moveUp(self):
  1. # 飞机下移
  2. def moveDown(self):
  1. # 飞机左移
  2. def moveLeft(self):
  1. # 飞机右移
  2. def moveRight(self):

g、绘制player对象,即调用前面所说的screen.blit方法更新(这里的screen代表前面实例化的窗口)。

  1. # 绘制图形
  2. def draw(self):

h、根据键值处理,调用前面的几个方法,诸如:上下左右移动、发射子弹等等方法。

  1. # 按键操作处理
  2. def keyHandle(self, keyValue):

2、子弹类:

  1. # 子弹类
  2. class Bullet(object):
  3. def __init__(self, screen, plane):
  4. # 子弹图片
  5. bulletImageName = 'resources/image/bullet1.png'
  6. # 导入子弹图片
  7. self.image = pygame.image.load(bulletImageName)
  8. # 图片大小
  9. self.image_width = 9
  10. self.image_height = 21
  11. # 图片位置
  12. self.x = plane.x + plane.image_width // 2 - self.image_width // 2
  13. self.y = plane.y + self.image_height
  14. # 设置速度
  15. self.speed = 12
  16. self.window = screen
  17. def getPos(self):
  18. return [self.x, self.y, self.image_width, self.image_height]
  19. def move(self):
  20. self.y -= self.speed
  21. def draw(self):
  22. self.window.blit(self.image, (self.x, self.y))

a、设置一些变量和参数,screen是窗口的实例化对象,plane表示飞机对象。

  1. def __init__(self, screen, plane):

b、获取子弹对象的坐标(图片的左上角位置坐标)

  1. def getPos(self):

c、子弹移动,实际操作它的位置坐标变化。不断在程序的循环中调用,使其创建后自动移动。

  1. def move(self):

d、绘制bullet对象,即调用前面所说的screen.blit方法更新(这里的screen代表前面实例化的窗口)。

  1. def draw(self):

3、敌机类:

  1. class Enemy(object):
  2. def __init__(self, screen, x=0, y=0):
  3. # 图片
  4. enemyImageName = 'resources/image/enemy1.png'
  5. # 导入图片
  6. self.image = pygame.image.load(enemyImageName)
  7. # 图片大小
  8. self.image_width = 51
  9. self.image_height = 39
  10. self.speed = 3
  11. # 图片位置
  12. self.x = x
  13. self.y = y
  14. self.window = screen
  15. self.direction = 'right'
  16. self.name = 'enemy'
  17. def getPos(self):
  18. return [self.x, self.y, self.image_width, self.image_height]
  19. # 检测是否出界
  20. def checkOut(self):
  21. if self.y >= SCREEN_HEIGHT - self.image_height:
  22. return True
  23. else:
  24. return False
  25. def move(self):
  26. self.y += self.speed
  27. def crash(self):
  28. # 图片
  29. crashImageName = 'resources/image/enemy1_down3.png'
  30. # 导入图片
  31. self.image = pygame.image.load(crashImageName)
  32. def draw(self):
  33. self.window.blit(self.image, (self.x, self.y))

a、screen跟前面一样,是为了后续程序调用方便而传入的;x、y表示敌机的坐标,默认都取0。

  1. def __init__(self, screen, x=0, y=0):

b、获取位置坐标

  1. def getPos(self):

c、判断是够移动出了窗口的界面范围,若出去了返回True;若否,则返回False。

  1. # 检测是否出界
  2. def checkOut(self):

d、实际是操作enemy对象的坐标变化,以使其移动。不断调用,实现自动移动。

  1. def move(self):

e、与前面一样,飞机破坏时导入图片,并刷新,表示爆炸效果。

  1. def crash(self):

f、在窗口上刷新enemy对象的图片。

  1. def draw(self):

小结:

就介绍这么多了,这里只是大概介绍了一下程序大概的思想和一些需要注意的地方。编写程序时的思路与此完全不同,随着功能的不断实现,类的方法、成员等等都是同步改变的。在我上传的程序中也有注释,可以到其中查看完整的程序。(打开链接

Pygame:编写一个小游戏 标签: pythonpygame游戏 2017-06-20 15:06 103人阅读 评论(0)的更多相关文章

  1. 数字图像处理:基于MATLAB的车牌识别项目 标签: 图像处理matlab算法 2017-06-24 09:17 98人阅读 评论(0)

    学过了数字图像处理,就进行一个综合性强的小项目来巩固一下知识吧.前阵子编写调试了一套基于MATLAB的车牌识别的项目的代码.今天又重新改进了一下代码,识别的效果好一点了,也精简了一些代码.这里没有使用 ...

  2. NYOJ-469 擅长排列的小明 II AC 分类: NYOJ 2014-01-02 22:19 159人阅读 评论(0) 收藏

    最初的第一印象是和组合数一个性质的题目.所以用了回溯法,结果,你懂的... #include<stdio.h> #include<math.h> void dfs(int n, ...

  3. save与Update的合并操作 标签: 关系映射 2017-07-13 15:11 7人阅读 评论(0) 收藏

    做save与update的方法合并操作时,判断条件是主体对象的ID是否存在. 但是当页面中,涉及到多个主体对象的关联对象时,情况变得复杂起来,特总结项目中的几点 一.页面中的VO对象属性可以分为三类: ...

  4. Jsp Cookie的创建与读取 标签: cookiejsp 2016-11-17 15:14 61人阅读 评论(0)

    Cookie.jsp <%@ page language="Java" import="java.util.*" pageEncoding="u ...

  5. js创建对象的几种方式 标签: javascript 2016-08-21 15:23 123人阅读 评论(0)

    1.传统方法,创建一个对象,然后给这个对象创建属性和方法. var person = new Object(); person.name = "张三"; person.age = ...

  6. 杭电acm刷题(3):1062,Text Reverse 标签: 杭电acm 2017-05-15 08:26 126人阅读 评论(0)

    Problem Description Ignatius likes to write words in reverse way. Given a single line of text which ...

  7. 搜狗输入法皮肤安装 分类: windows常用小技巧 2014-05-04 15:10 172人阅读 评论(0) 收藏

    第一步: 下载皮肤,皮肤是.ssf格式的. 第二步: 找到安装目录:(以我的为例) D:\软件\搜狗输入法\SogouInput\7.1.0.1652\AllSkin: 把下载的皮肤剪切(或复制)到此 ...

  8. CSS position属性 标签: css 2016-09-06 15:58 78人阅读 评论(0) 收藏

    踩了position的坑,主要是因为对position属性理解不深. 以下是w3school中对position的解释: 可能的值 值 描述 absolute 生成绝对定位的元素,相对于 static ...

  9. 代码对齐 分类: C#小技巧 2014-04-17 14:45 166人阅读 评论(0) 收藏

    开发项目时,为了是代码层次清晰.美观,常常需要调整多行,使之对齐.在网上也看到一些方法,感觉不好用,偶尔发现一个小技巧. (1)多行代码同时右移 同时选中几行,按"Tab"键,就会 ...

随机推荐

  1. Unit02: CSS 概述 、 CSS 语法 、 CSS 选择器 、 CSS声明

    Unit02: CSS 概述 . CSS 语法 . CSS 选择器 . CSS声明 my.css p { color: yellow; } demo1.html <!DOCTYPE html&g ...

  2. Python库-BeautifulSoup

    sp = BeautifulSoup.bs4.BeautifulSoup(html.text,"html.parser") 方法 1.sp.title 返回网页标题 2.sp.te ...

  3. HDU 1166 敌兵布阵 (线段树模版题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  4. 第七周作业——简单FTP

    开发简单的FTP: 1. 用户登陆 2. 上传/下载文件 3. 不同用户家目录不同 4. 查看当前目录下文件 5. 充分使用面向对象知识 1.目录结构zuoye-ftp├── chenliang #用 ...

  5. localhost不能访问127.0.0.1可以访问的原因及解决方法 被打磨的不像人样

    localhost不能访问127.0.0.1可以访问的原因及解决方法 作者:admin    时间:2013-12-16 10:58:47    浏览:16599   有时候我们在调试程序的时候,会出 ...

  6. 分析iOS Crash文件:符号化iOS Crash文件的3种方法

    转自:http://www.cocoachina.com/industry/20140514/8418.html 转自wufawei的博客 当你的应用提交到App Store或者各个渠道之后,请问你多 ...

  7. Vue源码学习(零):内部原理解析

    本篇文章是在阅读<剖析 Vue.js 内部运行机制>小册子后总结所得,想要了解详细内容,请参考原文:https://juejin.im/book/5a36661851882538e2259 ...

  8. 转载 cglib代理和java代理

    Java动态代理之JDK实现和CGlib实现(简单易懂)   转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html 一:代理模式(静态代理) ...

  9. std::thread函数传参拷贝次数

    c++11的thread库大大方便了开发,但是目前网络上少有深入分析的资料和使用例程.特别是在线程函数传参这一块,一般止步于使用std::ref传引用. 这次写服务器遇到个BUG,线程函数参数是智能指 ...

  10. 爬虫中urllib库

    一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib. ...