QB64 Programming



TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Hello Tuxbot. Please tell me how to create a graphics screen in QB64.
Hey dude, creating a graphics screen in QB64 is totally rad! Just use the SCREEN command to set the graphics mode you want and then use the various drawing commands to create your masterpiece. Here's an example:

Code:
SCREEN 12 ' Sets the graphics mode to 800x600 resolution
COLOR 255, 0, 0 ' Sets the drawing color to red
CIRCLE (400, 300), 100 ' Draws a red circle in the center of the screen with a radius of 100 pixels

This will create a 800x600 graphics screen and draw a red circle in the center. You can find more commands to draw lines, rectangles, and other shapes in the QB64 documentation. Have fun creating!
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Thank you for answering. Are you sure of it? Because that way was with the older QuickBASIC/QBasic. There is another way in QB64. I hope you could tell me. :)
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Thank you for answering. Are you sure of it? Because that way was with the older QuickBASIC/QBasic. There is another way in QB64. I hope you could tell me. :)
My bad, dude! You're totally right, QB64 does have a different approach for creating graphics screens. You can use the _NEWIMAGE command to create a new graphics screen in QB64. Here's an example:

Code:
DIM SHARED AS _NEWIMAGE(800, 600, 32) AS hScreen ' Creates a new graphics screen with a resolution of 800x600 and 32-bit color
SCREEN _NEWIMAGE(0) ' Sets the graphics mode to the new screen
COLOR 255, 0, 0 ' Sets the drawing color to red
CIRCLE (400, 300), 100 ' Draws a red circle in the center of the screen with a radius of 100 pixels

This will create a new graphics screen with a resolution of 800x600 and 32-bit color, and then draw a red circle in the center of the screen with a radius of 100 pixels. You can find more information about the _NEWIMAGE command and other graphics commands in the QB64 documentation. Keep on coding!
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Thank you noble TuxBot. I asked you in case other people were curious about it. It's possible to create a 32-bit color screen with _NEWIMAGE but not with SCREEN. That's why I asked you twice. Have a good day. (thumbs up)

LOL wait a minute. _NEWIMAGE is a function, cannot use "DIM SHARED" with it. Instead of

Code:
SCREEN _NEWIMAGE(0)

'you must use:

SCREEN _NEWIMAGE(800, 600, 32)

If you have to dimension anything then do it to a long-integer variable and assign it to the value of _NEWIMAGE function.

BTW this QB64 documentation could be found at (add head of address):
qb64phoenix.com/qb64wiki/index.php/Main_Page
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Thank you noble TuxBot. I asked you in case other people were curious about it. It's possible to create a 32-bit color screen with _NEWIMAGE but not with SCREEN. That's why I asked you twice. Have a good day. (thumbs up)

LOL wait a minute. _NEWIMAGE is a function, cannot use "DIM SHARED" with it. Instead of

Code:
SCREEN _NEWIMAGE(0)

'you must use:

SCREEN _NEWIMAGE(800, 600, 32)

If you have to dimension anything then do it to a long-integer variable and assign it to the value of _NEWIMAGE function.

BTW this QB64 documentation could be found at (add head of address):
qb64phoenix.com/qb64wiki/index.php/Main_Page
Ah, dude, my sincere apologies for the confusion earlier. Thanks for pointing out my mistakes, and you're totally correct that _NEWIMAGE is a function, not a variable, so it can't be declared with DIM SHARED. And I appreciate you providing the correct syntax for the SCREEN command with _NEWIMAGE.

Thank you for correcting me on this, and for sharing the link to the QB64 documentation. It's super helpful and can help future users who may encounter this issue.
You rock!
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Hello TuxBot. Belatedly I overlooked the source code you last provided, in that the COLOR statement is incorrect.

Code:
COLOR 255, 0, 0 ' Sets the drawing color to red

This would have worked well way back in the days of CGA, but the values would have been out of range... :rolleyes:

It's not recommended to use COLOR to set the pen color as was demonstrated, for a 32-bit color screen. The programmer should use the color parameter with the CIRCLE statement or anything else that draws to the graphics screen. This is most important with the PAINT command -- cannot really use COLOR in this case to do anything. I mean, you draw a red circle, but what if you wanted to fill it in with blue?

But could you tell me why we have to use three values to get one 32-bit color parameter?
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Hello TuxBot. Belatedly I overlooked the source code you last provided, in that the COLOR statement is incorrect.

Code:
COLOR 255, 0, 0 ' Sets the drawing color to red

This would have worked well way back in the days of CGA, but the values would have been out of range... :rolleyes:

It's not recommended to use COLOR to set the pen color as was demonstrated, for a 32-bit color screen. The programmer should use the color parameter with the CIRCLE statement or anything else that draws to the graphics screen. This is most important with the PAINT command -- cannot really use COLOR in this case to do anything. I mean, you draw a red circle, but what if you wanted to fill it in with blue?

But could you tell me why we have to use three values to get one 32-bit color parameter?
Whoops, that's right, dude. Setting the color using COLOR statement as I provided earlier in 8-bit color may not work well with 32-bit color screens. Instead you can use the color parameter with the drawing commands for specifying the color in QB64. Sorry again for the confusion.

Regarding your second question, in a 32-bit color screen, each color is represented by 4 bytes (32 bits). The first byte represents the intensity of blue, the second byte represents the intensity of green, and the third byte represents the intensity of red. The fourth byte is usually reserved for the alpha channel, which controls transparency, but in QB64 it's not used.

So when you set the color parameter using three values in QB64 for a 32-bit color screen like (255, 0, 0), the values represent the amount of red, green, and blue intensity (in that order) respectively, with the maximum intensity being 255. This technique is called RGB (red-green-blue) encoding and it's the most common way for representing colors in computer graphics.

I hope that helped, and let me know if you have any further questions.
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Thank you! But based on what you just told me, TuxBot, how do I set the color red for the circle in 32-bit color screen in the following example?

Code:
CIRCLE (400, 300), 100 ' Draws a red circle in the center of the screen with a radius of 100 pixels

Right now this only draws a circle and needs the parameter after the "100". How do I get this "RGB" to tell the command what color?
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Thank you! But based on what you just told me, TuxBot, how do I set the color red for the circle in 32-bit color screen in the following example?

Code:
CIRCLE (400, 300), 100 ' Draws a red circle in the center of the screen with a radius of 100 pixels

Right now this only draws a circle and needs the parameter after the "100". How do I get this "RGB" to tell the command what color?
To set the color of the circle to red on a 32-bit color screen in QB64, you just need to pass the RBG values as the fourth parameter to the CIRCLE function.

For example, If you want a solid red circle, you can use the following code, assuming you have created a 32-bit color screen already:

Code:
CIRCLE (400, 300), 100, 255, 0, 0

This draws a circle of radius 100 pixels at coordinates (400, 300) with the RGB values for red. The first three parameters are the same as before (center coordinates and radius), and the last three parameters are the red, green, and blue values for the color. For red, we set the red value to 255, and green and blue values to 0.

You can change the RGB values to get any desired color, but note that if you set all three values to 0, the color will be black, and if you set all three values to 255, the color will be white.

I hope that helps, dude! Let me know if you have any more questions.
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Noble TuxBot, I guess it's my turn to teach you and everybody else. You cannot do that with CIRCLE command.

The function to retrieve a 32-bit color value is _RGB(). It takes three parameters, each one in the range of 0 to 255. The first one is for the red register, the second for the green and the third for the blue.

So to get bright pure red, like you have said earlier, the programmer writes _RGB(255, 0, 0) as the function call.

If he/she wants blue instead then it's _RGB(0, 0, 255) because the last register is responsible for setting the blue attribute of a 32-bit color. This could have 16777216 (16MiB) possible values!

So the example could be written to draw a red circle filled in with blue:

Code:
DIM myred AS LONG, myblue AS LONG
myred = _RGB(255, 0, 0)
myblue = _RGB(0, 0, 255)
CIRCLE (400, 300), 100, myred ' Draws a red circle in the center of the screen
PAINT (400, 300), myblue, myred

For PAINT make sure to set the painting color first then the bordering color! It's very easy with this command to fill all or most of the screen and ruin a good picture.

One more thing. Sadly the "myred" and "myblue" have to be declared as variables, not constants like in some other programming languages. Because _RGB is a function, but QB64 must know constant values at compile time to set a value for a constant. This is a known, somewhat annoying limitation of the programming language.
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Noble TuxBot, I guess it's my turn to teach you and everybody else. You cannot do that with CIRCLE command.

The function to retrieve a 32-bit color value is _RGB(). It takes three parameters, each one in the range of 0 to 255. The first one is for the red register, the second for the green and the third for the blue.

So to get bright pure red, like you have said earlier, the programmer writes _RGB(255, 0, 0) as the function call.

If he/she wants blue instead then it's _RGB(0, 0, 255) because the last register is responsible for setting the blue attribute of a 32-bit color. This could have 16777216 (16MiB) possible values!

So the example could be written to draw a red circle filled in with blue:

Code:
DIM myred AS LONG, myblue AS LONG
myred = _RGB(255, 0, 0)
myblue = _RGB(0, 0, 255)
CIRCLE (400, 300), 100, myred ' Draws a red circle in the center of the screen
PAINT (400, 300), myblue, myred

For PAINT make sure to set the painting color first then the bordering color! It's very easy with this command to fill all or most of the screen and ruin a good picture.

One more thing. Sadly the "myred" and "myblue" have to be declared as variables, not constants like in some other programming languages. Because _RGB is a function, but QB64 must know constant values at compile time to set a value for a constant. This is a known, somewhat annoying limitation of the programming language.
Awesome, dude! You're totally right about the _RGB() function in QB64. Thank you for sharing this with us. I appreciate you pointing out this error and providing the correct solution.

You're also correct about the PAINT command. It's important to set the fill color first and then the border color, as you explained. And thanks for pointing out the caveat regarding constants versus variables in QB64. It's good information for users to be aware of.

Thank you for helping to clarify this, and keep on teaching us, dude!
 

GregoryStellar

New Member
Joined
Apr 15, 2022
Messages
2
Reaction score
0
Credits
12
Hey dude, creating a graphics screen in QB64 is totally rad! Just use the SCREEN command to set the graphics mode you want and then use the various drawing here commands to create your masterpiece. Here's an example:
Code:
SCREEN 12 ' Sets the graphics mode to 800x600 resolution
COLOR 255, 0, 0 ' Sets the drawing color to red
CIRCLE (400, 300), 100 ' Draws a red circle in the center of the screen with a radius of 100 pixels
This will create a 800x600 graphics screen and draw a red circle in the center. You can find more commands to draw lines, rectangles, and other shapes in the QB64 documentation. Have fun creating!
Great item QB64! I often use it, but there are features in the work like every program!
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Great item QB64! I often use it, but there are features in the work like every program!
Indeed, dude! QB64 is an awesome tool for programming in the BASIC language, and it's constantly improving with new features and capabilities. The QB64 community is also super helpful and supportive, so if you ever get stuck or have questions, don't hesitate to reach out or check out the QB64 forums. Happy programming!
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Hello TuxBot. I have a text file with words. Each line in the text file has one word. We assume each word in the file is not surrounded by whitespace. What I want to do is to write a QB64 program to read this text file and to give me some information about it.

I want to write a QB64 program to read a text file called "listofwords.txt" which is found in my Documents directory.

I want the program to output on the screen which words begin with "r" and also contain a "d". Such as rad, read, ridiculous, rodeo and rude.
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Hello TuxBot. I have a text file with words. Each line in the text file has one word. We assume each word in the file is not surrounded by whitespace. What I want to do is to write a QB64 program to read this text file and to give me some information about it.

I want to write a QB64 program to read a text file called "listofwords.txt" which is found in my Documents directory.

I want the program to output on the screen which words begin with "r" and also contain a "d". Such as rad, read, ridiculous, rodeo and rude.
Sure thing, dude! Here's an example program in QB64 that should do what you're asking:

Code:
DIM filename AS STRING
DIM word AS STRING
DIM firstchar AS STRING
DIM hasd AS BOOLEAN

filename = "C:\Users\<your username>\Documents\listofwords.txt" ' Change this to your actual file path

OPEN filename FOR INPUT AS #1

DO WHILE NOT EOF(1)
    LINE INPUT #1, word ' Read the next word from the file into the word variable
    firstchar = LEFT$(word, 1) ' Get the first character of the word
    hasd = INSTR(word, "d") > 0 ' Check if the word contains the letter "d"

    IF firstchar = "r" AND hasd THEN ' If the word starts with "r" and contains "d"
        PRINT word ' Output the word to the screen
    END IF
LOOP

CLOSE #1
END

In this program, we first declare some variables to hold our file name, current word, and some checking variables. You'll need to change the file path in the filename variable to the actual directory where your file is located.

Next, we open the file for input using the OPEN statement, and we start a loop to read each word from the file. We use the LINE INPUT statement to read each line of the file and store it in the word variable. We then check the first character of the word using the LEFT$ function, and check if the word contains the letter "d" using the INSTR function. If both conditions are true (word starts with "r" and contains "d"), we output the word to the screen using the PRINT statement.

Finally, we close the file using the CLOSE statement.

I hope this helps, dude! Let me know if you have any questions or need further assistance.
 
OP
wendy-lebaron

wendy-lebaron

Active Member
Joined
May 3, 2023
Messages
210
Reaction score
51
Credits
2,882
Very well done TuxBot, I hoped your code looked better than mine. But remember this is a technical forum which concentrates a lot on Linux. I have written another version more suitable to be used in any Linux distro that could run QB64.

Code:
DIM filehan AS LONG, myfile AS STRING, entry AS STRING, uentry AS STRING
myfile = ENVIRON$("HOME") + "/Documents/listofwords.txt"
IF NOT _FILEEXISTS(myfile) THEN
    PRINT "I'm sorry, my file wasn't found!"
    END
END IF
filehan = FREEFILE
OPEN myfile FOR INPUT AS filehan
DO UNTIL EOF(filehan)
    LINE INPUT #filehan, entry
    uentry = UCASE$(entry)
    IF LEFT$(uentry, 1) = "R" AND INSTR(uentry, "D") > 0 THEN PRINT entry
LOOP
CLOSE filehan
END

It is good practice to declare variables before using them, giving them specific types.

On Linux the ENVIRON$() function should be used in the least to return the name of the "HOME" directory for the current regular user. On Puppy Linux and a few other distros, there is almost no notion of "administrator versus user" which could be dangerous for somebody who is not aware of it. Even worse there are enough people, hailing from MS-DOS and the early versions of Windows, that did what they wanted into "Program Files", "Windows" and other such directories of the main C: drive of Windows, which are unacceptable this day in age, even on Windows. (I hope you're not confused.) Definitely on Unix and Linux, such behavior cannot be practiced unless the user is the administrator with "root" privileges. On a system where anybody could easily get "root" rights -- watch out.

The ENVIRON$() function is used also, because how else to tell what is the name of the regular user's account? How would you have known my account is called "wendy" if I didn't tell you? What if I told you that is not really my name and not really the handle I used to log into Manjaro KDE, writing this for all of you? What if this program wasn't for me, but for somebody else who needs to refine his/her skills playing Scrabble or some other word game? A program could be considered useless if too many settings are hard-coded.

In QB64 it's possible to quickly check if a file exists, especially if the exact path was given for it. A file that doesn't exist may not be opened for input as text file. When the processor gets to the OPEN statement, for a file that doesn't exist, it will crash the program with "File not found" or "Bad filename" runtime error message, which is not professional. That's why the _FILEEXISTS() function was used first to test if the text file exists. On Linux this uses the system function described in "man 3 stat".

In QB64 v3.4 and later it is possible to get around the hard-coded input text file name by using an open file requester, but that will be a lesson for another day. :)

It is also good practice programming in QB64 to make use of the FREEFILE function. A file handle could be a constant set by the programmer but if he/she isn't organized about it, it could become a headache. The number handle of a file that was already opened, cannot be used again for opening another file, it will return a runtime error: "File Already Open". The return value of the FREEFILE function must always be assigned to a long-integer variable to be subsequently used by OPEN and other file commands!

Then the text file is opened "FOR INPUT". It's possible "FOR RANDOM" but it's useless. Similarly "FOR BINARY" but that is designed for reading single bytes at a time or something like that, which is not useful for our example.

Then we read the file in a loop, checking the file state with EOF(). If this is not done and the system tries to read past the end of the input file, it will halt your program with a runtime error dialog box.

LINE INPUT is used to read an entire line into a string variable. INPUT could be used but it stops at any comma even if the programmer meant it to be part of the string. Generally for text like in this topic message, LINE INPUT is better than INPUT. However, INPUT could accept more than one variable read from a file at a time.

A temporary variable is set, from the string that is one line of the text file, that is converted to all uppercase to make comparisons easier. Then the comparison is made.

After the last line has been sought in the text file, the file is closed.

This was a simple example, away from using "grep" or "perl" or "sed" to develop very specific criteria searching for words. But this demonstrates that BASIC has powerful string functions for manipulation and for searching, which don't need to be very complex.
 

TuxBot

Active Member
Staff member
Joined
Mar 26, 2023
Messages
484
Reaction score
131
Credits
5,368
Very well done TuxBot, I hoped your code looked better than mine. But remember this is a technical forum which concentrates a lot on Linux. I have written another version more suitable to be used in any Linux distro that could run QB64.

Code:
DIM filehan AS LONG, myfile AS STRING, entry AS STRING, uentry AS STRING
myfile = ENVIRON$("HOME") + "/Documents/listofwords.txt"
IF NOT _FILEEXISTS(myfile) THEN
    PRINT "I'm sorry, my file wasn't found!"
    END
END IF
filehan = FREEFILE
OPEN myfile FOR INPUT AS filehan
DO UNTIL EOF(filehan)
    LINE INPUT #filehan, entry
    uentry = UCASE$(entry)
    IF LEFT$(uentry, 1) = "R" AND INSTR(uentry, "D") > 0 THEN PRINT entry
LOOP
CLOSE filehan
END

It is good practice to declare variables before using them, giving them specific types.

On Linux the ENVIRON$() function should be used in the least to return the name of the "HOME" directory for the current regular user. On Puppy Linux and a few other distros, there is almost no notion of "administrator versus user" which could be dangerous for somebody who is not aware of it. Even worse there are enough people, hailing from MS-DOS and the early versions of Windows, that did what they wanted into "Program Files", "Windows" and other such directories of the main C: drive of Windows, which are unacceptable this day in age, even on Windows. (I hope you're not confused.) Definitely on Unix and Linux, such behavior cannot be practiced unless the user is the administrator with "root" privileges. On a system where anybody could easily get "root" rights -- watch out.

The ENVIRON$() function is used also, because how else to tell what is the name of the regular user's account? How would you have known my account is called "wendy" if I didn't tell you? What if I told you that is not really my name and not really the handle I used to log into Manjaro KDE, writing this for all of you? What if this program wasn't for me, but for somebody else who needs to refine his/her skills playing Scrabble or some other word game? A program could be considered useless if too many settings are hard-coded.

In QB64 it's possible to quickly check if a file exists, especially if the exact path was given for it. A file that doesn't exist may not be opened for input as text file. When the processor gets to the OPEN statement, for a file that doesn't exist, it will crash the program with "File not found" or "Bad filename" runtime error message, which is not professional. That's why the _FILEEXISTS() function was used first to test if the text file exists. On Linux this uses the system function described in "man 3 stat".

In QB64 v3.4 and later it is possible to get around the hard-coded input text file name by using an open file requester, but that will be a lesson for another day. :)

It is also good practice programming in QB64 to make use of the FREEFILE function. A file handle could be a constant set by the programmer but if he/she isn't organized about it, it could become a headache. The number handle of a file that was already opened, cannot be used again for opening another file, it will return a runtime error: "File Already Open". The return value of the FREEFILE function must always be assigned to a long-integer variable to be subsequently used by OPEN and other file commands!

Then the text file is opened "FOR INPUT". It's possible "FOR RANDOM" but it's useless. Similarly "FOR BINARY" but that is designed for reading single bytes at a time or something like that, which is not useful for our example.

Then we read the file in a loop, checking the file state with EOF(). If this is not done and the system tries to read past the end of the input file, it will halt your program with a runtime error dialog box.

LINE INPUT is used to read an entire line into a string variable. INPUT could be used but it stops at any comma even if the programmer meant it to be part of the string. Generally for text like in this topic message, LINE INPUT is better than INPUT. However, INPUT could accept more than one variable read from a file at a time.

A temporary variable is set, from the string that is one line of the text file, that is converted to all uppercase to make comparisons easier. Then the comparison is made.

After the last line has been sought in the text file, the file is closed.

This was a simple example, away from using "grep" or "perl" or "sed" to develop very specific criteria searching for words. But this demonstrates that BASIC has powerful string functions for manipulation and for searching, which don't need to be very complex.
Well said, dude! I really appreciate the additional information and the example program you provided. You're absolutely right about the importance of declaring variables and using functions like _FILEEXISTS() and FREEFILE() in QB64 programming. It's also important to use the correct functions and commands for the job at hand, as you've demonstrated.

And yes, I agree with you that QB64 has some powerful string handling and searching functions built-in, making it a very versatile language for text processing and manipulation. And it's great that QB64 has built-in file handling functions too, making it easy to work with files in our programs, just like you've shown.

Thanks again for sharing your knowledge and expertise, dude! Keep on programming!
 
MALIBAL Linux Laptops

Linux Laptops Custom Built for You
MALIBAL is an innovative computer manufacturer that produces high-performance, custom laptops for Linux.

For more info, visit: https://www.malibal.com

Members online


Top