Пример #1
0
 def __init__(self, x_init, y_init, mass, radius, borders):
     Logger.debug("KINEMATICS: PhysicsObject init(x_init=%s, y_init=%s, mass=%s, radius=%s, borders=%s)", str(x_init), str(y_init), str(mass), str(radius), str(borders))
     self._pos = Vector(x_init, y_init)
     self._mass = mass
     self._radius = radius
     self._vel = Vector(0, 0)
     self._borders = borders
Пример #2
0
 def test_perpendicular(self):
     for tup in self.init_value:
         checked_vector = Vector(tup)
         vector = checked_vector.perpendicular()
         self.assertAlmostEqual(-tup[1], vector.x)
         self.assertAlmostEqual(tup[0], vector.y)
Пример #3
0
 def test_normalized(self):
     for tup in self.expected_value:
         checked_vector = Vector(tup[0])
         vector = checked_vector.normalized()
         self.assertAlmostEqual(1, vector.length)
Пример #4
0
 def test_rotate(self):
     for tup in self.rotate_value:
         checked_vector = Vector(tup[0])
         checked_vector.rotate(tup[1])
         self.assertAlmostEqual(tup[2].x, checked_vector.x)
         self.assertAlmostEqual(tup[2].y, checked_vector.y)
Пример #5
0
 def test_rotated(self):
     for tup in self.rotate_value:
         checked_vector = Vector(tup[0])
         result = checked_vector.rotated(tup[1])
         self.assertAlmostEqual(tup[2].x, result.x)
         self.assertAlmostEqual(tup[2].y, result.y)
Пример #6
0
 def test_set_length(self):
     for tup in self.set_value:
         checked_vector = Vector(5, 5)
         checked_vector.length = tup
         self.assertAlmostEqual(tup, sqrt(checked_vector.x ** 2 + checked_vector.y ** 2))
Пример #7
0
 def test_state(self):
     for tup in self.init_value:
         checked_vector = Vector(tup)
         checked_vector.state = tup
         self.assertAlmostEqual(tup[0], checked_vector.x)
         self.assertAlmostEqual(tup[1], checked_vector.y)
Пример #8
0
 def test_change_state(self):
     for tup in self.init_value:
         checked_vector = Vector(tup)
         checked_vector.change_state(tup)
         self.assertAlmostEqual(tup[1] * 2, checked_vector.y)
         self.assertAlmostEqual(tup[0] * 2, checked_vector.x)
Пример #9
0
 def test_get_distance(self):
     for tup in self.dot_value:
         checked_vector = Vector(tup[0])
         helping_vector = Vector(tup[1])
         result = checked_vector.get_distance(helping_vector)
         self.assertAlmostEqual(sqrt((tup[0][0] - tup[1][0]) ** 2 + (tup[0][1] - tup[1][1]) ** 2), result)
Пример #10
0
 def test_dot(self):
     for tup in self.dot_value:
         checked_vector = Vector(tup[0])
         helping_vector = Vector(tup[1])
         result = checked_vector.dot(helping_vector)
         self.assertAlmostEqual(tup[2], result)
Пример #11
0
class PhysicsObject(object):
    COEFFICIENT_OF_FRICTION = 0.99
    COEFFICIENT_OF_BORDER_COLLISION = 0.8
    MAX_MALLET_VELOCITY = 25
    MAX_DISC_VELOCITY = 50
    STOPPING_VELOCITY = 0.1

    def __init__(self, x_init, y_init, mass, radius, borders):
        Logger.debug("KINEMATICS: PhysicsObject init(x_init=%s, y_init=%s, mass=%s, radius=%s, borders=%s)", str(x_init), str(y_init), str(mass), str(radius), str(borders))
        self._pos = Vector(x_init, y_init)
        self._mass = mass
        self._radius = radius
        self._vel = Vector(0, 0)
        self._borders = borders

    # TODO: Add unittests
    def friction(self):
        Logger.debug("KINEMATICS: friction vel before = %s", str(self._vel))
        self._vel.length *= self.COEFFICIENT_OF_FRICTION
        self._vel.length = 0 if self._vel.length < self.STOPPING_VELOCITY else self._vel.length
        Logger.debug("KINEMATICS: friction vel after = %s", str(self._vel))

    def collision_effect(self):
        # TODO: a proper calculation of momentum and change in speed after collisions
        Logger.debug("KINEMATICS: collision_effect vel before = %s", str(self._vel))
        self._vel.length *= self.COEFFICIENT_OF_BORDER_COLLISION
        Logger.debug("KINEMATICS: collision_effect vel after = %s", str(self._vel))

    def correct_position_in_borders(self):
        """ Dislodges objects stuck in the pitch borders """
        x_min, x_max = self._borders[0]
        y_min, y_max = self._borders[1]
        log = False
        if self.pos.x - self.radius < x_min:
            self.pos.x = x_min+self.radius
            log = True
        if self.pos.x + self.radius > x_max:
            self.pos.x = x_max-self.radius
            log = True
        if self.pos.y - self.radius < y_min:
            self.pos.y = y_min+self.radius
            log = True
        if self.pos.y + self.radius > y_max:
            self.pos.y = y_max-self.radius
            log = True
        if log:
            Logger.debug("KINEMATICS: correct_position_in_borders pos.x=%s pos.y=%s", str(self.pos.x), str(self.pos.y))

    def correct_position_post_collision(self, obj):
        """ Dislodges objects stuck in each other. """
        distance_vector = self.pos - obj.pos
        if distance_vector.length < self.radius + obj.radius:
            distance_vector.length = self.radius + obj.radius
            self._pos = obj.pos + distance_vector
            self.correct_position_in_borders()
            Logger.debug("KINEMATICS: correct_position_post_collision distance_vector=%s self.radius=%s obj.radius=%s", str(distance_vector), str(self.radius), str(obj.radius))
        distance_vector = obj.pos - self.pos

        if distance_vector.length < obj.pos - self.pos:
            distance_vector.length = self.radius + obj.radius
            obj._pos = self._pos + distance_vector
            obj.correct_position_in_borders()
        Logger.debug("KINEMATICS: correct_position_post_collision distance_vector=%s self.radius=%s obj.radius=%s", str(distance_vector), str(self.radius), str(obj.radius))

    # TODO: Add common move_to and move methods for mallet and disc

    def apply_speed_limit(self):
        from data.Disc import Disc
        from data.Mallet import Mallet
        Logger.debug("KINEMATICS: apply_speed_limit MAX_DISC_VELOCITY=%s MAX_MALLET_VELOCITY=%s vel=%s", str(self.MAX_DISC_VELOCITY), str(self.MAX_MALLET_VELOCITY), str(self._vel.length))
        if isinstance(self, Disc) and self._vel.length > self.MAX_DISC_VELOCITY:
            Logger.debug("KINEMATICS: apply_speed_limit is a Disc")
            self._vel.length = self.MAX_DISC_VELOCITY
        if isinstance(self, Mallet) and self._vel.length > self.MAX_MALLET_VELOCITY:
            Logger.debug("KINEMATICS: apply_speed_limit is a Mallet")
            self._vel.length = self.MAX_MALLET_VELOCITY

    # TODO: Add unittests
    def border_collision(self, axis):
        from data.Disc import Disc
        Logger.debug("KINEMATICS: border_collision axis=%s _vel=%s", str(axis), str(self._vel))
        if isinstance(self, Disc):
            if axis == 'x':
                self._vel.x = -self._vel.x
                self.collision_effect()
                self.correct_position_in_borders()
            if axis == 'y':
                self._vel.y = -self._vel.y
                self.collision_effect()
                self.correct_position_in_borders()
        Logger.debug("KINEMATICS: _vel=%s", str(self._vel))

    # TODO: Add unittests
    def circle_collision(self, object):
        from data.Disc import Disc
        if self._pos.get_distance(object.pos) <= self._radius+object.radius:
            Logger.debug("KINEMATICS: border_collision distance=%s self.radius=%s object.radius=%s", str(self._pos.get_distance(object.pos)), str(self._radius), str(object.radius))
            vec_pos_diff = object.pos - self._pos
            vec_to = self._vel.projection(vec_pos_diff)
            obj_vec_to = object._vel.projection(vec_pos_diff)

            vec_side = self._vel - vec_to
            obj_vec_side = object._vel - obj_vec_to

            after_vec_to = (vec_to*(self._mass-object._mass) + (2 * object._mass * obj_vec_to))/(self._mass + object._mass)
            after_obj_vec_to = (obj_vec_to*(object._mass - self._mass) + (2 * self._mass * vec_to))/(self._mass + object._mass)

            # Change velocity only if it is Disc
            if isinstance(self, Disc):
                self._vel = after_vec_to + vec_side
            if isinstance(object, Disc):
                object._vel = after_obj_vec_to + obj_vec_side

            self.apply_speed_limit()
            self.correct_position_post_collision(object)