DamnEazy
DamnEazy

Reputation: 31

How should I begin with colliding particles inside a square? (manim)

I've been trying to work this out for quite a while but haven't really come anywhere. The task is to represent a box with moving dots inside while it collides with all edges. It would also be beneficial if I could decide the amount of dots inside the square with a function.

import numpy as np
import random as rand

class bacteria(Scene):
    def construct(self):
        square = Square().scale(3)
        square.shift(3*LEFT)


        self.play(Write(square), run_time=3)
        self.wait()

This is basically how far I've come into the problem. I'm also fairly new to programming but I know the physics behind it all.

Upvotes: 3

Views: 929

Answers (1)

Péter Szilvási
Péter Szilvási

Reputation: 2049

I have created an example, where multiple bacteria (green dots) floating inside a box. Every time a bacteria hits the wall it changes its direction. First we need the class named Bacteria inherits from Dot class.

from manim import *

class Bacteria(Dot):
    def __init__(self, point=ORIGIN, ** kwargs):
        Dot.__init__(self, point=point, color=GREEN, ** kwargs)
        self.velocity = 6 * np.random.random_sample(3) - 3 # [-3, 3] interval

Bacteria's constructor accepts the dot location (3 x 1 dimension numpy array). Default location is the origin and dot's color is green. Velocity is random float number in [-3, 3] interval. Now let's see the BouncingBacteria class inherits from Scene class.

Following steps involved in the scene:

  1. Create a Rectangle object named box and some Bacteria objects (bacteria_array).
  2. Set up bacteria objects update function, where the collision detection is implemented.
  3. Attach collision detection to all bacteria updater. Achieved by the add_updater method.

Here is the code:

class BouncingBacteria(Scene):
    def construct(self):
        # Create objects
        box = Rectangle(width=5, height=5)
        self.play(FadeIn(box))

        bacteria_array = []
        for i in range(0, 3):
            bacteria_position = 4 * np.random.random_sample((3,)) - 2 # [-2, 2] interval
            bacteria_array.append(Bacteria(bacteria_position))
            self.play(FadeIn(bacteria_array[i]))

        # Collision detection
        def update_bacteria(bacteria, dt):
            bacteria.acceleration = 2 * np.random.random_sample(3) - 1 # [-1, 1] interval
            bacteria.velocity = bacteria.velocity + bacteria.acceleration * dt
            bacteria.shift(bacteria.velocity * dt)

            # Bounce off walls
            if bacteria.get_left()[0] <= box.get_left()[0] or bacteria.get_right()[0] >= box.get_right()[0]:
                bacteria.velocity[0] = -bacteria.velocity[0]

            # Bounce off ground and roof
            if bacteria.get_bottom()[1] <= box.get_bottom()[1] or bacteria.get_top()[1] >= box.get_top()[1]:
                bacteria.velocity[1] = -bacteria.velocity[1]

        # Attach collision detection to updater
        for bacteria in bacteria_array:
            bacteria.add_updater(update_bacteria)
        self.wait(20)

In my cases three bacteria were created at random position in [-2, 2] interval. Each bacteria has different random acceleration between [-1, 1] interval. If left 'x' coordinates of bacteria bounding box is less than or equal to left 'x' coordinates of rectangle bounding box, then the 'x' velocity is reversed. Same goes for the right side, the only difference is the greater than or equal sign: bacteria.get_right()[0] >= box.get_right()[0]. Top and bottom collision is very same, just 'x' coordinates are replaced with 'y' coordinates.

Bouncing Bacteria in action 😀 enter image description here

For better quality use the following command:

manim -pqh .\scene.py BouncingBacteria

Also check out the manim-physics plugin for physics simulation.

Upvotes: 2

Related Questions