本文基于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. MySQL——通过EXPLAIN分析SQL的执行计划

    在MySQL中,我们可以通过EXPLAIN命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序. 下面分别对EXPLAIN命令结果的每一列进行说明: ...

  2. Paxos协议笔记

    对Paxos协议的介绍,可以通过Leslie Lamport的<Paxos Made Simple>展开学习和了解.Paxos算法在允许失败的分布式系统环境下,实现系统一致性.失败的情况有 ...

  3. 在 Azure 中的 Windows 虚拟机上使用 SSL 证书保护 IIS Web 服务器

    若要保护 Web 服务器,可以使用安全套接字层 (SSL) 证书来加密 Web 流量. 这些 SSL 证书可存储在 Azure Key Vault 中,并可安全部署到 Azure 中的 Windows ...

  4. 网络基础之IP地址和子网掩码

    IP地址 IP是英文Internet Protocol的缩写,意思是"网络之间互连的协议",也就是为计算机网络相互连接进行通信而设计的协议.在因特网中,它是能使连接到网上的所有计算 ...

  5. 熟悉LINUX系统

    常用的Shell命令 当用户登录到字符界面系统或使用终端模拟窗口时,就是在和称为shell的命令解释程序进行通信.当用户在键盘上输入一条命令时,shell程序将对命令进行解释并完成相应的动作.这种动作 ...

  6. windows系统利用任务管理器-资源监视器了解程序的磁盘读写量

    场景摘要:   1.刚部署上线一个新功能,增加了日志输出模块 2.本身服务器资源已经紧张了,在增加日志输出,就想了解磁盘读写量 3.从中突然发现oracle的磁盘读写量比较大 4.在展开明细发现是or ...

  7. 【Ansible 文档】【译文】模式

    Patterns 模式 Ansible中的模式是指我们如何决定那些机器执行管理操作.这里意味着与那些主机通信,但是对于playbook,它是指哪些主机应用特定的配置或执行特定程序. 我们将重温一下In ...

  8. 基于汇编的 C/C++ 协程 - 背景知识

    近几年来,协程在 C/C++ 服务器中的解决方案开始涌现.本文主要阐述以汇编实现上下文切换的协程方案,并且说明其在异步开发模式中的应用. 本文地址:https://segmentfault.com/a ...

  9. VS2013自带报表+打印功能

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010773667/article/details/27540389 经过了VB版机房收费系统的学习 ...

  10. Android常见UI组件之ListView(一)

    使用ListView显示一个长的项列表 1.新建一个名为"BasicView5"的Android项目. 2.改动BasicView5.java文件.改动后的程序例如以下: pack ...