Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Junior Librarian

Pages: [1] 2
1
Pi-in-the-Sky Graphics Demonstration

Author: @Qwerkey
Source: qb64.org Forum
URL: https://qb64forum.alephc.xyz//index.php?topic=1969.0
Version: 15/01/22

Description:
This is a program which demonstrates the amazing graphics capabilities of QB64, using simple coding techniques and without resorting to the complexities of Open_GL.  Impressive 3D effects can be obtained using the QB64 _MAPTRIANGLE statement: the 3D _MAPTRIANGLE method gives a convincing 3D display along with perspective.

The program features a number of animations (some 2D and some 3D) enhanced with accompanying audio.  There is no interaction with the user, and the running display is an entertaining series of whimsical tableaux.  The program takes about 10 minutes before repeating.


You will need to go to the URL above to download the program.



screenshot.jpg

2
Interpreters / Symbolic Instruction Code Kit by Erik Jon Oredson
« on: December 27, 2021, 11:39:43 am »
Symbolic Instruction Code Kit (S.I.C.K.) Updated 2022-01-17

Author: @eoredson (eoredson@gmail.com)
URL: https://qb64forum.alephc.xyz/index.php?topic=4500.0
Version: v64.0a r5.5a

Description:
The Symbolic Instruction Code Kit, which contains a QB64 program named SIC64.BAS
and several smaller utility programs. The source code is public domain and can be
found on several sites, including, www.filegate.net and www.keepandshare.com

This program uses a recursive descent parser to interpret a psuedo-basic language
written in a line number oriented fashion and can be used for small programming chores.

The archive also contains some further imbedded .zip files which contain several
QB64 sample programs, and some .SIC programs which are used by the SIC engine.


Source Code:
See download(s) below, or follow this link:
https://bit.ly/EriksSICK

 

Commands:
Code: QB64: [Select]
  1. ENDIF  END IF  STOP  REM  MID$  LEFT$  RIGHT$  PRINT #  DPRINT
  2.  LPRINT USING  SPRINT  UPRINT  INPUT;  FORIF  FOR  NEXTIF  NEXT  CONTINUE FORIF  CONTINUE FOR
  3.  EXIT FORIF  EXIT FOR  DO UNTIL  LOOP WHILE  EXIT DO  CONTINUE DO  GOTO  GOSUB  RETURN  DO WHILE
  4.  DO  OFF  IF  ELSEIF  CASEIF ELSE  CASEIF  SELECT CASE  END SELECTIF  BEEP  SOUND
  5.  COLOR  LOCATE  CLS  SCREEN  WIDTH  WRITE #  LINE INPUT;  LINE INPUT #  INPUT #  WEND
  6.  WHILE  CONTINUE WHILE  EXIT WHILE  ELSE  LOOP UNTIL  LOOPIF  END LOOPIF  EXIT LOOPIF  LOOP  RANDOMIZE
  7.  POKE  INT86  DEFSEG  ABSOLUTE  OUT  WAIT  SLEEP  PAUSE  SELECTIF CASE  END SELECT
  8.  CASE ELSE  CASE  CONTINUE LOOPIF  END  CLEAR  SYSTEM  SWAP  ERROR  ON ERROR GOTO  ON ERROR RESUME PREVIOUS
  9.  ON ERROR RESUME SAME  ON ERROR RESUME NEXT  ON ERROR STOP  RESUME PREVIOUS  RESUME SAME  RESUME NEXT  RESUME  ON  DATE$  TIME$
  10.  CHDRIVE  CD  CHDIR  MD  MKDIR  RD  RMDIR  KILL  DELETE  RENAME
  11.  NAME  SHELL  CHAIN  LET  CLOSE #  OPEN #  FIELD #  WRITE  PRINT USING  INPUT
  12.  LINE INPUT  LSET #  RSET #  PUT #  GET #  READ #  DATA  READ  RESTORE  CIRCLE STEP
  13.  PSET  PRESET  GET  PUT  DIM  COMMON  DECLARE  LOCK #  UNLOCK #  PRINT
  14.  LPRINT  TRIANGLE  POLYGON

SICK.png


3
Embedding files in programs (FileToDATA convertor)

Author: @RhoSigma
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=790.0
Version: October 04 2021


Description:
These two programs I use a lot.  These goodies got an complete overhaul and are now using the LZW packer/unpacker, which I've released. So this is a good opportunity to make it available again for everybody.  MakeDATA.bas Create a DATA block out of the given file, so you can embed it in your program and write it back when needed.  The DATAs are written into a .bm file.   MakeCARR.bas will do the whole thing in an array on C/C++ level, rather then in DATAs on the QB64 level. Although it's handling is a bit more tricky, as you get not only a .bm file, but also a .h file, and both must match (ie. the DECLARE LIBRARY path in the .bm must point to the .h), this approach has several advantages.

Both of the following tools require the 'lzwpacker.bm' file.


The .bm file is to be found in the author's Libraries Collection https://www.qb64.org/forum/index.php?topic=809

Source Code MakeDATA.bas:
Code: QB64: [Select]
  1.     '+---------------+---------------------------------------------------+
  2.     '| ###### ###### |     .--. .         .-.                            |
  3.     '| ##  ## ##   # |     |   )|        (   ) o                         |
  4.     '| ##  ##  ##    |     |--' |--. .-.  `-.  .  .-...--.--. .-.        |
  5.     '| ######   ##   |     |  \ |  |(   )(   ) | (   ||  |  |(   )       |
  6.     '| ##      ##    |     '   `'  `-`-'  `-'-' `-`-`|'  '  `-`-'`-      |
  7.     '| ##     ##   # |                            ._.'                   |
  8.     '| ##     ###### |  Sources & Documents placed in the Public Domain. |
  9.     '+---------------+---------------------------------------------------+
  10.     '|                                                                   |
  11.     '| === MakeDATA.bas ===                                              |
  12.     '|                                                                   |
  13.     '| == Create a DATA block out of the given file, so you can embed it |
  14.     '| == in your program and write it back when needed.                 |
  15.     '|                                                                   |
  16.     '| == The DATAs are written into a .bm file together with a ready to |
  17.     '| == use write back FUNCTION. You just $INCLUDE this .bm file into  |
  18.     '| == your program and call the write back FUNCTION somewhere.       |
  19.     '|                                                                   |
  20.     '| == This program needs the 'lzwpacker.bm' file available from the  |
  21.     '| == Libraries Collection here:                                     |
  22.     '| ==      https://www.qb64.org/forum/index.php?topic=809            |
  23.     '| == as it will try to pack the given file to keep the DATA block   |
  24.     '| == as small as possible. If compression is successful, then your  |
  25.     '| == program also must $INCLUDE 'lzwpacker.bm' to be able to unpack |
  26.     '| == the file data again for write back. MakeDATA.bas is printing   |
  27.     '| == a reminder message in such a case.                             |
  28.     '|                                                                   |
  29.     '+-------------------------------------------------------------------+
  30.     '| Done by RhoSigma, R.Heyder, provided AS IS, use at your own risk. |
  31.     '| Find me in the QB64 Forum or mail to support&rhosigma-cw.net for  |
  32.     '| any questions or suggestions. Thanx for your interest in my work. |
  33.     '+-------------------------------------------------------------------+
  34.      
  35.     '--- if you wish, set any default paths, end with a backslash ---
  36.     srcPath$ = "" 'source path
  37.     tarPath$ = "" 'target path
  38.     '-----
  39.     IF srcPath$ <> "" THEN
  40.         COLOR 15: PRINT "Default source path: ": COLOR 7: PRINT srcPath$: PRINT
  41.     END IF
  42.     IF tarPath$ <> "" THEN
  43.         COLOR 15: PRINT "Default target path: ": COLOR 7: PRINT tarPath$: PRINT
  44.     END IF
  45.      
  46.     '--- collect inputs (relative paths allowed, based on default paths) ---
  47.     source:
  48.     LINE INPUT "Source Filename: "; src$ 'any file you want to put into DATAs
  49.     IF src$ = "" GOTO source
  50.     target:
  51.     LINE INPUT "Target Basename: "; tar$ 'write stuff into this file (.bm is added)
  52.     IF tar$ = "" GOTO target
  53.     '-----
  54.     ON ERROR GOTO abort
  55.     OPEN "I", #1, srcPath$ + src$: CLOSE #1 'file exist check
  56.     OPEN "O", #2, tarPath$ + tar$ + ".bm": CLOSE #2 'path exist check
  57.     ON ERROR GOTO 0
  58.      
  59.     '--- separate source filename part ---
  60.     FOR po% = LEN(src$) TO 1 STEP -1
  61.         IF MID$(src$, po%, 1) = "\" OR MID$(src$, po%, 1) = "/" THEN
  62.             srcName$ = MID$(src$, po% + 1)
  63.             EXIT FOR
  64.         ELSEIF po% = 1 THEN
  65.             srcName$ = src$
  66.         END IF
  67.     NEXT po%
  68.     '--- separate target filename part ---
  69.     FOR po% = LEN(tar$) TO 1 STEP -1
  70.         IF MID$(tar$, po%, 1) = "\" OR MID$(tar$, po%, 1) = "/" THEN
  71.             tarName$ = MID$(tar$, po% + 1)
  72.             EXIT FOR
  73.         ELSEIF po% = 1 THEN
  74.             tarName$ = tar$
  75.         END IF
  76.     NEXT po%
  77.     MID$(tarName$, 1, 1) = UCASE$(MID$(tarName$, 1, 1)) 'capitalize 1st letter
  78.      
  79.     '--- init ---
  80.     OPEN "B", #1, srcPath$ + src$
  81.     filedata$ = SPACE$(LOF(1))
  82.     GET #1, , filedata$
  83.     CLOSE #1
  84.     rawdata$ = LzwPack$(filedata$, 20)
  85.     IF rawdata$ <> "" THEN
  86.         OPEN "O", #1, tarPath$ + tar$ + ".lzw"
  87.         CLOSE #1
  88.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  89.         PUT #1, , rawdata$
  90.         CLOSE #1
  91.         packed% = -1
  92.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  93.     ELSE
  94.         packed% = 0
  95.         OPEN "B", #1, srcPath$ + src$
  96.     END IF
  97.     fl& = LOF(1)
  98.     cntL& = INT(fl& / 32)
  99.     cntB& = (fl& - (cntL& * 32))
  100.      
  101.     '--- .bm include file ---
  102.     OPEN "O", #2, tarPath$ + tar$ + ".bm"
  103.     PRINT #2, "'============================================================"
  104.     PRINT #2, "'=== This file was created with MakeDATA.bas by RhoSigma, ==="
  105.     PRINT #2, "'=== you must $INCLUDE this at the end of your program.   ==="
  106.     IF packed% THEN
  107.         PRINT #2, "'=== ---------------------------------------------------- ==="
  108.         PRINT #2, "'=== If your program is NOT a GuiTools based application, ==="
  109.         PRINT #2, "'=== then it must also $INCLUDE: 'lzwpacker.bm' available ==="
  110.         PRINT #2, "'=== from the Libraries Collection here:                  ==="
  111.         PRINT #2, "'===    https://www.qb64.org/forum/index.php?topic=809    ==="
  112.     END IF
  113.     PRINT #2, "'============================================================"
  114.     PRINT #2, ""
  115.     '--- writeback function ---
  116.     PRINT #2, "'"; STRING$(LEN(tarName$) + 18, "-")
  117.     PRINT #2, "'--- Write"; tarName$; "Data$ ---"
  118.     PRINT #2, "'"; STRING$(LEN(tarName$) + 18, "-")
  119.     PRINT #2, "' This function will write the DATAs you've created with MakeDATA.bas"
  120.     PRINT #2, "' back to disk and so it rebuilds the original file."
  121.     PRINT #2, "'"
  122.     PRINT #2, "' After the writeback call, only use the returned realFile$ to access the"
  123.     PRINT #2, "' written file. It's your given path, but with an maybe altered filename"
  124.     PRINT #2, "' (number added) in order to avoid the overwriting of an already existing"
  125.     PRINT #2, "' file with the same name in the given location."
  126.     PRINT #2, "'----------"
  127.     PRINT #2, "' SYNTAX:"
  128.     PRINT #2, "'   realFile$ = Write"; tarName$; "Data$ (wantFile$)"
  129.     PRINT #2, "'----------"
  130.     PRINT #2, "' INPUTS:"
  131.     PRINT #2, "'   --- wantFile$ ---"
  132.     PRINT #2, "'    The filename you would like to write the DATAs to, can contain"
  133.     PRINT #2, "'    a full or relative path."
  134.     PRINT #2, "'----------"
  135.     PRINT #2, "' RESULT:"
  136.     PRINT #2, "'   --- realFile$ ---"
  137.     PRINT #2, "'    - On success this is the path and filename finally used after all"
  138.     PRINT #2, "'      applied checks, use only this returned filename to access the"
  139.     PRINT #2, "'      written file."
  140.     PRINT #2, "'    - On failure this function will panic with the appropriate runtime"
  141.     PRINT #2, "'      error code which you may trap and handle as needed with your own"
  142.     PRINT #2, "'      ON ERROR GOTO... handler."
  143.     PRINT #2, "'---------------------------------------------------------------------"
  144.     PRINT #2, "FUNCTION Write"; tarName$; "Data$ (file$)"
  145.     PRINT #2, "'--- option _explicit requirements ---"
  146.     PRINT #2, "DIM po%, body$, ext$, num%, numL&, numB&, rawdata$, stroffs&, i&, dat&, ff%";
  147.     IF packed% THEN PRINT #2, ", filedata$": ELSE PRINT #2, ""
  148.     PRINT #2, "'--- separate filename body & extension ---"
  149.     PRINT #2, "FOR po% = LEN(file$) TO 1 STEP -1"
  150.     PRINT #2, "    IF MID$(file$, po%, 1) = "; CHR$(34); "."; CHR$(34); " THEN"
  151.     PRINT #2, "        body$ = LEFT$(file$, po% - 1)"
  152.     PRINT #2, "        ext$ = MID$(file$, po%)"
  153.     PRINT #2, "        EXIT FOR"
  154.     PRINT #2, "    ELSEIF MID$(file$, po%, 1) = "; CHR$(34); "\"; CHR$(34); " OR MID$(file$, po%, 1) = "; CHR$(34); "/"; CHR$(34); " OR po% = 1 THEN"
  155.     PRINT #2, "        body$ = file$"
  156.     PRINT #2, "        ext$ = "; CHR$(34); CHR$(34)
  157.     PRINT #2, "        EXIT FOR"
  158.     PRINT #2, "    END IF"
  159.     PRINT #2, "NEXT po%"
  160.     PRINT #2, "'--- avoid overwriting of existing files ---"
  161.     PRINT #2, "num% = 1"
  162.     PRINT #2, "WHILE _FILEEXISTS(file$)"
  163.     PRINT #2, "    file$ = body$ + "; CHR$(34); "("; CHR$(34); " + LTRIM$(STR$(num%)) + "; CHR$(34); ")"; CHR$(34); " + ext$"
  164.     PRINT #2, "    num% = num% + 1"
  165.     PRINT #2, "WEND"
  166.     PRINT #2, "'--- write DATAs ---"
  167.     PRINT #2, "RESTORE "; tarName$
  168.     PRINT #2, "READ numL&, numB&"
  169.     PRINT #2, "rawdata$ = SPACE$((numL& * 4) + numB&)"
  170.     PRINT #2, "stroffs& = 1"
  171.     PRINT #2, "FOR i& = 1 TO numL&"
  172.     PRINT #2, "    READ dat&"
  173.     PRINT #2, "    MID$(rawdata$, stroffs&, 4) = MKL$(dat&)"
  174.     PRINT #2, "    stroffs& = stroffs& + 4"
  175.     PRINT #2, "NEXT i&"
  176.     PRINT #2, "IF numB& > 0 THEN"
  177.     PRINT #2, "    FOR i& = 1 TO numB&"
  178.     PRINT #2, "        READ dat&"
  179.     PRINT #2, "        MID$(rawdata$, stroffs&, 1) = CHR$(dat&)"
  180.     PRINT #2, "        stroffs& = stroffs& + 1"
  181.     PRINT #2, "    NEXT i&"
  182.     PRINT #2, "END IF"
  183.     PRINT #2, "ff% = FREEFILE"
  184.     PRINT #2, "OPEN file$ FOR OUTPUT AS ff%"
  185.     IF packed% THEN
  186.         PRINT #2, "CLOSE ff%"
  187.         PRINT #2, "filedata$ = LzwUnpack$(rawdata$)"
  188.         PRINT #2, "OPEN file$ FOR BINARY AS ff%"
  189.         PRINT #2, "PUT #ff%, , filedata$"
  190.     ELSE
  191.         PRINT #2, "PRINT #ff%, rawdata$;"
  192.     END IF
  193.     PRINT #2, "CLOSE ff%"
  194.     PRINT #2, "'--- set result ---"
  195.     PRINT #2, "Write"; tarName$; "Data$ = file$"
  196.     PRINT #2, "EXIT FUNCTION"
  197.     PRINT #2, ""
  198.     PRINT #2, "'--- DATAs representing the contents of file "; srcName$
  199.     PRINT #2, "'---------------------------------------------------------------------"
  200.     PRINT #2, tarName$; ":"
  201.     '--- read LONGs ---
  202.     PRINT #2, "DATA "; LTRIM$(STR$(cntL& * 8)); ","; LTRIM$(STR$(cntB&))
  203.     tmpI$ = SPACE$(32)
  204.     FOR z& = 1 TO cntL&
  205.         GET #1, , tmpI$: offI% = 1
  206.         tmpO$ = "DATA " + STRING$(87, ","): offO% = 6
  207.         DO
  208.             tmpL& = CVL(MID$(tmpI$, offI%, 4)): offI% = offI% + 4
  209.             MID$(tmpO$, offO%, 10) = "&H" + RIGHT$("00000000" + HEX$(tmpL&), 8)
  210.             offO% = offO% + 11
  211.         LOOP UNTIL offO% > 92
  212.         PRINT #2, tmpO$
  213.     NEXT z&
  214.     '--- read remaining BYTEs ---
  215.     IF cntB& > 0 THEN
  216.         PRINT #2, "DATA ";
  217.         FOR x% = 1 TO cntB&
  218.             GET #1, , tmpB%%
  219.             PRINT #2, "&H" + RIGHT$("00" + HEX$(tmpB%%), 2);
  220.             IF x% <> 16 THEN
  221.                 IF x% <> cntB& THEN PRINT #2, ",";
  222.             ELSE
  223.                 IF x% <> cntB& THEN
  224.                     PRINT #2, ""
  225.                     PRINT #2, "DATA ";
  226.                 END IF
  227.             END IF
  228.         NEXT x%
  229.         PRINT #2, ""
  230.     END IF
  231.     PRINT #2, "END FUNCTION"
  232.     PRINT #2, ""
  233.     '--- ending ---
  234.     CLOSE #2
  235.     CLOSE #1
  236.      
  237.     '--- finish message ---
  238.     COLOR 10: PRINT: PRINT "file successfully processed..."
  239.     COLOR 9: PRINT: PRINT "You must $INCLUDE the created file (target name + .bm extension) at"
  240.     PRINT "the end of your program and call the function 'Write"; tarName$; "Data$(...)'"
  241.     PRINT "in an appropriate place to write the file back to disk."
  242.     IF packed% THEN
  243.         COLOR 12: PRINT: PRINT "Your program must also $INCLUDE 'lzwpacker.bm' available from"
  244.         PRINT "the Libraries Collection here:"
  245.         PRINT "     https://www.qb64.org/forum/index.php?topic=809"
  246.         PRINT "to be able to write back the just processed file."
  247.         KILL tarPath$ + tar$ + ".lzw"
  248.     END IF
  249.     done:
  250.     COLOR 7
  251.     END
  252.     '--- error handler ---
  253.     abort:
  254.     COLOR 12: PRINT: PRINT "something is wrong with path/file access, check your inputs and try again..."
  255.     RESUME done
  256.      
  257.     '$INCLUDE: 'QB64Library\LZW-Compress\lzwpacker.bm'
  258.      
  259.      
  260.  


Source Code MakeCARR.bas:
Code: QB64: [Select]
  1.     '+---------------+---------------------------------------------------+
  2.     '| ###### ###### |     .--. .         .-.                            |
  3.     '| ##  ## ##   # |     |   )|        (   ) o                         |
  4.     '| ##  ##  ##    |     |--' |--. .-.  `-.  .  .-...--.--. .-.        |
  5.     '| ######   ##   |     |  \ |  |(   )(   ) | (   ||  |  |(   )       |
  6.     '| ##      ##    |     '   `'  `-`-'  `-'-' `-`-`|'  '  `-`-'`-      |
  7.     '| ##     ##   # |                            ._.'                   |
  8.     '| ##     ###### |  Sources & Documents placed in the Public Domain. |
  9.     '+---------------+---------------------------------------------------+
  10.     '|                                                                   |
  11.     '| === MakeCARR.bas ===                                              |
  12.     '|                                                                   |
  13.     '| == Create a C/C++ array out of the given file, so you can embed   |
  14.     '| == it in your program and write it back when needed.              |
  15.     '|                                                                   |
  16.     '| == Two files are created, the .h file, which contains the array(s)|
  17.     '| == and some functions, and a respective .bm file which needs to   |
  18.     '| == be $INCLUDEd with your program and does provide the FUNCTION   |
  19.     '| == to write back the array(s) into any file. All used functions   |
  20.     '| == are standard library calls, no API calls are involved, so the  |
  21.     '| == writeback should work on all QB64 supported platforms.         |
  22.     '|                                                                   |
  23.     '| == Make sure to adjust the path for the .h file for your personal |
  24.     '| == needs in the created .bm files (DECLARE LIBRARY), if required. |
  25.     '| == You may specify default paths right below this header.         |
  26.     '|                                                                   |
  27.     '| == This program needs the 'lzwpacker.bm' file available from the  |
  28.     '| == Libraries Collection here:                                     |
  29.     '| ==      https://www.qb64.org/forum/index.php?topic=809            |
  30.     '| == as it will try to pack the given file to keep the array(s) as  |
  31.     '| == small as possible. If compression is successful, then your     |
  32.     '| == program also must $INCLUDE 'lzwpacker.bm' to be able to unpack |
  33.     '| == the file data again for write back. MakeCARR.bas is printing   |
  34.     '| == a reminder message in such a case.                             |
  35.     '|                                                                   |
  36.     '+-------------------------------------------------------------------+
  37.     '| Done by RhoSigma, R.Heyder, provided AS IS, use at your own risk. |
  38.     '| Find me in the QB64 Forum or mail to support&rhosigma-cw.net for  |
  39.     '| any questions or suggestions. Thanx for your interest in my work. |
  40.     '+-------------------------------------------------------------------+
  41.      
  42.     '--- if you wish, set any default paths, end with a backslash ---
  43.     srcPath$ = "" 'source path
  44.     tarPath$ = "" 'target path
  45.     '-----
  46.     IF srcPath$ <> "" THEN
  47.         COLOR 15: PRINT "Default source path: ": COLOR 7: PRINT srcPath$: PRINT
  48.     END IF
  49.     IF tarPath$ <> "" THEN
  50.         COLOR 15: PRINT "Default target path: ": COLOR 7: PRINT tarPath$: PRINT
  51.     END IF
  52.      
  53.     '--- collect inputs (relative paths allowed, based on default paths) ---
  54.     source:
  55.     LINE INPUT "Source Filename: "; src$ 'any file you want to put into a C/C++ array
  56.     IF src$ = "" GOTO source
  57.     target:
  58.     LINE INPUT "Target Basename: "; tar$ 'write stuff into this file(s) (.h/.bm is added)
  59.     IF tar$ = "" GOTO target
  60.     '-----
  61.     ON ERROR GOTO abort
  62.     OPEN "I", #1, srcPath$ + src$: CLOSE #1 'file exist check
  63.     OPEN "O", #2, tarPath$ + tar$ + ".bm": CLOSE #2 'path exist check
  64.     ON ERROR GOTO 0
  65.      
  66.     '--- separate source filename part ---
  67.     FOR po% = LEN(src$) TO 1 STEP -1
  68.         IF MID$(src$, po%, 1) = "\" OR MID$(src$, po%, 1) = "/" THEN
  69.             srcName$ = MID$(src$, po% + 1)
  70.             EXIT FOR
  71.         ELSEIF po% = 1 THEN
  72.             srcName$ = src$
  73.         END IF
  74.     NEXT po%
  75.     '--- separate target filename part ---
  76.     FOR po% = LEN(tar$) TO 1 STEP -1
  77.         IF MID$(tar$, po%, 1) = "\" OR MID$(tar$, po%, 1) = "/" THEN
  78.             tarName$ = MID$(tar$, po% + 1)
  79.             EXIT FOR
  80.         ELSEIF po% = 1 THEN
  81.             tarName$ = tar$
  82.         END IF
  83.     NEXT po%
  84.     MID$(tarName$, 1, 1) = UCASE$(MID$(tarName$, 1, 1)) 'capitalize 1st letter
  85.      
  86.     '---------------------------------------------------------------------
  87.     ' Depending on the source file's size, one or more array(s) are
  88.     ' created. This is because some C/C++ compilers seem to have problems
  89.     ' with arrays with more than 65535 elements. This does not affect the
  90.     ' write back, as the write function will take this behavior into account.
  91.     '---------------------------------------------------------------------
  92.      
  93.     '--- init ---
  94.     OPEN "B", #1, srcPath$ + src$
  95.     filedata$ = SPACE$(LOF(1))
  96.     GET #1, , filedata$
  97.     CLOSE #1
  98.     rawdata$ = LzwPack$(filedata$, 20)
  99.     IF rawdata$ <> "" THEN
  100.         OPEN "O", #1, tarPath$ + tar$ + ".lzw"
  101.         CLOSE #1
  102.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  103.         PUT #1, , rawdata$
  104.         CLOSE #1
  105.         packed% = -1
  106.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  107.     ELSE
  108.         packed% = 0
  109.         OPEN "B", #1, srcPath$ + src$
  110.     END IF
  111.     fl& = LOF(1)
  112.     cntL& = INT(fl& / 32)
  113.     cntV& = INT(cntL& / 8180)
  114.     cntB& = (fl& - (cntL& * 32))
  115.      
  116.     '--- .h include file ---
  117.     OPEN "O", #2, tarPath$ + tar$ + ".h"
  118.     PRINT #2, "// ============================================================"
  119.     PRINT #2, "// === This file was created with MakeCARR.bas by RhoSigma, ==="
  120.     PRINT #2, "// === use it in conjunction with its respective .bm file.  ==="
  121.     PRINT #2, "// ============================================================"
  122.     PRINT #2, ""
  123.     PRINT #2, "// --- Array(s) representing the contents of file "; srcName$
  124.     PRINT #2, "// ---------------------------------------------------------------------"
  125.     '--- read LONGs ---
  126.     tmpI$ = SPACE$(32)
  127.     FOR vc& = 0 TO cntV&
  128.         IF vc& = cntV& THEN numL& = (cntL& MOD 8180): ELSE numL& = 8180
  129.         PRINT #2, "static const unsigned int32 "; tarName$; "L"; LTRIM$(STR$(vc&)); "[] = {"
  130.         PRINT #2, "    "; LTRIM$(STR$(numL& * 8)); ","
  131.         FOR z& = 1 TO numL&
  132.             GET #1, , tmpI$: offI% = 1
  133.             tmpO$ = "    " + STRING$(88, ","): offO% = 5
  134.             DO
  135.                 tmpL& = CVL(MID$(tmpI$, offI%, 4)): offI% = offI% + 4
  136.                 MID$(tmpO$, offO%, 10) = "0x" + RIGHT$("00000000" + HEX$(tmpL&), 8)
  137.                 offO% = offO% + 11
  138.             LOOP UNTIL offO% > 92
  139.             IF z& < numL& THEN PRINT #2, tmpO$: ELSE PRINT #2, LEFT$(tmpO$, 91)
  140.         NEXT z&
  141.         PRINT #2, "};"
  142.         PRINT #2, ""
  143.     NEXT vc&
  144.     '--- read remaining BYTEs ---
  145.     IF cntB& > 0 THEN
  146.         PRINT #2, "static const unsigned int8 "; tarName$; "B[] = {"
  147.         PRINT #2, "    "; LTRIM$(STR$(cntB&)); ","
  148.         PRINT #2, "    ";
  149.         FOR x% = 1 TO cntB&
  150.             GET #1, , tmpB%%
  151.             PRINT #2, "0x" + RIGHT$("00" + HEX$(tmpB%%), 2);
  152.             IF x% <> 16 THEN
  153.                 IF x% <> cntB& THEN PRINT #2, ",";
  154.             ELSE
  155.                 IF x% <> cntB& THEN
  156.                     PRINT #2, ","
  157.                     PRINT #2, "    ";
  158.                 END IF
  159.             END IF
  160.         NEXT x%
  161.         PRINT #2, ""
  162.         PRINT #2, "};"
  163.         PRINT #2, ""
  164.     END IF
  165.     '--- some functions ---
  166.     PRINT #2, "// --- Saved full qualified output path and filename, so we've no troubles"
  167.     PRINT #2, "// --- when cleaning up, even if the current working folder was changed"
  168.     PRINT #2, "// --- during program runtime."
  169.     PRINT #2, "// ---------------------------------------------------------------------"
  170.     PRINT #2, "char "; tarName$; "Name[8192]; // it's a safe size for any current OS"
  171.     PRINT #2, ""
  172.     PRINT #2, "// --- Cleanup function to delete the written file, called by the atexit()"
  173.     PRINT #2, "// --- handler at program termination time, if requested by user."
  174.     PRINT #2, "// ---------------------------------------------------------------------"
  175.     PRINT #2, "void Kill"; tarName$; "Data(void)"
  176.     PRINT #2, "{"
  177.     PRINT #2, "    remove("; tarName$; "Name);"
  178.     PRINT #2, "}"
  179.     PRINT #2, ""
  180.     PRINT #2, "// --- Function to write the array(s) back into a file, will return the"
  181.     PRINT #2, "// --- full qualified output path and filename on success, otherwise an"
  182.     PRINT #2, "// --- empty string is returned (access/write errors, file truncated)."
  183.     PRINT #2, "// ---------------------------------------------------------------------"
  184.     PRINT #2, "const char *Write"; tarName$; "Data(const char *FileName, int16 AutoClean)"
  185.     PRINT #2, "{"
  186.     PRINT #2, "    FILE *han = NULL; // file handle"
  187.     PRINT #2, "    int32 num = NULL; // written elements"
  188.     PRINT #2, ""
  189.     PRINT #2, "    #ifdef QB64_WINDOWS"
  190.     PRINT #2, "    if (!_fullpath("; tarName$; "Name, FileName, 8192)) return "; CHR$(34); CHR$(34); ";"
  191.     PRINT #2, "    #else"
  192.     PRINT #2, "    if (!realpath(FileName, "; tarName$; "Name)) return "; CHR$(34); CHR$(34); ";"
  193.     PRINT #2, "    #endif"
  194.     PRINT #2, ""
  195.     PRINT #2, "    if (!(han = fopen("; tarName$; "Name, "; CHR$(34); "wb"; CHR$(34); "))) return "; CHR$(34); CHR$(34); ";"
  196.     PRINT #2, "    if (AutoClean) atexit(Kill"; tarName$; "Data);"
  197.     PRINT #2, ""
  198.     FOR vc& = 0 TO cntV&
  199.         PRINT #2, "    num = fwrite(&"; tarName$; "L"; LTRIM$(STR$(vc&)); "[1], 4, "; tarName$; "L"; LTRIM$(STR$(vc&)); "[0], han);"
  200.         PRINT #2, "    if (num != "; tarName$; "L"; LTRIM$(STR$(vc&)); "[0]) {fclose(han); return "; CHR$(34); CHR$(34); ";}"
  201.         PRINT #2, ""
  202.     NEXT vc&
  203.     IF cntB& > 0 THEN
  204.         PRINT #2, "    num = fwrite(&"; tarName$; "B[1], 1, "; tarName$; "B[0], han);"
  205.         PRINT #2, "    if (num != "; tarName$; "B[0]) {fclose(han); return "; CHR$(34); CHR$(34); ";}"
  206.         PRINT #2, ""
  207.     END IF
  208.     PRINT #2, "    fclose(han);"
  209.     PRINT #2, "    return "; tarName$; "Name;"
  210.     PRINT #2, "}"
  211.     PRINT #2, ""
  212.     '--- ending ---
  213.     CLOSE #2
  214.     CLOSE #1
  215.      
  216.     '--- .bm include file ---
  217.     OPEN "O", #2, tarPath$ + tar$ + ".bm"
  218.     PRINT #2, "'============================================================"
  219.     PRINT #2, "'=== This file was created with MakeCARR.bas by RhoSigma, ==="
  220.     PRINT #2, "'=== you must $INCLUDE this at the end of your program.   ==="
  221.     IF packed% THEN
  222.         PRINT #2, "'=== ---------------------------------------------------- ==="
  223.         PRINT #2, "'=== If your program is NOT a GuiTools based application, ==="
  224.         PRINT #2, "'=== then it must also $INCLUDE: 'lzwpacker.bm' available ==="
  225.         PRINT #2, "'=== from the Libraries Collection here:                  ==="
  226.         PRINT #2, "'===    https://www.qb64.org/forum/index.php?topic=809    ==="
  227.     END IF
  228.     PRINT #2, "'============================================================"
  229.     PRINT #2, ""
  230.     PRINT #2, "'-----------------"
  231.     PRINT #2, "'--- Important ---"
  232.     PRINT #2, "'-----------------"
  233.     PRINT #2, "' If you need to move around this .bm file and its respective .h file"
  234.     PRINT #2, "' to fit in your project, then make sure the path in the DECLARE LIBRARY"
  235.     PRINT #2, "' statement below does match the actual .h file location. It's best to"
  236.     PRINT #2, "' specify a relative path assuming your QB64 installation folder as root."
  237.     PRINT #2, "'---------------------------------------------------------------------"
  238.     PRINT #2, ""
  239.     '--- writeback function ---
  240.     PRINT #2, "'"; STRING$(LEN(tarName$) + 19, "-")
  241.     PRINT #2, "'--- Write"; tarName$; "Array$ ---"
  242.     PRINT #2, "'"; STRING$(LEN(tarName$) + 19, "-")
  243.     PRINT #2, "' This function will write the array(s) you've created with MakeCARR.bas"
  244.     PRINT #2, "' back to disk and so it rebuilds the original file."
  245.     PRINT #2, "'"
  246.     PRINT #2, "' After the writeback call, only use the returned realFile$ to access the"
  247.     PRINT #2, "' written file. It's the full qualified absolute path and filename, which"
  248.     PRINT #2, "' is made by expanding your maybe given relative path and an maybe altered"
  249.     PRINT #2, "' filename (number added) in order to avoid the overwriting of an already"
  250.     PRINT #2, "' existing file with the same name in the given location. By this means"
  251.     PRINT #2, "' you'll always have safe access to the file, no matter how your current"
  252.     PRINT #2, "' working folder changes during runtime."
  253.     PRINT #2, "'"
  254.     PRINT #2, "' If you wish, the written file can automatically be deleted for you when"
  255.     PRINT #2, "' your program will end, so you don't need to do the cleanup yourself."
  256.     PRINT #2, "'----------"
  257.     PRINT #2, "' SYNTAX:"
  258.     PRINT #2, "'   realFile$ = Write"; tarName$; "Array$ (wantFile$, autoDel%)"
  259.     PRINT #2, "'----------"
  260.     PRINT #2, "' INPUTS:"
  261.     PRINT #2, "'   --- wantFile$ ---"
  262.     PRINT #2, "'    The filename you would like to write the array(s) to, can contain"
  263.     PRINT #2, "'    a full or relative path."
  264.     PRINT #2, "'   --- autoDel% ---"
  265.     PRINT #2, "'    Shows whether you want the auto cleanup (see description above) at"
  266.     PRINT #2, "'    the program end or not (-1 = delete file, 0 = don't delete file)."
  267.     PRINT #2, "'----------"
  268.     PRINT #2, "' RESULT:"
  269.     PRINT #2, "'   --- realFile$ ---"
  270.     PRINT #2, "'    - On success this is the full qualified path and filename finally"
  271.     PRINT #2, "'      used after all applied checks, use only this returned filename"
  272.     PRINT #2, "'      to access the written file."
  273.     PRINT #2, "'    - On failure (write/access) this will be an empty string, so you"
  274.     PRINT #2, "'      should check for this before trying to access/open the file."
  275.     PRINT #2, "'---------------------------------------------------------------------"
  276.     PRINT #2, "FUNCTION Write"; tarName$; "Array$ (file$, clean%)"
  277.     PRINT #2, "'--- declare C/C++ function ---"
  278.     PRINT #2, "DECLARE LIBRARY "; CHR$(34); tarPath$; tar$; CHR$(34); " 'Do not add .h here !!"
  279.     PRINT #2, "    FUNCTION Write"; tarName$; "Data$ (FileName$, BYVAL AutoClean%)"
  280.     PRINT #2, "END DECLARE"
  281.     PRINT #2, "'--- option _explicit requirements ---"
  282.     PRINT #2, "DIM po%, body$, ext$, num%";
  283.     IF packed% THEN PRINT #2, ", real$, ff%, rawdata$, filedata$": ELSE PRINT #2, ""
  284.     PRINT #2, "'--- separate filename body & extension ---"
  285.     PRINT #2, "FOR po% = LEN(file$) TO 1 STEP -1"
  286.     PRINT #2, "    IF MID$(file$, po%, 1) = "; CHR$(34); "."; CHR$(34); " THEN"
  287.     PRINT #2, "        body$ = LEFT$(file$, po% - 1)"
  288.     PRINT #2, "        ext$ = MID$(file$, po%)"
  289.     PRINT #2, "        EXIT FOR"
  290.     PRINT #2, "    ELSEIF MID$(file$, po%, 1) = "; CHR$(34); "\"; CHR$(34); " OR MID$(file$, po%, 1) = "; CHR$(34); "/"; CHR$(34); " OR po% = 1 THEN"
  291.     PRINT #2, "        body$ = file$"
  292.     PRINT #2, "        ext$ = "; CHR$(34); CHR$(34)
  293.     PRINT #2, "        EXIT FOR"
  294.     PRINT #2, "    END IF"
  295.     PRINT #2, "NEXT po%"
  296.     PRINT #2, "'--- avoid overwriting of existing files ---"
  297.     PRINT #2, "num% = 1"
  298.     PRINT #2, "WHILE _FILEEXISTS(file$)"
  299.     PRINT #2, "    file$ = body$ + "; CHR$(34); "("; CHR$(34); " + LTRIM$(STR$(num%)) + "; CHR$(34); ")"; CHR$(34); " + ext$"
  300.     PRINT #2, "    num% = num% + 1"
  301.     PRINT #2, "WEND"
  302.     PRINT #2, "'--- write array & set result ---"
  303.     IF NOT packed% THEN
  304.         PRINT #2, "Write"; tarName$; "Array$ = Write"; tarName$; "Data$(file$ + CHR$(0), clean%)"
  305.     ELSE
  306.         PRINT #2, "real$ = Write"; tarName$; "Data$(file$ + CHR$(0), clean%)"
  307.         PRINT #2, "IF real$ <> "; CHR$(34); CHR$(34); " THEN"
  308.         PRINT #2, "    ff% = FREEFILE"
  309.         PRINT #2, "    OPEN real$ FOR BINARY AS ff%"
  310.         PRINT #2, "    rawdata$ = SPACE$(LOF(ff%))"
  311.         PRINT #2, "    GET #ff%, , rawdata$"
  312.         PRINT #2, "    filedata$ = LzwUnpack$(rawdata$)"
  313.         PRINT #2, "    PUT #ff%, 1, filedata$"
  314.         PRINT #2, "    CLOSE ff%"
  315.         PRINT #2, "END IF"
  316.         PRINT #2, "Write"; tarName$; "Array$ = real$"
  317.     END IF
  318.     PRINT #2, "END FUNCTION"
  319.     PRINT #2, ""
  320.     '--- ending ---
  321.     CLOSE #2
  322.      
  323.     '--- finish message ---
  324.     COLOR 10: PRINT: PRINT "file successfully processed..."
  325.     COLOR 9: PRINT: PRINT "You must $INCLUDE the created file (target name + .bm extension) at"
  326.     PRINT "the end of your program and call the function 'Write"; tarName$; "Array$(...)'"
  327.     PRINT "in an appropriate place to write the file back to disk."
  328.     IF packed% THEN
  329.         COLOR 12: PRINT: PRINT "Your program must also $INCLUDE 'lzwpacker.bm' available from"
  330.         PRINT "the Libraries Collection here:"
  331.         PRINT "     https://www.qb64.org/forum/index.php?topic=809"
  332.         PRINT "to be able to write back the just processed file."
  333.         KILL tarPath$ + tar$ + ".lzw"
  334.     END IF
  335.     done:
  336.     COLOR 7
  337.     END
  338.     '--- error handler ---
  339.     abort:
  340.     COLOR 12: PRINT: PRINT "something is wrong with path/file access, check your inputs and try again..."
  341.     RESUME done
  342.      
  343.     '$INCLUDE: 'QB64Library\LZW-Compress\lzwpacker.bm'
  344.      
  345.      
  346.  

                                                                                                                                         (162 downloads previously)

4
Games / Pipes Puzzle by Dav & bplus
« on: September 30, 2021, 06:06:46 am »
Pipes Puzzle

Author: @Dav
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=4232.0
Version: 1

Description:
This is a Maze puzzler.  To play you click on the pipes to rotate them and connect them to the flow, making the pipes all connected and one color.

Source Code (for reference only: use the zip file):
Code: QB64: [Select]
  1.     '================
  2.     'PIPES.BAS v1.0
  3.     '================
  4.     'Connect the pipes puzzle game
  5.     'Coded by Dav for QB64-GL 1.5 in SEP/2021
  6.      
  7.     'NOTE: Formally called MazeConnect Prototype on the forum.
  8.      
  9.     '============
  10.     'HOW TO PLAY:
  11.     '============
  12.      
  13.     'Click on pipes to rotate them and connect them as one.
  14.     'Object is to make all pipes on board connected to leader.
  15.     'Top left pipe is always on, the leader, so start from it.
  16.     'When pipes are all connected, you advance to next level.
  17.     'There are currently 20 levels.  ESC key exits game.
  18.      
  19.     'SPACE  = restarts level
  20.     'RIGHT ARROW = goto next level
  21.     'LEFT ARROW = go back a level
  22.     'ESC = Quits game
  23.      
  24.     '         VVVVVVV     blus fixed next line to work from his downloaded zip
  25.     $ExeIcon:'.\icon.ico'
  26.     _Icon
  27.      
  28.      
  29.      
  30.     Dim Shared GridSize, Level, MaxLevel, LD$, LU$, RD$, RU$, HZ$, VT$, BM$
  31.      
  32.     Level = 1: MaxLevel = 13
  33.      
  34.     GridSize = 3 'default starting GridSize is 3x3 (its level 1)
  35.     MaxGridSize = 15 'The last GridSize level so far (13 levels right now)
  36.      
  37.     'Declare image names: angle characters, right up, left up, etc
  38.     LD$ = "ld": LU$ = "lu"
  39.     RD$ = "rd": RU$ = "ru"
  40.     HZ$ = "hz": VT$ = "vt"
  41.     BM$ = "bm"
  42.      
  43.     'Sound files
  44.     new& = _SndOpen("sfx_magic.ogg")
  45.     move& = _SndOpen("sfx_click1.mp3"):
  46.     click& = _SndOpen("sfx_click2.mp3"):
  47.     clap& = _SndOpen("sfx_clap.ogg")
  48.      
  49.     'image file
  50.     Dim Shared Solved&
  51.     Solved& = _LoadImage("solved.png", 32) '<  thank bplus for this
  52.      
  53.     'For game state saving...to be added later
  54.     loaded = 0: fil$ = "pipe.dat"
  55.     If _FileExists(fil$) Then
  56.         loaded = 1
  57.     End If
  58.      
  59.     '=======
  60.     newlevel:
  61.     '=======
  62.      
  63.     Screen _NewImage(640, 640, 32)
  64.     'Do: Loop Until _ScreenExists ' <<<<<<<<<< sorry Dav this aint working on my system
  65.     _Delay .25 ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<< does this work for you?
  66.     '            No? increase delay time really nice to have centered on screen
  67.     _ScreenMove _Middle ' <  thank bplus for this , ahhhh that's better
  68.     Cls ', _RGB(32, 32, 77)
  69.      
  70.     If Level = 1 Then
  71.         back& = _LoadImage("hz-grn.png")
  72.         _PutImage (0, 0)-(640, 640), back&
  73.         _FreeImage back&
  74.         title& = _LoadImage("title.png")
  75.         _PutImage (84, 140), title&
  76.         _FreeImage title&
  77.         w$ = Input$(1)
  78.         For a = 0 To 64
  79.             Line (0, 0)-(640, 640), _RGBA(0, 0, 0, a), BF
  80.             _Delay .02
  81.         Next
  82.     End If
  83.      
  84.     PPRINT 100, 300, 30, _RGB(200, 200, 200), 0, "Level:" + Str$(Level) + " of" + Str$(MaxLevel)
  85.     _Delay 2
  86.      
  87.     _SndPlay new&
  88.      
  89.     Title$ = "Pipes: Level " + Str$(Level) + " of" + Str$(MaxLevel)
  90.     _Title Title$
  91.      
  92.     'Make space for variables
  93.     ReDim Shared TileVal$(GridSize * GridSize)
  94.     ReDim Shared TileX(GridSize * GridSize), TileY(GridSize * GridSize)
  95.     ReDim Shared TileClr(GridSize * GridSize), TileClr2(GridSize * GridSize)
  96.      
  97.     TileSize = Int(640 / GridSize) 'The width/height of tiles, in pixels
  98.      
  99.     'set tile values, and generate x/y values...
  100.     bb = 1
  101.     For r = 1 To GridSize
  102.         For c = 1 To GridSize
  103.             x = (r * TileSize): y = (c * TileSize)
  104.             If Rnd(GridSize * 2) = GridSize Then br = 0
  105.             TileX(bb) = x - TileSize: TileY(bb) = y - TileSize
  106.             TileVal$(bb) = RD$
  107.             TileClr(bb) = 0
  108.             TileClr2(bb) = 0
  109.             bb = bb + 1
  110.         Next c
  111.     Next r
  112.      
  113.     TileClr(1) = 1 'turn on top left leader tile
  114.     TileClr2(1) = 1 'make a copy
  115.      
  116.     setmaze 'Load level maze data, it's already scrambled up
  117.      
  118.     firstdraw = 1
  119.     GoSub updatebuttons
  120.      
  121.     Do
  122.      
  123.         _Limit 300
  124.      
  125.         'wait until mouse button up to continue
  126.         While _MouseButton(1) <> 0: n = _MouseInput: Wend
  127.      
  128.         trap = _MouseInput
  129.         If _MouseButton(1) Then
  130.             mx = _MouseX: my = _MouseY
  131.      
  132.             For b = 1 To (GridSize * GridSize)
  133.      
  134.                 tx = TileX(b): tx2 = TileX(b) + TileSize
  135.                 ty = TileY(b): ty2 = TileY(b) + TileSize
  136.      
  137.                 If mx >= tx And mx <= tx2 Then
  138.                     If my >= ty And my <= ty2 Then
  139.                         'skip any black blocks clicked on
  140.                         If TileVal$(b) = BM$ Then GoTo skip
  141.      
  142.                         _SndPlay move&
  143.      
  144.                         bv2$ = TileVal$(b) 'see what tile it is
  145.      
  146.                         'rotate right angle tiles
  147.                         If bv2$ = RD$ Then TileVal$(b) = LD$
  148.                         If bv2$ = LD$ Then TileVal$(b) = LU$
  149.                         If bv2$ = LU$ Then TileVal$(b) = RU$
  150.                         If bv2$ = RU$ Then TileVal$(b) = RD$
  151.      
  152.                         'rotate horiz/vert lines
  153.                         If bv2$ = HZ$ Then TileVal$(b) = VT$
  154.                         If bv2$ = VT$ Then TileVal$(b) = HZ$
  155.      
  156.                         'show tile
  157.                         If TileClr(b) = 1 Then
  158.                             tag$ = "-grn.png"
  159.                         Else
  160.                             tag$ = "-wht.png"
  161.                         End If
  162.      
  163.                         SHOW TileVal$(b) + tag$, TileX(b), TileY(b), TileX(b) + TileSize, TileY(b) + TileSize
  164.      
  165.                         GoSub updatebuttons
  166.                         GoSub checkforwin
  167.      
  168.                     End If
  169.                 End If
  170.             Next b
  171.         End If
  172.         skip:
  173.      
  174.         ink$ = UCase$(InKey$)
  175.      
  176.         If ink$ = Chr$(32) Then GoTo newlevel
  177.      
  178.         'Right arrows advance to next level
  179.         If ink$ = Chr$(0) + Chr$(77) Then
  180.             GridSize = GridSize + 1
  181.             Level = Level + 1
  182.             If Level > MaxLevel Then Level = 1
  183.             If GridSize > MaxGridSize Then
  184.                 GridSize = 3 'MaxGridSize  'restart
  185.             End If
  186.             GoTo newlevel
  187.         End If
  188.      
  189.         'Left Arrows go back a level
  190.         If ink$ = Chr$(0) + Chr$(75) Then
  191.             GridSize = GridSize - 1
  192.             If GridSize < 3 Then GridSize = MaxGridSize
  193.             Level = Level - 1
  194.             If Level < 1 Then Level = MaxLevel
  195.             GoTo newlevel
  196.         End If
  197.      
  198.     Loop Until ink$ = Chr$(27)
  199.      
  200.     System
  201.      
  202.     '============
  203.     updatebuttons:
  204.     '============
  205.      
  206.     'first tile always on, draw it green
  207.     SHOW TileVal$(1) + "-grn.png", TileX(1), TileY(1), TileX(1) + TileSize, TileY(1) + TileSize
  208.      
  209.      
  210.     'turn all off tile colors first, except 1st
  211.     For g = 2 To GridSize * GridSize
  212.         TileClr(g) = 0
  213.     Next g
  214.      
  215.      
  216.     'set leader tile flow direction
  217.     If TileVal$(1) = HZ$ Then direction = 1 'going right
  218.     If TileVal$(1) = VT$ Then direction = 2 'going down
  219.      
  220.     cur = 1 'start with 1st tile always
  221.      
  222.     'do until can't flow anymore (direction blocked)
  223.     Do
  224.      
  225.         If direction = 1 Then 'heading right
  226.             'see if already on the right edge of board
  227.             'if so, it can't go right anymore, so end flow...
  228.             For j = (GridSize * GridSize) - GridSize + 1 To GridSize * GridSize
  229.                 If cur = j Then GoTo flowdone
  230.             Next j
  231.             'now see if one to the right can connect with it.
  232.             'if not connectable, end flow here.
  233.             con = 0 'default is not connectable
  234.             nv$ = TileVal$(cur + GridSize)
  235.             If nv$ = HZ$ Then con = 1
  236.             If nv$ = LU$ Then con = 1
  237.             If nv$ = LD$ Then con = 1
  238.             'if not, end flow here
  239.             If con = 0 Then GoTo flowdone
  240.             'looks like it is connectable, so turn it on
  241.             TileClr(cur + GridSize) = 1 'turn piece to the right on.
  242.             'Make new pieve the new current flow position
  243.             tc = (cur + GridSize): cur = tc
  244.             'find/set new direction based on that character
  245.             If nv$ = HZ$ Then direction = 1 'right
  246.             If nv$ = LU$ Then direction = 4 'up
  247.             If nv$ = LD$ Then direction = 2 'down
  248.         End If
  249.      
  250.         If direction = 2 Then 'heading down
  251.             'see if this one is on the bottom edge
  252.             For j = GridSize To (GridSize * GridSize) Step GridSize
  253.                 If cur = j Then GoTo flowdone
  254.             Next j
  255.             'now see if new one can connect with this one.
  256.             'if not, end flow here.
  257.             con = 0 'default is not connectable
  258.             nv$ = TileVal$(cur + 1)
  259.             If nv$ = VT$ Then con = 1
  260.             If nv$ = LU$ Then con = 1
  261.             If nv$ = RU$ Then con = 1
  262.             'if not, end flow here
  263.             If con = 0 Then GoTo flowdone
  264.             'looks like it must be connectable
  265.             TileClr(cur + 1) = 1 'turn the next piece on too
  266.             'Make it the new current char position
  267.             tc = (cur + 1): cur = tc
  268.             'find/set new direction based on character
  269.             If nv$ = LU$ Then direction = 3 'left
  270.             If nv$ = RU$ Then direction = 1 'right
  271.             If nv$ = VT$ Then direction = 2 'down
  272.         End If
  273.      
  274.         If direction = 3 Then 'heading left
  275.             'see if this one is on the bottom edge
  276.             For j = 1 To GridSize
  277.                 If cur = j Then GoTo flowdone
  278.             Next j
  279.      
  280.             'now see if new one can connect with this one.
  281.             'if not, end flow here.
  282.             con = 0 'default is not connectable
  283.             nv$ = TileVal$(cur - GridSize)
  284.             If nv$ = HZ$ Then con = 1
  285.             If nv$ = RU$ Then con = 1
  286.             If nv$ = RD$ Then con = 1
  287.             'if not, end flow here
  288.             If con = 0 Then GoTo flowdone
  289.             'looks like it must be connectable
  290.             TileClr(cur - GridSize) = 1 'turn the next piece on too
  291.             'Make it the new current char position
  292.             tc = (cur - GridSize): cur = tc
  293.             'find/set new direction based on character
  294.             If nv$ = HZ$ Then direction = 3 'left
  295.             If nv$ = RU$ Then direction = 4 'up
  296.             If nv$ = RD$ Then direction = 2 'down
  297.         End If
  298.      
  299.         If direction = 4 Then 'going up
  300.             'see if this one is on the edge of board
  301.             'if so, it can't go up, so end flow...
  302.             For j = 1 To (GridSize * GridSize) Step GridSize
  303.                 If cur = j Then GoTo flowdone
  304.             Next j
  305.             'now see if new one can connect with this one.
  306.             'if not, end flow here.
  307.             con = 0 'default is not connectable
  308.             nv$ = TileVal$(cur - 1)
  309.             If nv$ = VT$ Then con = 1
  310.             If nv$ = LD$ Then con = 1
  311.             If nv$ = RD$ Then con = 1
  312.             'if not, end flow here
  313.             If con = 0 Then GoTo flowdone
  314.             'looks like it must be connectable
  315.             TileClr(cur - 1) = 1 'turn the next piece on too
  316.             'Make it the new current char position
  317.             tc = (cur - 1): cur = tc
  318.             'find/set new direction based on character
  319.             If nv$ = VT$ Then direction = 4 'up
  320.             If nv$ = LD$ Then direction = 3 'left
  321.             If nv$ = RD$ Then direction = 1 'right
  322.         End If
  323.      
  324.     Loop
  325.      
  326.     flowdone:
  327.      
  328.     If firstdraw = 0 Then
  329.      
  330.         'draw/colorize board
  331.         For t = 2 To (GridSize * GridSize)
  332.             If TileClr(t) = 1 And TileClr2(t) = 0 Then
  333.                 'show green...
  334.                 SHOW TileVal$(t) + "-grn.png", TileX(t), TileY(t), TileX(t) + TileSize, TileY(t) + TileSize
  335.             End If
  336.             If TileClr(t) = 0 And TileClr2(t) = 1 Then
  337.                 'show white...
  338.                 SHOW TileVal$(t) + "-wht.png", TileX(t), TileY(t), TileX(t) + TileSize, TileY(t) + TileSize
  339.             End If
  340.         Next t
  341.      
  342.     Else
  343.      
  344.         'draw/colorize board
  345.         For t = 2 To (GridSize * GridSize)
  346.             If TileClr(t) = 1 Then
  347.                 tag$ = "-grn.png"
  348.             Else
  349.                 tag$ = "-wht.png"
  350.             End If
  351.             SHOW TileVal$(t) + tag$, TileX(t), TileY(t), TileX(t) + TileSize, TileY(t) + TileSize
  352.         Next t
  353.      
  354.         firstdraw = 0
  355.      
  356.     End If
  357.      
  358.      
  359.     'copy current color values
  360.     For t = 1 To GridSize * GridSize
  361.         TileClr2(t) = TileClr(t)
  362.     Next t
  363.      
  364.      
  365.     '===========
  366.     checkforwin:
  367.     '===========
  368.      
  369.     all = 0
  370.     For w = 1 To (GridSize * GridSize)
  371.         If TileClr(w) = 1 Then all = all + 1
  372.         If TileVal$(w) = BM$ Then all = all + 1 'add any blocks
  373.     Next w
  374.      
  375.     If all = (GridSize * GridSize) Then
  376.      
  377.         ' bplus rewrote this section to fade in the You did it! sign over the gameboard =======================
  378.         ' Solved& has already been loaded after sounds at start of program
  379.         _SndPlay clap&
  380.         snap& = _NewImage(_Width, _Height, 32)
  381.         _PutImage , 0, snap&
  382.         For alph = 0 To 255
  383.             Cls
  384.             _PutImage , snap&, 0 'background
  385.             _SetAlpha alph, , Solved&
  386.             _PutImage (166, 258), Solved&
  387.             _Limit 40 ' 255 frames in 2 secs
  388.             _Display ' damn blinking!!! without this
  389.         Next
  390.         _AutoDisplay '<<<<<< back to not needing _display
  391.         _FreeImage snap&
  392.         ' end of bplus meddling ================================================================================
  393.      
  394.         Level = Level + 1
  395.      
  396.         GridSize = GridSize + 1
  397.      
  398.         If Level > MaxLevel Then Level = 1
  399.      
  400.         If GridSize > MaxGridSize Then
  401.             GridSize = 3 'MaxGridSize  'restart
  402.         End If
  403.      
  404.         GoTo newlevel
  405.      
  406.     End If
  407.      
  408.     Return
  409.      
  410.      
  411.     Sub setmaze ()
  412.      
  413.         If Level = 1 Then
  414.             GridSize = 3
  415.             a$ = "" '3x3 MazeConnect GridSize
  416.             a$ = a$ + "hzrdru"
  417.             a$ = a$ + "hzhzhz"
  418.             a$ = a$ + "ldluld"
  419.         End If
  420.      
  421.         If Level = 2 Then
  422.             GridSize = 4
  423.             a$ = "" '4x4 MazeConnect GridSize
  424.             a$ = a$ + "vtvtruru"
  425.             a$ = a$ + "rdvtluhz"
  426.             a$ = a$ + "hzrdruhz"
  427.             a$ = a$ + "ldluldlu"
  428.         End If
  429.      
  430.         If Level = 3 Then
  431.             GridSize = 5
  432.             a$ = "" '5x5 MazeConnect GridSize
  433.             a$ = a$ + "hzrdvtvtld"
  434.             a$ = a$ + "hzhzrdrdhz"
  435.             a$ = a$ + "hzhzldhzhz"
  436.             a$ = a$ + "hzldvtluhz"
  437.             a$ = a$ + "ldvtvtvtlu"
  438.         End If
  439.      
  440.         If Level = 4 Then
  441.             GridSize = 6
  442.             a$ = "" '6x6 MazeConnect GridSize
  443.             a$ = a$ + "hzrdrurdvtru"
  444.             a$ = a$ + "hzhzhzhzrdlu"
  445.             a$ = a$ + "ldluhzhzldru"
  446.             a$ = a$ + "rdvtluhzbmhz"
  447.             a$ = a$ + "hzrdruldruhz"
  448.             a$ = a$ + "ldluldvtlulu"
  449.         End If
  450.      
  451.         If Level = 5 Then
  452.             GridSize = 7
  453.             a$ = "" '7x7 MazeConnect GridSize
  454.             a$ = "vtruvtvtrurdru"
  455.             a$ = a$ + "rdlurdruldluhz"
  456.             a$ = a$ + "ldvtluldrurdlu"
  457.             a$ = a$ + "rdvtrurdluldru"
  458.             a$ = a$ + "ldruldlurdvtlu"
  459.             a$ = a$ + "rdlurdruldvtru"
  460.             a$ = a$ + "ldvtluldvtvtlu"
  461.         End If
  462.      
  463.         If Level = 6 Then
  464.             GridSize = 8
  465.             a$ = "" '8x8 MazeConnect GridSize
  466.             a$ = a$ + "hzvtrurdrurdrubm"
  467.             a$ = a$ + "hzbmldluhzhzldru"
  468.             a$ = a$ + "ldvtrurdluhzrdlu"
  469.             a$ = a$ + "rdvtluldvtluldru"
  470.             a$ = a$ + "ldrurdvtrurdvtlu"
  471.             a$ = a$ + "bmhzhzbmldlurdru"
  472.             a$ = a$ + "rdluldvtvtvtluhz"
  473.             a$ = a$ + "ldvtvtvtvtvtvtlu"
  474.         End If
  475.      
  476.         If Level = 7 Then
  477.             GridSize = 9
  478.             a$ = "" '9x9 MazeConnect GridSize
  479.             a$ = a$ + "hzrdvtvtrurdrurdru"
  480.             a$ = a$ + "hzldvtruldluldluhz"
  481.             a$ = a$ + "ldvtruldrubmrdvtlu"
  482.             a$ = a$ + "rdruldruldruldrubm"
  483.             a$ = a$ + "hzldruldruldruldru"
  484.             a$ = a$ + "ldruhzbmldruhzbmhz"
  485.             a$ = a$ + "rdluldvtvtluldruhz"
  486.             a$ = a$ + "hzrdrurdvtrurdluhz"
  487.             a$ = a$ + "ldluldlubmldluvtlu"
  488.         End If
  489.      
  490.         If Level = 8 Then
  491.             GridSize = 10
  492.             a$ = "" '10x10 MazeConnect GridSize
  493.             a$ = a$ + "vtvtvtrurdrurdvtrubm"
  494.             a$ = a$ + "hzrdvtluhzhzldruldru"
  495.             a$ = a$ + "hzldvtvtluldruhzrdlu"
  496.             a$ = a$ + "hzbmrdvtvtruldluldru"
  497.             a$ = a$ + "hzrdlurdruhzrdvtvtlu"
  498.             a$ = a$ + "hzhzrdluhzldlurdrubm"
  499.             a$ = a$ + "hzhzhzbmldrubmhzldru"
  500.             a$ = a$ + "hzldlurdruldvtlurdlu"
  501.             a$ = a$ + "hzrdruhzldrurdruldru"
  502.             a$ = a$ + "ldluldlubmldluldvtlu"
  503.         End If
  504.      
  505.         If Level = 9 Then
  506.             GridSize = 11
  507.             a$ = "" '11x11 MazeConnect GridSize
  508.             a$ = a$ + "hzvtrubmrdvtrubmrdvtru"
  509.             a$ = a$ + "ldruldruldruldruldruhz"
  510.             a$ = a$ + "bmldruldruldruldruhzhz"
  511.             a$ = a$ + "rdruldruldruldruldluhz"
  512.             a$ = a$ + "hzldruldruldruldrurdlu"
  513.             a$ = a$ + "ldruldruldruldruhzldru"
  514.             a$ = a$ + "bmldruldruldruldlurdlu"
  515.             a$ = a$ + "rdruldruldruldrurdlubm"
  516.             a$ = a$ + "hzldruldruldvtluldvtru"
  517.             a$ = a$ + "ldruldvtlurdrurdrurdlu"
  518.             a$ = a$ + "bmldvtvtvtluldluldlubm"
  519.         End If
  520.      
  521.         If Level = 10 Then
  522.             GridSize = 12
  523.             a$ = "" '12x12 MazeConnect GridSize
  524.             a$ = a$ + "vtvtrubmbmrdrurdrurdvtru"
  525.             a$ = a$ + "bmbmhzbmrdluldluhzhzrdlu"
  526.             a$ = a$ + "bmrdlurdlurdrurdluhzldru"
  527.             a$ = a$ + "rdlurdlurdluhzhzrdlurdlu"
  528.             a$ = a$ + "ldruldvtlurdluhzhzbmldru"
  529.             a$ = a$ + "bmldvtvtruhzbmldlurdvtlu"
  530.             a$ = a$ + "rdvtvtvtluhzrdvtvtlurdru"
  531.             a$ = a$ + "ldrurdvtvtluhzrdvtvtluhz"
  532.             a$ = a$ + "rdluhzbmbmbmldlurdrurdlu"
  533.             a$ = a$ + "hzrdlurdrurdrubmhzhzhzbm"
  534.             a$ = a$ + "ldlurdluhzhzhzrdluhzldru"
  535.             a$ = a$ + "vtvtlubmldluldlubmldvtlu"
  536.         End If
  537.      
  538.         If Level = 11 Then
  539.             GridSize = 13
  540.             a$ = "" '13x13 MazeConnect GridSize
  541.             a$ = a$ + "hzvtvtvtvtvtrurdrurdrurdru"
  542.             a$ = a$ + "hzrdrurdvtruldluhzhzldluhz"
  543.             a$ = a$ + "hzhzhzhzspldvtruhzhzrdruhz"
  544.             a$ = a$ + "hzhzhzldrubmrdluldluhzhzhz"
  545.             a$ = a$ + "hzhzldvtlurdlurdvtvtluldlu"
  546.             a$ = a$ + "hzldrubmrdlubmldvtvtrurdru"
  547.             a$ = a$ + "ldruldruhzbmbmbmrdruhzhzhz"
  548.             a$ = a$ + "rdlurdluldrubmrdluhzldluhz"
  549.             a$ = a$ + "hzrdlurdruldvtlurdlubmrdlu"
  550.             a$ = a$ + "hzldruhzldrurdvtlurdruldru"
  551.             a$ = a$ + "hzrdluhzbmldlurdvtluhzrdlu"
  552.             a$ = a$ + "hzhzrdlurdvtruhzrdvtluldru"
  553.             a$ = a$ + "ldluldvtlubmldluldvtvtvtlu"
  554.         End If
  555.      
  556.         If Level = 12 Then
  557.             GridSize = 14
  558.             a$ = "" '14x14 MazeConnect GridSize
  559.             a$ = a$ + "hzrdrurdvtvtrurdrurdvtvtrubm"
  560.             a$ = a$ + "hzhzhzldvtruhzhzhzhzrdruhzbm"
  561.             a$ = a$ + "ldluhzrdruhzldluldluhzhzhzbm"
  562.             a$ = a$ + "rdruhzhzhzldvtvtvtruhzldlubm"
  563.             a$ = a$ + "hzhzhzhzhzrdrurdruhzldvtrubm"
  564.             a$ = a$ + "hzhzhzhzhzhzhzhzhzhzrdruldru"
  565.             a$ = a$ + "hzhzldluhzhzhzhzhzhzhzldvtlu"
  566.             a$ = a$ + "hzldvtruhzhzhzhzhzhzldrurdru"
  567.             a$ = a$ + "hzrdruhzldluhzhzhzhzbmldluhz"
  568.             a$ = a$ + "ldluhzldvtruhzhzhzhzrdrurdlu"
  569.             a$ = a$ + "rdruhzrdvtluhzhzldluhzhzhzbm"
  570.             a$ = a$ + "hzldluldvtvtluhzrdvtluhzhzbm"
  571.             a$ = a$ + "hzvtvtvtvtvtvtluldrurdluhzbm"
  572.             a$ = a$ + "ldvtvtvtvtvtvtvtvtluldvtlubm"
  573.         End If
  574.      
  575.         If Level = 13 Then
  576.             GridSize = 15
  577.             a$ = "" '15x15 MazeConnect GridSize
  578.             a$ = a$ + "vtvtrurdrurdrurdrubmrdvtvtvtru"
  579.             a$ = a$ + "vtruldluhzhzldluldvtlurdvtruhz"
  580.             a$ = a$ + "rdlubmbmhzldvtvtrurdvtlubmldlu"
  581.             a$ = a$ + "ldrurdruhzbmrdruhzldrurdvtvtru"
  582.             a$ = a$ + "bmhzhzldlurdluhzldruldlurdvtlu"
  583.             a$ = a$ + "rdluldrurdlubmhzrdlurdruldrubm"
  584.             a$ = a$ + "ldrubmldlurdruldlubmhzhzbmldru"
  585.             a$ = a$ + "rdlurdvtvtluldrurdruhzhzrdvtlu"
  586.             a$ = a$ + "ldvtlurdvtvtvtluhzldluhzldvtru"
  587.             a$ = a$ + "rdvtvtlurdvtvtruldrurdlurdruhz"
  588.             a$ = a$ + "ldvtrurdlubmrdlurdluhzrdluldlu"
  589.             a$ = a$ + "rdvtluldrurdlurdlurdluhzbmrdru"
  590.             a$ = a$ + "ldvtrurdluhzbmldruldruldvtluhz"
  591.             a$ = a$ + "rdvtluldruhzrdruldruldvtrurdlu"
  592.             a$ = a$ + "ldvtvtvtluldluldvtlubmbmldlubm"
  593.         End If
  594.      
  595.         dd = 1
  596.         For s = 1 To Len(a$) Step 2
  597.             b$ = Mid$(a$, s, 2)
  598.             If b$ = "vt" Then rotate dd, 1
  599.             If b$ = "hz" Then rotate dd, 1
  600.             If b$ = "ld" Then rotate dd, 2
  601.             If b$ = "lu" Then rotate dd, 2
  602.             If b$ = "rd" Then rotate dd, 2
  603.             If b$ = "ru" Then rotate dd, 2
  604.             If b$ = "bm" Then TileVal$(dd) = BM$
  605.      
  606.             dd = dd + 1
  607.         Next s
  608.      
  609.     End Sub
  610.      
  611.     Sub rotate (num, typ)
  612.      
  613.         'there are only two types of rotating characters,
  614.         'straight lines, or right angles...
  615.      
  616.         'randomly rotate straight character
  617.         If typ = 1 Then
  618.             If Int(Rnd * 2) = 0 Then
  619.                 TileVal$(num) = VT$
  620.             Else
  621.                 TileVal$(num) = HZ$
  622.             End If
  623.         End If
  624.      
  625.         'randomly rotate right angles...
  626.         If typ = 2 Then
  627.             rn = Int(Rnd * 4) + 1
  628.             If rn = 1 Then TileVal$(num) = LD$
  629.             If rn = 2 Then TileVal$(num) = LU$
  630.             If rn = 3 Then TileVal$(num) = RD$
  631.             If rn = 4 Then TileVal$(num) = RU$
  632.         End If
  633.      
  634.     End Sub
  635.      
  636.     Sub SHOW (i$, x1, y1, x2, y2)
  637.         'Just a little sub to load & put an image at x1/y1
  638.         ttmp = _LoadImage(i$)
  639.         _PutImage (x1, y1)-(x2, y2), ttmp
  640.         _FreeImage ttmp
  641.     End Sub
  642.      
  643.     Sub PPRINT (x, y, size, clr&, trans&, text$)
  644.         'This sub outputs to the current _DEST set
  645.         'It makes trans& the transparent color
  646.      
  647.         'x/y is where to print text
  648.         'size is the font size to use
  649.         'clr& is the color of your text
  650.         'trans& is the background transparent color
  651.         'text$ is the string to print
  652.      
  653.         '=== get users current write screen
  654.         orig& = _Dest
  655.      
  656.         '=== if you are using an 8 or 32 bit screen
  657.         bit = 32: If _PixelSize(0) = 1 Then bit = 256
  658.      
  659.         '=== step through your text
  660.         For t = 0 To Len(text$) - 1
  661.             '=== make a temp screen to use
  662.             pprintimg& = _NewImage(16, 16, bit)
  663.             _Dest pprintimg&
  664.             '=== set colors and print text
  665.             Cls , trans&: Color clr&
  666.             Print Mid$(text$, t + 1, 1);
  667.             '== make background color the transprent one
  668.             _ClearColor _RGB(0, 0, 0), pprintimg&
  669.             '=== go back to original screen  to output
  670.             _Dest orig&
  671.             '=== set it and forget it
  672.             x1 = x + (t * size): x2 = x1 + size
  673.             y1 = y: y2 = y + size
  674.             _PutImage (x1 - (size / 2), y1)-(x2, y2 + (size / 3)), pprintimg&
  675.             _FreeImage pprintimg&
  676.         Next
  677.     End Sub
  678.  
  679.  

Attachments:

 

PipesPuzzle.jpg

Author's previous version for rerefence:https://www.qb64.org/foru/index.php?topic=2094.msg113243#msg113243

5
2D/3D Graphics / MOVED: SaveImage (take screenshots) by SMcNeill
« on: September 26, 2021, 04:55:45 am »

6
General, Math & Geometry / MOVED: Curve Smoother
« on: September 25, 2021, 08:02:15 am »

7
General, Math & Geometry / MOVED: Circle Intersecting Line
« on: September 25, 2021, 08:00:25 am »

8
General, Math & Geometry / MOVED: Circle Intersecting Circle
« on: September 25, 2021, 07:57:43 am »

10
Utilities / Filled Circles and Ellipses (collaborative)
« on: September 25, 2021, 06:48:06 am »
Filled Circles and Ellipses

Contributor(s): @bplus, @Pete, @SMcNeill, @STxAxTIC
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=1044.0

Description:
We develop four variations on the CIRCLE command in the form of four SUBs:
(i) CircleFill = Filled circle
(ii) EllipseFill = Filled ellipse
(iii) EllipseTilt = Tilted ellipse
(iv) EllipseTiltFill = Tilted and filled ellipse

These works have been optimized for speed and respect for alpha transparency.


Source Code:
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2.  
  3. DIM TransRed AS _UNSIGNED LONG
  4. DIM TransGreen AS _UNSIGNED LONG
  5. DIM TransBlue AS _UNSIGNED LONG
  6. TransRed = _RGBA(255, 0, 0, 128)
  7. TransGreen = _RGBA(0, 255, 0, 128)
  8. TransBlue = _RGBA(0, 0, 255, 128)
  9.  
  10. CALL CircleFill(100, 100, 75, TransRed)
  11. CALL CircleFill(120, 120, 75, TransBlue)
  12.  
  13. CALL EllipseFill(550, 100, 150, 75, TransBlue)
  14. CALL EllipseFill(570, 120, 150, 75, TransGreen)
  15.  
  16. CALL EllipseTilt(200, 400, 150, 75, 0, TransGreen)
  17. CALL EllipseTilt(220, 420, 150, 75, 3.14 / 4, TransRed)
  18.  
  19. CALL EllipseTiltFill(0, 550, 400, 150, 75, 3.14 / 6, TransRed)
  20. CALL EllipseTiltFill(0, 570, 420, 150, 75, 3.14 / 4, TransGreen)
  21.  
  22.  
  23. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  24.     ' CX = center x coordinate
  25.     ' CY = center y coordinate
  26.     '  R = radius
  27.     '  C = fill color
  28.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  29.     DIM X AS INTEGER, Y AS INTEGER
  30.     Radius = ABS(R)
  31.     RadiusError = -Radius
  32.     X = Radius
  33.     Y = 0
  34.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  35.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  36.     WHILE X > Y
  37.         RadiusError = RadiusError + Y * 2 + 1
  38.         IF RadiusError >= 0 THEN
  39.             IF X <> Y + 1 THEN
  40.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  41.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  42.             END IF
  43.             X = X - 1
  44.             RadiusError = RadiusError - X * 2
  45.         END IF
  46.         Y = Y + 1
  47.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  48.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  49.     WEND
  50.  
  51. SUB EllipseFill (CX AS INTEGER, CY AS INTEGER, a AS INTEGER, b AS INTEGER, C AS _UNSIGNED LONG)
  52.     ' CX = center x coordinate
  53.     ' CY = center y coordinate
  54.     '  a = semimajor axis
  55.     '  b = semiminor axis
  56.     '  C = fill color
  57.     IF a = 0 OR b = 0 THEN EXIT SUB
  58.     DIM h2 AS _INTEGER64
  59.     DIM w2 AS _INTEGER64
  60.     DIM h2w2 AS _INTEGER64
  61.     DIM x AS INTEGER
  62.     DIM y AS INTEGER
  63.     w2 = a * a
  64.     h2 = b * b
  65.     h2w2 = h2 * w2
  66.     LINE (CX - a, CY)-(CX + a, CY), C, BF
  67.     DO WHILE y < b
  68.         y = y + 1
  69.         x = SQR((h2w2 - y * y * w2) \ h2)
  70.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  71.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  72.     LOOP
  73.  
  74. SUB EllipseTilt (CX, CY, a, b, ang, C AS _UNSIGNED LONG)
  75.     '  CX = center x coordinate
  76.     '  CY = center y coordinate
  77.     '   a = semimajor axis
  78.     '   b = semiminor axis
  79.     ' ang = clockwise orientation of semimajor axis in radians (0 default)
  80.     '   C = fill color
  81.     FOR k = 0 TO 6.283185307179586 + .025 STEP .025
  82.         i = a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  83.         j = -a * COS(k) * SIN(ang) + b * SIN(k) * COS(ang)
  84.         i = i + CX
  85.         j = -j + CY
  86.         IF k <> 0 THEN
  87.             LINE -(i, j), C
  88.         ELSE
  89.             PSET (i, j), C
  90.         END IF
  91.     NEXT
  92.  
  93. SUB EllipseTiltFill (destHandle&, CX, CY, a, b, ang, C AS _UNSIGNED LONG)
  94.     '  destHandle& = destination handle
  95.     '  CX = center x coordinate
  96.     '  CY = center y coordinate
  97.     '   a = semimajor axis
  98.     '   b = semiminor axis
  99.     ' ang = clockwise orientation of semimajor axis in radians (0 default)
  100.     '   C = fill color
  101.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER
  102.     DIM prc AS _UNSIGNED LONG
  103.     DIM D AS INTEGER, S AS INTEGER
  104.     D = _DEST: S = _SOURCE
  105.     prc = _RGB32(255, 255, 255, 255)
  106.     IF a > b THEN max = a + 1 ELSE max = b + 1
  107.     mx2 = max + max
  108.     tef& = _NEWIMAGE(mx2, mx2)
  109.     _DEST tef&
  110.     _SOURCE tef&
  111.     FOR k = 0 TO 6.283185307179586 + .025 STEP .025
  112.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  113.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  114.         IF k <> 0 THEN
  115.             LINE (lasti, lastj)-(i, j), prc
  116.         ELSE
  117.             PSET (i, j), prc
  118.         END IF
  119.         lasti = i: lastj = j
  120.     NEXT
  121.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  122.     FOR y = 0 TO mx2
  123.         x = 0
  124.         WHILE POINT(x, y) <> prc AND x < mx2
  125.             x = x + 1
  126.         WEND
  127.         xleft(y) = x
  128.         WHILE POINT(x, y) = prc AND x < mx2
  129.             x = x + 1
  130.         WEND
  131.         WHILE POINT(x, y) <> prc AND x < mx2
  132.             x = x + 1
  133.         WEND
  134.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  135.     NEXT
  136.     _DEST destHandle&
  137.     FOR y = 0 TO mx2
  138.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + CX - max, y + CY - max)-(xright(y) + CX - max, y + CY - max), C, BF
  139.     NEXT
  140.     _DEST D: _DEST S
  141.     _FREEIMAGE tef&
  142.  

Attachments:
 
                                                                                                                                         (191 downloads previously)

Ellipses.png

11
Utilities / RotoZoom3 (Modification) by bplus
« on: September 25, 2021, 06:20:27 am »
Author and contributor: @bplus @Galleon
Source: QB64.org Wiki and Forum
URL: https://www.qb64.org/wiki/MAPTRIANGLE
https://www.qb64.org/forum/index.php?topic=1511.msg115148#msg115148
Version: 2020 version #3
Tags: [graphics] [image]
Description:
A modification of Galleon's RotoZoom in Wiki that both scales and rotates an image, this version scales the x-axis and y-axis independently allowing some rotations of image just by changing X or Y Scales making this already powerful routine even more a versatile image tool.

Source Code (and demos with Spike Image (attached)):
Code: QB64: [Select]
  1. _TITLE "Another RotoZoom Demo" 'b+ started 2020-03-02
  2.  
  3. CONST xmax = 1200, ymax = 700, xc = 600, yc = 350
  4. SCREEN _NEWIMAGE(xmax, ymax, 32)
  5. _SCREENMOVE 100, 40
  6. DIM SHARED s&, ao
  7. DIM a, x, y, x1, y1, xs, dxs, ddxs, ys, dys, ddys, maxScale
  8.  
  9. ' Starting from an image I pulled from Internet, I used Paint 3D to give it a transparent background.
  10. s& = _LOADIMAGE("tspike.png") 't for transparent background
  11.  
  12.  
  13. ' Standard Rotation about the image center on a given X, Y location. Rotating image in middle of screen,
  14. ' I used something like this to find ideal angle for level point on left head on right.
  15. WHILE _KEYDOWN(27) = 0
  16.     a = a + _PI(1 / 36)
  17.     IF a > _PI(1.999) THEN a = 0
  18.     CLS
  19.     RotoZoom3 xc, yc, s&, 1, 1, a
  20.     PRINT "Raw image rotation:": PRINT
  21.     PRINT "radian angle:"; a; "   degrees:"; _R2D(a) \ 1; " press key for next angle... esc to rotate on y axis"
  22.     WHILE LEN(INKEY$) = 0: _LIMIT 60: WEND
  23.  
  24. ao = _PI(.27) ' I have to offset the image angle by this amount so that the spike point is on the left
  25. '               and the head is on the right at 0 degrees or radians.
  26.  
  27.  
  28. 'Demo of the independent x and y scale for axis rotations
  29. maxScale = 4: dxs = .01: ddxs = 1: xs = maxScale:
  30.     CLS
  31.     PRINT "Press any for rotation on x axis..."
  32.     RotoZoom3 xc, yc, s&, xs, maxScale, ao
  33.     IF xs + dxs > maxScale OR xs + dxs < -maxScale THEN ddxs = ddxs * -1
  34.     xs = xs + dxs * ddxs
  35.     _DISPLAY
  36.     _LIMIT 60
  37.  
  38. ys = maxScale: dys = .01: ddys = 1
  39.     CLS
  40.     PRINT "Press any to see layout of image over whole screen and end demo..."
  41.     RotoZoom3 xc, yc, s&, maxScale, ys, ao
  42.     IF ys + dys > maxScale OR ys + dys < -maxScale THEN ddys = ddys * -1
  43.     ys = ys + dys * ddys
  44.     _DISPLAY
  45.     _LIMIT 60
  46.  
  47. ' Demo of an applied layout on screen
  48. COLOR , &HFFBBBBBB: CLS ' the image has slight gray halo so hide with gray background
  49. FOR x = 40 TO _WIDTH - 40 STEP 20
  50.     RotoZoom3 x, 15, s&, .2, .2, _PI(1.5 + .27)
  51.     RotoZoom3 x, _HEIGHT - 15, s&, .2, .2, _PI(.5 + .27)
  52. FOR y = 40 TO _HEIGHT - 40 STEP 20
  53.     RotoZoom3 15, y, s&, .2, .2, _PI(1 + .27)
  54.     RotoZoom3 _WIDTH - 15, y, s&, .2, .2, _PI(.27)
  55. FOR a = 0 TO _PI(2) STEP _PI(1 / 6)
  56.     x1 = xc + 200 * COS(a)
  57.     y1 = yc + 200 * SIN(a)
  58.     RotoZoom3 x1, y1, s&, 2, 2, a + ao
  59.  
  60. 'And finally a little show. What is better than a knife thrower throwing bananas?
  61. WHILE _KEYDOWN(27) = 0
  62.     CLS
  63.     drawKite xc, .9 * ymax, 600, a + ao
  64.     _DISPLAY
  65.     _LIMIT 30
  66.     a = a + _PI(2 / 360)
  67.  
  68. SUB drawKite (x, y, s, a)
  69.     RotoZoom3 x, y, s&, s / _WIDTH(s&), s / _HEIGHT(s&), a + ao
  70.     IF s > 10 THEN
  71.         drawKite x + .5 * s * COS(_PI(2) - a), (y - .25 * s) + .25 * s * SIN(_PI(2) - a), s / 1.5, a
  72.         drawKite x + .5 * s * COS(_PI + a), (y - .25 * s) + .25 * s * SIN(_PI + a), s / 1.5, a
  73.     END IF
  74.  
  75. ' Description:
  76. ' Started from a mod of Galleon's in Wiki that both scales and rotates an image.
  77. ' This version scales the x-axis and y-axis independently allowing rotations of image just by changing X or Y Scales
  78. ' making this tightly coded routine a very powerful and versatile image tool.
  79. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE)
  80.     ' This assumes you have set your drawing location with _DEST or default to screen.
  81.     ' X, Y - is where you want to put the middle of the image
  82.     ' Image - is the handle assigned with _LOADIMAGE
  83.     ' xScale, yScale - are shrinkage < 1 or magnification > 1 on the given axis, 1 just uses image size.
  84.     ' These are multipliers so .5 will create image .5 size on given axis and 2 for twice image size.
  85.     ' radianRotation is the Angle in Radian units to rotate the image
  86.     ' note: Radian units for rotation because it matches angle units of other Basic Trig functions
  87.     '       and saves a little time converting from degree.
  88.     '       Use the _D2R() function if you prefer to work in degree units for angles.
  89.  
  90.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE ' simple arrays for x, y to hold the 4 corners of image
  91.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2& '   variables for image manipulation
  92.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  93.     px(0) = -W& / 2: py(0) = -H& / 2 'left top corner
  94.     px(1) = -W& / 2: py(1) = H& / 2 ' left bottom corner
  95.     px(2) = W& / 2: py(2) = H& / 2 '  right bottom
  96.     px(3) = W& / 2: py(3) = -H& / 2 ' right top
  97.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation) ' rotation helpers
  98.     FOR i& = 0 TO 3 ' calc new point locations with rotation and zoom
  99.         x2& = xScale * (px(i&) * cosr! + sinr! * py(i&)) + X: y2& = yScale * (py(i&) * cosr! - px(i&) * sinr!) + Y
  100.         px(i&) = x2&: py(i&) = y2&
  101.     NEXT
  102.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  103.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  104.  
  105.  

Attachments:
 
                                                                                                                                         (124 downloads previously)

Spiked.PNG

12
General, Math & Geometry / Convert BMP to Dominoes by Richard Frost
« on: September 25, 2021, 05:46:49 am »
Convert BMP to Dominoes

Author: @Richard Frost
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=1023.0
Version: 2019

Description:
[This] is an image converter that takes a picture a small block at a time and finds the "best fit" domino for that space. (The woman is Heather Thomas.)

Source Code:
Code: QB64: [Select]
  1. ' The woman is Heather Thomas
  2.  
  3. DEFINT A-Z
  4. DIM dots(7), x(7, 7), y(7, 7), c1(7), c2(28), pixel(7, 7), w(3), y$(30)
  5. cps! = 12.83 ' cost per set
  6. FOR i = 1 TO 28: READ y$(i): NEXT i
  7. FOR n = 1 TO 7
  8.     READ dots(n)
  9.     FOR dot = 1 TO dots(n)
  10.         READ x(n, dot), y(n, dot)
  11.     NEXT dot
  12. xb = 10: xe = 350 ' x begin and end
  13. yb = 0: ye = 470 ' y begin and end
  14. OPEN "heath.bmp" FOR RANDOM AS #1 LEN = 1: FIELD #1, 1 AS t$
  15. FOR y1 = yb TO ye STEP 8
  16.     FOR x1 = xb TO xe STEP 8
  17.         n = 0
  18.         FOR y2 = 0 TO 7
  19.             FOR x2 = 0 TO 7
  20.                 x3 = x1 + x2
  21.                 y3 = y1 + y2
  22.                 r& = CDBL(479 - y3) * 640 + x3 + 441
  23.                 GET #1, r&
  24.                 d = ASC(t$) \ 13
  25.                 IF d > 15 THEN d = 15
  26.                 pixel(x2, y2) = -(d > 7) ' for 3 problem
  27.                 n = n + d
  28.             NEXT x2
  29.         NEXT y2
  30.         n = n / 155 ' 175
  31.         IF n > 6 THEN n = 6
  32.         x$ = x$ + CHR$(48 + n) ' for counting tiles used
  33.         IF LEN(x$) = 2 THEN ' got left & right
  34.             FOR i = 1 TO 28
  35.                 IF x$ = y$(i) THEN c2(i) = c2(i) + 1: EXIT FOR
  36.             NEXT i
  37.             x$ = ""
  38.         END IF
  39.         IF n = 3 THEN ' default bottom left - top right
  40.             IF (l = 3) OR (l = 7) THEN ' can't change direction if the
  41.                 n = l ' last piece was also a 3
  42.             ELSE
  43.                 FOR zi = 0 TO 3
  44.                     w(zi) = 0
  45.                 NEXT zi
  46.                 FOR y2 = 0 TO 7
  47.                     FOR x2 = 0 TO 7
  48.                         xi = x2 \ 4 ' 0 or 1
  49.                         yi = y2 \ 4 ' 0 or 1
  50.                         zi = xi * 2 + yi ' 0-3
  51.                         ' LOCATE zi + 1, 1: PRINT zi;
  52.                         w(zi) = w(zi) + pixel(x2, y2)
  53.                     NEXT x2
  54.                 NEXT y2
  55.                 IF (w(1) + w(2)) > (w(0) + w(3)) THEN n = 7
  56.             END IF
  57.         END IF
  58.         l = n ' save last used (for 3)
  59.         d = dots(n)
  60.         c1(n) = c1(n) + 1
  61.         FOR dot = 1 TO d
  62.             tx = (x1 + 4) + x(n, dot) * 2 - xb
  63.             ty = (y1 + 4) + y(n, dot) * 2 - yb
  64.             PSET (tx, ty), 15
  65.         NEXT dot
  66.         IF INKEY$ = CHR$(27) THEN CLOSE: SCREEN 0, 0, 0, 0: END
  67.         nd = nd + 1
  68.     NEXT x1
  69.     GOSUB Status
  70. NEXT y1
  71.  
  72. Status:
  73. FOR i = 0 TO 7
  74.     'COLOR i
  75.     LOCATE i + 2, 49: PRINT USING "####"; i; c1(i);
  76. RESTORE count
  77. FOR i = 1 TO 28
  78.     LOCATE i + 1, 60: PRINT " ";
  79.     LOCATE i + 1, 60
  80.     IF c2(i) >= max THEN
  81.         max = c2(i)
  82.         PRINT "*";
  83.     ELSE
  84.         PRINT " ";
  85.     END IF
  86.     PRINT y$(i);
  87.     PRINT USING " #### "; c2(i);
  88.     c! = c2(i) * cps!
  89.     c! = c! + c! * .07
  90.     PRINT USING "####.##"; c!;
  91. xn = (xe - xb) / 16
  92. yn = (ye - yb) / 8
  93. LOCATE 27, 52: PRINT xn;
  94. LOCATE 28, 52: PRINT yn;
  95. LOCATE 29, 52: PRINT xn * yn;
  96.  
  97. count:
  98. DATA 00,01,02,03,04,05,06
  99. DATA 11,12,13,14,15,16
  100. DATA 22,23,24,25,26
  101. DATA 33,34,35,36
  102. DATA 44,45,46
  103. DATA 55,56
  104. DATA 66
  105.  
  106. dots:
  107. DATA 1,0,0
  108. DATA 2,0,-1,0,1
  109. DATA 3,-1,-1,0,0,1,1
  110. DATA 4,-1,1,-1,-1,1,-1,1,1
  111. DATA 5,-1,1,-1,-1,1,-1,1,1,0,0
  112. DATA 6,-1,1,-1,0,-1,-1,1,1,1,0,1,-1
  113. DATA 3,1,-1,0,0,-1,1
  114.  

Attachments:
Requires HEATH.BMP

 
                                                                                                                                         (219 downloads previously)
 
HEATH.BMP


BMP2Dominoes.png

13
General, Math & Geometry / InForm Calculator by Terry Ritchie
« on: September 24, 2021, 05:12:55 am »
InForm Calculator

Author: @TerryRitchie
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=507.0
Version: 1

Description:
This is a calculator program I have been working on.  This little program gave me the general feel for InForm and got me back into programming QB64, a win-win.

Source Code:
Code: QB64: [Select]
  1.  
  2.     ':  ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
  3.     ': ||C |||A |||L |||C |||U |||L |||A |||T |||O |||R ||
  4.     ': ||__|||__|||__|||__|||__|||__|||__|||__|||__|||__||
  5.     ': |/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|
  6.     ':
  7.     ': QB64 Calculator V1.0
  8.     ': Terry Ritchie - 08/29/18
  9.     ':
  10.     ': Built as a clone of the Windows 7 standard calculator
  11.     ': An exersize in getting to know the InForm library
  12.     ':
  13.     ': This program uses
  14.     ': InForm - GUI library for QB64 - Beta version 7
  15.     ': Fellippe Heitor, 2016-2018 - fellippe@qb64.org - [member=2]FellippeHeitor[/member]
  16.     ': https://github.com/FellippeHeitor/InForm
  17.     '----------------------------------------------------------------------------------------------------------------------
  18.      
  19.     ': Program constants: -------------------------------------------------------------------------------------------------
  20.      
  21.     CONST EQUATE = 0
  22.     CONST ADDITION = 1
  23.     CONST SUBTRACTION = 2
  24.     CONST MULTIPLICATION = 3
  25.     CONST DIVISION = 4
  26.      
  27.     ': Controls' IDs: -----------------------------------------------------------------------------------------------------
  28.      
  29.     DIM SHARED Calculator AS LONG
  30.     DIM SHARED frmResults AS LONG
  31.     DIM SHARED mnuEdit AS LONG
  32.     DIM SHARED mnuHelp AS LONG
  33.     DIM SHARED butMC AS LONG
  34.     DIM SHARED butMR AS LONG
  35.     DIM SHARED butMS AS LONG
  36.     DIM SHARED butMplus AS LONG
  37.     DIM SHARED butMminus AS LONG
  38.     DIM SHARED butBS AS LONG
  39.     DIM SHARED butCE AS LONG
  40.     DIM SHARED butC AS LONG
  41.     DIM SHARED butSign AS LONG
  42.     DIM SHARED butSQR AS LONG
  43.     DIM SHARED but7 AS LONG
  44.     DIM SHARED but8 AS LONG
  45.     DIM SHARED but9 AS LONG
  46.     DIM SHARED butDivide AS LONG
  47.     DIM SHARED butPercent AS LONG
  48.     DIM SHARED but4 AS LONG
  49.     DIM SHARED but5 AS LONG
  50.     DIM SHARED but6 AS LONG
  51.     DIM SHARED butMultiply AS LONG
  52.     DIM SHARED butReciprocate AS LONG
  53.     DIM SHARED but1 AS LONG
  54.     DIM SHARED but2 AS LONG
  55.     DIM SHARED but3 AS LONG
  56.     DIM SHARED butSubtract AS LONG
  57.     DIM SHARED but0 AS LONG
  58.     DIM SHARED butPoint AS LONG
  59.     DIM SHARED butAdd AS LONG
  60.     DIM SHARED butEqual AS LONG
  61.     DIM SHARED mnuCopy AS LONG
  62.     DIM SHARED mnuPaste AS LONG
  63.     DIM SHARED mnuAbout AS LONG
  64.     DIM SHARED lblAnswer AS LONG
  65.     DIM SHARED lblMemory AS LONG
  66.     DIM SHARED lblHistory AS LONG
  67.      
  68.     ': Program variables: -------------------------------------------------------------------------------------------------
  69.      
  70.     DIM SHARED operand$ '                       current operand
  71.     DIM SHARED history$ '                       calculation history
  72.     DIM SHARED operand1 AS DOUBLE '             first operand enetered
  73.     DIM SHARED operand2 AS DOUBLE '             second operand entered
  74.     DIM SHARED operator AS INTEGER '            current operator selected
  75.     DIM SHARED operator$(4)
  76.     DIM SHARED previousoperator AS INTEGER '    previous operator saved
  77.     DIM SHARED resetoperand AS INTEGER '        True when operand entry needs reset
  78.     DIM SHARED memory AS DOUBLE '               value stored in memory
  79.     DIM SHARED nohistory AS INTEGER
  80.      
  81.     ': External modules: --------------------------------------------------------------------------------------------------
  82.      
  83.     '$INCLUDE:'InForm\InForm.ui'
  84.     '$INCLUDE:'InForm\xp.uitheme'
  85.     '$INCLUDE:'Calculator.frm'
  86.      
  87.     ': Windows libraries : ------------------------------------------------------------------------------------------------
  88.      
  89.     ' Windows system sounds
  90.     ' Code contributed by QB64.org Wiki - Author unknown
  91.     ' http://qb64.org/wiki/Windows_Libraries#Windows_Sounds
  92.     ' Note: this Windows library will fail in SDL versions of QB64
  93.     '       change DECLARE LIBRARY to DECLARE DYNAMIC LIBRARY "Wimmm"
  94.     '       to allow this library to work with SDL versions of QB64
  95.      
  96.         FUNCTION PlaySound (pszSound AS STRING, BYVAL hmod AS INTEGER, BYVAL fdwSound AS INTEGER)
  97.     END DECLARE
  98.      
  99.     ': Program procedures: ------------------------------------------------------------------------------------------------
  100.      
  101.     '----------------------------------------------------------------------------------------------------------------------
  102.     SUB ALERT () '                                                                                                  ALERT()
  103.         '------------------------------------------------------------------------------------------------------------------
  104.      
  105.         ' Plays Windows default sounds
  106.         ' Sounds can be invoked using the following strings:
  107.         ' "SystemDefault","SystemExclamation","SystemExit","SystemHand","SystemQuestion","SystemStart","SystemWelcome"
  108.      
  109.         s = PlaySound("SystemDefault" + CHR$(0), 0, 65537) '                play Windows default system sound
  110.      
  111.     END SUB
  112.      
  113.     '----------------------------------------------------------------------------------------------------------------------
  114.     FUNCTION CLEAN$ (n AS DOUBLE) '                                                                                CLEAN$()
  115.         '------------------------------------------------------------------------------------------------------------------
  116.      
  117.         ' Return number (n) as a string with no leading/trailing spaces
  118.         ' Add leading zero if necessary
  119.      
  120.         DIM c$ ' n converted to a clean string
  121.      
  122.         c$ = LTRIM$(RTRIM$(STR$(n))) '                                      create clean string
  123.         IF ASC(c$, 1) = 46 THEN '                                           first character a decimal point?
  124.             c$ = "0" + c$ '                                                 yes, add leading zero
  125.         ELSEIF ASC(c$, 1) = 45 AND ASC(c$, 2) = 46 THEN '                   no, minus sign then decimal point?
  126.             c$ = "-0" + RIGHT$(c$, LEN(c$) - 1) '                           yes, add leading zero
  127.         END IF
  128.         CLEAN$ = c$ '                                                       return cleaned string
  129.      
  130.      
  131.     '----------------------------------------------------------------------------------------------------------------------
  132.     SUB UPDATEOPERAND (n$) '                                                                                UPDATEOPERAND()
  133.         '------------------------------------------------------------------------------------------------------------------
  134.      
  135.         ' Add user entries to operand
  136.         ' Keep operand to a max length of 16 numbers (not including decimal point)
  137.         ' Reset user operand input as needed
  138.         ' Keep leading zero for decimal values between one and negative one
  139.      
  140.         DIM olen AS INTEGER ' operand length
  141.      
  142.         IF resetoperand THEN '                                              new operand input?
  143.             operand$ = "" '                                                 yes, reset operand
  144.             resetoperand = False '                                          reset trigger
  145.         END IF
  146.         IF n$ = "." THEN '                                                  adding decimal point?
  147.             IF INSTR(operand$, ".") = 0 THEN '                              yes, already a decimal point?
  148.                 IF operand$ = "" THEN '                                     no, has operand been reset?
  149.                     n$ = "0." '                                             yes, add leading zero
  150.                 END IF
  151.             ELSE '                                                          yes, decimal point exists
  152.                 n$ = "" '                                                   ignore user request for decimal point
  153.             END IF
  154.         END IF
  155.         operand$ = operand$ + n$ '                                          update operand with user entry
  156.         olen = LEN(operand$) '                                              get length of operand
  157.         IF INSTR(operand$, ".") > 0 THEN olen = olen - 1 '                  don't count decimal point if preset
  158.         IF olen > 16 THEN operand$ = LEFT$(operand$, LEN(operand$) - 1) '   keep operand within 16 number limit
  159.      
  160.     END SUB
  161.      
  162.     '----------------------------------------------------------------------------------------------------------------------
  163.     SUB CALCULATE () '                                                                                          CALCULATE()
  164.         '------------------------------------------------------------------------------------------------------------------
  165.      
  166.         ' Calculate operand values based on operator previously used
  167.         ' Store result back into current operand
  168.      
  169.         SELECT CASE previousoperator '                                      which operator to use?
  170.             CASE ADDITION '                                                 add the operands
  171.                 operand$ = CLEAN$(operand1 + operand2) '                    perform clculation
  172.             CASE SUBTRACTION '                                              subtract the operands
  173.                 operand$ = CLEAN$(operand1 - operand2) '                    perform calculation
  174.             CASE MULTIPLICATION '                                           multiply the operands
  175.                 operand$ = CLEAN$(operand1 * operand2) '                    perform calculation
  176.             CASE DIVISION '                                                 divide the operands
  177.                 IF operand2 = 0 THEN '                                      dividing by zero?
  178.                     ALERT '                                                 get user's attention
  179.                     operand$ = "Can't divide by zero!" '                    yes, not in this universe!
  180.                 ELSE '                                                      no, physics is safe for now
  181.                     operand$ = CLEAN$(operand1 / operand2) '                perform calculation
  182.                 END IF
  183.         END SELECT
  184.         calculated = True
  185.      
  186.     END SUB
  187.      
  188.     '----------------------------------------------------------------------------------------------------------------------
  189.     SUB COMMITOPERAND () '                                                                                  COMMITOPERAND()
  190.         '------------------------------------------------------------------------------------------------------------------
  191.      
  192.         ' Get value of current operand
  193.         ' Calculate operands if necessary
  194.         ' Save current operand value
  195.         ' Remember the operator that invoked this routine
  196.      
  197.         operand2 = VAL(operand$) '                                          store value of current operand
  198.         IF previousoperator THEN '                                          previous operator selected?
  199.             CALCULATE '                                                     yes, calculate
  200.         END IF
  201.         operand1 = VAL(operand$) '                                          move current total to previous value
  202.         previousoperator = operator '                                       move current operator to previous operator
  203.         resetoperand = True '                                               trigger an operand reset
  204.      
  205.     END SUB
  206.      
  207.     '----------------------------------------------------------------------------------------------------------------------
  208.     SUB SCANKEYBOARD () '                                                                                    SCANKEYBOARD()
  209.         '------------------------------------------------------------------------------------------------------------------
  210.      
  211.         ' Scan the keyboard for user keystrokes
  212.         ' Invoke the appropriate button for the desired key
  213.      
  214.         DIM k$ ' key pressed by user
  215.         DIM ctrl AS INTEGER
  216.      
  217.         k$ = INKEY$ '                                                       look for a key press
  218.         IF k$ <> "" THEN '                                                  was a key pressed?
  219.             SELECT CASE k$ '                                                yes, which one?
  220.                 CASE "0" '                                                  zero key pressed
  221.                     __UI_Click (but0) '                                     manually click the zero button
  222.                 CASE "1" '                                                  etc..
  223.                     __UI_Click (but1) '                                     etc..
  224.                 CASE "2"
  225.                     __UI_Click (but2)
  226.                 CASE "3"
  227.                     __UI_Click (but3)
  228.                 CASE "4"
  229.                     __UI_Click (but4)
  230.                 CASE "5"
  231.                     __UI_Click (but5)
  232.                 CASE "6"
  233.                     __UI_Click (but6)
  234.                 CASE "7"
  235.                     __UI_Click (but7)
  236.                 CASE "8"
  237.                     __UI_Click (but8)
  238.                 CASE "9"
  239.                     __UI_Click (but9)
  240.                 CASE "."
  241.                     __UI_Click (butPoint)
  242.                 CASE "+"
  243.                     __UI_Click (butAdd)
  244.                 CASE "-"
  245.                     __UI_Click (butSubtract)
  246.                 CASE "*"
  247.                     __UI_Click (butMultiply)
  248.                 CASE "/"
  249.                     __UI_Click (butDivide)
  250.                 CASE "%"
  251.                     __UI_Click (butPercent)
  252.                 CASE "=", CHR$(13) '                                        treat ENTER and = the same
  253.                     __UI_Click (butEqual)
  254.                 CASE CHR$(8) '                                              backspace key pressed
  255.                     __UI_Click (butBS)
  256.      
  257.                 CASE "c", "C" '                                             CTRL-C copy
  258.                     ctrl = _KEYDOWN(100305) OR _KEYDOWN(100306)
  259.                     IF ctrl THEN BEEP
  260.      
  261.                     ' Will need to investigate how to capture CTRL-C and CTRL-V
  262.                     ' Neither the code above or below works
  263.      
  264.                 CASE "v", "V" '                                             CTRL-V paste
  265.                     IF __UI_CtrlIsDown THEN '                               is CTRL key presses?
  266.      
  267.                         BEEP
  268.      
  269.                     END IF
  270.      
  271.             END SELECT
  272.         END IF
  273.      
  274.     END SUB
  275.      
  276.     '----------------------------------------------------------------------------------------------------------------------
  277.     SUB ADDHISTORY (h$) '                                                                                      ADDHISTORY()
  278.         '------------------------------------------------------------------------------------------------------------------
  279.      
  280.         IF nohistory THEN
  281.             nohistory = False
  282.         ELSE
  283.             history$ = history$ + h$
  284.         END IF
  285.      
  286.     END SUB
  287.      
  288.     '----------------------------------------------------------------------------------------------------------------------
  289.      
  290.     ': Event procedures: --------------------------------------------------------------------------------------------------
  291.      
  292.     SUB __UI_BeforeInit
  293.      
  294.     END SUB
  295.      
  296.     SUB __UI_OnLoad
  297.      
  298.         operator$(1) = " + " ' define operator strings
  299.         operator$(2) = " - "
  300.         operator$(3) = " * "
  301.         operator$(4) = " / "
  302.      
  303.     END SUB
  304.      
  305.     SUB __UI_BeforeUpdateDisplay
  306.         'This event occurs at approximately 30 frames per second.
  307.         'You can change the update frequency by calling SetFrameRate DesiredRate%
  308.      
  309.         DIM answer$ ' current operand displayed
  310.      
  311.         SCANKEYBOARD '                                                      process keys pressed by user
  312.      
  313.         Caption(lblHistory) = history$ + operator$(operator) '              update history display
  314.      
  315.         answer$ = operand$ '                                                copy operand
  316.         IF answer$ = "" THEN answer$ = "0" '                                set to zero if empty
  317.      
  318.         Caption(lblAnswer) = answer$ '                                      display current operand
  319.      
  320.         IF memory THEN '                                                    does memory have value?
  321.             Caption(lblMemory) = "M" '                                      yes, apply screen indication
  322.         ELSE '                                                              no
  323.             Caption(lblMemory) = "" '                                       remove screen indication
  324.         END IF
  325.      
  326.     END SUB
  327.      
  328.     SUB __UI_BeforeUnload
  329.         'If you set __UI_UnloadSignal = False here you can
  330.         'cancel the user's request to close.
  331.      
  332.     END SUB
  333.      
  334.     SUB __UI_Click (id AS LONG)
  335.         SELECT CASE id
  336.             CASE Calculator
  337.      
  338.             CASE frmResults
  339.      
  340.             CASE mnuEdit
  341.      
  342.             CASE mnuHelp
  343.      
  344.                 ': memory buttons: ----------------------------------------------------------------------------------------
  345.      
  346.             CASE butMC '                                                    memory clear clicked
  347.                 memory = 0 '                                                reset memory value
  348.      
  349.             CASE butMR '                                                    memory recall clicked
  350.                 IF memory THEN '                                            memory available?
  351.                     operand$ = CLEAN$(memory) '                             Yes, make it the current operand
  352.                     resetoperand = True '                                   trigger an operand reset
  353.                 END IF
  354.      
  355.             CASE butMS '                                                    memory store clicked
  356.                 memory = VAL(operand$) '                                    overwrite memory with current operand
  357.                 resetoperand = True '                                       trigger an operand reset
  358.      
  359.             CASE butMplus '                                                 memory addition clicked
  360.                 memory = memory + VAL(operand$) '                           add current operand to memory
  361.                 resetoperand = True '                                       trigger an operand reset
  362.      
  363.             CASE butMminus '                                                memory subtraction clicked
  364.                 memory = memory - VAL(operand$) '                           subtract current operand from memory
  365.                 resetoperand = True '                                       trigger an operand reset
  366.      
  367.                 ': clear buttons: -----------------------------------------------------------------------------------------
  368.      
  369.             CASE butCE '                                                    clear entry clicked
  370.                 operand$ = "" '                                             reset current operand
  371.      
  372.             CASE butC '                                                     clear clicked
  373.                 operand1 = 0 '                                              initialize all values
  374.                 operand2 = 0
  375.                 operator = 0
  376.                 previousoperator = 0
  377.                 operand$ = ""
  378.                 history$ = ""
  379.      
  380.             CASE butBS '                                                    backspace clicked
  381.                 IF LEN(operand$) THEN '                                     characters in operand?
  382.                     operand$ = LEFT$(operand$, LEN(operand$) - 1) '         yes, remove right-most character
  383.                 END IF
  384.      
  385.                 ': calculation buttons: -----------------------------------------------------------------------------------
  386.      
  387.             CASE butReciprocate '                                           reciprocate clicked
  388.                 IF VAL(operand$) THEN '                                     dividing by zero?
  389.      
  390.                     ADDHISTORY (operator$(previousoperator) + "Reciproc(" + operand$ + ")")
  391.                     nohistory = True '                                      skip operand history next time
  392.                     operator = EQUATE
  393.      
  394.                     operand$ = CLEAN$(1 / VAL(operand$)) '                  no, calculate reciprocate
  395.                 ELSE '                                                      yes, physics will collapse!
  396.                     ALERT '                                                 get user's attention
  397.                     operand$ = "Can't divide by zero!" '                    report error to user
  398.                 END IF
  399.                 resetoperand = True '                                       trigger an operand reset
  400.      
  401.             CASE butSQR '                                                   square root clicked
  402.                 IF VAL(operand$) >= 0 THEN '                                positive value?
  403.      
  404.                     ADDHISTORY (operator$(previousoperator) + "SQRT(" + operand$ + ")")
  405.                     nohistory = True '                                      skip operand history next time
  406.                     operator = EQUATE
  407.      
  408.                     operand$ = CLEAN$(SQR(VAL(operand$))) '                 yes, calculate square root
  409.                 ELSE '                                                      no, value is negative
  410.                     ALERT '                                                 get user's attention
  411.                     operand$ = "Invalid input!" '                           nice try buddy
  412.                 END IF
  413.                 resetoperand = True '                                       trigger an operand reset
  414.      
  415.             CASE butPercent '                                               percent clicked
  416.                 operand$ = CLEAN$(operand1 * VAL(operand$) / 100) '         calculate percentage of previous operand
  417.                 resetoperand = True
  418.      
  419.             CASE butSign '                                                  sign clicked
  420.                 IF VAL(operand$) THEN '                                     value equal to zero?
  421.                     operand$ = CLEAN$(-VAL(operand$)) '                     no, reverse sign of operand
  422.                 END IF
  423.      
  424.                 ': number buttons: ----------------------------------------------------------------------------------------
  425.      
  426.             CASE but0 '                                                     zero clicked
  427.                 IF VAL(operand$) OR INSTR(operand$, ".") THEN '             ok to add a zero?
  428.                     UPDATEOPERAND ("0") '                                   yes, append zero
  429.                 END IF
  430.      
  431.             CASE but1 '                                                     one clicked
  432.                 UPDATEOPERAND ("1") '                                       append one
  433.      
  434.             CASE but2 '                                                     etc..
  435.                 UPDATEOPERAND ("2") '                                       etc..
  436.      
  437.             CASE but3
  438.                 UPDATEOPERAND ("3")
  439.      
  440.             CASE but4
  441.                 UPDATEOPERAND ("4")
  442.      
  443.             CASE but5
  444.                 UPDATEOPERAND ("5")
  445.      
  446.             CASE but6
  447.                 UPDATEOPERAND ("6")
  448.      
  449.             CASE but7
  450.                 UPDATEOPERAND ("7")
  451.      
  452.             CASE but8
  453.                 UPDATEOPERAND ("8")
  454.      
  455.             CASE but9
  456.                 UPDATEOPERAND ("9")
  457.      
  458.             CASE butPoint
  459.                 UPDATEOPERAND (".")
  460.      
  461.                 ': operator buttons: --------------------------------------------------------------------------------------
  462.      
  463.             CASE butDivide '                                                divide clicked
  464.      
  465.                 ADDHISTORY (operator$(previousoperator) + operand$)
  466.      
  467.                 operator = DIVISION '                                       remember operator selected
  468.                 COMMITOPERAND '                                             save operand
  469.      
  470.             CASE butMultiply '                                              multiply clicked
  471.      
  472.                 ADDHISTORY (operator$(previousoperator) + operand$)
  473.      
  474.                 operator = MULTIPLICATION '                                 remember operator selected
  475.                 COMMITOPERAND '                                             save operand
  476.      
  477.             CASE butSubtract '                                              subtract clicked
  478.      
  479.                 ADDHISTORY (operator$(previousoperator) + operand$)
  480.      
  481.                 operator = SUBTRACTION '                                    remember operator selected
  482.                 COMMITOPERAND '                                             save operand
  483.      
  484.             CASE butAdd '                                                   addition clicked
  485.      
  486.                 ADDHISTORY (operator$(previousoperator) + operand$)
  487.      
  488.                 operator = ADDITION '                                       remember operator selected
  489.                 COMMITOPERAND '                                             save operand
  490.      
  491.             CASE butEqual '                                                 equal clicked
  492.      
  493.                 history$ = ""
  494.                 operator = EQUATE '                                         remember operator selected
  495.                 COMMITOPERAND '                                             save operand
  496.                 previousoperator = 0
  497.      
  498.      
  499.             CASE mnuCopy
  500.      
  501.             CASE mnuPaste
  502.      
  503.             CASE mnuAbout
  504.                 operand$ = "InForm Calculator 1.0"
  505.                 resetoperand = True
  506.      
  507.             CASE lblAnswer
  508.      
  509.             CASE lblMemory
  510.      
  511.             CASE lblHistory
  512.      
  513.         END SELECT
  514.     END SUB
  515.      
  516.     SUB __UI_MouseEnter (id AS LONG)
  517.         SELECT CASE id
  518.             CASE Calculator
  519.      
  520.             CASE frmResults
  521.      
  522.             CASE mnuEdit
  523.      
  524.             CASE mnuHelp
  525.      
  526.             CASE butMC
  527.      
  528.             CASE butMR
  529.      
  530.             CASE butMS
  531.      
  532.             CASE butMplus
  533.      
  534.             CASE butMminus
  535.      
  536.             CASE butBS
  537.      
  538.             CASE butCE
  539.      
  540.             CASE butC
  541.      
  542.             CASE butSign
  543.      
  544.             CASE butSQR
  545.      
  546.             CASE but7
  547.      
  548.             CASE but8
  549.      
  550.             CASE but9
  551.      
  552.             CASE butDivide
  553.      
  554.             CASE butPercent
  555.      
  556.             CASE but4
  557.      
  558.             CASE but5
  559.      
  560.             CASE but6
  561.      
  562.             CASE butMultiply
  563.      
  564.             CASE butReciprocate
  565.      
  566.             CASE but1
  567.      
  568.             CASE but2
  569.      
  570.             CASE but3
  571.      
  572.             CASE butSubtract
  573.      
  574.             CASE but0
  575.      
  576.             CASE butPoint
  577.      
  578.             CASE butAdd
  579.      
  580.             CASE butEqual
  581.      
  582.             CASE mnuCopy
  583.      
  584.             CASE mnuPaste
  585.      
  586.             CASE mnuAbout
  587.      
  588.             CASE lblAnswer
  589.      
  590.             CASE lblMemory
  591.      
  592.             CASE lblHistory
  593.      
  594.         END SELECT
  595.     END SUB
  596.      
  597.     SUB __UI_MouseLeave (id AS LONG)
  598.         SELECT CASE id
  599.             CASE Calculator
  600.      
  601.             CASE frmResults
  602.      
  603.             CASE mnuEdit
  604.      
  605.             CASE mnuHelp
  606.      
  607.             CASE butMC
  608.      
  609.             CASE butMR
  610.      
  611.             CASE butMS
  612.      
  613.             CASE butMplus
  614.      
  615.             CASE butMminus
  616.      
  617.             CASE butBS
  618.      
  619.             CASE butCE
  620.      
  621.             CASE butC
  622.      
  623.             CASE butSign
  624.      
  625.             CASE butSQR
  626.      
  627.             CASE but7
  628.      
  629.             CASE but8
  630.      
  631.             CASE but9
  632.      
  633.             CASE butDivide
  634.      
  635.             CASE butPercent
  636.      
  637.             CASE but4
  638.      
  639.             CASE but5
  640.      
  641.             CASE but6
  642.      
  643.             CASE butMultiply
  644.      
  645.             CASE butReciprocate
  646.      
  647.             CASE but1
  648.      
  649.             CASE but2
  650.      
  651.             CASE but3
  652.      
  653.             CASE butSubtract
  654.      
  655.             CASE but0
  656.      
  657.             CASE butPoint
  658.      
  659.             CASE butAdd
  660.      
  661.             CASE butEqual
  662.      
  663.             CASE mnuCopy
  664.      
  665.             CASE mnuPaste
  666.      
  667.             CASE mnuAbout
  668.      
  669.             CASE lblAnswer
  670.      
  671.             CASE lblMemory
  672.      
  673.             CASE lblHistory
  674.      
  675.         END SELECT
  676.     END SUB
  677.      
  678.     SUB __UI_FocusIn (id AS LONG)
  679.         SELECT CASE id
  680.             CASE butMC
  681.      
  682.             CASE butMR
  683.      
  684.             CASE butMS
  685.      
  686.             CASE butMplus
  687.      
  688.             CASE butMminus
  689.      
  690.             CASE butBS
  691.      
  692.             CASE butCE
  693.      
  694.             CASE butC
  695.      
  696.             CASE butSign
  697.      
  698.             CASE butSQR
  699.      
  700.             CASE but7
  701.      
  702.             CASE but8
  703.      
  704.             CASE but9
  705.      
  706.             CASE butDivide
  707.      
  708.             CASE butPercent
  709.      
  710.             CASE but4
  711.      
  712.             CASE but5
  713.      
  714.             CASE but6
  715.      
  716.             CASE butMultiply
  717.      
  718.             CASE butReciprocate
  719.      
  720.             CASE but1
  721.      
  722.             CASE but2
  723.      
  724.             CASE but3
  725.      
  726.             CASE butSubtract
  727.      
  728.             CASE but0
  729.      
  730.             CASE butPoint
  731.      
  732.             CASE butAdd
  733.      
  734.             CASE butEqual
  735.      
  736.         END SELECT
  737.     END SUB
  738.      
  739.     SUB __UI_FocusOut (id AS LONG)
  740.         'This event occurs right before a control loses focus.
  741.         'To prevent a control from losing focus, set __UI_KeepFocus = True below.
  742.         SELECT CASE id
  743.             CASE butMC
  744.      
  745.             CASE butMR
  746.      
  747.             CASE butMS
  748.      
  749.             CASE butMplus
  750.      
  751.             CASE butMminus
  752.      
  753.             CASE butBS
  754.      
  755.             CASE butCE
  756.      
  757.             CASE butC
  758.      
  759.             CASE butSign
  760.      
  761.             CASE butSQR
  762.      
  763.             CASE but7
  764.      
  765.             CASE but8
  766.      
  767.             CASE but9
  768.      
  769.             CASE butDivide
  770.      
  771.             CASE butPercent
  772.      
  773.             CASE but4
  774.      
  775.             CASE but5
  776.      
  777.             CASE but6
  778.      
  779.             CASE butMultiply
  780.      
  781.             CASE butReciprocate
  782.      
  783.             CASE but1
  784.      
  785.             CASE but2
  786.      
  787.             CASE but3
  788.      
  789.             CASE butSubtract
  790.      
  791.             CASE but0
  792.      
  793.             CASE butPoint
  794.      
  795.             CASE butAdd
  796.      
  797.             CASE butEqual
  798.      
  799.         END SELECT
  800.     END SUB
  801.      
  802.     SUB __UI_MouseDown (id AS LONG)
  803.         SELECT CASE id
  804.             CASE Calculator
  805.      
  806.             CASE frmResults
  807.      
  808.             CASE mnuEdit
  809.      
  810.             CASE mnuHelp
  811.      
  812.             CASE butMC
  813.      
  814.             CASE butMR
  815.      
  816.             CASE butMS
  817.      
  818.             CASE butMplus
  819.      
  820.             CASE butMminus
  821.      
  822.             CASE butBS
  823.      
  824.             CASE butCE
  825.      
  826.             CASE butC
  827.      
  828.             CASE butSign
  829.      
  830.             CASE butSQR
  831.      
  832.             CASE but7
  833.      
  834.             CASE but8
  835.      
  836.             CASE but9
  837.      
  838.             CASE butDivide
  839.      
  840.             CASE butPercent
  841.      
  842.             CASE but4
  843.      
  844.             CASE but5
  845.      
  846.             CASE but6
  847.      
  848.             CASE butMultiply
  849.      
  850.             CASE butReciprocate
  851.      
  852.             CASE but1
  853.      
  854.             CASE but2
  855.      
  856.             CASE but3
  857.      
  858.             CASE butSubtract
  859.      
  860.             CASE but0
  861.      
  862.             CASE butPoint
  863.      
  864.             CASE butAdd
  865.      
  866.             CASE butEqual
  867.      
  868.             CASE mnuCopy
  869.      
  870.             CASE mnuPaste
  871.      
  872.             CASE mnuAbout
  873.      
  874.             CASE lblAnswer
  875.      
  876.             CASE lblMemory
  877.      
  878.             CASE lblHistory
  879.      
  880.         END SELECT
  881.     END SUB
  882.      
  883.     SUB __UI_MouseUp (id AS LONG)
  884.         SELECT CASE id
  885.             CASE Calculator
  886.      
  887.             CASE frmResults
  888.      
  889.             CASE mnuEdit
  890.      
  891.             CASE mnuHelp
  892.      
  893.             CASE butMC
  894.      
  895.             CASE butMR
  896.      
  897.             CASE butMS
  898.      
  899.             CASE butMplus
  900.      
  901.             CASE butMminus
  902.      
  903.             CASE butBS
  904.      
  905.             CASE butCE
  906.      
  907.             CASE butC
  908.      
  909.             CASE butSign
  910.      
  911.             CASE butSQR
  912.      
  913.             CASE but7
  914.      
  915.             CASE but8
  916.      
  917.             CASE but9
  918.      
  919.             CASE butDivide
  920.      
  921.             CASE butPercent
  922.      
  923.             CASE but4
  924.      
  925.             CASE but5
  926.      
  927.             CASE but6
  928.      
  929.             CASE butMultiply
  930.      
  931.             CASE butReciprocate
  932.      
  933.             CASE but1
  934.      
  935.             CASE but2
  936.      
  937.             CASE but3
  938.      
  939.             CASE butSubtract
  940.      
  941.             CASE but0
  942.      
  943.             CASE butPoint
  944.      
  945.             CASE butAdd
  946.      
  947.             CASE butEqual
  948.      
  949.             CASE mnuCopy
  950.      
  951.             CASE mnuPaste
  952.      
  953.             CASE mnuAbout
  954.      
  955.             CASE lblAnswer
  956.      
  957.             CASE lblMemory
  958.      
  959.             CASE lblHistory
  960.      
  961.         END SELECT
  962.     END SUB
  963.      
  964.     SUB __UI_KeyPress (id AS LONG)
  965.         'When this event is fired, __UI_KeyHit will contain the code of the key hit.
  966.         'You can change it and even cancel it by making it = 0
  967.      
  968.         SELECT CASE id
  969.             CASE butMC
  970.      
  971.             CASE butMR
  972.      
  973.             CASE butMS
  974.      
  975.             CASE butMplus
  976.      
  977.             CASE butMminus
  978.      
  979.             CASE butBS
  980.      
  981.             CASE butCE
  982.      
  983.             CASE butC
  984.      
  985.             CASE butSign
  986.      
  987.             CASE butSQR
  988.      
  989.             CASE but7
  990.      
  991.             CASE but8
  992.      
  993.             CASE but9
  994.      
  995.             CASE butDivide
  996.      
  997.             CASE butPercent
  998.      
  999.             CASE but4
  1000.      
  1001.             CASE but5
  1002.      
  1003.             CASE but6
  1004.      
  1005.             CASE butMultiply
  1006.      
  1007.             CASE butReciprocate
  1008.      
  1009.             CASE but1
  1010.      
  1011.             CASE but2
  1012.      
  1013.             CASE but3
  1014.      
  1015.             CASE butSubtract
  1016.      
  1017.             CASE but0
  1018.      
  1019.             CASE butPoint
  1020.      
  1021.             CASE butAdd
  1022.      
  1023.             CASE butEqual
  1024.      
  1025.         END SELECT
  1026.     END SUB
  1027.      
  1028.     SUB __UI_TextChanged (id AS LONG)
  1029.         SELECT CASE id
  1030.         END SELECT
  1031.     END SUB
  1032.      
  1033.     SUB __UI_ValueChanged (id AS LONG)
  1034.         SELECT CASE id
  1035.         END SELECT
  1036.     END SUB
  1037.      
  1038.     SUB __UI_FormResized
  1039.      
  1040.     END SUB
  1041.  

Calculator Screenshot.jpg

 
                                                                                                                                         (175 downloads previously)

14
Audio / Drum Machine Prototype by Dav
« on: September 23, 2021, 05:41:59 am »
Drum Machine Prototype

Author: @Dav
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=2459.msg117923#msg117923
Version: v0.1c

Description:
Here's a drum machine, or beat maker.  I started making another puzzle game, but it turned into a little music making program instead.   With this you can make drum beats using 14 drum instrument samples.

Controls:
L Load Pattern
S Save Pattern
M Toggle Metronome

Source Code:
The code is given here for reference.  You will need to load all the files from the .zip.
Code: QB64: [Select]
  1.     '=======================
  2.     'DRUMMACHINE.BAS - v0.1c
  3.     '=======================
  4.     'QB64 Drum machine
  5.     'Make drum beats using 16 drum sounds.
  6.     'Coded by Dav for QB64, MAY/2020
  7.      
  8.     'Follow this programs development here:
  9.     'https://www.qb64.org/forum/index.php?topic=2459.0
  10.      
  11.     '===================================================================
  12.     'New in v0.1c...
  13.      
  14.     'Added: Added program _TITLE and _ICON.
  15.     'Added: New logo with keyboard command help.
  16.     'Added: Shows big TEMPO (BMP) font at top left.
  17.     'Added: Shows green playing position line down grid.
  18.     '       (replaced little white moving marker)
  19.     'Added: Give user notices when a Save/Load is done.
  20.     'Added: Instrument names can now be clicked on to mute/unmute.
  21.     'Added: Now shows on screen if metronome is ON/OFF
  22.     'Fixed: Changed keyboard input method. Much more responsive.
  23.     '
  24.     '===================================================================
  25.     ''NOTE: You need "\drummachine-data\" and all of its data files!
  26.     '===================================================================
  27.      
  28.     '=====
  29.     'ABOUT:
  30.     '=====
  31.      
  32.     'This is a very basic drum machine with limited capabilities.
  33.     'With it you can program beats (limited to 2 bars of 4/4 now).
  34.     'It uses 16 real drum sounds to make a real sound drum beat.
  35.     'Drum patterns can be saved and loaded by file DRUMMACHINE.SAV.
  36.     'I just wanted to see if QB64 can handle something like this,
  37.     'and it looks like it can.  So a more serious program can be tackled.
  38.     'The real drum sound samples were all found in public domain.
  39.      
  40.     '==========
  41.     'HOW TO USE:
  42.     '==========
  43.      
  44.     'The grid represents bars and notes that you can click on.
  45.     'Click on squares in a row to to add sound for that beat.
  46.     'Click an square again to turn it back off or change it's volume.
  47.     'A bright red square is loudest, a darker red is softer volume.
  48.      
  49.     'Click on the instrument name on left screen to mute/unmute it.
  50.      
  51.     'The following keys can be used as well:
  52.      
  53.     '* +/- keys:  Speeds up and slow down tempo (shown upper left)
  54.     '* SPACE key: Will pause and resume the playback.
  55.     '* ENTER:     Resets current playback marker to the beginning.
  56.     '* M:         Turns on/off metonome click sound (default is on)
  57.     '* C:         Clears the playing grid (starts over).
  58.     '* L:         Loads last saved grid pattern from DRUMMACHINE.SAV
  59.     '* S:         Saves current grid pattern to DRUMMACHINE.SAV.
  60.     '* D:         Enters drawing mode (fast filling of boxes.
  61.     '             (While in it, enter ESC to exit drawing mode)
  62.     '* ESC:       Exits program. DOES NOT ATUMATICALLY SAVE ON EXIT.
  63.      
  64.     '======================================================================
  65.      
  66.     $EXEICON:'.\drummachine-data\icon.ico'
  67.     _ICON
  68.      
  69.     'define playing grid and button deminsions
  70.     DIM SHARED row: row = 16 'rows in playing grid
  71.     DIM SHARED col: col = 8 * 4 'columns in grid (8 beats, 4 boxes per beat)
  72.     DIM SHARED size: size = 30 ' pixel size of buttons
  73.     DIM SHARED buttons: buttons = row * col ' total number of buttons on playing grid
  74.      
  75.     'define button data
  76.     DIM SHARED buttonv(row * col) ' num data for button
  77.     DIM SHARED buttonx(row * col), buttony(row * col) 'top x/y cords of buttons
  78.     DIM SHARED buttonx2(row * col), buttony2(row * col) ' bottom x/y cords of buttons
  79.      
  80.     'define intrument name data
  81.     DIM SHARED instv(row * col) 'value for is intrument on or off
  82.     DIM SHARED instx(row * col), insty(row * col) 'top x/y cords of instr names
  83.      
  84.     'share these sound files
  85.     DIM SHARED crash&, crash2&, ride&, ride2&, hhopen&, hhclosed&, snare&, kick&, tamb&, gong2&
  86.     DIM SHARED tomhigh&, tommid&, tomlow&, cowbell&, shaker&, gong&, vibraslap&, vibraslap2&
  87.     DIM SHARED clave&, trianglelong&, triangleshort&
  88.      
  89.     '====================================================
  90.      
  91.     'Set screen based on grid deminsions
  92.      
  93.     SCREEN _NEWIMAGE(size * col + 100, size * row + 100, 32)
  94.     DO: LOOP UNTIL _SCREENEXISTS 'Make sure window exists before TITLE used.
  95.      
  96.     _TITLE "QB64 Drum Machine"
  97.      
  98.     '===================================================
  99.      
  100.     CLS , _RGB(42, 42, 42)
  101.      
  102.     'Load title top area.
  103.     ttmp = _LOADIMAGE("drummachine-data\title.png")
  104.     _PUTIMAGE (5, 5), ttmp: _FREEIMAGE ttmp
  105.      
  106.     'Load media sounds used
  107.     click& = _SNDOPEN("drummachine-data\click.ogg")
  108.     hhopen& = _SNDOPEN("drummachine-data\hhopen.ogg")
  109.     hhclosed& = _SNDOPEN("drummachine-data\hhclosed.ogg")
  110.     kick& = _SNDOPEN("drummachine-data\kick.ogg")
  111.     snare& = _SNDOPEN("drummachine-data\snare.ogg")
  112.     crash& = _SNDOPEN("drummachine-data\crash.ogg")
  113.     crash2& = _SNDOPEN("drummachine-data\crash.ogg")
  114.     ride& = _SNDOPEN("drummachine-data\ride.ogg")
  115.     ride2& = _SNDOPEN("drummachine-data\ride.ogg")
  116.     tomhigh& = _SNDOPEN("drummachine-data\tomhigh.ogg")
  117.     tommid& = _SNDOPEN("drummachine-data\tommid.ogg")
  118.     tomlow& = _SNDOPEN("drummachine-data\tomlow.ogg")
  119.     cowbell& = _SNDOPEN("drummachine-data\cowbell.ogg")
  120.     shaker& = _SNDOPEN("drummachine-data\shaker.ogg")
  121.     vibraslap& = _SNDOPEN("drummachine-data\vibraslap.ogg")
  122.     gong& = _SNDOPEN("drummachine-data\gong.ogg")
  123.     vibraslap2& = _SNDOPEN("drummachine-data\vibraslap.ogg")
  124.     gong2& = _SNDOPEN("drummachine-data\gong.ogg")
  125.     tamb& = _SNDOPEN("drummachine-data\tamb.ogg")
  126.     clave& = _SNDOPEN("drummachine-data\clave.ogg")
  127.     trianglelong& = _SNDOPEN("drummachine-data\trianglelong.ogg")
  128.     triangleshort& = _SNDOPEN("drummachine-data\triangleshort.ogg")
  129.      
  130.     'Load special number font images fro BMP display
  131.     DIM SHARED num&(0 TO 9)
  132.     FOR t = 0 TO 9
  133.         n$ = LTRIM$(RTRIM$(STR$(t)))
  134.         num&(t) = _LOADIMAGE("drummachine-data\font\" + n$ + ".png")
  135.     NEXT
  136.      
  137.      
  138.     '===================================================
  139.      
  140.     'Set program defaults
  141.      
  142.     beats = 8 'number of beats in pattern
  143.     tempo = 80 'tempo of drum pattern
  144.     curbeat = 1 'start at bar 1
  145.     clickon = 1 'turn on click sound, on the beat
  146.     playing = 1 'Pattern is playing
  147.     firstlaunch = 1 'flag to know when program first launches
  148.      
  149.      
  150.     '=========================================================
  151.     START:
  152.     '========
  153.      
  154.     'Init the grids button values (x/y, data)
  155.     bc = 1 'counter
  156.     FOR r = 1 TO row
  157.         FOR c = 1 TO col
  158.             x = (c * size) + 100: y = (r * size) + 100
  159.             buttonx(bc) = x - size: buttonx2(bc) = x ' generate x/y values
  160.             buttony(bc) = y - size: buttony2(bc) = y
  161.             buttonv(bc) = 0 'default button is OFF
  162.             bc = bc + 1
  163.         NEXT
  164.     NEXT
  165.      
  166.     'Show metronome on/off
  167.     Metronome clickon
  168.      
  169.     'Show the grid buttons
  170.     bc = 1
  171.     FOR r = 1 TO row
  172.         FOR c = 1 TO col
  173.             Show "drummachine-data\off.jpg", buttonx(bc), buttony(bc), 0
  174.             bc = bc + 1
  175.         NEXT
  176.     NEXT
  177.      
  178.      
  179.     'Draw beat lines, every 4 squares ...
  180.     bc = 1
  181.     FOR c = 1 TO col STEP 4
  182.         LINE (buttonx(bc), buttony(bc))-(buttonx(bc), buttony(bc) + (size * row)), _RGB(128, 128, 0), B
  183.         bc = bc + 4
  184.     NEXT
  185.      
  186.     '====================================
  187.      
  188.     'Init Instrument name data
  189.     FOR c = 1 TO 16
  190.         instv(c) = 1 'all instruments on by default
  191.     NEXT
  192.     bc = 1
  193.     FOR c = 1 TO col * row STEP col
  194.         instx(bc) = 0: insty(bc) = 70 + (bc * 30)
  195.         bc = bc + 1
  196.     NEXT
  197.     'show the nstrument names
  198.     FOR c = 1 TO 16
  199.         ShowInst c, instx(c), insty(c)
  200.     NEXT
  201.      
  202.     '==============================================
  203.      
  204.     'Show current TEMPO (BMP) on upper left
  205.     FPRINT 140, 15, 20, 40, LTRIM$(RTRIM$(STR$(tempo)))
  206.      
  207.     '================================================
  208.      
  209.     'If firstlaunch, load the saved pattern file
  210.     IF firstlaunch = 1 THEN
  211.         firstlaunch = 0
  212.         GOSUB loadfile
  213.     END IF
  214.      
  215.     '============================================================
  216.      
  217.     MAIN:
  218.     '=====
  219.      
  220.     'Main Loop here
  221.     DO
  222.      
  223.         GOSUB GetUserInput
  224.      
  225.         IF playing THEN
  226.      
  227.             IF clickon THEN
  228.                 SELECT CASE curbeat
  229.                     CASE 1, 2, 3, 4, 5, 6, 7, 8: _SNDPLAY click&
  230.                 END SELECT
  231.             END IF
  232.      
  233.             IF curbeat = 1 THEN PlayBeat (1)
  234.             IF curbeat = 1.25 THEN PlayBeat (2)
  235.             IF curbeat = 1.50 THEN PlayBeat (3)
  236.             IF curbeat = 1.75 THEN PlayBeat (4)
  237.             IF curbeat = 2 THEN PlayBeat (5)
  238.             IF curbeat = 2.25 THEN PlayBeat (6)
  239.             IF curbeat = 2.50 THEN PlayBeat (7)
  240.             IF curbeat = 2.75 THEN PlayBeat (8)
  241.             IF curbeat = 3 THEN PlayBeat (9)
  242.             IF curbeat = 3.25 THEN PlayBeat (10)
  243.             IF curbeat = 3.50 THEN PlayBeat (11)
  244.             IF curbeat = 3.75 THEN PlayBeat (12)
  245.             IF curbeat = 4 THEN PlayBeat (13)
  246.             IF curbeat = 4.25 THEN PlayBeat (14)
  247.             IF curbeat = 4.50 THEN PlayBeat (15)
  248.             IF curbeat = 4.75 THEN PlayBeat (16)
  249.             IF curbeat = 5 THEN PlayBeat (17)
  250.             IF curbeat = 5.25 THEN PlayBeat (18)
  251.             IF curbeat = 5.50 THEN PlayBeat (19)
  252.             IF curbeat = 5.75 THEN PlayBeat (20)
  253.             IF curbeat = 6 THEN PlayBeat (21)
  254.             IF curbeat = 6.25 THEN PlayBeat (22)
  255.             IF curbeat = 6.50 THEN PlayBeat (23)
  256.             IF curbeat = 6.75 THEN PlayBeat (24)
  257.             IF curbeat = 7 THEN PlayBeat (25)
  258.             IF curbeat = 7.25 THEN PlayBeat (26)
  259.             IF curbeat = 7.50 THEN PlayBeat (27)
  260.             IF curbeat = 7.75 THEN PlayBeat (28)
  261.             IF curbeat = 8 THEN PlayBeat (29)
  262.             IF curbeat = 8.25 THEN PlayBeat (30)
  263.             IF curbeat = 8.50 THEN PlayBeat (31)
  264.             IF curbeat = 8.75 THEN PlayBeat (32)
  265.      
  266.             curbeat = curbeat + .25
  267.             IF curbeat > beats + .75 THEN curbeat = 1
  268.      
  269.             'Delay routine, based on TEMP
  270.             d1 = TIMER
  271.             DO
  272.                 d2 = TIMER
  273.      
  274.                 'still get user input while delaying....
  275.                 GOSUB GetUserInput
  276.      
  277.             LOOP UNTIL d2 - d1 >= (60 / 4 / tempo)
  278.      
  279.         END IF
  280.      
  281.     LOOP
  282.      
  283.     '===============================
  284.      
  285.     EndProgram:
  286.      
  287.     _SNDCLOSE click&
  288.     _SNDCLOSE hhopen&
  289.     _SNDCLOSE hhclosed&
  290.     _SNDCLOSE kick&
  291.     _SNDCLOSE snare&
  292.     _SNDCLOSE crash&
  293.     _SNDCLOSE crash2&
  294.     _SNDCLOSE ride&
  295.     _SNDCLOSE ride2&
  296.     _SNDCLOSE tomhigh&
  297.     _SNDCLOSE tommid&
  298.     _SNDCLOSE tomlow&
  299.     _SNDCLOSE cowbell&
  300.     _SNDCLOSE shaker&
  301.     _SNDCLOSE vibraslap&
  302.     _SNDCLOSE gong&
  303.     _SNDCLOSE vibraslap2&
  304.     _SNDCLOSE gong2&
  305.     _SNDCLOSE tamb&
  306.     _SNDCLOSE clave&
  307.     _SNDCLOSE trianglelong&
  308.     _SNDCLOSE triangleshort&
  309.      
  310.     END
  311.      
  312.      
  313.      
  314.     '================================================
  315.     GetUserInput:
  316.     '============
  317.      
  318.     trap = _MOUSEINPUT
  319.      
  320.     'if left mouse button clicked
  321.      
  322.         mx = _MOUSEX: my = _MOUSEY 'current mouse position
  323.      
  324.         'see if a grid button was pressed
  325.         FOR t = 1 TO buttons
  326.             bx = buttonx(t): bx2 = buttonx2(t)
  327.             by = buttony(t): by2 = buttony2(t)
  328.      
  329.             'If clicked on a grid button...
  330.             IF mx >= bx AND mx <= bx2 AND my >= by AND my <= by2 THEN
  331.                 IF _MOUSEBUTTON(1) THEN
  332.      
  333.                     'change its value...
  334.                     buttonv(t) = buttonv(t) + 1
  335.                     IF buttonv(t) > 2 THEN buttonv(t) = 0
  336.                     'LOCATE 1, 1: PRINT t   'for testing purposes...
  337.                     SELECT CASE buttonv(t)
  338.                         CASE 0: Show "drummachine-data\off.jpg", buttonx(t), buttony(t), 0
  339.                         CASE 1: Show "drummachine-data\hot.jpg", buttonx(t), buttony(t), 0
  340.                         CASE 2: Show "drummachine-data\med.jpg", buttonx(t), buttony(t), 0
  341.                     END SELECT
  342.                 ELSE
  343.                     buttonv(t) = 0
  344.                     Show "drummachine-data\off.jpg", buttonx(t), buttony(t), 0
  345.                 END IF
  346.      
  347.             END IF
  348.         NEXT
  349.      
  350.         'see if a instrument name was pressed
  351.         FOR t = 1 TO 16
  352.             bx = instx(t): bx2 = instx(t) + 100
  353.             by = insty(t): by2 = insty(t) + 30
  354.      
  355.             'If clicked on an instrument name...
  356.             IF mx >= bx AND mx <= bx2 AND my >= by AND my <= by2 THEN
  357.                 IF _MOUSEBUTTON(1) THEN
  358.      
  359.                     'change its value...
  360.                     instv(t) = instv(t) + 1
  361.                     IF instv(t) > 1 THEN instv(t) = 0
  362.                     'redraw instrument name here
  363.                     ShowInst t, instx(t), insty(t)
  364.                 END IF
  365.      
  366.             END IF
  367.         NEXT
  368.      
  369.      
  370.         IF _MOUSEBUTTON(1) THEN
  371.             'wait until mouse button up to continue
  372.             WHILE _MOUSEBUTTON(1) <> 0: n = _MOUSEINPUT: WEND
  373.         END IF
  374.      
  375.     END IF
  376.      
  377.      
  378.     'check is user made a keypress
  379.      
  380.      
  381.         CASE "D": 'd enters drawing mode
  382.             DO
  383.                 trap = _MOUSEINPUT
  384.                 IF _MOUSEBUTTON(1) OR _MOUSEBUTTON(2) THEN
  385.                     mx = _MOUSEX: my = _MOUSEY
  386.                     'see if a button was pressed
  387.                     FOR t = 1 TO buttons
  388.                         bx = buttonx(t): bx2 = buttonx2(t)
  389.                         by = buttony(t): by2 = buttony2(t)
  390.                         IF mx >= bx AND mx <= bx2 AND my >= by AND my <= by2 THEN
  391.                             IF _MOUSEBUTTON(1) THEN
  392.                                 buttonv(t) = 1
  393.                                 Show "drummachine-data\hot.jpg", buttonx(t), buttony(t), 0
  394.                             ELSE
  395.                                 buttonv(t) = 0
  396.                                 Show "drummachine-data\off.jpg", buttonx(t), buttony(t), 0
  397.                             END IF
  398.                         END IF
  399.                     NEXT
  400.                 END IF
  401.             LOOP UNTIL INKEY$ = CHR$(27)
  402.      
  403.         CASE "C": GOTO START 'C clears playing grid, starts over
  404.      
  405.         CASE "S": 's = saves current pattern to file
  406.             backtmp& = _COPYIMAGE(_DISPLAY)
  407.             f$ = "drummachine-data\savingpattern.png"
  408.             ttmp = _LOADIMAGE(f$)
  409.             _PUTIMAGE (350, 250), ttmp: _FREEIMAGE ttmp
  410.             _DELAY 1
  411.             OPEN "drummachine.sav" FOR OUTPUT AS #3
  412.             PRINT #3, MKI$(tempo);
  413.             PRINT #3, MKI$(buttons);
  414.             FOR fs = 1 TO buttons
  415.                 PRINT #3, MKI$(buttonv(fs));
  416.             NEXT
  417.             CLOSE #3
  418.             _PUTIMAGE (0, 0), backtmp&
  419.      
  420.         CASE "L"
  421.             backtmp& = _COPYIMAGE(_DISPLAY)
  422.             f$ = "drummachine-data\loadingpattern.png"
  423.             ttmp = _LOADIMAGE(f$)
  424.             _PUTIMAGE (350, 250), ttmp: _FREEIMAGE ttmp
  425.             _DELAY .5
  426.             _PUTIMAGE (0, 0), backtmp&
  427.             GOSUB loadfile
  428.      
  429.         CASE " " 'SPACE pauses and resumes playing
  430.             IF playing = 1 THEN
  431.                 playing = 0
  432.             ELSE
  433.                 playing = 1
  434.             END IF
  435.      
  436.         CASE CHR$(13) 'ENTER resets marker to beginning
  437.             'erase all marker positions
  438.             FOR e = 1 TO 32
  439.                 SELECT CASE e
  440.                     CASE 1, 5, 9, 13, 17, 21, 25, 29
  441.                         LINE (buttonx(e), buttony(e))-(buttonx(e), buttony(e) + (size * row)), _RGB(128, 128, 0), B
  442.                     CASE ELSE
  443.                         LINE (buttonx(e), buttony(e))-(buttonx(e), buttony(e) + (size * row)), _RGB(0, 0, 0), B
  444.                 END SELECT
  445.             NEXT
  446.             LINE (buttonx(1), buttony(1))-(buttonx(1), buttony(1) + (size * row)), _RGB(0, 255, 128), B
  447.             curbeat = 1: GOTO MAIN
  448.      
  449.         CASE "M" 'm = turn metronome click on/off
  450.             IF clickon = 1 THEN
  451.                 clickon = 0
  452.             ELSE
  453.                 clickon = 1
  454.             END IF
  455.             Metronome clickon
  456.      
  457.         CASE "+": tempo = tempo + 1: IF tempo > 280 THEN tempo = 280
  458.             FPRINT 140, 15, 20, 40, LTRIM$(RTRIM$(STR$(tempo)))
  459.      
  460.         CASE "-": tempo = tempo - 1: IF tempo < 40 THEN tempo = 40
  461.             FPRINT 140, 15, 20, 40, LTRIM$(RTRIM$(STR$(tempo)))
  462.         CASE CHR$(27): GOTO EndProgram
  463.      
  464.     END SELECT
  465.      
  466.     RETURN
  467.      
  468.      
  469.     '=================================================================
  470.      
  471.     loadfile: 'Loads pattern from save file
  472.     '=======
  473.      
  474.     fil$ = "drummachine.sav"
  475.     IF _FILEEXISTS(fil$) THEN
  476.         OPEN fil$ FOR BINARY AS #3
  477.         IF LOF(3) <= 1028 THEN
  478.             tempo = CVI(INPUT$(2, 3))
  479.             bb = CVI(INPUT$(2, 3))
  480.             FOR b = 1 TO bb
  481.                 buttonv(b) = CVI(INPUT$(2, 3))
  482.                 SELECT CASE buttonv(b)
  483.                     CASE 0: Show "drummachine-data\off.jpg", buttonx(b), buttony(b), 0
  484.                     CASE 1: Show "drummachine-data\hot.jpg", buttonx(b), buttony(b), 0
  485.                     CASE 2: Show "drummachine-data\med.jpg", buttonx(b), buttony(b), 0
  486.                 END SELECT
  487.             NEXT
  488.             CLOSE 3
  489.             'Show current TEMPO (BMP) on upper left
  490.             FPRINT 140, 15, 20, 40, LTRIM$(RTRIM$(STR$(tempo)))
  491.             GOTO MAIN
  492.         ELSE
  493.             CLOSE 3
  494.             'print error message here
  495.         END IF
  496.     END IF
  497.      
  498.     RETURN
  499.      
  500.     '========================================================
  501.      
  502.     SUB Show (nam$, x, y, dly)
  503.         'Loads & puts image filename img$ on screen at x,y
  504.         'dly is optional delay after putting image on screen
  505.         'SUB frees up image handle after loading file.
  506.         ttmp = _LOADIMAGE(nam$)
  507.         _PUTIMAGE (x + 1, y + 1)-(x - 1 + size - 1, y - 1 + size - 1), ttmp: _FREEIMAGE ttmp
  508.         IF dly <> 0 THEN _DELAY dly
  509.     END SUB
  510.      
  511.     '===============================================
  512.      
  513.     SUB ShowInst (num, x, y)
  514.         'This SUB loads the instrumet name image files
  515.         src$ = "drummachine-data\"
  516.         IF instv(num) = 1 THEN pre$ = "_" ELSE pre$ = ""
  517.         IF num = 1 THEN n$ = pre$ + "crash.png"
  518.         IF num = 2 THEN n$ = pre$ + "ride.png"
  519.         IF num = 3 THEN n$ = pre$ + "hhopen.png"
  520.         IF num = 4 THEN n$ = pre$ + "hhclosed.png"
  521.         IF num = 5 THEN n$ = pre$ + "tomhigh.png"
  522.         IF num = 6 THEN n$ = pre$ + "tommid.png"
  523.         IF num = 7 THEN n$ = pre$ + "tomlow.png"
  524.         IF num = 8 THEN n$ = pre$ + "snare.png"
  525.         IF num = 9 THEN n$ = pre$ + "kick.png"
  526.         IF num = 10 THEN n$ = pre$ + "cowbell.png"
  527.         IF num = 11 THEN n$ = pre$ + "shaker.png"
  528.         IF num = 12 THEN n$ = pre$ + "tambourine.png"
  529.         IF num = 13 THEN n$ = pre$ + "vibraslap.png"
  530.         IF num = 14 THEN n$ = pre$ + "gong.png"
  531.         IF num = 15 THEN n$ = pre$ + "triangle.png"
  532.         IF num = 16 THEN n$ = pre$ + "clave.png"
  533.      
  534.         fil$ = src$ + n$
  535.         ttmp = _LOADIMAGE(fil$)
  536.         _PUTIMAGE (x, y), ttmp: _FREEIMAGE ttmp
  537.     END SUB
  538.      
  539.     '===============================================
  540.      
  541.     SUB PlayBeat (num)
  542.         'This SUB plays the sounds on current beat position.
  543.         'It also shows the playing marker moving across the grid
  544.      
  545.         'erase previous marker pos displayed first, and redraw the 4 beat lines...
  546.         IF num = 1 THEN
  547.             'erase the end playing position on grid
  548.             LINE (buttonx(col), buttony(col))-(buttonx(col), buttony(col) + (size * row)), _RGB(0, 0, 0), B
  549.         ELSE
  550.             'erase the last beat position
  551.             LINE (buttonx(num - 1), buttony(num - 1))-(buttonx(num - 1), buttony(num - 1) + (size * row)), _RGB(0, 0, 0), B
  552.             'if last position was one of the 4 beat lines, redraw it
  553.             SELECT CASE (num - 1)
  554.                 CASE 1, 5, 9, 13, 17, 21, 25, 29
  555.                     LINE (buttonx(num - 1), buttony(num - 1))-(buttonx(num - 1), buttony(num - 1) + (size * row)), _RGB(128, 128, 0), B
  556.             END SELECT
  557.         END IF
  558.      
  559.         'Show curreny marker position
  560.         'Now Draw current playing position beat line
  561.         LINE (buttonx(num), buttony(num))-(buttonx(num), buttony(num) + (size * row)), _RGB(0, 255, 128), B
  562.      
  563.         'Play sounds on the current beat position, if inst not muted
  564.         'play crash
  565.         IF instv(1) = 1 THEN
  566.             IF buttonv(num) = 1 THEN _SNDVOL crash&, 6: _SNDPLAY crash& '1
  567.             IF buttonv(num) = 2 THEN _SNDVOL crash2&, .2: _SNDPLAY crash2& '1
  568.         END IF
  569.         'play ride
  570.         IF instv(2) = 1 THEN
  571.             IF buttonv(num + (col * 1)) = 1 THEN _SNDVOL ride&, 5: _SNDPLAY ride& '2
  572.             IF buttonv(num + (col * 1)) = 2 THEN _SNDVOL ride2&, .2: _SNDPLAY ride2& '2
  573.         END IF
  574.         'play hhopen
  575.         IF instv(3) = 1 THEN
  576.             IF buttonv(num + (col * 2)) = 1 THEN _SNDSETPOS hhopen&, 0: _SNDVOL hhopen&, 5: _SNDPLAY hhopen& '3
  577.             IF buttonv(num + (col * 2)) = 2 THEN _SNDSETPOS hhopen&, 0: _SNDVOL hhopen&, .15: _SNDPLAY hhopen& '3
  578.         END IF
  579.         'play hhclosed
  580.         IF instv(4) = 1 THEN
  581.             IF buttonv(num + (col * 3)) = 1 THEN _SNDSTOP hhopen&: _SNDVOL hhclosed&, 1: _SNDPLAY hhclosed& '4
  582.             IF buttonv(num + (col * 3)) = 2 THEN _SNDSTOP hhopen&: _SNDVOL hhclosed&, .2: _SNDPLAY hhclosed& '4
  583.         END IF
  584.         'play tom high
  585.         IF instv(5) THEN
  586.             IF buttonv(num + (col * 4)) = 1 THEN _SNDVOL tomhigh&, 9: _SNDPLAY tomhigh& '5
  587.             IF buttonv(num + (col * 4)) = 2 THEN _SNDVOL tomhigh&, .1: _SNDPLAY tomhigh& '5
  588.         END IF
  589.         'play tom mid
  590.         IF instv(6) THEN
  591.             IF buttonv(num + (col * 5)) = 1 THEN _SNDVOL tommid&, 9: _SNDPLAY tommid& '6
  592.             IF buttonv(num + (col * 5)) = 2 THEN _SNDVOL tommid&, .1: _SNDPLAY tommid& '6
  593.         END IF
  594.         'play tom low
  595.         IF instv(7) THEN
  596.             IF buttonv(num + (col * 6)) = 1 THEN _SNDVOL tomlow&, 9: _SNDPLAY tomlow& '7
  597.             IF buttonv(num + (col * 6)) = 2 THEN _SNDVOL tomlow&, .1: _SNDPLAY tomlow& '7
  598.         END IF
  599.         'play snare
  600.         IF instv(8) THEN
  601.             IF buttonv(num + (col * 7)) = 1 THEN _SNDVOL snare&, 1: _SNDPLAY snare& '8
  602.             IF buttonv(num + (col * 7)) = 2 THEN _SNDVOL snare&, .1: _SNDPLAY snare& '8
  603.         END IF
  604.         'play kick
  605.         IF instv(9) THEN
  606.             IF buttonv(num + (col * 8)) = 1 THEN _SNDVOL kick&, 1: _SNDPLAY kick& '9
  607.             IF buttonv(num + (col * 8)) = 2 THEN _SNDVOL kick&, .1: _SNDPLAY kick& '9
  608.         END IF
  609.         'play cowbell
  610.         IF instv(10) THEN
  611.             IF buttonv(num + (col * 9)) = 1 THEN _SNDVOL cowbell&, .3: _SNDPLAY cowbell& '10
  612.             IF buttonv(num + (col * 9)) = 2 THEN _SNDVOL cowbell&, .02: _SNDPLAY cowbell& '10
  613.         END IF
  614.         'play shaker
  615.         IF instv(11) THEN
  616.             IF buttonv(num + (col * 10)) = 1 THEN _SNDVOL shaker&, .6: _SNDPLAY shaker& '11
  617.             IF buttonv(num + (col * 10)) = 2 THEN _SNDVOL shaker&, .1: _SNDPLAY shaker& '11
  618.         END IF
  619.         'play tambourine
  620.         IF instv(12) THEN
  621.             IF buttonv(num + (col * 11)) = 1 THEN _SNDVOL tamb&, 1: _SNDPLAY tamb& '12
  622.             IF buttonv(num + (col * 11)) = 2 THEN _SNDVOL tamb&, .1: _SNDPLAY tamb& '12
  623.         END IF
  624.         'play vibraslap
  625.         IF instv(13) THEN
  626.             IF buttonv(num + (col * 12)) = 1 THEN _SNDVOL vibraslap&, .1: _SNDPLAY vibraslap& '13
  627.             IF buttonv(num + (col * 12)) = 2 THEN _SNDVOL vibraslap2&, .05: _SNDPLAY vibraslap2& '13
  628.         END IF
  629.         'play gong
  630.         IF instv(14) THEN
  631.             IF buttonv(num + (col * 13)) = 1 THEN _SNDVOL gong&, .1: _SNDPLAY gong& '14
  632.             IF buttonv(num + (col * 13)) = 2 THEN _SNDVOL gong2&, .03: _SNDPLAY gong2& '14
  633.         END IF
  634.         'play triangle
  635.         IF instv(15) THEN
  636.             IF buttonv(num + (col * 14)) = 1 THEN _SNDVOL trianglelong&, .3: _SNDPLAY trianglelong& '15
  637.             IF buttonv(num + (col * 14)) = 2 THEN _SNDVOL triangleshort&, .3: _SNDPLAY triangleshort& '15
  638.         END IF
  639.         'play clave
  640.         IF instv(16) THEN
  641.             IF buttonv(num + (col * 15)) = 1 THEN _SNDVOL clave&, .6: _SNDPLAY clave& '16
  642.             IF buttonv(num + (col * 15)) = 2 THEN _SNDVOL clave&, .02: _SNDPLAY clave& '16
  643.         END IF
  644.     END SUB
  645.      
  646.     SUB FPRINT (x, y, xsize, ysize, num$)
  647.         LINE (x, y)-(x + 100, y + ysize), _RGB(42, 42, 42), BF
  648.         FOR t = 1 TO LEN(num$)
  649.             n = VAL(MID$(num$, t, 1))
  650.             _PUTIMAGE (x, y)-(x + xsize, y + ysize), num&(n)
  651.             x = x + xsize: y = y + zsize
  652.         NEXT
  653.     END SUB
  654.      
  655.     SUB Metronome (way)
  656.         IF way = 1 THEN
  657.             f$ = "drummachine-data\metron.png"
  658.         ELSE
  659.             f$ = "drummachine-data\metroff.png"
  660.         END IF
  661.         ttmp = _LOADIMAGE(f$)
  662.         _PUTIMAGE (875, 72), ttmp: _FREEIMAGE ttmp
  663.     END SUB
  664.  
  665.  

 
                                                                                                                                         (117 downloads previously)
Drum Machine Screenshot.png

15
Audio / Simple Piano by Terry Ritchie
« on: September 22, 2021, 05:49:27 am »
QB64 Simple Piano

Author: @TerryRitchie
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=2400.msg116185#msg116185
Version: 2

Description:
This is a little program I wrote back in 2014. It's a one-octave piano simulator that allows you to switch between octaves. The asset files (images and sounds) are contained in the zip file. Be sure to place the \PIANO folder in your QB64 folder and load the PIANO.bas file into the IDE.  Make sure that you have the RUN option “Output EXE to Source Folder” checked.

Directions for use are at the top of the source code listing.

Note: I wrote this using version 0.954 and because of that the sounds are loaded using options not available in the latest versions of QB64. If you compile this using an SDL version of QB64 the piano keys will stop the sound as soon as you release them. In non SDL versions of QB64 the key sustains even after released.

The thread for this project also contains variants by @Petr for saving the tunes created with this program.




Source Code:
Librarian's note: The code is given here for reference only.  Load the .bas file in the folder.
Code: QB64: [Select]
  1.     '*
  2.     '* QB64 Simple Piano
  3.     '*
  4.     '* by Terry Ritchie
  5.     '*
  6.     '* Demonstrates the use of external sound files to create a realistic piano.
  7.     '*
  8.     '* Modified 03/26/20
  9.     '* Removed the need for a separate .\PIANO\ folder to hold the graphics and
  10.     '* sound assets. All assets are now to be contained in the same folder as
  11.     '* PIANO.EXE
  12.     '*
  13.     '* ESC         - exit program
  14.     '* RIGHT ARROW - increase octave
  15.     '* LEFT ARROW  - decrease octave
  16.     '* Piano Keys  -  R T  U I O   (black keys)
  17.     '*             - D F GH J K L  (white keys)
  18.     '*
  19.      
  20.     '--------------------------------
  21.     '- Variable Declaration Section -
  22.     '--------------------------------
  23.      
  24.     TYPE IVORY '          key information
  25.         u AS INTEGER '    upper case value
  26.         l AS INTEGER '    lower case value
  27.         Down AS INTEGER ' key position
  28.         x AS INTEGER '    key indicator x coordinate
  29.         y AS INTEGER '    key indicator y coordinate
  30.     END TYPE
  31.      
  32.     DIM K(12) AS IVORY '  key information array
  33.     DIM Tone&(88) '       piano key sounds array
  34.     DIM imgPiano& '       piano keyboard image
  35.     DIM imgAoctave& '     active octave image
  36.     DIM imgIoctave& '     inactive octave image
  37.     DIM Octave% '         current octave
  38.     DIM Khit& '           keyboard status
  39.     DIM Keys% '           key cycle counter
  40.      
  41.     '----------------------------
  42.     '- Main Program Begins Here -
  43.     '----------------------------
  44.      
  45.     LOADPIANO '                                                          load piano assets
  46.     SCREEN _NEWIMAGE(512, 263, 32) '                                     create default screen
  47.     _TITLE "PIANO" '                                                     set window title
  48.     _SCREENMOVE _MIDDLE '                                                center window on desktop
  49.     _DELAY .25
  50.     _PUTIMAGE (0, 0), imgPiano& '                                        show piano image
  51.     SHOWOCTAVE '                                                         update octave indicator
  52.     DO '                                                                 MAIN LOOP begins
  53.         Khit& = _KEYHIT '                                                get keyboard status
  54.         IF Khit& THEN '                                                  was a key hit?
  55.             IF Khit& = 19200 OR Khit& = 19712 THEN '                     yes, left or right key?
  56.                 IF Khit& = 19200 THEN '                                  yes, left key?
  57.                     Octave% = Octave% - 1 '                              yes, decrease octave
  58.                     IF Octave% = -1 THEN Octave% = 0 '                   keep octave in limits
  59.                 ELSE '                                                   no, must be right key
  60.                     Octave% = Octave% + 1 '                              increase octave
  61.                     IF Octave% = 5 THEN Octave% = 4 '                    keep octave in limits
  62.                 END IF
  63.                 SHOWOCTAVE '                                             update octave indicator
  64.             ELSEIF Khit& = 27 THEN '                                     no, escape key?
  65.                 QUIT '                                                   yes, quit program
  66.             END IF
  67.         END IF
  68.         FOR Keys% = 1 TO 12 '                                            cycle through keys
  69.             IF _KEYDOWN(K(Keys%).u) OR _KEYDOWN(K(Keys%).l) THEN '       key pressed?
  70.                 PRESS Keys% '                                            yes, play note
  71.             ELSE '                                                       no
  72.                 RELEASE Keys% '                                          remove key indicator
  73.             END IF
  74.         NEXT Keys%
  75.         _DISPLAY '                                                       update screen changes
  76.     LOOP '                                                               MAIN LOOP back
  77.      
  78.     '-----------------------------------
  79.     '- Function and Subroutine section -
  80.     '-----------------------------------
  81.      
  82.     '--------------------------------------------------------------------------------------------
  83.      
  84.     SUB QUIT ()
  85.      
  86.         '*
  87.         '* Cleans RAM by removing all image and sound assets and then exits to Windows.
  88.         '*
  89.      
  90.         SHARED Tone&() '     need access to piano key sounds array
  91.         SHARED imgPiano& '   need access to piano keyboard image
  92.         SHARED imgAoctave& ' need access to active octave image
  93.         SHARED imgIoctave& ' need access to inactive octave image
  94.      
  95.         DIM Count% '         generic counter
  96.      
  97.         FOR Count% = 1 TO 88 '        cycle through all 88 sound files
  98.             _SNDCLOSE Tone&(Count%) ' remove sound file from RAM
  99.         NEXT Count%
  100.         _FREEIMAGE imgPiano& '        remove piano image from RAM
  101.         _FREEIMAGE imgAoctave& '      remove active octave image from RAM
  102.         _FREEIMAGE imgIoctave& '      remove inactive octave image from RAM
  103.         SYSTEM '                      return to Windows
  104.      
  105.     END SUB
  106.      
  107.     '--------------------------------------------------------------------------------------------
  108.      
  109.     SUB RELEASE (k%)
  110.      
  111.         '*
  112.         '* Removes key press display and sets key as being released
  113.         '*
  114.      
  115.         SHARED K() AS IVORY ' need access to key information array
  116.      
  117.         IF K(k%).Down THEN '                                                  is key pressed?
  118.             K(k%).Down = 0 '                                                  yes, set it as released
  119.             SELECT CASE k% '                                                  which key is it?
  120.                 CASE 1, 3, 5, 6, 8, 10, 12 '                                  white key
  121.                     LINE (K(k%).x, K(k%).y)-(K(k%).x + 27, K(k%).y + 27), _RGB32(255, 255, 255), BF
  122.                 CASE ELSE '                                                   black key
  123.                     LINE (K(k%).x, K(k%).y)-(K(k%).x + 27, K(k%).y + 27), _RGB32(32, 32, 32), BF
  124.             END SELECT
  125.         END IF
  126.      
  127.     END SUB
  128.      
  129.     '--------------------------------------------------------------------------------------------
  130.      
  131.     SUB PRESS (k%)
  132.      
  133.         '*
  134.         '* Applies key press display and sets key as being pressed
  135.         '*
  136.      
  137.         SHARED K() AS IVORY ' need access to key information array
  138.         SHARED Tone&() '      need access to piano key sounds array
  139.         SHARED Octave% '      need access to current octave
  140.      
  141.         IF NOT K(k%).Down THEN '                                               is key released?
  142.             K(k%).Down = -1 '                                                  yes, set it as pressed
  143.             _SNDPLAY Tone&(Octave% * 12 + k%) '                                play tone for key
  144.             SELECT CASE k% '                                                   which key is it?
  145.                 CASE 1, 3, 5, 6, 8, 10, 12 '                                   white key
  146.                     LINE (K(k%).x, K(k%).y)-(K(k%).x + 27, K(k%).y + 27), _RGB32(0, 0, 0), BF
  147.                 CASE ELSE '                                                    black key
  148.                     LINE (K(k%).x, K(k%).y)-(K(k%).x + 27, K(k%).y + 27), _RGB32(255, 255, 255), BF
  149.             END SELECT
  150.         END IF
  151.      
  152.     END SUB
  153.      
  154.     '--------------------------------------------------------------------------------------------
  155.      
  156.     SUB SHOWOCTAVE
  157.      
  158.         '*
  159.         '* Updates the small top piano keyboard to show current active octave
  160.         '*
  161.      
  162.         SHARED Octave% '     need access to current octave
  163.         SHARED imgAoctave& ' need access to active octave image
  164.         SHARED imgIoctave& ' need access to inactive octave image
  165.      
  166.         DIM Count% '         generic counter
  167.      
  168.         FOR Count% = 0 TO 4 '                                    cycle through octaves
  169.             IF Count% = Octave% THEN '                           current octave?
  170.                 _PUTIMAGE (96 + (Count% * 64), 0), imgAoctave& ' yes, place active octave image
  171.             ELSE '                                               no
  172.                 _PUTIMAGE (96 + (Count% * 64), 0), imgIoctave& ' place inactive octave image
  173.             END IF
  174.         NEXT Count%
  175.      
  176.     END SUB
  177.      
  178.     '--------------------------------------------------------------------------------------------
  179.      
  180.     SUB LOADPIANO ()
  181.      
  182.         '*
  183.         '* Loads the piano sounds and images and initializes variables
  184.         '*
  185.      
  186.         SHARED K() AS IVORY ' need access to key information array
  187.         SHARED Tone&() '      need access to piano key sounds array
  188.         SHARED imgPiano& '    need access to piano keyboard image
  189.         SHARED imgAoctave& '  need access to active octave image
  190.         SHARED imgIoctave& '  need access to inactive octave image
  191.         SHARED Octave% '      need access to current octave
  192.      
  193.         DIM Note% '           counter used to open sounds
  194.         DIM Count% '          counter used to close sounds if error
  195.         DIM File$ '           sound file names
  196.      
  197.         FOR Note% = 1 TO 88 '                                          cycle through notes
  198.             File$ = LTRIM$(STR$(Note%)) + ".ogg" '                     construct file name
  199.             IF _FILEEXISTS(File$) THEN '                               sound file exist?
  200.                 Tone&(Note%) = _SNDOPEN(File$, "VOL,SYNC,LEN,PAUSE") ' yes, load sound file
  201.             ELSE '                                                     no, sound file missing
  202.                 PRINT '                                                report error to user
  203.                 PRINT " ERROR: Sound file "; File$; " is missing."
  204.                 IF Note% > 1 THEN '                                    did any sounds load?
  205.                     FOR Count% = Note% TO 1 STEP -1 '                  yes, cycle notes backwards
  206.                         _SNDCLOSE Tone&(Count%) '                      remove sound from RAM
  207.                     NEXT Count%
  208.                     END '                                              end program
  209.                 END IF
  210.             END IF
  211.         NEXT Note%
  212.         IF _FILEEXISTS("piano.png") THEN '                             image file exist?
  213.             imgPiano& = _LOADIMAGE("piano.png", 32) '                  yes, load image file
  214.         ELSE '                                                         no, image file missing
  215.             PRINT '                                                    report error to user
  216.             PRINT " ERROR: piano.png missing."
  217.             END '                                                      end program
  218.         END IF
  219.         IF _FILEEXISTS("active.png") THEN '                            image file exist?
  220.             imgAoctave& = _LOADIMAGE("active.png", 32) '               yes, load image file
  221.         ELSE '                                                         no, image file missing
  222.             PRINT '                                                    report error to user
  223.             PRINT " ERROR: active.png missing."
  224.             _FREEIMAGE imgPiano& '                                     remove image from RAM
  225.             END '                                                      end program
  226.         END IF
  227.         IF _FILEEXISTS(Path$ + "inactive.png") THEN '                  image file exist?
  228.             imgIoctave& = _LOADIMAGE("inactive.png", 32) '             yes, load image file
  229.         ELSE '                                                         no, image file missing
  230.             PRINT '                                                    report error to user
  231.             PRINT " ERROR: inactive.png missing."
  232.             _FREEIMAGE imgPiano& '                                     remove image from RAM
  233.             _FREEIMAGE imgAoctave& '                                   remove image from RAM
  234.             END '                                                      end program
  235.         END IF
  236.      
  237.         K(1).x = 22: K(1).y = 212: K(2).x = 60: K(2).y = 132 '         set indicator coordinates
  238.         K(3).x = 95: K(3).y = 212: K(4).x = 134: K(4).y = 132
  239.         K(5).x = 168: K(5).y = 212: K(6).x = 241: K(6).y = 212
  240.         K(7).x = 278: K(7).y = 132: K(8).x = 314: K(8).y = 212
  241.         K(9).x = 353: K(9).y = 132: K(10).x = 387: K(10).y = 212
  242.         K(11).x = 428: K(11).y = 132: K(12).x = 460: K(12).y = 212
  243.         K(1).l = 100: K(1).u = 68: K(2).l = 114: K(2).u = 82 '         set key case values
  244.         K(3).l = 102: K(3).u = 70: K(4).l = 116: K(4).u = 84
  245.         K(5).l = 103: K(5).u = 71: K(6).l = 104: K(6).u = 72
  246.         K(7).l = 117: K(7).u = 85: K(8).l = 106: K(8).u = 74
  247.         K(9).l = 105: K(9).u = 73: K(10).l = 107: K(10).u = 75
  248.         K(11).l = 111: K(11).u = 79: K(12).l = 108: K(12).u = 76
  249.         Octave% = 2 '                                                  set initial octave
  250.      
  251.     END SUB
  252.      
  253.     '--------------------------------------------------------------------------------------------
  254.  

 
                                                                                                                                         (136 downloads previously)

PIANO Screenshot.png

Pages: [1] 2