zoukankan      html  css  js  c++  java
  • Pygame相关

    pygame是主要构筑在SDL库基础上的一组Python模块的集合,它使我们能够用Python语言来创建功能完整的游戏和多媒体程序。pygame是高度括平台可移植的,在任何SDL支持的平台上都可以运行(几乎可以在任何平台和操作系统上运行)。

    注:SDL(Simple DirectMedia Layer)是一个跨平台的多媒体库,可以用来访问底层的音频、键盘、鼠标、摇杆、3D硬件(通过OpenGL)以及2D视频缓冲。它被用在MPEG播放软件、模拟器和很多流行的游戏中,包括获得大奖的Linux版的”Civilization: Call To Power”。

    安装Pygame

    https://www.pygame.org/wiki/GettingStarted

    1
    2
    3
    4
    pip install pygame
    #检验是否安装成功
    python3 -m pygame.examples.aliens

    导入

    1
    2
    3
    import pygame
    # 引入 pygame 中的所有常量
    from pygame.locals import *

    模块

    模块 说明
    cdrom 访问光驱
    cursors 加载光标图像,包含标准光标
    display 控制显示窗口或屏幕
    draw 在Surface上绘制简单的图形
    event 管理事件和事件队列
    font 创建并呈现TrueType字体
    image 保存并加载图像
    joystick 管理游戏手柄设备
    key 管理键盘
    pygame.mixer 音效
    mouse 管理鼠标
    pygame.movie 播放视频
    pygame.music 播放音频
    pygame.rect 管理矩形区域
    pygame.sprite 操作移动图像
    sndarray 用numpy操纵声音
    surfarray 用numpy处理图像
    time 控制时间
    transform 缩放,旋转和翻转图像

    初始化和退出

    1
    2
    3
    4
    5
    # 导入并初始化所有 pygame 模块,使用其他模块之前,必须先调用 init 方法
    pygame.init()
    # 卸载所有 pygame 模块,在游戏结束之前调用,没有必要显式的调用这个函数,因为pygame会在python退出的时候自动清理所有已经初始化的模块
    pygame.quit()

    窗口/suiface pygame.display

    pygame.display模块用于创建、管理游戏窗口
    需要先创建一个窗口。其他的活动都是基于窗口的

    1
    pygame.display.set_mode(resolution=(0,0),flags=0,depth=0)
    • resolution:指定屏幕的宽和高,默认创建的窗口大小和屏幕大小一致
    • flags:标志位
      • FULLSCREEN 创建一个全屏窗口
      • DOUBLEBUF 创建一个“双缓冲”窗口,建议在HWSURFACE或者OPENGL时使用
      • HWSURFACE 创建一个硬件加速的窗口,必须和FULLSCREEN同时使用
      • OPENGL 创建一个OPENGL渲染的窗口
      • RESIZABLE 创建一个可以改变大小的窗口
      • NOFRAME 创建一个没有边框的窗口
    • depth:颜色的位深,默认自动匹配
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 指定窗口的宽和高
    # 只能有一个
    screen = pygame.display.set_mode((600,500))
    screen = pygame.display.set_mode((1024, 768), pygame.FULLSCREEN)
    # 设置窗口的标题
    pygame.display.set_caption('Hello World!')
    # 填充背景颜色
    screen.fill((255,255,255))
    # 刷新屏幕内容显示,把内容显示到屏幕上
    pygame.display.update()
    # 如果使用DOUBLEBUF,需要用flip函数把内容显示到屏幕上
    pygame.display.flip()
    # 可以查看当前设备支持的分辨率
    pygame.display.list_modes()

    游戏循环

    如果没有循环,窗口无法保持,只能看到一闪而过

    一个游戏循环(也可以称为主循环)就做下面这三件事:

    1. 处理事件
    2. 更新游戏状态
    3. 绘制游戏状态到屏幕上
    1
    2
    while True:
    pass
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import pygame
    from pygame.locals import *
    pygame.init()
    screen = pygame.display.set_mode((600,500))
    pygame.display.set_caption('Hello World')
    while True:
    pass
    pygame.quit()

    坐标系

    以左上角为(0,0)点,往右方向为X轴,往下方向为Y轴,单位为像素

    矩形区域 pygame.Rect

    pygame.Rect是用于存储直角坐标的pygame对象,在游戏中所有可见的元素都是以矩形区域来描述位置的(区别于绘制图形中的矩形)

    对象

    1
    2
    Rect(left, top, width, height)
    Rect((left, top), (width, height))

    前两项描述位置,后两项描述大小

    属性

    1
    2
    3
    4
    5
    6
    x,y
    top, left, bottom, right
    topleft, bottomleft, topright, bottomright
    midtop, midleft, midbottom, midright
    center, centerx, centery
    size, width, height

    绘制图形 pygame.draw

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    pygame.draw.rect(Surface, color, Rect, width=0)
    # 绘制一个矩形形状
    pygame.draw.polygon(Surface, color, pointlist, width=0)
    # 绘制多边形
    pygame.draw.circle(Surface, color, pos, radius, width=0)
    # 围绕一个点画一个圆
    pygame.draw.ellipse(Surface, color, Rect, width=0)
    # 在矩形内绘制圆形
    pygame.draw.arc(Surface, color, Rect, start_angle, stop_angle, width=1)
    # 绘制一个椭圆的局部部分
    pygame.draw.line(Surface, color, start_pos, end_pos, width=1)
    # 画出一条直线段
    pygame.draw.lines(Surface, color, closed, pointlist, width=1)
    # 绘制多个连续的线段
    pygame.draw.aaline(Surface, color, startpos, endpos, blend=1)
    # 画精美的抗锯齿线
    pygame.draw.aalines(Surface, color, closed, pointlist, blend=1)
    # 绘制抗锯齿线的连接序列

    实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import pygame
    from pygame.locals import *
    from math import pi
    # 定义颜色
    RED = (255,0,0)
    GREEN = (0,255,0)
    BLUE = (0,0,255)
    pygame.init()
    screen = pygame.display.set_mode((600,600))
    pygame.display.set_caption('绘制图形')
    # screen.fill((255,255,255))
    pygame.draw.rect(screen,BLUE,(400,400,100,100))
    pygame.draw.polygon(screen,GREEN,[[400,0],[500,70],[450,100]],5)
    pygame.draw.circle(screen,BLUE,[10,500],40)
    pygame.draw.ellipse(screen,BLUE,(300,200,50,40))
    pygame.draw.ellipse(screen,RED,(200,200,50,40),5)
    pygame.draw.arc(screen,GREEN,(300,500,40,40),0,pi/2,2)
    pygame.draw.arc(screen,RED,(300,500,40,40),pi/2,pi,2)
    pygame.draw.arc(screen,BLUE,(300,500,40,40),pi,3*pi/2,2)
    pygame.draw.arc(screen,(255,255,255),(300,500,40,40),3*pi/2,2*pi,2)
    pygame.draw.line(screen,RED,[1,1],[50,50],5)
    pygame.draw.lines(screen,RED,True,
    [[0,80],[50,90],[200,80],[220,30]],5)
    pygame.draw.aaline(screen,RED,[80,80],[40,90],True)
    while 1:
    pass
    pygame.display.update()

    字体/文本 pygame.font

    pygame.font模块将文本打印到窗口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    pygame.font.Font(filename, size)
    # filename:字体文件的文件名
    # size:字体的高 height,单位为像素
    pygame.font.Font.render(text, antialias, color, background=None)
    # text:要显示的文字,文字只能包含一行,换行符不会被画出来
    # antialias: 是否抗锯齿
    # color:字体颜色
    # background:背景颜色(可选参数),如果没有指定background,背景是透明的
    # 返回一个surgace
    pygame.font.get_fonts()
    # 获取可用的字体的列表
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import pygame
    pygame.init()
    screen = pygame.display.set_mode((300,300))
    pygame.display.set_caption('Font')
    # 1.字体对象,指定字体和大小
    myfont = pygame.font.Font(None,60)
    # myfont = pygame.font.Font('./font/楷体_GB2312.ttf',60)
    # 2.指定文本内容,文本颜色,文本背景色
    textSufaceObj = myfont.render('Hello world',True,(255,255,255),(0,255,0))
    # 3.指定文本位置
    screen.blit(textSufaceObj,(50,100))
    while 1:
    # 4.显示文本
    pygame.display.update()
    pygame.quit()

    图像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    img = pygame.image.load(filename)
    # 加载一张图片
    # 返回一个包含图像的Surface,Surface的格式和原来的文件相同(包括颜色格式、透明色和alpha透明)
    pygame.Surface.blit(img, dest, area=None, special_flags = 0)
    # 将图片绘制到屏幕相应坐标上(后面两个参数默认,可以不传)
    pygame.image.save(img, filename)
    # 把img这个Surface的内容保存为filename指定的图像文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import pygame
    from pygame.locals import *
    pygame.init()
    screen = pygame.display.set_mode((100,100))
    pygame.display.set_caption('Image')
    image = pygame.image.load('./Ball.png')
    # 获得图像位置
    imageRect = image.get_rect()
    # 指定图片居中
    imageRect.center = (50,50)
    screen.fill((156,178,166))
    # screen.blit(image,(50,50))
    screen.blit(image,imageRect)
    while 1:
    pygame.display.update()
    pygame.quit()

    音频

    背景音乐

    1
    pygame.mixer.music.load(filename)

    filename:音频文件的文件名
    该方法用来加载背景音乐,之后调用 pygame.mixer.music.play( ) 方法就可以播放背景音乐(Pygame 只允许加载一个背景音乐在同一个时刻)
    音乐文件可以很大,系统以流的形式播放

    1
    2
    3
    4
    5
    6
    7
    8
    9
    大专栏  Pygame相关>10
    11
    12
    13
    14
    15
    16
    pygame.init() #进行全部模块的初始化,
    pygame.mixer.init() #或者只初始化音频部分
    pygame.mixer.music.load('xx.mp3') #使用文件名作为参数载入音乐 ,音乐可以是ogg、mp3等格式。载入的音乐不会全部放到内容中,而是以流的形式播放的,即在播放的时候才会一点点从文件中读取。
    pygame.mixer.music.play() #播放载入的音乐。该函数立即返回,音乐播放在后台进行。
    #play方法还可以使用两个参数
    pygame.mixer.music.play(loops=0, start=0.0) #loops和start分别代表重复的次数和开始播放的位置
    pygame.mixer.music.stop() #停止播放
    pygame.mixer.music.pause() #暂停播放
    pygame.mixer.music.unpause() #取消暂停
    pygame.mixer.music.fadeout(time) #用来进行淡出,在time毫秒的时间内音量由初始值渐变为0,最后停止播放
    pygame.mixer.music.set_volume(value) #来设置播放的音量,音量value的范围为0.0到1.0
    pygame.mixer.music.get_busy() #判断是否在播放音乐,返回1为正在播放
    pygame.mixer.music.set_endevent(pygame.USEREVENT + 1) #在音乐播放完成时,用事件的方式通知用户程序,设置当音乐播放完成时发送
    pygame.USEREVENT+1 #事件给用户程序
    pygame.mixer.music.queue(filename) #使用指定下一个要播放的音乐文件,当前的音乐播放完成后自动开始播放指定的下一个。一次只能指定一个等待播放的音乐文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import pygame
    pygame.init()
    pygame.mixer.music.load('./sound/background.mp3')
    pygame.mixer.music.play()
    while 1:
    pass

    循环播放

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import pygame
    pygame.init()
    pygame.mixer.music.load('./sound/曲锦楠 - 霞光.mp3')
    pygame.mixer.music.play()
    clock = pygame.time.Clock()
    while 1:
    clock.tick(1)
    isbusy = pygame.mixer.music.get_busy()
    print(isbusy)
    if isbusy == 0:
    pygame.mixer.music.play()

    特效声音

    要在游戏中播放碰撞、爆炸、语音等音效,需要使用pygame.mixer模块。这个模块支持同时播放多个音效文件,多个文件在多个不同的通道Channel中播放,一个通道一次只能播放一个音效文件。

    音效和音乐的区别是:音效要整个文件载入到Sound对象中才能播放,而音乐不用完全载入,而以流的方式播放。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    pygame.mixer.get_num_channels()
    # 查看总共有多少个通道
    channel = pygame.mixer.Channel(i)
    # 取得第i个通道
    channel = pygame.mixer.find_channel()
    # 自动取得一个空闲的通道(没有音效正在播放的通道)
    sound = pygame.mixer.Sound('./sound/enemy1_down.wav')
    channel.play(sound)
    # 在一个通道中播放一个音效
    sound.play()
    # 自动找一个空闲的通道播放音效
    sound.stop()
    # 停止音效sound的播放
    channel.stop()
    # 停止在通道channel中播放的音效
    channel.pause()
    # 暂停通道中的音效
    channel.unpause()
    # 暂停的音效继续播放
    channel.get_busy()
    # 检查通道是否正在播放音效
    channel.fadeout(time)
    # 淡出,在time毫秒的时间内音量由初始值渐变为0,最后停止播放
    channel.queue(soundfile)
    # 为正在播放音效的通道指定下一个要播放的音效。当前的音效播放完成后,下一个音效会自动播放。一个通道只能有一个等待播放的音效。
    channel.set_volume(value)
    # 设置通道中播放的音效的音量
    sound.set_volume(value)
    # 设置单个音效的音量
    # 两者的取值范围都是0.0到1.0。音效播放的实际音量是通道音量和音效音量的乘积,比如通道音量0.5,音效音量0.6,则实际播放的音量为0.3

    说了这么多,实际上只需要两句就足够了

    1
    2
    sound = pygame.mixer.Sound('./sound/enemy1_down.wav')
    sound.play()

    视频 pygame.movie

    https://stackoverflow.com/questions/37775635/pygame-movie-missing

    该模块已经过时

    要在游戏中播放片头动画、过场动画等视频画面,可以使用pygame.movie模块

    要播放视频中的音乐,pygame.movie模块需要对音频接口的完全控制,不能初始化mixer模块。因此要这样完成初始化~~

    1
    2
    pygame.init()
    pygame.mixer.quit()

    或者只初始化

    1
    pygame.display.init()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    movie = pygame.movie.Movie(’filename’)
    # 指定文件名载入视频。视频的格式可以为mpeg1。视频文件不会马上全部载入内存,而是在播放的时候一点一点的载入内存。
    movie.set_display(pygame.display.set_mode((640,480)))
    # 指定播放的surface。
    movie.set_volume(value)
    # 指定播放的音量。音量的值value的取值范围为0.0到1.0。
    movie.play()
    # 播放视频。这个函数会立即返回,视频在后台播放。这个函数可以带一个参数loops,指定重复次数。
    movie.stop()
    # 停止播放
    movie.pause()
    # 暂停播放
    movie.skip(seconds)
    # 使视频前进seconds秒钟。
    如有不懂的可以参考Pygame的官方例子,在Python安装目录下的libsite-packagespygameexamplesmovieplayer.py文件。

    动画

    帧率(Frame rate):每秒钟能够刷新的次数

    1
    2
    3
    4
    5
    pygame.time.Clock()
    # 获得 pygame 的时钟对象
    pygame.time.Clock.tick(FPS)
    # 设置 pygame 时钟的间隔时间
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import pygame
    from pygame.locals import *
    pygame.init()
    screen = pygame.display.set_mode((100,100))
    pygame.display.set_caption('Image')
    image = pygame.image.load('./Ball.png')
    imageRect = image.get_rect()
    imageRect.center = (50,50)
    # screen.blit(image,(50,50))
    fps = pygame.time.Clock()
    while 1:
    fps.tick(10)
    imageRect.x += 1
    # 需要重新绘制背景
    screen.fill((156,178,166))
    screen.blit(image,imageRect)
    # pygame.display.flip()
    pygame.display.update()
    pygame.quit()

    事件

    Pygame通过一个事件系统与用户进行交互,以及处理一些系统发生的事件。事件系统包括一个事件队列,其中每一项都是一个Event对象。所有的用户输入和一些系统事件,都会形成一个Event对象被添加到事件队列中。
    Event对象有各种不同的类型,通过Event.type属性来区分。不同的类型的Event对象还有不同的其它属性。通过Event.dict属性来查看。

    详细:http://www.xefan.com/archives/83586.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    import pygame
    from pygame.locals import *
    pygame.init()
    screen = pygame.display.set_mode((600,600))
    pygame.display.set_caption('Event')
    while 1:
    # 获取事件列表
    for event in pygame.event.get():
    # 点击关闭
    if event.type == QUIT:
    pygame.quit()
    exit()
    # 鼠标移动
    if event.type == MOUSEMOTION:
    print(event.pos)
    if event.type == MOUSEBUTTONDOWN:
    print('鼠标按下',event.pos)
    if event.type == MOUSEBUTTONUP:
    print('鼠标抬起',event.pos)
    # 方向键
    if event.type == KEYDOWN:
    if (event.key == K_UP or event.key == K_w):
    print('上')
    if (event.key == K_DOWN or event.key == K_s):
    print('下')
    if (event.key == K_LEFT or event.key == K_a):
    print('左')
    if (event.key == K_RIGHT or event.key == K_d):
    print('右')
    if event.key == K_ESCAPE:
    pygame.quit()
    exit()

    定时器

    每隔多少时间触发一次事件
    pygame中的时间是以毫秒(千分之一秒)表示的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 自定义计时事件
    COUNT = pygame.USEREVENT +1
    # 每隔1秒发送一次自定义事件
    pygame.time.set_timer(COUNT,1000)
    # 获取事件
    for event in pygame.event.get():
    # 判断事件是否为计时事件
    if event.type == COUNT:
    pass

    计时器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import pygame,time
    from pygame.locals import *
    SCREEN_RECT = pygame.Rect(0,0,700,200)
    COUNT = pygame.USEREVENT+1
    pygame.init()
    screen = pygame.display.set_mode(SCREEN_RECT.size)
    pygame.display.set_caption('time')
    font = pygame.font.Font(None,60)
    pygame.time.set_timer(COUNT,1000)
    while 1:
    for event in pygame.event.get():
    if event.type == QUIT:
    pygame.quit()
    exit()
    if event.type == COUNT:
    now = time.ctime()
    clock = now[11:19]
    timeObj = font.render(clock,True,(255,255,255))
    # timeObj = font.render(now,True,(255,255,255))
    timeRect = timeObj.get_rect()
    timeRect.center = SCREEN_RECT.center
    screen.fill((0,0,0))
    screen.blit(timeObj,timeRect)
    pygame.display.update()

    冲突

    while True: # 程序主循环
    for event in pygame.event.get():# 获取事件
    if event.type == QUIT:# 判断事件是否为退出事件
    pygame.quit()# 退出pygame
    sys.exit()# 退出系统
    pygame.display.update()# 绘制屏幕内容

    参考:

  • 相关阅读:
    cubic-bezier贝塞尔曲线css3动画工具
    css媒体查询
    this call和apply
    容易混淆的url src href
    你不知道的css中的expression
    不同浏览器对document.documentElement和document.body的scrollheight ,scrollTop,clientHeight以及判断滚动条是否滚动到页面最底部 【转载】
    jquery动画遮罩
    手机页面中的meta标签
    Knowledge Point 20180305 机器数转换与进制转换
    Knowledge Point 20180305 数据在计算机中的表示
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12288759.html
Copyright © 2011-2022 走看看