pygame入门

article/2025/8/26 16:22:48

pygame入门

文章目录

  • pygame入门
    • 说明
    • 一、pygame的安装
    • 二、pygame模块概览
    • 三、pygame的“hello world”
    • 四、事件
      • 理解事件
      • 事件检索
      • 处理鼠标事件
      • 处理键盘事件
      • 事件过滤
      • 产生事件
    • 五、显示
      • 全屏显示
      • 改变窗口尺寸
      • 复合模式
      • 其他
    • 六、字体
      • 创建font对象
      • 使用字体
      • 中文字体
    • 七、颜色
    • 八、图像
      • 使用Surface对象
        • 创建Surface对象
        • 转换Surfaces
        • 矩形对象(Rectangle Objects)
        • 剪裁(Clipping)
        • 子表面(Subsurfaces)
        • 填充Surface
        • 设置Surface的像素
        • 锁定Surface
        • blit
    • 九、绘制各种图形
      • 一些说明
    • 十、运动
      • 直线运动
      • 时间
      • 斜线运动
      • 向量
    • 十一、用户输入
      • 键盘输入
        • 使用键盘控制方向
      • 鼠标控制
    • 版本信息

说明

在学习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 exitbackground_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()/2y -= 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 exitpygame.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_heightfor text in reversed(event_text):screen.blit(font.render(text, True, (0, 0, 0)), (0, y))y -= font_heightpygame.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 exitbackground_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 = -1elif event.key == K_RIGHT:move_x = 1elif event.key == K_UP:move_y = -1elif event.key == K_DOWN:move_y = 1elif event.type == KEYUP:move_x = 0move_y = 0x += move_xy += move_yscreen.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 exitbackground_image = '../image/sushiplate.jpg'pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)
background = pygame.image.load(background_image).convert()Fullscreen = Falsewhile True:for event in pygame.event.get():if event.type == QUIT:exit()if event.type == KEYDOWN:if event.key == K_f:Fullscreen = not Fullscreenif 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 exitbackground_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.sizescreen = pygame.display.set_mode(SCREEN_SIZE, RESIZABLE, 32)pygame.display.set_caption("Window resized to " + str(event.size))# 这里需要重新填满窗口screen_width, screen_height = SCREEN_SIZEfor 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 exitpygame.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())/2while True:for event in pygame.event.get():if event.type == QUIT:exit()screen.blit(background, (0, 0))x -= 1if 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 pygamepygame.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) * 256y = (r >> 4) * 256for 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 exitpygame.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_surfacered_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 randintpygame.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 exitbackground_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 = 0while True:for event in pygame.event.get():if event.type == QUIT:exit()screen.blit(background, (0, 0))screen.blit(sprite, (x, 100))x += 1if x>640:x = 0pygame.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 exitbackground_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 = 250while 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/1000distance_moved = time_passed_seconds * speedx += distance_movedif x > 640:x -= 640pygame.display.update()

斜线运动

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

#!/usr/bin/env python
# -*- coding:utf-8 -*-import pygame
from pygame.locals import *
from sys import exitbackground_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, 170while 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/1000x += speed_x * time_passed_secondsy += speed_y * time_passed_seconds# 到达边界后速度反向if x > 640 - sprite.get_width():speed_x = -speed_xx = 640 - sprite.get_width()elif x < 0:speed_x = -speed_xx = 0if y > 480 - sprite.get_height():speed_y = -speed_yy = 480 - sprite.get_height()elif y < 0:speed_y = -speed_yy = 0pygame.display.update()

向量

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

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

#!/usr/bin/env python
# -*- coding:utf-8 -*-import pygame
from pygame.locals import *
from sys import exit
from vector import Vec2dbackground_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_secondspygame.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 Vec2dbackground_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 = 300while 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 = -1elif pressed_keys[K_RIGHT]:key_direction.x = +1if pressed_keys[K_UP]:key_direction.y = -1elif pressed_keys[K_DOWN]:key_direction.y = +1key_direction.normalized()screen.blit(background, (0, 0))screen.blit(sprite, sprite_pos)time_passed = clock.tick(30)time_passed_seconds = time_passed/1000sprite_pos += key_direction * sprite_speed * time_passed_secondspygame.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 = 360while True:for event in pygame.event.get():if event.type == QUIT:exit()pressed_keys = pygame.key.get_pressed()rotation_direction = 0movement_direction = 0# 更改角度if pressed_keys[K_LEFT]:rotation_direction = +1elif 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_directionsprite_pos += heading * sprite_speed * time_passed_secondspygame.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 = 360while 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 = 0movement_direction = 0# 得到鼠标的偏移量(x, y)rotation_direction = pygame.mouse.get_rel()[0]/5if pressed_keys[K_LEFT]:rotation_direction = -1elif pressed_keys[K_RIGHT]:rotation_direction = +1if pressed_keys[K_UP] or pressed_mouse[0]:movement_direction = -1if pressed_keys[K_DOWN] or pressed_mouse[2]:movement_direction = +1screen.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/1000sprite_rotation += rotation_direction * sprite_rotation_speed * time_passed_secondsheading_x = sin(sprite_rotation * pi / 180)heading_y = cos(sprite_rotation * pi / 180)heading = Vec2d(heading_x, heading_y)heading *= movement_directionsprite_pos += heading * sprite_speed * time_passed_secondspygame.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


http://chatgpt.dhexx.cn/article/2uirrPyy.shtml

相关文章

pygame下载(非常详细)

pygame安装 第一次安装pygame&#xff0c;从网上查了很多资料&#xff0c;各种方式都有&#xff0c;我发现了一种很简单的方法&#xff0c;不用去官网找&#xff0c;直接输入命令就能下载&#xff0c;希望能给大家提供一些参考&#xff01; 打开终端 1、winR 打开终端&#…

Pygame是什么

Python 是当下最为火热,且功能最为全面的一门编程语言。Python 之所以深受大家喜爱, 除了可以被应用到“人工智能”领域之外,还可以延伸到数据分析、Web 开发、自动化测试、自然语言处理、游戏开发等各个领域。这一切的实现得益于 Python 有一个强大的第三方库,这个第三方库…

【pygame游戏开发】这几个经典游戏,勾起了少年的快乐

给大家分享几个好玩有趣的小游戏&#xff0c;既提升了学习的兴趣&#xff0c;又提升了学习效率&#xff0c;告别枯燥的学习。 一、飞机大战 1、源码部分 模块导入 import sys import cfg import pygame from modules import *游戏界面 def GamingInterface(num_player, scr…

python-颜色识别

使用Python来做颜色识别&#xff0c;使用了openCV import cv2 import numpy as np import time class ColorTac(object):def colorTacing(self):print(-*-COLOR TACKING MODE-*-)print(you can input:blue,red,yellow,green,purple.and must input one)color input("Col…

android颜色识别

写的一个关于颜色识别的小功能。识别主要颜色。 思路&#xff1a;遍历像素点&#xff0c;找出出现次数最多的像素值作为主要颜色。 采用的方法有&#xff1a; 1.调用摄像头&#xff0c;拍照&#xff0c;裁剪&#xff0c;压缩。 2.找出色值。 3.转换成hsv空间&#xff0c;进行颜…

颜色及图片识别原理,颜色识别传感器介绍

光及颜色 1.光&#xff1a;是人类眼睛可以看见的一种电磁波&#xff0c;也称可见光谱。在科学上的定义&#xff0c;光是指所有的电磁波谱。光是由光子为基本粒子组成&#xff0c;具有粒子性与波动性&#xff0c;称为波粒二象性&#xff0c;一般人的眼睛所能接受的光的波长在380…

颜色识别总结

颜色检测 1、目标检测detr 【End-to-End Object Detection with Transformers】 论文解读 源码复现 2、目标检测deformable detr 【DEFORMABLE DETR: DEFORMABLE TRANSFORMERS FOR END-TO-END OBJECT DETECTION】 论文解读 源码复现 3、目标检测mmdet中的deformable detr …

Python-OpenCV实现简单的颜色识别(对红色和蓝色识别并输出)

摄像头识别红色和蓝色并框选&#xff0c;当该颜色为摄像头屏幕上大多数颜色时打印出该颜色的名称 新手学习笔记&#xff0c;第一次写博客&#xff0c;若有错误还请指出&#xff08; ~_ &#xff09;~ 1.调包 import cv2 import numpy as np from matplotlib import pyplot as…

Python3识别判断图片主要颜色并和颜色库进行对比的方法

【更新】主要提供两种方案&#xff1a; 方案一&#xff1a;&#xff08;参考网上代码&#xff0c;感觉实用性不是很强&#xff09;使用PIL截取图像&#xff0c;然后将RGB转为HSV进行判断&#xff0c;统计判断颜色&#xff0c;最后输出RGB值 方案二&#xff1a;使用opencv库函…

【Python 之HSV颜色识别】

Python 之HSV颜色识别 前言一、HSV颜色模型二、黄色识别三、使用步骤1.引入库2.处理图片3.识别结果 总结 前言 汽车自动驾驶&#xff0c;需要颜色识别&#xff0c;如黄色/红色车道线&#xff0c;蓝色车牌。 本文从HSV颜色模型出发&#xff0c;提供一种识别黄色车道线的方法供参…

OpenCV识别图像中的颜色

OpenCV识别图像中的颜色 利用OpenCV识别图像中区域的颜色 效果如图所示&#xff1a; 代码中需要读取的图像RGB对照表&#xff1a; 代码中所需读取的BGR对照表在此下载&#xff1a;图像RBG对照表 import cv2 import pandas as pdimg_path "./rgb_pic/color.jpg" i…

openCV python 颜色识别

图像识别 这个代码的功能是根据摄像头输入的图像&#xff0c;识别红色块&#xff0c;绿色块的坐标&#xff0c;并返回红绿色块的中心点的图像坐标&#xff08;单位为像素&#xff09; 当然&#xff0c;识别色可以自己更改&#xff0c;如蓝色&#xff0c;白色&#xff0c;黑色…

K210视觉体验—颜色识别

K210视觉体验—颜色识别 使用设备ZTFR开发板 颜色识别Lab 颜色空间构造函数示例代码1&#xff1a;识别RGB&#xff08;红&#xff0c;绿&#xff0c;蓝&#xff09;示例代码2&#xff1a;识别指定颜色 使用设备 ZTFR开发板 颜色识别 MaixPy 集成了 RGB565 颜色块识别 find_blo…

Halcon 学习笔记八:颜色识别

Halcon 学习笔记八&#xff1a;颜色识别 一、图像处理需要的知识二、图像处理的预处理和分割过程二、颜色识别的方法三、例子一四、例子二五、例子三 一、图像处理需要的知识 1.图像处理基础&#xff08;rgb(hsv),gray&#xff09; 2.图像灰度变换(scale_img) 3.图像基础(emph…

基于Python的颜色识别器

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 在这篇文章中&#xff0c;我们将展示如何使用Python构建颜色识别器。此过程也称为“颜色检测”。我们将创建一个基本应用程序&#xff0c;该应用程序将帮助我们检测图像…

python颜色识别demo

一般对颜色空间的图像进行有效处理都是在HSV空间进行的&#xff0c;然后对于基本色中对应的HSV分量需要给定一个严格的范围&#xff0c;下面是通过实验计算的模糊范围&#xff08;准确的范围在网上都没有给出&#xff09;。 H: 0 — 180 S: 0 — 255 V: 0 — 255 此处把部分…

openCV-python实现颜色识别

本文将介绍使用OpenCV实现颜色识别的详细步骤 代码。 背景介绍 在截取出模板匹配到的logo区域之后&#xff0c;需要判断logo是什么颜色。本案例中要识别的对象是纯色的所以适用下面的颜色识别方法&#xff0c;有不同需求的请斟酌借鉴。 原理介绍 数字图像处理中常用的采用模型…

python颜色识别,46行代码实现865种颜色识别,看过的都说顶呱呱!

1.先介绍我做的颜色识别的功能&#xff0c;简单的说&#xff0c;就是该脚本可以打开图片&#xff0c;在图片上点击某个区域&#xff0c;可以识别某个区域的颜色&#xff0c;颜色识别准确度很高&#xff0c;很多时候颜色识别是辅助物体的颜色识别&#xff0c;但这个代码你们可以…

OpenCV(Python)颜色识别(一)

1. 基本原理 1.1 彩色模型 数字图像处理中常用的采用模型是RGB&#xff08;红&#xff0c;绿&#xff0c;蓝&#xff09;模型和HSV&#xff08;色调&#xff0c;饱和度&#xff0c;亮度&#xff09;&#xff0c;RGB广泛应用于彩色监视器和彩色视频摄像机&#xff0c;我们平时…

OpenCV颜色识别

彩色模型 数字图像处理中常用的采用模型是RGB&#xff08;红&#xff0c;绿&#xff0c;蓝&#xff09;模型和HSV&#xff08;色调&#xff0c;饱和度&#xff0c;亮度&#xff09;&#xff0c;RGB广泛应用于彩色监视器和彩色视频摄像机&#xff0c;我们平时的图片一般都是RGB…