Changed SurfaceSet to use QuadTreeR instead of a list
import pygame
from OpenGL.GL import *
+from util import QuadTreeR
import math
class Surface:
- fuzz = 20
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
# A collision rect for fast collision culling. Only surfaces
# whose initial rect collision check passes will run the
# detailed check
- self.rect = pygame.Rect(p1,(self.dx,self.dy))
- self.rect.normalize()
- #self.rect.width += 1
- #self.rect.height += 1
+ self.bbox = pygame.Rect(p1,(self.dx,self.dy))
+ self.bbox.normalize()
def lineSideTest(self, point):
def collidePoint(self, point):
- if self.rect.collidepoint(point[0],point[1]):
+ if self.bbox.collidepoint(point[0],point[1]):
return self.lineSideTest(point)
def collideRect(self, rect):
- if not self.rect.colliderect(rect):
+ if not self.bbox.colliderect(rect):
return False
#print self.collidePoint(rect.bottomleft), self.collidePoint(rect.bottomright), self.collidePoint(rect.topright), self.collidePoint(rect.topright)
return self.lineSideTest(rect.bottomleft) or \
glDisable(GL_TEXTURE_2D)
if self.dx > 0:
- py = self.rect.top # rects are upside-down in our space
+ py = self.bbox.top # rects are upside-down in our space
else:
- py = self.rect.bottom - 1
+ py = self.bbox.bottom - 1
if self.dy > 0:
- px = self.rect.right - 1
+ px = self.bbox.right - 1
else:
- px = self.rect.left
+ px = self.bbox.left
glColor4f(1.0,0.0,0.0,0.25)
glBegin(GL_TRIANGLES)
glVertex3f(self.p2[0], self.p2[1], 0)
glBegin(GL_LINES)
glVertex3f(self.p1[0],self.p1[1],0)
glVertex3f(self.p2[0],self.p2[1],0)
- glVertex3f(self.rect.centerx, self.rect.centery, 0)
- glVertex3f(self.rect.centerx + anglepoint[0], self.rect.centery + anglepoint[1], 0)
+ glVertex3f(self.bbox.centerx, self.bbox.centery, 0)
+ glVertex3f(self.bbox.centerx + anglepoint[0], self.bbox.centery + anglepoint[1], 0)
glEnd()
glPopMatrix()
def __init__(self, p1, p2):
self.rect = pygame.Rect(p1,(p2[0]-p1[0],p2[1]-p1[1]))
self.rect.normalize()
+ self.bbox = self.rect
def collidePoint(self, point):
class SurfaceSet:
surfaces = None
- def __init__(self, file = None):
- self.surfaces = []
- if file is not None:
- self.parse(file)
+ def __init__(self, f):
+ if isinstance(f, str) or isinstance(f, unicode):
+ fo = open(f, 'r')
+ self.parse(fo)
+ fo.close()
+ else:
+ self.parse(f)
- def parse(self, file):
- self.surfaces = []
+ def parse(self, f):
+ surfaces = []
mf = (1,1)
- f = open(file,'r')
for line in f:
args = line.split()
if not args:
elif cmd == 'surface':
p1 = (int(args[0])*mf[0],int(args[1])*mf[1])
p2 = (int(args[2])*mf[0],int(args[3])*mf[1])
- self.surfaces.append(Surface(p1,p2))
+ surfaces.append(Surface(p1,p2))
elif cmd == 'solid':
p1 = (int(args[0])*mf[0],int(args[1])*mf[1])
p2 = (int(args[2])*mf[0],int(args[3])*mf[1])
- self.surfaces.append(Solid(p1,p2))
+ surfaces.append(Solid(p1,p2))
f.close()
-
+
+ # calculate bounding box for all surfaces
+ bbox = surfaces[0].bbox.unionall([s.bbox for s in surfaces[1:]])
+ self.surfaces = QuadTreeR(bbox)
+ for s in surfaces:
+ self.surfaces.add(s.bbox, s)
+
def collidePoint(self,point):
- colliders = filter(lambda x: x.rect.collidepoint(point), self.surfaces)
- if not colliders:
- return False
- for c in colliders:
- if not c.collidePoint(point):
- return False
- return True
+ colliders = self.surfaces.collidePointWalk(point)
+ #if not colliders:
+ # return False
+ for s in colliders:
+ if s.collidePoint(point):
+ return True
+ return False
def collideRect(self, rect):
- colliders = filter(lambda x: x.rect.colliderect(rect), self.surfaces)
- if not colliders:
- return False
- #print [(c,c.rect,c.collideRect(rect)) for c in colliders]
- for c in colliders:
- if not c.collideRect(rect):
- return False
- return True
+ for s in self.surfaces.collideRectWalk(rect):
+ if s.collideRect(rect):
+ return True
+ return False
def draw(self):
for s in self.surfaces:
s.draw()
+ self.surfaces.draw()
- def append(self, s):
- return self.surfaces.append(s)
+ def add(self, s):
+ return self.surfaces.add(s.bbox, s)
def remove(self, s):
self.rects.append((pygame.Rect(rect), obj))
+ def remove(self, obj):
+ for (r, o) in self.rects:
+ if o == obj:
+ self.rects.remove((r, o))
+ return
+ if self.subregions:
+ for s in self.subregions:
+ s.remove(obj)
+
+
+ def __iter__(self):
+ for (r, o) in self.rects:
+ yield o
+ if self.subregions:
+ for s in self.subregions:
+ for o in s:
+ yield o
+
+
def collideRectWalk(self, rect):
"""generator that walks through the QuadTree, returning rects
that collide with the given rect"""
yield o
if self.subregions:
for s in self.subregions:
- if s.bbox.contains(rect):
+ if s.bbox.colliderect(rect):
for o in s.collideRectWalk(rect):
yield o
def collideRect(self, rect):
- for o in self.collisionWalk(rect):
- return o
- else:
- return None
+ return [o for o in self.collideRectWalk(rect)]
+
+
+ def collidePointWalk(self, point):
+ """generator that walks through the QuadTree, returning rects
+ that collide with the given point"""
+ for (r, o) in self.rects:
+ if r.collidepoint(point):
+ yield o
+ if self.subregions:
+ for s in self.subregions:
+ if s.bbox.collidepoint(point):
+ for o in s.collidePointWalk(point):
+ yield o
+
+
+ def collidePoint(self, point):
+ return [o for o in self.collidePointWalk(point)]
def draw(self, rect = None):
h = randint(0, 480 - y)
r.add((x,y,w,h), None)
-mouse = pygame.Rect(0, 0, 10, 10)
+mouse = pygame.Rect(0, 0, 100, 100)
Engine.init((640, 480))
from Richter.Sprite import *
from Richter.Surface import *
import Richter.Engine as Engine
+from StringIO import StringIO
#resolution = (1280,1024)
resolution = (640,480)
pygame.display.set_caption("surfacetest")
-surfaces = SurfaceSet('data/example1')
-# Octagon
-#surfaces.append(Surface( (520,240),(461,98) ))
-#surfaces.append(Surface( (461,98),(319,40) ))
-#surfaces.append(Surface( (319,40),(178,98) ))
-#surfaces.append(Surface( (178,98),(120,240) ))
-#surfaces.append(Surface( (120,240),(178,381) ))
-#surfaces.append(Surface( (178,381),(320,440) ))
-#surfaces.append(Surface( (320,440),(461,381) ))
-#surfaces.append(Surface( (461,381),(520,240) ))
+#surfaces = SurfaceSet('data/example1')
# Concave
-#surfaces.append(Surface( (200,200), (200,400) ))
-#surfaces.append(Surface( (200,400), (300,300) ))
-#surfaces.append(Surface( (300,300), (400,300) ))
-#surfaces.append(Surface( (400,300), (500,400) ))
-#surfaces.append(Surface( (500,400), (500,200) ))
-#surfaces.append(Surface( (500,200), (200,200) ))
+surfaces = SurfaceSet(StringIO("""
+tilesize 100 100
+surface 2 4 3 2
+surface 3 4 2 3
+solid 2 2 5 3
+surface 4 3 5 4
+"""))
+
+# Octagon
+#surfaces = SurfaceSet(StringIO("""
+#surface 520 240 461 98
+#surface 461 98 319 40
+#surface 319 40 178 98
+#surface 178 98 120 240
+#surface 120 240 178 381
+#surface 178 381 320 440
+#surface 320 440 461 381
+#surface 461 381 520 240
+#"""))
+
player = Sprite('img/star.png')
player.setGravity(CENTER, CENTER)