02py游戏开发基础

版本

pygame 2.4.0 (SDL 2.26.4, Python 3.8.2)
Hello from the pygame community. https://www.pygame.org/contribute.html

Python开发基础

Pygame常用模块

02py游戏开发基础_第1张图片 02py游戏开发基础_第2张图片
background_image_filename = "bg.jpg"#设置图像文件名称
mouse_image_filename = "ship.bmp"

# 将import pygame和from pygame.locals import *分两次写是为了区分导入pygame模块
# 和导入pygame.locals模块中的常量和枚举类型,以便代码的可读性和维护性
import pygame
from pygame.locals import *
# pygame.locals模块提供了一些常量和枚举类型,用于表示键盘、鼠标、事件等相关的常量和状态。
from sys import exit#从sys模块导入函数exit()用于退出程序

pygame.init()#初始化pygame,使用硬件做准备
screen = pygame.display.set_mode((640, 480), pygame.DOUBLEBUF | pygame.RESIZABLE, 32)#创建一个窗口
pygame.display.set_caption("Hello, World!")#设置窗口标题
#下面两行代码加载并转换图像
background = pygame.image.load(background_image_filename).convert()
mouse_cursor = pygame.image.load(mouse_image_filename).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()#获得鼠标位置
    # 下面两行代码计算光标左上角位置
    # 使鼠标光标和光标图像中心对齐
    # pygame.mouse.set_visible(False)#隐藏鼠标
    print("旧")
    print(x, y)
    x -= mouse_cursor.get_width() / 2
    y -= mouse_cursor.get_height() / 2
    print("新")
    print(x, y)
    # print(mouse_cursor.get_width() / 2,mouse_cursor.get_height() / 2)
    screen.blit(mouse_cursor, (x, y))   #绘制光标
    #把光标画上去
    pygame.display.update()     #刷新画面

set_mode()

set_mode()方法用于创建一个窗口或全屏幕显示,它的函数签名为:

set_mode(resolution=(0,0), flags=0, depth=0)

其中,set_mode()方法有三个参数,分别为:

  1. resolution:表示窗口的分辨率,它是一个二元组,包含了窗口的宽度和高度。例如,(640, 480)表示窗口宽度为640像素,高度为480像素。如果将resolution设置为(0, 0),则表示创建一个全屏窗口。
  2. flags:表示窗口的特性,它是一个整数,可以通过按位或运算符(|)来组合多个特性。常用的特性包括:
    • pygame.FULLSCREEN:创建全屏窗口。
    • pygame.DOUBLEBUF:使用双缓冲技术,可以避免屏幕闪烁。
    • pygame.RESIZABLE:窗口可以调整大小。
    • pygame.HWSURFACE:使用硬件加速,可以提高绘制速度。
    • pygame.NOFRAME:创建一个没有边框的窗口。
  3. depth:表示颜色深度,它表示每个像素使用的位数。默认值为0,表示使用当前显示器的颜色深度。可以设置为16、24或32等值,表示使用16位、24位或32位颜色深度。

Surface对象

在Pygame中,Surface对象是表示图像和屏幕的基本类型,它是一个**二维的像素数组,**可以用来表示图像、屏幕、文本等。Surface对象可以通过加载图像文件、创建空白Surface对象、从屏幕截取图像等方式来创建。

Surface对象具有很多属性和方法,可以用来操作和绘制图像。一些常用的属性和方法包括:

  • get_width():返回Surface对象的宽度。
  • get_height():返回Surface对象的高度。
  • get_size():返回Surface对象的尺寸,是一个二元组。
  • blit():将一个Surface对象绘制到另一个Surface对象上。
  • fill():使用指定的颜色填充Surface对象。
  • convert():将Surface对象转换为指定的像素格式。
  • convert_alpha():将Surface对象转换为带有alpha通道的像素格式(保留了透明的部分,这样移动的光标才是不规则形状)。

主循环

游戏的主循环是一个无限循环,直到用户跳出。在这个主循环里做的事情就是不停地画背景和更新光标位置,虽然背景是不动的,但还是需要每次都画它,否则鼠标覆盖过的位置就不能恢复正常了

大都带有这样的一些while True循环,并且带有一条将该循环称为“main game loop”的注释。游戏循环(game loop,也叫作主循环main loop)中的代码做如下3件事情。

  • 处理事件。

  • 更新游戏状态。

  • 在屏幕上绘制游戏状态。

游戏状态

游戏状态(game state)只不过是针对游戏程序中用到的所有变量的一组值的一种叫法

事件基础

事件

在Pygame中,事件是指用户与程序交互时产生的动作,例如按键、鼠标移动、窗口关闭等。Pygame通过pygame.event模块来处理事件,可以使用pygame.event.get()函数获取当前所有的事件,并通过遍历事件队列来处理不同类型的事件。

02py游戏开发基础_第3张图片 02py游戏开发基础_第4张图片

pygame.quit()

在Event对象中有一个名为type的成员变量,其功能是告诉对象表示哪一种事件。针对pygame.locals模块中每一种可能的类型,Pygame都有一个常量变量。

pygame.quit()是pygame.init()的相反函数

pygame.event.Event对象

在任何时候,当用户按下一个按键或者把鼠标移动到程序的窗口上面等动作时,Pygame库就会创建一个pygame.event.Event对象来记录这个动作,这就是事件。我们可以调用函数pygame.event.get()来获取发生的事件,此函数会返回pygame.event.Event对象(简称为Event对象)的一个列表。这个Event对象的列表包含了自上次调用pygame.event.get()函数之后所发生的所有事件(如果从来没有调用过pygame.event.get(),会包括自程序启动以来所发生的所有事件)。

处理鼠标事件

在Pygame框架中,MOUSEMOTION事件会在鼠标动作的时候发生,它有如下所示的3个参数。

  • buttons:一个含有3个数字的元组,3个值分别代表左键、中键和右键,1就说明按下了。

  • pos:位置。

  • rel:代表现在距离上次产生鼠标事件时的距离。和MOUSEMOTION类似,常用的鼠标事件还有MOUSEBUTTONDOWN和MOUSEBUTTONUP两个。这两个事件的参数如下所示。

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

  • pos:位置。

import pygame
#判断一个点是否在指定范围内
def is_rect(pos,rect):
    x, y = pos
    rx, ry, rw, rh = rect
    if(rx <= x <= rx+rw) and (ry <= y <= ry+rh):
        return True
    return False

if __name__ == "__main__":
    pygame.init()
    screen = pygame.display.set_mode((600,600))
    screen.fill((255,255,255))
    pygame.display.set_caption("图片拖拽")
    #显示一张图片
    image = pygame.image.load("bg.jpg")
    image_x = 100
    image_y = 100

    screen.blit(image, (image_x, image_y))
    pygame.display.flip()
    #用来存储图片是否可以移动
    is_move = False
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            #鼠标按下,让状态可以移动
            if event.type == pygame.MOUSEBUTTONDOWN:
                w, h = image.get_size()
                if is_rect(event.pos, (image_x,image_y,w,h)):
                    is_move = True
            if event.type == pygame.MOUSEMOTION:
                if is_move:
                    screen.fill((255,255,255,255))
                    x, y = event.pos
                    image_w, image_h=image.get_size()
                    #保证鼠标在图片的中心
                    image_x=x-image_h/2
                    image_y=y-image_w/2
                    screen.blit(image,(image_x,image_y))
                    pygame.display.update()

处理键盘事件

在Pygame框架中,键盘和游戏手柄的事件比较类似,处理键盘的事件为KEYDOWN和KEYUP。KEYDOWN和KEYUP事件的参数描述如下所示。

  • key:按下或者放开的键值,是一个数字,因为很少有人可以记住,所以在Pygame中可以使用K_xxx来表示,比如字母a就是K_a,还有K_SPACE和K_RETURN等。
  • mod:包含了组合键信息,如果mod &KMOD_CTRL是真的话,表示用户同时按下了〈Ctrl〉键。类似的还有KMOD_SHIFT和KMOD_ALT。
  • unicode:代表按下键对应的Unicode值。例如在下面的实例文件shi.py中,演示了在Pygame框架中处理键盘事件的过程。
background_image_filename = "bg.jpg"
import pygame
from pygame.locals import *
from sys import exit

pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)
#下面一行代码加载并转换图像
background = pygame.image.load(background_image_filename).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_y = 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()#更新绘制操作后屏幕的显示

事件过滤

在现实应用中,并不是所有的事件都是需要处理的。应该有一个方法来过滤掉一些不感兴趣的事件。

  • 这时需要使用pygame.event.set_blocked(事件名)来完成。如果有好多事件需要过滤,可以传递一个专用列表来实现比如pygame.event.set_blocked([KEYDOWN,KEYUP]),如果设置参数None,那么所有的事件又被打开了。与之相对应的是,使用**pygame.event.set_allowed()**函数来设定允许的事件。

  • pygame.event.set_blocked():控制哪些事件禁止进入队列。

    • set_blocked(type)-> Noneset_blocked(typelist)-> None
    • set_blocked(None)-> None参数指定类型的事件均不允许出现在事件队列中。默认是允许所有事件进入队列的。多次禁止同一类型的事件并不会引发什么问题。如果传入None,则表示允许所有的事件进入队列。
  • pygame.event.set_allowed():控制哪些事件允许进入队列。

    • set_allowed(type)-> None
    • set_allowed(typelist)-> None
    • set_allowed(None)-> None参数指定类型的事件均允许出现在事件队列中。默认是允许所有事件进入队列。多次允许同一类型的事件并不会引发什么问题。如果传入None,则表示禁止所有的事件进入队列。
  • pygame.event.get_blocked():检测某一类型的事件是否被禁止进入队列

    • get_blocked(type)-> bool如果参数指定类型的事件被禁止进入队列,则返回

产生事件

有时候需要模拟出一些对应的事件,可以自定义一个全新事件

案例

move_ball.py

from sys import exit
import  pygame
from pygame.locals import *
#事件类型:"键盘输入",就根据方向键计算出这个速度(默认从左向右为1,从上向下为1)
def control_ball(event):
    speed = [0, 0]#设置相对位移
    speed_offset = 1

    if event.type == KEYDOWN:
        if event.key == pygame.K_LEFT:
            speed[0] -= speed_offset

        if event.key == pygame.K_RIGHT:
            speed[0] =  speed_offset
            print(event.key)

        if event.key == pygame.K_UP:#Y轴朝下是正
            speed[1] -= speed_offset

        if event.key == pygame.K_DOWN:
            speed[1] =  speed_offset
    #如果没有按键输入速度为0小球不动
    if event.type == KEYUP:
        speed = [0, 0]
    return speed


def play_ball():
    pygame.init()

    window_size = Rect(0, 0, 806, 480)
    screen = pygame.display.set_mode(window_size.size)
    pygame.display.set_caption("坤坤找不到他的篮球了")
    ball_image = pygame.image.load("ball01.png").convert_alpha()
    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:
                exit()

        control_speed = control_ball(event)#获取小球移动方向
        ball_rect = ball_rect.move(control_speed).clamp(window_size)#限制小球图片在window_size这个区域里

        screen.blit(back_image, (0, 0))#绘制游戏窗口
        screen.blit(ball_image, ball_rect)#把小球绘制到背景Surface上

        # pygame.display.flip()
        pygame.display.update()

if __name__ == "__main__":
    play_ball()

pygame.Rect()

Rect()是Pygame中的一个类,用于创建矩形对象。它接受四个参数,分别是矩形的左上角x坐标、左上角y坐标、矩形的宽度和高度。

Rect().size()返回一个元组,包含矩形的宽度和高度

pygame.Surface.get_rect()

get_rect():是Surface对象的一个方法,用于获取表示该表面的矩形区域的Rect对象。

get_rect()方法返回一个Rect对象,该对象表示了Surface的矩形区域。这个矩形区域的左上角坐标为(0, 0),宽度和高度与Surface的尺寸相匹配。

get_rect()方法还接受一个可选的关键字参数kwargs,可以用于设置Rect对象的属性。例如,可以使用kwargs参数来设置矩形区域的位置或大小。

pygame.Rect.clamp()

clamp()

moves the rectangle inside another

clamp(Rect) -> Rect

更新窗口内容

pygame.display.flip Update the full display Surface to the screen
pygame.display.update Update portions of the screen for software displays
  1. pygame.display.flip():
    • flip()函数用于交换屏幕缓冲区的内容。在绘制完成后,调用flip()函数可以将绘制的内容立即显示在屏幕上。
    • flip()函数没有参数,它会更新整个屏幕的显示。
    • flip()函数比较简单,适用于简单的图形绘制场景。
  2. pygame.display.update():
    • update()函数用于更新屏幕的部分区域。它可以接受一个可选的参数,表示要更新的矩形区域。如果不指定参数,update()函数将更新整个屏幕。
    • update()函数可以更加灵活地控制屏幕的更新。您可以选择只更新需要更新的部分,以提高性能。
    • update()函数可以接受一个矩形列表作为参数,表示要更新的多个矩形区域。

主程序运行

if __name__ == "__main__": 是一个常见的Python代码约定,用于判断当前模块是否作为主程序直接运行。

当一个Python脚本作为主程序直接运行时,__name__变量的值会被设置为__main__。而当一个脚本被作为模块导入时,__name__变量的值会是模块的名称。

因此,使用if __name__ == "__main__": 来判断__name__的值,可以使得一部分代码只在脚本作为主程序运行时执行,而在被导入时不执行。

在您的代码中,play_ball()函数会在if __name__ == "__main__": 条件满足时被调用。这意味着当您的脚本作为主程序直接运行时,play_ball()函数会被执行。但如果您的脚本被作为模块导入,play_ball()函数不会被执行。

这种约定可以用于将一些测试代码或调试代码放在if __name__ == "__main__": 条件下,以便在开发和调试阶段执行,而在实际使用时不执行。

你可能感兴趣的:(Pygame,python,pygame,开发语言)