Reflecting lines thingy

Started by BasicBoy, December 13, 2019, 05:05:33

Previous topic - Next topic

BasicBoy

Over on a BBC BASIC forum, some guy calling himself 'Repton' posted the following:

Quote


using draw commands how would this example be replicated

Here, he's referring to BBC BASIC native graphics commands (MOVE, DRAW, LINE, etc.).

Anyway, I took up his little challenge - it was easy enough, and the result looks kinda nice:




Here's the code (for completeness):


      *HEX 64

      WinW% = 800
      WinH% = 600

      VDU 23, 22, WinW%; WinH%; 8, 16, 16, 0 : OFF

      VDU 23,23,8| : REM set line thickness

      IF POS

      delay% = 32

      min_d% = 8
      max_d% = 24
      chgColTime% = 0

      DIM line{(1) x1, y1, x2, y2, dx1, dy1, dx2, dy2}

      FOR I% = 0 TO 1
        line{(I%)}.x1 = WinW% * FNrnd(I%)
        line{(I%)}.y1 = WinH% * FNrnd(I%)
        line{(I%)}.x2 = WinW% * FNrnd(I%)
        line{(I%)}.y2 = WinH% * FNrnd(I%)
        line{(I%)}.dx1 = FNd(I%)
        line{(I%)}.dy1 = FNd(I%)
        line{(I%)}.dx2 = FNd(I%)
        line{(I%)}.dy2 = FNd(I%)
      NEXT I%

      TIME = 0

      *REFRESH OFF

      REPEAT
 
        IF TIME >= chgColTime% THEN
          PROCSetRandomColour
          chgColTime% = TIME + 100 + RND(400)
        ENDIF
 
        FOR I% = 0 TO 1
          IF I% = 0 OR (I% = 1 AND delay% = 0) THEN
            IF I% = 0 THEN GCOL 3,1 ELSE GCOL 0
            LINE 2*line{(I%)}.x1, 2*line{(I%)}.y1, 2*line{(I%)}.x2, 2*line{(I%)}.y2
            LINE 2*line{(I%)}.y1, 2*line{(I%)}.x1, 2*line{(I%)}.y2, 2*line{(I%)}.x2
            LINE 2*(WinW%-line{(I%)}.x1), 2*line{(I%)}.y1, 2*(WinW%-line{(I%)}.x2), 2*line{(I%)}.y2
            LINE 2*(WinW%-line{(I%)}.y1), 2*line{(I%)}.x1, 2*(WinW%-line{(I%)}.y2), 2*line{(I%)}.x2
            LINE 2*line{(I%)}.x1, 2*(WinH%-line{(I%)}.y1), 2*line{(I%)}.x2, 2*(WinH%-line{(I%)}.y2)
            LINE 2*line{(I%)}.y1, 2*(WinH%-line{(I%)}.x1), 2*line{(I%)}.y2, 2*(WinH%-line{(I%)}.x2)
            LINE 2*(WinW%-line{(I%)}.x1), 2*(WinH%-line{(I%)}.y1), 2*(WinW%-line{(I%)}.x2), 2*(WinH%-line{(I%)}.y2)
            LINE 2*(WinW%-line{(I%)}.y1), 2*(WinH%-line{(I%)}.x1), 2*(WinW%-line{(I%)}.y2), 2*(WinH%-line{(I%)}.x2)
            line{(I%)}.x1 += line{(I%)}.dx1
            line{(I%)}.y1 += line{(I%)}.dy1
            line{(I%)}.x2 += line{(I%)}.dx2
            line{(I%)}.y2 += line{(I%)}.dx2
            IF line{(I%)}.x1 < 0     line{(I%)}.x1 = 0     : line{(I%)}.dx1 = -FNd(I%) * SGNline{(I%)}.dx1
            IF line{(I%)}.x1 > WinW% line{(I%)}.x1 = WinW% : line{(I%)}.dx1 = -FNd(I%) * SGNline{(I%)}.dx1
            IF line{(I%)}.x2 < 0     line{(I%)}.x2 = 0     : line{(I%)}.dx2 = -FNd(I%) * SGNline{(I%)}.dx2
            IF line{(I%)}.x2 > WinW% line{(I%)}.x2 = WinW% : line{(I%)}.dx2 = -FNd(I%) * SGNline{(I%)}.dx2
            IF line{(I%)}.y1 < 0     line{(I%)}.y1 = 0     : line{(I%)}.dy1 = -FNd(I%) * SGNline{(I%)}.dy1
            IF line{(I%)}.y1 > WinH% line{(I%)}.y1 = WinH% : line{(I%)}.dy1 = -FNd(I%) * SGNline{(I%)}.dy1
            IF line{(I%)}.y2 < 0     line{(I%)}.y2 = 0     : line{(I%)}.dy2 = -FNd(I%) * SGNline{(I%)}.dy2
            IF line{(I%)}.y2 > WinH% line{(I%)}.y2 = WinH% : line{(I%)}.dy2 = -FNd(I%) * SGNline{(I%)}.dy2
          ENDIF
        NEXT I%
 
        IF delay% > 0 delay% -= 1
 
        *REFRESH
 
        WAIT 8
 
      UNTIL FALSE
      END

      DEF PROCSetRandomColour
      CASE RND(14) OF
        WHEN  1 : COLOUR 1, 255, 0, 0
        WHEN  2 : COLOUR 1, 0, 255, 0
        WHEN  3 : COLOUR 1, 0, 0, 255
        WHEN  4 : COLOUR 1, 255, 0, 255
        WHEN  5 : COLOUR 1, 255, 255, 0
        WHEN  6 : COLOUR 1, 0, 255, 255
        WHEN  7 : COLOUR 1, 255, 127, 0
        WHEN  8 : COLOUR 1, 255, 0, 127
        WHEN  9 : COLOUR 1, 127, 255, 0
        WHEN 10 : COLOUR 1, 127, 0, 255
        WHEN 11 : COLOUR 1, 0, 127, 255
        WHEN 12 : COLOUR 1, 255, 127, 127
        WHEN 13 : COLOUR 1, 127, 255, 127
        WHEN 14 : COLOUR 1, 127, 127, 255
      ENDCASE
      ENDPROC

      DEF FNd(I%) = min_d% + (max_d% - min_d%) * FNrnd(I%)

      DEF FNrnd(I%)
      PRIVATE F%, S%%() : DIM S%%(1)
      IF NOT F% THEN
        S%%(0) = RND OR (RND << 31)
        S%%(1) = S%%(0)
        F% = TRUE
      ENDIF
      S%%(I%) EOR= S%%(I%) << 13
      S%%(I%) EOR= S%%(I%) >>> 17
      S%%(I%) EOR= S%%(I%) << 5
      = (S%%(I%) AND &FFFFFFFF) / &FFFFFFFF


Notice the 'custom' Xorshift RNG at the end (courtesy of the late George Marsaglia).


BasicBoy.
--


Qube

Good old kaleidoscope line effect in action ;D

Lol, I was going to comment that the 1st video was more like a C64 until I looked at the YouTube title :P - Yours run faster and looks more fancy.
Mac Studio M1 Max ( 10 core CPU - 24 core GPU ), 32GB LPDDR5, 512GB SSD,
Beelink SER7 Mini Gaming PC, Ryzen 7 7840HS 8-Core 16-Thread 5.1GHz Processor, 32G DDR5 RAM 1T PCIe 4.0 SSD
MSI MEG 342C 34" QD-OLED Monitor

Until the next time.

bplus

#2
Nice I am fan of this kind of stuff and Richard Russell :)
1 person likes this

BasicBoy

Since kaleidoscopes have been mentioned, here's a semi-realistic one (done rather inefficiently it must be said)  :D



The program runs faster/smoother than the video would suggest, but recording stuff at 60 fps on my laptop doesn't work too well due to on-the-fly system encryption which slows HD writes a bit.


      REM Semi-Realistic Kaleidoscope
      REM Requires BB4W & GfxLib2
      REM
      REM Note that this program uses a *very* inefficient means of achieving a kaleidoscope effect!

      *ESC OFF

      MODE 8 : OFF

      ScrW% = 640
      ScrH% = 512

      INSTALL @lib$ + "GFXLIB2.BBC"
      PROCInitGFXLIB(g{}, 0)

      DIM g2{} = g{}
      g2{} = g{}

      INSTALL @lib$+"GFXLIB_modules\ClrLG.bbc"             : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\DrawFilledCircle.bbc"  : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\BPlotRotateScale2.bbc" : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\PlotRotateScale2.bbc"  : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\Copy.bbc"              : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\BPlotFlip.bbc"         : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\PlotFlip.bbc"          : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\ReplaceColour.bbc"     : PROCInitModule(0)

      nDiscs% = 100
      DIM disc{( nDiscs%-1 ) move%, x, y, r, x2, y2, dx, dy, rgb}

      imgSz% = 512
      img% = FNmalloc(4 * imgSz%^2)

      maskSz% = 256
      maskBm% = FNmalloc(4 * maskSz%^2)

      bm1Sz% = 256
      bm1% = FNmalloc(4 * bm1Sz%^2)

      bm2Sz% = 256
      bm2% = FNmalloc(4 * bm2Sz%^2)

      REM Create equilateral triangle mask bitmap:
      SYS GFXLIB_SaveAndSetDispVars%, g{}, maskBm%, maskSz%, maskSz%
      FOR Y% = 0 TO maskSz%-1
        w = Y%*TANRAD30
        IF w <= maskSz%/2 THEN
          SYS GFXLIB_Line%, g{}, 0, Y%, maskSz%/2-w, Y%, &808080
          SYS GFXLIB_Line%, g{}, maskSz%/2+w, Y%, maskSz%-1, Y%, &808080
        ELSE
          SYS GFXLIB_Line%, g{}, 0, Y%, maskSz%-1, Y%, &808080
        ENDIF
      NEXT Y%
      SYS GFXLIB_RestoreDispVars%, g{}

      REM Initialise discs:
      FOR I% = 0 TO nDiscs%-1
        disc{(I%)}.move% = FALSE
        disc{(I%)}.x = RND(ScrW%)
        disc{(I%)}.y = RND(ScrH%)
        disc{(I%)}.r = 8 + RND(20)
        CASE RND(12) OF
          WHEN  1 : disc{(I%)}.rgb = &FF0000
          WHEN  2 : disc{(I%)}.rgb = &00FF00
          WHEN  3 : disc{(I%)}.rgb = &0000FF
          WHEN  4 : disc{(I%)}.rgb = &FF00FF
          WHEN  5 : disc{(I%)}.rgb = &FFFF00
          WHEN  6 : disc{(I%)}.rgb = &00FFFF
          WHEN  7 : disc{(I%)}.rgb = &FF8000
          WHEN  8 : disc{(I%)}.rgb = &0080FF
          WHEN  9 : disc{(I%)}.rgb = &00FF80
          WHEN 10 : disc{(I%)}.rgb = &80FF00
          WHEN 11 : disc{(I%)}.rgb = &8080FF
          WHEN 12 : disc{(I%)}.rgb = &FFFFFF
        ENDCASE
      NEXT I%

      TIME = 0

      moveDiscsTime% = 500

      *REFRESH OFF

      REPEAT
 
        T% = TIME
 
        REM Rotational angle of discs bitmap:
        angle = 720*SIN(T%/1000 + PI/5*SIN(T%/1050+0.345))*SIN(T%/950 + PI/8*SIN(T%/800-1.25))
 
        REM Draw discs and update their positions:
        SYS GFXLIB_SaveAndSetDispVars%, g{}, img%, imgSz%, imgSz%
        SYS GFXLIB_Clr%, g{}, 0
        FOR I% = 0 TO nDiscs%-1
          SYS GFXLIB_DrawFilledCircle%, g{}, disc{(I%)}.x, disc{(I%)}.y, disc{(I%)}.r+3, &010101
          SYS GFXLIB_DrawFilledCircle%, g{}, disc{(I%)}.x, disc{(I%)}.y, disc{(I%)}.r, disc{(I%)}.rgb
          IF disc{(I%)}.move% THEN
            disc{(I%)}.x += disc{(I%)}.dx
            disc{(I%)}.y += disc{(I%)}.dy
            IF (disc{(I%)}.x - disc{(I%)}.x2)^2 +  (disc{(I%)}.y - disc{(I%)}.y2)^2 < 0.5^2 THEN
              disc{(I%)}.move% = FALSE
            ENDIF
          ENDIF
        NEXT I%
        SYS GFXLIB_RestoreDispVars%, g{}
 
        REM If it's time to move the discs, then set new target positions:
        IF TIME > moveDiscsTime% THEN
          FOR I% = 0 TO nDiscs%-1
            disc{(I%)}.move% = TRUE
            disc{(I%)}.x2 = RND(ScrW%)
            disc{(I%)}.y2 = RND(ScrH%)
            dx = disc{(I%)}.x2 - disc{(I%)}.x
            dy = disc{(I%)}.y2 - disc{(I%)}.y
            len = SQR( dx^2 + dy^2 )
            disc{(I%)}.dx = dx / len
            disc{(I%)}.dy = dy / len
          NEXT I%
          moveDiscsTime% = TIME + 1000 + RND(1000)
        ENDIF
 
        REM Draw the rotating disc image bitmap:
        SYS GFXLIB_BPlotRotateScale2%, g{}, img%, imgSz%, imgSz%, ScrW%/2, ScrH%/2, &10000*angle, &10000
 
        REM Draw the equilateral triangle mask bitmap:
        SYS GFXLIB_Plot%, g{}, maskBm%, maskSz%, maskSz%, (ScrW%-maskSz%)/2, ScrH%/2
 
        REM Copy mask bitmap to a temp buffer (bm1%):
        SYS GFXLIB_SaveAndSetDispVars%, g2{}, bm1%, bm1Sz%, bm1Sz%
        SYS GFXLIB_Copy%, g{}, g2.bmBuffAddr%, g2.bmBuffW%, g2.bmBuffH%, (ScrW%-maskSz%)/2, ScrH%/2
        SYS GFXLIB_RestoreDispVars%, g2{}
 
        REM Replace the grey masking colour with black:
        SYS GFXLIB_ReplaceColour%, bm1%, bm1Sz%, bm1Sz%, &808080, &000000
 
        REM Copy a vertically flipped version of bm1 into bm2:
        SYS GFXLIB_SaveAndSetDispVars%, g{}, bm2%, bm2Sz%, bm2Sz%
        SYS GFXLIB_BPlotFlip%, g{}, bm1%, bm1Sz%, bm1Sz%, 0, 0, 1
        SYS GFXLIB_RestoreDispVars%, g{}
 
        REM Clear the window (actually fill it with a colour gradient):
        SYS GFXLIB_ClrLG%, g{}, &208020, &202080
 
        REM Draw top thee equilateral triangle bitmaps:
        SYS GFXLIB_Plot%, g{}, bm1%, bm1Sz%, bm1Sz%, (ScrW%-maskSz%)/2, ScrH%/2
        SYS GFXLIB_PlotRotateScale2%, g{}, bm2%, bm2Sz%, bm2Sz%, ScrW%/2+108, ScrH%/2+65, 60*&10000, &10000
        SYS GFXLIB_PlotRotateScale2%, g{}, bm2%, bm2Sz%, bm2Sz%, ScrW%/2-109, ScrH%/2+65,-60*&10000, &10000
 
        REM Draw the bottom three:
        SYS GFXLIB_PlotFlip%, g{}, bm1%, bm1Sz%, bm1Sz%, (ScrW%-maskSz%)/2, 5, 2
        SYS GFXLIB_PlotRotateScale2%, g{}, bm1%, bm1Sz%, bm1Sz%, ScrW%/2+108, ScrH%/2-60, (180-60)*&10000, &10000
        SYS GFXLIB_PlotRotateScale2%, g{}, bm1%, bm1Sz%, bm1Sz%, ScrW%/2-109, ScrH%/2-60, (180+60)*&10000, &10000
 
        REM Draw enclosing hexagon:
        FOR R% = 256 TO 258
          FOR I% = 0 TO 5
            x1 = 319 + R%*COSRAD(60 * I%)
            y1 = 258 + R%*SINRAD(60 * I%)
            x2 = 319 + R%*COSRAD(60 * (I%+1))
            y2 = 258 + R%*SINRAD(60 * (I%+1))
            SYS GFXLIB_Line%, g{}, x1, y1, x2, y2, &000001
          NEXT I%
        NEXT R%
 
        PROCdisplay
 
      UNTIL FALSE




BasicBoy.
--

bplus

Ah! seems like you are a step away from a snowflake generator. :)
1 person likes this