Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 490
» Latest member: Dr.Creek
» Forum threads: 2,823
» Forum posts: 26,475

Full Statistics

Latest Threads
DRAW to generate the poin...
Forum: QBJS, BAM, and Other BASICs
Last Post: CharlieJV
48 minutes ago
» Replies: 0
» Views: 6
Button rack or hotkey fun...
Forum: Utilities
Last Post: Petr
1 hour ago
» Replies: 4
» Views: 323
Next small EQ step - EQ D...
Forum: Petr
Last Post: Petr
1 hour ago
» Replies: 9
» Views: 434
What do you guys like to ...
Forum: General Discussion
Last Post: OldMoses
4 hours ago
» Replies: 32
» Views: 896
Happy Birthday Terry Ritc...
Forum: General Discussion
Last Post: madscijr
Today, 07:29 AM
» Replies: 21
» Views: 806
looking for project manag...
Forum: General Discussion
Last Post: TempodiBasic
Today, 02:04 AM
» Replies: 0
» Views: 24
Audio Spectrum Analyser
Forum: Programs
Last Post: SierraKen
Today, 01:36 AM
» Replies: 4
» Views: 89
Popup Calendar
Forum: Works in Progress
Last Post: SquirrelMonkey
Today, 01:11 AM
» Replies: 1
» Views: 36
Reading my brainwaves in ...
Forum: Programs
Last Post: Pete
Yesterday, 08:58 PM
» Replies: 3
» Views: 84
Rock Paper Scissor in TCP...
Forum: Games
Last Post: TempodiBasic
Yesterday, 08:05 PM
» Replies: 1
» Views: 24

 
  Correcting the code
Posted by: Chris - 10-27-2023, 07:19 PM - Forum: Programs - Replies (15)

The code is intended to work as follows: when only the Enter key is pressed, the variable (H#) cannot be set to zero. However, when the zero (0) key is pressed, the variable (H#) is supposed to have a zero value. But if the entered number is 1,2,3,4,5,6 digits, it is to be confirmed with the Enter key. However, the 7-digit number is to be approved automatically.
To sum up, the entered numbers may have the following values: 0, 11, 232, 1254, 36547, 325478, 3254657.

H$ = "": B$ = ""
WHILE LEN(H$) < 7 AND B$ <> CHR$(13)
    B$ = ""
    WHILE B$ = "": B$ = INKEY$: _LIMIT 30: WEND
    IF B$ = CHR$(27) THEN 4200
    IF B$ = CHR$(32) THEN 8425
    IF B$ = CHR$(45) THEN 6171
    IF B$ = CHR$(43) THEN 6172
    IF B$ = CHR$(81) OR B$ = CHR$(113) THEN 6304
    IF B$ = CHR$(65) OR B$ = CHR$(97) THEN 6305
    IF B$ = CHR$(87) OR B$ = CHR$(119) THEN 6306
    IF B$ = CHR$(83) OR B$ = CHR$(115) THEN 6307
    IF B$ = CHR$(69) OR B$ = CHR$(101) THEN 6308
    IF B$ = CHR$(68) OR B$ = CHR$(100) THEN 6309
    IF B$ = CHR$(82) OR B$ = CHR$(114) THEN 6310
    IF B$ = CHR$(70) OR B$ = CHR$(102) THEN 6311
    IF B$ <> CHR$(13) THEN H$ = H$ + B$
WEND
H# = VAL(H$): PRINT H#

Thank you for your help - regards

Print this item

  Little ASCII Race Car Game
Posted by: TerryRitchie - 10-27-2023, 06:21 PM - Forum: Programs - No Replies

I'm working on some very simple games for users of the tutorial to tear apart and learn from.

The very first computer game I ever played was a text race car game on the TRS-80 Model I in 1980.

I've recreated it here for your ASCII enjoyment.

Code: (Select All)
'* Race Day!
'* Inspired by the first computer game I ever played on a TRS-80 Model I in 1980
'* Terry Ritchie
'* for the QB64 tutorial ( www.qb64tutorial.com )
'*
'* RIGHT/LEFT arrow keys to steer car, ESC to exit.
'*
DIM RoadWidth AS INTEGER ' width of roadway
DIM RoadX AS INTEGER '     left location of roadway
DIM Road AS STRING '       one segment of roadway
DIM CarX AS INTEGER '      car location on roadway
DIM CarY AS INTEGER
DIM Travel AS INTEGER '    distance traveled counter
DIM Speed AS SINGLE '      current speed of car
DIM Direction AS INTEGER ' next turn direction on roadway
DIM Turn AS INTEGER '      distance to turn in direction
DIM Marker AS STRING * 2 ' road side markers
DIM Crash AS INTEGER '     crash indicator
DIM Score AS INTEGER '     player's score

RANDOMIZE TIMER '                                    seed the random number generator
RoadWidth = 44 '                                     initial width of roadway
RoadX = 18 '                                         initial left side of roadway
CarX = 40 '                                          intitial car location
CarY = 1
Speed = .2 '                                         initial speed
Turn = 25 '                                          turn counter
Marker = "||" '                                      initial road markers
DO '                                                 BEGIN MAIN PROGRAM LOOP
    Travel = Travel + 1 '                            increment travel counter
    IF Travel = 25 THEN '                            25 frames gone by?
        Travel = 0 '                                 reset travel counter
        IF Speed > .07 THEN Speed = Speed - .02 '    increase speed
        IF RoadWidth > 7 THEN '                      road width at least 8?
            RoadWidth = RoadWidth - 2 '              yes, decrease width of roadway
            RoadX = RoadX + 1 '                      move roadway to right one position
        END IF
        IF CarY < 14 THEN CarY = CarY + 1 '          increase car position on roadway
    END IF
    Turn = Turn - 1 '                                decrement turn counter
    IF Turn = 1 THEN Marker = "||" '                 make a smooth transition between curves
    IF Turn = 0 THEN '                               has this turn ended?
        Direction = INT(RND * 3) - 1 '               which new direction? (-1, 0, or 1)
        Turn = INT(RND * 7) + 2 '                    how long should turn last?
        IF Direction = -1 THEN Marker = "//" '       create appropriate turn road markers
        IF Direction = 0 THEN Marker = "||"
        IF Direction = 1 THEN Marker = "\\"
    END IF
    RoadX = RoadX + Direction '                      move road in direction
    IF RoadX < 1 THEN '                              too far left?
        RoadX = 1 '                                  yes, keep here
        Marker = "||" '                              straighten the road out
    ELSEIF RoadX > 80 - LEN(Road) THEN '             too far right?
        RoadX = 80 - LEN(Road) '                     yes, keep here
        Marker = "||" '                              straighten the road out
    END IF
    IF _KEYDOWN(19200) THEN CarX = CarX - 1 '        move car left when left arrow pressed
    IF _KEYDOWN(19712) THEN CarX = CarX + 1 '        move car right when right arrow pressed
    Road = Marker + SPACE$(RoadWidth) + Marker '     create road segment
    LOCATE 24, RoadX '                               position cursor for road segment
    PRINT Road '                                     print road segment
    IF SCREEN(CarY, CarX, 0) = 32 THEN '             is the road clear?
        LOCATE CarY, CarX '                          yes, position cursor for car
        PRINT "V" '                                  print the car
        LOCATE 1, 1 '                                position cursor at top left corner
        Score = Score + 1 '                          increment score
        PRINT "Score:"; Score; '                     print player's score
        _DELAY Speed '                               pause at current speed
    ELSE
        Crash = -1 '                                 no, kaboom
    END IF
LOOP UNTIL _KEYDOWN(27) OR Crash '                   leave when player crashes or presses ESC
IF Crash THEN '                                      did player crash?
    LOCATE CarY, CarX '                              yes, position cursor at car
    PRINT "*" '                                      print wrecked car
    LOCATE 1, 1 '                                    position cursor at top left
    PRINT "---------------------" '                  print player's final score
    PRINT "------ !CRASH! ------"
    PRINT "---------------------"
    PRINT " Final Score:"; Score
    PRINT "---------------------"
    PRINT "- Press ESC to exit -"
    PRINT "---------------------"
    DO '                                             begin exit loop
        _LIMIT 10 '                                  don't hog cpu
    LOOP UNTIL _KEYDOWN(27) '                        leave when player presses ESC
END IF
SYSTEM '                                             return to operating system

Print this item

  Virus targetting qb64pe
Posted by: Dimster - 10-25-2023, 03:21 PM - Forum: Help Me! - Replies (17)

So here's an interesting notice I received from Defender. Hope to hell this kind of threat isn't common or ongoing.

   

Print this item

  SaveScreen and RestoreScreen
Posted by: SMcNeill - 10-24-2023, 08:33 AM - Forum: SMcNeill - Replies (8)

Two of the simplest little routines in the world, though I think they'll both end up becoming something I rely on more often in the future:

Code: (Select All)
Sub SaveScreen (Image As Long, SaveTo As _MEM)
    Dim m As _MEM
    m = _MemImage(Image)
    SaveTo = _MemNew(m.SIZE)
    _MemCopy m, m.OFFSET, m.SIZE To SaveTo, SaveTo.OFFSET
    _MemFree m
End Sub

Sub RestoreScreen (FromWhich As _MEM, Image As Long)
    Dim m As _MEM
    m = _MemImage(Image)
    _MemCopy FromWhich, FromWhich.OFFSET, FromWhich.SIZE To m, m.OFFSET
    _MemFree m
End Sub


So what's these brilliant little pieces of code do for us?  The just let us save a screen and then restore that screen.

That's it.  Nothing special.  No great bells or whistles here, to see folks! 

There's already about 9000 different ways to do this, so why do we need THIS particular way, you ask??

Let's take a moment and look at this scenario:

Code: (Select All)
SUB foo
    PCOPY 0, 1
    .... do stuff
    PCOPY 1, 0
END SUB

Now the above is a simple enough way to grab a copy of the screen, do stuff (like place a pop up box on it), and then restore it and get rid of whatever temporary changes we made to it (such as when we close that pop up box).

But here's a question for you:  What happens if your main program already had a PCOPY 0, 1 to save a screen??  Didn't you just overwrite that page with the new PCOPY 0, 1 that your SUB did?  How's that gonna screw up stuff when the main routine now does a call back to the old PCOPY 1, 0 when it needs it?

So PCOPY isn't particularly a great command to make use of for SUBs or Library code...

But then there's always the old _COPYIMAGE trick!

Code: (Select All)
SUB foo
    tempImage = _COPYIMAGE(0)
    ... do stuff
    _PUTIMAGE ,tempImage
    _FREEIMAGE tempImage

Which works all fine and dandy.... BUT.... What if the _DISPLAY is a SCREEN 0 text screen?  Can't _PUTIMAGE that image back then, now can you?

So we try and get tricky:

Code: (Select All)
SUB foo
    tempImage = _COPYIMAGE(0)
    ...do stuff
    D = _DISPLAY
    SCREEN tempImage
    _FREEIMAGE D

Which works all fine and dandy....  BUT.... What if someone writes their code in the following manner:

Code: (Select All)
WorkScreen = _NEWIMAGE(1280, 720, 32)

When you did the tempImage, QB64 had to create a new image handle for that screen...  Since the main routine already had a reserved handle for the screen -- that you just freed with the _FREEIMAGE D -- none of the routines in the main program are going to work anymore as the handles don't match.

One glitch after another after another!!

Which is why I give you the two little routines above:

SaveScreen (Image As Long, SaveTo As _MEM)  <-- This takes any image handle (even _DISPLAY) and saves it to a designated memblock.
RestoreScreen (FromWhich As _MEM, Image As Long)  <-- And this does the reverse, taking a memblock and using it to restore the desired image.

Should work on ALL screen modes -- text, legacy graphics, 256 color screens, and 32-bit color screens.  Shouldn't have any problems with using _DISPLAY or 0 as imagehandles.  They're quick.  They're simple.  And they solve a lot of the issues which all the other various methods of saving and restoring a screen can have.

A simple working example is below, which shows that it works in both text screens and graphic screen modes. 

Code: (Select All)
Screen _NewImage(640, 480, 32)
$Color:32
Cls , Pink
Print "An original Pink screen"
Sleep
GreenFoo
Sleep

Screen 0
Cls , 4 'redscreen
Print "A Red TEXT Screen 0"
Sleep
WhiteFoo



Sub GreenFoo
Dim Saver As _MEM
SaveScreen _Display, Saver
Cls , Green
Print "A happy Green screen"
Sleep
RestoreScreen Saver, _Display
_MemFree Saver
End Sub

Sub WhiteFoo
Dim Saver As _MEM
SaveScreen _Display, Saver
Cls , 15
Print "Replaced with white"
Sleep
RestoreScreen Saver, _Display
_MemFree Saver
End Sub



Sub SaveScreen (Image As Long, SaveTo As _MEM)
Dim m As _MEM
m = _MemImage(Image)
SaveTo = _MemNew(m.SIZE)
_MemCopy m, m.OFFSET, m.SIZE To SaveTo, SaveTo.OFFSET
_MemFree m
End Sub

Sub RestoreScreen (FromWhich As _MEM, Image As Long)
Dim m As _MEM
m = _MemImage(Image)
_MemCopy FromWhich, FromWhich.OFFSET, FromWhich.SIZE To m, m.OFFSET
_MemFree m
End Sub

Print this item

  ASCII-mation Game
Posted by: SpriggsySpriggs - 10-23-2023, 12:45 PM - Forum: Works in Progress - Replies (8)

I am no good at graphics. It is not my forte. However, I am somewhat decent at filming and photography. So, my idea is to use my new system for converting images into ASCII text files and making a game using real actors for the main characters, some sort of pixel art characters for the enemies, and AI art for the bosses. All will be converted into ASCII text files that will contain all animation data for their movesets. Basically the entire screen will be created using PRINTSTRING and other PRINT commands. Collision will be fairly easy, as I will have tags on the boundary of each character that will not be printed but will be checked for proximity to another character's tag. If the tags are touching, there is collision. I'm even considering going as far as having cutscenes in the game, with varying degrees of detail provided by the ASCII conversion, so as to have cinematic qualities. Note, this will be my first game EVER, so expect development to be long and arduous, with me asking many of our resident game programmers for assistance. I don't know when I will start this project, but I also don't want people hounding me about it as I'm very bad about getting sidetracked and starting multiple projects at the same time and never finishing them. For the game, I'm thinking typical sidescroller with basic combat. Melee, ranged, etc. I am on call this week for work so I probably won't do much this week but Monday & Tuesday of next week will be a good time for me to start. I want to at least get a first character put on the screen with basic animations for idling, walking, running, and jumping. The hopes for this game will be that it will be compatible with not only QB64 (on all platforms) but that it will also run on QBJS. Shouldn't be too difficult to make that happen. The game probably won't be open source at first, but snippets might be shared for helping with debugging and whatnot.

Print this item

  Wrong explanation in Play?
Posted by: PhilOfPerth - 10-23-2023, 11:33 AM - Forum: Wiki Discussion - Replies (8)

Am I wrong again? (I often am)!
In the Wiki (and the Help file) I think there may be an error in the explanation for a pause in the Play function.
It says that Pn will pause for n quarter-notes, when it actually pauses for  1/n th. So p1 pauses longer than say, p16.
It's quite easy to adjust the string, but it's confusing. Huh

Print this item

  Speed comparison of MID$ vs ASC
Posted by: SMcNeill - 10-22-2023, 03:19 AM - Forum: Learning Resources and Archives - Replies (10)

As it seems everyone is always trying to make their stuff run as fast as possible, I want to take a moment to once again point out the difference in speed between using STRING manipulation (such as MID$) verses the equivalent numeric manipulation (such as with ASC).

Take a brief moment to look at the following code, and compare the run times of these two simple routines:

Code: (Select All)
DEFLNG A-Z
CONST Limit = 100000000 '100 million

DIM s AS STRING
s = STRING$(Limit, "A") 'a string Limit characters long of all "A".

t# = TIMER
FOR i = 1 TO Limit
    IF MID$(s, i, 1) = "A" THEN MID$(s, i, 1) = "B"
NEXT
t1# = TIMER
FOR i = 1 TO Limit
    IF ASC(s, i) = 66 THEN ASC(s, i) = 67 'replace "B" with "C"
NEXT
t2# = TIMER

PRINT USING "###.### seconds to replace with MID$."; t1# - t#
PRINT USING "###.### seconds to replace with ASC."; t2# - t1#

PRINT LEFT$(s, 10) 'just to show we're all "C" now, so we know both replacements worked.


Replacing 100 million characters inside a string with another character, so give this a wee bit to run.  (Particularly if you're on an older, slower PC.)   On my machine, this takes about 8 seconds from start to finish, so you can use that as some sort of general starting benchmark of what to expect with a higher-end PC.  (If your machine is 10 years old, or a bargain basement model, give it 30+ seconds to run.  If you're on something older than that, go grab yourself a cup of coffee and kindly report the results when your antique finishes two hours from now -- I'd love to see the comparison values on some older hardware!)

Most folks seem to forget that in QB64PE, you can add a second exponent to the ASC command to get the particular character you want.   Even more folks seem to have absolutely no knowledge in the fact that ASC is also a SUB and not just a FUNCTION, and that the SUB version can be used to assign values to your string!

If you guys are ever the type to be concerned about the speed and performance of your programs, **REMEMBER** these two commands and the features they possess.  They're quite a bit faster than MID$, and can improve program performance considerably!

Print this item

  Performance improvement splitting huge file
Posted by: mdijkens - 10-21-2023, 01:36 PM - Forum: Help Me! - Replies (11)

This is a simplified part of a more complex process to split 1 huge inFile into multiple smaller outFile() ones:

Code: (Select All)
  Dim As _Unsigned _Byte inPos, splitFiles, splitFile
  Dim As _Unsigned _Integer64 inSize, splitPos, splitSize
  Dim As _Unsigned _Byte inFile(1 To inSize), char
  Get #1, 1, inFile()
  Dim As String outFile(splitFiles)
  For splitFile = 1 To splitFiles
    outFile(splitFile) = String$(splitSize, 0)
  Next splitFile

  For splitPos = 1 To splitSize
    For splitFile = 1 To splitFiles
      inPos = inPos + 1
      If inPos <= inSize Then
        char = inFile(inPos)
        Mid$(outFile(splitFile), splitPos, 1) = Chr$(char)
      End If
    Next splitFile
  Next splitPos
  For splitFile = 1 To splitFiles
    Put #splitFile%, , outFile(splitFile)
  Next splitFile
inFile is the byte-array of the inputfile
inSize is the size in bytes of the inFile
inPos is the current characterposition of the inFile
outFile() are the strings build for the split-files
splitFiles is the number of files to split into
splitSize is the size in bytes of each outFile (e.g. roundup(inSize/splitFiles))
splitFile is current splitFile
splitPos is the current characterposition of the outFile

Above works, but variable length strings and the Mid$() command are very time-expensive (2GB inFile takes ~3 minutes)

I've tried 2-dimensional byte-arrays for the out-files like outFile(files, length) , but QB64 does not support Put with one dimension like Put #x, , outFile(x)
I've also tried mapping this 2-dimensional array with _MEM but did not succeed so far.

Does anyone have a clever trick to speed this up?

Print this item

  ASCII Animations
Posted by: SpriggsySpriggs - 10-21-2023, 07:15 AM - Forum: Programs - Replies (6)

Inspired by the thread started by mnrvovrfc (https://qb64phoenix.com/forum/showthread.php?tid=2112), I converted the whole Rick Astley - Never Gonna Give You Up music video to an ASCII animation.

And the code:

Code: (Select All)
Option Explicit
$NoPrefix

Screen NewImage(80, 25)

'You know the rules and so do I
Sleep
Open "B", 1, "rickroll.txt"
Dim As Long x
Dim As String pic, buf
Dim As Long s: s = SndOpen("02 - Rick Astley - Never Gonna Give You Up.flac", "STREAM")
If s Then SndPlay (s)
While Not EOF(1)
    For x = 0 To 24
        If EOF(1) = 0 Then
            Line Input #1, buf
            pic = pic + buf
        End If
    Next
    Cls
    Print Mid$(pic, 2)
    Limit 60
    pic = ""
    If EOF(1) Then Exit While
Wend
Close

Converted the video like this:
1) Download a GIF or video with plain background, preferably white. In my case, I had to get the green screen version of the music video and then use Kdenlive to make it white.
2) Use ffmpeg to convert the video/GIF into a JPEG image sequence
Code: (Select All)
ffmpeg -i rickroll.mkv -vsync 0 rickroll/rickroll_%d.jpg
3) Use a Python script 
.txt   img2ascii.txt (Size: 3.15 KB / Downloads: 49) (save as img2ascii.py) in a bash loop to iterate over each frame and convert them into ASCII text files
Code: (Select All)
#!/bin/bash
for filename in rickroll/*.jpg; do
    sem -j+0 python img2ascii.py --file "$filename" --out rickroll/$(basename "$filename".txt)
done
#you might have to kill this sem call to proceed
sem --wait
cat $(find rickroll/ -name "rickroll_*.jpg.txt" | sort -V) >> rickroll.txt
rm rickroll/rickroll_*.jpg.txt
echo "DONE"
4) Monitor the output of the script. It will tell you how many columns and rows the images are. Set your QB64 up for that many columns and rows for a perfect output!

5) ???
6) Profit


If you don't want to go through all that and just want to run it:
Linux - 
.zip   rickroll_lnx.zip (Size: 30.2 MB / Downloads: 77)
Windows - 
.zip   rickroll_win.zip (Size: 30.51 MB / Downloads: 81)

Print this item

  Best Bubble Sort
Posted by: dbox - 10-20-2023, 07:36 PM - Forum: QBJS, BAM, and Other BASICs - Replies (8)

I just saw where Spriggsy posted this great new algorithm.

Click this link to try it out in QBJS.



Attached Files
.zip   rr.zip (Size: 93.86 KB / Downloads: 144)
Print this item