Ball elastic collision

Ball elastic collision

WebGL-based small ball elastic collision demo

Code address: https://github.com/wisdomofgod/ball_elastic_collision/

Demo address: http://htmlpreview.github.io/?https://github.com/wisdomofgod/ball_elastic_collision/blob/master/index.html

Ball elastic collision :

  • Ball setting  : The position, speed and angle of the ball are generated by the random function, where the angle is controlled by the speed of the x and y axes;
  • Ball color  : The color of the ball is calculated from the position of the ball, the color value = the position of the ball * 0.5, and the gradient effect from the center of the circle to the outside is added;
  • Ball Collision  : There are two situations in which the ball hits the wall and hits other small balls. There are two elastic parameters of the impact that determine the rebound force. 
  • Alt textAlt text

fragment shader

In the vertex shader, set v_color = gl_Position * 0.5; In the fragment shader, first of all, because we want to draw a sphere, so judge the distance between the current interpolation point and the center of the sphere. When interpolating, the interpolation is performed according to the square. , we only color the points whose distance is less than or equal to the radius. If the distance is less than the radius, set the color value to v_color + d - 0.2; (in order to achieve a color gradient from the center of the circle to the edge)

code block

<script id="2d-fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        varying vec4 v_color;

        void main() {
            gl_FragColor = v_color;

            float d = distance(gl_PointCoord, vec2(0.5,0.5));
            if (d < 0.5) {
                vec4 color = v_color + d - 0.2;
                gl_FragColor = color;
            } else {
                discard;
            }
        }
    </script>

ball hits wall

When the ball hits the wall, it is judged in the move function. If it hits the wall, the speed in the direction of impact will be v * bounce (the elasticity of hitting the wall)

code block

this.balls.forEach(a => {
        a.x += a.vx;
        ay + = a.vy;
        if (a.x > this.R) {
            a.x = this.R;
            a.vx *= this.bounce;
        }
        if (a.x < this.L) {
            a.x = this.L;
            a.vx *= this.bounce;
        }
        if (a.y > this.T) {
            a.y = this.T;
            a.vy *= this.bounce;
        }
        if (a.y < this.B) {
            a.y = this.B;
            a.vy *= this.bounce;
        }
    });

collision between balls

First, through the distance between the two small balls, if the distance is less than or equal to the diameter of the small balls, when the two small balls are superimposed and the small balls are superimposed, the angle between the two small balls is calculated from the coordinates of the two small balls. Calculated through the angle, the shortest distance to separate the two balls, this distance is multiplied by the elasticity between the balls, and the reverse acceleration of the separation of the balls is obtained. Add the inverse acceleration to the original x,y velocity of the ball. Since the velocity value is greater than the reverse acceleration value, the ball will continue to squeeze in until the velocity direction is consistent with the acceleration direction, and then accelerate to separate. Therefore, a squeezing and popping effect can be produced.

code block

if (dist <= this.misDist) {
        //collision
        var angle, tx, ty, ax, ay;
        angle = Math.atan2(dy, dx);
        tx = ballA.x + Math.cos(angle) * this.misDist;
        ty = ballA.y + Math.sin(angle) * this.misDist;
        ax = (tx - ballB.x) * this.spring;
        ay = (ty - ballB.y) * this.spring;
        ballA.vx - = ax;
        ballA.vy -= ay;
        ballB.vx += ax;
        ballB.vy += ay;
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324977454&siteId=291194637