예제 #1
0
    def __init__(self, resource, position, progress, completed, parent_node):
        """Constructor.

        :param resource: The building resource
        :type resource: :class:`loaders.Resource`

        :param position: The position of the building
        :type position: :class:`tuple`

        :param progress: The current amount of hp and the total one
        :type progress: :class:`tuple`

        :param completed: Whether the building is completed or not
        :type completed: :class:`bool`

        :param parent_node: The parent node in the scene graph
        :type parent_node: :class:`renderer.scene.SceneNode`
        """
        self._position = position
        # Progress is going to be a property used to update only when necessary
        # the health bar.
        self._progress = progress
        self.completed = completed

        shader = resource['shader']
        texture = Texture.from_image(resource['texture'])
        self.mesh_project = resource['model_project']
        self.mesh_complete = resource['model_complete']

        # Setup the group node and add the health bar
        group_node = SceneNode()
        g_transform = group_node.transform
        g_transform.translate(to_scene(*position))
        parent_node.add_child(group_node)

        self.health_bar = HealthBar(
            resource['health_bar'], progress[0] / progress[1], group_node)

        params = {
            'tex': texture,
        }

        # create components
        renderable = Renderable(
            group_node,
            self.mesh,
            shader,
            params,
            textures=[texture],
            enable_light=True)

        # initialize entity
        super().__init__(renderable)

        # FIXME: hardcoded bounding box
        self._bounding_box = Vec(-0.5, 0, -0.5), Vec(0.5, 2, 0.5)
예제 #2
0
    def __init__(self, resource, actor_type, health, parent_node):
        """Constructor.

        :param resource: The character resource
        :type resource: :class:`loaders.Resource`

        :param health: The current amount of hp and the total one
        :type health: :class:`tuple`

        :param parent_node: The parent node in the scene graph
        :type parent_node: :class:`renderer.scene.SceneNode`
        """
        self.actor_type = actor_type

        # Health is going to be a property used to update only when necessary
        # the health bar.
        self._health = health

        shader = resource['shader']
        mesh = resource['model']['mesh']
        md = resource['model']['mesh_data']

        # root transformation to apply to the mesh
        self.transform = md.transform

        # instantiate animations
        self.init_animations(md)
        self.current_anim = self.animations[action_anim_index(ActionType.idle)]

        texture = Texture.from_image(resource['texture'])

        # shader params
        params = {
            'tex': texture,
            'opacity': 1.0,
            'color_ambient': Vec(0, 0, 0, 1),
            'color_diffuse': Vec(0, 0, 0, 1),
            'color_specular': Vec(0.1, 0.1, 0.1, 1),
        }

        # Initialize movable component
        movable = Movable((0.0, 0.0))

        # Setup the group node and add the health bar
        # FIXME: I don't like the idea of saving the group node here. We need
        # something better here.
        self.group_node = SceneNode()
        g_transform = self.group_node.transform
        g_transform.translate(to_scene(*movable.position))
        parent_node.add_child(self.group_node)

        self.health_bar = HealthBar(
            resource['health_bar'], health[0] / health[1], self.group_node,
            resource.data.get('hb_y_offset'))

        # create components
        renderable = Renderable(
            self.group_node,
            mesh,
            shader,
            params,
            textures=[texture],
            enable_light=True,
            animation=self.current_anim)

        # by default, start with playing animation
        renderable.animate = True

        # initialize actor
        super().__init__(renderable, movable)

        # FIXME: hardcoded bounding box
        self._bounding_box = Vec(-0.5, 0, -0.5), Vec(0.5, 2, 0.5)

        self.heading = 0.0
예제 #3
0
class Building(Entity):
    """Game entity which represents a building."""

    def __init__(self, resource, position, progress, completed, parent_node):
        """Constructor.

        :param resource: The building resource
        :type resource: :class:`loaders.Resource`

        :param position: The position of the building
        :type position: :class:`tuple`

        :param progress: The current amount of hp and the total one
        :type progress: :class:`tuple`

        :param completed: Whether the building is completed or not
        :type completed: :class:`bool`

        :param parent_node: The parent node in the scene graph
        :type parent_node: :class:`renderer.scene.SceneNode`
        """
        self._position = position
        # Progress is going to be a property used to update only when necessary
        # the health bar.
        self._progress = progress
        self.completed = completed

        shader = resource['shader']
        texture = Texture.from_image(resource['texture'])
        self.mesh_project = resource['model_project']
        self.mesh_complete = resource['model_complete']

        # Setup the group node and add the health bar
        group_node = SceneNode()
        g_transform = group_node.transform
        g_transform.translate(to_scene(*position))
        parent_node.add_child(group_node)

        self.health_bar = HealthBar(
            resource['health_bar'], progress[0] / progress[1], group_node)

        params = {
            'tex': texture,
        }

        # create components
        renderable = Renderable(
            group_node,
            self.mesh,
            shader,
            params,
            textures=[texture],
            enable_light=True)

        # initialize entity
        super().__init__(renderable)

        # FIXME: hardcoded bounding box
        self._bounding_box = Vec(-0.5, 0, -0.5), Vec(0.5, 2, 0.5)

    @property
    def mesh(self):
        """Returns the appropriate mesh based on the building status.

        :returns: The appropriate mesh
        :rtype: :class:`renderer.Mesh`
        """
        if not self.completed:
            return self.mesh_project
        else:
            return self.mesh_complete

    @property
    def progress(self):
        """Returns the progress of the building as a tuple current/total.

        :returns: The progress of the building
        :rtype: :class:`tuple`
        """
        return self._progress

    @progress.setter
    def progress(self, value):
        """Sets the progress of the building.

        Propagate the modification to the buliding health bar.

        :param value: The new progress
        :type value: :class:`tuple`
        """
        self._progress = value
        self.health_bar.value = value[0] / value[1]

    @property
    def position(self):
        """The position of the entity in world coordinates.

        :returns: The position
        :rtype: :class:`tuple`
        """
        return self._position

    @property
    def bounding_box(self):
        """The bounding box of the entity.

        The bounding box is represented by the smaller and bigger edge of the box
        itself.

        :returns: The bounding box of the actor
        :rtype: :class:`tuple`
        """
        l, m = self._bounding_box
        pos = self.position
        return l + Vec(pos[0], 0, pos[1]), m + Vec(pos[0], 0, pos[1])

    def destroy(self):
        """Removes itself from the scene.
        """
        LOG.debug('Destroying building {}'.format(self.e_id))

        # Destroys the health bar first.
        self.health_bar.destroy()

        node = self[Renderable].node
        node.parent.remove_child(node)

    def update(self, dt):
        """Updates the building.

        Applies the status of the building in terms of shader params and meshes.

        :param dt: Time delta from last update.
        :type dt: float
        """
        node = self[Renderable].node
        node.mesh = self.mesh

        # Update the health bar
        self.health_bar.update(dt)
예제 #4
0
class Actor(Entity):
    """Game entity which represents an actor."""

    # *FIXME* *FIXME* *FIXME*
    # REFACTOR THIS!!!
    TRANSFORMS = {
        ActorType.grunt: (pi, 0.12),
        ActorType.programmer: (pi, 0.022),
        ActorType.engineer: (pi, 5.5),
        ActorType.zombie: (pi, 0.05),
    }

    def init_animations(self, mesh_data):
        self.animations = {}
        for i in range(3):
            try:
                self.animations[i] = AnimationInstance(mesh_data.animations[i])
            except IndexError:
                self.animations[i] = None

    def __init__(self, resource, actor_type, health, parent_node):
        """Constructor.

        :param resource: The character resource
        :type resource: :class:`loaders.Resource`

        :param health: The current amount of hp and the total one
        :type health: :class:`tuple`

        :param parent_node: The parent node in the scene graph
        :type parent_node: :class:`renderer.scene.SceneNode`
        """
        self.actor_type = actor_type

        # Health is going to be a property used to update only when necessary
        # the health bar.
        self._health = health

        shader = resource['shader']
        mesh = resource['model']['mesh']
        md = resource['model']['mesh_data']

        # root transformation to apply to the mesh
        self.transform = md.transform

        # instantiate animations
        self.init_animations(md)
        self.current_anim = self.animations[action_anim_index(ActionType.idle)]

        texture = Texture.from_image(resource['texture'])

        # shader params
        params = {
            'tex': texture,
            'opacity': 1.0,
            'color_ambient': Vec(0, 0, 0, 1),
            'color_diffuse': Vec(0, 0, 0, 1),
            'color_specular': Vec(0.1, 0.1, 0.1, 1),
        }

        # Initialize movable component
        movable = Movable((0.0, 0.0))

        # Setup the group node and add the health bar
        # FIXME: I don't like the idea of saving the group node here. We need
        # something better here.
        self.group_node = SceneNode()
        g_transform = self.group_node.transform
        g_transform.translate(to_scene(*movable.position))
        parent_node.add_child(self.group_node)

        self.health_bar = HealthBar(
            resource['health_bar'], health[0] / health[1], self.group_node,
            resource.data.get('hb_y_offset'))

        # create components
        renderable = Renderable(
            self.group_node,
            mesh,
            shader,
            params,
            textures=[texture],
            enable_light=True,
            animation=self.current_anim)

        # by default, start with playing animation
        renderable.animate = True

        # initialize actor
        super().__init__(renderable, movable)

        # FIXME: hardcoded bounding box
        self._bounding_box = Vec(-0.5, 0, -0.5), Vec(0.5, 2, 0.5)

        self.heading = 0.0

    @property
    def health(self):
        """Returns the health of the character as a tuple current/total.

        :returns: The health of the character
        :rtype: :class:`tuple`
        """
        return self._health

    @health.setter
    def health(self, value):
        """Sets the health of the character.

        Propagate the modification to the buliding health bar.

        :param value: The new health
        :type value: :class:`tuple`
        """
        self._health = value
        self.health_bar.value = value[0] / value[1]

    @property
    def position(self):
        """The position of the actor in world coordinates.

        :returns: The position
        :rtype: :class:`tuple`
        """
        return self[Movable].position

    @property
    def bounding_box(self):
        """The bounding box of the entity.

        The bounding box is represented by the smaller and bigger edge of the box
        itself.

        :returns: The bounding box of the actor
        :rtype: :class:`tuple`
        """
        l, m = self._bounding_box
        pos = self.position
        return l + Vec(pos[0], 0, pos[1]), m + Vec(pos[0], 0, pos[1])

    def orientate(self):
        """Orientate the character towards the current destination.
        """
        direction = self[Movable].direction
        if direction:
            dx = direction.x
            dy = direction.y
            if dx:
                target_heading = atan(dy / dx) + (pi / 2) * copysign(1, dx)
            else:
                target_heading = pi if dy > 0 else 0

            # Compute remaining rotation
            delta = target_heading - self.heading
            abs_delta = abs(delta)
            if abs_delta > WHOLE_ANGLE / 2:
                abs_delta = WHOLE_ANGLE - abs(delta)
                delta = -delta

            # tweak speed (XXX: make it more rational)
            rot_speed = abs_delta * 2 * pi / 40
            if abs_delta < rot_speed * 2:
                # Rotation is complete within a small error.
                # Force it to the exact value:
                self.heading = target_heading
                return

            self.heading += copysign(1, delta) * rot_speed

            # normalize angle to be in (-pi, pi)
            if self.heading >= WHOLE_ANGLE / 2:
                self.heading = -WHOLE_ANGLE + self.heading
            if self.heading < -WHOLE_ANGLE / 2:
                self.heading = WHOLE_ANGLE + self.heading

    def destroy(self):
        """Removes itself from the scene.
        """
        LOG.debug('Destroying character {}'.format(self.e_id))
        node = self.group_node
        node.parent.remove_child(node)

    def set_action(self, action_type):
        """Sets current player action.

        :param action_type: Action to set.
        :type action_type: :class:`game.entities.actor.ActionType`
        """
        anim = self.animations[action_anim_index(action_type)]
        self[Renderable].animation = self.current_anim = anim

    def update(self, dt):
        """Update the character.

        This method computes character's game logic as a function of time.

        :param dt: Time delta from last update.
        :type dt: float
        """
        self[Movable].update(dt)
        x, y = self[Movable].position

        # FIXME: I don't like the idea of saving the group node here. We need
        # something better here.
        g_t = self.group_node.transform
        g_t.identity()
        g_t.translate(to_scene(x, y))

        rot, scale = self.TRANSFORMS[self.actor_type]
        t = self[Renderable].transform
        t.identity()
        t *= self.transform
        t.rotate(Vec(0, 1, 0), rot)  # FIXME
        t.rotate(Vec(0, 1, 0), -self.heading)
        t.scale(Vec(scale, scale, scale))

        self.orientate()

        # Update the health bar
        self.health_bar.update(dt)

        # play animation
        if self.current_anim:
            self.current_anim.play(dt)