Python中pygame游戏模块的用法详解
作者:软件技术爱好者
Python中的pygame游戏模块的使用
Pygame 是一组用来开发游戏软件的 Python 程序模块,Pygame 在 SDL(Simple DirectMedia Layer) 的基础上开发而成。它提供了诸多操作模块,比如图像模块(image)、声音模块(mixer)、输入/输出(鼠标、键盘、显示屏)模块,擅长开发 2D 游戏,Python 也提供了开发 3D 游戏的软件包,比如 Pyglet、Panda3D、PyOgre 等。Pygame 是一个高可移植性的模块可以支持多个操作系统。用它来开发小游戏非常适合。官网https://www.pygame.org/news
pygame模块的安装
若使用pygame模块(python的2D游戏开发库),这是第三方(扩展)模块,若未预先装,需要在CMD中,使用 pip install pygame 先装入,可能需要花点时间。
查看是否电脑上是否有pygame,在CMD中,使用pip list命令,参见下图
若没有 pygame,需要在CMD中,使用 pip install pygame 命令安装,参见下图:
验证是否成功安装
法一、在CMD中,使用python -m pygame.examples.aliens命令验证,参见下图:
法二、进入Python的交互界面,输入以下命令验证是否成功安装,参见下图:
不报错,则说明安装成功。
pygame快速入门
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()
运行之,显示如下:
Pygame设置窗口图标和设置窗口背景图片
#设置窗口图标,下面两句
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播放音频
有两个方法:
☆播放特效声音:
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绘制图形的常用的方法:
☆ 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不仅可以在屏幕上绘制形状,还可以将文本绘制到屏幕上。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实现动画
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提供了一个函数来获取游戏的事件,并把他们存放在一个队列中,程序通过读取整个事件队列,来获取当前发生的时间,并作出响应。
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()
效果图如下:
综合例子
下面给出综合例子
1、画一个小房子,房前有树,树顶上有太阳
先给出效果图:
源码如下:
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()
2、用方向键控制小猫移动示例
需要两个素材文件:小猫图片 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()
3、拼图游戏
两种实现:点击交换式和拖动交换式
★拼图游戏之点击交换式
加载一张图片分块打乱,用户用鼠标单击两块图片则两块图片交换位置,拼图完成后提示成功。确保图像文件存在并与代码中指定的路径相匹配——我这里图片名是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游戏模块的用法详解的详细内容,更多关于Python pygame游戏模块的资料请关注脚本之家其它相关文章!