pygame文档学习之Rect

pygame.Rect

是用来保存矩形坐标的pygame对象。
pygame使用Rect对象来存储和操纵矩形区域。我们可以用它的左顶点的坐标x、y值和宽、高来创建一个新的Rect。也可以从已经存在的Rect对象,或具有rect属性的对象创建一个新的Rect对象。
任何需要Rect参数的函数,也同样接受这些数据来创建一个Rect。这样可以方便我们创建一个Rect作为这些函数的参数。
需要改变Rect的位置或大小的Rect函数,将会复制出一个新的Rect并会受到改变的位置或大小的影响。而原来的Rect并没有受动影响。其中一些方法有一个带有“in_place”版本的替代函数。这些替代函数只会影响原来的Rect对象,而不会创建新的Rect对象。这些“in_place”方法都用“ip”后缀来标明。

  • :在这里in_place请大家不要翻译成在原地,而可翻译成在当前对象。

Rect对象拥有几个用于移动和对齐的虚拟属性。

x,y
top,bottom,left,right
topleft ,bottomleft,topright,bottomright
midtop,midbottom,midleft,midright
center,centerx,centery
size,width,height
w,h

所有的属性都可以象下面这样赋值。

rect1.right =10
rect2.center = (20,30)

赋值给size,width,height属性会改变矩形的大小。而其它属性只会移动矩形,而不会改变它的大小。请注意,一些属性只需赋一个整数,而另一些需赋两个整数。Rect对象中只要width或height属性中有一个不为0,那么在非0测试时,会返回True。一些方法中,如果返回Rect的size属性为0,那么代表这个Rect对象是无效的。一个size为0的Rect,当对它进行碰撞测试时,是不会发生任何碰撞的。Rect对象的坐标值都是整形的。size可以被编程为负数,但会被大多数操作系统认为是非法矩形。
这里有几个与其他矩形碰撞的测试。大多数容量都能被检测到与单个矩形的碰撞。Rect涵盖的区域不包括它的最右边及最下边像素。比如说,如果一个Rect的Top等于另一个Rect的bottom属性。那么说明它们是相遇了,但没有任何重叠发生。rect1.colliderect(rect2)会返回False。
Rect对象是可迭代的:

r = Rect(0,1,2,3)
x,y,w,h =r

Rect(left,top,width,height)->Rect
Rect((left,top),(width,height))->Rect
Rect(object)->Rect

pygame.Rect

  1. copy()->Rect 复制。返回一个具有相同位置及大小的矩形。

  2. move(x,y)-> Rect 以调用矩形为参照创建一个新矩形,并将这个矩形按参数给定数值偏移。

    • move_ip(x,y) 调用矩形移动。和move()相似,但它并不会创建一个新的矩形,而是把调用矩形移动参数给定的偏移量。
  3. inflate(x,y)->Rect 以调用矩形为参照创建一个新矩形,并将这个矩形扩大或缩小参数给定尺寸。

    • inflate_ip(x,y) 同inflate(),只是对当前Rect对象起作用,而不会创建新的Rect
    • 变化后的矩形以原始矩形中心点为中心。
    • 当矩形的宽和高为奇数时,它们中心点的位置为减1再除以2。
    • 当调用矩形的宽和高为偶数,参数x,y为负奇数时,中心点对应的x,y会偏移-1像素。
    • 当调用矩形的宽和高为奇数,参数x,y为正奇数时,中心点对应的x,y会偏移+1像素。
    • 其它情况,中心点不会改变
    • 官网说的偏移量太小(<2 >-2)时,中心点会偏移,这个说法并不成立。

    • 另补充说明一下中心点会发生移动的原理:当矩形的宽和高为奇数时,中心点的位置为减1再除以2。具体分析如下。
    • 首先要说明的时,任何情况下加减一个偶数,中心点都没会变化。我们不去讨论它。
    • 当调用矩形的宽或高是奇数时,它的中点心是减1后再除以2。这个减去的1,我们称之为消失的1。
      • 这时如果我们加上一个奇数,相当于加上一个比它小的偶数,再加1。那个偶数因为不会影响中心点,我们不用看它,我们最终只看这个加1。这个1与调用矩形计算中心点时消失的1相加后为2,除2后为1。这个1就会高调的让中心点向右或向下移动一位。
      • 这时如果我们减去一个奇数,相当于减去一个比它小的偶数,再减1。这个1与调用矩形计算中心点时消失的1相减后为0,所以它的中心点不会改变。
      • 这就是(当宽和高为奇数时,x,y为正奇数时,中心点对应的x,y会偏移+1像素。)的由来。
    • 当调用矩形的宽或高为偶数时。
      • 这时如果我们加上一个奇数,相当于加上一个比它小的偶数,再加1。这个多出的1,会在计算中心点时,被减去。也就是说它会变成那个消失的1 。中心点不会发生变化。
      • 这时如果我们减上一个奇数,相当于减去一个比它小的偶数(得到一个偶数),再减1。这时系统会发现它的结果是个奇数,在计算中心点是会再次减1,再除2 。 于是相当于减了两次1,所以中心点会发生左移或上移。
      • 这就是(当宽和高为偶数时,x,y为负奇数时,中心点对应的x,y会偏移-1像素。)的由来。
  4. scale_by(scalar)->Rect

    • scale_by(scalex,scaley)->Rect
    • scale_by_ip() 同scale_by(),只是对当前Rect对象起作用,而不会创建新的Rect
    • 以调用矩形为参照创建一个新矩形,并将这个矩形按比例缩放
    • 跟据参数按比例缩放矩形。
    • 变化后的矩形以调用矩形中心点为中心,也有可能偏移1像素。
    • 只有一个参数或分别给出宽、高的比例参数都是可以的。
    • 绝对值大于1的参数,将会扩大矩形,小于1的数会缩小矩形。
  5. update(x,y,width,heigh) 设置调用矩形的位置和大小。参数同pygame.Rect相同。

  6. clamp(Rect)->Rect 以调用矩形为参照创建一个新矩形,并将这个矩形移到参数给定的矩形里

    • clamp_ip(Rect) 同clamp(),只是对当前Rect对象起作用,而不会创建新的Rect。_ip特性都是这样。下面的不再累述。
    • 当矩形宽小于参数Rect的宽时,左边对齐。
    • 当矩形高小于参数Rect的高时,底边对齐。
    • 当矩形宽(高)大于参数Rect的宽(高)时,居中对齐。
  7. clip(Rect)->Rect 用调用矩形对参数里的矩形进行裁剪。返回裁剪后的矩形。

    • 如果这两个矩形没有重合部分,将返回一个size为0的矩形。
  8. clipline(x1,y1,x2,y2) -> ((x1,y1),(x2,y2))

    • clipline((x1,y1),(x2,y2))
    • clipline((x1,y1,x2,y2))
    • clipline(((x1,y1),(x2,y2)))
    • 用调用矩形对参数给定的两点之间线段的裁剪。返回线段与矩形边界相交的两个点的坐标。
    • 特别注意,矩形是不包括最右边及最下边的一个像素。例如,如果线条与矩形右边界相交,rect.right=200,那么返回的这个点的x=199。
    • 如果矩形的线段没有任何相交,那么返回一个空元组()
    • 注:此方法也可用来检测一个矩形是否与一条线段发生碰撞。返回值为空,说明没有发生了碰撞,否则发生了碰撞。
  9. union(Rect)-> Rect 创建一个刚好完全容纳这两个矩形的新矩形。

    • union_ip()
  10. unionall(Rect_sequence) -> Rect 创建一个刚好完全容纳多个矩形的新矩形。

    • unionall_ip()
  11. fit(Rect)-> Rect 以调用矩形的宽高比例调整大小以适应参数给的Rect。中心位置相同。这个矩形可能宽和高会小于目标Rect。

  12. normalize() 如果调用矩形的宽或高有负数时,取反,让它变成正数。中心位置不变。

  13. contains(Rect)->bool 测试调用矩形是否完全包含另一个矩形。当参数Rect完全在调用矩形里时返回True

  14. collidepoint(x,y)-> bool 测试参数给的点是否在调用矩形里,如果是,返回True。注,这个点在矩形的最右边界和最下边界时返回False。

  15. colliderect(Rect)-> bool 测试两个矩形是否有重合。注右边界和下边界例外。

  16. collidelist(list)->index 测试调用矩形是否与列表中任何一个矩形重合。如果有,返回第一个重合的索引。如果没有任何一个有重合,则返回-1 。

  17. collidelistall(list)->list 找到列表中与调用矩形有重合的所有矩形。返回所有有重合的矩形的索引列表。如果没有任何一个重合,则返回一个空列表。

  18. collidedict(dict)->(key,value)

    • collidedict(dict,use_values=0)->(key,value)
    • 返回字典中与调用窗口发生碰撞的的第一个键值对。如果字典中没有任何键值对与调用窗口发生碰撞,则没有返回。如果use_values的值为0,那么将检测与键的碰撞。否则将检测与值的碰撞。
    • Rect对象因为是哈希值所以在字典中不能做为键keys,所以它们必须转化为元组。如rect.collidedict({tuple(key_rect):value})
    • 不可哈希值指的是那些在其生命周期内可以改变其值的对象。比如我们的Rect对象。而字典的键要求唯一性和不可变性,所以说作为不可哈希值的Rect是不能做为字典的键。我们需要用ruple把它转化为元组。
  19. collidedictall(dict)->[(key,value),…]

    • collidedictall(dict,use_values=0)->[(key,value),…] 返回字典中与调用矩形有重合的所有键值对的列表。如果没有任何一个有重合,则返回一个空列表。
    • 如果use_values的值为0,那么将检测与字典键的碰撞。否则将检测与值的碰撞。
    • 其它的同上。
    • 另再下面程序的后面附上矩形与字典碰撞的程序。单独写了一个程序。方便更直观的测试效果。
import pygame,sys
'''
    进行任何碰撞及裁剪等测试时,请先把鼠标放到最左上角的rect1处,
    按下鼠标左键,把rect1拖到适当的位置,再松开鼠标右键,再进行
    相关操作。还可以按1或2键改变rect1的大小,来更方便观察效果。
    所有与矩形相关测试基本上都是与最右边那个矩形相测试。
'''

size=width,height = 800, 600
screen = pygame.display.set_mode(size)
x,y,width,height = 50,50,100,50
rect1 = pygame.Rect(x,y,width,height)
# copy 复制。返回一个具有相同位置及大小的矩形rect2。
rect2 = rect1.copy()
# 把 rect2 向右移动200像素
rect2.move_ip(200,0)
# 创建一个新的Rect:rect3,并把它向右移动400像素。
rect3 = rect1.move(400,0)
# 创建一个新的Rect:rect4,并把它的宽加90,高减11
rect4 =rect1.inflate(90,-101)
#rect1 宽减小10,高增加50
rect1.inflate_ip(-10,100)
#创建一个新的Rect:rect5,宽缩小为原来的0.8倍,高扩大为1.5倍。
rect5 = rect1.scale_by(0.8,1.5)
rect6 = rect7 = pygame.Rect(0,0,0,0)
#一条线段的第一个点和最后一个点
pos1 = (100,100)
pos2 = (600,500)
cpos1 = False

#当鼠标rect1 碰撞时按下鼠标键,rect1随鼠标移动的标志。方便各种碰撞测试。
move_flag=False

while True:
    pos = pygame.mouse.get_pos()
    #当move_flag标志为True时,设置rect1的center属性等于鼠标当前位置
    if move_flag:
        rect1.center = pos

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN: 
        #鼠标按下时,如果与rect1发生碰撞,则设move_flag为True           
            if rect1.collidepoint(pos):           
                move_flag = True
        elif event.type == pygame.MOUSEBUTTONUP:
            #松开鼠标键时,设move_flag为False
            move_flag =False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_q:
                sys.exit()
            #按1键扩大rect1,按2键缩小 rect1
            elif event.key == pygame.K_1:
                rect1.scale_by_ip(1.1)
            elif event.key == pygame.K_2:
                rect1.scale_by_ip(0.9)
            elif event.key == pygame.K_3:
                # 按3 把rect设置为初始值。
                rect1.update(x,y,width,height)
            elif event.key == pygame.K_4:
                #按4 创建一个矩形,并把它放到rect3里。
                rect6 = rect1.clamp(rect3)  
            elif event.key == pygame.K_5:
                # 按5 用rect1对rect3裁剪,返回一个新的矩形
                rect6 = rect1.clip(rect3)
            elif event.key == pygame.K_6:
                #用矩形对线段剪裁
                cpos1 = rect1.clipline(pos1,pos2)               
            elif event.key == pygame.K_7:
                rect6 = rect1.union(rect3)
            elif event.key == pygame.K_8:
                rect6 = rect1.unionall((rect2,rect3))
            elif event.key ==pygame.K_9:
                rect6 = rect1.fit(rect3)
            elif event.key == pygame.K_0:               
                rect4.normalize()
            elif event.key == pygame.K_a:
                print("当前窗口包含rect3:",rect1.contains(rect3))
            elif event.key == pygame.K_s:
                print("当前窗口与rect3重合:",rect1.colliderect(rect3))
            elif event.key == pygame.K_d:
                print("与当前窗口有重合的第一个窗口索引:",rect1.collidelist((rect2,rect3,rect4,rect5)))
            elif event.key == pygame.K_f:
                print("与当前窗口有重合的窗口是:",rect1.collidelistall((rect2,rect3,rect4,rect5)))

    screen.fill((0,0,0))
    pygame.draw.rect(screen,"blue",rect1,1)
    pygame.draw.rect(screen,"green",rect2,1)
    pygame.draw.rect(screen,"green",rect3,1)
    pygame.draw.rect(screen,"red",rect4,1)
    pygame.draw.rect(screen,"red",rect5,1)
    pygame.draw.rect(screen,"red",rect6,1)
    pygame.draw.rect(screen,"pink",rect7,1)
    pygame.draw.line(screen,"blue",pos1,pos2,width=1)
    if cpos1:
        pygame.draw.line(screen,"red",cpos1[0],cpos1[1],width=5)

    pygame.display.flip()

import pygame,sys
'''
用鼠标托运蓝色的矩形到适当的位置,然后按数字
   1,检测调用矩形与字典是否发生碰撞,碰撞对象是值
   2,检测调用矩形与字典是否发生碰撞,碰撞对象是键
   3,检测调用矩形与字典中所有矩形的碰撞,碰撞对象是的值
   4,检测调用矩形与字典中所有矩形的碰撞,碰撞对象是的键
'''

size=width,height = 800, 600
screen = pygame.display.set_mode(size)

#创建4个用于碰撞检测的Rect
rect1 = pygame.Rect(50 , 50,100,50)
rect2 = pygame.Rect(200, 50,100,50)  
rect3 = pygame.Rect(50 ,120,100,50)
rect4 = pygame.Rect(200,120,100,50)
rect_list =[rect1,rect2,rect3,rect4]

#一个以矩形rect为值的字典
dict_rectvalue = {1:rect1,2:rect2,3:rect3,4:rect4}
#创建一个以矩形rect的元组为键的字典
dict_rectkey={}
num = 0
for rect in rect_list:
    num +=1
    dict_rectkey[tuple(rect)] = num
print ("rect化为元组字典:",dict_rectkey)

#可以用鼠标拖动的矩形,作为与字典发生碰撞的调用矩形
rect  = pygame.Rect(50,300 ,100,50)

#控制rect是否跟随鼠标移动的标志
move_flag = False

while True:
    mouse_pos = pygame.mouse.get_pos() 
    #如果move_falg为True,那么矩形rect随着鼠标移动。
    if move_flag:
        rect.center = mouse_pos

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit() 
        elif event.type == pygame.MOUSEBUTTONDOWN:
            #鼠标按下时如果鼠标坐标在rect里,那么设置move_flag为True
            if rect.collidepoint(mouse_pos):
                move_flag = True
        elif event.type == pygame.MOUSEBUTTONUP:
            #松开鼠标键时,设置move_flag为False.
            move_flag = False

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_q:
                sys.exit()
            elif event.key == pygame.K_1:
                #检测调用矩形与字典是否发生碰撞,碰撞对象是值
                print(rect.collidedict(dict_rectvalue,1))
            elif event.key == pygame.K_2:
                #检测调用矩形与字典是否发生碰撞,碰撞对象是键
                print(rect.collidedict(dict_rectkey,0))
            elif event.key == pygame.K_3:
                #检测调用矩形与字典中所有矩形的碰撞,碰撞对象是的值
                print(rect.collidedictall(dict_rectvalue,1))
            elif event.key == pygame.K_4:
                #检测调用矩形与字典中所有矩形的碰撞,碰撞对象是的键
                print(rect.collidedictall(dict_rectkey,0))

    screen.fill((0,0,0))
    for value in rect_list:
        pygame.draw.rect(screen,"green",value,1)
    pygame.draw.rect(screen,"blue",rect,2)
    pygame.display.flip()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值