Exercise in fun graphics

This is an image of an array of circles. I wanted to create a series of images where they were all moved in systematic ways, such as moving around their original centre, or moving radially in/out from their original position. This is quite easy to do in LB, but to get adequate speed and smooth animation I needed some tricks. I also wanted nice colour effects, so used my HSV routine to display nice graduated colours. The image shows a radially moved set against a background of their old positions. I could display the new positions directly with Liberty BASIC but you see the new grid drawn circle-by-circle.

There is an easy way past this- save each image as a bmp then convert them to an animated GIF. Sadly there is no easy way to show the animation within LB.

HOWEVER, LB can call ImageMagick. This free software can do just about every kind of graphic processing you could want or imagine. It can assemble BMPs saved from LB; scale them if desired; and output as an animation with my choice of time delay per image. Just install the portable version of ImageMagick in the same directory folder as the LB code and you have no issues over whole-path file names.

Now the problem is display. LB can't show the animation directly. However it can call a web browser to display them. Usually web pages that are not html but just an image can be displayed directly at Windows discretion, but I work under Linux/Wine and this didn't work directly- the window opened in the browser but showed nothing. So I included a routine to write an html page to display the image and call the browser to display that.

What I have now is code that creates the desired images, strings them into an animation, then calls the web browser to display it. This display does not have the distraction of seeing the build up of each layer's image, nor show any kind of tearing.

Now I can experiment with colours and what distortion each layer is to undergo.


LB Code

NB; Web browsers get confused by < and > signs other than when paired round html tags. I'll put up a zipped copy of the code for anyone hit by this. And you need to unzip portable ImageMagick for Windows into your LB folder-directory.


    '   Assumes Linux/Wine/LB4.5 and PortableImageMagick
    '       in the directory this .bas file is stored.

    nomainwin

    global pi, col$: pi   =3.14158265

    WindowWidth  =716
    WindowHeight =740

    open "Circle animator" for graphics_nsb as #wg

    #wg "trapclose quit"

    #wg "size 1 ; down ; fill 0 0 160 ; flush"

    calldll #kernel32, "Sleep",  2000 as long, ret as void

    #wg "backcolor 200 0 0 ; color 200 0 0"

    for x =50 to 650 step 50
        for y =50 to 650 step 50
            #wg "up ; goto "; x; " "; y
            #wg "down"
            #wg "circlefilled 20"
        next y
    next x

    #wg "flush"

    calldll #kernel32, "Sleep",  2000 as long, ret as void

    #wg "getbmp scr0 1 1 706 740"

    n   =1
    pi  =3.14158265

    t       =-20
    stp     =  4

  [around]
    print t, stp

    #wg "cls ; drawbmp scr0 0 0 ; flush"

    for x =50 to 650 step 50
        for y =50 to 650 step 50
            scan
            radius  =int( ( ( x -350)^2 +( y -350)^2)^0.5) /30
            theta   =ATAN2( 350.1 -y, x -350.1)
            dx      =t *radius /10 *cos( theta)
            dy      =t *radius /10 *sin( theta)
            xx      =x +dx
            yy      =y -dy

            if x <350.1 and y <350.1 then xx =x -dx: yy =y +dy  '   quadrant upper left
            if x >350.1 and y <350.1 then xx =x -dx: yy =y +dy: '   quadrant upper right
            if x >350.1 and y >350.1 then xx =x -dx: yy =y +dy: '   quadrant lower right
            if x <350.1 and y >350.1 then xx =x -dx: yy =y +dy  '   quadrant lower left

            call hsv2rgb int( 360 *radius /20), 0.99, 0.99    '   hue, saturation, value

            #wg "up ; goto "; xx; " "; yy
            #wg "down ; backcolor "; col$
            #wg "circlefilled 20"
        next y
    next x

    #wg "flush ; getbmp scr 1 1 710 700"
    bmpsave "scr", "ZZZZ" +right$( "000" +str$( n), 3) +".bmp"
    n       =n +1
    calldll #kernel32, "Sleep",  1000 as long, ret as void

    t       =t +stp

    if t >  20 and stp >0 then stp =0 -stp: t =20: goto [around]
    if t > -20 and stp >0 then goto [around]
    if t > -20 and stp <0 then goto [around]
'wait
    calldll #kernel32, "Sleep",  2000 as long, ret as void

    IM$ ="convert -geometry 50%x50% -delay 50  ZZZZ*.bmp ZZZZani.gif"

    run "cmd.exe /c "; chr$( 34); IM$; chr$( 34), HIDE
    calldll #kernel32, "Sleep",  10000 as long, ret as void

    'for i =1 to 10
        'kill "ZZZZ" +right$( "000" +str$( i), 3) +".bmp"
    'next i

    'run "explorer.exe ZZZZani.gif"   '   calls Wine/IE but doesn't display the gif <<<<<

    projectFile$ ="sampleH.html"
    Q$           =chr$( 34)

    open projectFile$ for output as #w
        #w "<html>"
        #w "<<body bgcolor=" +Q$ +"C0C080" +Q$ +">"
        #w "<center>"
        #w "<<h1>"
        #w "Animation output"
        #w "<</h1>>"
        #w "<mg src=" +chr$( 34) +"ZZZZani.gif" +chr$( 34) +">"
        #w "<p>"
        #w "</center>"
        #w "This animation was prepared, embedded in an html page and displayed in the web browser"
        #w "<p>"
        #w "<<hr>"
        #w "</body>"
        #w "</html>"
    close #w

    run "explorer.exe sampleH.html"

    close #wg

    wait

    sub quit h$
        close #wg
        end
    end sub

    function ATAN2( y, x)
        Result$ = "Undetermined"
        If ( x =0) and ( y >0) then ATAN2 = pi /2:      Result$ ="Determined"
        if ( x =0) and ( y <0) then ATAN2 =3 * pi /2:   Result$ ="Determined"
        if ( x >0) and ( y =0) then ATAN2 =0:           Result$ ="Determined"
        if ( x <0) and ( y =0) then ATAN2 =pi:          Result$ ="Determined"

        If Result$ <>"Determined" then
            BaseAngle =ATN( abs( y) /abs( x))
            If ( x >0) and ( y >0) then ATAN2 =        BaseAngle
            If ( x <0) and ( y >0) then ATAN2 = pi    -BaseAngle
            If ( x <0) and ( y <0) then ATAN2 = pi    +BaseAngle
            If ( x >0) and ( y <0) then ATAN2 = 2 *pi -BaseAngle
        end if
    End Function

        sub hsv2rgb h, s, v '                       hue 0-360, saturation 0-1, value 0-1
    if h >=360 or s >1 or v >1 then call quit h$
        c   =v *s       '                           chroma
        h   =h
        x   =c *( 1 -abs( ( ( h /60) mod 2) -1))
        m   =v -c   '                               matching adjustment

        select case
            case h < 60
                r = c: g = x: b = 0
            case h <120
                r = x: g = c: b = 0
            case h <180
                r = 0: g = c: b = x
            case h <240
                r = 0: g = x: b = c
            case h <300
                r = x: g = 0: b = c
            case else
                r = c: g = 0: b = x
        end select

        rd      = abs( int( 256 *( r + m)))
        gn      = abs( int( 256 *( g + m)))
        bu      = abs( int( 256 *( b + m)))
        col$    =right$( "  " +str$( rd), 3) +" " +right$( "   " +str$( gn), 3) +" " +right$( "   " +str$( bu), 3)

    end sub