from Sprite import *
class Actor:
def __init__(self, surfaces = None, position = [0,0]):
self.states = {}
self.currentstatename = None
self.currentstate = None
self.surfaces = surfaces
self.position = position
self.hitbox = None
self.colliding = set()
def defineState(self, statename, sprite):
if self.states.has_key(statename):
print "WARNING: Redefining state", statename
self.states[statename] = sprite
def setState(self, statename):
self.currentstatename = statename
self.currentstate = self.states[statename]
self.currentstate.reset()
self.currentstate.play()
self.currentstate.setPosition(self.position[0], self.position[1])
self.hitbox = self.currentstate.hitbox
def setPosition(self, x, y):
self.position = [x,y]
self.currentstate.setPosition(x, y)
def collideDelta(self, delta):
if not self.surfaces:
return False
s = self.currentstate
new_hitbox = s.hitbox.move(delta[0], delta[1])
if self.surfaces.collideRect(new_hitbox):
return True
else:
return False
def moveDelta(self, delta):
collided = False
s = self.currentstate
d = [0,0]
if self.surfaces.collideRect(s.hitbox) or (delta[0] == 0 and delta[1] == 0):
return (True, (0,0))
if abs(delta[0]) > abs(delta[1]):
dx = delta[0] / abs(delta[0])
dy = float(delta[1]) / float(abs(delta[0]))
xrange = abs(int(delta[0]))
while xrange > 0:
d[0] += dx
d[1] += dy
nrect = s.hitbox.move(d[0],d[1])
if self.surfaces.collideRect(nrect):
nrect = s.hitbox.move(d[0],d[1]-dy)
if not self.surfaces.collideRect(nrect):
d[1] -= dy
xrange -= 1
continue
nrect = s.hitbox.move(d[0]-dx,d[1])
if dy != 0 and not self.surfaces.collideRect(nrect):
d[0] -= dx
xrange -= 1
continue
d[0] -= dx
d[1] -= dy
collided = True
break
xrange -= 1
d[1] = int(d[1])
else:
dy = delta[1] / abs(delta[1])
dx = float(delta[0]) / float(abs(delta[1]))
yrange = abs(int(delta[1]))
while yrange > 0:
d[1] += dy
d[0] += dx
nrect = s.hitbox.move(d[0],d[1])
if self.surfaces.collideRect(nrect):
nrect = s.hitbox.move(d[0]-dx,d[1])
if not self.surfaces.collideRect(nrect):
d[0] -= dx
yrange -= 1
continue
nrect = s.hitbox.move(d[0],d[1]-dy)
if dx != 0 and not self.surfaces.collideRect(nrect):
d[1] -= dy
yrange -= 1
continue
d[1] -= dy
d[0] -= dx
collided = True
break
yrange -= 1
d[0] = int(d[0])
return (collided, d)
def move(self, delta):
(collided, delta) = self.moveDelta(delta)
self.position[0] += delta[0]
self.position[1] += delta[1]
self.currentstate.setPosition(self.position[0], self.position[1])
if collided:
self.hitWall()
return collided
def collideCheck(self, objs):
if not self.surfaces: return
remove = []
for o in self.colliding:
if not self.hitbox.colliderect(o.hitbox):
remove.append(o)
for o in remove:
self.colliding.remove(o)
o.colliding.remove(self)
self.collideEnd(o)
o.collideEnd(self)
for i in self.hitbox.collidelistall(filter(None, [o.hitbox for o in objs])):
o = objs[i]
if o is self: continue
if o not in self.colliding:
self.colliding.add(o)
o.colliding.add(self)
self.collideStart(o)
o.collideStart(self)
def hitWall(self):
"Called when this object hits a wall after attempting to move"
pass
def collideStart(self, obj):
"Called when this object begins colliding with another"
pass
def collideEnd(self, obj):
"Called when this object stops colliding with another"
pass
def update(self):
"Override this function. Called once per frame."
pass
def draw(self):
self.currentstate.draw()