view nagslang/protagonist.py @ 104:1be3eebb87c4

More consistent debug rendering.
author Jeremy Thurgood <firxen@gmail.com>
date Mon, 02 Sep 2013 13:21:53 +0200
parents 93aa745d57ff
children b90d01e4d9d4
line wrap: on
line source

import pymunk
import pymunk.pygame_util

from nagslang.constants import COLLISION_TYPE_PLAYER
from nagslang.game_object import (
    GameObject, SingleShapePhysicser, FacingImageRenderer)
from nagslang.mutators import FLIP_H
from nagslang.resources import resources


class Protagonist(GameObject):
    """Representation of our fearless protagonist.

    TODO: Factor out a bunch of this stuff when we need it for other objects.
    """

    HUMAN_FORM = 'human'
    WOLF_FORM = 'wolf'

    def __init__(self, space, position):
        self._setup_physics(space, position)
        self._setup_renderers()
        self.inventory = {}
        self.form = self.HUMAN_FORM

        super(Protagonist, self).__init__(
            self._physicsers[self.form], self._renderers[self.form])

        self.go_human()

    def _setup_physics(self, space, position):
        self._body = pymunk.Body(10, pymunk.inf)
        self._body.position = position
        self._body.velocity_func = self.velocity_func

        self._shapes = {
            self.HUMAN_FORM: pymunk.Poly(
                self._body, [(-15, -30), (15, -30), (15, 30), (-15, 30)]),
            self.WOLF_FORM: pymunk.Circle(self._body, 30),
        }
        self._physicsers = {}
        for form, shape in self._shapes.iteritems():
            shape.elasticity = 1.0
            shape.friction = 10.0
            shape.collision_type = COLLISION_TYPE_PLAYER
            self._physicsers[form] = SingleShapePhysicser(space, shape)
        self.angle = 0

    def _get_image(self, name, *transforms):
        return resources.get_image('creatures', name, transforms=transforms)

    def _setup_renderers(self):
        self._renderers = {
            self.HUMAN_FORM: FacingImageRenderer(
                self._shapes[self.HUMAN_FORM],
                self._get_image('human_1.png'),
                self._get_image('human_1.png', FLIP_H)),
            self.WOLF_FORM: FacingImageRenderer(
                self._shapes[self.WOLF_FORM],
                self._get_image('werewolf_1.png'),
                self._get_image('werewolf_1.png', FLIP_H)),
        }

    @classmethod
    def from_saved_state(cls, saved_state):
        """Create an instance from the provided serialised state.
        """
        obj = cls()
        # TODO: Update from saved state.
        return obj

    def velocity_func(self, body, gravity, damping, dt):
        return pymunk.Body.update_velocity(body, gravity, self.damping, dt)

    def get_render_angle(self):
        return self.angle

    def go_werewolf(self):
        self._physicsers[self.form].remove_from_space()
        self.form = self.WOLF_FORM
        self._physicsers[self.form].add_to_space()
        self._body.mass = 100
        self._body.velocity_limit = 1000
        self.impulse_factor = 4000
        self.damping = 0.9
        self.renderer = self._renderers[self.form]

    def go_human(self):
        self._physicsers[self.form].remove_from_space()
        self.form = self.HUMAN_FORM
        self._physicsers[self.form].add_to_space()
        self._body.mass = 10
        self._body.velocity_limit = 1000
        self.impulse_factor = 500
        self.damping = 0.8
        self.renderer = self._renderers[self.form]

    def set_direction(self, dx, dy):
        if (dx, dy) == (0, 0):
            return
        self.angle = pymunk.Vec2d((dx, dy)).angle
        self._body.apply_impulse(
            (dx * self.impulse_factor, dy * self.impulse_factor))

    def toggle_form(self):
        if self.form == self.WOLF_FORM:
            self.go_human()
        else:
            self.go_werewolf()

    def act_on(self, target):
        """Perform an action on the target.
        """
        # TODO: Decide how best to do this.
        pass

    def attack(self):
        """Attempt to hurt something.
        """
        pass

    def in_wolf_form(self):
        return self.form == self.WOLF_FORM

    def in_human_form(self):
        return self.form == self.HUMAN_FORM

    def has_item(self, item):
        return item in self.inventory

    def environmental_movement(self, dx, dy):
        if (dx, dy) == (0, 0):
            return
        self._body.apply_impulse((dx, dy))