DNA Animation
#11
@OLdMoses

Sin puts a nice edge on those balls, thumbs up!
b = b + ...
Reply
#12
(07-31-2022, 05:05 PM)bplus Wrote: @OLdMoses

Sin puts a nice edge on those balls, thumbs up!

If my balls cause me to sin.... Blush
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#13
(07-31-2022, 05:05 PM)bplus Wrote: @OLdMoses

Sin puts a nice edge on those balls, thumbs up!
Great, with t and tt one can change the DNA strand: t=140, tt=45 -- t=140, tt=25 . . . and so on. Thanks!  Rolleyes
Reply
#14
Yeah I see what you mean about loose artifacts OldMoses. But I'm just going to keep it as it is. I'll just say that the bands are tilted and not lined up. It looks good enough for me.
Reply
#15
Awesome colors KernalPanic! Smile
Reply
#16
(07-31-2022, 07:49 PM)SierraKen Wrote: Yeah I see what you mean about loose artifacts OldMoses. But I'm just going to keep it as it is. I'll just say that the bands are tilted and not lined up. It looks good enough for me.

Ah, but you're so close! It's a great algorithm, and just needed a couple tweaks. Allow me to have a go at it...

The main issue is the many different variables for each ball, which make it difficult to compare them with simple tests and/or iterate through them with looping structures that can reduce code dramatically. The solution would be to either do multiple arrays indexed to each ball, or a single UDT array containing all the ball's data. I'll do a UDT array for the balls and also a small one for sorting purposes. Then add a sorting SUB to rearrange the balls after their position and radius data are updated in the loop. Arranging in ascending order of radius means they will be drawn from furthest away to closest, and thus will naturally overlap properly.

Code: (Select All)
'DNA Animation by SierraKen
'Ball design by B+ and OldMoses
'UDT array and sorting tweaks by OldMoses
'July 31, 2022

TYPE ball
    st AS INTEGER '                                             start point
    x AS INTEGER '                                              x position
    y AS INTEGER '                                              y position
    am AS SINGLE '                                              angular modifier
    ys AS INTEGER '                                             y axis offset
    r AS SINGLE '                                               radius
END TYPE

TYPE sort '                                                     used in SUB Sorter to sort by specific value
    index AS INTEGER
    value AS SINGLE
END TYPE

DIM SHARED B(12) AS ball '                                      ball array

FOR bl% = 1 TO 12 '                                             load static ball parameters
    IF bl% > 6 THEN
        B(bl%).st = 180
    ELSE
        B(bl%).st = 45
    END IF
    READ B(bl%).am, B(bl%).ys
NEXT bl%

_TITLE "DNA Animation by SierraKen"
SCREEN _NEWIMAGE(800, 600, 32)
DIM c AS LONG
t = 180
c = _RGB32(0, 127, 255)
DO
    _LIMIT 40
    FOR bl% = 1 TO 12 '                                         loop through position and radius computations
        'Ken's base algorithm- just tweaked to accept the UDT array
        B(bl%).x = (SIN(B(bl%).st + t + B(bl%).am) * 180) + 400
        B(bl%).y = (COS(B(bl%).st + t + B(bl%).am) * 180) / _PI / 10 + B(bl%).ys
        B(bl%).r = (COS(B(bl%).st + t + B(bl%).am) * 180) / _PI / 10 + 40
    NEXT bl%
    Sorter '                                                    next we will sort, by radius, smaller to larger
    FOR x% = 1 TO 12 '                                          loop through the sorted balls and display
        drawBall B(x%).x, B(x%).y, B(x%).r, c '                 balls earlier in the loop are smaller and thus farther
    NEXT x% '                                                   away and will be necessarily overlapped by later, larger balls
    t = t - .05
    _DISPLAY
    CLS
LOOP UNTIL INKEY$ = CHR$(27)
END

'static ball parameters for 12 paired balls
DATA 0,100,.7,165,1.4,230,2.1,295,2.8,360,3.5,425
DATA 0,100,.7,165,1.4,230,2.1,295,2.8,360,3.5,425


SUB Sorter
    'This may be a rather clumsy method, but seems to be fast enough to work
    DIM temp(UBOUND(B)) AS ball
    DIM s(UBOUND(B)) AS sort
    FOR x% = 1 TO UBOUND(B) '                                   iterate through the array
        temp(x%) = B(x%) '                                      copy original into a temporary array
        s(x%).index = x% '                                      set sorter index
        s(x%).value = B(x%).r '                                 set sorter value to radius of ball
    NEXT x%
    DO '                                                        bubble sort the array
        flips% = 0 '                                            reset flip flag for this loop
        FOR n% = 1 TO UBOUND(B) - 1 '                           loop through all but last array element
            IF s(n%).value > s(n% + 1).value THEN '             if radius greater than next radius
                SWAP s(n%), s(n% + 1) '                         swap the two and...
                flips% = -1 '                                   set flip flag to true
            END IF
        NEXT n%
    LOOP WHILE flips% '                                         loop until no more flips happen. No flips = fully sorted
    FOR x% = 1 TO UBOUND(B) '                                   iterate the array again
        B(x%) = temp(s(x%).index) '                             set ball order to sort order
    NEXT x%
END SUB 'Sorter


SUB drawBall (x, y, r, c AS _UNSIGNED LONG)
    DIM rred AS LONG, grn AS LONG, blu AS LONG, rr AS LONG, f
    rred = _RED32(c): grn = _GREEN32(c): blu = _BLUE32(c)
    FOR rr = r TO 0 STEP -1
        f = 1 - SIN(rr / r)
        fillCircle x, y, rr, _RGB32(rred * f, grn * f, blu * f)
    NEXT
END SUB


'from Steve Gold standard
SUB fillCircle (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
    DIM Radius AS INTEGER, RadiusError AS INTEGER
    DIM X AS INTEGER, Y AS INTEGER
    Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
    IF Radius = 0 THEN PSET (CX, CY), C: 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
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#17
Incredible OldMoses! I knew there had to be a way like that somehow, but the thing is, in my entire life I have only done multiple arrays on a single variable a couple times. And I have never used the Type command on my own code. So it's kinda like looking at a different language but someday I'll figure it out I hope. Thanks for figuring it out! Hopefully I'll look back at it sometime and try to decipher it all. But like I said, I had a feeling a lot less code was actually needed.
Reply
#18
TYPE...END TYPE UDT arrays can be a bit daunting at first, I know I found them so when I first got into QBasic. I was quite a while figuring out the whole "procedural" programming thing, having come from Applesoft Basic with it's line numbers, GOTOs, GOSUBs and two character variable names. It had arrays, but only very simple ones. Moving to Qbasic I had to learn SUBs, FUNCTIONS and UDTs, nearly giving up several times, but the effort paid off.

When ever you are doing some sort of data object multiple times (such as 12 helix balls), that contain multiple different data points ( x,y positions, radii, y offsets, start positions, etc), they are a great way to handle it. Particularly when you're doing the same things to those objects over and over.

They really made that sorting SUB easy, since I only needed to sort by the radius element and all the rest of the data just moves with it.

If you figured out that helical trig stuff, it shouldn't be too hard. Play with it some when you can and it'll come.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#19
I wondered if someone would resort to sorting.
b = b + ...
Reply
#20
Thanks OldMoses. I also started in AppleSoft BASIC in the 80's. Remember HOME instead of CLS? And there was GR and HGR and HGR2 for graphic screens. GR had the regular text at the bottom for a few lines. lol Actually the very first programming I did was in the 7th grade in the brand new computer lab the school got and we did a graphics language called LOGO. With LOGO we did PU PD (pen up, pen down) and the turtle walked in steps drawing your lines. Smile
Reply




Users browsing this thread: 18 Guest(s)