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
-
copy()->Rect 复制。返回一个具有相同位置及大小的矩形。
-
move(x,y)-> Rect 以调用矩形为参照创建一个新矩形,并将这个矩形按参数给定数值偏移。
- move_ip(x,y) 调用矩形移动。和move()相似,但它并不会创建一个新的矩形,而是把调用矩形移动参数给定的偏移量。
-
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像素。)的由来。
-
scale_by(scalar)->Rect
- scale_by(scalex,scaley)->Rect
- scale_by_ip() 同scale_by(),只是对当前Rect对象起作用,而不会创建新的Rect
- 以调用矩形为参照创建一个新矩形,并将这个矩形按比例缩放
- 跟据参数按比例缩放矩形。
- 变化后的矩形以调用矩形中心点为中心,也有可能偏移1像素。
- 只有一个参数或分别给出宽、高的比例参数都是可以的。
- 绝对值大于1的参数,将会扩大矩形,小于1的数会缩小矩形。
-
update(x,y,width,heigh) 设置调用矩形的位置和大小。参数同pygame.Rect相同。
-
clamp(Rect)->Rect 以调用矩形为参照创建一个新矩形,并将这个矩形移到参数给定的矩形里
- clamp_ip(Rect) 同clamp(),只是对当前Rect对象起作用,而不会创建新的Rect。_ip特性都是这样。下面的不再累述。
- 当矩形宽小于参数Rect的宽时,左边对齐。
- 当矩形高小于参数Rect的高时,底边对齐。
- 当矩形宽(高)大于参数Rect的宽(高)时,居中对齐。
-
clip(Rect)->Rect 用调用矩形对参数里的矩形进行裁剪。返回裁剪后的矩形。
- 如果这两个矩形没有重合部分,将返回一个size为0的矩形。
-
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。
- 如果矩形的线段没有任何相交,那么返回一个空元组()
- 注:此方法也可用来检测一个矩形是否与一条线段发生碰撞。返回值为空,说明没有发生了碰撞,否则发生了碰撞。
-
union(Rect)-> Rect 创建一个刚好完全容纳这两个矩形的新矩形。
- union_ip()
-
unionall(Rect_sequence) -> Rect 创建一个刚好完全容纳多个矩形的新矩形。
- unionall_ip()
-
fit(Rect)-> Rect 以调用矩形的宽高比例调整大小以适应参数给的Rect。中心位置相同。这个矩形可能宽和高会小于目标Rect。
-
normalize() 如果调用矩形的宽或高有负数时,取反,让它变成正数。中心位置不变。
-
contains(Rect)->bool 测试调用矩形是否完全包含另一个矩形。当参数Rect完全在调用矩形里时返回True
-
collidepoint(x,y)-> bool 测试参数给的点是否在调用矩形里,如果是,返回True。注,这个点在矩形的最右边界和最下边界时返回False。
-
colliderect(Rect)-> bool 测试两个矩形是否有重合。注右边界和下边界例外。
-
collidelist(list)->index 测试调用矩形是否与列表中任何一个矩形重合。如果有,返回第一个重合的索引。如果没有任何一个有重合,则返回-1 。
-
collidelistall(list)->list 找到列表中与调用矩形有重合的所有矩形。返回所有有重合的矩形的索引列表。如果没有任何一个重合,则返回一个空列表。
-
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把它转化为元组。
-
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()