Pygame游戏编程入门笔记

2024-09-05 12:48

本文主要是介绍Pygame游戏编程入门笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1. Python游戏编程入门
  • 2. 建立开发环境
  • 3. 简单示例
  • 4. 绘制不同形状
  • 5. 事件监听举例
  • 6. 用pygame打印文本
  • 7. 键盘事件
  • 8. 鼠标事件
  • 9. 轮询键盘
  • 10. 轮询鼠标
  • 11. 角度与弧度
  • 12. 遍历圆周
  • 13. 矢量图与位图
  • 14. 获取已有的surface
  • 15. 加载位图
  • 16. 绘制位图
  • 17. 绘制游戏背景图
  • 18. 缩放图像
  • 19. 旋转
  • 20. 用精灵实现动画
    • 20.1. 加载精灵序列图
    • 20.2. 更改帧
    • 20.3. 绘制帧
    • 20.4. 精灵组
    • 20.5. 一个精灵类
    • 20.6. 精灵冲突
    • 20.7. 精灵与精灵组的矩形冲突
    • 20.8. 两个精灵组之间的矩形冲突
  • 21. 中文字体
  • 22. 全屏模式
  • 23. 裁剪屏幕
  • 24. 让pygame完全控制鼠标
  • 25. 声音
  • 26. Sound对象
  • 27. 游戏背景声音
  • 28. 打包发布到Windows平台

1 Python游戏编程入门

买的《Python游戏编程入门》书籍到了,准备记录点学习Pygame开发2D游戏的笔记。

2 建立开发环境

由于书籍例子使用python3.2+pygame1.9,因此保持一致。其实,如果使用python2.7的话,应该更多软件包可以使用。

我使用的Mac,而pygame编译好的安装包只有windows版本,需要自己源码安装.

建立虚拟python环境:

$ python -m venv venv
$ source venv/bin/active

下载源码文件后,安装:

$ brew install sdl sdl_image sdl_mixer sdl_ttf portmidi
$ pip install hg+http://bitbucket.org/pygame/pygame

经过测试,发现使用python2.7完成可以运行所有的例子,因此使用python2.7,省去很多麻烦.

$ virtualenv envpygame
$ source envpygame/bin/activate
$ python --version
Python 2.7.6$ pip install hg+http://bitbucket.org/pygame/pygame$ pip listpip (1.5.6)
pygame (1.9.2a0)
setuptools (3.6)
wsgiref (0.1.2)

3 简单示例

import pygame
from pygame.locals import *
import sys# 初始化Pygame资源
pygame.init()                      screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("Hello Pygame")
myfont = pygame.font.Font(None,60)white = 255,255,255
blue = 0,0,255textImage = myfont.render("Hello Pygame",True,white)screen.fill(blue)
screen.blit(textImage,(100,100))   # 绘制图形pygame.display.update()while True:for event in pygame.event.get():if event.type in (QUIT,KEYDOWN):sys.exit()screen.fill(blue)screen.blit(textImage,(100,100))pygame.display.update()

4 绘制不同形状

使用 pygame.draw 来绘制图形,如:

  • pygame.draw.circle()
  • pygame.draw.rect()
  • pygame.draw.line()
  • pygame.draw.arc()

画弧线举例:

start_angle = math.radians(0)
end_angle = math.radians(90)
pygame.draw.arc(screen, color, position, start_angle, end_angle, width)

5 事件监听举例

while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()elif event.type == KEYUP:if event.key == pygame.K_ESCAPE:sys.exit()elif event.key == pygame.K_1:piece1 = Trueelif event.key == pygame.K_2:piece2 = Trueelif event.key == pygame.K_3:piece3 = Trueelif event.key == pygame.K_4:piece4 = True#.....

在监听事件的时候一般只设置变量,然后再根据变量进行后续操作。

6 用pygame打印文本

以图片的形式绘制文本:

myfont = pygame.font.Font("Arial",30)
image = myfont.render(text,True,(255,255,255))
screen.blit(image,(100,100))

7 键盘事件

一般按键事件分为 KEYDOWNKEYUP ,如果要在按键持续按住的情况下持续产生事件,需要设置:

pygame.key.set_repeat(10)  # 表示每个10毫秒一个事件

8 鼠标事件

Pygame支持的鼠标事件包括: MOUSEMOTIONMOUSEBUTTONUPMOUSEBUTTONDOWN.

for event in pygame.event.get():if event.type == MOUSEMOTION:mous_x,mouse_y = event.posmove_x,move_y = event.relelif event.type == MOUSEBUTTONDOWN:mouse_down = event.buttonmouse_down_x,mouse_down_y = event.poselif event.type == MOUSEBUTTONUP:mouse_up = event.buttonmouse_up_x,mouse_up_y = event.pos

9 轮询键盘

通过轮询键盘接口,可以一次性获取按键列表,不需要遍历事件系统:

keys = pygame.keys.get_pressed()
if keys[K_ESCAPE]:sys.exit()

10 轮询鼠标

pos_x,pos_y = pygame.mouse.get_pos()
rel_x,rel_y = pygame.mouse.get_rel()
button1,button2,button3 = pygame.mouse.get_pressed()

11 角度与弧度

正弦函数、余弦函数可以以任意的半径大小来模拟一个圆。

一个完整的圆的弧度表示为 2*PI ,等于360°

1弧度对应的角度值:

360 / 6.28 = 57.3248

1角度对应的弧度值:

6.28 / 360 = 0.0174

使用这些数字在角度与弧度之间转换,其精度在大多数游戏里面可以接受。

在 math 模块封装了转换函数:

  • math.degrees(): 转换为角度
  • math.radians(): 转换为弧度
>>> import math
>>> math.degrees(0.5)
28.64788975654116
>>> math.radians(30)
0.5235987755982988
>>> math.radians(28.64788975654116)
0.5

12 遍历圆周

计算绕着一个圆的圆周的任何点的X坐标,使用余弦函数。

>>> math.cos(math.radians(90))
6.123233995736766e-17
>>> '{:.2f}'.format(math.cos(math.radians(90)))
'0.00'
>>> '{:.2f}'.format(math.cos(math.radians(45)))
'0.71'

计算圆周上任何点Y坐标,使用正弦函数.

>>> '{:.2f}'.format(math.sin(math.radians(45)))
'0.71'
>>> '{:.2f}'.format(math.sin(math.radians(90)))
'1.00'
  • X = math.cos(math.radians(angle)) * radius
  • Y = math.sin(math.radians(angle)) * radius

13 矢量图与位图

要处理基于线条绘制的矢量图形,也要处理位图图形.

在Pygame中,一个位图叫 Surface,比如 pygame.display.set_mode() 返回的就是 Surface对象.

14 获取已有的surface

screen = pygame.display.get_surface()

15 加载位图

通过 pygame.image.load() 函数加载位图文件类型:

  • JPG
  • PNG
  • GIF
  • BMP
  • PCX
  • TGA
  • TIF
  • LBM,PBM,PGM,PPM,XPM
space = pygame.image.load("space.png").convert()
space = pygame.image.load("space.png").convert_alpha()
width,height = space.get_size() 
width = space.get_width() 
height = space.get_height()

16 绘制位图

Surface对象函数 blit() 用于绘制位图:

screen.blit(space, (0,0))

17 绘制游戏背景图

bg = pygame.image.load("space.png").convert_alpha()
screen.blit(bg, (0,0))

18 缩放图像

pygame.sprite.Sprite 善于绘制和操作用于游戏的图像,而 pygame.transform 也可以缩放、翻转图像。

ship = pygame.image.load("freelance.png").convert_alpha()
width,height = ship.get_size() 
ship = pygame.transform.scale(ship, (widht//2,height//2))  # 缩放 
ship = pygame.transform.smoothscale(ship, (width//2,height//2) # 平滑缩放

19 旋转

提供图像与旋转角度:

scratch_ship = pygame.transform.rotate(ship, rangled)

计算旋转角度需要使用到正切函数,记住上一个位置与当前位置,计算出正切后再加180°:

delta_x = (pos.x - old_pos.x)
delta_y = (pos.y - old_pos.y) 
rangle = math.atan2(delta_y,delta_x) 
rangled = -math.degrees(rangle) % 360

20 用精灵实现动画

pygame.sprite.Sprite 并不是一个完整的解决方案,只是一个有限的类,包含一副图片(image)和一个位置(rect)属性,需要自己继续并进行扩展。

20.1 加载精灵序列图

加载的时候必须告诉精灵类一帧有多大,需要宽度、高度,同时还需要知道精灵序列图有多少列:

def load(self, filename, width, height, columns):self.master_image = pygame.image.load(filename).convert_alpha()self.frame_width = widthself.frame_height = heightself.rect = 0,0,width,heightself.columns = columns#try to auto-calculate total framesrect = self.master_image.get_rect()self.last_frame = (rect.width // width) * (rect.height // height) - 1

对于加载的图像,有两个函数很重要:

  • image.get_rect(): 获取图像的矩形范围
  • image.subsurface(rect): 获取图像的区域

20.2 更改帧

帧速率:

framerate = pygame.time.Clock()
framerate.tick(30)

运行速度:

ticks = pygame.time.get_ticks()
pygame.sprite.Sprite.update(ticks)  # 需要自己重新此函数

20.3 绘制帧

def update(self, current_time, rate=30):#update animation frame numberif current_time > self.last_time + rate:self.frame += 1if self.frame > self.last_frame:self.frame = self.first_frameself.last_time = current_time#build current frame only if it changedif self.frame != self.old_frame:frame_x = (self.frame % self.columns) * self.frame_widthframe_y = (self.frame // self.columns) * self.frame_heightrect = ( frame_x, frame_y, self.frame_width, self.frame_height )self.image = self.master_image.subsurface(rect)self.old_frame = self.frame
  • 获取精灵序列图的大小
  • 获取每一帧,即每一个小图的大小
  • 根据帧数,计算出精灵序列图的子图大小
  • 绘制子图作为帧图像

20.4 精灵组

精灵组是一个简单的实体容器,调用精灵类的update()方法,然后,绘制容器中的所有精灵。

精灵组刷新频率:

group = pygame.sprite.Group()
group.add(sprite)
framerate = pygame.time.Clock()
framerate.tick(30)
ticks = pygame.time.get_ticks()
group.update(ticks)
group.draw(screen)

20.5 一个精灵类

class MySprite(pygame.sprite.Sprite):def __init__(self, target):pygame.sprite.Sprite.__init__(self) #extend the base Sprite classself.master_image = Noneself.frame = 0self.old_frame = -1self.frame_width = 1self.frame_height = 1self.first_frame = 0self.last_frame = 0self.columns = 1self.last_time = 0#X propertydef _getx(self): return self.rect.xdef _setx(self,value): self.rect.x = valueX = property(_getx,_setx)#Y propertydef _gety(self): return self.rect.ydef _sety(self,value): self.rect.y = valueY = property(_gety,_sety)#position propertydef _getpos(self): return self.rect.topleftdef _setpos(self,pos): self.rect.topleft = posposition = property(_getpos,_setpos)def load(self, filename, width, height, columns):self.master_image = pygame.image.load(filename).convert_alpha()self.frame_width = widthself.frame_height = heightself.rect = Rect(0,0,width,height)self.columns = columns#try to auto-calculate total framesrect = self.master_image.get_rect()self.last_frame = (rect.width // width) * (rect.height // height) - 1def update(self, current_time, rate=30):#update animation frame numberif current_time > self.last_time + rate:self.frame += 1if self.frame > self.last_frame:self.frame = self.first_frameself.last_time = current_time#build current frame only if it changedif self.frame != self.old_frame:frame_x = (self.frame % self.columns) * self.frame_widthframe_y = (self.frame // self.columns) * self.frame_heightrect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)self.image = self.master_image.subsurface(rect)self.old_frame = self.framedef __str__(self):return str(self.frame) + "," + str(self.first_frame) + \"," + str(self.last_frame) + "," + str(self.frame_width) + \"," + str(self.frame_height) + "," + str(self.columns) + \"," + str(self.rect)

20.6 精灵冲突

边界矩形冲突检测是比较两个精灵的矩形看它们是否重叠:

pygame.sprite.collide_rect(sprite1,sprite2)

边界圆形冲突检测是比较两个精灵的半径:

pygame.sprite.collide_circle(first, second)
pygame.sprite.collide_circle_radio(radio)(first,second)

像素精确遮罩冲突检测:

pygame.sprite.collide_mask(first,second)

除非是一个移动缓慢的游戏并且高度精确性又很重要,否则不建议使用这个,耗资源.

20.7 精灵与精灵组的矩形冲突

collide_list = pygame.sprite.spritecollide(arrow,flock_of_birds,False)
  • 第一个参数是单个的精灵
  • 第二个参数是精灵组
  • 第三个参数是布尔值,传递True将导致精灵组中的所有冲突的精灵被删除掉
  • 精灵与精灵组中挨个进行冲突检测,返回一个冲突精灵的列表
pygame.sprite.spritecollideany(arrow, flock_of_birds)

重要精灵与精灵组中任何一个精灵有冲突,则返回True.

20.8 两个精灵组之间的矩形冲突

不要轻易使用,耗费资源:

hit_list = pygame.sprite.groupcollide(bombs, cities, True, False)
  • 第一个参数是精灵组
  • 第二个参数是另一个精灵组
  • 第三个参数,是否删除有冲突的精灵,在第一个精灵组中
  • 第四个参数,是否删除有冲突的精灵,在第二个精灵组中

21 中文字体

要显示中文,需要以下几点:

  • 对程序编码使用 utf-8 ,添加 # coding: utf-8
  • 将字体文件找到,最好把字体文件复制过来,比如Mac上使用 fc-list 找到字体 /Library/Fonts/Microsoft/Kaiti.ttf ,楷体
  • 创建字体对象:
font1 = pygame.font.Font('resources/fonts/Kaiti.ttf',18)
text = font1.render(u"夏目友人帐", True, (255,0,0))  # 注意使用Unicode

22 全屏模式

一般设置大小是:

screen=pygame.display.set_mode((600, 400))

如果要全屏:

screen=pygame.display.set_mode((600, 400),FULLSCREEN,32)

各个标志位说明:

  • FULLSCREEN: 创建一个全屏窗口
  • DOUBLEBUF: 创建一个“双缓冲”窗口,建议在HWSURFACE或者OPENGL时使用
  • HWSURFACE: 创建一个硬件加速的窗口,必须和FULLSCREEN同时使用
  • OPENGL: 创建一个OPENGL渲染的窗口
  • RESIZABLE: 创建一个可以改变大小的窗口
  • NOFRAME: 创建一个没有边框的窗口

当窗口大小改变时候,可以相应修改屏幕大小:

if event.type == VIDEORESIZE:SCREEN_SIZE = event.sizescreen = pygame.display.set_mode(SCREEN_SIZE, RESIZABLE, 32)

如果使用 双缓冲 ,则刷新使用 pygame.display.flip()

23 裁剪屏幕

screen.set_clip(0, 400, 200, 600)
draw_map()    #在左下角画地图 
screen.set_clip(0, 0, 800, 60) 
draw_panel()  #在上方画菜单面板

24 让pygame完全控制鼠标

pygame.mouse.set_visible(False)
pygame.event.set_grab(True)

25 声音

通过 pygame.mixer.init 来初始化声音.

在Pygame上只支持 未压缩的WAV 和 OGG 音频文件, 将WAV用于较短的音频文件,而OGG用于较长的音频文件。

26 Sound对象

sound = pygame.mixer.Sound("1.wav")
  • fadeout: 淡出声音,可接受一个数字(毫秒)作为淡出时间
  • get_length: 获得声音文件长度,以秒计
  • get_num_channels: 声音要播放多少次
  • get_volume: 获取音量(0.0 ~ 1.0)
  • play: 开始播放,返回一个Channel对象,失败则返回None
  • set_volume: 设置音量
  • stop: 立刻停止播放

对于要播放的Sound:

channel = pygame.mixer.find_channel(True)   # 返回可用最低优先级的频道
channel.play(sound_clip)

27 游戏背景声音

pygame.mixer.music.load("resources/audio/吉森信 春を知らせるもの 続 夏目友人帐のテ マ.ogg")
pygame.mixer.music.play(-1, 0.0) 
pygame.mixer.music.set_volume(0.25)

如果要切换背景音乐:

# part 1
pygame.mixer.music.load("xxx") 
pygame.mixer.music.play() 
# part 2 
pygame.mixer.music.fadeout(1000) 
pygame.mixer.music.load("xxx") 
pygame.mixer.music.play()

28 打包发布到Windows平台

http://eyehere.net/2011/python-pygame-novice-professional-py2exe/

这篇关于Pygame游戏编程入门笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139004

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就