本文基于win7(64) + py3.5(64)环境。

本文是这里的一篇学习笔记。加入了自己的理解。

本文最终目的是实现一个飞机躲避导弹的游戏。

1、核心概念

pygame 的核心概念有:

  • Surface 对象(一个容器,一个载体,可以是空白的矩形区域,亦可是图片)
  • Surface 对象的矩形区域(用 Surface 实例的get_rect()方法获得)
  • 屏幕对象的blit()方法用于放置 Surface 对象
  • display 模块的flip()方法用于重绘游戏界面
  • 窗口主循环
import pygame, sys
from pygame.locals import * # 全局常量 # 初始化
pygame.init() # 屏幕对象
screen = pygame.display.set_mode((400,270)) # 尺寸 # Surface对象
surf = pygame.Surface((50,50)) # 长、宽
surf.fill((255,255,255)) # 颜色 # Surface对象的矩形区域
rect = surf.get_rect() # 窗口主循环
while True:
# 遍历事件队列
for event in pygame.event.get():
if event.type == QUIT: # 点击右上角的'X',终止主循环
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE: # 按下'ESC'键,终止主循环
pygame.quit()
sys.exit() # 放置Surface对象
screen.blit(surf, ((400-50)//2, (270-50)//2)) # 窗口正中
#screen.blit(surf, rect) # surf的左上角 # 重绘界面
pygame.display.flip()

效果图

2、引入精灵

上面的代码很能体现pygame的核心概念,但不利于规模比较大的游戏开发。

为此,就需要继承 Sprite 类,并且设置属性surf为Surface对象。同时设置rect属性。

调用屏幕对象的blit方法时,以精灵实例的surf属性和rect属性为参数。

import pygame, sys
from pygame.locals import *
import random '''玩家随着方向键运动''' # 玩家
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.surf = pygame.Surface((75,25))
self.surf.fill((255,255,255))
self.rect = self.surf.get_rect() def update(self, key):
# 随着方向键运动
if key[K_UP]:
self.rect.move_ip(0,-5)
if key[K_DOWN]:
self.rect.move_ip(0,5)
if key[K_LEFT]:
self.rect.move_ip(-5,0)
if key[K_RIGHT]:
self.rect.move_ip(5,0) # 限定player在屏幕中
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.right > 800:
self.rect.right = 800
if self.rect.top <= 0:
self.rect.top = 0
elif self.rect.bottom >= 600:
self.rect.bottom = 600 # 初始化
pygame.init() # 屏幕对象
screen = pygame.display.set_mode((800,600)) # 尺寸 # 玩家精灵对象
player = Player() # 窗口主循环
while True:
# 遍历事件队列
for event in pygame.event.get():
if event.type == QUIT: # 点击右上角的'X',终止主循环
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE: # 按下'ESC'键,终止主循环
pygame.quit()
sys.exit() # 更新屏幕
screen.fill((0,0,0)) # 获得按键
key = pygame.key.get_pressed() # 更新玩家
player.update(key) # 放置玩家
screen.blit(player.surf, player.rect) # 更新界面
pygame.display.flip()

效果图

3、引入敌人

由于敌人很多,最好的方式是用Group来管理那么多的精灵。

import pygame, sys
from pygame.locals import *
import random # 玩家
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.surf = pygame.Surface((75,25))
self.surf.fill((255,255,255))
self.rect = self.surf.get_rect() def update(self, key):
if key[K_UP]:
self.rect.move_ip(0,-5)
if key[K_DOWN]:
self.rect.move_ip(0,5)
if key[K_LEFT]:
self.rect.move_ip(-5,0)
if key[K_RIGHT]:
self.rect.move_ip(5,0) # 限定player在屏幕中
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.right > 800:
self.rect.right = 800
if self.rect.top <= 0:
self.rect.top = 0
elif self.rect.bottom >= 600:
self.rect.bottom = 600 # 敌人
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.surf = pygame.Surface((20, 10))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect(center=(820, random.randint(0, 600)))
self.speed = random.randint(5, 20) def update(self):
self.rect.move_ip(-self.speed, 0) # 从右向左
if self.rect.right < 0:
self.kill() # Sprite 的内建方法 # 初始化
pygame.init() # 屏幕对象
screen = pygame.display.set_mode((800,600)) # 尺寸 # 自定义事件
ADDENEMY = pygame.USEREVENT + 1 # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都要比 USEREVENT 大
pygame.time.set_timer(ADDENEMY, 250) # 每隔 250 毫秒(四分之一秒) 触发 # 玩家
player = Player() # 两个精灵组
enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player) # 窗口主循环
while True:
# 遍历事件队列
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == ADDENEMY: # 自定义事件
new_enemy = Enemy()
enemies.add(new_enemy)
all_sprites.add(new_enemy) # 更新屏幕
screen.fill((0,0,0)) # 更新玩家
key = pygame.key.get_pressed()
player.update(key)
screen.blit(player.surf, player.rect) # 更新敌人
for enemy in enemies:
enemy.update()
screen.blit(enemy.surf, enemy.rect) # 碰撞检测(灵魂所在)
if pygame.sprite.spritecollideany(player, enemies):
player.kill()
print('发生碰撞!') # 重绘界面
pygame.display.flip()

效果图

4、使用图片

上面的例子是丑陋的黑白界面,需要进行美化。好的方式是使用图片来代替。可以去网上找素材,也可以自己画。

为了让游戏更好看,增添了云朵精灵。

注意:下面的surf属性用image来代替了。

为方便朋友们测试,下面给出代码中用到的三张图片素材:





import pygame, sys
from pygame.locals import *
import random '''飞机躲避导弹''' # 玩家
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load('jet.png').convert() # load函数,返回一个 Surface 对象
self.image.set_colorkey((255,255,255), RLEACCEL)
self.rect = self.image.get_rect() def update(self, key):
if key[K_UP]:
self.rect.move_ip(0,-5)
if key[K_DOWN]:
self.rect.move_ip(0,5)
if key[K_LEFT]:
self.rect.move_ip(-5,0)
if key[K_RIGHT]:
self.rect.move_ip(5,0) # 限定player在屏幕中
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.right > 800:
self.rect.right = 800
if self.rect.top <= 0:
self.rect.top = 0
elif self.rect.bottom >= 600:
self.rect.bottom = 600 # 敌人
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load('missile.png').convert()
self.image.set_colorkey((255, 255, 255), RLEACCEL)
self.rect = self.image.get_rect(center=(820, random.randint(0, 600)))
self.speed = random.randint(5, 20) def update(self):
self.rect.move_ip(-self.speed, 0) # 从右向左
if self.rect.right < 0:
self.kill() # Sprite 的内建方法 # 白云
class Cloud(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load('cloud.png').convert()
self.image.set_colorkey((0,0,0),RLEACCEL)
self.rect = self.image.get_rect(
center = (random.randint(820,900),random.randint(0,600))
) def update(self):
self.rect.move_ip(-5,0)
if self.rect.right < 0:
self.kill() # 游戏初始化
pygame.init() # 屏幕对象
screen = pygame.display.set_mode((800,600)) # 尺寸 # 背景Surface
background = pygame.Surface(screen.get_size())
background.fill((135, 206, 250)) # 浅蓝色 # 两个自定义事件
ADDENEMY = pygame.USEREVENT + 1 # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都必须比 USEREVENT 大)
pygame.time.set_timer(ADDENEMY, 250) # 每隔 250 毫秒(四分之一秒) 触发
ADDCLOUD = pygame.USEREVENT + 2
pygame.time.set_timer(ADDCLOUD, 1000) # 玩家精灵对象
player = Player() # 三个精灵组
enemies = pygame.sprite.Group()
clouds = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player) # 窗口主循环
while True:
# 遍历事件队列
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == ADDENEMY: # 自定义事件
new_enemy = Enemy()
enemies.add(new_enemy)
all_sprites.add(new_enemy)
elif event.type == ADDCLOUD: # 自定义事件
new_cloud = Cloud()
clouds.add(new_cloud)
all_sprites.add(new_cloud) # 背景
screen.blit(background, (0, 0)) # 获取按键
key = pygame.key.get_pressed() # 更新精灵(组)
player.update(key)
enemies.update()
clouds.update() # 放置精灵
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect) # 碰撞检测(灵魂所在)
if pygame.sprite.spritecollideany(player, enemies):
player.kill()
#print('发生碰撞!') # 重绘界面
pygame.display.flip()

效果图

全都是类

所有的东西都放到类里面!难道这就是传说中的面向对象编程???

import pygame, sys
from pygame.locals import *
import random '''飞机躲避导弹''' # 根据概率随机选取
def choice(seq, prob):
p = random.random()
for i in range(len(seq)):
if sum(prob[:i]) < p < sum(prob[:i+1]):
return seq[i] # 玩家
class PlayerSprite(pygame.sprite.Sprite):
speed = 5 def __init__(self):
super().__init__()
self.image = pygame.image.load('jet.png').convert() # load函数,返回一个 Surface 对象
self.image.set_colorkey((255,255,255), RLEACCEL)
self.rect = self.image.get_rect() def update(self, key):
if key[K_UP]:
self.rect.move_ip(0, -self.speed)
if key[K_DOWN]:
self.rect.move_ip(0, self.speed)
if key[K_LEFT]:
self.rect.move_ip(-self.speed, 0)
if key[K_RIGHT]:
self.rect.move_ip(self.speed, 0) # 限定player在屏幕中
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.right > 800:
self.rect.right = 800
if self.rect.top <= 0:
self.rect.top = 0
elif self.rect.bottom >= 600:
self.rect.bottom = 600 # 敌人
class EnemySprite(pygame.sprite.Sprite):
speed = choice([1,3,5], [0.5, 0.4, 0.1]) def __init__(self):
super().__init__()
self.image = pygame.image.load('missile.png').convert()
self.image.set_colorkey((255, 255, 255), RLEACCEL)
self.rect = self.image.get_rect(center=(820, random.randint(0, 600)))
#self.speed = random.randint(5, 20) def update(self):
self.rect.move_ip(-self.speed, 0) # 从右向左
if self.rect.right < 0:
self.kill() # Sprite 的内建方法 # 白云
class CloudSprite(pygame.sprite.Sprite):
speed = choice([1,2], [0.8, 0.2]) def __init__(self):
super().__init__()
self.image = pygame.image.load('cloud.png').convert()
self.image.set_colorkey((0,0,0),RLEACCEL)
self.rect = self.image.get_rect(
center = (random.randint(820,900),random.randint(0,600))
) def update(self):
self.rect.move_ip(-self.speed,0)
if self.rect.right < 0:
self.kill() # 背景
class BackgroundSprite(pygame.sprite.Sprite): def __init__(self, size):
super().__init__()
self.image = pygame.Surface(size) # 实际上是surf,为了统一写成image
self.image.fill((135, 206, 250)) # 浅蓝色
self.rect = pygame.Rect(0, 0, *size) def update(self):
pass class Game(): def __init__(self):
# 游戏初始化
pygame.init() # 屏幕大小及屏幕对象
self.size = self.width, self.height = 800, 600
self.screen = pygame.display.set_mode(self.size) pygame.display.set_caption("Pygame 2D RPG !") # 两个自定义事件
self.ADDENEMY = pygame.USEREVENT + 1 # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都必须比 USEREVENT 大)
pygame.time.set_timer(self.ADDENEMY, 250) # 每隔 250 毫秒(四分之一秒) 触发
self.ADDCLOUD = pygame.USEREVENT + 2
pygame.time.set_timer(self.ADDCLOUD, 1000) # 两个精灵对象
self.background = BackgroundSprite(self.size)
self.player = PlayerSprite() # 三个精灵组
self.enemies = pygame.sprite.Group()
self.clouds = pygame.sprite.Group()
self.all_sprites = pygame.sprite.Group() self.all_sprites.add(self.player) def run(self):
# 窗口主循环
while True:
# 遍历事件队列
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == self.ADDENEMY: # 自定义事件
new_enemy = EnemySprite()
self.enemies.add(new_enemy)
self.all_sprites.add(new_enemy)
elif event.type == self.ADDCLOUD: # 自定义事件
new_cloud = CloudSprite()
self.clouds.add(new_cloud)
self.all_sprites.add(new_cloud) # 背景
self.screen.blit(self.background.image, self.background.rect) # 获取按键
key = pygame.key.get_pressed() # 更新精灵(组)
self.player.update(key)
self.enemies.update()
self.clouds.update() # 放置精灵
for sprite in self.all_sprites:
self.screen.blit(sprite.image, sprite.rect) # 碰撞检测(灵魂所在)
if pygame.sprite.spritecollideany(self.player, self.enemies):
self.player.kill()
print('发生碰撞!') # 重绘界面
pygame.display.flip() if __name__ == '__main__':
Game().run()

pygame 入门实例的更多相关文章

  1. pygame入门

    pygame入门 说明 在学习pygame时,主要参考了目光博客的教程.目光博客 原教程是2011年写的,年代比较久远了,使用Python2.我学习时使用python3将代码重新实现了一遍,同时补充了 ...

  2. React 入门实例教程(转载)

    本人转载自: React 入门实例教程

  3. struts入门实例

    入门实例 1  .下载struts-2.3.16.3-all  .不摆了.看哈就会下载了. 2  . 解压  后 找到 apps 文件夹. 3.    打开后将 struts2-blank.war   ...

  4. Vue.js2.0从入门到放弃---入门实例

    最近,vue.js越来越火.在这样的大浪潮下,我也开始进入vue的学习行列中,在网上也搜了很多教程,按着教程来做,也总会出现这样那样的问题(坑啊,由于网上那些教程都是Vue.js 1.x版本的,现在用 ...

  5. wxPython中文教程入门实例

    这篇文章主要为大家分享下python编程中有关wxPython的中文教程,分享一些wxPython入门实例,有需要的朋友参考下     wxPython中文教程入门实例 wx.Window 是一个基类 ...

  6. Omnet++ 4.0 入门实例教程

    http://blog.sina.com.cn/s/blog_8a2bb17d01018npf.html 在网上找到的一个讲解omnet++的实例, 是4.0下面实现的. 我在4.2上试了试,可以用. ...

  7. Spring中IoC的入门实例

    Spring中IoC的入门实例 Spring的模块化是很强的,各个功能模块都是独立的,我们可以选择的使用.这一章先从Spring的IoC开始.所谓IoC就是一个用XML来定义生成对象的模式,我们看看如 ...

  8. Node.js入门实例程序

    在使用Node.js创建实际“Hello, World!”应用程序之前,让我们看看Node.js的应用程序的部分.Node.js应用程序由以下三个重要组成部分: 导入需要模块: 我们使用require ...

  9. Java AIO 入门实例(转)

    Java7 AIO入门实例,首先是服务端实现: 服务端代码 SimpleServer: public class SimpleServer { public SimpleServer(int port ...

随机推荐

  1. 【转】C++11的enum class & enum struct和enum

    转自:https://blog.csdn.net/sanoseiichirou/article/details/50180533 C++标准文档——n2347(学习笔记) 链接:http://www. ...

  2. JavaScript动画:offset和匀速动画详解(含轮播图的实现)

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. offset简介 我们知道,三大家族包括:offset/scroll/c ...

  3. Oracle中,时间的相关操作方法

    无论是DATE还是timestamp都可以进行加减操作.可以对当前日期加年.月.日.时.分.秒,操作不同的时间类型,有三种方法: 1 使用内置函数numtodsinterval增加小时,分钟和秒2 加 ...

  4. Android高级_第三方框架Xutils

    xutils的功能主要包括有四个部分:(1)布局视图关联:(2)图片下载与缓存:(3)网络请求:(4)数据库: 1. 使用xutils进行视图注入: (1)在控件声明上方添加@ViewInject() ...

  5. 团队作业——Beta冲刺4

    团队作业--Beta冲刺 冲刺任务安排 杨光海天 今日任务:在同队成员帮助下,完成了浏览详情界面的跳转,以及图片的嵌入 明日任务:继续完成浏览详情界面 吴松青 今日任务:研究图片详情界面后端函数,遇到 ...

  6. 深入了解MyBatis二级缓存

    深入了解MyBatis二级缓存 标签: mybatis二级缓存 2015-03-30 08:57 41446人阅读 评论(13) 收藏 举报  分类: Mybatis(51)  版权声明:版权归博主所 ...

  7. 关于flex的crossdomain.xml文件存放目录

    最近在项目中遇到flex跨域访问的安全沙箱问题,查资料了解到需要在服务端加上crossdomain.xml文件,即: <?xml version="1.0" encoding ...

  8. BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  9. Android:你要的WebView与 JS 交互方式 都在这里了

    前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与 ...

  10. Scala学习之路 (六)Scala的类、对象、继承、特质

    一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...