Author Topic: Dav's Doodle Dandy - animated image drawing.  (Read 6774 times)

0 Members and 1 Guest are viewing this topic.

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Dav's Doodle Dandy - animated image drawing.
« on: June 02, 2021, 09:23:59 pm »
This is an animated image drawing doodler thing (work in progress)  You can draw images with the doodle make program, it saves it as a special image file.  Then you can play it back later with the doodle player program. When playing back the saved file it will draw the image on the screen with a hand, like it's drawing the image live, like a video animation.  Got the idea watching youtube vids yesterday made with a doodler program.  Wondered how easy it could be to make in QB64. 

To see what it can do, run the DOODLE-PLAY.BAS program and it will load/run the DOODLE.DAG image animation.  Just half a days work so far, lots of improvements to be made still. There is a glitch when changing colors, trying to figure that out.

You could make small presentations/intros with this I suppose...

- Dav

EDIT: Fixed glitch...redownload please...

  (93k)

 
davsdoodle.jpg

« Last Edit: June 02, 2021, 10:47:33 pm by Dav »

Offline OldsCool

  • Newbie
  • Posts: 19
  • 3D Spherical programming is as easy as pi
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #1 on: June 02, 2021, 09:58:43 pm »
very COOL and smooth! I created something similar to this in Qbasic some time ago (minus the hand image) that saved the screen data from individual computer generated images(low Res) to play back later as a motion video with an independent motion player I created. in the motion file it only saved the 'Differences' in each consecutive frame (Image) thereby acting as 'compression' increasing the playback speed (slow Qbasic and computer back then) and making for much smaller play-back files.
I enjoyed your demo !  thank goodness we have QB64 and thank you to the QB64 development team!

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #2 on: June 02, 2021, 10:42:12 pm »
Thanks, @OldsCool.  Thanks for trying it out.  Interesting about your Qbasic project.  Sounds like you made something like the FLIC format animation files used.  I think the challenge of getting by Qbasic's limitations only made it more fun!

I fixed the glitch - the jumping hand now and then.  I just posted a fixed version.  Had to re-record the drawing.  Redownload for the fixed programs.

- Dav   
« Last Edit: June 02, 2021, 10:49:36 pm by Dav »

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #3 on: June 04, 2021, 09:10:59 am »
I have been working on this some more, but want to put it in more of a finished product before posting.  Not sure when that will be because my gigs are picking up good again and my free programming time is reduced.  So here's a preview... 

It's using SPAINT routine now by @Petr that he wrote for my QuadDraw program last year (Thanks for the cool routine, Petr!).  Also trying to incorporate Petr's way or drawing the line so there are no gaps when drawing fast.  I'm adding pausing and wipe screen clear commands so you can do message kind of animations.  Playing around with an eraser pic to do the wiping.  And different hand position images now and then.  I'm adding the capability for custom screen sizes, and giving the image file a header to hold info.  Also doing a rewrite of the doodle-make program putting everything in a right click menu (color select is there too).  Adding a file browser to the player program, and also accept COMMAND$ to play on startup, and playback controls.

If anyone has any suggestions to add, please do.  Thanks. 

- Dav
« Last Edit: June 04, 2021, 09:13:32 am by Dav »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #4 on: June 04, 2021, 11:21:32 am »
I like how you will be able to make fun presentations hopefully.

Are you thinking soundly?

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #5 on: June 04, 2021, 11:56:35 am »
I like how you will be able to make fun presentations hopefully.

Are you thinking soundly?

Thanks for reminding me. It would be great to have optional background music.  And perhaps combining the sound and image data into one file. Image data can be tacked onto the end of an audio file, and QB64 will still be able to open and play the sound files with the extra data on the end (that’s how the .qbv video format thing last year worked). I’d like to keep the presentations as one file.

-Dav

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #6 on: June 05, 2021, 10:26:30 am »
Nice work, Dav! For a combination of audio and video, for the simplest work, a custom format would probably be the simplest - basically you can determine how long it takes to draw one frame according to the number of steps used (in your .DAG format). If you have the number of steps of one animation and the number of frames in the file (in the new type of binary file you specify the number of DAG files), you have the total video time. All you have to do is add information to the file about which frames belong together (for example, that the first animation has four frames (in the current state as if 4 .DAG files) and here you can insert a change of the soundtrack (up to this time). video and audio transition), for example by numbering. Subsequently, the binary file would describe the video, for example, as follows: (this is just a suggestion from my head)

Number of DAG files in the file - LONG - 4 bytes
Number of audio files - LONG - 4 bytes

Lengths of individual DAG files in seconds (repeated according to the number of DAG files in the file) - LONG - 4 bytes * number of DAG files

Binary sizes of individual DAG files - LONG - 4 bytes * number of DAG files

Offsets on which individual DAG files start - LONG - 4 bytes * number of DAG files

Offsets where music files start - LONG - 4 bytes * number of audio files

Playback description: (let's say we have 10 DAG files and 3 music files)

1 (plays the first DAG video), 1 (plays the first audio file), 5 (the effect number for the video when switching from one DAG file to another DAG file), 7 (the effect number for the sound when changing the audio), 2 (plays the second DAG video), 1 (plays the first audio file) .......

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #7 on: June 06, 2021, 09:16:04 am »
Petr, thank you for the great suggestions.  I think I should re-do how I'm recording the animation to sync sound.  Right now I'm just recording mouse movements and clicks in steps, outside of a timeline.   The way you describe doing the header is good, I'm thinking along that way too.  Thanks.

- Dav

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #8 on: June 08, 2021, 04:25:33 am »
@Dav
Hi, I find your work very good. 
A little set of questions to understand the goal of application
1.  no UNDO?
2. Is it in the feature that Fill clears the whole canvas into a single color?
3.  What do you think about an option to fill only background color with the new choosen color?
4. How other wonderful QB64 applications do you want share  ?

I agree with you message:
 
DAV Painter.jpg
Programming isn't difficult, only it's  consuming time and coffee

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #9 on: June 08, 2021, 07:04:13 am »
Hi @TempodiBasic !  Thank you! 

1. Yes, I have UNDO on the list, because I need it very much. I started to add it last night, but it’s not working good yet.

2.  I am adding screen wipes to clear screen to a certain color.  I also added brush size change, allowing one to wipe the screen clear very fast. 

3. Nice idea, maybe I can do a color swap for that

4. I write a lot of programs for fun or to work out an idea that I’m curious about.  The majority of them are not good enough to post here, so I don’t share most of them.  I suppose there are a couple more I could post without embarrassing myself.

Thank you for trying the program. 

- Dav

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #10 on: June 08, 2021, 06:39:55 pm »
One thing I'm trying to do is eliminate to gaps in the drawing line when moving the mouse too fast (like in your image above @TempodiBasic) by drawing in the in-between space.  It seems simple at first, save the last known x/y point and fill in between that and the new x/y, but I'm not seeing it clearly yet how to correctly.  It's too blocky when moving real fast, so I need to do a series of blocks on the line.   I'm sure I'm not seeing something probably so obvious to others.  Here's an example...

- Dav

Code: QB64: [Select]
  1.  
  2. SCREEN _NEWIMAGE(600, 600, 32)
  3.  
  4. CLS , _RGB(255, 255, 255)
  5.  
  6. size% = 3: clr& = _RGB(0, 0, 0)
  7.  
  8.  
  9.     mi = _MOUSEINPUT: mx = _MOUSEX: my = _MOUSEY
  10.  
  11.  
  12.         'if drawing still, draw pixels in between
  13.         IF drawing = 1 THEN
  14.             LINE (oldmx, oldmy)-(mx, my), clr&, BF
  15.         END IF
  16.  
  17.         'draw line brush
  18.         LINE (mx - (size% / 2), my - (size% / 2))-(mx + (size% / 2), my + (size% / 2)), clr&, BF
  19.  
  20.         'use circle brush instead of line
  21.         'FOR d = 1 TO size% STEP .2
  22.         '    CIRCLE (mx, my), d, clr&
  23.         'NEXT
  24.  
  25.         drawing = 1: oldmx = mx: oldmy = my
  26.  
  27.     ELSE
  28.  
  29.         drawing = 0
  30.  
  31.     END IF
  32.  
  33.  
« Last Edit: June 08, 2021, 07:28:03 pm by Dav »

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #11 on: June 08, 2021, 07:37:43 pm »
Sup Dav -

The thing you want is linear interpolation. Highly google-able, but I'll do you one better. From our very own archives, the curve smoother:

Code: QB64: [Select]
  1. '_OE
  2.  
  3. _TITLE "If these curves were smoother they'd steal your wife."
  4.  
  5. ' Hardware
  6. SCREEN _NEWIMAGE(800, 600, 32)
  7. _SCREENMOVE (_DESKTOPWIDTH \ 2 - _WIDTH \ 2) - 3, (_DESKTOPHEIGHT \ 2 - _HEIGHT \ 2) - 29
  8.  
  9. ' Meta
  10.  
  11. ' Data structures
  12. TYPE Vector
  13.     x AS DOUBLE
  14.     y AS DOUBLE
  15.  
  16. ' Object type
  17. TYPE Object
  18.     Elements AS INTEGER
  19.     Shade AS _UNSIGNED LONG
  20.  
  21. ' Object storage
  22. DIM SHARED Shape(300) AS Object
  23. DIM SHARED PointChain(300, 500) AS Vector
  24. DIM SHARED TempChain(300, 500) AS Vector
  25. DIM SHARED ShapeCount AS INTEGER
  26. DIM SHARED SelectedShape AS INTEGER
  27.  
  28. DIM SHARED MasterDraw AS STRING
  29.  
  30. ' Initialize
  31. ShapeCount = 0
  32.  
  33. ' Main loop
  34.     LOCATE 1, 1: PRINT ShapeCount
  35.     CALL UserInput
  36.     CALL Graphics
  37.     _LIMIT 120
  38.  
  39.  
  40. SUB UserInput
  41.     TheReturn = 0
  42.     ' Keyboard input
  43.     kk = _KEYHIT
  44.     SELECT CASE kk
  45.         CASE 32
  46.             DO: LOOP UNTIL _KEYHIT
  47.             WHILE _MOUSEINPUT: WEND
  48.             _KEYCLEAR
  49.             CALL NewMouseShape(7.5, 400, 15)
  50.             CLS
  51.         CASE ASC("e"), ASC("E")
  52.             OPEN "Curves" + LTRIM$(RTRIM$(STR$(INT(TIMER)))) + ".txt" FOR OUTPUT AS #1
  53.             PRINT #1, MasterDraw
  54.             CLOSE #1
  55.     END SELECT
  56.     IF (kk) THEN
  57.         _KEYCLEAR
  58.     END IF
  59.  
  60. SUB Graphics
  61.     DIM k AS INTEGER
  62.     DIM x1 AS DOUBLE
  63.     DIM x2 AS DOUBLE
  64.     DIM y1 AS DOUBLE
  65.     DIM y2 AS DOUBLE
  66.     MasterDraw = ""
  67.     LINE (0, 0)-(_WIDTH, _HEIGHT), _RGBA(0, 0, 0, 255), BF
  68.     CALL cPrintstring(16 * 17, "PRESS SPACE and then drag MOUSE 1 to draw a new shape.")
  69.     FOR k = 1 TO ShapeCount
  70.         z$ = "c" + STR$(Shape(k).Shade) + " "
  71.         FOR i = 1 TO Shape(k).Elements - 1
  72.             x1 = PointChain(k, i).x
  73.             y1 = PointChain(k, i).y
  74.             x2 = PointChain(k, i + 1).x
  75.             y2 = PointChain(k, i + 1).y
  76.             'CALL lineSmooth(x1, y1, x2, y2, Shape(k).Shade)
  77.  
  78.             '''
  79.             ' Fellippe, this was it ...
  80.             dr = SQR((x2 - x1) ^ 2 + (y2 - y1) ^ 2)
  81.             ang = (180 / 3.1416 * ATN((y2 - y1) / (x2 - x1)))
  82.             IF (x2 < x1) THEN
  83.                 ang = 180 + ang
  84.             END IF
  85.             z$ = z$ + "TA " + STR$(ang - 90) + " U" + STR$(dr) + " "
  86.             '''
  87.         NEXT
  88.         ' Make a point to get DRAW started.
  89.         CALL cPset(PointChain(k, 1).x, PointChain(k, 1).y, Shape(k).Shade)
  90.         ' Draw replaces CLine.
  91.         MasterDraw = MasterDraw + z$ + "___"
  92.         DRAW z$
  93.     NEXT
  94.     _DISPLAY
  95.  
  96. SUB NewMouseShape (rawresolution AS DOUBLE, targetpoints AS INTEGER, smoothiterations AS INTEGER)
  97.     ShapeCount = ShapeCount + 1
  98.     numpoints = 0
  99.     xold = 999 ^ 999
  100.     yold = 999 ^ 999
  101.     DO
  102.         DO WHILE _MOUSEINPUT
  103.             x = _MOUSEX
  104.             y = _MOUSEY
  105.             IF (x > 0) AND (x < _WIDTH) AND (y > 0) AND (y < _HEIGHT) THEN
  106.                 IF _MOUSEBUTTON(1) THEN
  107.                     x = x - (_WIDTH / 2)
  108.                     y = -y + (_HEIGHT / 2)
  109.                     delta = SQR((x - xold) ^ 2 + (y - yold) ^ 2)
  110.                     IF (delta > rawresolution) AND (numpoints < targetpoints - 1) THEN
  111.                         numpoints = numpoints + 1
  112.                         PointChain(ShapeCount, numpoints).x = x
  113.                         PointChain(ShapeCount, numpoints).y = y
  114.                         CALL cPset(x, y, _RGB(0, 255, 255))
  115.                         xold = x
  116.                         yold = y
  117.                     END IF
  118.                 END IF
  119.             END IF
  120.         LOOP
  121.         _DISPLAY
  122.     LOOP UNTIL NOT _MOUSEBUTTON(1) AND (numpoints > 1)
  123.  
  124.     DO WHILE (numpoints < targetpoints)
  125.         rad2max = -1
  126.         kmax = -1
  127.         FOR k = 1 TO numpoints - 1
  128.             xfac = PointChain(ShapeCount, k).x - PointChain(ShapeCount, k + 1).x
  129.             yfac = PointChain(ShapeCount, k).y - PointChain(ShapeCount, k + 1).y
  130.             rad2 = xfac ^ 2 + yfac ^ 2
  131.             IF rad2 > rad2max THEN
  132.                 kmax = k
  133.                 rad2max = rad2
  134.             END IF
  135.         NEXT
  136.         FOR j = numpoints TO kmax + 1 STEP -1
  137.             PointChain(ShapeCount, j + 1).x = PointChain(ShapeCount, j).x
  138.             PointChain(ShapeCount, j + 1).y = PointChain(ShapeCount, j).y
  139.         NEXT
  140.         PointChain(ShapeCount, kmax + 1).x = (1 / 2) * (PointChain(ShapeCount, kmax).x + PointChain(ShapeCount, kmax + 2).x)
  141.         PointChain(ShapeCount, kmax + 1).y = (1 / 2) * (PointChain(ShapeCount, kmax).y + PointChain(ShapeCount, kmax + 2).y)
  142.         numpoints = numpoints + 1
  143.     LOOP
  144.  
  145.     FOR j = 1 TO smoothiterations
  146.         FOR k = 2 TO numpoints - 1
  147.             TempChain(ShapeCount, k).x = (1 / 2) * (PointChain(ShapeCount, k - 1).x + PointChain(ShapeCount, k + 1).x)
  148.             TempChain(ShapeCount, k).y = (1 / 2) * (PointChain(ShapeCount, k - 1).y + PointChain(ShapeCount, k + 1).y)
  149.         NEXT
  150.         FOR k = 2 TO numpoints - 1
  151.             PointChain(ShapeCount, k).x = TempChain(ShapeCount, k).x
  152.             PointChain(ShapeCount, k).y = TempChain(ShapeCount, k).y
  153.         NEXT
  154.     NEXT
  155.  
  156.     Shape(ShapeCount).Elements = numpoints
  157.     Shape(ShapeCount).Shade = _RGB(100 + INT(RND * 155), 100 + INT(RND * 155), 100 + INT(RND * 155))
  158.     SelectedShape = ShapeCount
  159.  
  160. SUB cPset (x1 AS DOUBLE, y1 AS DOUBLE, col AS _UNSIGNED LONG)
  161.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
  162.  
  163. SUB cLine (x1 AS DOUBLE, y1 AS DOUBLE, x2 AS DOUBLE, y2 AS DOUBLE, col AS _UNSIGNED LONG)
  164.     LINE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2)-(_WIDTH / 2 + x2 - 0, -y2 + _HEIGHT / 2 + 0), col
  165.  
  166. SUB cPrintstring (y, a AS STRING)
  167.     _PRINTSTRING (_WIDTH / 2 - (LEN(a) * 8) / 2, -y + _HEIGHT / 2), a
  168.  
  169. SUB lineSmooth (x0, y0, x1, y1, c AS _UNSIGNED LONG)
  170.     'Credit: FellippeHeitor qb64.org (2020)
  171.     '        Adapted from https://en.wikipedia.org/w/index.php?title=Xiaolin_Wu%27s_line_algorithm&oldid=852445548
  172.     'Edit:   Correction to alpha channel (2020-11-20)
  173.  
  174.     DIM plX AS INTEGER, plY AS INTEGER, plI
  175.  
  176.     DIM steep AS _BYTE
  177.     steep = ABS(y1 - y0) > ABS(x1 - x0)
  178.  
  179.     IF steep THEN
  180.         SWAP x0, y0
  181.         SWAP x1, y1
  182.     END IF
  183.  
  184.     IF x0 > x1 THEN
  185.         SWAP x0, x1
  186.         SWAP y0, y1
  187.     END IF
  188.  
  189.     DIM dx, dy, gradient
  190.     dx = x1 - x0
  191.     dy = y1 - y0
  192.     gradient = dy / dx
  193.  
  194.     IF dx = 0 THEN
  195.         gradient = 1
  196.     END IF
  197.  
  198.     'handle first endpoint
  199.     DIM xend, yend, xgap, xpxl1, ypxl1
  200.     xend = _ROUND(x0)
  201.     yend = y0 + gradient * (xend - x0)
  202.     xgap = (1 - ((x0 + .5) - INT(x0 + .5)))
  203.     xpxl1 = xend 'this will be used in the main loop
  204.     ypxl1 = INT(yend)
  205.     IF steep THEN
  206.         plX = ypxl1
  207.         plY = xpxl1
  208.         plI = (1 - (yend - INT(yend))) * xgap
  209.         GOSUB plot
  210.  
  211.         plX = ypxl1 + 1
  212.         plY = xpxl1
  213.         plI = (yend - INT(yend)) * xgap
  214.         GOSUB plot
  215.     ELSE
  216.         plX = xpxl1
  217.         plY = ypxl1
  218.         plI = (1 - (yend - INT(yend))) * xgap
  219.         GOSUB plot
  220.  
  221.         plX = xpxl1
  222.         plY = ypxl1 + 1
  223.         plI = (yend - INT(yend)) * xgap
  224.         GOSUB plot
  225.     END IF
  226.  
  227.     DIM intery
  228.     intery = yend + gradient 'first y-intersection for the main loop
  229.  
  230.     'handle second endpoint
  231.     DIM xpxl2, ypxl2
  232.     xend = _ROUND(x1)
  233.     yend = y1 + gradient * (xend - x1)
  234.     xgap = ((x1 + .5) - INT(x1 + .5))
  235.     xpxl2 = xend 'this will be used in the main loop
  236.     ypxl2 = INT(yend)
  237.     IF steep THEN
  238.         plX = ypxl2
  239.         plY = xpxl2
  240.         plI = (1 - (yend - INT(yend))) * xgap
  241.         GOSUB plot
  242.  
  243.         plX = ypxl2 + 1
  244.         plY = xpxl2
  245.         plI = (yend - INT(yend)) * xgap
  246.         GOSUB plot
  247.     ELSE
  248.         plX = xpxl2
  249.         plY = ypxl2
  250.         plI = (1 - (yend - INT(yend))) * xgap
  251.         GOSUB plot
  252.  
  253.         plX = xpxl2
  254.         plY = ypxl2 + 1
  255.         plI = (yend - INT(yend)) * xgap
  256.         GOSUB plot
  257.     END IF
  258.  
  259.     'main loop
  260.     DIM x
  261.     IF steep THEN
  262.         FOR x = xpxl1 + 1 TO xpxl2 - 1
  263.             plX = INT(intery)
  264.             plY = x
  265.             plI = (1 - (intery - INT(intery)))
  266.             GOSUB plot
  267.  
  268.             plX = INT(intery) + 1
  269.             plY = x
  270.             plI = (intery - INT(intery))
  271.             GOSUB plot
  272.  
  273.             intery = intery + gradient
  274.         NEXT
  275.     ELSE
  276.         FOR x = xpxl1 + 1 TO xpxl2 - 1
  277.             plX = x
  278.             plY = INT(intery)
  279.             plI = (1 - (intery - INT(intery)))
  280.             GOSUB plot
  281.  
  282.             plX = x
  283.             plY = INT(intery) + 1
  284.             plI = (intery - INT(intery))
  285.             GOSUB plot
  286.  
  287.             intery = intery + gradient
  288.         NEXT
  289.     END IF
  290.  
  291.     EXIT SUB
  292.  
  293.     plot:
  294.     ' Change to regular PSET for standard coordinate orientation.
  295.     CALL cPset(plX, plY, _RGB32(_RED32(c), _GREEN32(c), _BLUE32(c), plI * _ALPHA32(c)))
  296.     RETURN
  297.  
You're not done when it works, you're done when it's right.

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #12 on: June 08, 2021, 07:44:29 pm »
Wow, thanks @STxAxTIC ! That’s something I sure will chew on and digest. Thank you.

- Dav

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #13 on: June 08, 2021, 08:04:10 pm »
One thing I'm trying to do is eliminate to gaps in the drawing line when moving the mouse too fast (like in your image above @TempodiBasic) by drawing in the in-between space.  It seems simple at first, save the last known x/y point and fill in between that and the new x/y, but I'm not seeing it clearly yet how to correctly.  It's too blocky when moving real fast, so I need to do a series of blocks on the line.   I'm sure I'm not seeing something probably so obvious to others.  Here's an example...

- Dav

Code: QB64: [Select]
  1.  
  2. SCREEN _NEWIMAGE(600, 600, 32)
  3.  
  4. CLS , _RGB(255, 255, 255)
  5.  
  6. size% = 3: clr& = _RGB(0, 0, 0)
  7.  
  8.  
  9.     mi = _MOUSEINPUT: mx = _MOUSEX: my = _MOUSEY
  10.  
  11.  
  12.         'if drawing still, draw pixels in between
  13.         IF drawing = 1 THEN
  14.             LINE (oldmx, oldmy)-(mx, my), clr&, BF
  15.         END IF
  16.  
  17.         'draw line brush
  18.         LINE (mx - (size% / 2), my - (size% / 2))-(mx + (size% / 2), my + (size% / 2)), clr&, BF
  19.  
  20.         'use circle brush instead of line
  21.         'FOR d = 1 TO size% STEP .2
  22.         '    CIRCLE (mx, my), d, clr&
  23.         'NEXT
  24.  
  25.         drawing = 1: oldmx = mx: oldmy = my
  26.  
  27.     ELSE
  28.  
  29.         drawing = 0
  30.  
  31.     END IF
  32.  
  33.  


I have this for that, hard to test with Wondows constant interrupts for update
Code: QB64: [Select]
  1. _Title "thic2 line mouse demo" 'b+ 2021-06-08
  2. Const xmax = 800
  3. Const ymax = 600
  4. Screen _NewImage(xmax, ymax, 32)
  5. _ScreenMove 360, 60
  6.  
  7.     mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
  8.     If mb Then
  9.         If lastmx And lastmy Then thic2 mx, my, lastmx, lastmy, 15, &HFFFFFF00
  10.         lastmx = mx: lastmy = my
  11.     Else
  12.         lastmx = 0: lastmy = 0
  13.     End If
  14.     _Display
  15.     _Limit 300
  16.  
  17. 'this version needs fcirc and is pretty inefficient but once and a while it comes in handy
  18. Sub thic2 (x1, y1, x2, y2, rThick, K As _Unsigned Long)
  19.     'x1, y1 is one endpoint of line
  20.     'x2, y2 is the other endpoint of the line
  21.     'rThick is the radius of the tiny circles that will be drawn
  22.     '   from one end point to the other to create the thick line
  23.     'Yes, the line will then extend beyond the endpoints with circular ends.
  24.     rThick = Int(rThick / 2): stepx = x2 - x1: stepy = y2 - y1
  25.     length = Int((stepx ^ 2 + stepy ^ 2) ^ .5)
  26.     If length Then
  27.         dx = stepx / length: dy = stepy / length
  28.         For i = 0 To length
  29.             fcirc x1 + dx * i, y1 + dy * i, rThick, K
  30.         Next
  31.     Else
  32.         fcirc x1, y1, rThick, K
  33.     End If
  34.  
  35. Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
  36.     Dim Radius As Integer, RadiusError As Integer
  37.     Dim X As Integer, Y As Integer
  38.  
  39.     Radius = Abs(R)
  40.     RadiusError = -Radius
  41.     X = Radius
  42.     Y = 0
  43.  
  44.     If Radius = 0 Then PSet (CX, CY), C: Exit Sub
  45.  
  46.     ' Draw the middle span here so we don't draw it twice in the main loop,
  47.     ' which would be a problem with blending turned on.
  48.     Line (CX - X, CY)-(CX + X, CY), C, BF
  49.  
  50.     While X > Y
  51.         RadiusError = RadiusError + Y * 2 + 1
  52.         If RadiusError >= 0 Then
  53.             If X <> Y + 1 Then
  54.                 Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  55.                 Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  56.             End If
  57.             X = X - 1
  58.             RadiusError = RadiusError - X * 2
  59.         End If
  60.         Y = Y + 1
  61.         Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  62.         Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  63.     Wend
  64.  
  65.  
thic2 line mouse demo.PNG

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Dav's Doodle Dandy - animated image drawing.
« Reply #14 on: June 08, 2021, 08:22:44 pm »
That looks good. I’ll give it a run when I get back home. Thanks, @bplus.

- Dav