Author Topic: Why does this program break QB64?  (Read 4481 times)

0 Members and 1 Guest are viewing this topic.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Why does this program break QB64?
« on: December 29, 2020, 04:00:46 pm »
I was minding my own business, trying to make a little Paint-like clone... Except when I run this code, nothing really happens - but the QB64 window itself seems to slow way down, like I can't drag things around anymore. Any clues?

Code: QB64: [Select]
  1.  
  2. _TITLE "PlasmaDoodle"
  3.  
  4. ' Hardware
  5. 'SCREEN _NEWIMAGE(1024, 768, 32)
  6.  
  7. Desktop = _SCREENIMAGE
  8. SCREEN _NEWIMAGE(_WIDTH(Desktop), _HEIGHT(Desktop), 32)
  9. _PUTIMAGE (0, 0), Desktop
  10.  
  11. ' Constants
  12. pi = 4 * ATN(1)
  13.  
  14. ' Structures and variables
  15. TYPE ShadeVector
  16.     VelocityRed AS INTEGER
  17.     VelocityGreen AS INTEGER
  18.     VelocityBlue AS INTEGER
  19.  
  20. DIM SHARED MainPhase(_WIDTH, _HEIGHT) AS ShadeVector
  21.  
  22.  
  23.  
  24.  
  25.  
  26. 'FOR i = 1 TO 350
  27. '    p = RND * _WIDTH
  28. '    q = RND * _HEIGHT
  29. '    CIRCLE (p - 50, q - 50), 100, _RGB32(RND * 255, RND * 255, RND * 255, RND * 255)
  30. '    LINE (100, 100)-(300, 300), _RGB32(255, 155, 0, 255), BF
  31. 'NEXT
  32.  
  33.  
  34. FOR i = 1 TO _WIDTH
  35.     FOR j = 1 TO _HEIGHT
  36.         MainPhase(i, j).VelocityRed = 9
  37.         MainPhase(i, j).VelocityGreen = 8
  38.         MainPhase(i, j).VelocityBlue = 7
  39.     NEXT
  40.  
  41. DIM t2
  42. DIM mx
  43. DIM my
  44.  
  45. ' Main loop
  46.         mx = _MOUSEX
  47.         my = _MOUSEY
  48.         IF _MOUSEBUTTON(1) THEN
  49.             GOSUB DrawIt
  50.         END IF
  51.     LOOP
  52.  
  53.     _DISPLAY
  54.     _LIMIT 60
  55.  
  56. ' Graphics
  57. DrawIt:
  58. FOR i = mx - 40 TO mx + 40
  59.     FOR j = my - 40 TO my + 40
  60.         IF ((i > 0) AND (i < _WIDTH) AND (j > 0) AND (j < _HEIGHT)) THEN
  61.             t2 = (i - mx) * (i - mx) + (j - my) * (j - my)
  62.             'IF (t2 < 1600) THEN
  63.             r = _RED32(POINT(i, j))
  64.             g = _GREEN32(POINT(i, j))
  65.             b = _BLUE32(POINT(i, j))
  66.             p = MainPhase(i, j).VelocityRed
  67.             q = MainPhase(i, j).VelocityGreen
  68.             w = MainPhase(i, j).VelocityBlue
  69.             r = r + p
  70.             IF (r > 255) OR (r < 1) THEN MainPhase(i, j).VelocityRed = -p
  71.             g = g + q
  72.             IF (g > 255) OR (g < 1) THEN MainPhase(i, j).VelocityGreen = -q
  73.             b = b + w
  74.             IF (b > 255) OR (b < 1) THEN MainPhase(i, j).VelocityBlue = -w
  75.             PSET (i, j), _RGB32(r, g, b, 255 * (1 - t2 / 1600))
  76.             'END IF
  77.         END IF
  78.     NEXT
  79.  
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Why does this program break QB64?
« Reply #1 on: December 29, 2020, 05:13:24 pm »
Strange radioactive glowing around Windows Toolbar button and red box X I clicked, v weird!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Why does this program break QB64?
« Reply #2 on: December 29, 2020, 05:35:12 pm »
Code: QB64: [Select]
  1. _PUTIMAGE (0, 0), Desktop
  2.  

Oh ha! it's a prank!

 
radoiactive glowing.PNG

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Why does this program break QB64?
« Reply #3 on: December 29, 2020, 05:37:45 pm »
My recommendation would be to change the _MOUSEBUTTON(1) part. Don't let the program keep looping, just because the mouse button is depressed. Drags are accomplished by detecting motion, so add that condition.

In stead of...

 IF _MOUSEBUTTON(1) THEN
        GOSUB DrawIt
 END IF

-----------------

 IF _MOUSEBUTTON(1) THEN
     IF oldmy <> my or oldmx <> mx THEN
            GOSUB DrawIt
     END IF
 END IF

old mx = mx: old my = my

--------------------------------------------------------

That's my 2-cents. I don't do graphics, so I didn't try it out. If you do try it, and it works, just drop a thank you off with 2-million dollars in bitcoin to my dropbox account.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Why does this program break QB64?
« Reply #4 on: December 29, 2020, 05:41:35 pm »
Yeah Pete the 2nd time I tried it I put a delay on if mb to wait until button released before processing and also an immediate end of program with any keypress in processing loop...

but it's a prank ;-))

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Why does this program break QB64?
« Reply #5 on: December 29, 2020, 06:02:03 pm »
It looks like my screen is breaking!
ss.png
* ss.png (Filesize: 1.83 MB, Dimensions: 1920x1080, Views: 236)
You're not done when it works, you're done when it's right.

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Why does this program break QB64?
« Reply #6 on: December 29, 2020, 06:38:43 pm »
Lol. I ran it. Had me fooled for a sec.  Neat effect.

- Dav
« Last Edit: December 29, 2020, 06:48:04 pm by Dav »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Why does this program break QB64?
« Reply #7 on: December 29, 2020, 06:39:03 pm »
Yeah Pete the 2nd time I tried it I put a delay on if mb to wait until button released before processing and also an immediate end of program with any keypress in processing loop...

but it's a prank ;-))

Yeah, mouse handling needs more than just single button detection. I use this, or similar code...

Code: QB64: [Select]
  1.             IF clicked_l% = 0 THEN
  2.                 IF mb.l% THEN
  3.                     clicked_l% = -1
  4.                 ELSE
  5.                     IF clicked_l% = -1 THEN clicked_l% = 1
  6.                 END IF
  7.             ELSE
  8.                 IF mb.l% = 0 THEN
  9.                     IF clicked_l% = -2 THEN clicked_l% = 0 ELSE clicked_l% = 1
  10.                 END IF
  11.             END IF

The -2 setting is for a case where a click in a previous routine activates a process but it needs to stay active until another click takes place. The other values ,-1, 0, and 1 allow for the process to complete only after the left mouse button is released. Notepad uses a similar technique. Click "File" and without a release, the file window will pop up. You can then then move the mouse, either with the button still down or up, and it will highlight the corresponding menu selections. Press the mouse button down on a selection... but wait, that selection will not process until the left mouse button is released.

I consider myself not only a SCREEN Zero Hero, but also the King of Drag, but if Bill puts his mind to it, he could become a close second. Hey, that would make Bill the drag queen around here. Well at least now I know why he supports QB64 as a cross-platform language.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Why does this program break QB64?
« Reply #8 on: December 29, 2020, 07:51:51 pm »
Suddenly I had this feeling that I was in Pepperland.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Why does this program break QB64?
« Reply #9 on: December 30, 2020, 11:00:56 am »
Hi. I really like the solution of the circle using the alpha channel. It's a math nut. The main question, as I understood it, was speed. So I tried to modify and speed up the program. To do this, I needed to clean up my old research on the topic: How the hell does alpha channel work. And I remembered. Here is the result. It's a bit faster, it doesn't use either POINT or PSET, but only MEM and it uses the calculated alpha channel. The way graphic commands do it for us.

Code: QB64: [Select]
  1. 'original author: STxAxTIC
  2. 'Petr's  speed up modification
  3.  
  4. Desktop = _SCREENIMAGE
  5. _TITLE "PlasmaDoodle"
  6.  
  7. SCREEN _NEWIMAGE(_WIDTH(Desktop), _HEIGHT(Desktop), 32)
  8. _PUTIMAGE (0, 0), Desktop
  9.  
  10. ' Constants
  11. pi = 4 * ATN(1)
  12.  
  13. ' Structures and variables
  14. TYPE ShadeVector
  15.     VelocityRed AS INTEGER
  16.     VelocityGreen AS INTEGER
  17.     VelocityBlue AS INTEGER
  18.  
  19. DIM SHARED MainPhase(_WIDTH, _HEIGHT) AS ShadeVector
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26. m = _MEMIMAGE(0)
  27.  
  28.  
  29. 'FOR i = 1 TO 350
  30. '    p = RND * _WIDTH
  31. '    q = RND * _HEIGHT
  32. '    CIRCLE (p - 50, q - 50), 100, _RGB32(RND * 255, RND * 255, RND * 255, RND * 255)
  33. '    LINE (100, 100)-(300, 300), _RGB32(255, 155, 0, 255), BF
  34. 'NEXT
  35.  
  36. '_DISPLAY
  37.  
  38. FOR i = 1 TO _WIDTH
  39.     FOR j = 1 TO _HEIGHT
  40.         MainPhase(i, j).VelocityRed = 1
  41.         MainPhase(i, j).VelocityGreen = 2
  42.         MainPhase(i, j).VelocityBlue = 3
  43.     NEXT
  44.  
  45. DIM t2
  46. DIM mx
  47. DIM my
  48.  
  49. ' Main loop
  50.     mx = _MOUSEX
  51.     my = _MOUSEY
  52.     IF _MOUSEBUTTON(1) THEN GOSUB DrawIt
  53.  
  54.  
  55.     '    _DISPLAY
  56.     _LIMIT 60
  57.  
  58.  
  59.  
  60. ' Graphics
  61. DrawIt:
  62. FOR i = mx - 40 TO mx + 40
  63.     FOR j = my - 40 TO my + 40
  64.         IF ((i > 0) AND (i < _WIDTH) AND (j > 0) AND (j < _HEIGHT)) THEN
  65.             t2 = (i - mx) * (i - mx) + (j - my) * (j - my)
  66.  
  67.             'IF (t2 < 1600) THEN
  68.             '                                                                             POINT is too slow
  69.             _MEMGET m, m.OFFSET + IN(i, j) + 2, r
  70.             _MEMGET m, m.OFFSET + IN(i, j) + 1, g
  71.             _MEMGET m, m.OFFSET + IN(i, j), b
  72.             rOld = r
  73.             gOld = g
  74.             bOld = b
  75.  
  76.             p = MainPhase(i, j).VelocityRed
  77.             q = MainPhase(i, j).VelocityGreen
  78.             w = MainPhase(i, j).VelocityBlue
  79.             r = r + p
  80.             IF (r > 255) OR (r < 1) THEN MainPhase(i, j).VelocityRed = -p
  81.             g = g + q
  82.             IF (g > 255) OR (g < 1) THEN MainPhase(i, j).VelocityGreen = -q
  83.             b = b + w
  84.             IF (b > 255) OR (b < 1) THEN MainPhase(i, j).VelocityBlue = -w
  85.             NC~& = _RGBA32(r, g, b, 255 * (1 - t2 / 1600))
  86.  
  87.             'PSET (i, j), _RGB32(r, g, b, 255 * (1 - t2 / 1600))                          PSET is too slow
  88.  
  89.  
  90.             REDIM alfa AS _UNSIGNED _BYTE, af AS DOUBLE, newerest AS _UNSIGNED LONG
  91.             alfa = 255 * (1 - t2 / 1600)
  92.             af = alfa / 255
  93.  
  94.             'for circle effect  must be R, G, B values recaltulated with alfa first:
  95.             MEMALPHA _RGBA32(rOld, gOld, bOld, 255), NC~&, newerest~&
  96.             _MEMPUT m, m.OFFSET + IN(i, j), newerest~&
  97.         END IF
  98.     NEXT
  99.  
  100. FUNCTION IN& (x, y)
  101.     IN& = 4 * (_WIDTH * y + x)
  102.  
  103. SUB MEMALPHA (oldColor~&, newColor~&, ResultColor~&)
  104.     NewR = _RED32(newColor~&)
  105.     NewG = _GREEN32(newColor~&)
  106.     NewB = _BLUE32(newColor~&)
  107.     NewA = _ALPHA32(newColor~&)
  108.  
  109.     NovaAlfa = NewA / 255 '                 new alpha channel value
  110.  
  111.     oldR = _RED32(oldColor~&)
  112.     oldG = _GREEN32(oldColor~&)
  113.     oldB = _BLUE32(oldColor~&)
  114.  
  115.     NstaraR = oldR * ((255 - NewA) / 255) ' Recalculate old (background) color with alpha channel (255 is always background value minus alpha from new color) -> in MEM use, if is image draw to untransparent background
  116.     NstaraG = oldG * ((255 - NewA) / 255)
  117.     NstaraB = oldB * ((255 - NewA) / 255)
  118.  
  119.     NnovaR = NewR * NovaAlfa 'Recalculate new (foreground) color
  120.     NnovaG = NewG * NovaAlfa
  121.     NnovaB = NewB * NovaAlfa
  122.  
  123.     VysR = NnovaR + NstaraR 'output values, tested using MEM and POINT
  124.     VysG = NnovaG + NstaraG
  125.     VysB = NnovaB + NstaraB
  126.  
  127.     ResultColor~& = _RGB32(VysR, VysG, VysB)
  128.  

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Why does this program break QB64?
« Reply #10 on: December 30, 2020, 11:04:25 am »
Thanks Petr for having a look at this!

Did you see the new code in the "PlasmaDoodle" thread? It's basically the same - your edits are not in vain!
You're not done when it works, you're done when it's right.