# HG changeset patch # User Simon Cross # Date 1315957541 -7200 # Node ID e0573297b17c0d2e120714d41cb40016558b7ea4 # Parent e7f65e737b0a413463ad2dd502e8330cb96d1930 Snake that moves (my god that was an epic struggle). diff -r e7f65e737b0a -r e0573297b17c mamba/mutators.py --- a/mamba/mutators.py Wed Sep 14 01:36:44 2011 +0200 +++ b/mamba/mutators.py Wed Sep 14 01:45:41 2011 +0200 @@ -1,7 +1,7 @@ """Mutations to apply to images when they're loaded.""" from pygame.transform import rotate -from pygame.locals import BLEND_ADD, BLEND_MULT +from pygame.locals import BLEND_MULT from mamba.data import load_image @@ -35,9 +35,9 @@ # sprites mutator aliases RIGHT = NULL -DOWN = R90 +UP = R90 LEFT = R180 -UP = R270 +DOWN = R270 # overlays diff -r e7f65e737b0a -r e0573297b17c mamba/snake.py --- a/mamba/snake.py Wed Sep 14 01:36:44 2011 +0200 +++ b/mamba/snake.py Wed Sep 14 01:45:41 2011 +0200 @@ -2,69 +2,60 @@ from pygame.sprite import Group from pygame.locals import BLEND_MULT -#from pygame.draw import lines -from pygame.draw import rect -from mamba.sprites import BaseSprite, tile_sizify +from mamba.constants import TILE_SIZE +from mamba.sprites import BaseSprite from mamba import mutators class Snake(object): UP, DOWN, LEFT, RIGHT = [(0, -1), (0, 1), (-1, 0), (1, 0)] - SPEED = 60.0 # pixels / s def __init__(self, tile_pos, orientation): self.segments = self.create_segments(tile_pos, orientation) self.segment_group = Group() self.segment_group.add(*self.segments) self.set_orientation(orientation) - self.pos = tile_sizify(tile_pos) - self.length = 80 - self.xs = self.snake_length(self.length) - self.ys = self.snake_length(self.length) + self.speed = 60.0 # pixel / s + self.frac_ds = 0.0 + self.segments = self.create_segments(tile_pos, orientation) + self.segment_group = Group(reversed(self.segments)) head = property(fget=lambda self: self.segments[0]) tail = property(fget=lambda self: self.segments[-1]) - def snake_length(self, size=10): - result = [] - for i in range(size): - result.append(0) - return result - def create_segments(self, tile_pos, orientation): - x, y = tile_pos + tx, ty = tile_pos dx, dy = orientation - return [Head((x, y)), - Body((x + dx, y + dy)), - Tail((x + 2 * dx, y + 2 * dy)), + return [Head((tx, ty)), + Body((tx + dx, ty + dy)), + Tail((tx + 2 * dx, ty + 2 * dy)), ] def draw(self, surface): - # self.segment_group.draw(surface) - (x, y), l = self.pos, self.length - #lines(surface, (0, 0, 255), False, [(x, y), (x + l, y)], 20) - for i in range(0, len(self.xs)): - rect(surface, (0, 0, 255), [(self.xs[i], self.ys[i]), (20, 20)]) + self.segment_group.draw(surface) def update(self, dt): - x, y = self.pos - ox, oy = self.orientation - ds = self.SPEED * dt - self.pos = (x + ox * ds, y + oy * ds) + ds = dt * self.speed + self.frac_ds + ds, self.frac_ds = divmod(ds, 1) + ds = int(ds) + while True: + tile_state = self.head.get_tile_state() + shifted, ds = self.head.shift_head(ds) + if not shifted: + break + self.head.set_orientation(self.orientation) + for segment in self.segments[1:]: + old_tile_state = segment.get_tile_state() + segment.shift_tile(tile_state) + tile_state = old_tile_state - for i in reversed(xrange(1, len(self.xs))): - self.xs[i] = self.xs[i - 1] - self.ys[i] = self.ys[i - 1] - self.xs[0] = self.pos[0] - self.ys[0] = self.pos[1] + for segment in self.segments: + segment.shift_pixels(ds) def set_orientation(self, orientation): self.orientation = orientation - #self.orientation = orientation - #for segment in self.segments: - # segment.set_orientation(self) class Segment(BaseSprite): @@ -80,7 +71,7 @@ super(Segment, self).__init__() self.set_base_image(image_name) self._colour_overlay = self.GREEN - self._orientation = Snake.UP + self.orientation = Snake.UP self.make_images() self.update_image() @@ -102,10 +93,10 @@ all_muts) def update_image(self): - self.image = self._images[self._orientation] + self.image = self._images[self.orientation] def set_orientation(self, orientation): - self._orientation = orientation + self.orientation = orientation self.update_image() def set_colour(self, colour_overlay): @@ -113,6 +104,24 @@ self.make_images() self.update_image() + def get_tile_state(self): + return self.tile_pos, self.orientation + + def shift_tile(self, tile_state): + """Shift this segment to the tile the other one was on. + + Also reset the position to be the center of the tile. + """ + tile_pos, orientation = tile_state + self.set_tile_pos(tile_pos) + self.orientation = orientation + + def shift_pixels(self, distance): + """Shift this segment a number of pixels.""" + dx, dy = self.orientation + dx, dy = distance * dx, distance * dy + self.rect = self.rect.move(dx, dy) + class Head(Segment): CLOSED = "snake-head" @@ -144,6 +153,40 @@ self.make_images() self.update_image() + def shift_head(self, ds): + """Shift the head a number of pixels in the direction of it + orientation. + """ + dx, dy = self.orientation + TX, TY = TILE_SIZE + rx, ry = self.rect.left, self.rect.top + tx, ty = self.tile_pos + # WARNING: Tri-state logic ahead + # (Tri-state logic is the mamba's natural habitat) + if dx != 0: + newdx = rx + ds * dx + newtx = newdx / TX + if newtx > tx: + self.set_tile_pos((tx + 1, ty)) + ds = newdx - self.rect.left + return True, ds + elif newtx < tx - 1: + self.set_tile_pos((tx - 1, ty)) + ds = self.rect.left - newdx + return True, ds + else: + newdy = ry + ds * dy + newty = newdy / TY + if newty > ty: + self.set_tile_pos((tx, ty + 1)) + ds = newdy - self.rect.top + return True, ds + elif newty < ty - 1: + self.set_tile_pos((tx, ty - 1)) + ds = self.rect.top - newdy + return True, ds + return False, ds + class Body(Segment): def __init__(self, tile_pos):