赞
踩
Pygame 是一组用来开发游戏软件的 Python 程序模块,Pygame 在 SDL(Simple DirectMedia Layer) 的基础上开发而成。它提供了诸多操作模块,比如图像模块(image)、声音模块(mixer)、输入/输出(鼠标、键盘、显示屏)模块,擅长开发 2D 游戏,Python 也提供了开发 3D 游戏的软件包,比如 Pyglet、Panda3D、PyOgre 等。Pygame 是一个高可移植性的模块可以支持多个操作系统。用它来开发小游戏非常适合。官网https://www.pygame.org/news
若使用pygame模块(python的2D游戏开发库),这是第三方(扩展)模块,若未预先装,需要在CMD中,使用 pip install pygame 先装入,可能需要花点时间。
查看是否电脑上是否有pygame,在CMD中,使用pip list命令,参见下图
若没有 pygame,需要在CMD中,使用 pip install pygame 命令安装,参见下图:
【关于安装安装第三方库的更多情况,可参见:https://blog.csdn.net/cnds123/article/details/104393385】
验证是否成功安装
法一、在CMD中,使用python -m pygame.examples.aliens命令验证,参见下图:
法二、进入Python的交互界面,输入以下命令验证是否成功安装,参见下图:
不报错,则说明安装成功。
Pygame的坐标原点(0,0)点位于左上角,X轴自左向右,Y轴自上向下,单位为像素,参见下图:
在游戏中,所有可见的元素都是以矩形区域来描述位置的;
pygame专门提供了一个类Rect 用于 描述矩形区域,格式:
Rect(x,y,width,height)
Pygame的Rect对象,表示的区域必须位于一个 Surface 对象之上,比如游戏的主窗口(screen)。上述方法由四个关键参数值构成,分别是 left、top、width、height
pygame. Rect(left, top, width, height)
display 用于创建、管理游戏窗口
pygame.display.set_mode() #初始化游戏显示窗口
pygame.dispaly.update() #刷新屏幕内容显示,稍后使用
为了做到游戏程序启动后,不会立即退出,通常会在游戏程序中使用一个游戏循环。
pygame开发游戏的大体框架结构如下:
import pygame
# 初始化pygame
pygame.init()
# 创建游戏的窗口 350 * 573(宽,高);注意:此窗口的大小是依据游戏的背景图片而设定的
screen=pygame.display.set_mode((350,600))
# 游戏循环
while True:
pass
示例代码如下:
- # 导入所需的模块
- import pygame
- import sys
- # 导入所有pygame.locals里的变量(比如下面大写的QUIT变量)
- from pygame.locals import *
-
- # 初始化pygame
- pygame.init()
-
- # 设置窗口的大小,单位为像素
- screen = pygame.display.set_mode((450, 300))
-
- # 设置窗口标题
- pygame.display.set_caption('Hello World')
-
- # 程序主循环
- while True:
-
- # 获取事件
- for event in pygame.event.get():
- # 判断事件是否为退出事件
- if event.type == QUIT:
- # 退出pygame
- pygame.quit()
- # 退出系统
- sys.exit()
-
- # 绘制屏幕内容
- pygame.display.update()
-

运行之,显示如下:
#设置窗口图标,下面两句
icon = pygame.image.load("./images/xyicon.png") # 加载图像数据
pygame.display.set_icon(icon) #设置图标
#设置窗口背景图片,下面三两句
bg = pygame.image.load("./images/background.png") # 加载图像数据
screen.blit(bg,(0,0)) #绘制图像 blit(图像,位置);
pygame.display.update() #更新屏幕显示
在前面示例代码,设置窗口标题之后,添加设置窗口图标和设置窗口背景图片:
运行之,如下图所示:
有两个方法:
☆播放特效声音:
pygame.mixer.Sound(filename)
该方法返回一个Sound对象,调用它的.play( )方法,即可播放较短的音频文件(如游戏中的枪炮声等);
☆播放背景音乐:
pygame.mixer.music.load(filename)
该方法用来加载背景音乐,之后调用pygame.mixer.music.play( )方法就可以播放背景音乐(在同一个时刻只允许加载一个背景音乐)
# 加载并播放一个特效音频文件)
sound = pygame.mixer.Sound('./music/alter.mp3')
sound.play()
# 加载背景音乐文件
pygame.mixer.music.load('./music/bgmusic.mp3')
# 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
pygame.mixer.music.play(-1, 0.0)
可以在适当的地方,作为测试在背景图片之后插入播放音频代码段,当然音频文件需要准备好。
Pygame绘制图形的常用的方法:
☆ pygame.draw.line(Surface, color, start_pos, end_pos, width)此方法用于绘制一条线段
☆ pygame.draw.aaline(Surface, color, start_pos, end_pos, blend)此方法用于绘制一条抗锯齿的线
☆ pygame.draw.lines(Surface, color, closed, pointlist, width)此方法用于绘制一条折线
☆ pygame.draw.rect(Surface, color, Rect)此方法用于绘制一个矩形
☆ pygame.draw.rect(Surface, color, Rect, width)此方法用于绘制一个矩形框
☆ pygame.draw.ellipse(Surface, color, Rect)此方法用于绘制一个椭圆
☆ pygame.draw.ellipse(Surface, color, Rect, width)此方法用于绘制一个椭圆框
☆ pygame.draw.polygon(Surface, color, pointlist, width)此方法用于绘制一个多边形
☆ pygame.draw.arc(Surface, color, Rect, start_angle, stop_angle, width)此方法用于绘制一条弧线
☆ pygame.draw.circle(Surface, color, Rect, radius)此方法用于绘制一个圆
示例代码
- # 导入需要的模块
- import pygame, sys
- from pygame.locals import *
- from math import pi
-
- # 初始化pygame
- pygame.init()
-
- # 设置窗口的大小,单位为像素
- screen = pygame.display.set_mode((400,300))
-
- # 设置窗口标题
- pygame.display.set_caption('Drawing')
-
- # 定义颜色
- BLACK = ( 0, 0, 0)
- WHITE = (255, 255, 255)
- RED = (255, 0, 0)
- GREEN = ( 0, 255, 0)
- BLUE = ( 0, 0, 255)
-
- # 设置背景颜色
- screen.fill(WHITE)
-
- # 绘制一条线
- pygame.draw.line(screen, GREEN, [10, 10], [50,30], 5)
-
- # 绘制一条抗锯齿的线
- pygame.draw.aaline(screen, GREEN, [10, 50],[50, 80],True)
-
- # 绘制一条折线
- pygame.draw.lines(screen, BLACK, False,[[10, 80], [50, 90], [200, 80], [220, 30]], 5)
-
- # 绘制一个空心矩形
- pygame.draw.rect(screen, BLACK, [75, 10, 50, 20], 2)
-
- # 绘制一个矩形
- pygame.draw.rect(screen, BLACK, [150, 10, 50, 20])
-
- # 绘制一个空心椭圆
- pygame.draw.ellipse(screen, RED, [225, 10, 50, 20], 2)
-
- # 绘制一个椭圆
- pygame.draw.ellipse(screen, RED, [300, 10, 50, 20])
-
- # 绘制多边形
- pygame.draw.polygon(screen, BLACK, [[100, 100], [0, 200], [200, 200]], 5)
-
- # 绘制多条弧线
- pygame.draw.arc(screen, BLACK,[210, 75, 150, 125], 0, pi/2, 2)
- pygame.draw.arc(screen, GREEN,[210, 75, 150, 125], pi/2, pi, 2)
- pygame.draw.arc(screen, BLUE, [210, 75, 150, 125], pi,3*pi/2, 2)
- pygame.draw.arc(screen, RED, [210, 75, 150, 125], 3*pi/2, 2*pi, 2)
-
- # 绘制一个圆
- pygame.draw.circle(screen, BLUE, [60, 250], 40)
-
- # 程序主循环
- while True:
-
- # 获取事件
- for event in pygame.event.get():
- # 判断事件是否为退出事件
- if event.type == QUIT:
- # 退出pygame
- pygame.quit()
- # 退出系统
- sys.exit()
-
- # 绘制屏幕内容
- pygame.display.update()
-

运行之,显示如下:
Pygame不仅可以在屏幕上绘制形状,还可以将文本绘制到屏幕上。Pygame 提供了一些非常简单易用的函数,可以创建字体和文本。字体(font)是字体类型的一种描述,表示按照统一风格绘制的一整套的字母、数字、符号和字符,例如 宋体 和 Times New Roman 都是字体。
☆font.SysFont()函数来创建一个 Font 对象,这个函数有两个参数,第 1 个参数是字体名称,第 2 个参数是字体大小(以像素点为单位)
☆font.render()函数的参数:第 1 个参数是要绘制的文本的字符串;第 2 个参数指定是否想要抗锯齿的一个 Boolean 值,如果是 True,文本看上去更加平滑一些;第 3 个参数是用来渲染文本的颜色,这个例子中使用的是白色。
☆blit() 函数,将像素从一个 Surface 复制到另一个 Surface 之上。常用两个参数:第一个参数是某矩形图像(Surface实例),第二个参数用于指定绘制的位置。
示例代码
- import pygame
- import sys
- from pygame.locals import *
-
- pygame.init()
- wS=pygame.display.set_mode((400,300)) #创建画布名称wS
- WHITE=(255,255,255)
- myString="Hello World!"
- font = pygame.font.SysFont("Times New Roman", 48) #来创建 Font对象
- text = font.render(myString, True, WHITE)
- wS.blit(text, (100,150)) #将text复制到指定位置(100,150)
-
- # 程序主循环
- while True:
-
- # 获取事件
- for event in pygame.event.get():
- # 判断事件是否为退出事件
- if event.type == QUIT:
- # 退出pygame
- pygame.quit()
- # 退出系统
- sys.exit()
-
- # 绘制屏幕内容
- pygame.display.update()
-

运行之,显示如下:
Pygame实现动画
由于人类眼睛的特殊生理结构,当所看画面的帧率高于24的时候,就会认为是连贯的。
帧率(Frame rate)是用于测量显示帧数的量度,所谓的测量单位为每秒显示帧数(Frames per Second,简称:FPS)。
在原有坐标系的基础上添加偏移量,再重新绘制,依次一张一张的循环绘制下去,就会得到我们想要的物体移动的效果。
Pygame实现动画主要用到的方法:
☆ pygame.image.load(filename) 加载一张图片
☆pygame.Surface.blit(source, dest, area=None, special_flags = 0) 将图片绘制到屏幕相应坐标上(后面两个参数默认,可以不传)
☆pygame.time.Clock() 获得pygame的时钟
☆pygame.time.Clock.tick(FPS) 设置pygame时钟的间隔时间
示例代码如下:
- # 导入需要的模块
- import pygame, sys
- from pygame.locals import *
-
- # 初始化pygame
- pygame.init()
-
- # 设置帧率(屏幕每秒刷新的次数)
- FPS = 30
-
- # 获得pygame的时钟
- fpsClock = pygame.time.Clock()
-
- # 设置窗口大小
- screen = pygame.display.set_mode((500, 400), 0, 32)
-
- # 设置标题
- pygame.display.set_caption('Animation')
-
- # 定义颜色
- WHITE = (255, 255, 255)
-
- # 加载一张图片
- img = pygame.image.load('./images/bird.png')
-
- # 初始化图片的位置
- imgx = 10
- imgy = 10
-
- # 初始化图片的移动方向
- direction = 'right'
-
- # 程序主循环
- while True:
-
- # 每次都要重新绘制背景白色
- screen.fill(WHITE)
-
- # 判断移动的方向,并对相应的坐标做加减
- if direction == 'right':
- imgx += 5
- if imgx == 380:
- direction = 'down'
- elif direction == 'down':
- imgy += 5
- if imgy == 300:
- direction = 'left'
- elif direction == 'left':
- imgx -= 5
- if imgx == 10:
- direction = 'up'
- elif direction == 'up':
- imgy -= 5
- if imgy == 10:
- direction = 'right'
-
- # 该方法将用于图片绘制到相应的坐标中
- screen.blit(img, (imgx, imgy))
-
- for event in pygame.event.get():
- if event.type == QUIT:
- pygame.quit()
- sys.exit()
-
- # 刷新屏幕
- pygame.display.update()
-
- # 设置pygame时钟的间隔时间
- fpsClock.tick(FPS)

pygame事件可以处理游戏中的各种事情,事件是一个概念,比如点击鼠标左键,按下一个键盘的按键,关闭窗口等等都是一个事件,pygame提供了一个函数来获取游戏的事件,并把他们存放在一个队列中,程序通过读取整个事件队列,来获取当前发生的时间,并作出响应。
Pygame常用的事件如下表:
事件 | 产生途径 | 参数 |
QUIT | 用户按下关闭按钮 | none |
ACTIVEEVENT | Pygame被激活或者隐藏 | gain, state |
KEYDOWN | 键盘被按下 | unicode, key, mod |
KEYUP | 键盘被放开 | key, mod |
MOUSEMOTION | 鼠标移动 | pos, rel, buttons |
MOUSEBUTTONDOWN | 鼠标按下 | pos, button |
MOUSEBUTTONUP | 鼠标放开 | pos, button |
VIDEORESIZE | Pygame窗口缩放 | size, w, h |
示例代码:
- # 导入需要的模块
- import pygame, sys
- from pygame.locals import *
-
- # 定义颜色
- WHITE = (255, 255, 255)
-
- # 初始化pygame
- pygame.init()
-
- # 设置窗口的大小,单位为像素
- screen = pygame.display.set_mode((500,400), 0, 32)
-
- # 设置窗口的标题
- pygame.display.set_caption('Event')
-
- # 设置背景
- screen.fill(WHITE)
-
- # 程序主循环
- while True:
-
- # 获取事件
- for event in pygame.event.get():
- # 判断事件是否为退出事件
- if event.type == QUIT:
- # 退出pygame
- pygame.quit()
- # 退出系统
- sys.exit()
-
-
- # 获得鼠标按下的位置
- 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("右")
- # 按下键盘的Esc键退出
- if(event.key==K_ESCAPE):
- # 退出pygame
- pygame.quit()
- # 退出系统
- sys.exit()
-
- # 绘制屏幕内容
- pygame.display.update()
-

效果图如下:
下面给出综合例子
先给出效果图:
源码如下:
- import pygame
- import sys
-
- # 初始化pygame
- pygame.init()
-
- # 设置窗口尺寸
- width, height = 861, 594
- screen = pygame.display.set_mode((width, height))
- pygame.display.set_caption('画图')
-
- # 定义颜色
- WHITE = (255, 255, 255)
- ORANGE = (255, 165, 0)
- BROWN = (165, 42, 42)
- GREEN = (0, 128, 0)
- RED = (255, 0, 0)
- GRAY = (128, 128, 128)
-
- # 绘制背景
- screen.fill(WHITE)
-
- # 画房子
- pygame.draw.polygon(screen, GRAY, [(150, 300), (350, 300), (250, 200)]) # 房子的屋顶
- pygame.draw.polygon(screen, ORANGE, [(150, 400), (350, 400), (350, 300), (150, 300)]) # 房子的底部
-
- # 画房子的门和窗户
- pygame.draw.rect(screen, WHITE, (180, 350, 30, 30)) # 窗户1
- pygame.draw.rect(screen, WHITE, (230, 350, 40, 50)) # 门
- pygame.draw.rect(screen, WHITE, (290, 350, 30, 30)) # 窗户2
-
- # 画树1
- pygame.draw.rect(screen, BROWN, (400, 300, 20, 100)) # 树干
- pygame.draw.circle(screen, GREEN, (410, 250), 50) # 树冠
-
- # 画树2
- pygame.draw.rect(screen, BROWN, (560, 300, 40, 150)) # 绘制树干
- # 绘制树冠
- pygame.draw.circle(screen, GREEN, (550, 250), 50)
- pygame.draw.circle(screen, GREEN, (620, 250), 50)
- pygame.draw.circle(screen, GREEN, (590, 220), 50)
- pygame.draw.circle(screen, GREEN, (560, 280), 50)
- pygame.draw.circle(screen, GREEN, (610, 280), 50)
-
- # 画太阳
- pygame.draw.circle(screen, RED, (650, 50), 25) # 太阳
-
- # 刷新屏幕
- pygame.display.flip()
-
- # 保持窗口打开
- while True:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- pygame.quit()
- sys.exit()

需要两个素材文件:小猫图片 cat.png 和背景图片bg1.jpg,为简便将它们 和源码程序文件,放在同一文件夹中。
源码如下:
- import sys
- import pygame
- from pygame.locals import *
-
- def control_ball(event):
- speed = [x,y] =[0,0]# 设置相对位移
- speed_offset = 1 #小球的速度
-
- # 如果事件的类型是 键盘输入,就根据方向键来求出速度的方向(默认是从左往右为1,从上往下为1)
- if event.type == KEYDOWN:
- if event.key == pygame.K_LEFT:
- speed[0] -= speed_offset
- event.key
-
- if event.key == pygame.K_RIGHT:
- speed[0] = speed_offset
- event.key
-
- if event.key == pygame.K_UP:
- speed[1] -= speed_offset
- event.key
-
- if event.key == pygame.K_DOWN:
- speed[1] = speed_offset
- event.key
-
- #如果没有方向键的输入,则速度为0,小球不动
- if event.type in (pygame.K_UP, pygame.K_LEFT, pygame.K_RIGHT, pygame.K_DOWN):
- speed = [0,0]
-
- return speed
-
- #定义函数
- def play_ball():
- pygame.init()#初始化
- window_size = Rect(0,0,600,440)#设置窗口的大小
-
- screen = pygame.display.set_mode(window_size.size)#设置窗口模式
- pygame.display.set_caption('hello cat')#设置窗口标题
- ball_image = pygame.image.load('cat.png')#载入小球图片
- back_image = pygame.image.load('bg1.jpg')#载入背景图片
- ball_rect = ball_image.get_rect()# 获取小球图片所在的区域
-
- while True:
- #退出事件的处理
- for event in pygame.event.get():
- if event.type == QUIT:
- pygame.quit()
- sys.exit()
-
- control_speed = control_ball(event)#获取到小球的方向
- ball_rect = ball_rect.move(control_speed).clamp(window_size)#小球按照方向移动,并且不会移出窗口。
-
- screen.blit(back_image,(0,0))#设置窗口背景,位于(0,0)处,窗口左上角。
- screen.blit(ball_image, ball_rect)#把小球绘制到背景surface上。
-
- pygame.display.flip()#更新窗口内容
-
- #调用函数
- play_ball()
-

两种实现:点击交换式和拖动交换式
★拼图游戏之点击交换式
加载一张图片分块打乱,用户用鼠标单击两块图片则两块图片交换位置,拼图完成后提示成功。确保图像文件存在并与代码中指定的路径相匹配——我这里图片名是player.png,和源码文件放在同一文件夹中。
源码如下:
- import random
- from sys import exit # 使用sys模块的exit函数来退出游戏
- import pygame
- from pygame.locals import * # 导入一些常用的函数和常量
- from tkinter import messagebox #导入messagebox模块
-
- SCREEN_WIDTH = 600
- SCREEN_HEIGHT = 600
- ROW = 0
- COL = 0
- CELL_WIDTH = 0 #SCREEN_WIDTH / COL
- CELL_HEIGHT = 0 #SCREEN_HEIGHT / ROW
-
- firstClickCell = None
-
- # 标记是否游戏成功
- successFlag = False
-
- gamePictures='player.png' ##游戏图片##
-
- pygame.init() # 初始化pygame
- screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 创建了一个窗口 大小是(宽,高)
- pygame.display.set_caption('单击交换式拼图') # 设置窗口标题
-
- scaled_image =pygame.transform.scale(pygame.image.load(gamePictures), (SCREEN_WIDTH//6, SCREEN_HEIGHT//6)) #加载原始图片缩小
-
- GREEN = (0, 255, 0)
- BLUE = (0, 0, 255)
- RED = (255, 0, 0)
- WHITE = (255, 255, 255)
- myfont = pygame.font.SysFont('KaiTi', 60) #None系统默认字体,楷体:KaiTi
- textImage1 = myfont.render("难度级别 1", True , GREEN)
- textImage2 = myfont.render("难度级别 2", True , BLUE)
- textImage3 = myfont.render("难度级别 3", True , RED)
- myfont = pygame.font.SysFont('SimHei', 20) #黑体:SimHei
- textImage4 = myfont.render("选取上面难度等级进入游戏;用户用鼠标单击", True , WHITE)
- textImage5 = myfont.render("两个已打乱顺序的小图块则这两块交换位置。", True , WHITE)
-
- screen.fill((0,0,0))
- screen.blit(scaled_image, (0, 0))
- screen.blit(textImage1, (150, 100))
- screen.blit(textImage2, (150, 250))
- screen.blit(textImage3, (150, 400))
- screen.blit(textImage4, (100, 500))
- screen.blit(textImage5, (100, 530))
- pygame.display.update()
-
- class PartPicture:
- # 初始化一个图片分块,保存图像和图像的位置, id代表原图第几块的位置
- def __init__(self, img, x, y, id):
- self.img = img
- self.x = x
- self.y = y
- self.id = id
- # 判断是否在图片内
- def isOver(self):
- w, h = self.img.get_size()
- point_x, point_y = pygame.mouse.get_pos() # 返回鼠标当前坐标
- in_x = self.x < point_x < self.x + w
- in_y = self.y < point_y < self.y + h
- return in_x and in_y
- # 检测移动
- def isPressed(self, pictureList):
- # print('is_pressed')
- if self.isOver():
- b1, b2, b3 = pygame.mouse.get_pressed()
- if b1 == 1:
- global firstClickCell
- global successFlag
-
- if firstClickCell is None:
- firstClickCell = self
- print('id为{}的块被点击'.format(firstClickCell.getId()))
- else:
- print('交换{}与{}的坐标'.format(firstClickCell.getId(), self.getId()))
- self.pictureSwitch(firstClickCell, self)
- if self.isFinish(pictureList):
- successFlag = True
- print('成功!')
- else:
- successFlag = False
- firstClickCell = None
- return True
- return False
-
- # 判断拼图完成
- def isFinish(self, pictureList):
- for cell in pictureList:
- nowp_x, nowp_y = cell.getXY()
- p_x = cell.getId() % COL * CELL_WIDTH
- p_y = (cell.getId() // COL) * CELL_HEIGHT
- print("id{} nowx{}与nowy{}的坐标 本来的坐标x{}y{}".format(cell.getId(), nowp_x, nowp_y, p_x, p_y))
- if nowp_x != p_x or nowp_y != p_y:
- return False
- return True
-
- def pictureSwitch(self, cell1, cell2):
- tempX = cell1.getX()
- tempY = cell1.getY()
- cell1.setXY(cell2.getX(), cell2.getY())
- cell2.setXY(tempX, tempY)
-
- def render(self, screen):
- screen.blit(self.img, (self.x, self.y))
-
- # get和set方法
- def getX(self):
- return self.x;
- def getY(self):
- return self.y
- # 获取图片坐标
- def getXY(self):
- return self.x, self.y
- # 修改图片坐标
- def setXY(self,x, y):
- self.x = x
- self.y = y
- # 获取id
- def getId(self):
- return self.id
-
- # 图片分块
- def devide(imgSrc):
- # 切割原来的图片
- pictures = []
- ScPictures = []
- id = 0 # 给每个分块的图片设置下标
- for i in range(ROW):
- for j in range(COL):
- # 提取部分图片
- partOfPicutre = imgSrc.subsurface(j * CELL_WIDTH, i * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT)
- # 保存第一组图片
- tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
- pictures.append(tempPicture)
- # 保存第二组图片
- tempPicture = PartPicture(partOfPicutre, j * CELL_WIDTH, i * CELL_HEIGHT, id)
- ScPictures.append(tempPicture)
- id += 1
- random.shuffle(pictures)
- # 开始利用第二组图片来打乱原来的图片
- for i in range(len(pictures)):
- pictures[i].setXY(ScPictures[i].getX(), ScPictures[i].getY())
- return pictures # 把打乱的图片返回
-
- setInit = False
- while True:
- if setInit:
- break
- for event in pygame.event.get():
- if event.type == QUIT:
- exit() # 接收到退出事件后退出程序
- elif event.type == MOUSEBUTTONDOWN:
- b1, b2, b3 = pygame.mouse.get_pressed()
- if b1 == 1:
- point_x, point_y = pygame.mouse.get_pos() # 返回鼠标当前坐标
- if 100 < point_y < 200:
- ROW = 3
- COL = 3
- setInit = True
- elif 250 < point_y < 350:
- ROW = 4
- COL = 4
- setInit = True
- elif 350 < point_y < 450:
- ROW = 5
- COL = 5
- setInit = True
-
- CELL_WIDTH = SCREEN_WIDTH / COL
- CELL_HEIGHT = SCREEN_HEIGHT / ROW
- # 原图 提高 blit 的速度 convert_alpha相对于convert,保留了图像的Alpha 通道信息,可以认为是保留了透明的部分,实现了透明转换
- imgSrc = pygame.image.load(gamePictures).convert() ##加载游戏图片
- PictureList = devide(imgSrc) #图片分块
-
- while True: # 游戏主循环
- for event in pygame.event.get():
- if event.type == QUIT:
- exit() # 接收到退出事件后退出程序
- elif event.type == MOUSEBUTTONDOWN:
- for cell in PictureList:
- # 检测按键按下,并且交换图片位置
- if cell.isPressed(PictureList):
- break
- for partPicture in PictureList:
- partPicture.render(screen)
- if not successFlag:
- # # Sta 绘制分割线
- for i in range(1, COL):
- pygame.draw.lines(screen, GREEN, 0, [(i * SCREEN_WIDTH // COL, 0), (i * SCREEN_WIDTH // COL, SCREEN_HEIGHT)], 1)
- for i in range(1, ROW):
- pygame.draw.lines(screen, GREEN, 0, [(0, i * SCREEN_HEIGHT // ROW), (SCREEN_WIDTH, i * SCREEN_HEIGHT // ROW)], 1)
- # End 绘制分割线
- pygame.display.update() # 刷新一下画面
-
- if successFlag:
- messagebox.showinfo("祝贺你!", "成功完成!")
- break

效果示意图如下:
★拼图游戏之拖动交换式
下面给出拼图游戏的另一种实现
功能:窗体上有两个按钮,单击"open"按钮加载的游戏图片,单击"start"按钮将加载的游戏图片分割成9小块打乱排列。游戏规则:将一个小块拖动到另一小块时,两小块图片将交换位置,当恢复原样时,提示"success!"。
源码如下:
- import pygame
- import random
- import sys
- import tkinter as tk
- from tkinter import filedialog
-
- # 初始化Tkinter
- root = tk.Tk()
- root.withdraw()
-
- # 初始化游戏
- pygame.init()
-
- # 设置游戏窗口尺寸
- WIDTH = 600
- HEIGHT = 600
- window = pygame.display.set_mode((WIDTH, HEIGHT))
- pygame.display.set_caption("拼图游戏:拖动交换小块图")
-
- # 设置颜色
- WHITE = (255, 255, 255)
- BLUE = (0, 0, 255)
-
- # 设置字体
- font = pygame.font.Font(None, 36)
-
- # 设置拼图块的尺寸和间隙
- BLOCK_SIZE = 200
- BLOCK_MARGIN = 5
-
- # 设置拼图块的初始位置
- block_positions = [(j * (BLOCK_SIZE + BLOCK_MARGIN), i * (BLOCK_SIZE + BLOCK_MARGIN))
- for i in range(3) for j in range(3)]
-
- # 拼图块的当前位置
- current_positions = block_positions.copy()
-
- # 游戏状态
- game_started = False
- puzzle_completed = False
-
- # 选中的拼图块
- selected_block = None
- selected_block_index = None
-
- # 加载游戏图片
- original_image = None
- block_images = []
-
- def load_image():
- global original_image, block_images
- # 选择并加载计算机中的图片
- file_path = filedialog.askopenfilename()
- if file_path:
- try:
- original_image = pygame.image.load(file_path)
- original_image = pygame.transform.scale(original_image, (BLOCK_SIZE * 3, BLOCK_SIZE * 3))
-
- # 分割原始图片为拼图块
- block_images = []
- for i in range(3):
- for j in range(3):
- block_images.append(original_image.subsurface(pygame.Rect(j * BLOCK_SIZE, i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)))
-
- # 重置游戏状态
- global game_started, puzzle_completed
- game_started = False
- puzzle_completed = False
- except pygame.error:
- print("加载图片失败!")
- sys.exit(1)
-
- # 检查拼图是否完成
- def check_puzzle_completed():
- global puzzle_completed
- puzzle_completed = all(current_positions[i] == block_positions[i] for i in range(len(current_positions)))
-
- # "start"按钮的点击事件处理
- def start_game():
- global game_started, puzzle_completed, current_positions
- if original_image is not None:
- current_positions = block_positions.copy()
- random.shuffle(current_positions)
- game_started = True
- puzzle_completed = False
-
- # 交换拼图块位置
- def swap_pieces(pos1, pos2):
- current_positions[pos1], current_positions[pos2] = current_positions[pos2], current_positions[pos1]
-
- # 获取拼图块索引
- def get_block_index(position):
- for i, pos in enumerate(current_positions):
- if pos == position:
- return i
- return None
-
- # 游戏主循环
- running = True
- clock = pygame.time.Clock()
-
- while running:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- running = False
- elif event.type == pygame.MOUSEBUTTONDOWN:
- if 50 <= event.pos[0] <= 180 and 50 <= event.pos[1] <= 80:
- load_image() # 当鼠标在"open"按钮区域内按下时,调用load_image()函数加载图片
- elif game_started and not puzzle_completed:
- for i, position in enumerate(current_positions):
- block_rect = pygame.Rect((position[0], position[1]), (BLOCK_SIZE, BLOCK_SIZE))
- if block_rect.collidepoint(event.pos):
- selected_block = position # 记录选中的拼图块的位置
- selected_block_index = i # 记录选中的拼图块的索引
- break
- elif 200 <= event.pos[0] <= 330 and 50 <= event.pos[1] <= 80:
- start_game() # 当鼠标在"start"按钮区域内按下时,调用start_game()函数开始游戏
- elif event.type == pygame.MOUSEBUTTONUP:
- if game_started and not puzzle_completed and selected_block is not None:
- for i, position in enumerate(current_positions):
- block_rect = pygame.Rect((position[0], position[1]), (BLOCK_SIZE, BLOCK_SIZE))
- if block_rect.collidepoint(event.pos) and selected_block != position:
- swap_pieces(selected_block_index, i) # 交换选中的拼图块与鼠标释放位置上的拼图块的位置
- break
- selected_block = None
- selected_block_index = None
- elif event.type == pygame.KEYDOWN:
- if event.key == pygame.K_r:
- if original_image is not None:
- random.shuffle(current_positions) # 按下"r"键后,随机洗牌拼图块的位置
- game_started = True
- puzzle_completed = False
- elif event.key == pygame.K_q:
- running = False # 按下"q"键后,退出游戏循环
-
- window.fill(WHITE) # 填充窗口背景颜色为白色
-
- if original_image is not None:
- for i in range(len(current_positions)):
- position = current_positions[i]
- pygame.draw.rect(window, BLUE, (position[0], position[1], BLOCK_SIZE, BLOCK_SIZE)) # 绘制拼图块的矩形边框
- window.blit(block_images[i], position) # 在拼图块的位置上绘制对应的图像
-
- pygame.draw.rect(window, BLUE, (50, 50, 130, 30)) # 绘制"open"按钮的矩形边框
- open_text = font.render("open", True, WHITE) # 创建渲染的"open"文本图像
- window.blit(open_text, (90, 55)) # 在窗口上绘制"open"文本图像
-
- pygame.draw.rect(window, BLUE, (200, 50, 130, 30)) # 绘制"start"按钮的矩形边框
- start_text = font.render("start", True, WHITE) # 创建渲染的"start"文本图像
- window.blit(start_text, (235, 55)) # 在窗口上绘制"start"文本图像
-
- check_puzzle_completed() # 检查拼图是否完成
-
- if puzzle_completed:
- success_text = font.render("success!", True, WHITE) # 创建渲染的"success!"文本图像
- success_text_rect = success_text.get_rect(center=(WIDTH // 2, HEIGHT // 2)) # 计算"success!"文本图像的中心位置
- window.blit(success_text, success_text_rect) # 在窗口上绘制"success!"文本图像
-
- pygame.display.flip() # 更新窗口显示
- clock.tick(60) # 控制游戏循环的帧率为60帧每秒
-
- pygame.quit()

在此就不给出效果示意图了,你可以试试。
python和pygame实现烟花特效 https://blog.csdn.net/cnds123/article/details/134974517
python和pygame实现捉小兔游戏 https://blog.csdn.net/cnds123/article/details/134996061
Pygame官方文档https://www.pygame.org/docs/
pygame中文教程 https://www.w3schools.cn/pygame/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。