Package gameobjects :: Module grid
[hide private]
[frames] | no frames]

Source Code for Module gameobjects.grid

  1   
  2  from locals import WRAP_REPEAT, WRAP_CLAMP, WRAP_ERROR 
  3  from util import saturate 
  4   
5 -class Grid(object):
6
7 - def __init__( self, node_factory, 8 width, 9 height, 10 x_wrap = WRAP_ERROR, 11 y_wrap = WRAP_ERROR ):
12 13 """Create a grid object. 14 15 node_factory -- Callable that takes the x and y coordinate of the node 16 and returns a node object. x_wrap and y_wrap parameters should be 17 one of (WRAP_REPEAT, WRAP_CLAMP, WRAP_ERROR). 18 19 width -- Width of the grid. 20 height -- Height of the grid. 21 x_wrap -- How to handle out of range x coordinates 22 y_wrap -- How to handle out of range y coordinates 23 24 """ 25 26 self.node_factory = node_factory 27 self.width = width 28 self.height = height 29 30 self.nodes = [ [node_factory(x, y) for x in xrange(width)] \ 31 for y in xrange(height)] 32 33 self._x_wrap = x_wrap 34 self._y_wrap = y_wrap 35 36 self._wrap_functions = [ self._make_wrap(self._x_wrap, self.width), 37 self._make_wrap(self._y_wrap, self.height) ]
38 39
40 - def _get_x_wrap(self):
41 return self._x_wrap
42 - def _set_x_wrap(self, x_wrap):
43 self._x_wrap = x_wrap 44 self._wrap_functions[0] = self._make_wrap(x_wrap, self.width)
45 x_wrap = property(_get_x_wrap, _set_x_wrap, None, "X wrap") 46
47 - def _get_y_wrap(self):
48 return self._y_wrap
49 - def _set_y_wrap(self, y_wrap):
50 self._y_wrap = y_wrap 51 self._wrap_functions[1] = self._make_wrap(y_wrap, self.height)
52 y_wrap = property(_get_y_wrap, _set_y_wrap, None, "Y wrap") 53 54
55 - def _make_wrap(self, wrap, edge):
56 57 if wrap == WRAP_NONE: 58 def do_wrap(value): 59 return value
60 61 elif wrap == WRAP_REPEAT: 62 def do_wrap(value): 63 return value % edge
64 65 elif wrap == WRAP_CLAMP: 66 def do_wrap(value): 67 if value < 0: 68 return 0 69 if value >= edge: 70 value = edge 71 return value 72 73 elif wrap == WRAP_ERROR: 74 def do_wrap(value): 75 if value < 0 or value >= edge: 76 raise IndexError("coordinate out of range") 77 78 else: 79 raise ValueError("Unknown wrap mode") 80 81 return do_wrap 82 83
84 - def wrap(self, coord):
85 86 x, y = coord 87 wrap_x, wrap_y = self._wrap_functions 88 return ( wrap_x(x), wrap_y(y) )
89 90
91 - def wrap_x(self, x):
92 """Wraps an x coordinate. 93 94 x -- X Coordinate 95 96 """ 97 98 return self._wrap_functions[0](x)
99
100 - def wrap_y(self, y):
101 """Wraps a y coordinate. 102 103 y -- Y Coordinate. 104 105 """ 106 107 return self._wrap_functions[1](y)
108 109
110 - def get_size(self):
111 112 """Retrieves the size of the grid as a tuple (width, height).""" 113 114 return self.width, self.height
115 116
117 - def __getitem__(self, coord):
118 119 x, y = coord 120 121 if isinstance(x, slice) or isinstance(y, slice): 122 if isinstance(x, slice): 123 x_indices = x.indices(self.width) 124 else: 125 x_indices = [x] 126 127 if isinstance(y, slice): 128 y_indices = y.indices(self.height) 129 else: 130 y_indices = [y] 131 132 try: 133 wrap_x, wrap_y = self._wrap_functions 134 135 ret = [] 136 137 for y_index in xrange(*y_indices): 138 nodes_y = self.nodes[ wrap_y(y_index) ] 139 140 for x_index in xrange(*x_indices): 141 ret.append( nodes_y[ wrap_x(x_index) ] ) 142 143 except IndexError: 144 raise IndexError("Slice out of range") 145 146 return ret 147 148 149 x, y = self.wrap(coord) 150 151 if x < 0 or y < 0: 152 raise IndexError("coordinate out of range") 153 154 try: 155 return self.nodes[y][x] 156 except IndexError: 157 raise IndexError("coordinate out of range")
158 159
160 - def __iter__(self):
161 162 for row in self.nodes: 163 for node in row: 164 yield node
165 166
167 - def __contains__(self, value):
168 169 for row in self.nodes: 170 if node in row: 171 return True 172 173 return False
174 175
176 - def clear(self):
177 178 """Resets the grid.""" 179 180 node_factory = self.node_factory 181 182 self.nodes[:] = [ [node_factory(x, y) for x in xrange(width)] \ 183 for y in xrange(height)]
184 185
186 - def get(self, coord, default=None):
187 188 """Retrieves a node from the grid. 189 190 coord -- Coordinate to retrieve 191 default -- Default value to use if coord is out of range 192 193 """ 194 195 x, y = self.wrap(coord) 196 197 if x < 0 or y < 0 or x >= self.width or y >= self.height: 198 if default is not None: 199 return default 200 else: 201 raise IndexError("coordinate out of range") 202 203 return self.nodes[y][x]
204 205
206 - def get_nodes(self, coord, size, wrap=False):
207 208 width = self.width 209 height = self.height 210 211 x1, y1 = coord 212 x1 = saturate(x1, 0, width) 213 y1 = saturate(y1, 0, height) 214 w, h = size 215 x2, y2 = (x+w, y+h) 216 x = saturate(x, 0, width) 217 y = saturate(y, 0, height) 218 219 if x1 > x2: 220 x1, x2 = x2, x1 221 if y1 > y2: 222 y1, y2 = y2, y1 223 224 wrap_x, wrap_y = self._wrap_functions 225 226 nodes = self.nodes 227 return [self.nodes[y_coord][x1:x2] for y_coord in xrange(y1, y2)]
228 229 230 231 232 if __name__ == "__main__": 233
234 - class Square(object):
235 - def __init__(self, x, y):
236 self.coord = (x, y)
237 - def __str__(self):
238 return str(self.coord)
239 - def __repr__(self):
240 return str(self.coord)
241 242 g = Grid(Square, 100, 100, x_wrap = WRAP_REPEAT) 243 244 for square in g: 245 print str(square) 246 247 print g[10:20, 10:20] 248 print g.get_nodes((-2, 0), (5, 5)) 249