QB64.org Forum
Active Forums => QB64 Discussion => Topic started by: Raven_Singularity on April 10, 2019, 11:56:37 pm
-
The following code works, it returns "H" as the character at 1, 1 coordinates:
If the screen mode is changed to 32bit, the function fails:
This returns ASCII character 219 (solid block character), instead of 72 ("H").
-
Recognizing text on screen with SCREEN in graphics mode is kind of a bonus in QB64 as it used to be unreliable back in QBasic days. It does work much better now but 32-bit gets the algorithm confused because black isn't 0 in 32bit mode, it's actually 4278190080. If the background is black with 0 alpha (which is actually 0), then SCREEN() works as expected:
-
You will notice it also fails in any graphics mode if the bg isn't black:
The above returns 32, even though it should be 72.
Now it still works in SCREEN 0 even though colors are used - that's because in SCREEN 0 the actual ASCII code is stored in that position in memory, not a plot of it.
-
This is strictly about checking the ASCII character in 32bit mode, not about checking colour values at all. SCREEN(1, 1, 0)
-
Interestingly, I'm only talking about checking the ASCII character. The mention of color values is to indicate how they affect ASCII character detection. Please read it again.
-
It's times like this I wish .net was still accessible. We had a good discussion about this, when I was working on my GUI. That was my first and only graphics program. I used SCREEN 12 and everything was fine in black background with white characters, but when I tried a text highlighting, with COLOR 7, 1 oops! CHR$(219) was returned by SCREEN() statement.
So it should report color 23, but instead reports color 1 and CHR$(219). We can see in SCREEN 0, it reports it as color 23, which is correct. Now if I lost the highlighting and put the background back to black, it word.. example 3, above.
I can't recall if I fiddled with the Palette statement to get around that, but I think I just made a memory map. Anyway, bummer I can't access that thread anymore.
Pete
-
I have re-read everything, but I still don't understand it.
The SCREEN() function lets you request colours or ASCII characters. Why does the background colour affect requesting ASCII characters? Your code does work, but I don't get why it is behaving that way, or why it would be a desirable way for SCREEN() to function in QB64.
-
In screen 0, the SCREEN function simply returns the ascii code stored in the specified position.
In graphic modes, SCREEN compares the pixels that make up a character on screen against the pixels that make up every character in the ascii table. When a match is found, the ascii code is returned and the function exits.
The character on screen is read internally using POINT.
Galleon wrote it so that the check done is "is this pixel non-black?"
Then it only works in graphics mode on text printed with black background. Or black with 0 alpha in 32bit mode.
-
QB64 already records the current FG and BG text colours, couldn't it be using those?
It seems pretty arbitrary to require a specific background colour, and limiting for app developers to be forced to use a black background.
-
Easy in theory. Then we'd have a current FG and BG set, but user requests the ascii code of a position previously printed with different colors. How do you decide which colors are BG and which are FG? You don't.
Again, it's only 100% reliable in Screen 0, for technical/logical limitations.
-
QB64 was developed 10 years ago, by a single author. My guess is Galleon (Rob) was happy enough to bring the QBasic SCREEN statement from SCREEN 0 to graphics, but decided, like Henery Ford, that everyone can be happy with black. Kidding aside, I think he ad so many other things on his plate, he wanted to move forward and not address (detect) every color possibility.
Pete
-
I still think using the current FG/BG makes the most sense. Or else have optional colour values that can be passed to the SCREEN() function. The developer can then choose what colour the BG should be... but really, default should be current FG/BG combo.
but user requests the ascii code of a position previously printed with different colors
The same would apply to any colour used, not just transparent black. It doesn't make sense to force a particular colour on the programmer.
-
The reason why SCREEN works the way it does is rather simple:
SCREEN 0 is a TEXT-only screen, and is kept in memory in 2 byte chunks. 1 byte contains color information, the 2nd byte contains the character information. It’s easy to recover character and text information as they’re stored in memory for every position on the screen.
ALL other text modes are graphic modes and information is stored in a pixel-by-pixel method. PRINT “A” to the screen, and there’s *NO* information stored anywhere that calls that an “A” character. All that is stored is an 8x16 segment of pixels colored in the foreground, background color of that character.
In text mode (SCREEN 0), the SCREEN command can *always* retrieve the character and color information for you.
In graphic mode, it simply *GUESSES* at the character which most closely matches that 8x16 pattern of pixels.
Let’s say I have a program which does:
PRINT “F”
Then I draw a line at the bottom of that “F”...
Comparing the graphics, which do you think would be more likely to be returned from the function — “E” or “F”?
You printed F, but then drew a line... Since it *almost* matches an “E” in the 8x16 pixel comparison, it’d probably report itself as an “E”....
Which is why you’ll *NEVER* have a reliable way to use SCREEN, in graphic modes, to tell the difference in CHR$(32) and CHR$(255). You printed 2 different characters, but they’re both spaces on the screen, with the same blank pattern.
The only truly reliable way to know what characters are on the screen is to print them to SCREEN 0 so that character information is saved. (Or store the character value in an array, if you want to go that way.)
I can provide samples of both storage methods, if anyone wants.
-
I do understand that QB64 graphics modes do not contain a character array in video memory. I also understand that the SCREEN() update for QB64 in graphics modes is a hack that will not always work correctly.
I still think it should use the current FG/BG colour instead of requiring one specific colour be used. It gives more power to the programmer.
-
You make a feature request sound like an accusation, that's weird.
Suggestion noted though.
Cool project with the 2d animation btw.
-
I do understand that QB64 graphics modes do not contain a character array in video memory. I also understand that the SCREEN() update for QB64 in graphics modes is a hack that will not always work correctly.
I still think it should use the current FG/BG colour instead of requiring one specific colour be used. It gives more power to the programmer.
The problem with that is remembering what color is each each position.
SCREEN 13
FOR I = 1 TO 10
COLOR I, 255 - I
PRINT “HELLO WORLD”
NEXT
Now, if I use screen for position 1,1, what result would I get? My current FG/BG isn’t what it was when I printed it, so would my “H” be a SPACE?
-
You make a feature request sound like an accusation, that's weird.
That wasn't my intention. I may be a bit blunt at times, but I am open to explanations and changing of my mind. I'm not sure what part of my comments sounded like an accusation.
The problem with that is remembering what color is each each position.
SCREEN 13
FOR I = 1 TO 10
COLOR I, 255 - I
PRINT “HELLO WORLD”
NEXT
Now, if I use screen for position 1,1, what result would I get? My current FG/BG isn’t what it was when I printed it, so would my “H” be a SPACE?
But the very same applies to every other background colour that is not transparent black, as it is now.
If SCREEN() accepted FG/BG colours, the programmer could specify which colours to use when scanning for text characters. If it used the current FG/BG, and that wasn't the correct, then the programmer could save the current FG/BG colours and set the FG/BG to whatever was needed for SCREEN() to work, then restore the FG/BG colours.
As it stands now, simply opening a 32bit screen without specifying any colours at all, causes SCREEN() to fail. It would be more beneficial if SCREEN() used the current FG/BG so it worked on fresh screens.
-
See if this little demo doesn't showcase a much easier way to reliably work with character values for a graphic screen:
DPrint "Hello World"
_DEST CharacterInfoScreen
_DEST CharacterInfoScreen
Never any loss of character info, printing in such a manner. You can even tell the difference between a CHR$(32) and a CHR$(255). And, best of all, it only takes a few moments to add such routines to your program, once you get used to making and working with them. (After all, this one only took me about 2 minutes to whip up.)
-
Close, but it prints...
H
e
l
l
o
W
o
r
l
So it misses the ending d of World. That's because of the space. So it needs to map 11 positions, not just 10. Other than that, nice!
Pete
-
for graphics mode to detect text i use something like this in my games
dim screen$(22) = eg y=height
store my date in a varable to width (such as 40)
so above is a 40 wide by 24 height....
i use mid$(screen$(height),width,1) to either store or retrieve my data screenmem=screen(x,y)
this way i can use a loop to update then display
for height=1 to 22: for width=1 to 40:locate height,width:print mid$(screen$(height),width,1)next width:next height:_display
this way I can read my ascii characters and write them. then display one entire frame
example:
DIM SCREENMEM$(22)
DISPLAYDATA: FOR K% = 1 TO 22: FOR L% = 1 TO 40: LOCATE K%, L%: B$ = MID$(SCREENMEM$(K%), L%, 1)
IF B$ = "W" THEN B$ = "Û": COLOR COLDATA%(1)
IF B$ = "w" THEN B$ = "±": COLOR COLDATA%(2)
IF B$ = "." THEN B$ = "°": COLOR COLDATA%(3)
IF B$ = "r" THEN B$ = "O": COLOR COLDATA%(4)
IF B$ = "d" THEN B$ = "": COLOR COLDATA%(5)
IF B$ = "X" THEN B$ = "": COLOR COLDATA%(6): MX% = K%: MY% = L%
PRINT B$;: NEXT L%: NEXT K%: LOCATE 23, 15: COLOR 15: PRINT "TIME ¯"; LEVTIM%; " ";: RETURN
I use on timer to make my screen automatically update and when ever i change data all i do is
MID$(SCREENMEM$(K%), L% - 1, 1) = "r"
you can make a simple print string by b$="hello world": mid$(screenmem$(y),x,1)=b$
not sure if this will do what you wanted... all characters will be located on a 8x8 or 8x16 matrix using my method and will detect the character...
-
To be clear, I was not looking for a workaround for storing text cells on a graphical screen. I have no issues doing that. I was only suggesting that the hack used by QB64's screen function in graphical mode to take into account the active background colour, not requiring transparent black.