Esempio n. 1
0
class Camera:
    def __init__(self, track, map):

        self._track_obj = track


        position = self._track_obj.getPosition()
        self._target = Verlet(position)
        self._pos = Verlet(position + (1,0,0))
        self._map = map

        self._pos.setGravity(0)
        self._target.setGravity(0)

        self._pos.setDamping((0.3,0.3,0.99))
        self._target.setDamping(0.3)

        self._up = N.array((0,0,1),dtype="f")
        self._look_at = position

    @profile
    def update(self,time):
        self._pos.update()
        self._target.update()

        look_at = self._track_obj.getPosition()+(0,0,0.6)
        cam_pos = look_at -self._track_obj.getFrontVector() * 2.0  + N.array((0,0,0.0))

        self._pos.impulseTowards(cam_pos)
        self._target.impulseTowards(look_at)

        # see if the camera doesn't intersect geometry. If it does, push it up

        cam_pos =self._pos.getPosition()
        look_at = self._target._position
        dv = cam_pos - look_at


        dist = T.vector_norm(dv[0:2]) # distance across floor

        n = math.ceil(dist / 0.2)

        z0 = look_at[2]
        dray = dv / n
        m = self._map

        hit = False

        # ray-march
        #z_list = []
        ray_pos = look_at + dray # advance once
        for i in xrange(1,int(n)+3): # start at i=1 to avoid division by zero
            z = m(ray_pos[0], ray_pos[1], False)+0.4 # is an offset so the camera can see
            #z_list.append(int(z*10))
            if z > ray_pos[2]:
                slope = (z-z0) / float(i)
                #if slope > 0.1:
                #   ray_pos -= dray # go back one step
                #   break
                dray[2] = slope
                ray_pos[2] = z
                hit = True

            ray_pos += dray

        ray_pos -= dray*3

        #print z_list
        #print "%s -> %s   %s" % (self._pos.getPosition(), ray_pos, "HIT" if hit else "")

        if hit:
            self._pos.moveTo(ray_pos)







    def getMatrix(self):
        return lookAtMtx(self._pos._position, self._target._position, self._up)
Esempio n. 2
0
class Player(Entity):
    def __init__(self, map, position):

        print "New player"

        Entity.__init__(self)
        self._lock = None
        self._phys = Verlet(position)
        self._phys.setDamping((0.02, 0.02, 0.0002))
        self._phys.setGravity((0, 0, -0.00006))

        self._on_floor = False
        self._speed = 0

        self._map = map
        self._heading = 0
        self.reset()

        r = self._radius = 0.1

        self.setBounds(((-r, -r, -r), (r, r, r)))  # entity stuff
        Entity.moveTo(self, position)  # keep the entity updated

        self._scaling = T.scale_matrix(self._radius)

        self._last_pos = N.array((0, 0, 0), dtype="f")

        self._graphics = R.loadObject("sphere.obj", "diffuse")

    def getMissile(self, scene):

        if self._lock is not None:
            follow = self._lock[0]
        else:
            follow = None

        m_dir = 50 * (self._speed + 0.02) * self._front_vec * 1.5 + self._normal
        T.unit_vector(m_dir, out=m_dir)

        return Missile(scene, self._pos, m_dir, "projectile", follow)

    def reset(self, position=None):
        self._rotation = T.quaternion_about_axis(0, (1, 0, 0))
        self.setHeading(0)
        if position is not None:
            self.moveTo(position)

    def checkLock(self, enemy):
        best_d = 100000 if self._lock is None else self._lock[1]
        if enemy._closing:
            return
        v = enemy._pos - self._pos
        d = N.dot(v, v)
        if d < 1000:  # max enemy distance
            if self._lock is None or best_d > d:
                self._lock = (enemy, d, enemy._pos)

    def getLockPosition(self):
        try:
            return self._lock[2]  # enemy position when locked
        except:
            return None

    # for physics simulation
    @profile
    def update(self, time):
        self._lock = None

        # ----- here be dragons

        ph = self._phys

        ph._impuse = ph._gravity

        ph.update()

        # test for collision with map
        z, normal = self._map(ph._position[0], ph._position[1])

        h = (z + self._radius) - ph._position[2]

        T.unit_vector(normal, out=normal)

        self._on_floor = h > 0

        if self._on_floor and ph._position[2] < ph._last_position[2]:  # collision
            ph._impulse += h * normal * 0.00001  # * normal[2]
            ph._position[2] += h
            ph._last_position[2] += h

        new_pos = ph._position

        # -----

        self._dir = new_pos - self._pos

        self._speed = T.vector_norm(self._dir)

        self._last_pos[:] = new_pos

        Entity.moveTo(self, new_pos)  # updates self._pos too

        self._normal = normal

        self._axis = N.cross(self._dir, normal)

        self.roll(self._axis)

    def moveTo(self, pos):
        dp = pos - self._pos
        Entity.moveTo(pos)
        self._phys.displace(dp)

    def roll(self, axis):
        len = T.vector_norm(axis) * 5.0
        rot = T.quaternion_about_axis(-len, axis)
        self._rotation = T.quaternion_multiply(rot, self._rotation)

    def getHeading(self):
        return self._heading

    def setHeading(self, new_angle):
        self._heading = new_angle
        self._front_vec = N.array((math.cos(new_angle), math.sin(new_angle), 0), dtype="f")

    def alterHeading(self, delta_angle):
        if delta_angle != 0:
            self.setHeading(self._heading + delta_angle)

    def advance(self, amount):
        if amount == 0:
            return

        r = N.cross(self._normal, self._front_vec)
        T.unit_vector(r, out=r)

        # vector facing front, parallel to the floor
        front = N.cross(r, self._normal)

        self._phys.impulse(front * amount)

    def getFrontVector(self):
        return self._front_vec

    def draw(self, scene):
        self._graphics.draw(scene, mmult(self._pos_m, T.quaternion_matrix(self._rotation), self._scaling))

    def jump(self):
        if self._on_floor:
            self._phys._last_position = self._phys._position - self._normal * 0.1