Samples Gallery & Reference > General, Math & Geometry

Dropping Balls by bplus

(1/1)

Qwerkey:
Dropping Balls

Author: @bplus
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=194.0
Version: 2020
Tags: [gravity], [spherical collisions]

Description:
Dropping Balls an attempt to build a pile by adjusting drop rate, elasticity, and gravity.
Bplus used tools from SMcNeill for fill circle and STxAxTIC for non-overlapping balls.

This thread is a fun continuation of ball collision experiments from a number of members including: @_vince who offered an hourglass challenge, @[banned user], @SMcNeill, @STxAxTIC, creating a collection of interesting variations. The code given here is just one program from a variety produced.  Look through the whole of the designated thread, it continues into Hourglass thread linked near end of URL above.

Source Code:

--- Code: QB64: ---    _TITLE "Dropping Balls: Pile Attempt #3" ' bplus started 2018-04-03"    ' Attempt to build a pile by adjusting drop rate, elasticity, and gravity.    ' Built from Dropping balls 4 w snd and STATIC created 2018-04-3    ' Add STATIC's ball moving before figuring any bounce from collision    ' which was a mod in Dropping Balls 2 w sound posted 2018-03-31.    ' 2020-03-04 Pile Attempt #3 revive and tidy up         RANDOMIZE TIMER    CONST xmax = 750, ymax = 720, elastic = .8, gravity = .75, balls = 400, br = 15    SCREEN _NEWIMAGE(xmax, ymax, 32)    _SCREENMOVE 360, 20    DIM x(balls), y(balls), dx(balls), dy(balls), a(balls), rr(balls), gg(balls), bb(balls)    FOR i = 1 TO balls 'initialize balls to drop        x(i) = xmax / 2 + (i MOD 2) * 8 - 4: y(i) = 0 '                                     location        dx(i) = 0: dy(i) = 3 '                                                        change on axis        rr(i) = 150 + RND * 100: gg(i) = 150 + RND * 100: bb(i) = 150 + RND * 100 '        rgb color    NEXT    WHILE 1        CLS        loopCnt = loopCnt + 1 '                   drop ball every 17 loops so previous ball is clear        IF loopCnt MOD 17 = 0 THEN            IF maxBall < balls THEN maxBall = maxBall + 1        END IF        _PRINTSTRING (100, 10), "Balls:" + STR$(maxBall)        FOR i = 1 TO maxBall            'ready for collision            dy(i) = dy(i) + gravity '                               gravity increase update on y axis            a(i) = _ATAN2(dy(i), dx(i)) '                                       angle ball is heading            imoved = 0            FOR j = i + 1 TO maxBall                '      The following is STxAxTIC's adjustment of ball positions if overlapping before                ' calculation of new positions from collision. Displacement vector and its magnitude:                nx = x(j) - x(i): ny = y(j) - y(i)                nm = SQR(nx ^ 2 + ny ^ 2)                IF nm < 1 + 2 * br THEN                    nx = nx / nm: ny = ny / nm                    ' Regardless of momentum exchange, separate balls along the line connecting them.                    DO WHILE nm < 1 + 2 * br                        flub = .001                        x(j) = x(j) + flub * nx: y(j) = y(j) + flub * ny                        x(i) = x(i) - flub * nx: y(i) = y(i) - flub * ny                        nx = x(j) - x(i): ny = y(j) - y(i)                        nm = SQR(nx ^ 2 + ny ^ 2)                        nx = nx / nm: ny = ny / nm                    LOOP                    imoved = 1                    a(i) = _ATAN2(y(i) - y(j), x(i) - x(j))                    a(j) = _ATAN2(y(j) - y(i), x(j) - x(i))                    power1 = (dx(i) ^ 2 + dy(i) ^ 2) ^ .5 '       update new dx, dy for i and j balls                    power2 = (dx(j) ^ 2 + dy(j) ^ 2) ^ .5                    power = elastic * (power1 + power2) / 2                    dx(i) = power * COS(a(i)): dy(i) = power * SIN(a(i))                    dx(j) = power * COS(a(j)): dy(j) = power * SIN(a(j))                    x(i) = x(i) + dx(i): y(i) = y(i) + dy(i)                    x(j) = x(j) + dx(j): y(j) = y(j) + dy(j)                END IF '                                                              Thanks STxAxTIC            NEXT            IF imoved = 0 THEN x(i) = x(i) + dx(i): y(i) = y(i) + dy(i)            IF x(i) - br < 0 OR x(i) + br > xmax THEN '       keep balls inside sides and bottom edge                dx(i) = -dx(i)                IF x(i) - br < 0 THEN x(i) = br                IF x(i) + br > xmax THEN x(i) = xmax - br            END IF            IF y(i) + br > ymax THEN y(i) = ymax - br: dy(i) = -dy(i) * elastic            FOR rad = br TO 1 STEP -1 '                                         finally draw the ball                fcirc x(i), y(i), rad, _RGB32(rr(i) - 10 * rad, gg(i) - 10 * rad, bb(i) - 10 * rad)            NEXT        NEXT        _DISPLAY        _LIMIT 20    WEND         SUB fcirc (CX AS LONG, CY AS LONG, R AS LONG, C AS _UNSIGNED LONG) '       SMcNeill's fill circle        DIM subRadius AS LONG, RadiusError AS LONG, X AS LONG, Y AS LONG        subRadius = ABS(R): RadiusError = -subRadius: X = subRadius: Y = 0        IF subRadius = 0 THEN PSET (CX, CY): EXIT SUB        LINE (CX - X, CY)-(CX + X, CY), C, BF        WHILE X > Y            RadiusError = RadiusError + Y * 2 + 1            IF RadiusError >= 0 THEN                IF X <> Y + 1 THEN                    LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF                    LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF                END IF                X = X - 1                RadiusError = RadiusError - X * 2            END IF            Y = Y + 1            LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF            LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF        WEND    END SUB 

Navigation

[0] Message Index

Go to full version