def init_engine(self, file=block_loader.BLOCK_FILE_NAME): self.blocks_to_add = [] block_loader.load_block_types(file) self.world_generator = WorldGenerator(self)
class BlockSystem(System): """The BlockSystem is a specialized entity handler for static blocks. The catch is that it needs to be able to handle adding and removing blocks, keeping the blocks on a grid, and possibly chunking in the future. All blocks are also members on the EntityManager, so we don't have to worry about the general entity stuff.""" # block is a Dict [Nat -> Block] blocks = {} chunk_depth_sections = 1 chunk_depth = 256 size = vector3(128, 64, chunk_depth * chunk_depth_sections) block_size = 32 chunks = [] chunk_size = vector3(32, 32, chunk_depth) chunk_counts = size / chunk_size seed = 1000 resource_group_name = "BlockSystemResourceGroup" def init_engine(self, file=block_loader.BLOCK_FILE_NAME): self.blocks_to_add = [] block_loader.load_block_types(file) self.world_generator = WorldGenerator(self) def load_level_from_height_map(self): print "Generating world..." elevation = self.world_generator.generate_height_map(self.seed, int(self.size.x), int(self.size.y), .02, 10) roughness = self.world_generator.generate_height_map(self.seed * 1273, int(self.size.x), int(self.size.y), .1, 5) detail = self.world_generator.generate_height_map(self.seed * 12379, int(self.size.x), int(self.size.y), .25, 3) blocks = {} scene = set() for x in range(int(self.size.x)): for y in range(int(self.size.y)): scene.add((x, y)) max_height = int((elevation[x][y] * 5 + (roughness[x][y] * detail[x][y])) * 64) for height in range(max_height + 1): blocks[(x, height, y)] = block_loader.BLOCK_TYPES.Wood print "Adding blocks..." self.add_blocks(blocks) print "World fully generated." def load_level(self): self.generate_chunks() self.load_level_from_height_map() def generate_chunks(self): count = self.size / self.chunk_size for x in range(int(count.x)): for y in range(int(count.y)): for z in range(int(count.z)): chunk = Chunk(self.engine.graphics_system.scene_manager, self.engine.physics_system, self.resource_group_name, self.chunk_size, x * self.chunk_size.x, y * self.chunk_size.y, z * self.chunk_size.z) self.chunks.append(chunk) def crosslink(self): pass def add_block(self, block, x, y, z): """Add a block at the given grid coordinates pre: self.valid_coords(x, y, z) """ self.delegate_to_chunk(x, y, z, lambda chunk: lambda x, y, z: chunk.add_block(block, x, y, z)) def add_block_without_rebuild(self, block, x, y, z): """Add a block without rebuilding the chunk model. pre: self.valid_coords(x, y, z) """ self.delegate_to_chunk(x, y, z, lambda chunk: lambda x, y, z: chunk.add_block_without_rebuild(block, x, y, z)) # [Tuple X, Y, Z] [Type <= Block] -> def add_blocks(self, block_dict): """Add blocks all at once to avoid rebuilding for every block.""" blocks = [] chunks = set() for (x, y, z), block in block_dict.items(): print "Adding (%d, %d, %d)" % (x, y, z) chunk = self.get_chunk(x, y, z) chunks.add(chunk) chunk.add_block_without_rebuild(block, x, y, z) blocks.append(block) for chunk in chunks: print "adding chunk" chunk.create_object() def get_chunk(self, x, y, z): """Get the chunk that contains the provided coordinates. pre: self.valid_coords(x, y, z) """ for chunk in self.chunks: if chunk.grid_coords_inside(x, y, z): return chunk raise BlockSystemError("World doesn't contain a chunk at (%d, %d, %d)" % (x, y, z)) def is_empty_block(self, x, y, z): """Return true if the block at (x, y, z) is empty. pre: self.valid_coords(x, y, z) """ return self.delegate_to_chunk(x, y, z, lambda c: c.is_empty_block) def remove_block(self, x, y, z): """Remove the provided block from the world. pre: self.valid_coords(x, y, z) """ self.delegate_to_chunk(x, y, z, lambda c: c.remove_block) def remove_block_without_rebuild(self, x, y, z): """Remove the provided block from the world. pre: self.valid_coords(x, y, z) """ self.delegate_to_chunk(x, y, z, lambda c: c.remove_block_without_rebuild) def grid_to_world(self, v): """Convert a grid coordinate vector to the rendering system's coordinates""" return v * self.block_size # Nat Nat Nat -> Boolean def valid_coords(self, x, y, z): """Determine if the given world coords are valid. pre: isinstance(x, int) or isinstance(x, float) isinstance(y, int) or isinstance(x, float) isinstance(z, int) or isinstance(x, float) """ return (0 <= x < self.size.x and 0 <= y < self.size.y and 0 <= z < self.size.z) # X, Y, Z [Chunk -> [X Y Z -> 'A]] -> 'A def delegate_to_chunk(self, x, y, z, f): """Call f on the chunk at coords (x, y, z) pre: self.valid_coords(x, y, z) """ chunk = self.get_chunk(x, y, z) print x, y, z, chunk.x_off, chunk.y_off, chunk.z_off return f(chunk)(x - chunk.x_off, y - chunk.y_off, z - chunk.z_off)