pygame 订阅
Pygame是跨平台Pyth,Pygame 作者是 Pete Shinners, 协议为 GNU Lesser General Public License。 展开全文
Pygame是跨平台Pyth,Pygame 作者是 Pete Shinners, 协议为 GNU Lesser General Public License。
信息
中文名
Pygame
引擎和库
Phil's Pygame Utilities (P
介    绍
Pygame是 跨平台 Pyth
其    他
Pyweek,游戏制作竞赛,
Pygame介绍
包含图像、声音。 建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。基于这样一个设想,所有需要的游戏功能和理念都(主要是图像方面)都完全简化为游戏逻辑本身,所有的资源结构都可以由高级语言提供,如Python。Pygame 原为代替突然停止的 pySDL
收起全文
精华内容
下载资源
问答
  • pygame

    2021-08-18 19:36:16
    pygame 文章目录pygamepygame简介安装 pygamepygame 模块pygame 项目地址 pygame简介 安装 pygame pygame 模块 pygame 项目地址

    pygame

    pygame简介

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

    安装 pygame

    在安装了pip的前提下打开cmd输入

    pip3 install pygame
    

    pygame 模块

    模块名功能
    pygame.cdrom访问光驱
    pygame.cursors加载光标
    pygame.display访问显示设备
    pygame.draw绘制形状、线和点
    pygame.event管理事件
    pygame.font使用字体
    pygame.image加载和存储图片
    pygame.joystick使用游戏手柄或者类似的东西
    pygame.key读取键盘按键
    pygame.mixer声音
    pygame.mouse鼠标
    pygame.movie播放视频
    pygame.music播放音频
    pygame.overlay访问高级视频叠加
    pygame.rect管理矩形区域
    pygame.scrap本地剪贴板访问
    pygame.sndarray操作声音数据
    pygame.sprite操作移动图像
    pygame.surface管理图像和屏幕
    pygame.surfarray管理点阵图像数据
    pygame.time管理时间和帧信息
    pygame.transform缩放和移动图像

    pygame 小项目预告

    网上有不少人都用pygame制作一款名为〃飞机大战〃的小游戏,我寻思着过些日子我也做一款。

    结束语

    各位互联网上的同事、同仁、同学们,C# 编写 WinForm 窗体应用程序(第三期)到这里就结束了。码字不易,读完了这篇博客在评论区里留下你的真心话,甩给作者一个赞再走呗!👍👍👍
    在这里插入图片描述

    展开全文
  • Pygame

    2018-03-14 20:48:57
    #级联编程(开火车式的编程) 让方法返回...了解pygame #faststone capture 下载这个工具可以录屏,量屏,屏幕拾色器 #下面演示一下不用面向对象的方式,进行游戏编程,代码如下: import pygame EMPTY ...
    #级联编程(开火车式的编程) 让方法返回对象本身 f().add().mul()   return self
    # pygame 去https://www.pygame.org/ 了解pygame
    #faststone capture 下载这个工具可以录屏,量屏,屏幕拾色器
    #下面演示一下不用面向对象的方式,进行游戏编程,代码如下:
    import pygame
    
    EMPTY = 0
    BLACK = 1
    WHITE = 2
    
    
    def main():
        board = [[EMPTY] * 15 for _ in range(15)]
        pygame.init()
        screen = pygame.display.set_mode([640, 640]) #创建窗口
        screen.fill([255, 255, 0]) #添加背景颜色
        black_color = [0, 0, 0]
        white_color = [255, 255, 255]
        for index in range(1, 16):
            pygame.draw.line(screen,black_color, [40, 40 * index], [600, 40 * index], 1)
            pygame.draw.line(screen, black_color, [40 * index, 40], [ 40 * index, 600], 1)
        pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4) #36,36表示起点的横纵坐标,568,568表示矩形的长宽
        pygame.draw.circle(screen, black_color, [320, 320], 5, 0)#5表示半径,0表示线条是实心
        pygame.draw.circle(screen, black_color, [160, 160], 5, 0)
        pygame.draw.circle(screen, black_color, [480, 480], 5, 0)
        pygame.draw.circle(screen, black_color, [480, 160], 5, 0)
        pygame.draw.circle(screen, black_color, [160, 480], 5, 0)
    
        for row in range(len(board)):
            for col in range(len(board[row])):
                if board[row][col] != EMPTY:
                    ccolor = black_color \
                        if board[row][col] == BLACK else white_color
                    pos = [40 * (col + 1), 40 * (row + 1)]
                    pygame.draw.circle(screen, ccolor, pos, 20, 0)
    
        pygame.display.flip() #刷新窗口
        pygame.display.set_caption('五子棋') #创建标题
        running = True
        is_black_turn = True
        while running:
            for event in pygame.event.get(): #接受事件
                if event.type == pygame.QUIT: #事件类型是关闭事件
                    running = False
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1: #表示鼠标左键
                        x, y = event.pos #获取鼠标的坐标
                        if 40 <= x <= 600 and 40 <= y <= 600:
                            col = round((x - 40) / 40)
                            row = round((y - 40) / 40)
                            if board[row][col] == EMPTY:
                                board[row][col] = BLACK if is_black_turn else WHITE
                                is_black_turn = not is_black_turn
                                for row in range(len(board)):
                                    for col in range(len(board[row])):
                                        if board[row][col] != EMPTY:
                                            ccolor = black_color \
                                                if board[row][col] == BLACK else white_color
                                            pos = [40 * (col + 1), 40 * (row + 1)]
                                            pygame.draw.circle(screen, ccolor, pos, 20, 0)
                                pygame.display.flip()
    
        pygame.quit()
    
    
    if __name__ == '__main__':
        main()
    pycharm中选择想要创建函数的代码,右键,refactor 下excract下,method,可以直接生成函数
    # 下面一段代码用面向对象的思想实现了相同的功能,但是代码整体感觉更加清晰
    import pygame
    EMPTY = 0
    BLACK = 1
    WHITE = 2
    black_color = [0, 0, 0]
    white_color = [255, 255, 255]
    
    
    class RenjuBoard(object):
    
        def __init__(self):
            self._board = [[]] * 15
            self.reset()
    
        def reset(self):
            for row in range(len(self._board)):
                self._board[row] = [EMPTY] * 15
    
        def draw(self, screen):
            for index in range(1, 16):
                pygame.draw.line(screen, black_color, [40, 40 * index], [600, 40 * index], 1)
                pygame.draw.line(screen, black_color, [40 * index, 40], [40 * index, 600], 1)
            pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)  # 36,36表示起点的横纵坐标,568,568表示矩形的长宽
            pygame.draw.circle(screen, black_color, [320, 320], 5, 0)  # 5表示半径,0表示线条是实心
            pygame.draw.circle(screen, black_color, [160, 160], 5, 0)
            pygame.draw.circle(screen, black_color, [480, 480], 5, 0)
            pygame.draw.circle(screen, black_color, [480, 160], 5, 0)
            pygame.draw.circle(screen, black_color, [160, 480], 5, 0)
            for row in range(len(self._board)):
                for col in range(len(self._board[row])):
                    if self._board[row][col] != EMPTY:
                        ccolor = black_color \
                            if self._board[row][col] == BLACK else white_color
                        pos = [40 * (col + 1), 40 * (row + 1)]
                        pygame.draw.circle(screen, ccolor, pos, 20, 0)
    
        def move(self,row,col,is_black):
            if self._board[row][col] == EMPTY:
                self._board[row][col] = BLACK if is_black else WHITE
                return True
            return False
    
    
    def main():
        pygame.init()
        is_black = True
        pygame.display.set_caption('五子棋')  # 创建标题
        screen = pygame.display.set_mode([640, 640]) #创建窗口
        screen.fill([255, 255, 0]) #添加背景颜色
        r1 = RenjuBoard()
        r1.draw(screen)
        pygame.display.flip()  # 刷新窗口
        running = True
        while running:
            for event in pygame.event.get(): #接受事件
                if event.type == pygame.QUIT: #事件类型是关闭事件
                    running = False
                elif event.type == pygame.KEYDOWN:
                    pass
                elif event.type == pygame.MOUSEBUTTONDOWN \
                        and event.button == 1:
                    x, y = event.pos
                    row = round((y - 40) / 40)
                    col = round((x - 40) / 40)
                    if r1.move(row, col, is_black):
                        is_black = not is_black
                        screen.fill([255, 255, 0])
                        r1.draw(screen)
                        pygame.display.flip()
    
        pygame.quit()
    
    
    if __name__ == '__main__':
        main()
    
    """
    大球吃小球
    """
    from random import randint
    from math import sqrt, pi
    import pygame
    
    
    class Ball(object):
    
        def __init__(self, center, color, radius, sx, sy):
            """
    
            :param x: 横坐标
            :param y: 纵坐标
            :param color: 颜色
            :param radius: 半径
            :param sx: 横向移动速度
            :param sy: 纵向移动速度
            """
            self._center = center
            self._color = color
            self._radius = radius
            self._sx = sx
            self._sy = sy
    
        @property
        def center(self):
            return self._center
    
        @property
        def radius(self):
            return self._radius
    
        @radius.setter
        def radius(self, radius):
            self._radius = radius
    
        def area(self):
            return pi * self._radius ** 2
    
        def move(self):
            x, y = self._center[0], self._center[1]
            x += self._sx
            y += self._sy
            self._center = (x, y)
            if x + self._radius > 800:
                x = 790 - self._radius
                self._sx = -self._sx
                self._center = (x, y)
            elif x - self._radius < 0:
                x = 10 + self._radius
                self._sx = -self._sx
                self._center = (x, y)
            elif x + self._radius == 800 or x - self._radius == 0:
                self._sx = -self._sx
            if y + self._radius > 600:
                y = 590 - self._radius
                self._sy = -self._sy
                self._center = (x, y)
            elif y - self._radius < 0:
                y = 10 + self._radius
                self._sy = -self._sy
                self._center = (x, y)
            elif y + self._radius == 600 or y - self._radius == 0:
                self._sy = -self._sy
    
        def draw(self, screen):
            pygame.draw.circle(screen, self._color, self._center,
                               self._radius, 0)
    
        def eat(self, other):
            for ball in other:
                if (self._radius > ball.radius) and (distance(self._center, ball.center)
                                                     < (self._radius + ball.radius)):
                    temp_area = self.area() + ball.area()
                    self._radius = int(sqrt(temp_area / pi))
                    # del ball
                    other.remove(ball)
                elif self._radius < ball._radius and distance(self._center, ball.center) \
                        < (self._radius + ball.radius):
                    temp_area = self.area() + ball.area()
                    ball.radius = int(sqrt(temp_area / pi))
                    other.remove(self)
    
    
    def main():
        balls = []
        pygame.init()
        screen = pygame.display.set_mode([800, 600])
        pygame.display.set_caption('大球吃小球')
        clock = pygame.time.Clock()
        running = True
    
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.MOUSEBUTTONDOWN and \
                        event.button == 1:
                    color = random_color()
                    radius = randint(10, 30)
                    sx, sy = randint(-10, 10), randint(-10, 10)
                    ball = Ball(event.pos, color, radius, sx, sy)
                    balls.append(ball)
    
            refresh(screen, balls)
            clock.tick(50)
            for ball in balls:
                ball.move()
                ball.eat(balls)
    
        pygame.quit()
    
    
    def refresh(screen, balls):
        bg_color = (242, 242, 242)
        screen.fill(bg_color)
        for ball in balls:
            ball.draw(screen)
        pygame.display.flip()
    
    
    def random_color():
        red = randint(0, 255)
        green = randint(0, 255)
        blue = randint(0, 255)
        return red, green, blue
    
    
    def distance(one, other):
        x1 = one[0]
        y1 = one[1]
        x2 = other[0]
        y2 = other[1]
        return sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
    
    
    if __name__ == '__main__':
        main()
    展开全文
  • Python游戏编程(Pygame)

    万次阅读 多人点赞 2018-10-05 13:04:42
    安装Pygame pip install pygame C:\Users&amp;amp;amp;gt; pip install pygame Collecting pygame Downloading https://files.pythonhosted.org/packages/3e/f5/feabd88a2856ec86166a897b62...

    安装Pygame

    pip install pygame
    
    C:\Users> pip install pygame                
    Collecting pygame                   
      Downloading https://files.pythonhosted.org/packages/3e/f5/feabd88a2856ec86166a897b62bfad828bfe7a94a27cbd7ebf07fd
    70399/pygame-1.9.4-cp37-cp37m-win_amd64.whl (4.2MB)
        100% |██████████████████████████| 4.2MB 6.6MB/s
    Installing collected packages: pygam
    Successfully installed pygame-1.9.4 
    

    Pygame常用模块

    模块名功能
    pygame.cdrom访问光驱
    pygame.cursors加载光标
    pygame.display访问显示设备
    pygame.draw绘制形状、线和点
    pygame.event管理事件
    pygame.font使用字体
    pygame.image加载和存储图片
    pygame.joystick使用游戏手柄或者类似的东西
    pygame.key读取键盘按键
    pygame.mixer声音
    pygame.mouse鼠标
    pygame.movie播放视频
    pygame.music播放音频
    pygame.overlay访问高级视频叠加
    pygame.rect管理矩形区域
    pygame.scrap本地剪贴板访问
    pygame.sndarray操作声音数据
    pygame.sprite操作移动图像
    pygame.surface管理图像和屏幕
    pygame.surfarray管理点阵图像数据
    pygame.time管理时间和帧信息
    pygame.transform缩放和移动图像

    简单示例:

    import pygame
    import sys
    
    pygame.init()  # 初始化pygame
    size = width, height = 320, 240  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    
    while True:  # 死循环确保窗口一直显示
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()
    
    pygame.quit()  # 退出pygame
    

    执行结果:

    制作一个跳跃的小球游戏

    创建一个游戏窗口,然后在窗口内创建一个小球。以一定的速度移动小球,当小球碰到游戏窗口的边缘时,小球弹回,继续运动按照如下步骤实现该功能:

    创建游戏窗口

    1. 创建一个游戏窗口,宽和高设置为640*480。代码如下:

    import sys
    import pygame
    pygame.init()                       # 初始化pygame
    size = width, height = 640, 480     # 设置窗口大小
    screen = pygame.display.set_mode()  # 显示窗口
    

    上述代码中,首先导入pygame模块,然后调用init()方法初始化pygame模块,接下来,设置窗口的宽和高,最后使用display模块显示窗体。

    display模块的常用方法

    方法名功能
    pygame.display.init()初始化display模块
    pygame.display.quit()结束display模块
    pygame.display.get_init()如果display模块已经被初始化,则返回True
    pygame.display.set_mode()初始化一个准备显示的界面
    pygame.display.get_surface()获取当前的Surface对象
    pygame.display.flip()更新整个待显示的Surface对象到屏幕上
    pygame.display.update()更新部分内容显示到屏幕上,如果没有参数,则与flip功能相同(上一条)

    保持窗口显示

    2. 运行第一步的代码后会出现一个一闪而过的黑色窗口,这是因为程序执行完成后,会自动关闭。如果想要让窗口一直显示,需要使用while True让程序一直执行,此外,还需要设置关闭按钮。具体代码如下:

    import pygame
    import sys
    
    pygame.init()  # 初始化pygame
    size = width, height = 320, 240  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    
    while True:  # 死循环确保窗口一直显示
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()
    
    pygame.quit()  # 退出pygame
    

    上述代码中添加了轮询事件检测。pygame.event.get()能够获取事件队列,使用for...in遍历事件,然后根据type属性判断事件类型。这里的事件处理方式与GUI类似,如event.type等于pygame.QUIT表示检测到关闭pygame窗口事件,pygame.KEYDOWN表示键盘按下事件,pygame.MOUSEBUTTONDOWN表示鼠标按下事件等。

    加载游戏图片

    开发过程中使用的图片

    3. 在窗口添加小球。我们先准备好一张ball.png
    图片,然后加载该图片,最后将图片显示在窗口中,具体代码如下:

    import pygame
    import sys
    
    pygame.init()  # 初始化pygame
    size = width, height = 640, 480  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    color = (0, 0, 0)  # 设置颜色
    ball = pygame.image.load('ball.png')  # 加载图片
    ballrect = ball.get_rect()  # 获取矩形区域
    
    while True:  # 死循环确保窗口一直显示
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()
        screen.fill(color)  # 填充颜色(设置为0,执不执行这行代码都一样)
        screen.blit(ball, ballrect)  # 将图片画到窗口上
        pygame.display.flip()  # 更新全部显示
    
    pygame.quit()  # 退出pygame
    

    上述代码中使用iamge模块的load()方法加载图片,返回值ball是一个Surface对象。Surface是用来代表图片的pygame对象,可以对一个Surface对象进行涂画、变形、复制等各种操作。事实上,屏幕也只是一个Surfacepygame.display.set_mode()就返回了一个屏幕Surface对象。如果将ball这个Surface对象画到screen Surface 对象,需要使用blit()方法,最后使用display模块的flip()方法更新整个待显示的Surface对象到屏幕上。

    Surface对象的常用方法

    方法名功能
    pygame.Surface.blit()将一个图像画到另一个图像上
    pygame.Surface.convert()转换图像的像素格式
    pygame.Surface.convert_alpha()转化图像的像素格式,包含alpha通道的转换
    pygame.Surface.fill()使用颜色填充Surface
    pygame.Surface.get_rect()获取Surface的矩形区域

    移动图片

    4. 下面让小球动起来,ball.get_rect()方法返回值ballrect是一个Rect对象,该对象有一个move()方法可以用于移动矩形。move(x, y)函数有两个参数,第一个参数是 X 轴移动的距离,第二个参数是 Y 轴移动的距离。窗口的左上角是(0, 0),如果是move(100, 50)就是左移100下移50。

    为实现小球不停移动,将move()函数添加到while循环内,具体代码如下:

    import pygame
    import sys
    
    pygame.init()  # 初始化pygame
    size = width, height = 640, 480  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    color = (0, 0, 0)  # 设置颜色
    ball = pygame.image.load('ball.png')  # 加载图片
    ballrect = ball.get_rect()  # 获取矩形区域
    
    speed = [5, 5]  # 设置移动的X轴、Y轴
    while True:  # 死循环确保窗口一直显示
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()
        ballrect = ballrect.move(speed)  # 移动小球
        screen.fill(color)  # 填充颜色(设置为0,执不执行这行代码都一样)
        screen.blit(ball, ballrect)  # 将图片画到窗口上
        pygame.display.flip()  # 更新全部显示
    
    pygame.quit()  # 退出pygame
    

    碰撞检测

    5. 运行上述代码,发现小球在屏幕中一闪而过,此时,小球并没有真正消失,而是移动到窗体之外,此时需要添加碰撞检测的功能。当小球与窗体任一边缘发生碰撞,则更改小球的移动方向,具体代码如下:

    import pygame
    import sys
    
    pygame.init()  # 初始化pygame
    size = width, height = 640, 480  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    color = (0, 0, 0)  # 设置颜色
    ball = pygame.image.load('ball.png')  # 加载图片
    ballrect = ball.get_rect()  # 获取矩形区域
    speed = [5, 5]  # 设置移动的X轴、Y轴
    
    while True:  # 死循环确保窗口一直显示
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()
                
        ballrect = ballrect.move(speed)  # 移动小球
        # 碰到左右边缘
        if ballrect.left < 0 or ballrect.right > width:
            speed[0] = -speed[0]
        # 碰到上下边缘
        if ballrect.top < 0 or ballrect.bottom > height:
            speed[1] = -speed[1]
    
        screen.fill(color)  # 填充颜色(设置为0,执不执行这行代码都一样)
        screen.blit(ball, ballrect)  # 将图片画到窗口上
        pygame.display.flip()  # 更新全部显示
    
    pygame.quit()  # 退出pygame
    

    上述代码中,添加了碰撞检测功能。如果碰到左右边缘,更改X轴数据为负数,如果碰到上下边缘,更改Y轴数据为负数。

    限制移动速度

    6. 运行上述代码看似有很多球,这是因为运行上述代码的时间非常短,运行快的错觉,使用pygame的time模块,使用pygame时钟之前,必须先创建Clock对象的一个实例,然后在while循环中设置多长时间运行一次。

    import pygame
    import sys
    
    pygame.init()  # 初始化pygame
    size = width, height = 640, 480  # 设置窗口大小
    screen = pygame.display.set_mode(size)  # 显示窗口
    color = (0, 0, 0)  # 设置颜色
    ball = pygame.image.load('ball.png')  # 加载图片
    ballrect = ball.get_rect()  # 获取矩形区域
    speed = [5, 5]  # 设置移动的X轴、Y轴
    clock = pygame.time.Clock()  # 设置时钟
    
    while True:  # 死循环确保窗口一直显示
        clock.tick(60)  # 每秒执行60次
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
                sys.exit()
    
        ballrect = ballrect.move(speed)  # 移动小球
        # 碰到左右边缘
        if ballrect.left < 0 or ballrect.right > width:
            speed[0] = -speed[0]
        # 碰到上下边缘
        if ballrect.top < 0 or ballrect.bottom > height:
            speed[1] = -speed[1]
    
        screen.fill(color)  # 填充颜色(设置为0,执不执行这行代码都一样)
        screen.blit(ball, ballrect)  # 将图片画到窗口上
        pygame.display.flip()  # 更新全部显示
    
    pygame.quit()  # 退出pygame
    

    开发Flappy Bird游戏

    Flappy Bird是一款鸟类飞行游戏,一根手指操控按下小鸟上飞。

    分析
    在Flappy Bird游戏中,主要有两个对象:小鸟、管道。可以创建Brid类和Pineline类来分别表示这两个对象。小鸟可以通过上下移动来躲避管道,所以在Brid类中创建一个bridUpdate()方法,实现小鸟的上下移动,为了体现小鸟向前飞行的特征,可以让管道一直向左侧移动,这样在窗口中就好像小鸟在向前飞行。所以在Pineline类中也创建一个updatePipeline()方法,实现管道的向左侧移动。此外还创建了3个函数:createMap()函数用于绘制地图;checkDead()函数用于判断小鸟的生命状态;getResult()函数用于获取最终分数。最后在主逻辑中实例化并调用相关方法,实现相应的功能。

    搭建主框架

    # -*- coding:utf-8 -*-
    import sys  # 导入sys模块
    import pygame  # 导入pygame模块
    import random
    
    
    class Bird(object):
        """定义一个鸟类"""
        def __init__(self):
            """定义初始化方法"""
            pass
    
        def birdUpdate(self):
            pass
    
    
    class Pipeline(object):
        """定义一个管道类"""
        def __init__(self):
            """定义初始化方法"""
    
        def updatePipeline(self):
            """水平移动"""
    
    
    def createMap():
        """定义创建地图的方法"""
        screen.fill((255, 255, 255))  # 填充颜色(screen还没定义不要着急)
        screen.blit(background, (0, 0))  # 填入到背景
        pygame.display.update()  # 更新显示
    
    
    if __name__ == '__main__':
        pygame.init()                           # 初始化pygame
        size = width, height = 400, 650         # 设置窗口大小
        screen = pygame.display.set_mode(size)  # 显示窗口
        clock = pygame.time.Clock()             # 设置时钟
        Pipeline = Pipeline()                   # 实例化管道类
        while True:
            clock.tick(60)                      # 每秒执行60次
            # 轮询事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:   # 如果检测到事件是关闭窗口
                    sys.exit()
    
            background = pygame.image.load("assets/background.png")  # 加载背景图片
            createMap()
        pygame.quit()  # 退出
    

    执行结果:

    开发过程中使用的图片

    创建小鸟类、创建管道类、计算得分、碰撞检测

    import pygame
    import sys
    import random
    
    
    class Bird(object):
        """定义一个鸟类"""
    
        def __init__(self):
            """定义初始化方法"""
            self.birdRect = pygame.Rect(65, 50, 50, 50)  # 鸟的矩形
            # 定义鸟的3种状态列表
            self.birdStatus = [pygame.image.load("assets/1.png"),
                               pygame.image.load("assets/2.png"),
                               pygame.image.load("assets/dead.png")]
            self.status = 0      # 默认飞行状态
            self.birdX = 120     # 鸟所在X轴坐标,即是向右飞行的速度
            self.birdY = 350     # 鸟所在Y轴坐标,即上下飞行高度
            self.jump = False    # 默认情况小鸟自动降落
            self.jumpSpeed = 10  # 跳跃高度
            self.gravity = 5     # 重力
            self.dead = False    # 默认小鸟生命状态为活着
    
        def birdUpdate(self):
            if self.jump:
                # 小鸟跳跃
                self.jumpSpeed -= 1           # 速度递减,上升越来越慢
                self.birdY -= self.jumpSpeed  # 鸟Y轴坐标减小,小鸟上升
            else:
                # 小鸟坠落
                self.gravity += 0.2           # 重力递增,下降越来越快
                self.birdY += self.gravity    # 鸟Y轴坐标增加,小鸟下降
            self.birdRect[1] = self.birdY     # 更改Y轴位置
    
    
    class Pipeline(object):
        """定义一个管道类"""
    
        def __init__(self):
            """定义初始化方法"""
            self.wallx = 400  # 管道所在X轴坐标
            self.pineUp = pygame.image.load("assets/top.png")
            self.pineDown = pygame.image.load("assets/bottom.png")
    
        def updatePipeline(self):
            """"管道移动方法"""
            self.wallx -= 5  # 管道X轴坐标递减,即管道向左移动
            # 当管道运行到一定位置,即小鸟飞越管道,分数加1,并且重置管道
            if self.wallx < -80:
                global score
                score += 1
                self.wallx = 400
    
    
    def createMap():
        """定义创建地图的方法"""
        screen.fill((255, 255, 255))     # 填充颜色
        screen.blit(background, (0, 0))  # 填入到背景
    
        # 显示管道
        screen.blit(Pipeline.pineUp, (Pipeline.wallx, -300))   # 上管道坐标位置
        screen.blit(Pipeline.pineDown, (Pipeline.wallx, 500))  # 下管道坐标位置
        Pipeline.updatePipeline()  # 管道移动
    
        # 显示小鸟
        if Bird.dead:              # 撞管道状态
            Bird.status = 2
        elif Bird.jump:            # 起飞状态
            Bird.status = 1
        screen.blit(Bird.birdStatus[Bird.status], (Bird.birdX, Bird.birdY))              # 设置小鸟的坐标
        Bird.birdUpdate()          # 鸟移动
    
        # 显示分数
        screen.blit(font.render('Score:' + str(score), -1, (255, 255, 255)), (100, 50))  # 设置颜色及坐标位置
        pygame.display.update()    # 更新显示
    
    
    def checkDead():
        # 上方管子的矩形位置
        upRect = pygame.Rect(Pipeline.wallx, -300,
                             Pipeline.pineUp.get_width() - 10,
                             Pipeline.pineUp.get_height())
    
        # 下方管子的矩形位置
        downRect = pygame.Rect(Pipeline.wallx, 500,
                               Pipeline.pineDown.get_width() - 10,
                               Pipeline.pineDown.get_height())
        # 检测小鸟与上下方管子是否碰撞
        if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
            Bird.dead = True
        # 检测小鸟是否飞出上下边界
        if not 0 < Bird.birdRect[1] < height:
            Bird.dead = True
            return True
        else:
            return False
    
    
    def getResutl():
        final_text1 = "Game Over"
        final_text2 = "Your final score is:  " + str(score)
        ft1_font = pygame.font.SysFont("Arial", 70)                                      # 设置第一行文字字体
        ft1_surf = font.render(final_text1, 1, (242, 3, 36))                             # 设置第一行文字颜色
        ft2_font = pygame.font.SysFont("Arial", 50)                                      # 设置第二行文字字体
        ft2_surf = font.render(final_text2, 1, (253, 177, 6))                            # 设置第二行文字颜色
        screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])  # 设置第一行文字显示位置
        screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 200])  # 设置第二行文字显示位置
        pygame.display.flip()                                                            # 更新整个待显示的Surface对象到屏幕上
    
    
    if __name__ == '__main__':
        """主程序"""
        pygame.init()                            # 初始化pygame
        pygame.font.init()                       # 初始化字体
        font = pygame.font.SysFont("Arial", 50)  # 设置字体和大小
        size = width, height = 400, 650          # 设置窗口
        screen = pygame.display.set_mode(size)   # 显示窗口
        clock = pygame.time.Clock()              # 设置时钟
        Pipeline = Pipeline()                    # 实例化管道类
        Bird = Bird()                            # 实例化鸟类
        score = 0
        while True:
            clock.tick(60)                       # 每秒执行60次
            # 轮询事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                    Bird.jump = True             # 跳跃
                    Bird.gravity = 5             # 重力
                    Bird.jumpSpeed = 10          # 跳跃速度
    
            background = pygame.image.load("assets/background.png")  # 加载背景图片
            if checkDead():                      # 检测小鸟生命状态
                getResutl()                      # 如果小鸟死亡,显示游戏总分数
            else:
                createMap()                      # 创建地图
        pygame.quit()
    
    

    执行结果:

    展开全文
  • PyGame-源码

    2021-03-13 12:42:16
    PyGame
  • PYGAME-源码

    2021-03-09 02:25:47
    PYGAME
  • pygame入门

    万次阅读 多人点赞 2018-02-09 17:55:53
    pygame入门 说明 在学习pygame时,主要参考了目光博客的教程。目光博客 原教程是2011年写的,年代比较久远了,使用Python2。我学习时使用python3将代码重新实现了一遍,同时补充了一些细节。相比较原博客,少了...

    pygame入门

    说明

    在学习pygame时,主要参考了目光博客的教程。目光博客

    原教程是2011年写的,年代比较久远了,使用Python2。我学习时使用python3将代码重新实现了一遍,同时补充了一些细节。相比较原博客,少了一些实例。

    pygame官网文档

    文中代码github

    一、pygame的安装

    pip install pygame
    

    安装好后,可以用下面的方法确认有没有安装成功

    >>>import pygame
    >>>print(pygame.ver)
    1.9.3
    

    二、pygame模块概览

    三、pygame的“hello world”

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = 'image/sushiplate.jpg'
    mouse_image = 'image/fugu.png'
    
    # 初始化pygame,为使用硬件做准备
    pygame.init()
    # 创建了一个窗口
    screen = pygame.display.set_mode((640, 480), 0, 32)
    # 设置窗口标题
    pygame.display.set_caption("hello world")
    
    # 加载并转换图像
    background = pygame.image.load(background_image).convert()
    mouse_cursor = pygame.image.load(mouse_image).convert_alpha()
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:  # 接收到退出事件后退出程序
                exit()
        screen.blit(background, (0, 0))  # 画上背景图
    
        x, y = pygame.mouse.get_pos()  # 获得鼠标位置
        # 计算光标左上角位置
        x -= mouse_cursor.get_width()/2
        y -= mouse_cursor.get_height()/2
        # 画上光标
        screen.blit(mouse_cursor, (x, y))
    
        # 刷新画面
        pygame.display.update()
    

    hello world.png](https://i.loli.net/2018/01/25/5a6978dd4f545.png)

    set_mode:返回一个Surface对象,代表了桌面上出现的窗口。第一个参数代表分辨率;第二个参数是标志位,如果不需要使用热河特性,则指定为0;第三个为色深。

    标志位功能
    FULLSCREEN创建一个全屏窗口 (create a fullscreen display)
    DOUBLEBUF创建一个“双缓冲”窗口,建议在HWSURFACE或者OPENGL时使用( recommended for HWSURFACE or OPENGL)
    HWSURFACE创建一个硬件加速的窗口,必须和FULLSCREEN同时使用( hardware accelerated, only in FULLSCREEN)
    OPENGL创建一个OPENGL渲染的窗口 (create an OpenGL-renderable display)
    RESIZABLE创建一个可以改变大小的窗口 (display window should be sizeable)
    NOFRAME创建一个没有边框的窗口 (display window will have no border or controls)

    convert: 将图像转化为Surface对象,每次加载完图像后就要使用这个函数.

    **convert_alpha:**相比convert,保留了Alpha 通道信息(可以简单理解为透明的部分),这样我们的光标才可以是不规则的形状。可以试试不用convert_alpha()生成的效果。

    blit:第一个参数为一个Surface对象,第二个为左上角位置。画完以后得用update更新,否则画面一片漆黑。

    四、事件

    理解事件

    我们上一个程序,一直运行直到关闭窗口而产生了一个QUIT事件,Pygame会接受用户的各种操作(比如按键盘,移动鼠标等)产生事件。事件随时可能发生,而且量也可能会很大,Pygame的做法是把一系列的事件存放一个队列里,逐个的处理。

    事件检索

    上个程序中,使用了pygame.event.get()来处理所有的事件;也可以使用pygame.event.wait(),pygame会等到发生一个时间才继续下去;另外一个方法pygame.event.poll(),一旦调用,它会根据现在的情形返回一个真实的事件,或者一个“什么都没有”。下表是一个常用事件集:

    事件产生途径参数
    QUIT用户按下关闭按钮none
    ATIVEEVENTPygame被激活或者隐藏gain, state
    KEYDOWN键盘被按下unicode, key, mod
    KEYUP键盘被放开key, mod
    MOUSEMOTION鼠标移动pos, rel, buttons
    MOUSEBUTTONDOWN鼠标按下pos, button
    MOUSEBUTTONUP鼠标放开pos, button
    JOYAXISMOTION游戏手柄(Joystick or pad)移动joy, axis, value
    JOYBALLMOTION游戏球(Joy ball)?移动joy, axis, value
    JOYHATMOTION游戏手柄(Joystick)?移动joy, axis, value
    JOYBUTTONDOWN游戏手柄按下joy, button
    JOYBUTTONUP游戏手柄放开joy, button
    VIDEORESIZEPygame窗口缩放size, w, h
    VIDEOEXPOSEPygame窗口部分公开(expose)?none
    USEREVENT触发了一个用户事件code

    接下来我们写一个把所有发生的事件输出的程序

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    pygame.init()
    SCREEN_SIZE = (640, 480)
    screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
    
    font = pygame.font.SysFont("MicrosoftYaHei", 16)
    font_height = font.get_linesize()
    event_text = []
    
    while True:
        event = pygame.event.wait()
        event_text.append(str(event))
        # 保证event_text里面只保留一个屏幕的文字
        event_text = event_text[-SCREEN_SIZE[1]//font_height:]
    
        if event.type == QUIT:
            exit()
    
        screen.fill((255, 255, 255))
    
        # 寻找一个合适的起笔位置,最下面开始,留一行的空
        y = SCREEN_SIZE[1] - font_height
        for text in reversed(event_text):
            screen.blit(font.render(text, True, (0, 0, 0)), (0, y))
            y -= font_height
        pygame.display.update()
    

    结果如下,会将发生的事件列出。在程序中使用wait(),因为这个程序只要在有动作时执行就好了。

    event.png

    处理鼠标事件

    MOUSEMOTION事件会在鼠标动作的时候发生,它有三个参数:

    • buttons – 一个含有三个数字的元组,三个值分别代表左键、中键和右键,1就是按下了。
    • pos – 位置
    • rel – 代表了现在距离上次产生鼠标事件时的距离

    和MOUSEMOTION类似的,我们还有MOUSEBUTTONDOWNMOUSEBUTTONUP两个事件。它们的参数为:

    • button – 这个值代表了哪个按键被操作

    • pos – 位置

    处理键盘事件

    键盘的事件为KEYDOWNKEYUP

    下面这个例子演示的是使用方向键来移动图片。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = '../image/sushiplate.jpg'
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    
    x, y = 0, 0
    move_x, move_y = 0, 0
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
            if event.type == KEYDOWN:
                if event.key == K_LEFT:
                    move_x = -1
                elif event.key == K_RIGHT:
                    move_x = 1
                elif event.key == K_UP:
                    move_y = -1
                elif event.key == K_DOWN:
                    move_y = 1
            elif event.type == KEYUP:
                move_x = 0
                move_y = 0
    
        x += move_x
        y += move_y
    
        screen.fill((0, 0, 0))
        screen.blit(background, (x,y))
    
        pygame.display.update()
    

    KEYDOWN和KEYUP的参数描述如下:具体描述请点击这里

    • key – 按下或者放开的键值,是一个数字,Pygame中可以使用K_xxx来表示,比如字母a就是K_a,还有K_SPACEK_RETURN等。
    • mod – 包含了组合键信息,如果mod & KMOD_CTRL是真的话,表示用户同时按下了Ctrl键。类似的还有KMOD_SHIFTKMOD_ALT
    • unicode – 代表了按下键的Unicode值

    事件过滤

    并不是所有的事件都需要处理。我们使用**pygame.event.set_blocked(type)来完成。如果有好多事件需要过滤,可以传递一个列表,比如pygame.event.set_blocked([KEYDOWN, KEYUP]),如果你设置参数None,那么所有的事件有被打开了。与之相对的,我们使用pygame.event.set_allowed()**来设定允许的事件。

    产生事件

    通常玩家做什么,Pygame就产生对应的事件就可以了,不过有的时候我们需要模拟出一些事件来,比如录像回放的时候,我们就要把用户的操作再现一遍。

    为了产生事件,必须先造一个出来,然后再传递它:

    my_event = pygame.event.Event(KEYDOWN, key=K_SPACE, mod=0, unicode=' ')
    # 你也可以像下面这样写
    my_event = pygame.event.Event(KEYDOWN, {"key":K_SPACE, "mod":0, "unicode":' '})
    pygame.event.post(my_event)
    

    Event():Event(type, dict) 或者 Event(type, **attributes),

    post(): 把新的事件放在事件队列的最后。

    也可以产生一个完全自定义的全新事件。

    import pygame
    from pygame.locals import *
    
    pygame.init()
    
    my_event = pygame.event.Event(KEYDOWN, key=K_SPACE, mod=0, unicode=' ')
    # my_event = pygame.event.Event(KEYDOWN,{"key":K_SPACE, "mod":0, "unicode":' '})
    pygame.event.post(my_event)
    
    ###############
    # 产生一个自定义的全新事件
    CATONKEYBOARD = USEREVENT + 1
    my_event = pygame.event.Event(CATONKEYBOARD, message="bad act!")
    pygame.event.post(my_event)
    # 获得这个事件
    for event in pygame.event.get():
        if event.type == CATONKEYBOARD:
            print( event.message)
    

    五、显示

    全屏显示

    在第一个例子“hello world”中,使用了如下语句

    screen = pygame.display.set_mode((640, 480), 0, 32)
    

    如果把第二个参数设置成FULLSCREEN,就会得到一个全屏显示的窗口。

    在全屏模式下,显卡可能就切换了一种模式,你可以用如下代码获得您的机器支持的显示模式

    >>> import pygame
    >>> pygame.init()
    >>> pygame.display.list_modes()
    

    接下来这个程序,按“f键实现全屏和窗口之间的切换。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = '../image/sushiplate.jpg'
    
    pygame.init()
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    
    Fullscreen = False
    
    while True:
    
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
        	if event.type == KEYDOWN:
            	if event.key == K_f:
                	Fullscreen = not Fullscreen
                	if Fullscreen:
                    	screen = pygame.display.set_mode((640, 480), FULLSCREEN, 32)
                	else:
                    	screen = pygame.display.set_mode((640, 480), 0, 32)
    
        screen.blit(background, (0, 0))
        pygame.display.update()
    

    改变窗口尺寸

    pygame的默认显示窗口是不支持拖动边框改变大小的,改变set_mode函数的参数后可以实现。

    screen = pygame.display.set_mode(SCREEN_SIZE, RESIZABLE, 32)
    
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = '../image/sushiplate.jpg'
    SCREEN_SIZE = (640, 480)
    
    pygame.init()
    screen = pygame.display.set_mode(SCREEN_SIZE, RESIZABLE, 32)
    
    background = pygame.image.load(background_image).convert()
    
    while True:
    
        event = pygame.event.wait()
        if event.type == QUIT:
            exit()
        if event.type == VIDEORESIZE:
            SCREEN_SIZE = event.size
            screen = pygame.display.set_mode(SCREEN_SIZE, RESIZABLE, 32)
            pygame.display.set_caption("Window resized to " + str(event.size))
    
        # 这里需要重新填满窗口
        screen_width, screen_height = SCREEN_SIZE
        for y in range(0, screen_height, background.get_height()):
            for x in range(0, screen_width, background.get_width()):
                screen.blit(background, (x, y))
    
        pygame.display.update()
    

    VIDEORESIZE 事件,它包含如下内容:

    • size — 一个二维元组,值为更改后的窗口尺寸,size[0]为宽,size[1]为高
    • w — 宽
    • h — 高

    复合模式

    screen = pygame.display.set_mode(SCREEN_SIZE, HWSURFACE | FULLSCREEN, 32)
    

    其他

    当使用OPENGL时,不能使用pygame.display.update()来更新窗口,而是pygame.display.flip()。

    flip和update的说明如下:

    flip.png

    update.png

    六、字体

    创建font对象

    Pygame可以直接调用系统字体,或者也可以使用TTF字体。

    1. SysFont(name, size, bold=False, italic=False)

      my_font = pygame.font.SysFont("arial", 16)
      

      第一个参数是字体名,第二个是大小。该函数返回一个系统字体,这个字体与“bold”和“italic”两个flag相匹配。如果找不到,就会使用pygame的默认字体。可以使用**pygame.font.get_fonts()**来获得当前系统所有可用字体。

    2. Font(filename, size) 或者Font(object, size)

      my_font = pygame.font.Font("simsun.ttf", 16)
      

      使用这个方法,需要把字体文件随同游戏一起发送,这样可以避免使用者机器上没有所需的字体

    使用字体

    render(text, antialias, color, background=None)

    text_surface = my_font.render("Pygame is cool!", True, (0,0,0), (255, 255, 255))
    

    第一个参数文字;第二个参数是个布尔值,表示是否开启抗锯齿,如果为True,字体会比较平滑,不过相应的速度有一点点影响;第三个参数是字体的颜色;第四个是背景色,如果你想没有背景色(也就是透明),就不加这第四个参数。

    中文字体

    下面这个例子演示了用pygame书写中文

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    pygame.init()
    screen = pygame.display.set_mode((640, 480), 0, 32)
    
    background_image = 'image/sushiplate.jpg'
    background = pygame.image.load(background_image).convert()
    
    # 以下两种方法都可以,第一种需要把字体文件复制到代码文件目录下
    font = pygame.font.Font("simsun.ttc", 40)
    # font = pygame.font.SysFont("simsunnsimsun", 40)
    
    text_surface = font.render("你好", True, (0, 0, 255))
    
    x = 0
    y = (480 - text_surface.get_height())/2
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
        screen.blit(background, (0, 0))
    
        x -= 1
        if x < -text_surface.get_width():
            x = 640 - text_surface.get_width()
    
        screen.blit(text_surface, (x, y))
    
        pygame.display.update()
    

    七、颜色

    一般的32位RGB,每个像素可以显示16.7百万种颜色。

    第一个例子,可以生成所有的颜色。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480))
    all_colors = pygame.Surface((4096, 4096), depth=24)
    
    for r in range(256):
        print(r + 1, "out of 256")
        x = (r & 15) * 256
        y = (r >> 4) * 256
        for g in range(256):
            for b in range(256):
                all_colors.set_at((x + g, y + b), (r, g, b))
    
    pygame.image.save(all_colors, "allcolors.bmp")
    

    第二个例子,用鼠标移动三个点,代表三原色的值,下方是三原色混合得到的结果。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    
    def create_scales(height):
        red_scale_surface = pygame.surface.Surface((640, height))
        green_scale_surface = pygame.surface.Surface((640, height))
        blue_scale_surface = pygame.surface.Surface((640, height))
        for x in range(640):
            c = int((x / 640) * 255)
            red = (c, 0, 0)
            green = (0, c, 0)
            blue = (0, 0, c)
            line_rect = Rect(x, 0, 1, height)
            pygame.draw.rect(red_scale_surface, red, line_rect)
            pygame.draw.rect(green_scale_surface, green, line_rect)
            pygame.draw.rect(blue_scale_surface, blue, line_rect)
        return red_scale_surface, green_scale_surface, blue_scale_surface
    
    
    red_scale, green_scale, blue_scale = create_scales(80)
    
    color = [127, 127, 127]
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        screen.fill((0, 0, 0))
    
        screen.blit(red_scale, (0, 0))
        screen.blit(green_scale, (0, 80))
        screen.blit(blue_scale, (0, 160))
    
        x, y = pygame.mouse.get_pos()
    
        if pygame.mouse.get_pressed()[0]:
            for component in range(3):
                if y > component * 80 and y < (component + 1) * 80:
                    color[component] = int((x / 639) * 255)
            pygame.display.set_caption("PyGame Color Test - " + str(tuple(color)))
    
        for component in range(3):
            pos = (int((color[component] / 255) * 639), component * 80 + 40)
            pygame.draw.circle(screen, (255, 255, 255), pos, 20)
    
        pygame.draw.rect(screen, tuple(color), (0, 240, 640, 240))
    
        pygame.display.update()
    

    八、图像

    使用Surface对象

    加载图片用pygame.image.load,返回一个Surface对象。事实上,屏幕也只是一个surface对象,pygame.display.set_mode返回一个屏幕的surface对象。

    创建Surface对象

    除了上面说的pygame.image.load外,还可以指定尺寸创建一个空的surface。

    >>> a = pygame.Surface((256,256))
    

    这个Surface对象是全黑的。除了大小外,Surface函数还有flags和depth两个参数。

    • HWSURFACE – creates the image in video memory
    • SRCALPHA – the pixel format will include a per-pixel alpha。创建有Alpha通道的surface,选择这个选项需要depth为32。
    alpha_surface = pygame.Surface((256,256), flags=SRCALPHA, depth=32)
    

    转换Surfaces

    convert(): Creates a new copy of the Surface with the pixel format changed. 当一个surface多次使用blit时,最好使用convert。转换后的surface没有alpha。

    convert_alpha(): change the pixel format of an image including per pixel alphas.

    矩形对象(Rectangle Objects)

    pygame中有Rect类,用来存储和处理矩形对象(包含在pygame.locals)中。

    Rect(left, top, width, height)

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

    有了Rect对象之后,可以对其做很多操作,例如调整大小、位置,判断一个点是否在其中等。

    剪裁(Clipping)

    surface中有裁剪区域(clip area),是一个矩形,定义了哪部分会被绘制,即若定义了这个区域,只有这个区域内的像素会被修改。

    set_clip(screen_rect=None): 设定区域,当参数为None时,重置。一个surface对象默认的剪裁区域为这个surface。

    get_clip() : 得到剪裁区域,返回一个Rect对象。

    子表面(Subsurfaces)

    Subsurfaces是在一个surface中再提取出一个surface。当在subsurface上操作时,同时也向父表面上操作。这可以用来绘制图形文字,比如吧文字变成多种颜色。把整张图读入后,用subsurface将每个字分隔开。

    my_font_image = Pygame.load("font.png")
    letters = []
    letters["a"] = my_font_image.subsurface((0,0), (80,80))
    letters["b"] = my_font_image.subsurface((80,0), (80,80))
    

    填充Surface

    fill(color, rect=None, special_flags=0)

    当rect参数为默认参数时,整个surface都会被填充。color参数可以为RGB或者RGBA。如果使用RGBA,除非surface有alpha通道(使用了SRCALPHA flag),否则RGBA的Alpha会被忽略。

    设置Surface的像素

    set_at((x, y), Color) : 设置单个像素的颜色

    get_at((x, y)) : 得到单个像素的颜色

    锁定Surface

    当对像素进行读或写操作时,surface会被锁定。一个锁定的surface,经常不能被显示或被pygame操作,所以除非必要,在手动lock之后不要忘了unlock。

    所有pygame的函数如过需要锁定和解锁,这些操作时自动发生的。如果不想发生自动的lock和unlock(有些时候为了提高效率),可以在一些会造成自动锁定和解锁的语句前后注释掉这两句。

    import pygame
    from pygame.locals import *
    from sys import exit
    from random import randint
    
    pygame.init()
    screen = pygame.display.set_mode((640, 480), 0, 32)
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        rand_col = (randint(0, 255), randint(0, 255), randint(0, 255))
    
        # screen.lock)()
        for _ in range(100):
            rand_pos = (randint(0, 639), randint(0, 479))
            screen.set_at(rand_pos, rand_col)
        # screen.unlock()
        pygame.display.update()
    

    blit

    blit(source, dest, area=None, special_flags = 0)

    将源图像画到目标位置,dest可以为一个点,也可以是一个矩形,但只有矩形的左上角会被使用,矩形的大小不会造成影响。

    area参数可以指定源图像中的一部分被画到目标位置。

    九、绘制各种图形

    pygame使用pygame.draw来绘制图形。其包含以下几种函数。

    函数作用用法
    rect绘制矩形rect(Surface, color, Rect, width=0)
    polygon绘制多边形polygon(Surface, color, pointlist, width=0)
    circle绘制圆circle(Surface, color, pos, radius, width=0)
    ellipse绘制椭圆ellipse(Surface, color, Rect, width=0)
    arc绘制圆弧arc(Surface, color, Rect, start_angle, stop_angle, width=1)
    line绘制线line(Surface, color, start_pos, end_pos, width=1)
    lines绘制一系列的线lines(Surface, color, closed, pointlist, width=1)
    aaline绘制一根平滑的线aaline(Surface, color, startpos, endpos, blend=1)
    aalines绘制一系列平滑的线aalines(Surface, color, closed, pointlist, blend=1)

    一些说明

    • width参数:width参数为0或省略,则填充。

    • 画填充的矩形,有另一个方法Surface.fill(),事实上,这种方法速度更快。

    • lines函数的closed为一个布尔变量,如果closed为真,则会画一条连接第一个和最后一个点的线,是整个图形闭合。

    十、运动

    直线运动

    下面这个程序让“hello world”程序中的鱼动起来。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    
    # sprite的起始坐标
    x = 0
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        screen.blit(background, (0, 0))
        screen.blit(sprite, (x, 100))
        x += 1
    
        if x>640:
            x = 0
    
        pygame.display.update()
    

    时间

    在上面的程序中,帧率是很高的。而且电脑的性能不同,鱼的速度就会不同,如果动画的的元素很多,速度就会下降。

    为了解决这个问题,可以使用pygame的时间模块。

    clock = pygame.time.Clock()
    time_passed = clock.tick()
    time_passed = clock.tick(30)
    

    第一行初始化了一个Clock对象。第二行返回了距上一次调用这个函数,过去了多长时间(注意,得到的值是以毫秒为单位的)。第三行,在函数中添加了framerate参数,这个函数会延时使得游戏的帧率不会超过给定值。

    给定的值仅仅是最大帧率,当动作复杂或机器性能不足时,实际帧率无法达到这个值,需要一种手段控制动画效果。比如给吾提一个恒定的速度,再通过时间,计算出移动的距离。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    
    # clock对象
    clock = pygame.time.Clock()
    
    x = 0
    speed = 250
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        screen.blit(background, (0, 0))
        screen.blit(sprite, (x, 100))
    
        time_passed = clock.tick()
        time_passed_seconds = time_passed/1000
    
        distance_moved = time_passed_seconds * speed
        x += distance_moved
    
        if x > 640:
            x -= 640
    
        pygame.display.update()
    

    斜线运动

    接下来这个程序,使得物体斜线运动并且触边反弹。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    
    clock = pygame.time.Clock()
    x, y = 100, 100
    speed_x, speed_y = 133, 170
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        screen.blit(background, (0, 0))
        screen.blit(sprite, (x, y))
    
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed/1000
        x += speed_x * time_passed_seconds
        y += speed_y * time_passed_seconds
    
        # 到达边界后速度反向
        if x > 640 - sprite.get_width():
            speed_x = -speed_x
            x = 640 - sprite.get_width()
        elif x < 0:
            speed_x = -speed_x
            x = 0
    
        if y > 480 - sprite.get_height():
            speed_y = -speed_y
            y = 480 - sprite.get_height()
        elif y < 0:
            speed_y = -speed_y
            y = 0
    
        pygame.display.update()
    

    向量

    下面这个例子,使用向量代替之前的x和y的计算,实现了鱼在鼠标周围游动的效果。

    使用向量类来存储和计算向量。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    from vector import Vec2d
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    
    clock = pygame.time.Clock()
    
    position = Vec2d(100, 100)
    heading = Vec2d((0, 0))
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        screen.blit(background, (0, 0))
        screen.blit(sprite, position)
    
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed/1000
    
        # 在参数前面加*意味着把列表或元组展开
        destination = Vec2d(*pygame.mouse.get_pos()) - Vec2d(*sprite.get_size())/2
        # 计算当鱼儿当前位置到鼠标位置的向量
        vector_to_mouse = Vec2d.__sub__(destination, position)
        vector_to_mouse.normalized()
    
        # heading可以看做是鱼的速度,鱼的速度大小、方向不断改变
        heading = heading + (vector_to_mouse * 0.1)
        position += heading * time_passed_seconds
    
        pygame.display.update()
    

    十一、用户输入

    键盘输入

    在之前的例子中使用过键盘输入,使用pygame.event.get()获取所有事件,当event.type==KEYDOWN时,再判断event.key的种类。也可以使用pygame.key.get_pressed()来获取所有按下的键值,它会返回一个元组,这个元祖的索引就是键值,对应的值为True就是按下。

    但是,如果要处理文本输入,这个函数不是正确的方法。因为我们不知道按键被按下的顺序。

    key模块下还有如下的函数:

    • key.get_focused —— 返回当前的pygame窗口是否激活

    • key.get_mods —— 按下的组合键(Alt, Ctrl, Shift)

      if pygame.key.get_mods() & KMOD_SHIFT:
      
    • key.set_mods —— 你也可以模拟按下组合键的效果(KMOD_ALT, KMOD_CTRL, KMOD_SHIFT)

    • key.set_repeat —— 参数为(delay,interval)。当有参数时,即repeat被激活时,被按住的键会产生多次KEYDOWN事件。第一次发送KEYDOWN事件后,经过delay时间(ms)发送第二次,然后每隔interval时间(ms)发送一次事件。如果没有参数,不产生重复按键事件。当pygame初始化之后,重复按键默认为disabled

    • key.name —— 接受键值返回键名

    使用键盘控制方向

    下面这个例子使用ASDW控制方向。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    from vector import Vec2d
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    clock = pygame.time.Clock()
    sprite_pos = Vec2d(200, 150)
    sprite_speed = 300
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    
        pressed_keys = pygame.key.get_pressed()
        key_direction = Vec2d(0, 0)
        if pressed_keys[K_LEFT]:
            key_direction.x = -1
        elif pressed_keys[K_RIGHT]:
            key_direction.x = +1
        if pressed_keys[K_UP]:
            key_direction.y = -1
        elif pressed_keys[K_DOWN]:
            key_direction.y = +1
        key_direction.normalized()
    
        screen.blit(background, (0, 0))
        screen.blit(sprite, sprite_pos)
    
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed/1000
        sprite_pos += key_direction * sprite_speed * time_passed_seconds
    
        pygame.display.update()
    

    接下来这个例子,使鱼做到全方位移动。先转向,再移动。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    from vector import Vec2d
    from math import *
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    clock = pygame.time.Clock()
    sprite_pos = Vec2d(200, 150)
    sprite_speed = 300
    sprite_rotation = 0
    sprite_rotation_speed = 360
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
        pressed_keys = pygame.key.get_pressed()
        rotation_direction = 0
        movement_direction = 0
    
        # 更改角度
        if pressed_keys[K_LEFT]:
            rotation_direction = +1
        elif pressed_keys[K_RIGHT]:
            rotation_direction = -1
        # 前进、后退
        if pressed_keys[K_UP]:
            movement_direction = +1.
        if pressed_keys[K_DOWN]:
            movement_direction = -1.
    
        screen.blit(background, (0, 0))
        # 将鱼转向
        rotated_sprite = pygame.transform.rotate(sprite, sprite_rotation)
        # 转向后,图片的长宽会变化,因为图片永远是矩形,为了放得下一个转向后的矩形,外接的矩形势必会比较大
        w, h = rotated_sprite.get_size()
        sprite_draw_pos = Vec2d(sprite_pos.x - w / 2, sprite_pos.y - h / 2)
        screen.blit(rotated_sprite, sprite_draw_pos)
    
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed/1000
    
        # 图片的转向速度也通过时间来
        控制
        sprite_rotation += rotation_direction * sprite_rotation_speed * time_passed_seconds
    
        # 获得前进(x方向和y方向)
        heading_x = sin(sprite_rotation * pi / 180)
        heading_y = cos(sprite_rotation * pi / 180)
        # 转换为单位速度向量
        heading = Vec2d(heading_x, heading_y)
        # 转换为速度
        heading *= movement_direction
        sprite_pos += heading * sprite_speed * time_passed_seconds
    
        pygame.display.update()
    

    鼠标控制

    我们可以从MOUSEMOTION和pygame.mouse.get_pos()获得鼠标坐标。我们可以使用这个坐标来控制方向,如使用鼠标的偏移量来控制视角。在接下来的这个例子中,使用鼠标左右移动来转动鱼。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pygame
    from pygame.locals import *
    from sys import exit
    from vector import Vec2d
    from math import *
    
    background_image = '../image/sushiplate.jpg'
    sprite_image = '../image/fugu.png'
    
    pygame.init()
    
    screen = pygame.display.set_mode((640, 480), 0, 32)
    background = pygame.image.load(background_image).convert()
    sprite = pygame.image.load(sprite_image)
    clock = pygame.time.Clock()
    
    pygame.mouse.set_visible(False)
    # 使所有的输入都锁定在这个程序中
    pygame.event.set_grab(True)
    
    sprite_pos = Vec2d(200, 150)
    sprite_speed = 300
    sprite_rotation = 0
    sprite_rotation_speed = 360
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            # 按Esc,退出游戏
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exit()
    
        pressed_keys = pygame.key.get_pressed()
        pressed_mouse = pygame.mouse.get_pressed()
    
        rotation_direction = 0
        movement_direction = 0
        # 得到鼠标的偏移量(x, y)
        rotation_direction = pygame.mouse.get_rel()[0]/5
    
        if pressed_keys[K_LEFT]:
            rotation_direction = -1
        elif pressed_keys[K_RIGHT]:
            rotation_direction = +1
        if pressed_keys[K_UP] or pressed_mouse[0]:
            movement_direction = -1
        if pressed_keys[K_DOWN] or pressed_mouse[2]:
            movement_direction = +1
    
        screen.blit(background, (0, 0))
        rotated_sprite = pygame.transform.rotate(sprite, sprite_rotation)
        w, h = rotated_sprite.get_size()
        sprite_draw_pos = Vec2d(sprite_pos.x - w / 2, sprite_pos.y - h / 2)
        screen.blit(rotated_sprite, sprite_draw_pos)
    
        time_passed = clock.tick(30)
        time_passed_seconds = time_passed/1000
    
        sprite_rotation += rotation_direction * sprite_rotation_speed * time_passed_seconds
    
        heading_x = sin(sprite_rotation * pi / 180)
        heading_y = cos(sprite_rotation * pi / 180)
        heading = Vec2d(heading_x, heading_y)
        heading *= movement_direction
    
        sprite_pos += heading * sprite_speed * time_passed_seconds
    
        pygame.display.update()
    

    pygame.mouse的函数:

    • pygame.mouse.get_pressed —— 返回按键按下情况,返回的是一元组,分别为(左键, 中键, 右键),如按下则为True

    • pygame.mouse.get_rel —— 返回相对偏移量,(x方向, y方向)的一元组

    • pygame.mouse.get_pos —— 返回当前鼠标位置(x, y)

    • pygame.mouse.set_pos —— 设置鼠标位置

    • pygame.mouse.set_visible —— 设置鼠标光标是否可见

    • pygame.mouse.get_focused —— 检查窗口是否接受鼠标事件,即鼠标是否focus到窗口

    • pygame.mouse.set_cursor —— 设置鼠标光标式样

    • pyGame.mouse.get_cursor ——得到鼠标图片

    版本信息

    1.0 20180209

    展开全文
  • Pygame研究:学习Pygame
  • pygame 欢迎使用pygame的文档!
  • Python-with-PyGame PyGame
  • pygame参考

    2018-06-30 22:39:54
    pygame参考书籍【扫描版】,有兴趣的小伙伴可以阅读下
  • pygame飞机大战

    2021-01-20 02:51:12
    这是我python的pygame库编的一个小游戏,只要一发子弹不打中两架敌机就没有bug。打开时请使用cmd或dos等终端打开。 以下是源代码: import pygame import random import math #初始化界面 pygame.init() pygame....
  • Pygame 官方文档 - pygame

    千次阅读 2019-02-28 12:37:29
    pygame Pygame 最顶层的包。 pygame.init — 初始化所有导入的 pygame 模块 pygame.quit — 卸载所有导入的 pygame 模块 pygame.error — 标准 pygame 异常模块 pygame.get_error — 获得当前错误信息 pygame.set_...
  • pygame安装包

    2017-10-20 22:15:03
    pygame安装包, 版本为1.9.3,64位, 支持python3.4-3.6
  • pygamepygame模块

    千次阅读 2018-06-07 14:56:08
    pygame-最顶层的Pygame模块pygame.init—初始化所有导入的pygame模块pygame.quit—卸载掉导入的pygame模块pygame.error—标准pygame异常pygame.get_error—得到当前的错误信息pygame.set_error—设置当前的错误信息...
  • pygame教程

    2018-07-07 16:14:53
    收集的pygame学习手册,大力感谢原博主~~~~~~~~~~~~~~~~~~~~~~~~~
  • 主要为大家详细介绍了pygame游戏之旅,分享python和pygame的安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Pygame是跨平台Pyth,Pygame 作者是 Pete Shinners, 协议为 GNU Lesser General Public License。
  • PyGame项目 用蛇学习PyGame 刚开始玩PyGame,和朋友一起玩
  • 使用python和pygame开发的游戏 使用运行python rpg.py 为了运行代码,您需要安装pygame框架: sudo pip install pygame
  • pygame 使用pygame的游戏小程序
  • 3D_pygame3D_Pygame_3d_源码

    2021-10-03 12:36:57
    由Python语言,基于模块pygame开发的简易3D引擎
  • pygame安装(超级详细)

    万次阅读 多人点赞 2019-03-17 15:09:34
    安装时是需要设置python环境变量的,下载python的时候底下有个小框框(没有默认选中) Add Python 3.7 to PATH需要选择的,如果没有选择的话,需要自己设置,我一般比较懒,卸载了python重新下载的,让下载器自动...
  • Pygame学习笔记:https://pan.baidu.com/s/1-042vCw-Imp_yDfm7UOu9Q 密码:8chr ...pygame.init() # 导入并初始化所有pygame模块 # 编写游戏的代码 print("游戏的代码...") pygame.quit() # 卸载所有p...
  • pygame物理学 使用Pygame进行简单的物理模拟 的Python:3.5+ pygame:pip安装pygame 欧拉积分器 使用Euler积分器的弹丸运动 质量和弹簧系统 Verlet积分器 使用Verlet积分器的简单布料模拟
  • pygame小行星 此回购包含一组步骤,可通过简单的步骤从0到小行星。 创建一个可以关闭的pygame屏幕。 在屏幕上添加一个播放器。 让玩家移动。 小行星与子弹 计分和文字 步骤0:安装Pygame 视窗 确保您具有NON-64...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,537
精华内容 14,214
关键字:

pygame