QB64.org Forum

Active Forums => Programs => Topic started by: dbox on February 18, 2022, 09:58:59 am

Title: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 09:58:59 am
Update 30-Mar-2022
New beta release v0.3.0
https://qb64forum.alephc.xyz/index.php?topic=4670.msg141653#msg141653 (https://qb64forum.alephc.xyz/index.php?topic=4670.msg141653#msg141653)



Hi All,

I've decided to spin off QBJS into it's own project.  This started as a feature of the GX game engine https://qb64forum.alephc.xyz/index.php?topic=4481.0 (https://qb64forum.alephc.xyz/index.php?topic=4481.0) that allows you to publish games built in QB64 for the web.  Based on the interest in this feature I've created a new stand-alone project: QBJS.

 


The goal here is to recreate the feel and accessibility of programming in QBasic/QB64 in the browser.  You can try it out here:

https://boxgm.itch.io/qbjs (https://boxgm.itch.io/qbjs)

This is still a work-in-progress, but it is pretty functional at this point so I thought I would share with a wider audience to get some additional feedback.  I've tried to document what is currently supported here:
https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support (https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support)
https://github.com/boxgaming/qbjs/wiki/Supported-Keywords (https://github.com/boxgaming/qbjs/wiki/Supported-Keywords)

Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 10:33:13 am
Wow that's interesting!
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 11:47:23 am
Hey @bplus, if you get a cool example working there use the share link and post it back here and we can add it to the samples list.

Here's an example that should look familiar:
Quick Falling Letters Game (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=BfIqNLo2MoBBAIgii6tLG1uMjMLY2NLczyMmMro6Mrk54GjsLayjoBP4DEgCsuQDKwDCu8AW5eOAGJpgBQqoSI0tp8FBczwyS3OjKzsrldBbHjgBQdgGugCkPbuyKpujk0tzPOGbGV0dGVyc9Vna6tRXNjcmVlbkEz0CNjS3Mrn2gHAaOYVhY3Jvc3O0N+IVTaW5nbGXlDaGl0c6gCyzIbGV0dGVyUG9z83gDTvbDo7C2sqe7MrkGZ0BLyAJGmXBRG96qQJDbHOP+rtgHu1x4uHTHZ2VuZXJhdGXcCbmV3yRWxldHRlctYFhdO+GysLG0bAjk3urcyX/5QUlmcOwB85jANM4NUaGVu5u558LDaEjN7k+Wl0uatAKo3pMgam6MrgzmmRxGN5Y2xlaWAJhbmR/kODe5tLo0t7c5rQbI3u7dIBRnyqVsqpdDB7gA2qaFa06pM764gJoacyvDpAcfa8btsJDaHLAh9BJLc6S/AlJuZGOAVLewBt82cIBz6AG8ErLEc3RhcnR5AML2Px4OFdWdP/f+v2noLN2lr6PlfD5EcGxhY2XweT1ct4RJbktleaLJwCMbQysbWrQmtleW4M4OTK5ubK5pcJmb3JpCNrC6MbQuQXRvbAzG6uTkytzoogJsRXaGlsZXDvcsqW0as4RjYXRjaEmC6uDQDd2l0aE6EwtjYwiWtleXByZXNzZXOADmPmYwXagAZoTCyMjTrcRzY29yZfgGKLFCv8AtQIt3C8AADcrMNuZXh0Xg7WyvLg5Mrm5/CBDV2VuZPhuEKKzaO3t0G5tDe7vKIxN7C5MiiDd2hhdPeeA5qwNsZWZ0fEFvZlXgCWFTG9jYXRlU/THGuHTAOk0IoOTS3OiyO8O6Ad+DDfCet+6opADO2UtSWZLhpDS6OenBOiKXvLo/CxTQiY0trS6Jf5oaY3t7gjBFVudGlsWP6JvQ1OJ6dTjmvCJDT3ZlcovP/LiKbYysrhC)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 12:45:58 pm
Hey yeah! I will set up a folder and check out list of Keywords you have working...

I sure like doing Quick demos. I just finished a trans of Animal to JB, using a file to save learning questions and answers.

How would Loading and Saving files work with this system? Normal? TBA?
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 12:58:29 pm
Oh, just tried Falling Letters and wondered why it wasn't working, seems part of the right side was missing from my view of screen. What are the output screen dimensions?

PS I see we don't do files yet.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 01:09:06 pm
The editor defaults to 600px wide.  You can change the view to view just the output panel or just the code editor with the small left and right buttons in the area between the panels.

The output screen dimensions are based on the screen command. If this is omitted then it defaults to screen 0 size (640x400).

Perhaps for a future update I will make this default to a certain percentage of the screen rather than a fixed size.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 01:22:14 pm
PS I see we don't do files yet.

File I/O is definitely still a work-in-progress.  I do plan to support the OPEN/INPUT mechanism for reading external file content.  Writing files in the web context is more complex due to web security rules.  Just in general accessing the local machine is a no-no, but there are options to explore for utilizing local browser storage or cloud-hosted storage.

There is currently a QBJS-specific keyword for reading file content from a provided URL.  This is still a bit experimental so I haven't added it to the documentation.  Here is an example of reading content directly from an online location (this one specifically reads from the qbjs github):
Code: QB64: [Select]
  1. Screen _NewImage(800, 600, 32)
  2.  
  3. Dim res as FetchResponse
  4. res = Fetch("https://raw.githubusercontent.com/boxgaming/gx/main/LICENSE")
  5. Print "OK: "; res.ok
  6. Print "Status: "; res.status
  7. Print "Status Text: "; res.statusText
  8. Print "Response Text"
  9. Print "-------------------------------------"
  10. Print res.text
  11.  
Title: Re: QBJS - QBasic for the Web
Post by: Dav on February 18, 2022, 01:34:27 pm
This is cool! Looks like you’ve done a great job.  I’m going to play with it some more later today.

- Dav
Title: Re: QBJS - QBasic for the Web
Post by: _vince on February 18, 2022, 01:58:13 pm
PS I see we don't do files yet.

Do you mean an Open/Save dialog for your programs saved on your local hard drive or OPEN "file.txt" FOR BINARY etc?  For the former, I just use notepad plus copy/paste as quick and easy intermediate. 

Ultimately, you can probably do something with the QB64 IDE or any other editor and have a script generate a base64 URL, open a browser and instant run when you press F5.  But yeah, it can't lock you into a comfortable playpen like JB but then again there's a whole universe waiting outside!
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 02:30:50 pm
This is cool! Looks like you’ve done a great job.  I’m going to play with it some more later today.

- Dav

Thanks @Dav, I'd be curious in any feedback you have.
Title: Re: QBJS - QBasic for the Web
Post by: MasterGy on February 18, 2022, 03:21:02 pm
the idea is very big! It gives a huge space to any QB program. An idea, an implementation, would be easier to reach people who didn’t even know what “QB” was. I wish you much success on your journey!
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 04:57:17 pm
Do you mean an Open/Save dialog for your programs saved on your local hard drive or OPEN "file.txt" FOR BINARY etc?  For the former, I just use notepad plus copy/paste as quick and easy intermediate. 

Ultimately, you can probably do something with the QB64 IDE or any other editor and have a script generate a base64 URL, open a browser and instant run when you press F5.  But yeah, it can't lock you into a comfortable playpen like JB but then again there's a whole universe waiting outside!

Hi @_vince  I meant using a file for adding data and saving. I am still fresh from Animal Guessing translation to JB and very impressed how this old code holds up so well over time like Eliza. Seems pretty smart for about 100 LOC.
Title: Re: QBJS - QBasic for the Web
Post by: johnno56 on February 18, 2022, 05:57:01 pm
I think this is pretty cool... QB via a web page... Impressive.

dbox. I think what you have done so far is brilliant! Looking forward to future updates!

Potential 'can of worms' scenario... Adding save'load would be a nice idea... but for people like myself. who are inherently lazy, would use QB.JS because I would not have to install QB... If the goal is to 'replace' QB4.5 then adding file function would be ideal. But, having QB64 functions within QB.JS, in my opinion, may convince some not to install QB64...  Am I over analysing this?

J
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 06:59:46 pm
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=FEbwBQBBUK5srG5MrpQD2BJLc6MAoQSk3MigFSAGPgGHPAFLACt3wdkPMRJbnB1dLQCJwiO6srm51gtrzYK3OraxMrlQVYLo3zEVndQDtIRndWVzc4D3wUlmvb6d4NUaGVurhorw0ulgf7e7aAPL61sCKDk0tzpGiC2N4y/2aKgB9XrVNJ4LQ0uLwQ0xvb3CYIqtzo0tlFeIvOvdhLLe6xAmdvdLUFpdHwBCBe2guJquVOw=

Share link?

Here is code for simple "Hello World!" Game I try on new things.
Code: QB64: [Select]
  1.     secret = Int(Rnd * 100) + 1
  2.     Do
  3.         Input "Guess my number (1 to 100) "; guess
  4.         If guess = 0 Then Exit Do
  5.         If guess < secret Then Print "lo"
  6.         If guess > secret Then Print "hi"
  7.     Loop Until guess = secret
  8.     Print "You got it!"
  9.     Print
  10. Loop Until guess = 0
  11.  
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 07:15:31 pm
Hmm.... no Sub or Function, no GoTo nor GoSub? They are not in Supported Keywords but I see Sub and Function in samples. Also Shared but in Vector Field Code like Sub and Function.

Is DIM required of everything? No, I didn't in above code.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 07:27:44 pm
Hey @bplus nice example!  Yes, Subs and Functions are supported and at present all variables must be declared. 

Goto and gosub are not supported at present. There will be some complexity to do that as there is not a parallel in javascript.
Title: Re: QBJS - QBasic for the Web
Post by: George McGinn on February 18, 2022, 07:37:38 pm
If you support SUBS, all a GOSUB is is a SUB with a label. I would think you should be able to process a GOSUB the same way as a SUB.


Hey @bplus nice example!  Yes, Subs and Functions are supported and at present all variables must be declared. 

Goto and gosub are not supported at present. There will be some complexity to do that as there is not a parallel in javascript.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 08:19:23 pm
@dbox
I am trying a game of Hangman and I can't seem to get to first base with this code:

Code: QB64: [Select]
  1. Dim Shared As String w(1 To 7) ' word list
  2. LoadWords
  3. For i = 1 To 7
  4.     Print w(i)
  5.  
  6. Sub LoadWords
  7.     w(1) = "HANGMAN"
  8.     w(2) = "GALLOWS"
  9.     w(3) = "REVEAL"
  10.     w(4) = "KEYPRESS"
  11.     w(5) = "REPORT"
  12.     w(6) = "LETTERS"
  13.     w(7) = "BASIC"
  14.     'w(8) = ""
  15.     'w(9) = ""
  16.     'w(10) = ""
  17.     'w(11) = ""
  18.     'w(12) = ""
  19.     'w(13) = ""
  20.     'w(14) = ""
  21.     'w(15) = ""
  22.     'w(16) = ""
  23.     'w(17) = ""
  24.     'w(18) = ""
  25.     'w(19) = ""
  26.     'w(20) = ""
  27.     'w(21) = ""
  28.     'w(22) = ""
  29.     'w(23) = ""
  30.     'w(24) = ""
  31.     'w(25) = ""
  32.     'w(26) = ""
  33.     'w(27) = ""
  34.     'w(28) = ""
  35.     'w(29) = ""
  36.     'w(30) = ""
  37.     'w(31) = ""
  38.     'w(32) = ""
  39.     'w(33) = ""
  40.     'w(34) = ""
  41.     'w(35) = ""
  42.     'w(36) = ""
  43.     'w(37) = ""
  44.     'w(38) = ""
  45.     'w(39) = ""
  46.     'w(40) = ""
  47.     'w(41) = ""
  48.  
  49.  

Originally I had Data and Read to read into w$() but those aren't supported so am trying a simple array def in a sub.

What am I doing wrong?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 08:26:40 pm
I’m not yet supporting the (x to y) syntax when dim-ing arrays.  Try this instead:
Code: QB64: [Select]
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 08:28:50 pm
Ah good! Thanks!

Oh while I'm here, will REDIM work from w(7) to say REDIM as string w(25) in the Sub probably.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 08:32:43 pm
Yes, ReDim is supported as well as ReDim _Preserve.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 09:22:10 pm
@dbox

OK I have some code running but as soon as I uncomment this function, it all dies!
Code: QB64: [Select]
  1. 'Function Reveal$ ' from remaining selected letters a * will cover unchosen letters in w$(round)
  2. '    Dim as integer i
  3. '    dim b$
  4. '    For i = 1 To Len(w$(round))
  5. '        If InStr(selectLetters$, Mid$(w$(round), i, 1)) > 0 Then b$ = b$ + "*" Else b$ = b$ + Mid$(w$(round), i, 1)
  6. '    Next
  7. '    Reveal$ = b$
  8. 'End Function
  9.  


selectLetters$ is shared (and tracks letters guessed by replacing with a -) and so is w$ and round

I am not even calling the function yet.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 09:38:29 pm
@dbox

More info, shouldn't Mid$( ) be color coded same as InStr?
 


PS I started to break down the loaded call to InStr with c$= Mid$(...
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 09:39:41 pm
Try putting the if/then/else on separate  lines.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 09:42:13 pm
Yep! that fixed it, I'll remember for other places I do that.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 09:51:49 pm
@dbox

More info, shouldn't Mid$( ) be color coded same as InStr?
 



Yes, the syntax highlighting still needs a bit of refinement.  I started from a vbscript implementation that already existed for the codemirror editor.
Title: Re: QBJS - QBasic for the Web
Post by: Pete on February 18, 2022, 10:31:12 pm
I like the part of the console that shows the JavaScript conversion. It would be fun to make a small qb app, and then use the JS code on a server. I have made a few dozen JS snippets for various websites, but I do so at such an infrequent rate, I find myself constantly in need of refreshing my language skills. That's very time consuming. It would be much more intuitive to program in QB and convert. Thanks for this. It's a very neat project on a couple of levels!

Pete
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 18, 2022, 10:44:47 pm
@dbox
 I almost have this guy roughed out but _delay is not working

Code: QB64: [Select]
  1. _Title "Hangman" 'for QB64 B+ (redo Hang it) restarted 2019-06-14 for strip down version
  2. Const hung = "Hanged!" ' allows 7 misses
  3. ReDim Shared w$(7) ' word list
  4. Dim Shared As Integer round, nHung, done
  5. Dim Shared selectLetters$
  6. Dim As Integer place
  7. Dim k$
  8. LoadWords
  9. For i = 0 To 7
  10.     cp i + 1, w$(i)
  11. Do ' main loop manages the letters to select from and removes letter when selected
  12.     selectLetters$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  13.     nHung = 0
  14.     done = 0
  15.     Cls
  16.     Update
  17.     While done = 0
  18.         k$ = ""
  19.         While Len(k$) = 0
  20.             k$ = UCase$(InKey$)
  21.             _Limit 60
  22.         Wend
  23.         place = InStr(selectLetters$, k$)
  24.         If place Then
  25.             selectLetters$ = Mid$(selectLetters$, 1, place - 1) + "-" + Mid$(selectLetters$, place + 1)
  26.         End If
  27.         If InStr(w$(round), k$) = 0 Then
  28.             nHung = nHung + 1
  29.         End If
  30.         Update
  31.         _Limit 30
  32.     Wend
  33. Loop Until round > 7
  34.  
  35. Function Reveal$ ' from remaining selected letters a * will cover unchosen letters in w$(round)
  36.     Dim i, b$
  37.     b$ = ""
  38.     For i = 1 To Len(w$(round))
  39.         If InStr(selectLetters$, Mid$(w$(round), i, 1)) > 0 Then
  40.             b$ = b$ + "*"
  41.         Else
  42.             b$ = b$ + Mid$(w$(round), i, 1)
  43.         End If
  44.     Next
  45.     Reveal$ = b$
  46.  
  47. Sub Update 'draw everything for screen 0 and while we're at it decide if word round is done
  48.     cp 8, "Hangman: " + Reveal$
  49.     cp 10, "Press a letter from: " + selectLetters$
  50.     cp 12, "Gallows Report: " + Mid$(hung, 1, nHung)
  51.     If Reveal$ = w$(round) Then
  52.         cp 14, "Congratulations! you got it."
  53.         done = -1
  54.     End If
  55.     If Len(hung) = nHung Then
  56.         cp 14, "Yikes! You were hung by: " + w$(round)
  57.         done = -1
  58.     End If
  59.     If done = -1 Then
  60.         If round + 1 > 7 Then
  61.             cp 16, "Hangman is out of words to play. Goodbye in 5"
  62.             _Delay 5
  63.             End
  64.         End If
  65.     End If
  66.     If done = -1 Then
  67.         If round + 1 <= 7 Then
  68.             round = round + 1
  69.             cp 16, "Next Round in 5 secs"
  70.             _Delay 5
  71.             'sleep2 ' sleeps suck!!!
  72.             '_KeyClear ' >>>>>>>>>>>> unsupported
  73.         End If
  74.     End If
  75.  
  76. Sub cp (row, s$)
  77.     Locate row, (80 - Len(s$)) / 2: Print s$
  78.  
  79. Sub LoadWords
  80.     w$(0) = "BPLUS GAMES"
  81.     w$(1) = "HANGMAN"
  82.     w$(2) = "GALLOWS"
  83.     w$(3) = "REVEAL"
  84.     w$(4) = "KEYPRESS"
  85.     w$(5) = "REPORT"
  86.     w$(6) = "LETTERS"
  87.     w$(7) = "BASIC"
  88.     'w$(8) = ""
  89.     'w$(9) = ""
  90.     'w$(10) = ""
  91.     'w$(11) = ""
  92.     'w$(12) = ""
  93.     'w$(13) = ""
  94.     'w$(14) = ""
  95.     'w$(15) = ""
  96.     'w$(16) = ""
  97.     'w$(17) = ""
  98.     'w$(18) = ""
  99.     'w$(19) = ""
  100.     'w$(20) = ""
  101.     'w$(21) = ""
  102.     'w$(22) = ""
  103.     'w$(23) = ""
  104.     'w$(24) = ""
  105.     'w$(25) = ""
  106.     'w$(26) = ""
  107.     'w$(27) = ""
  108.     'w$(28) = ""
  109.     'w$(29) = ""
  110.     'w$(30) = ""
  111.     'w$(31) = ""
  112.     'w$(32) = ""
  113.     'w$(33) = ""
  114.     'w$(34) = ""
  115.     'w$(35) = ""
  116.     'w$(36) = ""
  117.     'w$(37) = ""
  118.     'w$(38) = ""
  119.     'w$(39) = ""
  120.     'w$(40) = ""
  121.     'w$(41) = ""
  122.  
  123.  

Sleep is messing with Keypresses need a _KeyClear

I tried my own version of sleep and that worked perfect in QB64 keeping inkey$ clear for next letter but QBJS ignored code. So I am just trying _delay to give user time to read what happened before next round starts.

Sharing
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=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
Title: Re: QBJS - QBasic for the Web
Post by: Dav on February 18, 2022, 10:57:50 pm
It's a very neat project on a couple of levels!

I totally agree.  And Pete -- welcome back!  You were missed.

- Dav
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 11:24:52 pm
I like the part of the console that shows the JavaScript conversion. It would be fun to make a small qb app, and then use the JS code on a server. I have made a few dozen JS snippets for various websites, but I do so at such an infrequent rate, I find myself constantly in need of refreshing my language skills. That's very time consuming. It would be much more intuitive to program in QB and convert. Thanks for this. It's a very neat project on a couple of levels!

Pete

Thanks @Pete!  If you are interested in using just the converter you can check it out here: https://github.com/boxgaming/gx/blob/main/tools/qb2js.bas (https://github.com/boxgaming/gx/blob/main/tools/qb2js.bas).  It's actually written in QB64 and can be run from the command line.  In fact, it actually converts itself to javascript to be included in the web version:

Code: [Select]
qb2js.exe qb2js.bas > qb2js.js
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 18, 2022, 11:40:46 pm
@dbox
 I almost have this guy roughed out but _delay is not working

Sleep is messing with Keypresses need a _KeyClear

I tried my own version of sleep and that worked perfect in QB64 keeping inkey$ clear for next letter but QBJS ignored code. So I am just trying _delay to give user time to read what happened before next round starts.


Hey @bplus, looking good so far.  _KeyClear should be easy to add.  I'll put that on the top of the list.  Thanks for the good feedback! I'll also look into what's happening with _Delay in your example.
Title: Re: QBJS - QBasic for the Web
Post by: DANILIN on February 19, 2022, 01:42:03 am
https://boxgm.itch.io/qbjs

does work... goto & labels ?
does work... circle ? 

Circle (100,150),25,5
QB.sub_Circle(false, 100, 150, 25, 5);

so far: has been calculated in this shell only ... factorial
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 07:21:17 am
@DANILIN

Goto and labels are not currently supported.

Circle is supported but I have not mapped the color table for the legacy screen modes.  I do plan to, but at the moment colors need to be defined with the _RGB or _RGB32 function:

Code: QB64: [Select]
  1. Circle (100,150), 25, _RGB(100,255,50)
  2.  
Title: Re: QBJS - QBasic for the Web
Post by: DANILIN on February 19, 2022, 08:37:06 am
theoretically it works and there will still be uncovered functions

Code: [Select]
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=BOAQAHvAN8AKgkRJTdAZAAoXAKeoqmhqSKipyQDEAGU8JGT1J4BrvX7QVRPmANV/mKmJ6GgqiLuQBZhedrgNLi5u74BUByQkEkpypd+EpJyI3AKngBzqAYOgCt17aAOnpc0Mr2uQC1+rKy2AJCIaemJ6ldgL5ASkjoWv85k1Dw9iQxYBOIoKSSnKiqwahpyKsKhmRj386O3dc5evgfr8ARWQlNVTat3cAdo7R4sO6CrTu2sA3zLCr3M8MABel2HGdsigqCT3N2gCUCkoyfp9fIB9d+o/eeqAaokIqct+vmkcP8XlAhAF16wFBAdEABqbZcVdbdgamqIqg7PyAaSAf02mT63kAD6u2cYSanojLrLaBnlFQ0lSQ0xFevQDPXcbjl77g6eKWR+y6nvunuY7+59bZr2j71+/1r2s8+o51fcs7iIepdVa/OF86kziuad/vll7bv9/cAAxgkVORGFwADqfyx7vySbA5ev3nc6Rgz7Ss1qgbQXP1u95alLv23f866+47/n2+h/HjfEZt+4rdxsziXF++5akvvuWtR77557OuvYfez3YAHdXfsA72wCjqiIiKmIKy1d1xIBtsMXYUcSrvT4=
 


This is Danilin Russian Circle Diagram
https://qb64forum.alephc.xyz/index.php?topic=4367.msg138214#msg138214
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 08:46:00 am
Nice @DANILIN, cool example!
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 19, 2022, 11:56:17 am
+1 I am still trying to get a graphics working, so far getting 0 drawn from small apps.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 12:44:06 pm
@bplus can you share the code that is not working?
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 19, 2022, 12:55:49 pm
Sure here is last simple one that I've cut and cut, turns out I use one liner IF's allot and also :'s that are so common I don't see them.  Connett Circles:
Code: QB64: [Select]
  1. Const xmax = 600
  2. Const ymax = 600
  3.  
  4. Dim As Integer i, j, s, sq
  5. Dim As Double x, y, c, d
  6.  
  7. Screen _NewImage(xmax, ymax, 32)
  8.  
  9. s = 1
  10. sq = 5
  11.     For j = 0 To ymax / sq
  12.         For i = 0 To xmax / sq
  13.             x = i * s / 600
  14.             y = j * s / 600
  15.             c = x * x + y * y
  16.             d = c / 2
  17.             d = d - Int(d)
  18.             d = Int(d * 1000)
  19.             If d < 250 Then
  20.                 cc = _RGB32(d, 0, 0)
  21.             ElseIf d < 500 Then
  22.                 cc = _RGB32(0, d - 250, 0)
  23.             ElseIf d < 750 Then
  24.                 cc = _RGB32(0, 0, d - 500)
  25.             Else
  26.                 cc = _RGB32(255, 255, 255)
  27.             End If
  28.             Line (i * sq, j * sq)-Step(sq, sq), cc, BF
  29.         Next
  30.     Next
  31.     _Delay 2
  32.     'Color _RGB32(255, 255, 255)
  33.     'Locate 1, 1
  34.     'Print s
  35.     s = s + 15
  36.     If s > 1000 Then  ' it was this on one line!
  37.         s = 1
  38.     End If
  39.  
  40.  
  41.  

Finally! Share:
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=RDb25zdAEAbw2sLxwD1gG0AYd0An6E3N7ogzu3uTW0tzP4BDyUAFDgN5bWF42wKqdBIjS26AoLn3GSW50ZWdlcsgGmoBZgA1T9wHO3EFzcYu7ugqI3urE2MusB4XcA8tpAYzqAZJjwxgL6B1Vuc2lnbmVk7Q0xvbmfMCxsdVOKpsbkysrdnkHTmV3SW1hZ2W4AoIrWrCAZzAGT4BTumWtwAYo+bZAGqeBRG9X54SM3uXE4cNwFUb+vaAL99f//6rjC7zWPKz0ACEw7vIBUjc0d8aABjMPbaqVCfkYAB8NNyykbQCtsRocAHXrpidO1//IXX0iAWxgSS3OhGOML/+xdFopuVGGMYJX/8WCks0MEAeRow+BDVGhlbk//8xsincJSR0IaWsQhuLcvT/99FRWxzZUlmlv+AcN9p//79ZVtt8evBNLfMNQJotz//bWW2W0A3XjaT//89XatB0kITRPLZb8Sfl/+IhorY5spf/+xrvQzBQJQFBFxNtFxt0A//1YJFbmSyz//Kw0xpbmWg8XNGmEubQp5a4am6Mrgg6ZGOZbsjwKEjF/uENOZXh0LxxL3o4IiMrYwvNsvJgkIht7Y3uUUkvbVebdZCADIRHPPxkYFTG9jYXRlqLKifr69EUHJpbnSZTzcVdGkCc/Fre+gD6ic51jP/fy2B+P6uj4DTG9vcERg==

BTW _delay might be working for this.

 




Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 01:00:33 pm
Nice @bplus!  Looks great.  I’ll add this and @DANILIN’s to the sample apps later!
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 01:04:57 pm
Also, I’ll add single line if/then/else support to the todo list.

And yes it looks like the issue is when _Delay is called from a Sub instead of from the main program.  I’ll fix that too.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 19, 2022, 01:28:37 pm
Here finally got this working, without _Display in QB64 this blinks to great annoyance! but in QB64 it's just a little slow but not as slow as other Basic's I've run it in so JS is fast Interpreter.

share:
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=VPcHRpb24BAAvx0V4cGxpY2l0ABTiKjS6NjKIBFx1BhcnRpY2xlMOjN7q3OjC0t25RENvbnN0EC3KB4B7cAZ6AYYujgao8uDKwO4MLk6NLG2MpXxAeMAUFz7iqbS3M7Yyn/sA8rVcCoLI8KJ+EgWR5Q74cgOSHfDgBjahmOqtzm0s7cysjYNMb25nlYSK3MjhNAkRpbWQqm0MLkysj+A4YAFGq8ApU2S0VTY3JlZW5/9HTmV3SW1hZ2W3QAbc5EAWIfeyrBKAZU+xvMb6A0/20FscO2BIze5Nl0ocwVRvRaHAJuZXdy3GGnMrw6bmBRG+BbCQ2xzgZAUlmc7GAeL3+GqNDK3QAxOKxeAK1UAx/+BtL+BwqlT7PXQA4NNda0AXZipRi6loMtapVD4B1nhNyvnCPWGkWekst4bYzXAGn9/s55s8/v93ksr22K+ZdAKCdsVlyRLD8BT3JS2az6JMA+Rcgiu0sjo0PfgAH4bwA9V7ADgpXNZ3HHRcYqQytLO0Oj/hILcyJW3WXVqKuLAAJ39aX5olgC2cKAbygBq+YBUlf2KxUABPPsX1rkU9TlNaAIT5QBNCobS5MbYytW57WvkFfnt657gs99zU5xs99zc6sKRYQSgiY0trS6MKEL/waY3t7hd4cJTdWJWt+3YX57evS1DP0AAXp6qPsEpNzIlL+xTDYpYZ77mtzBVEq7+L8pWwx33M/1W/DRfrVZyKDG/b12XvqxOgxz29RLNdPt/aDG/b1EOln8CUkdCtrrlyUkl3L7L3xr7XOayjtCKxhxvStXhRYnP/qfZzszX

Particle Fountain:
Code: QB64: [Select]
  1. _Title "Particle Fountain"
  2. Const nP = 30000
  3. Type particle
  4.     x As Single
  5.     y As Single
  6.     dx As Single
  7.     dy As Single
  8.     r As Single
  9.     c As _Unsigned Long
  10. Dim Shared p(nP) As particle
  11. Screen _NewImage(600, 600, 32)
  12. Dim As Long i, lp
  13. For i = 0 To nP
  14.     new i
  15.     Cls
  16.     If lp < nP Then
  17.         lp = lp + 100
  18.     End If
  19.     For i = 0 To lp
  20.         p(i).dy = p(i).dy + .1
  21.         p(i).x = p(i).x + p(i).dx
  22.         p(i).y = p(i).y + p(i).dy
  23.         If p(i).x < 0 Or p(i).x > _Width Then
  24.             new i
  25.         End If
  26.         If p(i).y > _Height And p(i).dy > 0 Then
  27.             p(i).dy = -.75 * p(i).dy
  28.             p(i).y = _Height - 5
  29.         End If
  30.         Circle (p(i).x, p(i).y), p(i).r, p(i).c
  31.     Next
  32.     _Limit 30
  33.  
  34. Sub new (i)
  35.     p(i).x = _Width / 2 + Rnd * 20 - 10
  36.     p(i).y = _Height + Rnd * 5
  37.     p(i).dx = Rnd * 1 - .5
  38.     p(i).dy = -10
  39.     p(i).r = Rnd * 3
  40.     p(i).c = _RGB32(100 * Rnd + 155, 100 * Rnd + 155, 200 + Rnd * 55)
  41.  
  42.  
  43.  

Oh hey! It worked with Option _Explicit, I forgot I had that at top, great!

A screen shot that took awhile to setup, so I had lunch while it ran:
 
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 01:51:51 pm
That’s a lot of circles!  Very cool.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 19, 2022, 02:53:04 pm
@dbox _Keydown and _Keyhit have notesthat say see GXKeyDown but links to HomePage with no further info.
I assume these are constants, are they similar to QB64's?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 03:34:09 pm
Hey @bplus, looks like when I moved that page from the GX project I broke the link to that page.   I ported most of the GX game engine code to JS first, so the input handling is a bit more fleshed out there.  I plan to fully implement _KeyDown and _KeyHit but I thought I would reference the GX-specific methods since they were already available.

I fixed the links in the supported keywords page.  Here is what it is pointing to now:
https://github.com/boxgaming/gx/wiki/GXKeyDown (https://github.com/boxgaming/gx/wiki/GXKeyDown)

Also, links to your examples are up on the qbjs main page.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 19, 2022, 04:49:25 pm
Hi @dbox

Here's one I can't figure out what's not working with keys. I found I had to get rid of $ for string variables and DIM as String just to get board to show.
Code: QB64: [Select]
  1. _Title "15 Squares Puzzle" 'b+ mod for QBJS 2022-02-19
  2. Dim Shared As Integer board(4, 4)
  3. Dim Shared As Integer r0, c0, d
  4. Dim As Integer r, c, i, solved
  5. For r = 1 To 4
  6.     For c = 1 To 4
  7.         board(c, r) = c + (r - 1) * 4
  8.     Next
  9. board(4, 4) = 0
  10. c0 = 4
  11. r0 = 4
  12. For i = 0 To 50 * 4 * 4
  13.     d = Val(Mid$("0358", Int(Rnd * 4) + 1, 1))
  14.     handle
  15.     Locate 1, 1
  16.     b = ""
  17.     solved = 1
  18.     For r = 1 To 4
  19.         For c = 1 To 4
  20.             If board(c, r) Then
  21.                 If board(c, r) <> c + (r - 1) * 4 Then
  22.                     solved = 0
  23.                 End If
  24.                 b = b + Right$("   " + Str$(board(c, r)), 3) + " "
  25.             Else
  26.                 b = b + "    "
  27.             End If
  28.         Next
  29.         Print b
  30.         b = ""
  31.     Next
  32.     Print
  33.     If solved Then
  34.         Locate 4 + 2, 2
  35.         Print "Solved!"
  36.         _Delay 5
  37.         'End
  38.     End If
  39.     k = InKey$
  40.     If Len(k) = 2 Then
  41.         d = (Asc(Right$(k, 1)) - 72)
  42.         handle
  43.     End If
  44.     _Limit 30
  45.  
  46. Sub handle
  47.     Select Case d
  48.         Case 3
  49.             If c0 < 4 Then
  50.                 board(c0, r0) = board(c0 + 1, r0)
  51.                 board(c0 + 1, r0) = 0
  52.                 c0 = c0 + 1
  53.             End If
  54.         Case 5
  55.             If c0 > 1 Then
  56.                 board(c0, r0) = board(c0 - 1, r0)
  57.                 board(c0 - 1, r0) = 0
  58.                 c0 = c0 - 1
  59.             End If
  60.         Case 0
  61.             If r0 < 4 Then
  62.                 board(c0, r0) = board(c0, r0 + 1)
  63.                 board(c0, r0 + 1) = 0
  64.                 r0 = r0 + 1
  65.             End If
  66.         Case 8
  67.             If r0 > 1 Then
  68.                 board(c0, r0) = board(c0, r0 - 1)
  69.                 board(c0, r0 - 1) = 0
  70.                 r0 = r0 - 1
  71.             End If
  72.     End Select
  73.  
  74.  
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 19, 2022, 11:49:46 pm
Hey @bplus, it looks like the non-printable characters that are returned for InKey$ do not match the QB64 version at present.  I'll add that to the list.  Here is an example using the GXKeyDown function as an alternative in the meantime:

Code: QB64: [Select]
  1. _Title "15 Squares Puzzle" 'b+ mod for QBJS 2022-02-19
  2. Dim Shared As Integer board(4, 4)
  3. Dim Shared As Integer r0, c0, d
  4. Dim Shared As Integer keyState(0)
  5. Dim As Integer r, c, i, solved
  6. For r = 1 To 4
  7.     For c = 1 To 4
  8.         board(c, r) = c + (r - 1) * 4
  9.     Next
  10. board(4, 4) = 0
  11. c0 = 4
  12. r0 = 4
  13. For i = 0 To 50 * 4 * 4
  14.     d = Val(Mid$("0358", Int(Rnd * 4) + 1, 1))
  15.     handle
  16.  
  17.     Locate 1, 1
  18.     b = ""
  19.     solved = 1
  20.     For r = 1 To 4
  21.         For c = 1 To 4
  22.             If board(c, r) Then
  23.                 If board(c, r) <> c + (r - 1) * 4 Then
  24.                     solved = 0
  25.                 End If
  26.                 b = b + Right$("   " + Str$(board(c, r)), 3) + " "
  27.             Else
  28.                 b = b + "    "
  29.             End If
  30.         Next
  31.         Print b
  32.         b = ""
  33.     Next
  34.     Print
  35.     If solved Then
  36.         Locate 4 + 2, 2
  37.         Print "Solved!"
  38.         _Delay 5
  39.         'End
  40.     End If
  41.     'd = InKey$
  42.     'If Len(k) = 2 Then
  43.     '    d = (Asc(Right$(k, 1)) - 72)
  44.     '    handle
  45.     'End If
  46.     d = -1
  47.     handle
  48.     UpdateKeyState
  49.     _Limit 30
  50.  
  51. Sub handle
  52.     'Select Case d
  53.         'Case 3
  54.     If KeyPressed(GXKEY_LEFT) Or d = 3 Then
  55.             If c0 < 4 Then
  56.                 board(c0, r0) = board(c0 + 1, r0)
  57.                 board(c0 + 1, r0) = 0
  58.                 c0 = c0 + 1
  59.             End If
  60.    
  61.         'Case 5
  62.     ElseIf KeyPressed(GXKEY_RIGHT) Or d = 5 Then
  63.             If c0 > 1 Then
  64.                 board(c0, r0) = board(c0 - 1, r0)
  65.                 board(c0 - 1, r0) = 0
  66.                 c0 = c0 - 1
  67.             End If
  68.         'Case 0
  69.     ElseIf KeyPressed(GXKEY_UP) Or d = 0 Then
  70.             If r0 < 4 Then
  71.                 board(c0, r0) = board(c0, r0 + 1)
  72.                 board(c0, r0 + 1) = 0
  73.                 r0 = r0 + 1
  74.             End If
  75.         'Case 8
  76.     ElseIf KeyPressed(GXKEY_DOWN) Or d = 8 Then
  77.             If r0 > 1 Then
  78.                 board(c0, r0) = board(c0, r0 - 1)
  79.                 board(c0, r0 - 1) = 0
  80.                 r0 = r0 - 1
  81.             End If
  82.     End If
  83.     'End Select
  84.  
  85.  
  86. Function KeyPressed (key As Integer)
  87.     KeyPressed = (Not GXKeyDown(key) && keyState(key)
  88.  
  89. Sub UpdateKeyState
  90.     Dim i as integer
  91.     For i = 1 To 350 'GXKEY_UP To GXKEY_DOWN
  92.         keyState(i) = GXKeyDown(i)
  93.     Next i
  94.  
Title: Re: QBJS - QBasic for the Web
Post by: DANILIN on February 20, 2022, 07:55:58 am
https://boxgm.itch.io/qbjs

Bubble Sorting

10 ^ 3 = 0,81 s
10 ^ 4 = 78 s
10 ^ 5 = ? 780 seconds ?
10 ^ 6 = ??? 8100 seconds ??? 1,5 hours

Code: [Select]
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=BOAQAHvAM8A6QDCjgGNAMEAXlQ8JESU1gDJYBRagCmAAr4SMnqWwDTjdqCqJ/NfUd38+wklOVM0CUk5E2gFX6vuQacirCpRJh316doBq+ERQUklOVNwEFad6G9AD1zxiKiSmoqkyC8ueDppUAWo2/cwGpDz8AVtvm6AHUFJRnk+zegD55n3wzhqiQipy4AHEB0QtrmLgAW3zSWN9tYAAz/31TQ4ANASKnIjX3q6o9GTaFWjM6xNe5z637P/N19R6rDNSXtnfdy0jCWK3SVzS43A=
Code: QB64: [Select]
  1. N = 3: a = 10 ^ N: DIM d(a)
  2. FOR i = 1 TO a: d(i) = INT(RND * a): NEXT
  3. FOR i = 1 TO 5: PRINT d(i): NEXT: PRINT: z = TIMER
  4.  
  5. FOR i = 1 TO a - 1: FOR j = i + 1 TO a
  6.         IF d(i) > d(j) THEN
  7.             t = d(i)
  8.             d(i) = d(j)
  9.             d(j) = t
  10.         END IF
  11.  
  12. FOR i = 1 TO 5: PRINT d(i): NEXT: PRINT
  13. FOR i = a - 5 TO a: PRINT d(i): NEXT

error ":" without "end if"
IF d(i) > d(j) THEN t = d(i): d(i) = d(j): d(j) = t
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 20, 2022, 11:15:59 am
Yeah @DANILIN, single line IF statements not working. I am surprised all your other : lines are!!!

@dbox  so are : supported?

Also can this:
Code: QB64: [Select]
  1. 'Function KeyPressed (key As Integer)
  2. '    KeyPressed = (Not GXKeyDown(key) && keyState(key)
  3. 'End Function
  4.  
  5.  
be written in such a way that QB64 doesn't red line it?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 20, 2022, 01:15:38 pm
@bplus, yes, the : line separator is supported.  The single line if/then should also work in most scenarios, I just didn’t account for the single line if/then/else.  You should also be able to use the _ to continue a line.

If you want to use the GX functions in QB64 you will need to $include the gx.bi and gx.bm files from here:

https://github.com/boxgaming/gx/tree/main/gx (https://github.com/boxgaming/gx/tree/main/gx)

Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 20, 2022, 02:11:03 pm
Oh look at what's at the end of 3000+ LOC GX.BM
Code: QB64: [Select]
  1.  
  2.     '$Include: 'gx_fs.bm'
  3.     '$Include: 'resource/font-default.png.bm'
  4.     '$Include: 'resource/font-default-black.png.bm'
  5.  
  6.  
  7.  

Ehh this is too much!
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 20, 2022, 03:03:43 pm
Ha! Well, you did ask if it could be used in QB64.  But, yeah I get it, including the entire game engine for one method is a bit overkill.

I’ll plan to prioritize fully porting the standard QB/QB64 keyboard methods for the next build.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 20, 2022, 04:33:57 pm
@dbox

I'm sorry, bad day, too crabby! What you are working on is really good! Ground level stuff requires patience.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 21, 2022, 12:08:37 am
Bubble Sorting

10 ^ 3 = 0,81 s
10 ^ 4 = 78 s
10 ^ 5 = ? 780 seconds ?
10 ^ 6 = ??? 8100 seconds ??? 1,5 hours

Hey @DANILIN this is a good example for testing out performance improvements.  I'll look into this one further.  There is definitely a significant difference between the QBJS version and the natively complied version.
Title: Re: QBJS - QBasic for the Web
Post by: DANILIN on February 21, 2022, 01:05:57 am
2d arrays matrix are supported?

simply in "Bubble Sorting" replace "d(" on "d(5, "

Javascript without variables:
 
var d = QB.initArray([ 5], }); //


update:
Code: QB64: [Select]
  1. Dim As Integer matrix(5, 5)
  2. matrix(1, 1) = 3: matrix(2, 2) = 5: matrix(3, 3) = 7
  3.      
  4. for i = 1 to 5: for j = 1 to 5
  5.     Print matrix(i, j);

30000
05000
00700
00000
00000
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 21, 2022, 08:13:32 am
Hi @DANILIN.  Looks like you found an issue with the Dim/Redim that I need to fix.  There is an issue when you declare a multi-dimensional array like this:
Code: QB64: [Select]
  1. Dim matrix(5, 5) As Integer
  2.  

I will add this to the list for the next build.   In the meantime, if you declare the array with the newer Dim As Type syntax it will work as expected:

Code: QB64: [Select]
  1. Dim As Integer matrix(5, 5)
  2.  
  3. matrix(1, 1) = 3
  4. matrix(1, 2) = 5
  5. matrix(3, 4) = 7
  6.  
  7. Print matrix(1, 1)
  8. Print matrix(1, 2)
  9. Print matrix(3, 4)
  10. Print matrix(5, 5)
  11.  
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 21, 2022, 11:06:05 am
Fun fact: you can include native javascript in your QBJS program.  This is to allow you to use external libraries or generally just add additional functionality.  This would be analogous to calling out to a DLL in QB64 or calling inline assembly in classic QBasic.

Here's a simple example that will create a message box method by calling out to javascript's alert function:
Code: QB64: [Select]
  1. Input "Enter the message text: ", msg
  2.  
  3. MessageBox msg
  4.  
  5. Print "After message"
  6.  
  7. Sub MessageBox (text As String)
  8. $If Javascript
  9.     alert(text);
  10. $End If  
  11.  

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=JEaW0BAE2ubPwUFzYqm6OTS3M8AFcRJbnB1dMAIqIitzoyuXAnRoZXjNrK5ubCzsrg3RleHTQDrAJEWdcmyU1lc3NhZ2VCb3hXuBFByaW502KIgszoyuXNLTCU3VilwgFAtey4BTFgEjgUlm0kpTC7MLmxuTS4Ok/2CMLYyuTo/J1YB3W0BIrcybP0ztmA==)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 21, 2022, 11:47:28 am
@dbox

We (I) need a public check list of known issues unsupported or differences with QB64, that is detailed enough to pin point problem so that we (I) don't go trying to fix things not broken or attempt things not possible because of an issue like anything using arrow keys and probably all len(2) INKEY$ returns.

The : thing, works unless in one-liner If.
The keys number thing, work unless beyond the ascii list.
Something about dimensioning strings?
DIM a$, b$, c$ ' does not work (or did not for me once with 15 squares puzzle)
DIM as string a, b, c ' does work

DIM as something a, b, c works better than DIM a as something, b as something,...

2 Dimensional arrays work but assume base 1?

These are what I vaguely have picked up along the way in this thread but I am sure I don't have things clearly correct.

Perhaps we can track these issues in updated Supported Keywords page I am constantly consulting:
https://github.com/boxgaming/qbjs/wiki/Supported-Keywords

Like a pilot for an aircraft, a QB64 coder has a list of items to check before take off.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 21, 2022, 12:16:46 pm
Hey @bplus.  That was the intent of this page that I referenced in the first post:

QBasic Language Support (https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support)

However, there are several things that have been discovered since I posted that need to be added to this page.  Perhaps to make it easier to reference I can put a bulleted list at the top, similar to what you've created here with links to the detail to make it easier to scan through.  I'll also update the keyword reference page for the issues that have been discovered that are related to a specific keyword.

Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 21, 2022, 01:08:57 pm
Hey @bplus.  That was the intent of this page that I referenced in the first post:

QBasic Language Support (https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support)

However, there are several things that have been discovered since I posted that need to be added to this page.  Perhaps to make it easier to reference I can put a bulleted list at the top, similar to what you've created here with links to the detail to make it easier to scan through.  I'll also update the keyword reference page for the issues that have been discovered that are related to a specific keyword.

That would be great. See, I am making a sort of mental checklist but never sure it is correct in detail and extent.

It also may be good for a Punch list for you.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 21, 2022, 06:48:35 pm
Hey @bplus, I found a temporary workaround for the delay and KeyClear issue until I can get a new build out.  This seems to be working as intended now:

View Hangman in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=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)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 21, 2022, 06:56:15 pm
Actually a replaced 2 Sleep's with 2 _Delay's and it was after the Sleep's I needed KeyClear.

But looks and plays right, yeah!

(I forgot about _delay for the checklist, only working in main, so it works in procedures now too, excellent!)
Title: Re: QBJS - QBasic for the Web
Post by: STxAxTIC on February 22, 2022, 04:54:31 am
The epicycles code runs so awesome on this, on par with native:

  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 22, 2022, 10:16:22 am
I've updated the QBasic Language Support (https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support) to include the bulleted list at the top that we discussed @bplus.  It's divided in to three sections:

I will attempt to keep this updated as any new issues are reported.  Bugs or discrepancies that are specific to a keyword will still be maintained here:  Supported Keywords (https://github.com/boxgaming/qbjs/wiki/Supported-Keywords).

I think this is pretty up-to-date now with what has been discussed on this thread, but let me know if you see anything missing or find anything new.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 22, 2022, 12:18:58 pm
The epicycles code runs so awesome on this, on par with native:

 


If you didn't have to edit anything, I'm jealous!

Don't you want to share (link assigned at QBJS) the glory?  :)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 22, 2022, 12:21:20 pm
@dbox so one liner IF's fully functional now?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 22, 2022, 12:55:23 pm
@bplus, no I haven't pushed any updates up since my original post yet.  I have the following regarding single-line if/then on the QBasic Language Support (https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support#known-issues) page:


So as long as your If/Then statement doesn't have an Else or a : on the same line, I think it should work as expected.

Let me know if you run into any examples where this is not the case.
Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 22, 2022, 01:21:01 pm
@dbox

Oh sorry, the first link went to Keywords, that's where it said IF was full.

Ah, the 2nd link you just posted I will book mark, thanks!
Title: Re: QBJS - QBasic for the Web
Post by: STxAxTIC on February 22, 2022, 01:25:14 pm
Hey bplus -

On the road so pardon my briefness... So dbox had to help get the code ready, it wasn't quite paste and go.... For now...

As for the link, I would share if it was convenient. I'll try at the next red light.

....

Crap, url too big.

....


Title: Re: QBJS - QBasic for the Web
Post by: DANILIN on February 23, 2022, 08:06:38 am
graphic colors: especially RGB colors are unclear
so I think we need a table of a dozen colors

https://boxgm.itch.io/qbjs

Relief 3d multivariate parametric animate

Code: [Select]
https://v6p9d9t4.ssl.hwcdn.net/html/5279712/index.html?qbcode=BOAQAHvAMsAwmAOsAcc9AMfANb0EiJKbgFBc+xkludGVnZXLoBhkAowgArU8AWckAKcgCfEZEYW5pbGluwAM7gMnYVyZWxpZWbqAFUCRk9STAeEOpAqie7pKiA8vPN7LsAtXZnAOQUlGaBJKcqXZhKSciLQCp72cTAJNT0RYAbvuE4aokIqdqAByy163O11LdP9E6Zga7eavqABpHnRu0tKDbpiz63vjtm9quOwBpjkAClpyRbtjV5sAOM/gFoJFTkRaf5Q05FWFT98tcb08B0dWYEzNScD2rgNLq7yqVmuAFLxAanWlDRnb2H+2IdcjkF18Te9bqEfCs/IM9E0cEhpim70KltU2tGqd/oULap9adPCxBpiSnIsz25QsA3dSoTCT6k/AFLOlGj6s6qRd+8AGNKlmyu7Qp46Xm+ZYSPvkrfHbfqRB63p6gv+jGP67AX+OEpI6FStov1/NcV6iVYewdg7XYBi2GrfAmdqsIVbpngBMgsyjZPG3J+tT4/b8UOX7fqpCCF3z515ik+Y26inOf18Pn7vzVfp+vZF35qpFc99B59yzVJiyDTPUVVGLXm83zOfzfo9pRfYBw2HDYcbxCIiKmIKyjmAF3vJ05O31
https://qb64forum.alephc.xyz/index.php?topic=4398.msg138349#msg138349

 


Code: QB64: [Select]
  1. N = 200: q = 15: DIM As Integer a(q + 1, N) ' Danilin 3d relief
  2. FOR x = 1 TO q: FOR y = 1 TO N - 5:
  3.         IF INT(RND * 100) MOD 7 = 5 THEN
  4. a(x, y) = 5:a(x, y + 1) = 10
  5. a(x, y + 2) = 20: a(x, y + 3) = 40
  6. a(x, y + 4) = 80
  7.         END IF
  8.  
  9. FOR t = 1 TO N - q
  10.     FOR i = 1 TO q - 1
  11.         FOR j = 1 TO q - 1
  12. a(i, j) = a(i, j + t)
  13.         NEXT
  14.     NEXT
  15.     FOR y = 1 TO q - 1
  16.         FOR x = 1 TO q - 2
  17. LINE (30 + 20 * x + 20 * y, 400 - 20 * y - a(x, y))-(30 + 20 * (x + 1) + 20 * y, 400 - 20 * y - a(x + 1, y)), _RGB(((y + t) MOD 5) * 70, 0, 0)
  18.         NEXT
  19.     NEXT
  20.  
  21.     FOR x = 1 TO q - 1
  22.         FOR y = 1 TO q - 2
  23. LINE (30 + 20 * x + 20 * y, 400 - 20 * y - a(x, y))-(30 + 20 * (x + 1) + 20 * y, 400 - 20 * (y + 1) - a(x, y + 1)), _RGB(0, 0, 250)
  24.         NEXT
  25.     NEXT
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 23, 2022, 09:29:53 am
Hey @DANILIN, great example.  I will plan to include the color table for the various screen modes so the simple indexed color numbers can be used in the next build.  I'm compiling a list of bugs and requests that I'm planning to add to the Roadmap page on the qbjs github so we can keep track of what's coming in upcoming releases.

(Sorry for the double post. I was looking at your original thread and put this response there by mistake.)
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 24, 2022, 01:16:43 am
Thanks to everyone who has given this project a try so far.  I really appreciate all of the great feedback.

As I look at putting together the next release, in addition to the fixes and enhancements I have planned I would like to poll the group for your input...

What additional 1-10 keyword(s) would you consider to be the most essential for you beyond what is currently listed on the Supported Keywords (https://github.com/boxgaming/qbjs/wiki/Supported-Keywords) page?

Title: Re: QBJS - QBasic for the Web
Post by: bplus on February 24, 2022, 09:37:20 am
_Display, _PutImage, full use of _NewImage, _MapTriangle, files access for loading sounds or images or loading and saving data.

Maybe for keys need metacommand switch if running code in QB64 one set of key values, running QB64 another set because I'd prefer developing in QB64 because with errors, execution is plainly stopped and the offending error pointed at, you aren't left hanging, What went wrong?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on February 24, 2022, 01:31:04 pm
Great, thanks @bplus!  I'll look at adding the image methods in the near-term.

Definitely more that I need to do from an error reporting perspective and will look at including some of that work as well.

Thanks for the feedback.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 15, 2022, 06:10:44 pm
Hi All,

Fun QBJS update for everyone.  There is a new beta release (v.0.2.1) out to take for a spin!

You can try it out online here:  https://boxgm.itch.io/qbjs (https://boxgm.itch.io/qbjs)

Want to download it and run it locally?  Just go to the releases page on github (https://github.com/boxgaming/qbjs/releases (https://github.com/boxgaming/qbjs/releases)) and download the qbjs.zip file.  Unzip it to your preferred location and then just launch the index.html file.

This update has a number of fixes and enhancements:

Fixes
* Keywords that perform a system wait or sleep (_Delay, _Limit, Sleep) do not wait correctly when called from a Sub
* Keywords that perform a system wait (_Delay, _Limit, Sleep, Print, Input, Line Input) error when called from a Function
* Array declaration (Dim/ReDim)
  * (x To y) syntax not supported at present (e.g. Dim myArray(0 To 10))
  * Multi-dimensional arrays are not initialized correctly unless using the "Dim As Type" format (e.g. Dim As Integer myArray(10, 20))
* Improved support for standard key mappings for InKey$, _KeyDown and _KeyHit methods
* Single-line If/Then/Else statements are not converted correctly
* Single-line If/Then statements with ":" to combine additional lines do not work correctly

Enhancements
* Implement color table for the various screen modes so the simple indexed color numbers can be used in addition to colors defined with _RGB(32)
* Add support for QB64 image handling methods (_NewImage, _LoadImage, _PutImage, _CopyImage, _FreeImage)
* Improved runtime error reporting

You can check out the current list of supported keywords here:  Supported Keywords (https://github.com/boxgaming/qbjs/wiki/Supported-Keywords)

Keyboard Event Handling Updates
Support for standard QBasic/QB64 keyboard keywords have been greatly improved.  The following two examples should run pretty similar in native QB64 vs. QBJS:

Classic Indexed Color Support
QBJS now supports the original simple indexed 256-color palette.  Keywords that take colors as parameter will now accept the simple indexed color numbers as well as colors created with the _RGB* methods.
  [ This attachment cannot be displayed inline in 'Print Page' view ]  
View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=RQcmludAEABFGRGVmYXVsdMIht7Y3uTABQEiNLbcBp/BIze5MsAPcAGHYKo39AGMgGr8o3wkzrIAO2fUNOZXh0ZJ09w4ZM7/CwqG0uTG2MrUAoj0AcTxALGeADK9oBTnZAGemABWtSAVKgDTFfzL/5qQDf94C/ISoOTS3Oim6OTS3QgM7BX73nkBkP3xBKyOg5oqG3tje5OfCcKpsbkysrdvgcsZGyA1W54DxfSAeR7IDGXNLw47nGwf9fHTn0cyjwONeo/94PtxrjADBevIU1tSQToBwDTGluZXu1lT9qQBao5uaXGAc5ckaURn2pdogKEjWAQHjU0YsK7V11c=)

QB64 Image Keywords
QBJS now supports most of the QB64 image keywords.  Here are some examples to try out:

Note: If you find that previous link examples in this thread are not working you can simply replace the first part of the link with the current internal QBJS URL:
Code: [Select]
https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=
As always I value any and all feedback!
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 16, 2022, 12:57:21 pm
Here's another little tidbit for you.  I put together a simple POC to work out some ideas around allowing the QBJS canvas to interact with other elements on the page.  In this example you can create html elements, add them to a page and even assign events to your QB Subs:
 [ This attachment cannot be displayed inline in 'Print Page' view ]  
Code: QB64: [Select]
  1. DomInit
  2. DomAdd "div", "button-panel"
  3. DomAdd "button", "circle-button", "Draw Circle", "button-panel"
  4. DomAdd "button", "rect-button", "Draw Rectangle", "button-panel"
  5. DomAdd "input", "myinput", "", "button-panel"
  6. DomAdd "button", "text-button", "Draw Text", "button-panel"
  7. DomAdd "button", "clear-button", "Clear Screen", "button-panel"
  8.  
  9. Dim panel
  10. panel = DomGet("button-panel")
  11. panel.style.border = "1px solid green"
  12. panel.style.backgroundColor = "#333"
  13. panel.style.padding = "6px"
  14.  
  15. Dim btn
  16. btn = DomGet("circle-button")
  17. btn.onclick = sub_OnBtnCircleClick
  18. btn = DomGet("rect-button")
  19. btn.onclick = sub_OnBtnRectClick
  20. btn = DomGet("text-button")
  21. btn.onclick = sub_OnBtnTextClick
  22. btn = DomGet("clear-button")
  23. btn.onclick = sub_OnBtnClearClick
  24. btn.style.marginLeft = "15px"
  25.  
  26. Dim myinput
  27. myinput = DomGet("myinput")
  28. myinput.style.marginLeft = "15px"
  29.  
  30. Sub OnBtnCircleClick
  31.     Circle (Rnd * 600, Rnd * 380), 10 + Rnd * 90, Rnd * 14 + 1
  32.  
  33. Sub OnBtnRectClick
  34.     Dim As Integer x, y, w, h
  35.     x = Rnd * 600
  36.     y = Rnd * 380
  37.     w = Rnd * 90 + 10
  38.     h = Rnd * 90 + 10
  39.     Line (x, y)-(x + w, y + h), Rnd * 14 + 1, B
  40.  
  41. Sub OnBtnTextClick
  42.     If myinput.value <> "" Then
  43.         Color Rnd * 14 + 1
  44.         _PrintString (Rnd * 600, Rnd * 380), myinput.value
  45.     End If
  46.  
  47. Sub OnBtnClearClick
  48.     Cls
  49.  
  50. ' ------------------------------------------------------------------
  51. ' HTML DOM API Methods
  52. ' ------------------------------------------------------------------
  53. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  54. $If Javascript
  55.     if (document.getElementById(eid)) { return; }
  56.     var e = document.createElement(etype);
  57.     e.id = eid;
  58.     e.className = "qbjs";
  59.     if (content != undefined) {
  60.         e.innerHTML = content;
  61.     }
  62.     if (parentId == undefined || parentId == "") {
  63.         parentId = "gx-container";    
  64.     }
  65.     document.getElementById(parentId).appendChild(e);
  66.        
  67. Function DomGet (eid as String)
  68.     $If Javascript
  69.         return document.getElementById(eid);
  70.     $End IF
  71.            
  72. Sub DomInit
  73. $If Javascript
  74.     var elements = document.getElementsByClassName("qbjs");
  75.     for (var i=0; i < elements.length; i++) {
  76.         elements[i].remove();
  77.     }

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=ZEb21Jbml0AFCoje2oLIyQCAARYTI0u0CRFnqKxOro6N7dgC2iODC3MrZ8rl3gCsbS5MbYyr/ZsNEcmF34iobS5MbYyn9Vf3XAegG5MrG6ZD0P0QpMrG6MLcztjKf/zIq8sI0tzg6uk5mM2vLS3ODq6TkCIiIs/7NkfHoOoboyvDpnwezQNUZXh0ofmzvem9lEY2xlYXLDezCIbYysLl84qmxuTKyt1D94RFgSI0tpyumUA9GhURvbUdldNYBR1k+AAputIBduEc3R5bGWf2isTe5MjK5EM+sAxtguDwkCObe2NLI4RGdyZWVu8yYXjzEsTCxtbO5N7q3MmIRDb2xvckp9sAj4AGZ9vepEG6+M4MLIyNLczlx2oBsv9UkNQTE6NxTlNne2/vNn1KnOnjN7cxtjSxtYkUhObqxUAF9GSntyE6NyG0uTG2QhWVDbGlja7VElWp6xr9LIoUI8n52GSntyE6Nykysbohrg2xpY2vvCJ//ajW997yUEqQH7klPbkJ0blRleHRD6dqODzuiknN2yPc4durUlPbkJ0bkNsZWFyUCIbY0sbXcJ9MYpLawuTO0tyYyszocK6egBq9uY8HXZ02PP13ZOQynpFOlRonNd1EEpurEJrLoB/yX6CUm5kMIAqPrmgGDmz4BYZs87A8QDjypxI/fHYAVvg9rXAHPSvHgbepqAaPDQt4AkVuZH27oO6fQ9VMNsCguaSjJLc6MrOyuTkAPBJ74DzXawB37JCA0eq1lw6nS+gQvKs3cID7cetl5aetuEg7Qs2fC69VPTbk5KcdYHI/9VPQaY0tzLKPIs8IqY/JTOQ992WcFUZuamVbfJ3CSQELk3ffcek3+9VH4KSzW8yAI7MLY6st5QDwqAPpvgkRFFgao0Mrd1VVJOfnrZIirfqr/Vk5Kg5NLc6Kbo5NLdNQGfbj4uzuvj5ejhsY2o8Ix9n/Rs/yz8SZiZ4hlf5YEhtjnYvDu2WAT61rW58IQn0AABFERVVmZ3d3d83u7/////8AkkkkpJJJdum3QaQqJqZbwJET02OYSCoJNthk1ldGhvZHPt7JJJJJNtttt7bbbbbbbf//////////gABnCW39KiMro8uDLc9agVTdHJpbmdedwTK0sl5YLC5z1uWUGY29udGVudLL2DxsEO4MLkytzokskiyJ+f4wCTkWEJSmF2YXNjcmlwdHqu3BaWaQbQ7I3sbq2src6bfySzsroitjK2src6ZgNCeUlkQ0k46Z4D3G0VyZXR1cm5uAHcHwH16ppBOzC5RpAZYlmIsgSxuTKwujKitjK2p4JlbnRnTWMleqa0TVBaWSLZZdvVLoRhIY2xhc3NOYW1liyYgNxYmpzQmeqzOTzuZoBCWWRDq3MjKzNLcysi9lL1VUSjwJDS3NzK5JCompkWweG9Vkb1WEmH5lqCenstcqgHxoM05oZ9F5wZV/43l0aALO8VREMbe3OjC0tzK5JPf8f7Uj/d4XvettiZCwSWFwcGVuZENoaWw3AMkrXIHh7wmQwI5kf//ClHRnVuY3Rpb27F8pZsLt8kf68XdhK//958UCwF/auWJq/wZJrcFJRqVYF1////V7ZCla51rX+yOjx2VsZW1lbnRzy6uEEd8lzQnlDbGFzc05hUALay2m4p2LK/yWEzN7l3KTs8BpKi50I7VagjQgrYytzO6NDzSaptZglf/+kUgAtv9uwV0uFwrkytre7Mttlzr/vnT42wFOOfc=)

Assuming this approach is useful I may look at building in the DOM API methods as new QBJS Keywords.
Title: Re: QBJS - QBasic for the Web
Post by: FellippeHeitor on March 16, 2022, 01:06:14 pm
Man, this is just so amazing. Galleon intended to bring QB64 into the web with a javascript core one day™️, you just went ahead and did it yourself. The integration blows my mind, with parameters going back and forth between basic code and javascript. You are on fire, man. 🔥
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 16, 2022, 03:15:58 pm
Thanks @FellippeHeitor!
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 16, 2022, 04:38:13 pm
@dbox yeah so recursive does work, fantastic!
Code: QB64: [Select]
  1. _Title "Basic Tree from branch"
  2. 'Randomize Timer
  3. Screen _NewImage(800, 600, 32)
  4. '_ScreenMove 300, 20
  5. Color _RGB32(0, 255, 0)
  6.  
  7. 'just test call to sub
  8. '       x,   y,  270, .2*height, 1  start a tree with 270 degrees to point up, and about 1/5 the height you want to grow the tree
  9. branch 400, 500, 270, 100, 1
  10. Print "press any to see the forest..."
  11.  
  12. Dim horizon, i, y
  13. horizon = .35 * _Height
  14. For i = 0 To horizon
  15.     Line (0, i)-(_Width, i), _RGB(0, 0, .25 * i + 100)
  16. For i = horizon To _Height
  17.     Line (0, i)-(_Width, i), _RGB(0, 255 - .25 * i - 50, 0)
  18. For i = 1 To 250
  19.     y = randWeight(horizon, _Height, 3)
  20.     branch _Width * Rnd, y, 270, (.015 * Rnd + .027) * y, 1
  21.  
  22. Sub branch (x, y, angD, lngth, lev)
  23.     Dim x2, y2, l
  24.     x2 = x + Cos(_D2R(angD)) * lngth
  25.     y2 = y + Sin(_D2R(angD)) * lngth
  26.     Line (x, y)-(x2, y2), _RGB32(Rnd * 100, Rnd * 170 + 80, Rnd * 50)
  27.     If lev > 6 Or lngth < 2 Then Exit Sub
  28.     l = lev + 1
  29.     branch x2, y2, angD + 10 + 30 * Rnd, .7 * lngth + .2 * Rnd * lngth, l
  30.     branch x2, y2, angD - 10 - 30 * Rnd, .7 * lngth + .2 * Rnd * lngth, l
  31.     If Rnd < .65 Then branch x2, y2, angD + 20 * Rnd - 10, .7 * lngth + .2 * Rnd * lngth, l
  32.  
  33. Function randWeight (manyValue, fewValue, power)
  34.     randWeight = manyValue + Rnd ^ power * (fewValue - manyValue)
  35.  
  36.     _D2R = d * _Pi / 180
  37.  
 [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 16, 2022, 04:56:50 pm
Here's another little tidbit for you.  I put together a simple POC to work out some ideas around allowing the QBJS canvas to interact with other elements on the page.  In this example you can create html elements, add them to a page and even assign events to your QB Subs:

Code: QB64: [Select]
  1. DomInit
  2. DomAdd "div", "button-panel"
  3. DomAdd "button", "circle-button", "Draw Circle", "button-panel"
  4. DomAdd "button", "rect-button", "Draw Rectangle", "button-panel"
  5. DomAdd "input", "myinput", "", "button-panel"
  6. DomAdd "button", "text-button", "Draw Text", "button-panel"
  7. DomAdd "button", "clear-button", "Clear Screen", "button-panel"
  8.  
  9. Dim panel
  10. panel = DomGet("button-panel")
  11. panel.style.border = "1px solid green"
  12. panel.style.backgroundColor = "#333"
  13. panel.style.padding = "6px"
  14.  
  15. Dim btn
  16. btn = DomGet("circle-button")
  17. btn.onclick = sub_OnBtnCircleClick
  18. btn = DomGet("rect-button")
  19. btn.onclick = sub_OnBtnRectClick
  20. btn = DomGet("text-button")
  21. btn.onclick = sub_OnBtnTextClick
  22. btn = DomGet("clear-button")
  23. btn.onclick = sub_OnBtnClearClick
  24. btn.style.marginLeft = "15px"
  25.  
  26. Dim myinput
  27. myinput = DomGet("myinput")
  28. myinput.style.marginLeft = "15px"
  29.  
  30. Sub OnBtnCircleClick
  31.     Circle (Rnd * 600, Rnd * 380), 10 + Rnd * 90, Rnd * 14 + 1
  32.  
  33. Sub OnBtnRectClick
  34.     Dim As Integer x, y, w, h
  35.     x = Rnd * 600
  36.     y = Rnd * 380
  37.     w = Rnd * 90 + 10
  38.     h = Rnd * 90 + 10
  39.     Line (x, y)-(x + w, y + h), Rnd * 14 + 1, B
  40.  
  41. Sub OnBtnTextClick
  42.     If myinput.value <> "" Then
  43.         Color Rnd * 14 + 1
  44.         _PrintString (Rnd * 600, Rnd * 380), myinput.value
  45.     End If
  46.  
  47. Sub OnBtnClearClick
  48.     Cls
  49.  
  50. ' ------------------------------------------------------------------
  51. ' HTML DOM API Methods
  52. ' ------------------------------------------------------------------
  53. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  54. $If Javascript
  55.     if (document.getElementById(eid)) { return; }
  56.     var e = document.createElement(etype);
  57.     e.id = eid;
  58.     e.className = "qbjs";
  59.     if (content != undefined) {
  60.         e.innerHTML = content;
  61.     }
  62.     if (parentId == undefined || parentId == "") {
  63.         parentId = "gx-container";    
  64.     }
  65.     document.getElementById(parentId).appendChild(e);
  66.        
  67. Function DomGet (eid as String)
  68.     $If Javascript
  69.         return document.getElementById(eid);
  70.     $End IF
  71.            
  72. Sub DomInit
  73. $If Javascript
  74.     var elements = document.getElementsByClassName("qbjs");
  75.     for (var i=0; i < elements.length; i++) {
  76.         elements[i].remove();
  77.     }

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=ZEb21Jbml0AFCoje2oLIyQCAARYTI0u0CRFnqKxOro6N7dgC2iODC3MrZ8rl3gCsbS5MbYyr/ZsNEcmF34iobS5MbYyn9Vf3XAegG5MrG6ZD0P0QpMrG6MLcztjKf/zIq8sI0tzg6uk5mM2vLS3ODq6TkCIiIs/7NkfHoOoboyvDpnwezQNUZXh0ofmzvem9lEY2xlYXLDezCIbYysLl84qmxuTKyt1D94RFgSI0tpyumUA9GhURvbUdldNYBR1k+AAputIBduEc3R5bGWf2isTe5MjK5EM+sAxtguDwkCObe2NLI4RGdyZWVu8yYXjzEsTCxtbO5N7q3MmIRDb2xvckp9sAj4AGZ9vepEG6+M4MLIyNLczlx2oBsv9UkNQTE6NxTlNne2/vNn1KnOnjN7cxtjSxtYkUhObqxUAF9GSntyE6NyG0uTG2QhWVDbGlja7VElWp6xr9LIoUI8n52GSntyE6Nykysbohrg2xpY2vvCJ//ajW997yUEqQH7klPbkJ0blRleHRD6dqODzuiknN2yPc4durUlPbkJ0bkNsZWFyUCIbY0sbXcJ9MYpLawuTO0tyYyszocK6egBq9uY8HXZ02PP13ZOQynpFOlRonNd1EEpurEJrLoB/yX6CUm5kMIAqPrmgGDmz4BYZs87A8QDjypxI/fHYAVvg9rXAHPSvHgbepqAaPDQt4AkVuZH27oO6fQ9VMNsCguaSjJLc6MrOyuTkAPBJ74DzXawB37JCA0eq1lw6nS+gQvKs3cID7cetl5aetuEg7Qs2fC69VPTbk5KcdYHI/9VPQaY0tzLKPIs8IqY/JTOQ992WcFUZuamVbfJ3CSQELk3ffcek3+9VH4KSzW8yAI7MLY6st5QDwqAPpvgkRFFgao0Mrd1VVJOfnrZIirfqr/Vk5Kg5NLc6Kbo5NLdNQGfbj4uzuvj5ejhsY2o8Ix9n/Rs/yz8SZiZ4hlf5YEhtjnYvDu2WAT61rW58IQn0AABFERVVmZ3d3d83u7/////8AkkkkpJJJdum3QaQqJqZbwJET02OYSCoJNthk1ldGhvZHPt7JJJJJNtttt7bbbbbbbf//////////gABnCW39KiMro8uDLc9agVTdHJpbmdedwTK0sl5YLC5z1uWUGY29udGVudLL2DxsEO4MLkytzokskiyJ+f4wCTkWEJSmF2YXNjcmlwdHqu3BaWaQbQ7I3sbq2src6bfySzsroitjK2src6ZgNCeUlkQ0k46Z4D3G0VyZXR1cm5uAHcHwH16ppBOzC5RpAZYlmIsgSxuTKwujKitjK2p4JlbnRnTWMleqa0TVBaWSLZZdvVLoRhIY2xhc3NOYW1liyYgNxYmpzQmeqzOTzuZoBCWWRDq3MjKzNLcysi9lL1VUSjwJDS3NzK5JCompkWweG9Vkb1WEmH5lqCenstcqgHxoM05oZ9F5wZV/43l0aALO8VREMbe3OjC0tzK5JPf8f7Uj/d4XvettiZCwSWFwcGVuZENoaWw3AMkrXIHh7wmQwI5kf//ClHRnVuY3Rpb27F8pZsLt8kf68XdhK//958UCwF/auWJq/wZJrcFJRqVYF1////V7ZCla51rX+yOjx2VsZW1lbnRzy6uEEd8lzQnlDbGFzc05hUALay2m4p2LK/yWEzN7l3KTs8BpKi50I7VagjQgrYytzO6NDzSaptZglf/+kUgAtv9uwV0uFwrkytre7Mttlzr/vnT42wFOOfc=)

Assuming this approach is useful I may look at building in the DOM API methods as new QBJS Keywords.

Holy cow, getting JS and Basic both if I understand!?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 16, 2022, 05:44:10 pm
Here are a couple more quick web examples:

Copy Cat
This one copies the text to the QBJS canvas as well as another HTML element as the user types into a textarea control:
Code: QB64: [Select]
  1. Screen _NewImage(640, 200)
  2. DomInit
  3. DomAdd "div", "content-panel"
  4. DomAdd "textarea", "text-src", "", "content-panel"
  5. DomAdd "div", "text-div", "", "content-panel"
  6.  
  7. Dim Shared textArea
  8. textArea = DomGet("text-src")
  9. textArea.style.width = "640px"
  10. textArea.style.height = "100px"
  11. textArea.onkeyup = sub_OnTextChange
  12.  
  13. Dim Shared copyDiv
  14. copyDiv = DomGet("text-div")
  15. copyDiv.style.width = "640px"
  16. copyDiv.style.margin = "0 auto"
  17. copyDiv.style.padding = "10px"
  18. copyDiv.style.border = "1px solid green"
  19. copyDiv.style.textAlign = "left"
  20. copyDiv.style.backgroundColor = "#333"
  21. copyDiv.style.fontFamily = "arial, helvetica, sans-serif"
  22. copyDiv.style.whiteSpace = "pre"
  23.  
  24. Sub OnTextChange
  25.     Cls
  26.     Locate 1, 1
  27.     Print textArea.value
  28.     copyDiv.innerHTML = textArea.value
  29.  
  30.  
  31. ' ------------------------------------------------------------------
  32. ' HTML DOM API Methods
  33. ' ------------------------------------------------------------------
  34. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  35. $If Javascript
  36.     if (document.getElementById(eid)) { return; }
  37.     var e = document.createElement(etype);
  38.     e.id = eid;
  39.     e.className = "qbjs";
  40.     if (content != undefined) {
  41.         e.innerHTML = content;
  42.     }
  43.     if (parentId == undefined || parentId == "") {
  44.         parentId = "gx-container";    
  45.     }
  46.     document.getElementById(parentId).appendChild(e);
  47.        
  48. Function DomGet (eid as String)
  49.     $If Javascript
  50.         return document.getElementById(eid);
  51.     $End IF
  52.            
  53. Sub DomInit
  54. $If Javascript
  55.     var elements = document.getElementsByClassName("qbjs");
  56.     for (var i=0; i < elements.length; i++) {
  57.         elements[i].remove();
  58.     }

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=VTY3JlZW4BAAvx05ld0ltYWdlAFGAbQBogGAAWLgGXygFJACkMiN7aktzS6fIqI3tqCyMk0Ai4JkaXaQSIsu8GY29udGVudIALVEcGFuZWyR2lh3RleHRhcmVhjkQboyvDo0AnNyYx3giIiLNF7LHP31S6tB/V+o0dMtCRGltIxVNoYXJlZBA7oyvDoguTKw7inYB6Pioje2o7K6equGan33gBdoI5ujy2MrPMR3aWR0aDyXP5XiC4PF5uWNFIrQytLO0Onw8PAMbbdzYvcGb25rZXl1cObtBObqxQlyU9uVGV4dENoYW6eCzsu6u+jqDMbe4PKI0uwtvZ2j013nHwhRi6j18Qcu3Bbuz6IrawuTO0t2rpnvQ2F1dG+aRc1yDODCyMjS3M/v5kcfmqZLXxWJvcmRlcvjy9d1Ijm3tjSyd8IzuTKyt05jrdKQ6Mrw6ILY0s7ceJYDbGVmdJzqbWuSxMLG1s7k3urcyQhENvbG9yPDQgEcQAz21c+nksXksze3OiMwtrS2PPPuvEYXJpYWxo7AhoZWx2ZXRpY2FX1QbmwtzmvtEc2VyaWabfLYoJd2hpdGVTcGFjZT5KcJwcmWad/BKbqxDw2cAJQkNsc+AEQqY3sbC6Mpt3iHAGqIoOTS3OhXn4I7MLY6svAt8oyGlubmVySFRNTHzpn176CRW5kQXu7oAJ0ZZ1vrXPDETNVeZmbu94BLbkkkltttttu223///Lqn1QaQqJqZ6wJET03sYSCoJJPDJrK6NDeyOd1p/+qqqqqqqqqqrVVVVVVVVVWN/UdV/RGV0eXBlGQFBczdiqbo5NLczvxWCZWlkPaCwuYw+p9jFF34MA7gwuTK3OiSyC4eyPPWASIwKSzHLJSmF2YXNjcmlwdMAFQFpZhn3R2RvY3VtZW50+hEs7K6IrYytrK3OnDDQnlJZOLBWPRQAez3CuTK6Ork3PsA7EwB90A5oTswuR+gGUQKPySSxuTKwujKitjK29EJlbnT4x+yX0A//3+BaWQQJ/80A7fu0QxtjC5uacwtrKIH3obixNTm/JgApT4vPwAQtPgQ6tzIyszS3MrJ3E3gAAcfUkNNHzgAFcavjfRbesE9PbybyAPnKby3K3iBIiL3erKqq2J02nBZ3g5hDG3tzowtLcyuTaKrKrzZVJHUijVedTvDJYXBwZW5kQ2hpbOQAyNejGrOQRsjc4tsZVVZxx0Z1bmN0aW9uvNPbV3F7u5VdbqXXZVVX02jztdl7od2ZVOTrb8FJRs1b/+VVVVnTdxm0429yq2e2I7K2Mraytzo5y7b43s0lzQnlDbGFzc05h1ALayvJ3KPbsqneEzN7lP6yaIDSv36n4z8APLURdQrYytzO6NBVo9AAVktemXKqq0LvAW2Qjgrpc+BXJlbW92ZXcVXqm1zh613WR0=)

QBJS Paint
This one extends the first simple drawing program example that was added to the QBJS site by adding an HTML5 color picker that is used to change the current drawing color:
Code: QB64: [Select]
  1. Screen _NewImage(640, 200)
  2. DomInit
  3. DomAdd "div", "content-panel"
  4. DomAdd "textarea", "text-src", "", "content-panel"
  5. DomAdd "div", "text-div", "", "content-panel"
  6.  
  7. Dim Shared textArea
  8. textArea = DomGet("text-src")
  9. textArea.style.width = "640px"
  10. textArea.style.height = "100px"
  11. textArea.onkeyup = sub_OnTextChange
  12.  
  13. Dim Shared copyDiv
  14. copyDiv = DomGet("text-div")
  15. copyDiv.style.width = "640px"
  16. copyDiv.style.margin = "0 auto"
  17. copyDiv.style.padding = "10px"
  18. copyDiv.style.border = "1px solid green"
  19. copyDiv.style.textAlign = "left"
  20. copyDiv.style.backgroundColor = "#333"
  21. copyDiv.style.fontFamily = "arial, helvetica, sans-serif"
  22. copyDiv.style.whiteSpace = "pre"
  23.  
  24. Sub OnTextChange
  25.     Cls
  26.     Locate 1, 1
  27.     Print textArea.value
  28.     copyDiv.innerHTML = textArea.value
  29.  
  30.  
  31. ' ------------------------------------------------------------------
  32. ' HTML DOM API Methods
  33. ' ------------------------------------------------------------------
  34. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  35. $If Javascript
  36.     if (document.getElementById(eid)) { return; }
  37.     var e = document.createElement(etype);
  38.     e.id = eid;
  39.     e.className = "qbjs";
  40.     if (content != undefined) {
  41.         e.innerHTML = content;
  42.     }
  43.     if (parentId == undefined || parentId == "") {
  44.         parentId = "gx-container";    
  45.     }
  46.     document.getElementById(parentId).appendChild(e);
  47.        
  48. Function DomGet (eid as String)
  49.     $If Javascript
  50.         return document.getElementById(eid);
  51.     $End IF
  52.            
  53. Sub DomInit
  54. $If Javascript
  55.     var elements = document.getElementsByClassName("qbjs");
  56.     for (var i=0; i < elements.length; i++) {
  57.         elements[i].remove();
  58.     }

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=ZEb21Jbml0AFCoje2oLIyQCAARYTI0u0CRFnqMxt7c6OTe2YAtojgwtzK2fK5A3NwYW6MeI2MLEytnZsZDdXJyZW50KEQ29sb3L4B0emqU+W+BGlucHV09NCMbe2N7lyorg0sbWyuUcBEREWJ3+/VFCRGltZCqbQwuTKyOYLG4bBYAHqYVEb21HZXS8Ao9tT8gBTp6wC4Abo8uDKlvH9pnzEdmFsdWVyfcARliszMzMzMzfRnLBmRyYXdpbmcqBQXN3jJLc6MrOyuQoBRG8ApIKSzMwC/rJTW91c2VCdXR0b5AG6ZGAYyGENUaGVuCrVK4cJOb3SZxsV///mhqCmyumkpKFTW91c2VYIALMmeKmt7q5sqyhe94lTZWxlY3RlZENvuBNje5D///2xUhv2AYQ0Vsc2WwAO8NMaW5lQ7zZ+VPky/WHX6AVgkVuZF7QrXAHtikgGHBl3rg8iiJjS2tLo3QDOD6AGmN7e4B3d9Dozq3Mbo0t7clyg4LrZAcpnYAz3NEBizewDHwY6yUyoLuD5AJIW8SlMLswubG5NLg6cAddk5R3BhcnNlSW50h6MV+K5urE5ujlZ8a+ABlNut2oBtVwB9Wjw3XvOzy/sdjZNt2HDgDptWlnomy/dgA1nk4zSZG/Bm8h94A4L1RumwglJHQoZlmnZh/dGeHuDrwAnVV66+/0pS2c73v3vzMzM1V3mZmb3d3d3////ySSSSSW227EKIDSFRNTHuCRE9NZUJBUEl+Bk1ldGhvZHPP2tttttt2222222222/////6qqqqqqq0BhKbqxYjrLhGV0eXBl4Rk4qm6OTS3M5u2hMrSyZQCwueUTZGMxt7c6Mrc6ZVkUe4juDC5Mrc6JLJ2fZW0ahZVr/JAWlm7xYdkb2N1bWVudBIeSzsroitjK2src6DgaE8pLIEn239/Ae+FiuTK6Ork3DAB3zkB9r/vQTswuXJwGXmxyIKEsbkysLoyorYytt2CZW50CU7xbX+DRAUFpZOXGrnX/copOQxtjC5uacwtrLy8AgNxYmpzhI1/jvASe6gENnaiHVuZGVmaW5lZL8Y1/hIRXEhpbm5lckhUTUxYud3QZXQXRhnqygnp6stOgHy0K1rRWgEiIr1woAhljeFgs7xpkQxt7c6MLS3Mrl/8hQWyg5/297z8nuv85JYXBwZW5kQ2hpbKMAyeW/UGY6+U551ySAm9uLef5W7l7mqqL/IVO/cdYq/lN3Qno/FPBSUaYr7SACZcnKviu+lhyKPDsrYytrK3OjmoSkXy8klzQnlDbGFzc05hhgLay9e0L71JoIGEzN7k7jDxQGm2SXUQUQAPEUw/8K2MrczujRfQeCAFfUvLrYAQWBgLfV40FdLv8FcmVtb3Zl755YHOz9kN+T3mn8)
Title: Re: QBJS - QBasic for the Web
Post by: Pete on March 16, 2022, 10:19:23 pm
Man, this is just so amazing. Galleon intended to bring QB64 into the web with a javascript core one day™️, you just went ahead and did it yourself. The integration blows my mind, with parameters going back and forth between basic code and javascript. You are on fire, man. 🔥

Yep. one down, one to go on that wish list of his, JAVA. Rob wanted to redo QB64 in JAVA, so it could be used to make mobile apps for Android devices. Honestly for the time, circa 2007, C/C++ seemed to be the most stable choice, and PCs and laptops were in the user majority. JAVA would have satisfied both, and can be run on Apple and Linux too, but I guess a couple JAVA versions were blocked by Apple in the past.

Oh, and a post for history sake: https://www.tapatalk.com/groups/qbasic/welcome-to-the-qb64-forum-t36432.html#p158976 
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 16, 2022, 10:25:03 pm
@dbox   This is game I wanted to try tonight. The arrow keys work great! Miss a little noise maker when yellow square, our hero, hits a circle, now I just pause action so you can read your hits.

Actually a couple people here have posted similar game. While playing tonight I came up with new idea for scoring, TBA, say tuned!


Code: QB64: [Select]
  1. Dim As Long HX, HY, i, hits, score, Stars, nEnemies, Height
  2. HX = 320: HY = 400: nStars = 1000: nEnemies = 50: Height = 480
  3. Dim EX(nEnemies), EY(nEnemies), EC(nEnemies) As _Unsigned Long ' enemy stuff
  4. Screen _NewImage(640, Height, 32)
  5. Stars = _NewImage(640, Height, 32)
  6. For i = 1 To nStars
  7.     PSet (Int(Rnd * 640), Int(Rnd * 480)), _RGB32(55 + Rnd * 200, 55 + Rnd * 200, 55 + Rnd * 200)
  8. _PutImage , 0, Stars
  9. For i = 1 To nEnemies
  10.     EX(i) = Int(Rnd * 600 + 20): EY(i) = -2 * Height * Rnd + Height: EC(i) = _RGB32(55 + Rnd * 200, 55 + Rnd * 200, 55 + Rnd * 200)
  11.     Cls
  12.     _PutImage , Stars, 0
  13.     Print "Hits:"; hits, "Score:"; score
  14.     Line (HX - 10, HY - 10)-Step(20, 20), _RGB32(255, 255, 0), BF
  15.     For i = 1 To nEnemies ' the enemies
  16.         Circle (EX(i), EY(i)), 10, EC(i)
  17.         If Sqr((EX(i) - HX) ^ 2 + (EY(i) - HY) ^ 2) < 20 Then 'collision
  18.             _Delay .5
  19.             hits = hits + 1
  20.             EX(i) = Int(Rnd * 600 + 20): EY(i) = -Height * Rnd ' move that bad boy!
  21.             If hits = 10 Then Print "Too many hits, goodbye!": End
  22.         End If
  23.         EY(i) = EY(i) + Int(Rnd * 5)
  24.         If EY(i) > 470 Then EX(i) = Int(Rnd * 600 + 20): EY(i) = -Height * Rnd: score = score + 1
  25.     Next
  26.     If _KeyDown(20480) Then HY = HY + 3
  27.     If _KeyDown(18432) Then HY = HY - 3
  28.     If _KeyDown(19200) Then HX = HX - 3
  29.     If _KeyDown(19712) Then HX = HX + 3
  30.     If HX < 10 Then HX = 10
  31.     If HX > 630 Then HX = 630
  32.     If HY < 10 Then HY = 10
  33.     If HY > 470 Then HY = 470
  34.     _Display
  35.     _Limit 100
  36.  
  37.  

There is some flicker and odd where it is printing.

share:
https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QIoOTS3OnWAESGGkNLo5wwJ0RJoB3iDYKAEU2NvcmUBteCX/7UNMaW5l5BMA0VNiOw4tSM2Iam6MrhN9NwqT8VWdCcGtfBrX7k+mgoSM3/a9fRmbXqbO2YJ0aGXdBmVuZW1pZXOf//lYqG0uTG2MvN7u5ZuCFywNnS2xDcFv//WgUlmyMJTcXIRMFcG2xIa4AvddjIOl4dPPBjL1LOwDztPcw1RoZW7ZVAhjb2xsaXNpb26v///7UfERGVsYXnRgC6Ff///2PD0vHo1/wDt3hpmxN0LnjEJ1I1jde8tOF/AuVLhZQ21vdmVgg3RoYXRYQmJhZHACYm95lYBDUADuXMzcoc+6J3tsEqN7evQbawtzyk+d+Mzt7eyMTyy7LsASI6W4JFbmSgB/a2tAD+zhhunaywmcerFr7FQCeXNY5YUA+TvzAN4ZR+c301fvKVqREJn8bssHfON1mytV3l7eM+qbqBlKBfs98GS2V5RG93bt//rZT+0szHrwVJlAgPMLeeISzOjtYILxMXVaYQHuvc9V8A5l/+3Mv3jLZ2aYR3vv89d61/DHbudrxCTOkwqKSoknkNffJPTDI1qRdvXyO6PETr6walVFkvmJheq/2Dm4OxYIv9ncnrNxf3DzTRkRpc3BsYXm4ee+ETGltaXRX/9+JDTG9vcEYEVW50aWx7p9eR2rTLxFNsZWVwvAg=


I've got another I hope I can get working tomorrow.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 16, 2022, 11:35:03 pm
Nice one @bplus!  Looks like the flicker is related to the screen scrolling that happens when you print a newline on the last viewable line of the page.  I found that if you replace the Print call on line 16 with this...
Code: QB64: [Select]
  1.     Locate 30, 1
  2.     Print "Hits:"; hits, "Score:"; score;
... the display is nice and smooth.

View Mod in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QKmN7GwujLo224D/rBFByaW500sAiqA0hpdHNZBOiKSAO8Qbt9qIpsbe5MtrbvcLAP+yDTGluZeV52/u0+A0vLqRmODU3RlcJtp+Fyfis14TgxjdXvbuTbMChI1f9n1s2jyenxzZQnRoZcxGZW5lbWllcw//9SFQ2lyY2xl6wF15tu4OTs2tUb+NwW//8vBSWbWAlNxchEsNwbrNhy8Be57GQ07w6WPDUnqWpAHnWdMDVGhlbtko5DG3tjY0ubS3t1f///2kIREZWxheelgF0K////sGHuOPXt4Ade8NM1zuhW64hGpOsjo3jpmv4FapdOQG2t7syoWG6NDC6OAExMLImoTE3vN6AIagAdO4277DlXJO1tQlRvb0tDbWFueUjzYDM7e3sjE8sux3MEiOklCRW5kqAYxbSoB+5ww3f+ssJnFqlW7xUAnFnWOWEAPn/fADeGTfe+dOUjdK1xxCZ/GrbBvzTtasrVN5g3b6p3ygZOgX7rKxktleURvd27kf0bx/aUXr1lp0+gZbxZHnvX2K8dq1BeJi6x0CA9d7z3ZADmP/7dy8eNJidaBLeuzySXNkyR28ni7e6Z1qFBOTgk+hL7tL+wZGtVbt6/SXR4ievWDUopCr8wsDxX+wc2NIFeRfcHF4zcj9w9T4ZEaXNwbGF5uHqrxExpbWl0Yf/eMBpje3uC3RFVudGlsQz2vI3Nl3Qim2MrK4Ys)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 17, 2022, 07:02:33 am
Ah! in QB64 a CLS restarts Print line at top, line 1, so CLS in QBJS is not doing that! Thus the need for Locate.

That score should always be at the top.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 17, 2022, 09:16:39 am
Aha, good catch @bplus!  I've added that to the Known Issues (https://github.com/boxgaming/qbjs/wiki/QBasic-Language-Support#known-issues) page as well as the fix list for the next release on the Roadmap (https://github.com/boxgaming/qbjs/wiki/Roadmap) page.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 17, 2022, 12:42:12 pm
Played around a bit more with the QBJS Paint program.  Here's a version that will allow you to select different drawing tools and has 1 level of undo:
Code: QB64: [Select]
  1. CreateToolbar
  2. Dim fimage, cimage
  3. fimage = _NewImage(640, 400)
  4. cimage = _NewImage(640, 400)
  5.  
  6. Dim drawing, lastX, lastY, startX, startY, tool, radius
  7.         If Not drawing Then
  8.             _PutImage , cimage, fimage
  9.             '_FreeImage cimage
  10.             cimage = _NewImage(640, 400)
  11.             lastX = _MouseX
  12.             lastY = _MouseY
  13.             startX = lastX
  14.             startY = lastY
  15.             drawing = -1
  16.             DomGet("btn-undo").disabled = false
  17.         Else
  18.             tool = DomGet("tool").value
  19.            
  20.             If tool = "Freehand" Then
  21.                 _Dest cimage
  22.                 Line (lastX, lastY)-(_MouseX, _MouseY), SelectedColor
  23.                 lastX = _MouseX
  24.                 lastY = _MouseY
  25.                 _Dest 0
  26.                
  27.             ElseIf tool = "Line" Then
  28.                 '_FreeImage cimage
  29.                 cimage = _NewImage(640, 400)
  30.                 _Dest cimage
  31.                 Line (startX, startY)-(_MouseX, _MouseY), SelectedColor
  32.                 _Dest 0
  33.  
  34.             ElseIf tool = "Rectangle" Then
  35.                 '_FreeImage cimage
  36.                 cimage = _NewImage(640, 400)
  37.                 _Dest cimage
  38.                 Line (startX, startY)-(_MouseX, _MouseY), SelectedColor, B
  39.                 _Dest 0
  40.  
  41.             ElseIf tool = "Filled Rectangle" Then
  42.                 '_FreeImage cimage
  43.                 cimage = _NewImage(640, 400)
  44.                 _Dest cimage
  45.                 Line (startX, startY)-(_MouseX, _MouseY), SelectedColor, BF
  46.                 _Dest 0
  47.  
  48.             ElseIf tool = "Circle" Then
  49.                 '_FreeImage cimage
  50.                 cimage = _NewImage(640, 400)
  51.                 If Abs(_MouseX - startX) > Abs(_MouseY - startY) Then
  52.                     radius = Abs(_MouseX - startX)
  53.                 Else
  54.                     radius = Abs(_MouseY - startY)
  55.                 End If
  56.                 _Dest cimage
  57.                 Circle (startX, startY), radius, SelectedColor
  58.                 _Dest 0
  59.  
  60.             ElseIf tool = "Filled Circle" Then
  61.                 '_FreeImage cimage
  62.                 cimage = _NewImage(640, 400)
  63.                 If Abs(_MouseX - startX) > Abs(_MouseY - startY) Then
  64.                     radius = Abs(_MouseX - startX)
  65.                 Else
  66.                     radius = Abs(_MouseY - startY)
  67.                 End If
  68.                 _Dest cimage
  69.                 Dim r
  70.                 For r = 0 To radius Step .3
  71.                     Circle (startX, startY), r, SelectedColor
  72.                 Next r
  73.                 _Dest 0
  74.  
  75.             End If
  76.        
  77.         End If
  78.     Else
  79.         drawing = 0
  80.     End If
  81.     Cls
  82.     _PutImage , fimage
  83.     _PutImage , cimage
  84.     _Limit 30
  85. Loop    
  86.  
  87. Sub OnBtnUndo
  88.     '_FreeImage cimage
  89.     cimage = _NewImage(640, 400)
  90.     DomGet("btn-undo").disabled = true
  91.  
  92. Sub CreateToolbar
  93.     DomInit
  94.     DomAdd "div", "control-panel"
  95.     DomAdd "span", "label1", "Tool: ", "control-panel"
  96.     DomAdd "select", "tool", "", "control-panel"
  97.     DomAdd "span", "label2", "Color: ", "control-panel"
  98.     DomAdd "input", "color-picker", "", "control-panel"
  99.    
  100.     Dim btnUndo
  101.     btnUndo = DomAdd("button", "btn-undo", "Undo", "control-panel")
  102.     'btnUndo.style.marginLeft = "15px"
  103.     btnUndo.style.float = "right"
  104.     btnUndo.style.padding = "5px 10px"
  105.     btnUndo.disabled = true
  106.     btnUndo.onclick = sub_OnBtnUndo
  107.  
  108.     Dim panel
  109.     panel = DomGet("control-panel")
  110.     panel.style.textAlign = "left"
  111.     panel.style.width = "640px"
  112.     panel.style.margin = "0 auto"
  113.     panel.style.padding = "5px"
  114.     panel.style.fontFamily = "Arial, helvetica, sans-serif"
  115.     panel.style.fontSize = ".85em"
  116.     panel.style.border = "1px solid #666"
  117.     panel.style.backgroundColor = "#333"
  118.     panel.style.verticalAlign = "middle"
  119.  
  120.     Dim cp
  121.     cp = DomGet("color-picker")
  122.     cp.type = "color"
  123.     cp.value = "#ffffff"
  124.        
  125.     InitToolList
  126.    
  127. Sub InitToolList
  128.     Dim ts, topt
  129.     ts = DomGet("tool")
  130.     ts.style.marginRight = "15px"
  131.     ts.style.padding = "5px"
  132.     ts.style.verticalAlign = "top"
  133.     topt = DomAdd("option", "", "Freehand", "tool"): topt.value = "Freehand"
  134.     topt = DomAdd("option", "", "Line", "tool"): topt.value = "Line"
  135.     topt = DomAdd("option", "", "Rectangle", "tool"): topt.value = "Rectangle"
  136.     topt = DomAdd("option", "", "Filled Rectangle", "tool"): topt.value = "Filled Rectangle"
  137.     topt = DomAdd("option", "", "Circle", "tool"): topt.value = "Circle"
  138.     topt = DomAdd("option", "", "Filled Circle", "tool"): topt.value = "Filled Circle"
  139.    
  140. Function SelectedColor    
  141.     Dim r, g, b, c, cp
  142.     cp = DomGet("color-picker")
  143.     c = cp.value
  144.  
  145.     $If Javascript
  146.         r = parseInt(c.substr(1,2), 16)
  147.         g = parseInt(c.substr(3,2), 16)
  148.         b = parseInt(c.substr(5,2), 16)
  149.     $End If
  150.        
  151.     SelectedColor = _RGB(r, g, b)
  152.  
  153.    
  154. ' ------------------------------------------------------------------
  155. ' HTML DOM API Methods
  156. ' ------------------------------------------------------------------
  157. Function DomAdd (etype As String, eid as String, content As String, parentId As String)
  158. $If Javascript
  159.     if (document.getElementById(eid)) { return; }
  160.     var e = document.createElement(etype);
  161.     if (eid != undefined && eid != "") {
  162.         e.id = eid;
  163.     }
  164.     e.className = "qbjs";
  165.     if (content != undefined) {
  166.         e.innerHTML = content;
  167.     }
  168.     if (parentId == undefined || parentId == "") {
  169.         parentId = "gx-container";    
  170.     }
  171.     document.getElementById(parentId).appendChild(e);
  172.     return e;
  173.  
  174. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  175.     Dim e: e = DomAdd(etype, eid, content, parentId)
  176.        
  177. Function DomGet (eid as String)
  178. $If Javascript
  179.     return document.getElementById(eid);
  180.            
  181. Sub DomInit
  182. $If Javascript
  183.     var elements = document.getElementsByClassName("qbjs");
  184.     for (var i=0; i < elements.length; i++) {
  185.         elements[i].remove();
  186.     }

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=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)

(I also realized in the process that the _FreeImage keyword is not registered correctly, so it's been added to the fix list for the next release.)
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 18, 2022, 12:31:47 pm
Hi All,

As I'm working on planning the next beta release of QBJS I'd love to hear from the community what you'd like to see included next.  Here is my current list for v.0.3.0:

Fixes
* Cls is not resetting the text location to the top left of the screen.
* _FreeImage is being reported as an unrecognized method
* Using the "Call" keyword to call a sub with no arguments causes an error 
  Workaround: Remove the "Call" keyword
* Function calls prefixed with the negative operator (e.g. -_WIDTH) are not converting properly. 
  Workaround: Wrap function call in extra parenthesis (e.g. -(_WIDTH) )

Enhancements
* Add parameter to launch QBJS in "Play" mode with no IDE (mode=play)~~
  * Add checkbox on the share dialog to automatically add this parameter to the generated URL
* Add support for additional string keywords ( @FellippeHeitor let me know if you found some more from your examples ):
  * String$, Space$, Mkl$
* Add support for basic sound keywords:
  * _SndOpen, _SndClose, _SndPlay, _SndLoop, _SndVol, _SndPause, _SndStop
* Add Keywords to interact with HTML DOM (e.g. DomAdd, DomGet)
* Scale canvas to screen size when in fullscreen mode
  * Add support for _FullScreen keyword
* Add support for touch events on mobile
* Show runtime errors traced back to line in basic source in console window


The most up-to-date list is maintained on the QBJS project Roadmap (https://github.com/boxgaming/qbjs/wiki/Roadmap) page.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 30, 2022, 11:58:13 pm
The QBJS v0.3.0 release is out!  You can now go beyond the screen!

Check out the latest here: https://boxgm.itch.io/qbjs (https://boxgm.itch.io/qbjs).
The full list of fixes and enhancements are in the Release Notes (https://github.com/boxgaming/qbjs/releases/tag/v0.3.0-beta).

This release added more QB/QB64 keywords:
* More string keywords:  String$, Space$, Cvi, Cvl, Mki$, Mkl$
* Sound keywords: _SndOpen, _SndClose, _SndPlay, _SndLoop, _SndVol, _SndPause, _SndStop
* Resize keywords: _Resize, _ResizeWidth, _ResizeHeight

The most major addition to this release is the addition of new QBJS-specific keywords that allow access to create and manipulate HTML page elements and respond to DOM events.  Now rich HTML controls can be used in conjunction with your QBasic application.  Here are several examples:
* Input Controls (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=AnAQDobe3Ojk3tjnACiJRG9tQ29udGFpboFlckAoACngF2Ec3R5bGW6O3uzK5MzY3u6YB6iARAVzY3JvbGza/DAgXkOjK8OiC2NLO3IUjBtjKzOm6qKiVkSxMLG1s7k3urcyLEQ29sb3JmxwAjGEzMzMfsSiN7ajsroktrCzhAZQwAYAwfYzI0ubg2MLyuoMDbm9uZR3oSI0tuAAx9e4d2QiN7ahuTKwujKptCZGl2bd8RPgzgwsjI0tzPlzpAMhbgXB4fVJLQRjb2xvcq9fakAzDYn/EW2AwuAkRZqggFmiwaY0tzXOm+G0OTKzZdILzA6CyMiS3ODq6ayxWJ1dHRvbryXVIdjaGVja2JveLyNz/CW9ANkYXRl5HeIOyMLoyujS2sr8AtCEbG9jYWzmF8URlbWFpbOYbgBszS2MvVcOxWhpZGRlbhXxaEaW1hZ2UTYeiNre3OjQJsWBW51bWJlchNj/HcGFzc3dvcmQT4nCOTCyNLeKMMRHJhbmdlFXJgjkyubK6Drm2K5srC5MbQGuyhXN1Ym1pdE53dCdGVsTnZAboyvDonM+4bo0trKzsjgnVybGfnpDd2Vla2G2gqS08UJQWRkQ29udHJvbApQcZIgJJQKAbcecYKhOro6N7cafeDUHVzaOIBTWW5AIXWXfbjoEMO6Mrw6MLkysI/oyNFeL+8GqMrw6etDQXJlYRPzgnlvdfUhMbC3fYDdHlwZedgtLd9INoZXJl3rpAuf74HVFc2VsZWN0dDpdsRW9wdGlvbrXlu9zhU9wdGlvbvUgGKavcnm9eXuR4AnH3Fh+EHcT2EnIHRnVuY3Rpb273eG8AdJ+BhP/ATcgMlaBgOdrZBsbo5NhVbKjQQfM8AVbEVEb21BZGRsN3aFWBSemaYvv47lVsbNh39cG5uDC3QtbZs+4VamktKCyfUCtLc2NLcy0CZEYmxvY2vhVJZnyQiO7SyOjQyfeYwA1sKrhWbsqSEt7WLaUCiqUz7chCCRW5klGCiBKbqxWYeqEVWzayScVX+dJFyviiqUMeS1iqZey9Tm2f/OFU+mzJss/9wSyEI0tzg6ujdBOiKIACuQfiq5PaetTbJtYTOFV8e5xGzbI6JejmFV8wGmbMGxBJmfxVex6sZ0uFV7B0RvbUV2ZW50vUW3oFY2hhbmdlVlqE5urF4gF9Rkp7cktzg6uiG0MPkCbmdlFUuQUlmmk+xlrnBqjQyt0v9Vojswtjqyz7E7gSXeBYW6S4iS3ODq6SVPf3E38YfrEMVQL/Y9i5r5R/1oRBbGVydNCjqFdGFyZ2V0pae2edRGY2hhbmdlZEqAdbmBWyLqGhRz6Vvpm/QiJdIhVtaD4)
* HTML Content (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=AnAQDIbe3OjK3OkAKIlEb21Db250YWlugWVyQCgAKeAXYRzdHlsZbo7e7MrkzNje7pgHqIBEBXNjcm9sbNr8MCBeQ6Mrw6ILY0s7chSMG2MrM6bqoqJWRLEwsbWzuTe6tzIsRDb2xvcmbHACMYTMzMx+xKI3tqOyuiS2sLOEBlDABgDB9jMjS5uDYwvK6gwNub25lHehIjS24Aqm0MLkysmvAY++cO+IRG9tQ3JlYXRlU+BMjS7Me9ImsZwYWRkaW5n0Z3AGQtoLg8PqElCIxt7Y3uVmvjQAZxJL+qNRCMzY3sLpozqv/v5yANE8AxUBIizc8gFmowyQysLI0tzPh99bVTDS7qPVFx03DQ+Y3ZM9l8l0vsaIBpEdhLAcG6wvPAA1zEyLiYG68qsABt+J8X0fO7oGfAODBFmkBqjQ0uZ+gtLmMhmNvbnRlbnQvwWluIgDCfJDgwuTCzuTC4NBfH+C4J0YWeACXEXTNegMQxFmVBoTe2MhEtQSI6OkhMaW5lQnJlYWs/XxxIVzdHJvbmc6Bm5Yqm6OTe3M6UJX7pG5aOAaZISbwipLowtjSxvsG6Mrw6DUY4Zpu+Cyts0JNEDora4NDC5tLmiO5ju2ab/gOs0JNhyVVuZGVybGluZWR/vz9es434AcZpSaIP+fq+Yji6t7oywJ77nGCF0rs8mm+L/nweaZ1vOE4OTLpKbTibeIlwcmVmb3JtYXR0GwWVkTWJ2YAVw6EhtDkb4/xtsZ7AKS6SkO5Mrm4MrG6OcSjtzK7tjS3MrnuGYX168iStocWZ2D+z8puJQ9w/kkLM32CbLH/n8ygZnS96yPBE7ZQNIZXJlmBkA5pgCwtz1xGltYWdlHgToi38JaE0trPvTUDySlUEZd+vFYTm5MaRs/EaHR0cHMOAOviAXhiGCs7S6NDqxeIgmNvbSPukMTe8M7C2tLcz4ZACzvAvshOTC78BQNtYWlu6y8Zwcm9qZWN0GHff8E4NzPdKd/gju0sjo0InmLsz8m5uG5JPzsMJiX0uomIwurI0t7wRmNvbnRyb2wr6WIDQSFw0gbZ/Vp/wMOxt7c6OTe2OaFljZucgIzC5t7q5MbLt9Uzi6e0Vzb3VyY2Wrmt32dJrRhLJIxZD6QaBWsc6i/gW8/sZzYW1wbGVz98Qjmwtzow/VUJzbmQnoEaW50cm/o/BbXAyZ4a8yzMtHhGCV0Iud8Qjs0sjK3oDA8/3bgO2VlStqjudHk+bjgAxSKnKLgPZMV9/OrnJFaGVpZ2h0ZOmrhkJoIzs5t7q5MbLmsWbao+rJg05d+9pmns9gItYExsjd+CiuzSyMrs3/1ATcyug/v3sBfhIjM0tjK5j349oGzOTKyjv+yYtAOdgAWh3xC4jYwuTOy7TciXdhdGVybWFya2XSAMk9kJgHHuYbyNKdo9uiJTEFCT1JBVE9SSSqCiqemx4ZTQ0lFTkNF0MWpDGDODkyuzSyu/+XOBd4ZMqhkEd4+R/SkweV79Xj7H+yUFCMNQq+fb/pSgm5XcBZGHORN3A3GRMuK0szkwtrK7a1PZdnhQjKumw5Jr39iKCaPY99VCd3d3/6ozy3uro6sTL/BQbwjK2sTKyR9EBMvs4BWkq680RRS3VpS81bm+eQjC2Nje7lBdWSwsbGytjK5N7aywwJ0ZXL4QDscwbC6ujf98vDcGxheXXHUQytzG5PLg6MrJMQQRtZWRpYYKd2QzvLk3ubG3uDKt+fW4oO8Sa89bJg4lv3dewSm6sRSIXoIxt7q3OkWgODgpLMla3SsQ6tzIyszS3MrIwgNUaGVuYS3bWqpVkjVUthIze5Jabtt6sFUb3raqqpkQAFiciN9VeDDTmV4dHqaZAkVuZGFzw==)
* Web Dialogs (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAK5Mrm6tjpACgiS3ODq6GARIau0MLpALS59DeW91cuDszC7N7k0ujK8VhbmltYWzUAd9JV4APdRVByb21wdIAKLMNUaGF07bBtjC2sqAFnURlbnRlcsiHNvbWV0aGluZ+ZDI0szMyuTK3OgBHREWdVERQcmludOJBLLe67w2hhdmXcO5srYysboysjQDrgndW+mApLNlGQ29uZmlybXLQGqNDS59sQjm6NLY2c4DDsZBWFuc3dlcrgC7jFU2hvdWxkwAu7Lyjsbe3OjS3OrLUAfy+AU9gao0MrdX/0mEFPa4yIN3ZWxsQAtLp3AJ/wDnsisLY2t7m6bgbe7MrlpisLc8u7C8tAlxFSoaK2ObKf9fLAKc3w9XVEbWlnaHTDBYXPf6QrM0tzS5tGgG7tDC6ajs8F2Ze2M5ujC5OjKyMbMCRW5k3FrAoLclCKDkyubnkBMLc89UJrZXntAujfxwnNlZe4G6NDS56DrgtLdwwWFuwBGFsZXJ0LuaIptjKyuFqkIgtjK5OnEkNZb3Vy6gjM0tzC2YXM+46IBW+9)
* Multiple Image Canvases (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAKptDC5MrJwGPALEKxsbe6tzp+iObgysrIdDY2ltZ4AFRsBpuCSktzS6Ibe3Ojk3uC2Oe3AojeVahIbY562AMbgGp/2CRm9yWMgHrVMFUb0KgF34jswtjqywA+FQ2lyY2xlegFHgSk3MjsAqdAG3IBlwAYY6ubcAz0AONOYBTboxAK2zVhlbBWqJoXgGnB/DTmV4dGXBEAv+xExpbWl0T82LpA0xvb3DugEQ29sb3J59TztoqY3sbC6MrWf7PA7cIoOTS3OjGARag0dhbWVhDT3ZlcuPd4BKbqxMxKe3ILIyKbi6sLldAZYH1kAeKWQHmmINzaXplgYrgfN1+PXww1t27Wu/DCqHC+mk5j4YeENEZXN0Y3BYDTGluZWLg8u5lYAtq7oLnm2jVU+g9e4n3mAhaFmteb+hIrcyKPu3ljccGZvhtrC0t3mGQxt7c6MLS3MrlwbFa2CURvbUdldEltYWepzfYtDn++YRzdHlsZa/AKxN7kyMrkrVYXoLg8MwRzb2xpZFqAR5QTGxsdvQ5q5jkoje2obe3OjC0t1iCyuWhjZ83LiDt7syuTM2N7uwZL4VzY3JvbGyjQr1X91GQ6Mrw6ILY0s7cwU2wbYyszpZ4XrqHU2SxMLG1s7k3urcyZhBbj64JmZmb3g4K8iqyERvbUNyZWF0ZdX8yEyNLtHTwVX9iFQM4MLIyNLczoJZvfL04P+PqU+Ixt7Y3uSCdZBobp8HBUU6fRAkRYpTZ9oao0NLmjAWlzZcJ0aGV7pIVzY3JlZW56RWNhbnZhc/8CdEXBqxURvbUFkZEjDZwS7MICxOUpeeDg8GYsNzcGFuin3DO9GQ2lyY2xlc4IA6a4J58iX9dkRpbnB1dO1D00L3+ADdHlwZXzmdEcmFuZ2Xmh7f+oJtaW58t0MH9fCbWF4fOeWWhmpmr6BHdpZHRoTd/2bL980PFe9saS7Mrk6NLGwtiC2Z4JpZ25RybitrSyMjYy90ND8cwBz0MKqJ+TsF90s3eGIpuDKyskBdyaHKv4vyCW1hcmdpbkxlZnRV3FyxP6H4VYM8evQS5sC0v6qqPTjA3L/783zKqOXjA/b/786qji2a7sGBTv6Kr/gWr8+q9+mBqv6lk2mYFdGj002BbRZrCfA9IwlpT+jX2vtMAwvTFc2Vjb25kUYRpbWFnZc14NIqobiOnMruktrCzsujv66/T+eZ9D4SUNkaW1n0KYquBv3ST56FLt+thar8/ew9LcD/Q9+f2cIwSiKquCsrMyszKzRoVOZM82S2sLkztLchN7o6SIFvbVEWPqNC23D6m0OiPnyTaH6moTE6N2hxaw8dImIrE6ujo3t3JP4j0QkFkZH5Cqbi6sLkyxy0Jhnpxm9uY2xpY2tdLAnN1Yq+XOntVPhKw=)
* Simple Drawing (Event-based Version) (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAMyOTC7tLczwAoOiN7aiuzK3Ohkoje2o7K6JLaws6AygBRwDDAFNALGAERIbW91c2Vtb3ZlQJEWHhObqxcAv6Sntya3urmypre7I2iL5bXDWENre6ubKyN7u3X98kSntya3urmyoje76Abqnxjsqf9xm1vdXNldXDvDdiE9uTW91c2VVcKrcJTdWL2V3tb4sgUlmakgao0MrciDTGluZWkAtjgBU1vdXNlWKP4xU1vdXNlWf30EitzI/d3h+bH9kFrkNQU2V0j/11DrL6rmxAPbecAY/ji/VAvMyMx/17ntDPJ)
* Zoom Tool (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAS5t7q5MbKktrCzwGUAWGQ9N7e2pLaws7K5FenBhbmVsOgsbw8BY3kgBVFAA9tAX8ITG9hZEltYWdlcAoYAiURodHRwc4AOjALySFZ2l0aHViQAu+Ext7aviGJveGdhbWluZ+2CzvA0E5MLvchtrC0t14M4OTe1MrG6WYbu0tbTpAtrbEAtoAYHAMtXBODcz8QAKboFcpHDpzK7pLaws7KSGUS4YAW0pKS3NLoht7c6OTf8C2OffciqbG5MrK3YQ5zdgURv625cJDbHM7cysHUHV0SW1hZ2UUrQqvJzZTipre6ubKsONjAMehW0RJSIqa3urmyrMle/xXmhpjS3MuotfQV865uYBXch+8hG9Df8ZlYQBC2qz0DRGVzdJLau/r/iH37bX23yDfsnCpPN3FGjD3Eev+ioSxHN0eWxlQFhtjKzOnPoRw7QAzNODpFQXB4t1/wH3m50E6N7hh1jx7qKcu4e2V/ne8a/zqhExpbWl01JUKDTG9vcKqbCU3Vi354v/QEoje2o7K6JLaws87SYCHJcGFyZW50Tm9kZQKyFCHRleHRBbGlnburuZ7q/5PfiyERvbUNyZWF0ZXjmQGRjq/xG2HAhWJvcmRlcsPCaE4cRzb2xpZO0AI08JjY2ONf7cAITQ7g3ubS6NLe3auD6OwsTm3tjq6MsZ/7gVEb21BZGTKX3ANtvzHhIrcyZXM=)
   * Event-based Version (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAS5t7q5MbKktrCzwGUAWGQ9N7e2pLaws7K5FenBhbmVsOgsbw8BY3kgBVFAA9tAX8ITG9hZEltYWdlcAoYAiURodHRwc4AOjALySFZ2l0aHViQAu+Ext7aviGJveGdhbWluZ+2CzvA0E5MLvchtrC0t14M4OTe1MrG6WYbu0tbTpAtrbEAtoAYHAMtXBODcz8QAKblCqbG5MrK3LXmsJSW5pdENvbnRybwgtjmJGCU3ViXZKe3Jre6ubKmt7t2jAz22wgkNsc8/701HUHV0SW1hZ2VJvWK3q9TcujN7MzObK6LD7VgDEXFrNNyoYGb2Zmc2V0WdnNp3/nhpjS3MvO4GlEUV+OAV7e8O7GcEVt86u+MAhT/tUw0Rlc3Tr5/wc/9F7viu/VfKSMNtq1YHYuNOxmWiI/6+ysI5ujy2MpSYzI0ubg2MLzsdqIIxNjextZl+Adx/zjzK3QbYyszpy5zdG4AM1owchEFweK4/znuaMgnRvcO7OXHsrVZcROOP99r5wfCRW5k2mZFb48V/3MHMbHTmV3SW1hZ2Vd8pl32sqv+LJRG9tQ29udGFpbiALK5ObKbKpIdGV4dEFsaWduwaEdk/4wlEb21HZXRJbWFnbC76D0phWN1cnNvcsW59Dbm9uZXCM/6GrtCERvbUNyZWF0ZXRogmRpdouj/Wq1V5FYm9yZGVy1c3h3uBHNvbGlk10AjnAmNjY6R/tg0aWO4N7m0ujS3t2zs9DsLE5t7Y6ujKUf8hvncNmV1K7j/oRURvbUFkZO9lXZXPqiP9uHRG9tRXZlbnTfUskueb4Q2t7q5sra3uzKNgkRZsQTm6sSswTAHqQ==)
* QBJS Paint (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAKptDC5MrJw3Rvb2zALECxuH6MxOjcqtzI30AKhKG5MrC6Mqo3t7YwmJhcnOSFZmltYWdlNorG0trCzsu7cAezAL5jpzK7pLaws7KgBQIBsQBp8Aw+CDwAClhgQDlH2vYr9vjpsZkcmF3aW5n49EbGFzdFjkQjYwubos+7iubowuTosFAK5ujC5OizXUVyYWRpdXP+gURv9azBSWaJwSmt7q5sqE6ujo3ngNxNgDHybDVGhlbjVVc/kCTm906HFP//49iHUHV0SW1hZ2VivFWAAf8yEZyZWVJbWFnZXGAAeva3ryj/OJ77zoAH4uW+Cpre6ubKsaAB/uGcQqa3urmyrOA/qkNWn/6BFUt/+nmqAC1Pb/94MgFw4dkaXNhYmxlZJ6+IzMLY5srf5QNFbHNlb/9HcCsmI7MLY6stUgARJ46M5MrK0MLcyBtC3//nDBojK5ulVv//GBpjS3Ms50FycWpoGAoGFAv5KmytjKxujKyIbeehNje5L//4s9L6v//iT0vjf/+5/yt//7f/vQqK2ObKks0URH6I17j6Fv//WK0W//9Oqs+ibPIFAhS1//9rTcX//3ag2hdTWpNxkLjiQU6mV//95GZW//TGMGJctImEKTKxujC3M7Yyuqtv//eg1m//9eaCZVGkV1MpU1//8D99f//IWh7o5Ma88s68q26cFrr1AQl//8Us6r/+WSpR7mgDwqM0tjYyskejUS//+DXdX//3ZoJ3mCZ3UznbX//waX1//8neJOkWyDz0jrz7brUzui4KEjL//4NaFX/9mnTg6WMjRUNpcmNsZSLJf//AFaX//3pIMWmCZ20zocX//02+AkFic3QSy8y5HYB9Zl8Ek5MPVyf//5okqsQLaubfT//xmn//+qpZiIF1pMvp//7cCRW5kt6f/+Dm6n//t3EpZUPsk7bCwJ//4OZ0T/9hmTJKWQwc5kWSf/+D/cX//3JIHxnzzNnmMJP//e68MGNnWiq7cHwXW9Y/bJ///q0kYJ7WDaBT//1en//+zyyY3sYNiJP//RzDL//729xf//CKOAcl//8AhIze5ThjmnAFUb4GUg1N0ZXCVdUAzX///dcLRNiFMtpszCv//lgNOZXh0ulf//e1lX/86TC/6PmF9H1/3THKvk9EvkEJDbHNfeTtNtr7wLTaX3kgRMaW1pdJJlUiBpje3uHqwKCU3VioWQntyE6Nyq3Mje3vdKzevHeYEVMMmcYwW8nFy0jkAN0cnVlZGkCzKrIgsm8XEoje2o7K6JLaws7rAMoDgMFuI5ujy2MpsUCsbq5Obe5R3CikMbk3ubm0MLS5OW9vJ7tCODC3MrY3lexxKQiN7ahuTKwujKF0rITI0uz8De82I8wbm4MLc/AJEWX8TJR0NUb29seoA6kt77HDL5aoiubK2MrG6BLVL7ei5oTvHe6KQQEQ29sb3IIaTeE0d7ATekRpbnB1dE7Mn2950jzBujy4MsdQXxGNvbG9yWb0wlVY7TxAEZ6iszMzMzMzOL6+6QBOZ3Q3u6OYAcJsVidXR0b255VFFxXg1VuZG919vLVLnFTkiMzY3sLpHdE8RyaWdodHV9BcOQ4a4ZwYWRkaW5nkvlWAat4C4PF2xm6hX2p64UkBl9Px0RvbUV2ZW50tx4W0EY2xpY2s0oKE5urExwCr7lUO0L7YNctshURvbUdldHwi2Mxt7c6OTe2JncLy+KBQYzVEOjK8OiC2NLO3SwmyG2MrM6CXzAzUJS4R3aWR0aJYncADbDXzxIecX4rawuTO0t0kYLSBsLq6N419IcXIt5kjbePiL7FFgRaMlmb250RmFtaWx5lmQoRBcmlhbCX9kNDK2OzK6NLGwkswG5sLc5sRxEc2VyaWYy+yTZ00mHZm9udFNpemWS58EiLk0AOGbF0FlbTL7Jh8YSIVib3JkZXKSdINCNIjm3tjSyU+AhRA6+8Yf2zeJYmFja2dyb3VuZGkSzpa0wsNp1942JdSwl2ZXJ0aWNhbEFsTAJpZ26Wdq4ra0sjI2Mp1XzOJSW5pdFRvb2xMaQ9Bc3RSOLl9THSSkivsbop1LCW1hcmdpblJpZ2gSQHSWhOCd+oX3B0m6wUtB+DUL7s8cAl9LstB/BOje4IXx6hm4re4OjS3txFCioS+hfJaEASyHFS+Ur5/YUx9HisS5i+22P+2TI7Euv81fc7Tk5TY7UE1fBWsoDPDtZexWqaWUvqgA6M6tzG6NLe3RQU9fMZ8He6AzkicAxFo/AY18zGOiXzBV83ACR6ikSlMLswubG5NLg6L/uCOwcdwYXJzZUludEzHfMQVzdWJzdHJNxFZmAZJFvEYkv+buOR9MAPGlTZpTSUiyIgkv+bmOaDBneM1hJFMxMsyJJp5qzm7p/p4eQRxGkEpI6E2AlmiWHaaok3q+Qo=)
   * Event-based Version (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAKptDC5MrJw3Rvb2zALECxuH6MxOjcqtzI30AKhKS3NLoht7c6OTewWxzc5IVmaW1hZ2U2isbS2sLOy7twB7MAvmOnMruktrCzsqAFAgGxAGnwDD4IPAAKWGBAOUfa9iv2+OlZsZkcmF3aW5n5EI2MLm6LHO4jYwubos+kFc3RhcnRYFqK5ujC5Oiy7oVyYWRpdXP/zCU3ViuCU9uTW91c2VNb3bEBlVVsCks0Y8lNb3VzZUJ1dHRv0AbmNgGPlkGqNDK3Kqr5PCEnN7p0N+f///dfx1B1dEltYWdlYtxRoAH3ohGcmVlSW1hZ2VfwAHjwrPfN9rEtd40ADwWK5xU1vdXNlWNAA6GTFcVNb3VzZVnQH3CCmb/9Khnm//WTToBalt/+tFgC55HZGlzYWJsZWSaSEZmFsc2Vv9zDRWxzZW//cTwlICOzC2OrLVcQCIYOjOTKytDC3Minnm//9AsNEZXN0rN//5+GmNLcyznIV5pOognfQWnviCVNlbGVjdGVkQ294CbG9yb//389D03//vp6Hlv//cIyt//7f/r4qK2ObKks0eOGZ4p4lrhv//WLUm//9SmsyccOIE8hTl//9rtZX//1Oe7BcjnNJxcLiyIUei1//95CVW//RWcJok1WikKTKxujC3M7Yyq6Rv//epVm//9ea9QqhTK6mUqa//+87eX//x9oc6NTGNvKOvPtOlpY6SAIS//+CWdV//JZQm1yxGWKjNLY2MrJGYtCv//g1XV//92WCF5Ckd1I521//8Gd9f//I3iDo9sc89I68+260tDowChIy//+DShV//ZJw2NkivwVDaXJjbGUexX//wE2l//96SDBpKmdtM53F//85nEJBYnN0EktMOUsAfRvfA/Ny71an//+NJLIECyqmn0//9xU///1HLJxArr5l9P//bISK3MluT//3uLqf/+2sSlc+FcmbZmdP//e5mRP/1+dOB5ZDM1URYp//7w1xf//ckvPvoDzNnmM+v//vVMEDC3pH6L2sQJberftk///1SSME9pBrwp//6uT///apJYb2UGxEv//othV//97u4v//hdFgOS//+UgkZvcrq5JpdBVG+AsGGpujK4Sg6AM1///3bCzTYhTNibCwL//7shpzK8OlHr//72sq//m+OX/bUmvtqv+2o5V8lol8xBIbY5r7zbpodfeRKbSo0l/VULkUhPbkJ0blVuZG9ve4Vm9aO8mImcVM4xgt5ELETHIAbo5OrK3loWbLdAsztkURTeLiURvbUdldEltYWcWAMAup4jm6PLYynnOFY3Vyc29yjuCvIY3Jvc3NoYWlyeN4kHRG9tRXZlbnSJr0CYCb4ZkNre6ubK2t7synWCRFlfgnN1YnD0Yb28lo6I4MLcytje+jFfQhEb21DcmVhdGUL94gmRpdgX28u8gIhubgwtwVwmmSu4ao3t7YpIB1Mb3qKEAGvYK5srYysbo91Svt5/oPbF95opPGIht7Y3uTx6be8eK8gJrmI0tzg6ujwlz7e7p93A3R5cGWKqVYjG3tje5ON6USKkVx2gCM7RWZmZmZmZnF9fO0csC46wrE6ujo3txXSz3BHDVW5kb3AL7iavGap8IzNjewukd1wBHJpZ2h0fXyhu4LdCxnBhZGRpbmeS+0QBqLYLg8XeG2iFfQwG4ku+X3KU88LaCMbY0sbWi3AMbQq+1AGcZrCHRleHRBbGlnbpIXfhtjKzOgV9qGaRKTCO7SyOjRLECAA14l9+MDjDpFbWFyZ2luljBaANhdXRvGvv55yi2uWRtJxIvjUWJFnyWZvbnRGYW1pbHmSVEhEFyaWFsNGUhoZWx2ZXRpY2E1lA3NhbnNC+cRzZXJpZir49hmYSYdmb250U2l6ZY5IgkRcyABwy4vgsraVfPsObCRCsTe5MjK5RyjhnXviObe2NLJZACFEDL59h+bPYliYWNrZ3JvdW5kYTHMnKdjyfEy+mbEupwS7Mrk6NLGwtiC2CiE0s7dHMcwra0sjI2MplX3jkpLc0uio3t7YmNKUAuboqRfy+olE2T6vszot0vyW1hcmdpblJpZ2hIAHSSZPCl9HX2t0s6z0k5xEEL7s8XAlVKclB6hOje4IXxKgshW9wdGlvbjuFHQyJC+U0Hqn0OOh3sXzywMXCLHYGLF9PtCrnMjtTKFGr7labwU4O1LNXwNrhCTpLXFuBqoMxX1PUdGdW5jdGlvboiI+vuGeCTUAZywJAYixyAY19lbFPD44q+bIBI5XqkpTC7MLmxuTS4Oi/7Lih8O4MLk5sqS3OiZsPPnFc3Vic3RyTcJTQAMki38HSX/NrFNCw/zxj2EMUx1IsiIJL/mzjkuwZniWabxSVTLMiaa+aVIuy/6+RB0cRnhKSOhNABZnFk4yrFNuvh)
* Resize Example (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=lEb21HZXRJbWFnAygFEAwAFOAXQjm6PLYytFYm9yZGVy4BBgD26ARJrACgCiN/5teCks04C+wqkyubS9Msoao0Mrd1/519arRwR3aWR0aHju5KkyubS9Mqu0sjpQBogA3rP8f9FaGVpZ2h0WV8JUmVzaXplSGVpZ7wWh0kOgkVuZElByEiNLanAaaDYJDbHPAlCRm9yY1WABisBVG9D9/QCsVDaXJjbGVP2EpNzImAKkfIiu0sjo0RAFiOipQipDK0s7Q6ffqrz8AVoH9x3vt49Ldsx6ANKDcGnMrw6PdhPGImNLa0ujM3sDTG9vcA==)
   * Event-based Version (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=lEb21HZXRJbWFnAygFEAwAFOAXQjm6PLYytFYm9yZGVy4BBgD26ARJrACgOiN7aiuzK3Ok8V3aW5kb3fgCzGxXJlc2l6ZaBIizOE5urFAC+o6e3KTK5tL0y/ZUMCiN5/5sJEaW14A0uqyEhtjm6+QSM3uXLy8QDHUCqN+eJL/x6KhtLkxtjKq1CUm5kYgFTVkIrtLI6NEjKwscBUhlaWdodNV7zawArXLUf/+UVL567UAaaEAacyvDou0PeYiY0trS6O+34GmN7e4bucJTdWJixoV6FTrj6/z2Ed2lkdGh5WSURvbUNvbnRhaW7ECyuXPFtUljbGllbnRXaWR0vANGB0ulEtqYrQytLO0Oitr6s5f3iWNsaWVudEhlaWeCC0Ol4AkVuZG/I=)
* Sound Keywords (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BAA5wCzDMTC5sqqpJkAFPQD3oBFBGh0dHBzYB0gC8pFZ2l0aHVi8Au4Jjb20aQxN7wzsLa0tzPcBZ3iyE5MLuwG2sLS3JjObC2uDYyuaQjmwtzowohObcybFWARQcmludH/Yyg2MLy0tzOy3gjo0Mray2DLi4uIpFSYe3eYC/uMptzInuDK3OAKKdIBWLeJgLa4IAM15AKbdMMptzIoNjC88d2PyQRQcmVzc/oEwtzz6wmtlefkC6N7SG5uje4WMBFNsZWVwPq4ym3Mim6N7gbb1LqGU3RvcHBlZGQS4ijZHl6CgRpbnRybxwFvbhUNsb29wwTo+LsOPywa3fcN9bxjQym3MiY3t7gek4azGI/Dr9EcGF1c2XaRsfA6m3Migwurmyvbcu/H2+ny8hXJlc3VtZdvOz8XtuXZWRjYn12wWWulxA==)

As always I'm very interested in any and all feedback from the community!
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 31, 2022, 06:48:08 am
@dbox  You've found a way to load sound files? image files?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 31, 2022, 08:03:29 am
@bplus - Yes, loading images and sounds are now supported.  In my most recent post there are examples of loading images and sounds from URLs: (Zoom Tool, Sound Keywords).

If you run QBJS on your local machine (by downloading and extracting the qbjs.zip (https://github.com/boxgaming/qbjs/releases/download/v0.3.0-beta/qbjs.zip)) you can load files from the local filesystem:
Code: QB64: [Select]
  1. Dim img
  2. img = _LoadImage("play.png")
  3. _PutImage (100, 100), img

To load files that are outside of your QBJS folder you can use the file URL format: "file://C:/mypath/myfile.png"
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 31, 2022, 08:07:06 am
@bplus - Yes, loading images and sounds are now supported.  In my most recent post there are examples of loading images and sounds from URLs: (Zoom Tool, Sound Keywords).

If you run QBJS on your local machine (by downloading and extracting the qbjs.zip (https://github.com/boxgaming/qbjs/releases/download/v0.3.0-beta/qbjs.zip)) you can load files from the local filesystem:
Code: QB64: [Select]
  1. Dim img
  2. img = _LoadImage("play.png")
  3. _PutImage (100, 100), img

To load files that are outside of your QBJS folder you can use the file URL format: "file://C:/mypath/myfile.png"

Very good! Can't wait to try out if I can drag myself from eggs.
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 31, 2022, 09:06:52 am
One other thing I forgot to mention about the latest release... there are two new options for sharing your program in QBJS: Play and Auto.

 


Here are a couple of Easter egg related examples:

The Play option is good for games where you want to have a play button to start the game: Play Eggs o Dozens! (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?mode=play&qbcode=BfIqNLo2MoBBAIgaKzs7m4DfIqI3vTK3OdwAngDEwCvQBkQDAbABb3gDPNwA5gAKMRDb25zdBg1htYXgUA9EAMbfNWdDWW1heHu0AaeubcAqDS5jPTeKpsbkysrc2kOnMruktrCzsvYBRbAAscTLjpgClhBIjS2z4jmxsLYykgAPGJsB5f3NgvADZ1wURv2qyCRm9ys92EZ7EFUb4biaDU3RlcJSZ//9rycNsnZ9aidlyUr///9klkcmF3RWFzdGVyGCRWdnz17EuGu58C2GnMrw6SGRkJsgiIytjC8o3gDTG9vcEERVbnRpbGNIZLZXlEb3du5dXQDfBpU8JTdWJl5KpRBeGOaUC8sc33T1JcmFkaWFuQW5nbIwDLSsJRFAcuuMBn6iuvX3n6EAx/RcPYQrp6BKTcyeAB09Lt1+tert02FRAo7uUBygusAurmgDW9stUWlJoT7eKAA2wUlmSsUA8W2A1RoZW54U2s5Taqq1wDVqBorY5sq0u0uChmZD5AA2KncvwCpc1WamjZq4BeZMSp87zDfpLEXb8rga+iWrtT8AAMdGxAD5S1+AAAWgiG3tje5O3PCUkdCj+er+WQBwjPW3pLvd7nndU1FxCr7OiDCU2lup6Oqs/3c+in5pxQ0jVHPt1M24za5MG/dvDJsZ3clWGjfrJpmxuyxbV51i0zcvd56cs7fjQAAS3QAABVWyP1LectGZXL1XzD/ifNjmzt8Da7fKk85SqMD2rt8B4fvuKLU7FHd/HIAAd8JFbmRh5AACDgMLNj4gaC6MLdeeVEMcgABaQGRq7lWKCU3FynIqlQNFW0cgAB74agpsronxaBjarGBIbe50x9C83JjF9ylilmCeIVqCXhHIAHEuPIB1tB9e5Jn/cw==)

The Auto option is useful when you just want the program to automatically start playing: Eggs o Dozens (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?mode=auto&qbcode=BfIqNLo2MoBBAIgaKzs7m4DfIqI3vTK3OdwAngDEwCvQBkQDAbABb3gDPNwA5gAKMRDb25zdBg1htYXgUA9EAMbfNWdDWW1heHu0AaeubcAqDS5jPTeKpsbkysrc2kOnMruktrCzsvYBRbAAscTLjpgClhBIjS2z4jmxsLYykgAPGJsB5f3NgvADZ1wURv2qyCRm9ys92EZ7EFUb4biaDU3RlcJSZ//9rycNsnZ9aidlyUr///9klkcmF3RWFzdGVyGCRWdnz17EuGu58C2GnMrw6SGRkJsgiIytjC8o3gDTG9vcEERVbnRpbGNIZLZXlEb3du5dXQDfBpU8JTdWJl5KpRBeGOaUC8sc33T1JcmFkaWFuQW5nbIwDLSsJRFAcuuMBn6iuvX3n6EAx/RcPYQrp6BKTcyeAB09Lt1+tert02FRAo7uUBygusAurmgDW9stUWlJoT7eKAA2wUlmSsUA8W2A1RoZW54U2s5Taqq1wDVqBorY5sq0u0uChmZD5AA2KncvwCpc1WamjZq4BeZMSp87zDfpLEXb8rga+iWrtT8AAMdGxAD5S1+AAAWgiG3tje5O3PCUkdCj+er+WQBwjPW3pLvd7nndU1FxCr7OiDCU2lup6Oqs/3c+in5pxQ0jVHPt1M24za5MG/dvDJsZ3clWGjfrJpmxuyxbV51i0zcvd56cs7fjQAAS3QAABVWyP1LectGZXL1XzD/ifNjmzt8Da7fKk85SqMD2rt8B4fvuKLU7FHd/HIAAd8JFbmRh5AACDgMLNj4gaC6MLdeeVEMcgABaQGRq7lWKCU3FynIqlQNFW0cgAB74agpsronxaBjarGBIbe50x9C83JjF9ylilmCeIVqCXhHIAHEuPIB1tB9e5Jn/cw==)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 31, 2022, 09:10:09 am
Hey those eggs have some really nice patterns in them!

@dbox How do you get back to the code from Play?
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 31, 2022, 09:58:06 am
@bplus - Just remove the mode=play parameter from the URL.

Here it is in default IDE mode:  Eggs o' Dozens (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=BfIqNLo2MoBBAIgaKzs7m4DfIqI3vTK3OdwAngDEwCvQBkQDAbABb3gDPNwA5gAKMRDb25zdBg1htYXgUA9EAMbfNWdDWW1heHu0AaeubcAqDS5jPTeKpsbkysrc2kOnMruktrCzsvYBRbAAscTLjpgClhBIjS2z4jmxsLYykgAPGJsB5f3NgvADZ1wURv2qyCRm9ys92EZ7EFUb4biaDU3RlcJSZ//9rycNsnZ9aidlyUr///9klkcmF3RWFzdGVyGCRWdnz17EuGu58C2GnMrw6SGRkJsgiIytjC8o3gDTG9vcEERVbnRpbGNIZLZXlEb3du5dXQDfBpU8JTdWJl5KpRBeGOaUC8sc33T1JcmFkaWFuQW5nbIwDLSsJRFAcuuMBn6iuvX3n6EAx/RcPYQrp6BKTcyeAB09Lt1+tert02FRAo7uUBygusAurmgDW9stUWlJoT7eKAA2wUlmSsUA8W2A1RoZW54U2s5Taqq1wDVqBorY5sq0u0uChmZD5AA2KncvwCpc1WamjZq4BeZMSp87zDfpLEXb8rga+iWrtT8AAMdGxAD5S1+AAAWgiG3tje5O3PCUkdCj+er+WQBwjPW3pLvd7nndU1FxCr7OiDCU2lup6Oqs/3c+in5pxQ0jVHPt1M24za5MG/dvDJsZ3clWGjfrJpmxuyxbV51i0zcvd56cs7fjQAAS3QAABVWyP1LectGZXL1XzD/ifNjmzt8Da7fKk85SqMD2rt8B4fvuKLU7FHd/HIAAd8JFbmRh5AACDgMLNj4gaC6MLdeeVEMcgABaQGRq7lWKCU3FynIqlQNFW0cgAB74agpsronxaBjarGBIbe50x9C83JjF9ylilmCeIVqCXhHIAHEuPIB1tB9e5Jn/cw==)
Title: Re: QBJS - QBasic for the Web
Post by: dbox on March 31, 2022, 10:55:07 am
By the way @bplus, the lastest version has that Cls fix, so your original game code is working as intended now:

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QIoOTS3OnWAESGGkNLo5wwJ0RJoB3iDYKAEU2NvcmUBteCX/7UNMaW5l5BMA0VNiOw4tSM2Iam6MrhN9NwqT8VWdCcGtfBrX7k+mgoSM3/a9fRmbXqbO2YJ0aGXdBmVuZW1pZXOf//lYqG0uTG2MvN7u5ZuCFywNnS2xDcFv//WgUlmyMJTcXIRMFcG2xIa4AvddjIOl4dPPBjL1LOwDztPcw1RoZW7ZVAhjb2xsaXNpb26v///7UfERGVsYXnRgC6Ff///2PD0vHo1/wDt3hpmxN0LnjEJ1I1jde8tOF/AuVLhZQ21vdmVgg3RoYXRYQmJhZHACYm95lYBDUADuXMzcoc+6J3tsEqN7evQbawtzyk+d+Mzt7eyMTyy7LsASI6W4JFbmSgB/a2tAD+zhhunaywmcerFr7FQCeXNY5YUA+TvzAN4ZR+c301fvKVqREJn8bssHfON1mytV3l7eM+qbqBlKBfs98GS2V5RG93bt//rZT+0szHrwVJlAgPMLeeISzOjtYILxMXVaYQHuvc9V8A5l/+3Mv3jLZ2aYR3vv89d61/DHbudrxCTOkwqKSoknkNffJPTDI1qRdvXyO6PETr6walVFkvmJheq/2Dm4OxYIv9ncnrNxf3DzTRkRpc3BsYXm4ee+ETGltaXRX/9+JDTG9vcEYEVW50aWx7p9eR2rTLxFNsZWVwuwg=)
Play Game (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?mode=play&qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QIoOTS3OnWAESGGkNLo5wwJ0RJoB3iDYKAEU2NvcmUBteCX/7UNMaW5l5BMA0VNiOw4tSM2Iam6MrhN9NwqT8VWdCcGtfBrX7k+mgoSM3/a9fRmbXqbO2YJ0aGXdBmVuZW1pZXOf//lYqG0uTG2MvN7u5ZuCFywNnS2xDcFv//WgUlmyMJTcXIRMFcG2xIa4AvddjIOl4dPPBjL1LOwDztPcw1RoZW7ZVAhjb2xsaXNpb26v///7UfERGVsYXnRgC6Ff///2PD0vHo1/wDt3hpmxN0LnjEJ1I1jde8tOF/AuVLhZQ21vdmVgg3RoYXRYQmJhZHACYm95lYBDUADuXMzcoc+6J3tsEqN7evQbawtzyk+d+Mzt7eyMTyy7LsASI6W4JFbmSgB/a2tAD+zhhunaywmcerFr7FQCeXNY5YUA+TvzAN4ZR+c301fvKVqREJn8bssHfON1mytV3l7eM+qbqBlKBfs98GS2V5RG93bt//rZT+0szHrwVJlAgPMLeeISzOjtYILxMXVaYQHuvc9V8A5l/+3Mv3jLZ2aYR3vv89d61/DHbudrxCTOkwqKSoknkNffJPTDI1qRdvXyO6PETr6walVFkvmJheq/2Dm4OxYIv9ncnrNxf3DzTRkRpc3BsYXm4ee+ETGltaXRX/9+JDTG9vcEYEVW50aWx7p9eR2rTLxFNsZWVwuwg=)
Title: Re: QBJS - QBasic for the Web
Post by: bplus on March 31, 2022, 11:38:05 am
@dbox Yes my version of Hangman is almost there too, just get an extra letter at start of new puzzle.

I don't know if I showed:
Code: QB64: [Select]
  1. _Title "Hangman" 'for QB64 B+ (redo Hang it) working almost in QBJS v 3.0 2022-03-30
  2. Const hung = "Hanged!" ' allows 7 misses
  3. ReDim Shared w$(7) ' word list
  4. Dim Shared As Integer round, nHung, done
  5. Dim Shared selectLetters$
  6. Dim As Integer place
  7. Dim k$
  8. LoadWords
  9. For i = 0 To 7
  10.     cp i + 1, w$(i)
  11. Do ' main loop manages the letters to select from and removes letter when selected
  12.     selectLetters$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  13.     nHung = 0
  14.     done = 0
  15.     Cls
  16.     Update
  17.     While done = 0
  18.         k$ = ""
  19.         While Len(k$) = 0
  20.             k$ = UCase$(InKey$)
  21.             _Limit 60
  22.         Wend
  23.         place = InStr(selectLetters$, k$)
  24.         If place Then
  25.             selectLetters$ = Mid$(selectLetters$, 1, place - 1) + "-" + Mid$(selectLetters$, place + 1)
  26.         End If
  27.         If InStr(w$(round), k$) = 0 Then
  28.             nHung = nHung + 1
  29.         End If
  30.         Update
  31.         _Limit 30
  32.     Wend
  33. Loop Until round > 7
  34.  
  35. Function Reveal$ ' from remaining selected letters a * will cover unchosen letters in w$(round)
  36.     Dim i, b$
  37.     b$ = ""
  38.     For i = 1 To Len(w$(round))
  39.         If InStr(selectLetters$, Mid$(w$(round), i, 1)) > 0 Then
  40.             b$ = b$ + "*"
  41.         Else
  42.             b$ = b$ + Mid$(w$(round), i, 1)
  43.         End If
  44.     Next
  45.     Reveal$ = b$
  46.  
  47. Sub Update 'draw everything for screen 0 and while we're at it decide if word round is done
  48.     cp 8, "Hangman: " + Reveal$
  49.     cp 10, "Press a letter from: " + selectLetters$
  50.     cp 12, "Gallows Report: " + Mid$(hung, 1, nHung)
  51.     If Reveal$ = w$(round) Then
  52.         cp 14, "Congratulations! you got it."
  53.         done = -1
  54.     End If
  55.     If Len(hung) = nHung Then
  56.         cp 14, "Yikes! You were hung by: " + w$(round)
  57.         done = -1
  58.     End If
  59.     If done = -1 Then
  60.         If round + 1 > 7 Then
  61.             cp 16, "Hangman is out of words to play. Goodbye in 5"
  62.             _Delay 5
  63.             End
  64.         End If
  65.     End If
  66.     If done = -1 Then
  67.         If round + 1 <= 7 Then
  68.             round = round + 1
  69.             cp 16, "Next Round in 5 secs"
  70.             _Delay 5
  71.             'sleep2 ' sleeps suck!!!
  72.             '_KeyClear ' >>>>>>>>>>>> unsupported
  73.         End If
  74.     End If
  75.  
  76. Sub cp (row, s$)
  77.     Locate row, (80 - Len(s$)) / 2: Print s$
  78.  
  79. Sub LoadWords
  80.     w$(0) = "BPLUS GAMES"
  81.     w$(1) = "HANGMAN"
  82.     w$(2) = "GALLOWS"
  83.     w$(3) = "REVEAL"
  84.     w$(4) = "KEYPRESS"
  85.     w$(5) = "REPORT"
  86.     w$(6) = "LETTERS"
  87.     w$(7) = "BASIC"
  88.     'w$(8) = ""
  89.     'w$(9) = ""
  90.     'w$(10) = ""
  91.     'w$(11) = ""
  92.     'w$(12) = ""
  93.     'w$(13) = ""
  94.     'w$(14) = ""
  95.     'w$(15) = ""
  96.     'w$(16) = ""
  97.     'w$(17) = ""
  98.     'w$(18) = ""
  99.     'w$(19) = ""
  100.     'w$(20) = ""
  101.     'w$(21) = ""
  102.     'w$(22) = ""
  103.     'w$(23) = ""
  104.     'w$(24) = ""
  105.     'w$(25) = ""
  106.     'w$(26) = ""
  107.     'w$(27) = ""
  108.     'w$(28) = ""
  109.     'w$(29) = ""
  110.     'w$(30) = ""
  111.     'w$(31) = ""
  112.     'w$(32) = ""
  113.     'w$(33) = ""
  114.     'w$(34) = ""
  115.     'w$(35) = ""
  116.     'w$(36) = ""
  117.     'w$(37) = ""
  118.     'w$(38) = ""
  119.     'w$(39) = ""
  120.     'w$(40) = ""
  121.     'w$(41) = ""
  122.  
  123.  

I will explore v 3.0 later when I get caught up on sleep. But I guess the patterns I see over the Eggs o Dozen is an artifact of Screen differences between QB64 in Windows and JS in HTML. It works very well by accident! No special coding did that. BTW you DIM'd radianAngle that was a parameter of the drawing Sub, fortunately for that app they were all 0's anyway. For correctness it should be replaced by a, d which are missing. BTW don't always have to have everything DIM'd though highly recommended.

 
Title: Re: QBJS - QBasic for the Web
Post by: dbox on April 03, 2022, 04:21:34 pm
By the way @bplus, the lastest version has that Cls fix, so your original game code is working as intended now:

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QIoOTS3OnWAESGGkNLo5wwJ0RJoB3iDYKAEU2NvcmUBteCX/7UNMaW5l5BMA0VNiOw4tSM2Iam6MrhN9NwqT8VWdCcGtfBrX7k+mgoSM3/a9fRmbXqbO2YJ0aGXdBmVuZW1pZXOf//lYqG0uTG2MvN7u5ZuCFywNnS2xDcFv//WgUlmyMJTcXIRMFcG2xIa4AvddjIOl4dPPBjL1LOwDztPcw1RoZW7ZVAhjb2xsaXNpb26v///7UfERGVsYXnRgC6Ff///2PD0vHo1/wDt3hpmxN0LnjEJ1I1jde8tOF/AuVLhZQ21vdmVgg3RoYXRYQmJhZHACYm95lYBDUADuXMzcoc+6J3tsEqN7evQbawtzyk+d+Mzt7eyMTyy7LsASI6W4JFbmSgB/a2tAD+zhhunaywmcerFr7FQCeXNY5YUA+TvzAN4ZR+c301fvKVqREJn8bssHfON1mytV3l7eM+qbqBlKBfs98GS2V5RG93bt//rZT+0szHrwVJlAgPMLeeISzOjtYILxMXVaYQHuvc9V8A5l/+3Mv3jLZ2aYR3vv89d61/DHbudrxCTOkwqKSoknkNffJPTDI1qRdvXyO6PETr6walVFkvmJheq/2Dm4OxYIv9ncnrNxf3DzTRkRpc3BsYXm4ee+ETGltaXRX/9+JDTG9vcEYEVW50aWx7p9eR2rTLxFNsZWVwuwg=)
Play Game (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?mode=play&qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QIoOTS3OnWAESGGkNLo5wwJ0RJoB3iDYKAEU2NvcmUBteCX/7UNMaW5l5BMA0VNiOw4tSM2Iam6MrhN9NwqT8VWdCcGtfBrX7k+mgoSM3/a9fRmbXqbO2YJ0aGXdBmVuZW1pZXOf//lYqG0uTG2MvN7u5ZuCFywNnS2xDcFv//WgUlmyMJTcXIRMFcG2xIa4AvddjIOl4dPPBjL1LOwDztPcw1RoZW7ZVAhjb2xsaXNpb26v///7UfERGVsYXnRgC6Ff///2PD0vHo1/wDt3hpmxN0LnjEJ1I1jde8tOF/AuVLhZQ21vdmVgg3RoYXRYQmJhZHACYm95lYBDUADuXMzcoc+6J3tsEqN7evQbawtzyk+d+Mzt7eyMTyy7LsASI6W4JFbmSgB/a2tAD+zhhunaywmcerFr7FQCeXNY5YUA+TvzAN4ZR+c301fvKVqREJn8bssHfON1mytV3l7eM+qbqBlKBfs98GS2V5RG93bt//rZT+0szHrwVJlAgPMLeeISzOjtYILxMXVaYQHuvc9V8A5l/+3Mv3jLZ2aYR3vv89d61/DHbudrxCTOkwqKSoknkNffJPTDI1qRdvXyO6PETr6walVFkvmJheq/2Dm4OxYIv9ncnrNxf3DzTRkRpc3BsYXm4ee+ETGltaXRX/9+JDTG9vcEYEVW50aWx7p9eR2rTLxFNsZWVwuwg=)

Hey @bplus, your falling circle game is even more epic with sound:  Play Game (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?mode=play&qbcode=JEaW0BAGxOr09QCzCNrq5tLHeDbG9zZQAKNwD2YC+hlNuZE9wZW4gFAAIrEaHR0cHPgDrQC/HCW9wZW5nYW1lYXKgHSQC6Am9yZ7cRzaXRlc0wzIyszC6tjoviMzS2MrniIbmV3YmF0dGxleITuwuzNgFMnU1+MbxBNk+AVu937N5yAYCoJvZ2cVcYCw3QZmbsYYG4eTj+PIBLoAZc9c+blmAY44IPALTBvZv8Lf7l+sGU25kTG9vcLVLpcIKC57nDTG9uZ+eBSFiFaQUhZxTgDS1ZQ2hpdHObQEc2NvcmXDliKbowuTmbKHbkVuZW1pZXM5dFSGVpZ2h0spmEIAM096qOjogBp/4cAK3KbowuTnn8k2Zn2fD6wDV2cT8/X0gHFy3esCirEWpYepBRVnBG8/cBRUMspPcdlkdVbnNpZ25lZPpeGATnyIytzK2vJUEc3R1ZmanOKpsbkysrcRfDpzK7pLaws7KjtANsce94vXAPTO9PORdIerqdFIfKdSAkZvciqLnATgqjeSmgD7DUFNldCOyEktzpRQEpNzIXYBUQG3Yh78e0/ktIYlUGn8EpI6Fv8wJdz3gFb+P2+xBODw161mGjmSYLnuezzT1VJ94acyvDpOAeOoOroktrCzsqTZIbYO+yR9PrR9qvSvGomf3IyIzrtlJbte+u/LDB/Rkl6tSdcIHeCsh4mRO/uXp7CElbaWzBd/wsvdTmYL8Utb3018etoraAURvdVeMJDbHPlURNwRgLO1SoIoOTS3OkGoBpDS6OeXBOiJCAO72FJJoimxt7kypsfyr7VH4aY0tzLOapdvGFMlz3rHofeGpujK4YbpTdecNX5YxsYztlKdjzkAFCRt1RfBw4WXIGR0FhOjQyzjGZW5lbWllc91VWQCobS5MbYy7i+IUDmLQuMpEukKbX1qqr6qCks2DBKbi5UvU3anYLe9Z0BeoZPeou36zW16FGx6FADyw91g1RoZW6ImqQxt7Y2NLm0t7dqr//+sEHU25kUGF1c2XJT////rbIym3Mig2MLzwVP///wgQiIytjC88s9P///yTr3bVzaf///jKxV7+Ds5vaBm1+TVUxNpq5OpF3tzfdzhtre7MvPA3RoYXTNYTEwsnDgmJveXCAQz////FfV59ZsE8//8AYSxzgJUb29NA21hbnlyaZuMzt7eyMTyyzTnoAAGU9v5QAAJkMjMLIyp7q6YAADgwkVuZMAASxTfAAGVzODAB/7y6AOGklG7ltJVzUV/r+ytoAlES8lksAPnLsYBv1NmxeqzdxY+oWx3ro+9fYj4qu3UIaJ/2pM3Ud+bdBKNBRroMMlsryiN7u3Z+9/zf2HMSDZQvzn0G6v3Nvw3EL2+ug2W2eKggaD1ZwTHmCgHP3e3TaEctRbTsh/NNbjzrLBfn67VajlxPSrkJj6SQ/dcaU5SdyFhTQ638XXkwOXDp7kML/eYk6jozlR3IYVRXqP5vVVWcpsX7kMPPGRGlzcGxhedBh6AiY0trS6Ke91QoaY3t7gz4RVbnRpbG32t12a5VFiKbYysrhrbhBlNuZFN0b3Bg6AAAADV4hKbqxO46DXsDrYXlNsMIncqXFAujep95sA7gt+L9aNtMnEV2lkdGiLSFWTeYw1JHQkG10l0mMkdZuLaAN+Osn9BSUug4AVMb2NhdGVj2zZo9BBUaTw0dhbWVhwae7MrlI1S3B9tuvMb)

Code: QB64: [Select]
  1. Dim buzz, music, lose
  2. music = _SndOpen("https://opengameart.org/sites/default/files/newbattle.wav")
  3. buzz = _SndOpen("https://opengameart.org/sites/default/files/buzz_0.ogg")
  4. lose = _SndOpen("https://opengameart.org/sites/default/files/lose%20music%201%20-%201_0.wav")
  5. _SndLoop music
  6. Dim As Long HX, HY, i, hits, score, Stars, nEnemies, Height
  7. HX = 320: HY = 400: nStars = 1000: nEnemies = 50: Height = 480
  8. Dim EX(nEnemies), EY(nEnemies), EC(nEnemies) As _Unsigned Long ' enemy stuff
  9. Screen _NewImage(640, Height, 32)
  10. Stars = _NewImage(640, Height, 32)
  11. For i = 1 To nStars
  12.     PSet (Int(Rnd * 640), Int(Rnd * 480)), _RGB32(55 + Rnd * 200, 55 + Rnd * 200, 55 + Rnd * 200)
  13. _PutImage , 0, Stars
  14. For i = 1 To nEnemies
  15.     EX(i) = Int(Rnd * 600 + 20): EY(i) = -2 * Height * Rnd + Height: EC(i) = _RGB32(55 + Rnd * 200, 55 + Rnd * 200, 55 + Rnd * 200)
  16.     Cls
  17.     _PutImage , Stars, 0
  18.     Print "Hits:"; hits, "Score:"; score
  19.     Line (HX - 10, HY - 10)-Step(20, 20), _RGB32(255, 255, 0), BF
  20.     For i = 1 To nEnemies ' the enemies
  21.         Circle (EX(i), EY(i)), 10, EC(i)
  22.         If Sqr((EX(i) - HX) ^ 2 + (EY(i) - HY) ^ 2) < 20 Then 'collision
  23.             _SndPause music
  24.             _SndPlay buzz
  25.             _Delay .5
  26.             hits = hits + 1
  27.             EX(i) = Int(Rnd * 600 + 20): EY(i) = -Height * Rnd ' move that bad boy!
  28.             If hits = 10 Then
  29.                 Print "Too many hits, goodbye!"
  30.                 _SndPlay lose
  31.                 FadeOut
  32.                 End
  33.             End If
  34.             _SndLoop music
  35.         End If
  36.         EY(i) = EY(i) + Int(Rnd * 5)
  37.         If EY(i) > 470 Then EX(i) = Int(Rnd * 600 + 20): EY(i) = -Height * Rnd: score = score + 1
  38.     Next
  39.     If _KeyDown(20480) Then HY = HY + 3
  40.     If _KeyDown(18432) Then HY = HY - 3
  41.     If _KeyDown(19200) Then HX = HX - 3
  42.     If _KeyDown(19712) Then HX = HX + 3
  43.     If HX < 10 Then HX = 10
  44.     If HX > 630 Then HX = 630
  45.     If HY < 10 Then HY = 10
  46.     If HY > 470 Then HY = 470
  47.     _Display
  48.     _Limit 100
  49. _SndStop music
  50.                            
  51. Sub FadeOut
  52.     _Delay 2
  53.     Dim i
  54.     For i = 1 to 100
  55.         Line (0, 0)-(_Width, _Height), _RGBA(1, 1, 1, 5), BF
  56.         _Limit 30
  57.     Next i
  58.     Locate 16, 35
  59.     Print "Game Over"
  60.  
Title: Re: QBJS - QBasic for the Web
Post by: bplus on April 03, 2022, 06:46:03 pm
Wow you are loading sounds right out of the Internet!

For some reason there seems to be either more circles or they are moving down screen faster than when I first made game. I couldn't of gotten that much older! I can barely make it across the screen 1 time, which is how the new scoring of the game is done in my versions. Remember Frogger Game?
Title: Re: QBJS - QBasic for the Web
Post by: johnno56 on April 04, 2022, 04:53:13 pm
Cool... "Now with Sound"... But got killed off quite quickly... *sigh*  I suppose I should be getting used to that by now... lol
Title: Re: QBJS - QBasic for the Web
Post by: dbox on April 06, 2022, 09:51:30 am
Recent fun discovery with QBJS... you can use data URLs to embed the content of images, sounds and other assets into the program itself.  Think of it as a web-native BIN-to-BAS.  Here's an example showing both loading an image from an external URL and from a data URL:

Code: QB64: [Select]
  1. Screen _NewImage(800, 600)
  2. Dim screenshot
  3. screenshot = _LoadImage("https://wiki.qb64.org/wiki/images/8/87/IDE_Mainscreen.png")
  4. _PutImage (1, 1), screenshot
  5.  
  6. Dim logo
  7. logo = _LoadImage("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAAAA8AXHiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGRDdGMTE3NDA3MjA2ODExODA4MzkyRDgxRTZDNzNERiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3N0Y2QjRFNjUxQjgxMUU5QkRCQUEwQjNGQjY2MzA5MyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3N0Y2QjRFNTUxQjgxMUU5QkRCQUEwQjNGQjY2MzA5MyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDc4MDExNzQwNzIwNjgxMTgwODM4RkI5NjAyMDgwMDciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RkQ3RjExNzQwNzIwNjgxMTgwODM5MkQ4MUU2QzczREYiLz4gPC9yZGY6RGVzY3Jp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")
  8. _PutImage (300, 150), logo

View in QBJS (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=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)
Title: Re: QBJS - QBasic for the Web
Post by: _vince on April 06, 2022, 06:52:24 pm
I'm very happy to have this game playable in the browser:

https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=AnKnuDo0t7cAQQF8OivDg2NLG0umAFaIUmFuZG9taXplwIqNLayuRcKiMrMmNzP4Ag+AWoBat0NUeXBlvEKTe6KTK5urY6GGUF4eJgUFz7ioje6sTYyn+gLy8/Le7CRW5kf24CRGltSFU2hhcmVkWVfiODSysbLAAo5AMXAG94BZsAMi9YBoMApsfDvtIEY29sb3J1tkeHzdeuMNzaXplV1AubvHhBc2hufzAHumFzeR0xuTr55ADVssRSZURpbdG/dpCMTewuTI81udlNbO7MyLDPAMK7trlW9fQWAddhhB1DWTH2jvbCZ5D6u29UyQvk/eO7Wxro0YRjHhopvo0YY0ny2L7tO845c+GeQROs6Z9NZuRRey99+3FTKPs+YgGf713ls++X53Sr6o7HV770hd+osdfd8uFfuRePvm+c/X5l9kobxyBw6iLowuFwwVh6qw2HaY9uwVhvHaY9wCsOxsmPbMFcbjlMe24LI4DlMe3BZHY4Jj3DBZHI4hjzDBpPE8jy5cWk9nBHl1DFqPRwx5dRxejyPNbPsSej2cO2fccno9HmNn1HJ6PE85s+xEniez22fccnkej22fccnkeZ7bPsSeZ7PTZ9xyeZ6PTZ4lk8zzPRZ4uUWWF2XTqWcWXSwXTqWcAsFiunYHArtZddO5ZwK6XNXTqWcCsVzl06A4Jdrmrp3LOCXK6q6cyzglksRdOwA4EXa7XTuWcCLldrp3XOBliu107A4KXa5XTuucFrlcrp1POC1iul07A4kXaxXTuecULlYrpzXOKVksl07A4pXa6V07rnFK5WJdOa5wJZLEunYHAl2umunNc4IuV0105rnBFiumunYAcELtdrp3XOClyu107rnBaxXa6dgcFrtcrp3XOKFyuV05rnFCxXK6dgcULtYrp3XOKFysV05rnFCxWK6d1OKF2si6dhnFK5WRdOQzilYrIundDitdrrXTuucBXKwrpzXOArFYV05pQ4DldrtdO65wQlyu107rnBfWK7XTuhwULtcrpiucFy5XK6YtnFSu65XTFDirWF3XTmucWa5XddOa5wWWKxXTuhwWXa6105DOC65XWunIZxUWKyLp3Q4qLtYV07rnAC5WFdOa5wCsVhXTulDgCgGy7Xa6d1zguVcrtdO65wAliu107ocFddrldO65wALlcrp3XOCpYrldO6HBau13XTFc4L1y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3u+8BIiz/D77fX33n7ufbXVf6LNnF9sIqNLo2Mt/F82c/rI799nI0AURvzVD/gpLNOM6E0M9oZgB9P8MxDS0JsJBbmSEGEnN7pDOhkBqjQyt2aqqGXhLiOzC2NLI4zlDOUM6Ea9QzmhC81VVVYfjhghivzVVQww0Vsc2XNVVVQz44T/mqqhmIY2c1VVD3Ph/H//xn54nuf+Jrh3Of+JXDzGFP//x5xN3EFYoLhhcPm4cT////GEzxdiODYwsbK4sLFdcNLFZp////w3ioxVn/////jFnwBwPyln/////y4l/PF3lgV/K+K4UOLEZvLTNyziwzlOzn7nWP3nVOXnRml/////wBQ8UpzL///+c/O0v//EbEUpf/+PueK84sHOTsdaX//j5nzgl//86541CX//wLn1KX//izn1L//50Z46uUv//GmKXipecVwesQLg5uCpf///iXCRm9yxBc+sIQKo34icF7l/////hY4jWfWFhxwwXuf//////iBOHZYeWz6n/////h4DTmV4dJ////gZa////ifPmv///43g2eJYXiVi/EkGciA10qzaT0HhpKMA0lDnSRDcNM1f///0yDsCo1f//SXSdf9PtO1r/p7D7Atf//B2GmNLcy7yeWBHT7QLRA6caQ6WMdMivJ5PLHjtBQkav//hv4+684beOsE7r///+lvS3rzpawNhXdf////8Bw2OF5wxbDIAeBnc4Hr//////4ZO6O8c8cHjDj/j5goAYam6Mrg4Rw/odCaD0Y4pUZ42vGp40bUu2OEPX/////UZr//////4Qd48wlqk8d6h1myqEBeM6x0PHNZ6MdapOBJwJODLHCAAhV/////wBgNf///wzV//9Qda//+GGDdOcLtev///6kYO05w96V/////4xAmFcm90YXRlwanCCcOnD54/PHFf////+LVwgjqI4fOCjgmv/////H8XDZ1cdmrhPjDu8c8Zw5wQgF0WV2Dx07h3jWzICDFhdl4CtiC9wHseJwns+LHFWqOqlOD2////4LX//8Nr3//92BAZEaXNwbGF5v//4bac3/wZgd7/4GOnDAAKlsrykNLpf/B+0fC9///Ah04dowyWyvKI3u7c1TLswL2uAp7l2Ay7VMuy6t///tDFU2VsZWN03LQ0Nhc2XhTf///+1h6D3YI4I2sAurhf/////CtyzQg4FOGzs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 (https://v6p9d9t4.ssl.hwcdn.net/html/5512918/index.html?qbcode=AnKnuDo0t7cAQQF8OivDg2NLG0umAFaIUmFuZG9taXplwIqNLayuRcKiMrMmNzP4Ag+AWoBat0NUeXBlvEKTe6KTK5urY6GGUF4eJgUFz7ioje6sTYyn+gLy8/Le7CRW5kf24CRGltSFU2hhcmVkWVfiODSysbLAAo5AMXAG94BZsAMi9YBoMApsfDvtIEY29sb3J1tkeHzdeuMNzaXplV1AubvHhBc2hufzAHumFzeR0xuTr55ADVssRSZURpbdG/dpCMTewuTI81udlNbO7MyLDPAMK7trlW9fQWAddhhB1DWTH2jvbCZ5D6u29UyQvk/eO7Wxro0YRjHhopvo0YY0ny2L7tO845c+GeQROs6Z9NZuRRey99+3FTKPs+YgGf713ls++X53Sr6o7HV770hd+osdfd8uFfuRePvm+c/X5l9kobxyBw6iLowuFwwVh6qw2HaY9uwVhvHaY9wCsOxsmPbMFcbjlMe24LI4DlMe3BZHY4Jj3DBZHI4hjzDBpPE8jy5cWk9nBHl1DFqPRwx5dRxejyPNbPsSej2cO2fccno9HmNn1HJ6PE85s+xEniez22fccnkej22fccnkeZ7bPsSeZ7PTZ9xyeZ6PTZ4lk8zzPRZ4uUWWF2XTqWcWXSwXTqWcAsFiunYHArtZddO5ZwK6XNXTqWcCsVzl06A4Jdrmrp3LOCXK6q6cyzglksRdOwA4EXa7XTuWcCLldrp3XOBliu107A4KXa5XTuucFrlcrp1POC1iul07A4kXaxXTuecULlYrpzXOKVksl07A4pXa6V07rnFK5WJdOa5wJZLEunYHAl2umunNc4IuV0105rnBFiumunYAcELtdrp3XOClyu107rnBaxXa6dgcFrtcrp3XOKFyuV05rnFCxXK6dgcULtYrp3XOKFysV05rnFCxWK6d1OKF2si6dhnFK5WRdOQzilYrIundDitdrrXTuucBXKwrpzXOArFYV05pQ4DldrtdO65wQlyu107rnBfWK7XTuhwULtcrpiucFy5XK6YtnFSu65XTFDirWF3XTmucWa5XddOa5wWWKxXTuhwWXa6105DOC65XWunIZxUWKyLp3Q4qLtYV07rnAC5WFdOa5wCsVhXTulDgCgGy7Xa6d1zguVcrtdO65wAliu107ocFddrldO65wALlcrp3XOCpYrldO6HBau13XTFc4L1y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3u+8BIiz/D77fX33n7ufbXVf6LNnF9sIqNLo2Mt/F82c/rI799nI0AURvzVD/gpLNOM6E0M9oZgB9P8MxDS0JsJBbmSEGEnN7pDOhkBqjQyt2aqqGXhLiOzC2NLI4zlDOUM6Ea9QzmhC81VVVYfjhghivzVVQww0Vsc2XNVVVQz44T/mqqhmIY2c1VVD3Ph/H//xn54nuf+Jrh3Of+JXDzGFP//x5xN3EFYoLhhcPm4cT////GEzxdiODYwsbK4sLFdcNLFZp////w3ioxVn/////jFnwBwPyln/////y4l/PF3lgV/K+K4UOLEZvLTNyziwzlOzn7nWP3nVOXnRml/////wBQ8UpzL///+c/O0v//EbEUpf/+PueK84sHOTsdaX//j5nzgl//86541CX//wLn1KX//izn1L//50Z46uUv//GmKXipecVwesQLg5uCpf///iXCRm9yxBc+sIQKo34icF7l/////hY4jWfWFhxwwXuf//////iBOHZYeWz6n/////h4DTmV4dJ////gZa////ifPmv///43g2eJYXiVi/EkGciA10qzaT0HhpKMA0lDnSRDcNM1f///0yDsCo1f//SXSdf9PtO1r/p7D7Atf//B2GmNLcy7yeWBHT7QLRA6caQ6WMdMivJ5PLHjtBQkav//hv4+684beOsE7r///+lvS3rzpawNhXdf////8Bw2OF5wxbDIAeBnc4Hr//////4ZO6O8c8cHjDj/j5goAYam6Mrg4Rw/odCaD0Y4pUZ42vGp40bUu2OEPX/////UZr//////4Qd48wlqk8d6h1myqEBeM6x0PHNZ6MdapOBJwJODLHCAAhV/////wBgNf///wzV//9Qda//+GGDdOcLtev///6kYO05w96V/////4xAmFcm90YXRlwanCCcOnD54/PHFf////+LVwgjqI4fOCjgmv/////H8XDZ1cdmrhPjDu8c8Zw5wQgF0WV2Dx07h3jWzICDFhdl4CtiC9wHseJwns+LHFWqOqlOD2////4LX//8Nr3//92BAZEaXNwbGF5v//4bac3/wZgd7/4GOnDAAKlsrykNLpf/B+0fC9///Ah04dowyWyvKI3u7c1TLswL2uAp7l2Ay7VMuy6t///tDFU2VsZWN03LQ0Nhc2XhTf///+1h6D3YI4I2sAurhf/////CtyzQg4FOGzs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)