示例#1
0
    def canCapture(s, point, distance, targetPlanet):
        if s.isParent(targetPlanet):
            #print "Nope, is parent"
            return False
        if targetPlanet.parent != None:
            #print "Nope, has parent"
            return False
        if targetPlanet == s:
            #print "Nope, self"
            return False
        if s in targetPlanet.children:
            #print "Nope, is a child already"
            return False

        vecBetweenPlanets = vec.sub(targetPlanet.loc, s.loc)
        # Adjust distance to measure from surface to surface, not center
        # to center
        distance += s.radius + targetPlanet.radius
        if vec.magSquared(vecBetweenPlanets) > (distance * distance):
            #print "Nope, out of range"
            return False

        # Okay we are close enough to an eligible planet, are we facing it?
        angleBetweenPlanets = vec.toAngle(vecBetweenPlanets)
        # Urrrrrg I hate this, -180 to 180 and 0-360 behave differently and both are
        # awful in different situations so neither one is really correct.
        point = (point + 360) % 360
        angleBetweenPlanets = (angleBetweenPlanets + 360) % 360
        #print "Point and angle:", point, angleBetweenPlanets
        if abs(angleBetweenPlanets - point) < 10:
            #print "Yep!"
            return True

        #print "Nope, angle too great", angleBetweenPlanets, point, abs(angleBetweenPlanets - point)
        return False

        vecBetweenPlanets = vec.sub(targetPlanet.loc, s.loc)
        vecBPU = vec.unit(vecBetweenPlanets)
        vecToPlanetEdge = vec.mul(vec.perpendicular(vecBPU),
                                  targetPlanet.radius)
        #print("Vec between planets: {0}, vec to planet edge: {1}".format(vecBPU, vec.unit(vecToPlanetEdge)))
        angularSize = vec.angleBetween(
            vecBetweenPlanets, vec.add(vecBetweenPlanets, vecToPlanetEdge))
        vecToPoint = vec.mul(vec.fromAngle(point), s.radius)
        angularDistance = vec.angleBetween(vecBetweenPlanets, vecToPoint)
        #print("Angular size: {0}, angular distance: {1}".format(angularSize, angularDistance))
        if angularDistance > abs(angularSize):
            return False
        else:
            # Check distance between planets surfaces
            distance = distance + (s.radius + targetPlanet.radius)
            # Can't capture a planet if you're overlapping it
            # XXX: Doesn't seem to work, but...
            if distance < 0:
                return False
            return vec.within(s.loc, targetPlanet.loc, distance)
示例#2
0
    def arc_left(
        self, arc_angle, radius=None, center=None, start_slant=None, end_slant=None,
    ):
        if (
            (radius is None and center is None)
            or (radius is not None and center is not None)
        ):
            raise TypeError('You must specify exactly one of center or radius.')

        arc_angle = Angle(arc_angle)
        # Create a radius vector, which is a vector from the arc center to the
        # current position. Subtract to find the center, then rotate the radius
        # vector to find the arc end point.
        if center is None:
            if arc_angle < 0:
                radius = -abs(radius)
            v_radius = vec.neg(vec.perp(self._vector(radius)))
            center = vec.sub(self._position, v_radius)
        elif radius is None:
            v_radius = vec.vfrom(center, self._position)
            radius = vec.mag(v_radius)
            if arc_angle < 0:
                radius = -radius

        endpoint = vec.add(center, vec.rotate(v_radius, arc_angle.rad))

        self._arc(
            center,
            radius,
            endpoint,
            arc_angle,
            start_slant=start_slant,
            end_slant=end_slant,
        )
示例#3
0
    def arc_left(
        self, arc_angle, radius=None, center=None, start_slant=None, end_slant=None,
    ):
        if (
            (radius is None and center is None) or
            (radius is not None and center is not None)
        ):
            raise TypeError('You must specify exactly one of center or radius.')

        arc_angle = Angle(arc_angle)
        # Create a radius vector, which is a vector from the arc center to the
        # current position. Subtract to find the center, then rotate the radius
        # vector to find the arc end point.
        if center is None:
            if arc_angle < 0:
                radius = -abs(radius)
            v_radius = vec.neg(vec.perp(self._vector(radius)))
            center = vec.sub(self._position, v_radius)
        elif radius is None:
            v_radius = vec.vfrom(center, self._position)
            radius = vec.mag(v_radius)
            if arc_angle < 0:
                radius = -radius

        endpoint = vec.add(center, vec.rotate(v_radius, arc_angle.rad))

        self._arc(
            center,
            radius,
            endpoint,
            arc_angle,
            start_slant=start_slant,
            end_slant=end_slant,
        )
示例#4
0
    def rebound(self, *args, **kwargs):
        v_initial = self.velocity
        super(Player, self).rebound(*args, **kwargs)
        v_final = self.velocity

        # Apply damage based on the difference in momentum.
        v_diff = vec.sub(v_final, v_initial)
        self.damage += vec.mag(v_diff) * self.mass
示例#5
0
    def rebound(self, *args, **kwargs):
        v_initial = self.velocity
        super(Player, self).rebound(*args, **kwargs)
        v_final = self.velocity

        # Apply damage based on the difference in momentum.
        v_diff = vec.sub(v_final, v_initial)
        self.damage += vec.mag(v_diff) * self.mass
示例#6
0
 def capture(s, victimPlanet):
     # This vector points from self to the victim planet
     distance = vec.sub(s.loc, victimPlanet.loc)
     victimPlanet.parentVec = distance
     victimPlanet.parent = s
     victimPlanet.capturedFacing = victimPlanet.facing
     victimPlanet.capturedParentFacing = s.facing
     s.children.append(victimPlanet)
     victimPlanet.genCaptureImage()
示例#7
0
def draw_graph(graph):
    gap_size = 0.25

    p = canoepaddle.Pen()
    p.stroke_mode(0.1, 'black')
    for a, b in graph_edges(graph):
        gap = vec.norm(vec.vfrom(a, b), gap_size)
        p.move_to(vec.add(a, gap))
        p.line_to(vec.sub(b, gap))

    return p.paper
示例#8
0
def balls_collisions(balls):
    collided = False
    for b1 in balls:
        for b2 in balls:
            if b1 is b2:
                continue

            d = vec.sub(b1.pos, b2.pos)
            penetration = (b1.radius + b2.radius) - vec.len(d)
            if penetration < 0:
                continue

            collided = True
            n = vec.unit(d)
            b1.pos = vec.add(b1.pos, vec.scale(n, penetration / 2 + 1))
            b2.pos = vec.add(b2.pos, vec.scale(n, -penetration / 2 - 1))

            j = vec.dot(vec.sub(b2.speed, b1.speed), n)
            b1.speed = vec.add(b1.speed, vec.scale(n, j))
            b2.speed = vec.add(b2.speed, vec.scale(n, -j))

    return collided
示例#9
0
文件: planar.py 项目: nickoala/openrv
    def project(self, points, reverse=False):
        if reverse:
            if self.H_ is None:
                self.H_ = mtx.lu([r[:] for r in self.H])

            qs = [
                mtx.solve(self.H_,
                          vec.sub(p, self.offset) + [1]) for p in points
            ]
            return [vec.div(q[:-1], q[-1]) for q in qs]
        else:
            qs = [mtx.mul(self.H, p + [1]) for p in points]
            return [vec.add(self.offset, vec.div(q[:-1], q[-1])) for q in qs]
示例#10
0
 def draw(s, gs):
     sx, sy = gs.screenCoords(s.loc)
     s.sprite.x = sx
     s.sprite.y = sy
     s.sprite.rotation = s.facing
     s.sprite.draw()
     if s.parent != None:
         #parentSloc = gs.screenCoords(s.parent.loc)
         vecToParent = vec.sub(s.parent.loc, s.loc)
         angle = vec.toAngle(vecToParent)
         centerPointVec = vec.div(vecToParent, 2)
         actualVec = vec.add(s.loc, centerPointVec)
         s.captureSprite.position = gs.screenCoords(actualVec)
         s.captureSprite.rotation = angle
         s.captureSprite.draw()
示例#11
0
    def collide_wall(self, p):
        restitution = self.restitution * p.restitution

        # First, check that we haven't crossed through the wall due to
        # extreme speed and low framerate.
        intersection = intersect_segments(self.p1, self.p2, p.last_pos, p.pos)
        if intersection:
            p.pos = p.last_pos
            p.rebound(self.normal, intersection, restitution)
            return

        # Find vectors to each endpoint of the segment.
        v1 = vec.vfrom(self.p1, p.pos)
        v2 = vec.vfrom(self.p2, p.pos)

        # Find a perpendicular vector from the wall to p.
        v_dist = vec.proj(v1, self.normal)

        # Test distance from the wall.
        radius2 = p.radius**2
        if vec.mag2(v_dist) > radius2:
            return

        # Test for collision with the endpoints of the segment.
        # Check whether p is too far off the end of the segment, by checking
        # the sign of the vector projection, then a radius check for the
        # distance from the endpoint.
        if vec.dot(v1, self.tangent) < 0:
            if vec.mag2(v1) <= radius2:
                p.rebound(v1, self.p1, restitution)
            return
        if vec.dot(v2, self.tangent) > 0:
            if vec.mag2(v2) <= radius2:
                p.rebound(v2, self.p2, restitution)
            return

        # Test that p is headed toward the wall.
        if vec.dot(p.velocity, v_dist) >= c.epsilon:
            return

        # We are definitely not off the ends of the segment, and close enough
        # that we are colliding.
        p.rebound(self.normal, vec.sub(p.pos, v_dist), restitution)
示例#12
0
    def collide_wall(self, p):
        restitution = self.restitution * p.restitution

        # First, check that we haven't crossed through the wall due to
        # extreme speed and low framerate.
        intersection = intersect_segments(self.p1, self.p2, p.last_pos, p.pos)
        if intersection:
            p.pos = p.last_pos
            p.rebound(self.normal, intersection, restitution)
            return

        # Find vectors to each endpoint of the segment.
        v1 = vec.vfrom(self.p1, p.pos)
        v2 = vec.vfrom(self.p2, p.pos)

        # Find a perpendicular vector from the wall to p.
        v_dist = vec.proj(v1, self.normal)

        # Test distance from the wall.
        radius2 = p.radius**2
        if vec.mag2(v_dist) > radius2:
            return

        # Test for collision with the endpoints of the segment.
        # Check whether p is too far off the end of the segment, by checking
        # the sign of the vector projection, then a radius check for the
        # distance from the endpoint.
        if vec.dot(v1, self.tangent) < 0:
            if vec.mag2(v1) <= radius2:
                p.rebound(v1, self.p1, restitution)
            return
        if vec.dot(v2, self.tangent) > 0:
            if vec.mag2(v2) <= radius2:
                p.rebound(v2, self.p2, restitution)
            return

        # Test that p is headed toward the wall.
        if vec.dot(p.velocity, v_dist) >= c.epsilon:
            return

        # We are definitely not off the ends of the segment, and close enough
        # that we are colliding.
        p.rebound(self.normal, vec.sub(p.pos, v_dist), restitution)
示例#13
0
    def genCaptureImage(s):
        """Builds a line sprite of the right length to go to the capturing planet."""
        # Some paranoid error checking
        if not s.parent:
            raise Exception(
                "Tried to generate capture image with nonexistant parent!")
        vecToParent = vec.sub(s.parent.loc, s.loc)
        distanceToParent = vec.mag(vecToParent)
        # It appears that we can blit image_data (software image data
        # in main memory) to a texture (hardware image data on the GPU)
        # but not any other way.
        ropeImage = resource.getImage('line2').get_image_data()
        img = pyglet.image.create(ropeImage.width,
                                  int(distanceToParent)).get_texture()
        img.anchor_x = int(img.width // 2)
        img.anchor_y = int(img.height // 2)

        # Now we have the image, we fill it up with the
        # capture-rope images.
        for i in range(0, int(distanceToParent), ropeImage.height):
            #print 'foo', i, img.height, ropeImage.height
            img.blit_into(ropeImage, 0, i, 0)

        s.captureSprite = pyglet.sprite.Sprite(img)
示例#14
0
    def join_with_line(self, other):
        v_self = self._vector()
        v_other = other._vector()

        # Check turn angle.
        self_heading = Heading.from_rad(vec.heading(v_self))
        other_heading = Heading.from_rad(vec.heading(v_other))
        turn_angle = self_heading.angle_to(other_heading)

        # Special case equal widths.
        if(
            abs(turn_angle) <= MAX_TURN_ANGLE and
            float_equal(self.width, other.width)
        ):
            # When joints between segments of equal width are straight or
            # almost straight, the line-intersection method becomes very
            # numerically unstable, so use another method instead.

            # For each segment, get a vector perpendicular to the
            # segment, then add them. This is an angle bisector for
            # the angle of the joint.
            w_self = self._width_vector()
            w_other = other._width_vector()
            v_bisect = vec.add(w_self, w_other)

            # Make the bisector have the correct length.
            half_angle = vec.angle(v_other, v_bisect)
            v_bisect = vec.norm(
                v_bisect,
                (self.width / 2) / math.sin(half_angle)
            )

            # Determine the left and right joint spots.
            p_left = vec.add(self.b, v_bisect)
            p_right = vec.sub(self.b, v_bisect)
        else:
            a, b = self.offset_line_left()
            c, d = other.offset_line_left()
            p_left = intersect_lines(a, b, c, d)

            a, b = self.offset_line_right()
            c, d = other.offset_line_right()
            p_right = intersect_lines(a, b, c, d)

        # Make sure the joint points are "forward" from the perspective
        # of each segment.
        if p_left is not None:
            if vec.dot(vec.vfrom(self.a_left, p_left), v_self) < 0:
                p_left = None
        if p_right is not None:
            if vec.dot(vec.vfrom(self.a_right, p_right), v_self) < 0:
                p_right = None

        # Don't join the outer sides if the turn angle is too steep.
        if abs(turn_angle) > MAX_TURN_ANGLE:
            if turn_angle > 0:
                p_right = None
            else:
                p_left = None

        if p_left is not None:
            self.b_left = other.a_left = Point(*p_left)
        if p_right is not None:
            self.b_right = other.a_right = Point(*p_right)

        if p_left is None or p_right is None:
            self.end_joint_illegal = True
            other.start_joint_illegal = True
示例#15
0
    def on_key_press(s, gs, key):
        if key == keys.SPACE:
            if not s.controlling:
                s.startControl()
            else:
                s.endControl()
        elif s.controlling:
            s.parent.on_key_press(gs, key)
        else:
            if key == keys.LEFT:
                s.facing = -1
                s.moving = -1
            elif key == keys.RIGHT:
                s.facing = 1
                s.moving = 1
            elif key == keys.X:
                # Try capture some nearby planet...
                #print("Trying capture...")
                for p in gs.planets:
                    facingpoint = (s.parent.facing + s.loc) % 360
                    #print("Trying to capture {0} at facing {1}".format(p, facingpoint))
                    # XXX: Make it only capture the closest planet, dammit!
                    # XXX: Ideally it will also go off the distance between the planet
                    # surfaces, not the centers  This needs to happen!
                    if s.parent.canCapture(facingpoint, s.captureRange, p):
                        print("Captured, facing {0}!".format(facingpoint))
                        s.parent.capture(p)
                        sound = resource.getSound("capture")
                        sound.play()
                        break
            elif key == keys.Z:
                # Try uncapture
                # XXX: At the moment we can't uncapture from the child side... hmm.
                # XXX: At the moment also, if there are multiple planets
                # captured close to each other, it essentially releases
                # one at random rather than doing the one closest to
                # where you're standing.
                for p in s.parent.children:
                    # This is a little f****d up but should work...
                    facingpoint = (s.parent.facing + s.loc) % 360
                    facingvec = vec.fromAngle(facingpoint)
                    offset = vec.sub(p.loc, s.parent.loc)
                    diff = vec.angleBetween(facingvec, offset)

                    if abs(diff) < 0.2:
                        #print("Uncapturing")
                        s.parent.uncapture(p)
                        sound = resource.getSound("uncapture")
                        sound.play()
                        break

            elif key == keys.C:
                if s.attackCooldown < 0.0:
                    s.attack(gs)
                    s.attackCooldown = s.attackCooldownTotal
                    s.attackSound.play()

            elif key == keys.UP:
                # Transport to captured planet.
                teleportAngle = 10.0
                for p in s.parent.children:
                    facingpoint = (s.parent.facing + s.loc) % 360
                    facingvec = vec.fromAngle(facingpoint)
                    offset = vec.sub(p.loc, s.parent.loc)
                    diff = vec.angleBetween(facingvec, offset)

                    if abs(diff
                           ) < teleportAngle and s.transportCooldown <= 0.0:
                        s.sprayParticles(gs, particles.WarpSpark, 50, 30)
                        facingdiff = s.parent.facing - p.facing
                        s.loc += facingdiff + 180
                        s.setParent(p)
                        s.transportCooldown = s.transportCooldownTotal
                        s.sprayParticles(gs, particles.WarpSpark, 50, 30)
                        s.teleportSound.play()
                        return

                # Oooor, if this planet is captured, you can go back to the parent
                if s.parent.parent != None:
                    p = s.parent.parent
                    facingpoint = (s.parent.facing + s.loc) % 360
                    facingvec = vec.fromAngle(facingpoint)
                    offset = vec.sub(p.loc, s.parent.loc)
                    diff = vec.angleBetween(facingvec, offset)
                    if abs(diff
                           ) < teleportAngle and s.transportCooldown <= 0.0:
                        s.sprayParticles(gs, particles.WarpSpark, 50, 30)
                        facingdiff = s.parent.facing - p.facing
                        s.loc += facingdiff + 180
                        s.setParent(p)
                        s.transportCooldown = s.transportCooldownTotal
                        s.sprayParticles(gs, particles.WarpSpark, 50, 30)
                        s.teleportSound.play()
                        return

                # If we've gotten this far, then you're not sitting on a connection,
                # So jump!
                if s.jumpCooldown < 0:
                    s.jump()
                    s.jumpSound.play()
示例#16
0
    def join_with_line(self, other):
        v_self = self._vector()
        v_other = other._vector()

        # Check turn angle.
        self_heading = Heading.from_rad(vec.heading(v_self))
        other_heading = Heading.from_rad(vec.heading(v_other))
        turn_angle = self_heading.angle_to(other_heading)

        # Special case equal widths.
        if(
            abs(turn_angle) <= MAX_TURN_ANGLE
            and float_equal(self.width, other.width)
        ):
            # When joints between segments of equal width are straight or
            # almost straight, the line-intersection method becomes very
            # numerically unstable, so use another method instead.

            # For each segment, get a vector perpendicular to the
            # segment, then add them. This is an angle bisector for
            # the angle of the joint.
            w_self = self._width_vector()
            w_other = other._width_vector()
            v_bisect = vec.add(w_self, w_other)

            # Make the bisector have the correct length.
            half_angle = vec.angle(v_other, v_bisect)
            v_bisect = vec.norm(
                v_bisect,
                (self.width / 2) / math.sin(half_angle)
            )

            # Determine the left and right joint spots.
            p_left = vec.add(self.b, v_bisect)
            p_right = vec.sub(self.b, v_bisect)
        else:
            a, b = self.offset_line_left()
            c, d = other.offset_line_left()
            p_left = intersect_lines(a, b, c, d)

            a, b = self.offset_line_right()
            c, d = other.offset_line_right()
            p_right = intersect_lines(a, b, c, d)

        # Make sure the joint points are "forward" from the perspective
        # of each segment.
        if p_left is not None:
            if vec.dot(vec.vfrom(self.a_left, p_left), v_self) < 0:
                p_left = None
        if p_right is not None:
            if vec.dot(vec.vfrom(self.a_right, p_right), v_self) < 0:
                p_right = None

        # Don't join the outer sides if the turn angle is too steep.
        if abs(turn_angle) > MAX_TURN_ANGLE:
            if turn_angle > 0:
                p_right = None
            else:
                p_left = None

        if p_left is not None:
            self.b_left = other.a_left = Point(*p_left)
        if p_right is not None:
            self.b_right = other.a_right = Point(*p_right)

        if p_left is None or p_right is None:
            self.end_joint_illegal = True
            other.start_joint_illegal = True