python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python pygame游戏模块

Python中pygame游戏模块的用法详解

作者:软件技术爱好者

Pygame是一组用来开发游戏软件的 Python 程序模块,Pygame 在 SDL(Simple DirectMedia Layer) 的基础上开发而成,它提供了诸多操作模块,本文给大家介绍了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游戏模块的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文