我目前正在使用pygame编写一个类似Snes的小RPG
在我的地图上,我有4层:
0:地形,无碰撞(在焦炭下)
1:Over Terrain没有碰撞(在char下)
2:碰撞物体(在焦炭下)
3:Over char对象
我想为第二层中的每个图块创建一个rect,这会阻止角色遍历这些对象。每次角色移动时,是否有一种有效的方法来不检查每个矩形?感谢。
答案 0 :(得分:2)
pygame为此提供了许多优化函数,例如Rect.collidelist
:
<强> collidelist()强>
相交
测试列表中的一个矩形是否与collidelist(list) - &gt;指数
测试矩形是否与矩形序列中的任何一个发生碰撞。返回找到的第一个碰撞的索引。如果未找到任何冲突,则返回-1的索引。
如果您仍遇到性能问题,可以使用QuadTree。
Here's an implementation in python using pygame.
from pygame import Rect
class QuadTree(object):
"""An implementation of a quad-tree.
This QuadTree started life as a version of [1] but found a life of its own
when I realised it wasn't doing what I needed. It is intended for static
geometry, ie, items such as the landscape that don't move.
This implementation inserts items at the current level if they overlap all
4 sub-quadrants, otherwise it inserts them recursively into the one or two
sub-quadrants that they overlap.
Items being stored in the tree must be a pygame.Rect or have have a
.rect (pygame.Rect) attribute that is a pygame.Rect
...and they must be hashable.
Acknowledgements:
[1] http://mu.arete.cc/pcr/syntax/quadtree/1/quadtree.py
"""
def __init__(self, items, depth=8, bounding_rect=None):
"""Creates a quad-tree.
@param items:
A sequence of items to store in the quad-tree. Note that these
items must be a pygame.Rect or have a .rect attribute.
@param depth:
The maximum recursion depth.
@param bounding_rect:
The bounding rectangle of all of the items in the quad-tree. For
internal use only.
"""
# The sub-quadrants are empty to start with.
self.nw = self.ne = self.se = self.sw = None
# If we've reached the maximum depth then insert all items into this
# quadrant.
depth -= 1
if depth == 0 or not items:
self.items = items
return
# Find this quadrant's centre.
if bounding_rect:
bounding_rect = Rect( bounding_rect )
else:
# If there isn't a bounding rect, then calculate it from the items.
bounding_rect = Rect( items[0] )
for item in items[1:]:
bounding_rect.union_ip( item )
cx = self.cx = bounding_rect.centerx
cy = self.cy = bounding_rect.centery
self.items = []
nw_items = []
ne_items = []
se_items = []
sw_items = []
for item in items:
# Which of the sub-quadrants does the item overlap?
in_nw = item.rect.left <= cx and item.rect.top <= cy
in_sw = item.rect.left <= cx and item.rect.bottom >= cy
in_ne = item.rect.right >= cx and item.rect.top <= cy
in_se = item.rect.right >= cx and item.rect.bottom >= cy
# If it overlaps all 4 quadrants then insert it at the current
# depth, otherwise append it to a list to be inserted under every
# quadrant that it overlaps.
if in_nw and in_ne and in_se and in_sw:
self.items.append(item)
else:
if in_nw: nw_items.append(item)
if in_ne: ne_items.append(item)
if in_se: se_items.append(item)
if in_sw: sw_items.append(item)
# Create the sub-quadrants, recursively.
if nw_items:
self.nw = QuadTree(nw_items, depth, (bounding_rect.left, bounding_rect.top, cx, cy))
if ne_items:
self.ne = QuadTree(ne_items, depth, (cx, bounding_rect.top, bounding_rect.right, cy))
if se_items:
self.se = QuadTree(se_items, depth, (cx, cy, bounding_rect.right, bounding_rect.bottom))
if sw_items:
self.sw = QuadTree(sw_items, depth, (bounding_rect.left, cy, cx, bounding_rect.bottom))
def hit(self, rect):
"""Returns the items that overlap a bounding rectangle.
Returns the set of all items in the quad-tree that overlap with a
bounding rectangle.
@param rect:
The bounding rectangle being tested against the quad-tree. This
must possess left, top, right and bottom attributes.
"""
# Find the hits at the current level.
hits = set( [ self.items[n] for n in rect.collidelistall( self.items ) ] )
# Recursively check the lower quadrants.
if self.nw and rect.left <= self.cx and rect.top <= self.cy:
hits |= self.nw.hit(rect)
if self.sw and rect.left <= self.cx and rect.bottom >= self.cy:
hits |= self.sw.hit(rect)
if self.ne and rect.right >= self.cx and rect.top <= self.cy:
hits |= self.ne.hit(rect)
if self.se and rect.right >= self.cx and rect.bottom >= self.cy:
hits |= self.se.hit(rect)
return hits
这将大大提高在简单循环中检查每个图块的性能。
答案 1 :(得分:1)
您可以使用recs
并检查它们是否与Dominic Kexel所说的相撞,但如果您的图形不完全正方形并且碰撞检测需要完美,我建议使用pygame sprite
具有pygame掩码的对象。可以根据alpha值(透明度)设置遮罩,并且非常容易处理:
class Entity(pygame.sprite.Sprite):
def __init__(self, image): #where image is a pygame image with that has had the convert_alpha() function used on it
self.image = image
self.rect = image.get_rect() #you can use a rect and a mask
self.mask = pygame.mask.from_surface(self.image) #creates a mask from the image ans assigns it to the sprite object
然后您可以使用rect
属性(使用rects可以处理各种不同类型的碰撞)轻松检查碰撞,或者您可以使用遮罩检查像素完美碰撞。
任何这一切都可以使用pygames精灵碰撞函数来完成,例如pygame.sprite.spritecollide()
或pygame.sprite.collide_mask()
+更多!
阅读:
http://www.pygame.org/docs/ref/sprite.html