示例#1
0
def circle_aabb(A, B, collision_class=Collision):
    cx, cx_, cy, cy_ = A.rect_coords
    ax, ax_, ay, ay_ = B.rect_coords
    dx = min(cx_, ax_) - max(cx, ax)
    dy = min(cy_, ay_) - max(cy, ay)
    if dy < 0 or dx < 0:
        return None

    x, y = pos = A.pos
    if dx < dy:
        # Circle is right at the bottom/top of AABB
        if ay <= y <= ay_:
            left = x < ax
            pos = Vec2(ax if left else ax_, y)
            normal = Vec2(1 if left else -1, 0)
            delta = dx / 2
            return collision_class(A, B, pos=pos, normal=normal, delta=delta)
    else:
        # Circle is right at the bottom/top of AABB
        if ax <= x <= ax_:
            bottom = y < ay
            pos = Vec2(x, ay if bottom else ay_)
            normal = Vec2(0, 1 if bottom else -1)
            delta = dy / 2
            return collision_class(A, B, pos=pos, normal=normal, delta=delta)

    # If we reached this point, the circle encountered the AABB at a vertex.
    # We must find the vertex that is closest to the center and define the
    # normal vector using it.
    vertex = min(B.vertices, key=lambda v: abs(v - pos))
    normal = (vertex - pos).normalize()
    delta = A.radius - (pos - vertex).norm()
    return collision_class(A, B, pos=vertex, normal=normal, delta=delta)
示例#2
0
 def _vertices(self, N, pos):
     length = self.length
     alpha = pi / N
     theta = 2 * alpha
     b = length / (2 * sin(alpha))
     P0 = Vec2(b, 0)
     pos = Vec2(*pos)
     return [(P0.rotate(n * theta)) + pos for n in range(N)]
示例#3
0
    def gravity(self, value):
        owns_prop = flags.owns_gravity
        old = self._gravity
        try:
            gravity = self._gravity = Vec2(*value)
        except TypeError:
            gravity = self._gravity = Vec2(0, -value)

        for obj in self._objects:
            if not obj.flags & owns_prop:
                obj._gravity = gravity
                gravity_changed_signal.trigger(self, old, self._gravity)
示例#4
0
文件: screen.py 项目: jonnatas/FGAme
 def __init__(self, shape=(800, 600), pos=(0, 0), zoom=1, background=None):
     self.width, self.height = shape
     self.pos = Vec2(*pos)
     self.zoom = zoom
     self.background = background
     self.camera = Camera(self)
     self.visible = False
示例#5
0
    def __init__(self, obj, k, pos=(0, 0), register=False):
        self._k = k
        kxy = 0
        x0, y0 = self._pos = Vec2(*pos)

        try:  # Caso isotrópico
            kx = ky = k = self._k = float(k)
        except TypeError:  # Caso anisotrópico
            k = self._k = tuple(map(float, k))
            if len(k) == 2:
                kx, ky = k
            else:
                kx, ky, kxy = k

        # Define forças e potenciais
        def F(R):
            Dx = x0 - R.x
            Dy = y0 - R.y
            return Vec2(kx * Dx + kxy * Dy, ky * Dy + kxy * Dx)

        def U(R):
            Dx = x0 - R.x
            Dy = y0 - R.y
            return (kx * Dx**2 + ky * Dy**2 + 2 * kxy * Dx * Dy) / 2.0

        super(SpringTensor, self).__init__(obj, F, U, register=register)
示例#6
0
    def __init__(self,
                 vertices,
                 pos=None,
                 vel=(0, 0),
                 theta=0.0,
                 omega=0.0,
                 mass=None,
                 density=None,
                 inertia=None,
                 **kwargs):

        if isinstance(vertices, int):
            raise ValueError('must pass a list of vertices. '
                             'Use RegularPoly to define a polygon by the '
                             'number of vertices')
        vertices = [Vec2(*pt) for pt in vertices]
        pos_cm = center_of_mass(vertices)
        vertices = [v - pos_cm for v in vertices]
        self._vertices = vertices

        # Cache vertices
        self._cache_theta = None
        self._cache_rvertices_last = None
        self._cache_rbbox_last = None
        super(Poly, self).__init__(pos_cm,
                                   vel,
                                   theta,
                                   omega,
                                   mass=mass,
                                   density=density,
                                   inertia=inertia,
                                   cbb_radius=max(v.norm() for v in vertices),
                                   **kwargs)

        self.num_sides = len(vertices)
        self._normals_idxs = self.get_li_indexes()
        self.num_normals = len(self._normals_idxs or self.vertices)

        # Slightly faster when all normals are linear dependent: if
        # self._normals_idx = None, all normals are recomputed at each frame.
        if self.num_normals == self.num_sides:
            self._normals_idxs = None

        # Move to specified position, if pos is given.
        if pos is not None:
            self._pos = Vec2(*pos)
示例#7
0
    def runner(self, dt, target, **kwds):
        time = 0
        interval = self.interval
        position = self.trajectory
        pos_shift = Vec2(0, 0) if not self.relative else target.pos

        while time < interval:
            time += dt
            target.pos = pos_shift + position(time)
示例#8
0
    def momentumP(self):
        """
        Linear momentum.
        """

        try:
            return self._vel / self._invmass
        except ZeroDivisionError:
            return Vec2(float('inf'), float('inf'))
示例#9
0
 def fast_func(t):
     F = null2D
     for k, func in nmuls:
         Fi = asvector(func(t))
         try:
             F += Fi * k
         except TypeError:
             x, y = Fi
             F += Vec2(k * x, k * y)
     return F
示例#10
0
    def get_normal(self, i):
        """
        Normal unity vector to the ith side.

        Each segment goes from point i to i + 1.
        """

        points = self.vertices
        x, y = points[(i + 1) % self.num_sides] - points[i]
        return Vec2(y, -x).normalize()
示例#11
0
    def orientation(self, theta=0.0):
        """
        Return an unitary vector in the direction the object is oriented.

        If the rotation is zero, the orientation vector is Vec2(1, 0). Rotation
        is applied accordingly.
        """

        theta += self._theta
        return Vec2(self._cos(theta), self._sin(theta))
示例#12
0
 def fast_func(t):
     F = null2D
     for scalar_func, func in fmuls:
         Fi = func(t)
         k = scalar_func(t)
         try:
             F += Fi * k
         except TypeError:
             x, y = Fi
             F += Vec2(k * x, k * y)
     return F
示例#13
0
def collision_aabb(A, B):
    # Detects collision using bounding box shadows.
    x0, x1 = max(A.xmin, B.xmin), min(A.xmax, B.xmax)
    y0, y1 = max(A.ymin, B.ymin), min(A.ymax, B.ymax)
    dx = x1 - x0
    dy = y1 - y0
    if x1 < x0 or y1 < y0:
        return None

    # Chose collision center as the center point in the intersection
    pos = Vec2((x1 + x0) / 2, (y1 + y0) / 2)

    # Normal is the direction with smallest penetration
    if dy < dx:
        delta = dy
        normal = Vec2(0, (1 if A.pos.y < B.pos.y else -1))
    else:
        delta = dx
        normal = Vec2((1 if A.pos.x < B.pos.x else -1), 0)

    return Collision(A, B, pos=pos, normal=normal, delta=delta)
示例#14
0
    def get_normals(self):
        """
        List of linearly independent normals.
        """

        if self._normals_idxs is None:
            N = self.num_sides
            points = self.vertices
            segmentos = (points[(i + 1) % N] - points[i] for i in range(N))
            return [Vec2(y, -x).normalize() for (x, y) in segmentos]
        else:
            return [self.get_normal(i) for i in self._normals_idxs]
示例#15
0
    def momentumL(self, *args):
        """
        Angular momentum.

        Angular momentum depends on a reference point. By default, we use the
        object's center of mass. One can pass any coordinate to specify the
        reference.

        Example:

            Consider the object

            >>> b1 = Body(pos=(0, 1), vel=(1, 0), mass=2)

            Its center of mass angualar momentum is zero since it has no angular
            velocity

            >>> b1.momentumL()
            0.0

            However, linear movement creates an angular moment around origin or
            other reference points

            >>> b1.momentumL(0, 0)
            -2.0
            >>> b1.momentumL(0, 2)
            2.0
        """

        if not args:
            momentumL = None
        else:
            if len(args) == 1:
                vec = args[0]
            else:
                vec = Vec2(*args)
            delta_pos = self.pos - vec
            momentumL = delta_pos.cross(self.momentumP())

        if self._invinertia:
            return momentumL + self.omega * self.inertia
        else:
            return momentumL
示例#16
0
    def __init__(self, obj, G, M=None, epsilon=0, pos=(0, 0), register=False):
        if M is None:
            M = obj.mass
        self._M = M = float(M)
        self._epsilon = epsilon = float(epsilon)
        self._G = G = float(G)
        self._pos = pos = Vec2(*pos)

        def F(R):
            R = pos - R
            r = R.norm()
            r3 = (r + epsilon)**2 * r
            R *= G * obj.mass * M / r3
            return R

        def U(R):
            R = (R - pos).norm()
            return -self._G * obj.mass * M / (R + epsilon)

        super(Gravity, self).__init__(obj, F, U, register=register)
    def random(self, *args):
        """
        Return random position in the visible screen.

        Signature:
            ``pos.random(size)``: create objects within screen and inside a
                margin with the given number of pixels.
            ``pos.random(margin_x, margin_y)``: specify margin in x and y
                directions.
            ``pos.random(margin_left, margin_bottom, margin_right, margin_top)``:
                specify each margin separately
        """

        x0 = y0 = 0
        x1, y1 = self._shape
        if len(args) == 1:
            margin = args[0]
            x0 += margin
            x1 -= margin
            y0 += margin
            y1 -= margin
        elif len(args) == 2:
            dx, dy = args
            x0 += dx
            x1 -= dx
            y0 += dy
            y1 -= dy
        elif len(args) == 4:
            x0 += args[0]
            y0 += args[1]
            x1 -= args[2]
            y1 -= args[3]
        elif len(args) != 0:
            raise TypeError('must be called with 0, 1, 2, or 4 arguments')

        return Vec2(random.uniform(x0, x1), random.uniform(y0,
                                                           y1)) + self._origin
示例#18
0
 def vy(self, value):
     self._vel = Vec2(self._vel.x, value)
示例#19
0
    def runner(self, dt, target, **kwds):
        n_steps = dt / self.duration
        delta = self.step / n_steps

        for _ in range(n_steps):
            target.pos += Vec2.frompolar(delta, target.theta)
示例#20
0
 def __init__(self, pos, interval):
     super(move_to, self).__init__(interval)
     self.pos = Vec2(*pos)
 def test_move_functions_signature(self, obj):
     for args in [[Vec2(1, 2)], [(1, 2)], (1, 2)]:
         obj.move(*args)
         obj.imove(*args)
         obj.boost(*args)
         obj.move_to(*args)
示例#22
0
    def move_tip(self, pos):
        '''Move a ponta para a nova posição pos'''

        self._pos = self._current[-1] = Vec2(*pos)
示例#23
0
 def vx(self, value):
     self._vel = Vec2(value, self._vel.y)
 def _origin(self):
     return Vec2(0, 0)
示例#25
0
 def F(R):
     Dx = x0 - R.x
     Dy = y0 - R.y
     return Vec2(kx * Dx + kxy * Dy, ky * Dy + kxy * Dx)
 def vel(self):
     return Vec2(1, 0)
示例#27
0
 def gravity(self, value):
     try:
         self._gravity = Vec2(*value)
     except TypeError:
         self._gravity = Vec2(0, -value)
     self.owns_gravity = True
示例#28
0
 def __init__(self, x, y=None):
     if y is None:
         self.pos = Vec2(*x)
     else:
         self.pos = Vec2(x, y)
示例#29
0
 def F(rA, rB):
     dx, dy = rB - rA
     return Vec2(kx * dx + kxy * dy, +ky * dy + kxy * dx)
 def from_pos(self, x, y):
     w, h = self._shape
     x0, y0 = self._origin
     return Vec2(x0 + a * w + x, y0 + b * h + y)