Example #1
0
 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)
Example #2
0
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)