Author Topic: Steve's Xmas Game 2021  (Read 3186 times)

0 Members and 1 Guest are viewing this topic.

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Steve's Xmas Game 2021
« Reply #15 on: November 29, 2021, 07:53:35 am »
Steve, great Christmas program.  Relaxing, and has a good vibe.  Even my wife was curious how to use it, and she is usually anti-programming on me. (I'd insert a funny smiley here but I haven't figured out how yet).  Nice classic song choice too, I've been getting requests for that on dining room gigs at retirement communities already.  I like the old timey wallpaper collection too.   Anyway, well done.  Runs well for me.  Gets me in the mood for Christmas.

- Dav

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #16 on: December 01, 2021, 01:19:34 am »
Version 0.4 is now up: https://1drv.ms/u/s!AknUrv8RXVYMm_QQ3W8KOf27i39tTA?e=jphyRd

Changes include:

A wider selection of music to play in the background, for anyone who stays in the program long enough to notice.  (The first song is always the same, but after that there's an assortment of music which it can play for you, which shuffles itself each runtime.)

falcon.h has been modified so that the path is no longer an issue, and it has been included into the main download folder itself now.  For most folks, this means you can just download the 7z, extract it, and compile the Xmas.bas file if you want and have it work, without having to make certain that anything is in the proper place or not.  It helps simplify the build process for us.

For Windows users, I went ahead and kept the compiled Xmas.EXE in the package for you guys.  It adds a little extra to the download size, but at this point I don't care about that.  Our resource files are much larger than any EXE would ever be, and it just makes things convenient for the end users.  (Like Dav's sweet wife, who has impeccable taste and astute aesthetics to enjoy my work!)  ;)

Our Christmas "Time to Color" background has been colorized, thanks to the coloring game itself!  This helps it pop out and look more appealing, in my opinion.  (Also helps highlight the difference between it and our actual coloring pages, once we click on it.)

  [ You are not allowed to view this attachment ]  

The only issue which I'm currently concerned about is with start-up behavior for people with slower, older computers.  There's a large music selection now which the program loads in the background while the user is enjoy the background or making selections and clicking on options.  I've tried to work this out so that it processes one file at a time, unobtrusively, but from my experience, loading a sound file can cause a half second delay (or more) as _SNDOPEN opens and decodes it into memory.  On a modern PC this isn't such a drag that it's very noticeable, but I'm afraid it might be an issue with older machines, and I'm not entirely certain how to work around it if it is.

When you guys test this version out, let me know how it performs for you and if it seems to miss mouse clicks (it shouldn't), or if it seems excessively slow to respond to them. (I'm worried it might, but hope not.  Mine's a newer, top of the line gaming PC and laptop, so almost nothing bogs it down, and this doesn't cause any problems for me personally.  I'm just worried that folks like Cobalt might see issues on his old 286's which he has running Dos 2.0 still...  ;D )

If all works well, and I don't have to do a rewrite anywhere to try and bypass some sort of lag issue, then the next things to implement are:

The high score system.  (For now, it'll track number of pictures colored and saved, and number of pictures printed for each user.  Except for the Grinch.  That dude never gets credit for anything he does!)  This should give us an actual reason to take advantage of the pretty little Log-in system from now on, rather than just bypass it and go straight to the games. 

One we have high scores starting to save themselves, I'll also need to add in the LOAD PLAYER option, so you can resume with your old log-in, and not have to start over from scratch each time as well, so those are the next two basic options which I'll be working into the game if all works as advertised without any major issues for anyone.
« Last Edit: December 01, 2021, 01:25:02 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Steve's Xmas Game 2021
« Reply #17 on: December 01, 2021, 09:33:59 am »
I'm sure this christmas musical coloring book is awesome, but can we get an alpha-version download that isn't 900 gigs and virus-ridden?

  [ You are not allowed to view this attachment ]  

Half-kidding, I'm sure that's my browser and operating system just being cranky. But the fact remains that I literally can't download this project.

Might I suggest a release with 5 pictures, 2 songs, and the rest just code - the thing we actually want to see!
You're not done when it works, you're done when it's right.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Steve's Xmas Game 2021
« Reply #18 on: December 01, 2021, 01:30:20 pm »
My new Windows 10 return the same output: Downloading failed, virus found.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #19 on: December 01, 2021, 03:12:00 pm »
I'll dig into it to see why it's acting up with the virus detection.  Maybe Windows doesn't like the precompiled EXE?
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Steve's Xmas Game 2021
« Reply #20 on: December 01, 2021, 06:12:01 pm »
Loaded fine for me on Windows 10 Laptop.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #21 on: December 02, 2021, 12:54:41 am »
I'm sure this christmas musical coloring book is awesome, but can we get an alpha-version download that isn't 900 gigs and virus-ridden?

  [ You are not allowed to view this attachment ]  

Half-kidding, I'm sure that's my browser and operating system just being cranky. But the fact remains that I literally can't download this project.

Might I suggest a release with 5 pictures, 2 songs, and the rest just code - the thing we actually want to see!

We all know the truth -- there's nothing here that you actually want to see.  You're just looking for something to complain about. :P

Here, the definitive STx version, without any of the bells or whistles which makes it worthwhile:   [ You are not allowed to view this attachment ]  

Of course, since a good portion of the code is all about loading, dealing with, and handling multiple resource files in the background, you're missing out on 90% of the brilliance of the project, but at least it's small enough now for folks to divide by zero and download it off dial-up when they have to.  ;D

https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #22 on: December 02, 2021, 12:59:30 am »
My new Windows 10 return the same output: Downloading failed, virus found.

Give this a try:  https://1drv.ms/u/s!AknUrv8RXVYMm_RfDlAhJZLM5Bmp_Q?e=xelOqf

It's the same version with just the precompiled EXE stripped out.  I included it just for convenience's sake, but if it's going to be triggering anti-virus warnings for everyone, it's simply more convenient to leave it out. 

Let me know if there's any issues with the download.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Steve's Xmas Game 2021
« Reply #23 on: December 02, 2021, 10:50:32 am »
@SMcNeill

Hi, thanks for the link. I tried it on windows 7 (other computer) and it behaves strangely - now seeing to source and this do opening sound files. At first, it didn't want to respond to anything at all (mouse or keyboard) and memory usage rose to 1.3 gigabytes. Thid duration is about 1 minute. I thing, you use RAMDRIVE? I use here standard harddrive... After that, it started to work fast and the memory usage remained at the same level and no longer increased.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #24 on: December 02, 2021, 02:50:58 pm »
@SMcNeill

Hi, thanks for the link. I tried it on windows 7 (other computer) and it behaves strangely - now seeing to source and this do opening sound files. At first, it didn't want to respond to anything at all (mouse or keyboard) and memory usage rose to 1.3 gigabytes. Thid duration is about 1 minute. I thing, you use RAMDRIVE? I use here standard harddrive... After that, it started to work fast and the memory usage remained at the same level and no longer increased.

@Petr thanks for the testing and invaluable feedback. 

If you look at the code, it's only supposed to load the sound files one at a time and then exit so the other routines can process keyboard/mouse clicks.  I've been testing it on my laptop with a SSD, and things seem to work okay with the mouse.  (To be honest, I'm not certain if I even tried it with the keyboard or not.  Lately my back has been hurting so I've been coding from my recliner and the mouse/trackball is a much simpler input device than the keyboard on my laptop which I'm not used to yet.)

The issue is QB64's slow loading of music files.  Even on my SSD, they often take 2-3 seconds to load and process.  I'd considered loading and unloading them, on the fly, as needed, but you never know when that delay with impact the user's experience.  So then I thoughtI'd load everything at start-up, but that causes a minute long opening for the game.  (Maybe if I animated a logo and some sound to distract the user, such a delay could be overlooked, but that's a lot of work just to conceal a background process.)

In an attempt to bypass both those major issues, I was hoping to load in the background, but apparently something is working quite right yet, from your description.  Now, I could always do as STx suggests and only use a single resource file of tiny size, but -- like you -- I have other projects I'm working on in the background.  Sorting out resource loading and management now, for a simple project like this one, will save me the time and hassle to figure them out later with other projects.

If what I have now isn't working as I'd hoped, as you say it isn't, then I need to rethink my process.  I'll have to dig into the keyboard routines, as I have an idea what the problem could be there (my custom Keyhit has no buffer by default, whereas _KEYHIT does), and I'll see if I can make the mouse more responsive as well. 

I'll give it one more good push for the current style of process handling, and if it doesn't work this next go, I'll switch gears and shoot for a completely different solution.  Heck, if all else fails, I can always use some video/audio editing software to break each song up into small, 10-second soundbites, to minimize load times of each segment -- but that'd be an extreme last resort.

There's a balance to be found yet, I'm certain, between loading resource files, program lag, and input responsiveness.  I just have to keep playing around to find the right combination which works on all machines outthere.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #25 on: December 02, 2021, 03:14:09 pm »
@Petr See if this is more responsive for you:

Code: QB64: [Select]
  1. 'So I can quickly add debug text if needed.  It's not ON by default.
  2.  
  3. '$INCLUDE:'Keyboard Library.BI'
  4. '$INCLUDE:'Virtual Keyboard.BI'
  5. '$INCLUDE:'SaveImage.BI'
  6. Repeat_Speed = 0.2 'Global variable in the Virtual Keyboard library which a user can change for repeat speed
  7.  
  8.  
  9. Screen _NewImage(1280, 720, 32)
  10.  
  11.  
  12. 'Remove the titlebar if on windows just to keep it prettier
  13. $If WIN Then
  14.     Declare Dynamic Library "User32"
  15.         Function GetWindowLongA& (ByVal hWnd As _Offset, Byval nIndex As Long)
  16.         Function SetWindowLongA& (ByVal hWnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  17.         Function SetWindowPos& (ByVal hWnd As Long, Byval hWndInsertAfter As _Offset, Byval X As Integer,_
  18.                   Byval Y As Integer, Byval cx As Integer, Byval cy As Integer, Byval uFlags As _Offset)
  19.  
  20.     End Declare
  21.     a = SetWindowLongA&(_WindowHandle, -16, GetWindowLongA(_WindowHandle, -16) And Not &H00C80000)
  22.     a& = SetWindowPos&(_WindowHandle, 0, _DesktopWidth / 2 - 640, _DesktopHeight / 2 - 360, 1280, 720, 32)
  23.  
  24. $If FALCON = UNDEFINED Then
  25.     $Let FALCON = TRUE
  26.     Declare Library "./falcon"
  27.         Sub uprint_extra (ByVal x&, Byval y&, Byval chars%&, Byval length%&, Byval kern&, Byval do_render&, txt_width&, Byval charpos%&, charcount&, Byval colour~&, Byval max_width&)
  28.         Function uprint (ByVal x&, Byval y&, chars$, Byval txt_len&, Byval colour~&, Byval max_width&)
  29.         Function uprintwidth (chars$, Byval txt_len&, Byval max_width&)
  30.         Function uheight& ()
  31.         Function uspacing& ()
  32.         Function uascension& ()
  33.     End Declare
  34.     Dim Shared QPrintTextType As String
  35.     QPrintTextType = "ASCII"
  36.  
  37.  
  38. Dim Shared As Long MusicPlaying
  39.  
  40.     TitleScreen
  41.     MainMenu
  42.  
  43.  
  44. '$INCLUDE:'Virtual Keyboard.BM'
  45. '$INCLUDE:'Keyboard Library.BM'
  46. '$INCLUDE:'SaveImage.BM'
  47.  
  48. Sub ColorIt
  49.     ReDim As String Dir(0), File(0)
  50.     GetLists "Coloring Sheets", Dir(), File()
  51.  
  52.  
  53.     f = _Font
  54.     f128 = _LoadFont("Xmas.ttf", 128)
  55.  
  56.     ImageLimit = UBound(File) '
  57.     ReDim As Long Image(ImageLimit)
  58.     CandyArrow = _LoadImage(".\candy arrow.jpg", 32)
  59.     For i = 1 To ImageLimit
  60.         Image(i) = _LoadImage("Coloring Sheets\" + File(i), 32)
  61.         'Image(i) = _LoadImage(File(i), 32)
  62.     Next
  63.     choice = 1: Oldmouse = -1
  64.     Color Green, 0
  65.     Do
  66.         Cls , SkyBlue
  67.         CenterText 25, "Welcome, " + User, f128
  68.         _PutImage (50, 400)-(250, 300), CandyArrow
  69.         _PutImage (300, 175)-(980, 560), Image(choice)
  70.         _PutImage (1230, 300)-(1030, 400), CandyArrow
  71.         CenterText 575, "What to color?", f128
  72.         k = _KeyHit
  73.         scroll = 0
  74.         While _MouseInput
  75.             If _MouseButton(1) Or _MouseButton(2) Then Exit While
  76.             scroll = scroll + _MouseWheel
  77.         Wend
  78.         scroll = Sgn(scroll)
  79.         If scroll = 1 Then k = 19200 'scroll left in choices
  80.         If scroll = -1 Then k = 20480 'scroll right in choices
  81.         MX = _MouseX: MY = _MouseY: MB = _MouseButton(1)
  82.         If MB And Not Oldmouse Then
  83.             k = 13 'count it as an enter press unless it's in the arrows
  84.             If MY >= 300 And MY <= 400 Then 'in the right y area for arrow interaction
  85.                 If MX >= 50 And MX <= 250 Then k = 19200 'in the left arrow box
  86.                 If MX >= 1030 And MX <= 1230 Then k = 20480 'in the right arrow box
  87.             End If
  88.         End If
  89.         If _MouseButton(2) Then k = 27
  90.         Select Case k
  91.             Case 19200, 18432 'left/up
  92.                 choice = choice - 1
  93.                 If choice < 1 Then choice = ImageLimit
  94.             Case 20480, 19712 'right/down
  95.                 choice = choice + 1
  96.                 If choice > ImageLimit Then choice = 1
  97.             Case 27 'ESC
  98.                 GoSub beforeexit
  99.                 MainMenu
  100.             Case 32, 13 'SELECT AN IMAGE
  101.                 Exit Do
  102.         End Select
  103.         _Limit 30
  104.         _Display
  105.         Oldmouse = MB
  106.     Loop
  107.  
  108.  
  109.     Dim kolor(3, 5) As _Unsigned Long
  110.     kolor(0, 0) = Black: kolor(1, 0) = DarkBlue: kolor(2, 0) = DarkGreen: kolor(3, 0) = DarkCyan
  111.     kolor(0, 1) = DarkRed: kolor(1, 1) = DarkMagenta: kolor(2, 1) = GoldenRod: kolor(3, 1) = LightGray
  112.     kolor(0, 2) = DimGray: kolor(1, 2) = Blue: kolor(2, 2) = Lime: kolor(3, 2) = Cyan
  113.     kolor(0, 3) = Red: kolor(1, 3) = Magenta: kolor(2, 3) = Yellow: kolor(3, 3) = White
  114.     kolor(0, 4) = Gold: kolor(1, 4) = Purple: kolor(2, 4) = Pink: kolor(3, 4) = Copper
  115.     kolor(0, 5) = Orange: kolor(1, 5) = Maroon: kolor(2, 5) = Salmon: kolor(3, 5) = Tann
  116.  
  117.  
  118.  
  119.     'At this point, we should now have our image chosen for coloring.
  120.     'Let's draw a simple color interface and place the image on the screen and start playing with it!
  121.     R = 128: G = 128: B = 128
  122.     Oldmouse = -1
  123.     Cls
  124.     _PutImage (0, 0)-(1000, 720), Image(choice)
  125.     Color White, 0
  126.     Do
  127.         CheckMusic
  128.         Line (1001, 0)-(1279, 719), DarkGray, BF
  129.         Line (1010, 25)-Step(257, 25), LightGray, BF
  130.         Line (1010, 25)-Step(R, 25), Red, BF
  131.         Line (1010, 60)-Step(257, 25), LightGray, BF
  132.         Line (1010, 60)-Step(G, 25), Green, BF
  133.         Line (1010, 95)-Step(257, 25), LightGray, BF
  134.         Line (1010, 95)-Step(B, 25), Blue, BF
  135.         Line (1010, 130)-Step(257, 70), _RGB32(R, G, B), BF
  136.         _PrintString (1090, 156), "Custom Color"
  137.         For x = 0 To 3
  138.             For y = 0 To 5
  139.                 Line (1020 + 60 * x, 220 + 60 * y)-Step(50, 50), kolor(x, y), BF
  140.         Next y, x
  141.         Line (1010, 590)-Step(120, 50), Green, BF
  142.         _PrintString (1070 - _PrintWidth("Save") \ 2, 610), "Save"
  143.         Line (1150, 590)-Step(120, 50), Green, BF
  144.         _PrintString (1210 - _PrintWidth("Print") \ 2, 610), "Print"
  145.         Line (1010, 650)-Step(250, 50), Red, BF
  146.         _PrintString (1135 - _PrintWidth("Quit") \ 2, 670), "Quit"
  147.         While _MouseInput
  148.             If _MouseButton(1) Or _MouseButton(2) Then Exit While
  149.         Wend
  150.         MX = _MouseX: MY = _MouseY: MB = _MouseButton(1): mb2 = _MouseButton(2)
  151.  
  152.         If MX < 1000 And MB And Not Oldmouse Then Paint (MX, MY), _RGB32(R, G, B), _RGB32(0, 0, 0)
  153.         If MB Then
  154.             If MX > 1010 And MX < 1265 Then 'on a color tile?
  155.                 If MY >= 25 And MY <= 50 Then R = MX - 1010
  156.                 If MY >= 60 And MY <= 85 Then G = MX - 1010
  157.                 If MY >= 95 And MY <= 120 Then B = MX - 1010
  158.             End If
  159.             If Not Oldmouse Then
  160.                 For x = 0 To 3
  161.                     For y = 0 To 5
  162.                            if MX >= 1020 + 60 * x and MX <= 1070 + 60 * x and _
  163.                               MY >= 220 + 60 * y and MY <= 270 + 60 * y then
  164.                             R = _Red32(kolor(x, y))
  165.                             G = _Green32(kolor(x, y))
  166.                             B = _Blue32(kolor(x, y))
  167.                         End If
  168.                 Next y, x
  169.                 If MX >= 1010 And MX <= 1130 And MY >= 590 And MY <= 640 Then
  170.                     Open "Saved Images\saved count.bin" For Binary As #1
  171.                     Get #1, 1, SC&
  172.                     SC& = SC& + 1
  173.                     Put #1, 1, SC&
  174.                     Close
  175.                     file$ = "Saved Images\Saved Picture" + Str$(SC&) + ".png"
  176.                     result = SaveImage(file$, 0, 0, 0, 1000, 719)
  177.                     PCopy 0, 1: Cls , 0
  178.                     Print "Image Saved as "; file$: _Display
  179.                     _Delay 5
  180.                     Print: Print "Press <ANY KEY> to return.": _Display
  181.                     Do: _Limit 15: Loop Until _KeyHit
  182.                     PCopy 1, 0
  183.                 End If
  184.  
  185.                 If MX >= 1150 And MX <= 1270 And MY >= 590 And MY <= 640 Then
  186.                     tempImage = _NewImage(1000, 720, 32)
  187.                     _PutImage , 0, tempImage, (0, 0)-(1000, 719)
  188.                     _PrintImage tempImage
  189.                     _FreeImage tempImage
  190.                 End If
  191.                 If MX >= 1010 And MX <= 1270 And MY >= 650 And MY <= 700 Then Exit Do
  192.             End If
  193.         End If
  194.         If mb2 Then Exit Do
  195.         _Limit 30
  196.         _Display
  197.         Oldmouse = MB
  198.     Loop
  199.  
  200.  
  201.  
  202.     GoSub beforeexit
  203.     Exit Sub
  204.  
  205.  
  206.  
  207.     beforeexit:
  208.     For i = 1 To ImageLimit: _FreeImage Image(i): Next
  209.     _FreeImage CandyArrow
  210.     _FreeFont f128
  211.     Return
  212.  
  213.  
  214.  
  215.  
  216. Sub ChooseGame
  217.     If User = "" Then User = "Grinch"
  218.     f = _Font
  219.     f128 = _LoadFont("Xmas.ttf", 128)
  220.  
  221.     GameLimit = 1 '                          Increase game limit and add new games as we go!
  222.     Dim As String Games(1 To GameLimit)
  223.     Dim As Long GameImage(1 To GameLimit)
  224.     Games(1) = "Christmas Color It!"
  225.  
  226.     GameImage(1) = _LoadImage("The Season to Color.png", 33)
  227.  
  228.     CandyArrow = _LoadImage(".\candy arrow.jpg", 32)
  229.     choice = 1: Oldmouse = -1: Oldmouse2 = -1
  230.     Color Green, 0
  231.     Do
  232.         Cls , SkyBlue
  233.         CenterText 25, "Welcome, " + User, f128
  234.         _PutImage (50, 400)-(250, 300), CandyArrow
  235.         _PutImage (300, 175)-(980, 560), GameImage(choice)
  236.         _PutImage (1230, 300)-(1030, 400), CandyArrow
  237.         CenterText 575, "Choose a game", f128
  238.         k = _KeyHit
  239.         scroll = 0
  240.         While _MouseInput
  241.             If _MouseButton(1) Or _MouseButton(2) Then Exit While
  242.             scroll = scroll + _MouseWheel
  243.         Wend
  244.         scroll = Sgn(scroll)
  245.         If scroll = 1 Then k = 19200 'scroll left in choices
  246.         If scroll = -1 Then k = 20480 'scroll right in choices
  247.         MB = _MouseButton(1): MB2 = _MouseButton(2)
  248.         If MB And Not Oldmouse Then
  249.             k = 13 'count it as an enter press unless it's in the arrows
  250.             If MY >= 300 And MY <= 400 Then 'in the right y area for arrow interaction
  251.                 If MX >= 50 And MX <= 250 Then k = 19200 'in the left arrow box
  252.                 If MX >= 1030 And MX <= 1230 Then k = 20480 'in the right arrow box
  253.             End If
  254.         End If
  255.         If MB2 And Not Oldmouse2 Then k = 27
  256.         Select Case k
  257.             Case 19200, 18432 'left/up
  258.                 choice = choice - 1
  259.                 If choice < 1 Then choice = GameLimit
  260.             Case 20480, 19712 'right/down
  261.                 choice = choice + 1
  262.                 If choice > GameLimit Then choice = 1
  263.             Case 27 'ESC
  264.                 GoSub beforeexit
  265.                 Exit Sub
  266.             Case 32, 13 'SELECT A GAME
  267.                 GoSub beforeexit
  268.                 Select Case choice
  269.                     Case 1: ColorIt
  270.                 End Select
  271.                 Exit Sub
  272.         End Select
  273.         _Limit 30
  274.         _Display
  275.         Oldmouse = MB: Oldmouse2 = MB2
  276.     Loop
  277.  
  278.     beforeexit:
  279.     For i = 1 To GameLimit: _FreeImage GameImage(i): Next
  280.     _FreeImage CandyArrow
  281.     _Font f
  282.     _FreeFont f128
  283.     Return
  284.  
  285.  
  286.  
  287. Sub NewPlayer
  288.  
  289.     'CREATE YOUR CUSTOM KEYBOARD LAYOUT HERE
  290.     Dim My_Keyboard(5) As String
  291.     My_Keyboard(0) = CHR$(0) + "27,ESC" + STRING$(2,0) + "15104,F1" + STRING$(2,0) + "15360,F2" + _
  292.         STRING$(2,0) + "15616,F3" + STRING$(2,0) + "15872,F4" + STRING$(2,0) + "16128,F5" + _
  293.         STRING$(2,0) + "16384,F6" + STRING$(2,0) + "16640,F7" + STRING$(2,0) + "16896,F8" + _
  294.         STRING$(2,0) + "17152,F9" + STRING$(2,0) + "17408,F10" + STRING$(2,0) + "34048,F11" + _
  295.         STRING$(2,0) + "34304,F12" + CHR$(0)
  296.     My_Keyboard(1) = "`1234567890-=" + Chr$(0) + "8,BKSP" + Chr$(0)
  297.     My_Keyboard(2) = Chr$(0) + "9,TAB" + Chr$(0) + "QWERTYUIOP[]\"
  298.     My_Keyboard(3) = Chr$(0) + "100301,caps" + Chr$(0) + "ASDFGHJKL;'" + Chr$(0) + "13,ENTER" + Chr$(0)
  299.     My_Keyboard(4) = Chr$(0) + "100304,SHIFT" + Chr$(0) + "ZXCVBNM,./" + Chr$(0) + "100303,SHIFT" + Chr$(0)
  300.     My_Keyboard(5) = CHR$(0) + "100306,CTRL" + STRING$(2,0) + "100311,WIN" + STRING$(2,0) + "100308,ALT" + _
  301.         STRING$(2,0) + "32,SPACE" + STRING$(2,0) + "100307,ALT" + STRING$(2,0) + "100312,WIN" + _
  302.         STRING$(2,0) + "100319,MENU" + STRING$(2,0) + "100305,CTRL" +  CHR$(0)
  303.  
  304.     f = _Font
  305.     font = _LoadFont("Courbd.ttf", 20, "monospace") 'IF USED ON A KEYBOARD, DON'T FREE THIS FONT
  306.     font2 = _LoadFont("Courbd.ttf", 64, "monospace")
  307.     font3 = _LoadFont("Courbd.ttf", 32, "monospace")
  308.  
  309.     Button_Style_Up = Register_Button(50, 50, 50, 150, 150, 150, 8, font, &HFFFFFF00, 0) 'create the styles for our keyboard buttons
  310.     Button_Style_Down = Register_Button(150, 150, 150, 110, 110, 110, 8, font, &HFFFFFF00, 0)
  311.     FullsizeKB1 = Create_KB(My_Keyboard(), 85, 65, Button_Style_Up, Button_Style_Down) 'and make the keyboard
  312.  
  313.  
  314.     'REDEFINE MY LOwERCASE KEYS FOR KEYBOARD 2
  315.     My_Keyboard(1) = "~!@#$%^&*()_+" + Chr$(0) + "8,BKSP" + Chr$(0)
  316.     My_Keyboard(2) = Chr$(0) + "9,TAB" + Chr$(0) + "qwertyuiop{}|"
  317.     My_Keyboard(3) = Chr$(0) + "100301,CAPS" + Chr$(0) + "asdfghjkl:" + Chr$(34) + Chr$(0) + "13,ENTER" + Chr$(0)
  318.     My_Keyboard(4) = Chr$(0) + "100304,SHIFT" + Chr$(0) + "zxcvbnm<>?" + Chr$(0) + "100303,SHIFT" + Chr$(0)
  319.     FullsizeKB2 = Create_KB(My_Keyboard(), 85, 65, Button_Style_Up, Button_Style_Down)
  320.  
  321.     Keyboard_In_Use = FullsizeKB1 'Set the keyboard I'm currently using
  322.     'View Print 1 To 20
  323.     Do
  324.         _Font font2
  325.         Color White, 0
  326.         Do
  327.             CheckMusic
  328.             Cls , SkyBlue
  329.             Display_KB Keyboard_In_Use, 25, 280, -1 'display the virtual keyboard
  330.  
  331.             QPrintString 25, 32, "NAME" 'show the user generated name
  332.             Line (200, 25)-Step(1000, 75), DarkGray, BF
  333.             QPrintString 1200 - QPrintWidth(User), 32, User
  334.  
  335.  
  336.             While _MouseInput: Wend 'must update mouse buffer before reading virtual keyboard
  337.             k = _KeyHit 'The library version which reads all the keys for us, not the qb64 _KEYHIT version
  338.             '(ONLY FOR WINDOWS. LINUX/MAC USERS STILL GET THE SAME OLE BUGGY _KEYHIT FOR NOW.  SORRY.)
  339.             If k = 0 Or k > 900000 Then k = VK_Keyhit(Keyboard_In_Use) 'this checks the virtual keyboard
  340.             'If VK_Keydown(32) Then Print "Space held"; 'and here we can check for virtual keys being held down.
  341.             Select Case k
  342.                 Case 100301 'swap keyboards, rather than having a CAPS LOCK key
  343.                     Keyboard_In_Use = (Keyboard_In_Use + 1) Mod 2
  344.                     _Delay .2 'we need a delay here, as we haven't actually pressed any key on the new keyboard
  345.                     'so the keys aren't going to have a down timer to stop repeats.. We'd probably change keyboards
  346.                     'multiple times quickly without it, before we lifted our finger up off the mouse button.
  347.                 Case 27: System
  348.                 Case 8: User = Left$(User, Len(User) - 1)
  349.                 Case 13: Exit Do
  350.                 Case 1 TO 255: User = User + Chr$(k)
  351.             End Select
  352.             _Display
  353.         Loop
  354.  
  355.         User = _Trim$(User)
  356.         If User = "" Then User = "Grinch"
  357.  
  358.         'Confirm entry
  359.         Color Green, 0
  360.         choice = -1
  361.         text = TextToImage(User + " is correct?", font3, Green, 0&, 1)
  362.         _PutImage (325, 150)-(955, 225), text 'make certain our user name always fits nicely in the center
  363.         Do
  364.             CheckMusic
  365.             k = _KeyHit
  366.             Select Case k
  367.                 Case 19200, 18432, 20480, 19712: choice = Not choice
  368.                 Case 13: Exit Do
  369.                 Case 27: System
  370.             End Select
  371.             If choice Then
  372.                 Line (50, 150)-Step(250, 75), Red, BF
  373.                 Line (980, 150)-Step(250, 75), DarkGray, BF
  374.             Else
  375.                 Line (50, 150)-Step(250, 75), DarkGray, BF
  376.                 Line (980, 150)-Step(250, 75), Red, BF
  377.             End If
  378.             QPrintString 175 - QPrintWidth("YES") / 2, 150, "YES"
  379.             QPrintString 1105 - QPrintWidth("NO") / 2, 150, "NO"
  380.             _Limit 60
  381.             _Display
  382.         Loop
  383.         User = ""
  384.     Loop Until choice
  385.  
  386.     beforeexit:
  387.     _Font f
  388.     _FreeFont font
  389.     _FreeFont font2
  390.     _FreeImage text
  391.     If User = "" Then User = "Grinch"
  392.     ChooseGame
  393.  
  394. Sub MainMenu
  395.     restart:
  396.     ReDim As String Dir(0), File(0)
  397.     ReDim As Long menu(5): MakeMenus menu()
  398.     Static OldMouse
  399.     GetLists "Backgrounds", Dir(), File()
  400.     Do
  401.         count = count + 1: fetch = Int(Rnd * UBound(File)) + 1: file$ = "Backgrounds\" + File(fetch)
  402.     Loop Until _FileExists(file$) Or count = 1000
  403.     If count = 100 Then Cls: Print "ERROR CAN NOT LOAD BACKGROUNDS": End
  404.     bg = _LoadImage(file$, 33)
  405.  
  406.     _DisplayOrder _Hardware , _Software 'we're going to use hardware only screens, just for the speed of things
  407.     Type Flake_type: As Integer x, y, size: End Type: ReDim Flakes(1000) As Flake_type
  408.  
  409.     Cls , 0
  410.     choice = 1: OldMouse = -1: Oldmouse2 = -1
  411.     Do
  412.         CheckMusic
  413.         k = _KeyHit
  414.         While _MouseInput
  415.             If _MouseButton(1) Or _MouseButton(2) Then Exit While
  416.             choice = choice + _MouseWheel
  417.             If choice > 5 Then choice = 1
  418.             If choice < 1 Then choice = 5
  419.         Wend
  420.         MX = _MouseX: MY = _MouseY: MB = _MouseButton(1): MB2 = _MouseButton(2)
  421.  
  422.         If MX >= 400 And MX <= 880 Then 'mouse is in right row area
  423.             For i = 1 To 5
  424.                 If MY >= 75 * i + 100 And MY <= 75 * i + 175 Then choice = i
  425.             Next
  426.         End If
  427.         If MB = -1 And OldMouse = 0 Then k = 32
  428.         If MB2 And Not Oldmouse2 Then k = 27
  429.         Select Case k
  430.             Case 18432, 19200: choice = choice - 1: If choice < 1 Then choice = 5
  431.             Case 20480, 19712: choice = choice + 1: If choice > 5 Then choice = 1
  432.             Case 13, 32
  433.                 Select Case choice
  434.                     Case 1 'new player
  435.                         GoSub beforeexit
  436.                         NewPlayer
  437.                         Exit Sub
  438.                     Case 2 'load player
  439.                     Case 3 'new game
  440.                         GoSub beforeexit
  441.                         ChooseGame
  442.                         GoTo restart
  443.                     Case 4 'high scores
  444.                     Case 5: System
  445.                 End Select
  446.             Case 27: System
  447.         End Select
  448.         _PutImage (0, 0)-(1279, 719), bg
  449.         _PutImage (0, 0)-(1279, 719), menu(choice)
  450.         _Limit 30
  451.         _Display
  452.         OldMouse = MB: Oldmouse2 = MB2
  453.     Loop
  454.  
  455.     beforeexit:
  456.     For i = 1 To 5: _FreeImage menu(i): Next
  457.     Return
  458.  
  459. Sub MakeMenus (Menu() As Long)
  460.     Dim Options(5) As String, tempMenu(5) As Long
  461.     D = _Dest
  462.     Options(1) = "New Player": Options(2) = "Load Player": Options(3) = "New Game"
  463.     Options(4) = "Highscores": Options(5) = "Quit"
  464.     f64 = _LoadFont("Xmas3.ttf", 64)
  465.     For j = 1 To 5
  466.         tempMenu(j) = _NewImage(1280, 720, 32)
  467.         _Dest tempMenu(j)
  468.         For i = 1 To 5
  469.             If i = j Then Color Red, 0 Else Color DarkGray, 0
  470.             CenterText 75 * i + 100, Options(i), f64
  471.         Next
  472.         Menu(j) = _CopyImage(tempMenu(j), 33)
  473.         _FreeImage tempMenu(j)
  474.     Next
  475.     _Dest D
  476.     _FreeFont f64
  477.  
  478. Sub TitleScreen
  479.     CheckMusic
  480.     Cls , SkyBlue: Color Snow, 0
  481.     f128 = _LoadFont("Xmas.ttf", 128): f64 = _LoadFont("Xmas.ttf", 64)
  482.     Wreath = _LoadImage("Images\OIP (7).jpg", 32): _SetAlpha 0, &HFFADADAD To &HFFFFFFFF, Wreath
  483.     Tree = _LoadImage("Images\OIP (5).jpg", 32): _SetAlpha 0, &HFFADADAD To &HFFFFFFFF, Tree
  484.     Bell = _LoadImage("Images\OIP (1).jpg", 32): _SetAlpha 0, &HFFADADAD To &HFFFFFFFF, Bell
  485.     Present = _LoadImage("Images\OIP (21).jpg", 32): _SetAlpha 0, &HFFADADAD To &HFFFFFFFF, Present
  486.     CenterText 250, "Xmas  Match", f128
  487.     CenterText 375, "by SMcNeill", f64
  488.     _PutImage (50, 10)-Step(250, 250), Wreath: _PutImage (980, 10)-Step(250, 250), Bell
  489.     _PutImage (980, 400)-Step(250, 250), Tree: _PutImage (50, 400)-Step(250, 250), Present
  490.     _FreeImage Wreath: _FreeImage Bell: _FreeImage Tree: _FreeImage Present
  491.     _FreeFont f128: _FreeFont f64
  492.     Do
  493.         While _MouseInput
  494.             If _MouseButton(1) Or _MouseButton(2) Then Exit While
  495.         Wend
  496.         If _MouseButton(1) Then Exit Sub
  497.         If _MouseButton(2) Then System
  498.         _Limit 5
  499.     Loop Until _KeyHit Or Not _SndPlaying(MusicPlaying)
  500.  
  501.  
  502. Sub CheckMusic
  503.     Static As Long MusicList, MusicLoaded, MusicFiles(1000)
  504.     Static As _Float Delay
  505.     If MusicList = 0 Then
  506.         ReDim As String Dir(0), File(0)
  507.         GetLists "Music", Dir(), File()
  508.         MusicList = UBound(File)
  509.     End If
  510.     If MusicLoaded < MusicList And ExtendedTimer > Delay Then 'load music files while the user is busy looking at graphics or making choices
  511.         ReDim As String Dir(0), File(0)
  512.         GetLists "Music", Dir(), File()
  513.         MusicLoaded = MusicLoaded + 1
  514.         MusicFiles(MusicLoaded) = _SndOpen("Music/" + File(MusicLoaded)) 'Load one file at a time in the background
  515.         If MusicLoaded = MusicList Then
  516.             For i = 2 To MusicList 'shuffle the playlist each time the program starts for variety
  517.                 Swap MusicFiles(i), MusicFiles(Rnd * i + 1)
  518.             Next
  519.         End If
  520.         Delay = ExtendedTimer + 1 'At most, only load one file per second.  Have a delay between loading.
  521.     End If
  522.     If Not _SndPlaying(MusicPlaying) Then
  523.         MusicPlaying = MusicPlaying + 1
  524.         If MusicPlaying > MusicList Then MusicPlaying = 1 'replay the list all over again, if someone let it go that long!
  525.         _SndPlay MusicPlaying 'play the new music file
  526.     End If
  527.  
  528. Sub CenterText (y, text$, font)
  529.     f = _Font: _Font font: pw = QPrintWidth(text$): w = 1280: x = (w - pw) / 2
  530.     QPrintString x, y, text$: _Font f
  531.  
  532.  
  533. Sub SafeLoadFont (font#) 'Safely loads a font without destroying our current print location and making it revert to the top left corner.
  534.     right = Pos(0): down = (CsrLin - 1) * _FontHeight
  535.     If _FontWidth <> 0 Then right = (right - 1) * _PrintWidth(" ") 'convert the monospace LOC to a graphic X coordinate
  536.     _Font font#
  537.     If _FontWidth <> 0 Then right = (right / _PrintWidth(" ")) + 1 'convert the graphic X coordinate back to a monospace LOC column
  538.     down = (down / _FontHeight) + 1: If right < 1 Then right = 1
  539.     Locate down, right
  540.  
  541.  
  542.  
  543. Sub GetLists (SearchDirectory As String, DirList() As String, FileList() As String)
  544.     Declare CustomType Library ".\direntry"
  545.         Function load_dir& (s As String)
  546.         Function has_next_entry& ()
  547.         Sub close_dir ()
  548.         Sub get_next_entry (s As String, flags As Long, file_size As Long)
  549.     End Declare
  550.  
  551.     Dim flags As Long, file_size As Long, DirCount As Long, FileCount As Long, length As Long
  552.     Dim nam$, slash$
  553.     ReDim _Preserve DirList(1000), FileList(1000)
  554.     DirCount = 0: FileCount = 0
  555.     $If WIN Then
  556.         slash$ = "\"
  557.     $Else
  558.         slash$ = "/"
  559.     $End If
  560.     If Right$(SearchDirectory$, 1) <> "/" And Right$(SearchDirectory$, 1) <> "\" Then SearchDirectory$ = SearchDirectory$ + slash$
  561.  
  562.     If load_dir(SearchDirectory + Chr$(0)) Then
  563.         Do
  564.             length = has_next_entry
  565.             If length > -1 Then
  566.                 nam$ = Space$(length)
  567.                 get_next_entry nam$, flags, file_size
  568.                 If _DirExists(SearchDirectory + nam$) Then
  569.                     DirCount = DirCount + 1
  570.                     If DirCount > UBound(DirList) Then ReDim _Preserve DirList(UBound(DirList) + 100)
  571.                     DirList(DirCount) = nam$
  572.                 ElseIf _FileExists(SearchDirectory + nam$) Then
  573.                     FileCount = FileCount + 1
  574.                     If FileCount > UBound(FileList) Then ReDim _Preserve FileList(UBound(FileList) + 100)
  575.                     FileList(FileCount) = nam$
  576.                 Else 'This else should never actually trigger
  577.                     Print: Print: Print "zzz...  Unknown file found: "; SearchDirectory; slash$; nam$, _DirExists(nam$)
  578.                     Beep: Sleep ' alert the user to
  579.                 End If
  580.             End If
  581.         Loop Until length = -1
  582.     End If
  583.     close_dir
  584.  
  585.     ReDim _Preserve DirList(DirCount)
  586.     ReDim _Preserve FileList(FileCount)
  587.  
  588.  
  589.  
  590. Sub QPrint (temp$)
  591.     Static m As _MEM: m = _MemImage(0)
  592.     Dim BreakPoint As String
  593.     BreakPoint = ",./- ;:!" 'I consider all these to be valid breakpoints.  If you want something else, change them.
  594.     If QPrintTextType = "ASCII" Or QPrintTextType = "" Then text$ = _Trim$(AnsiTextToUtf8Text$(temp$)) Else text$ = temp$
  595.     count = -1
  596.     Do
  597.         'first find the natural length of the line
  598.         x = Pos(0) - 1: If _FontWidth Then x = x * _FontWidth
  599.         y = CsrLin
  600.         wide% = _Width - x - 1
  601.         For i = 1 To Len(text$)
  602.             If Asc(text$, i) = 10 Or Asc(text$, i) = 13 Then i = i - 1: Exit For
  603.             p = uprintwidth(text$, i, 0)
  604.             If p > wide% Then Exit For
  605.         Next
  606.         'IF i < LEN(text$) THEN lineend = i - 1 ELSE
  607.         lineend = i
  608.  
  609.         t$ = RTrim$(Left$(text$, lineend)) 'at most, our line can't be any longer than what fits the screen.
  610.         For i = lineend To 1 Step -1
  611.             If InStr(BreakPoint, Mid$(text$, i, 1)) Then lineend = i: Exit For
  612.         Next
  613.         out$ = RTrim$(Left$(text$, lineend))
  614.         text$ = LTrim$(Mid$(text$, lineend + 1))
  615.         If Left$(text$, 2) = Chr$(13) + Chr$(10) Then text$ = Mid$(text$, 3)
  616.         If Left$(text$, 2) = Chr$(10) + Chr$(13) Then text$ = Mid$(text$, 3)
  617.         If Left$(text$, 1) = Chr$(13) Then text$ = Mid$(text$, 2)
  618.         If Left$(text$, 1) = Chr$(10) Then text$ = Mid$(text$, 2)
  619.         If _BackgroundColor <> 0 Then
  620.             Line (x - 1, (y - 1) * uheight)-Step(uprintwidth(out$, Len(out$), 0), uheight), _BackgroundColor, BF
  621.         End If
  622.         w& = uprint(x - 1, (y - 1) * uheight, out$, Len(out$), _DefaultColor, 0)
  623.         x = 1
  624.         If y + 1 >= _Height / uheight Then 'scroll up
  625.             h = uheight * _Width * 4
  626.             t$ = Space$(m.SIZE - h)
  627.             _MemGet m, m.OFFSET + h, t$
  628.             Cls , 0
  629.             _MemPut m, m.OFFSET, t$
  630.             Locate y, x
  631.         Else
  632.             Locate y + 1, x
  633.         End If
  634.  
  635.     Loop Until text$ = ""
  636.     clean_exit:
  637.  
  638. Function QPrintWidth& (out$)
  639.     QPrintWidth = uprintwidth(out$, Len(out$), 0)
  640.  
  641. Function QFontHeight
  642.     QFontHeight = uheight
  643.  
  644. Sub QPrintString (x, y, text$)
  645.     If QPrintTextType = "ASCII" Or QPrintTextType = "" Then temp$ = _Trim$(AnsiTextToUtf8Text$(text$)) Else temp$ = text$
  646.         Line (x, y)-Step(uprintwidth(temp$, Len(temp$), 0), uheight), _BackgroundColor, BF
  647.     End If
  648.     w& = uprint(x, y, temp$, Len(temp$), _DefaultColor, 0)
  649.  
  650. Function AnsiTextToUtf8Text$ (text$)
  651.     Dim chi&, ascii%, unicode&, aci%
  652.     For chi& = 1 To Len(text$)
  653.         '--- get ANSI char code, reset Unicode ---
  654.         unicode& = _MapUnicode(Asc(text$, chi&))
  655.         If unicode& = 0 Then unicode& = 65533 'replacement character
  656.         temp$ = temp$ + UnicodeToUtf8Char$(unicode&)
  657.     Next chi&
  658.     AnsiTextToUtf8Text$ = temp$
  659.  
  660. Function UnicodeToUtf8Char$ (unicode&)
  661.     '--- option _explicit requirements ---
  662.     Dim uc&, first%, remain%, conti%
  663.     '--- UTF-8 encoding ---
  664.     If unicode& < 128 Then
  665.         '--- standard ASCII (0-127) goes as is ---
  666.         UnicodeToUtf8Char$ = Chr$(unicode&)
  667.         Exit Function
  668.     Else
  669.         '--- encode the Unicode into UTF-8 notation ---
  670.         temp$ = "": uc& = unicode& 'avoid argument side effect
  671.         first% = &B10000000: remain% = 63
  672.         Do
  673.             first% = &B10000000 Or (first% \ 2): remain% = (remain% \ 2)
  674.             conti% = &B10000000 Or (uc& And &B00111111): uc& = uc& \ 64
  675.             temp$ = Chr$(conti%) + temp$
  676.             If uc& <= remain% Then
  677.                 first% = (first% Or uc&): uc& = 0
  678.             End If
  679.         Loop Until uc& = 0
  680.         UnicodeToUtf8Char$ = Chr$(first%) + temp$
  681.     End If
  682.  
  683. Function TextToImage& (text$, font&, fc&, bfc&, mode As _Byte)
  684.     'text$ is the text that we wish to transform into an image.
  685.     'font& is the handle of the font we want to use.
  686.     'fc& is the color of the font we want to use.
  687.     'bfc& is the background color of the font.
  688.  
  689.     'Mode 1 is print forwards
  690.     'Mode 2 is print backwards
  691.     'Mode 3 is print from top to bottom
  692.     'Mode 4 is print from bottom up
  693.     'Mode 0 got lost somewhere, but it's OK.  We check to see if our mode is < 1 or > 4 and compensate automatically if it is to make it one (default).
  694.  
  695.     If mode < 1 Or mode > 4 Then mode = 1
  696.     dc& = _DefaultColor: bgc& = _BackgroundColor
  697.     D = _Dest
  698.     F = _Font
  699.     T2Idown = CsrLin: T2Iright = Pos(0)
  700.     If font& <> 0 Then _Font font&
  701.     If mode < 3 Then
  702.         'print the text lengthwise
  703.         w& = _PrintWidth(text$): h& = _FontHeight
  704.     Else
  705.         'print the text vertically
  706.         For i = 1 To Len(text$)
  707.             If w& < _PrintWidth(Mid$(text$, i, 1)) Then w& = _PrintWidth(Mid$(text$, i, 1))
  708.         Next
  709.         h& = _FontHeight * (Len(text$))
  710.     End If
  711.  
  712.     TextToImage_temp& = _NewImage(w&, h&, 32)
  713.     TextToImage = TextToImage_temp&
  714.     _Dest TextToImage_temp&
  715.     If font& <> 0 Then _Font font&
  716.     Color fc&, bfc&
  717.  
  718.     Select Case mode
  719.         Case 1
  720.             'Print text forward
  721.             _PrintString (0, 0), text$
  722.         Case 2
  723.             'Print text backwards
  724.             temp$ = ""
  725.             For i = 0 To Len(text$) - 1
  726.                 temp$ = temp$ + Mid$(text$, Len(text$) - i, 1)
  727.             Next
  728.             _PrintString (0, 0), temp$
  729.         Case 3
  730.             'Print text upwards
  731.             'first lets reverse the text, so it's easy to place
  732.             temp$ = ""
  733.             For i = 0 To Len(text$) - 1
  734.                 temp$ = temp$ + Mid$(text$, Len(text$) - i, 1)
  735.             Next
  736.             'then put it where it belongs
  737.             For i = 1 To Len(text$)
  738.                 fx = (w& - _PrintWidth(Mid$(temp$, i, 1))) / 2 + .99 'This is to center any non-monospaced letters so they look better
  739.                 _PrintString (fx, _FontHeight * (i - 1)), Mid$(temp$, i, 1)
  740.             Next
  741.         Case 4
  742.             'Print text downwards
  743.             For i = 1 To Len(text$)
  744.                 fx = (w& - _PrintWidth(Mid$(text$, i, 1))) / 2 + .99 'This is to center any non-monospaced letters so they look better
  745.                 _PrintString (fx, _FontHeight * (i - 1)), Mid$(text$, i, 1)
  746.             Next
  747.     End Select
  748.     _Dest D
  749.     Color dc&, bgc&
  750.     _Font F
  751.     Locate T2Idown, T2Iright
  752.  

I'm swapped over to _KEYHIT, which has a back buffer for us, and introduced a noticeable delay in the loading of resource files.  (Delay = ExtendedTimer + 1 'At most, only load one file per second.  Have a delay between loading. )

Hopefully these two tweaks will help with the unresponsiveness you described.  If not, then I'll have to switch gears completely and shoot for a different solution to this type problem.  (Not that many folks ever load 100+ MB of sound files into a program to begin with -- I just like to push the boundaries and create issues for myself that nobody else ever sees, I think sometimes.)

Try it in place of the last Xmas.bas you downloaded and let me know how it goes for you. ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Steve's Xmas Game 2021
« Reply #26 on: December 02, 2021, 03:42:50 pm »
@SMcNeill

Hi, it's a bit faster, but there are noticeable jamming at first.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Steve's Xmas Game 2021
« Reply #27 on: December 02, 2021, 04:21:22 pm »
@SMcNeill

Hi, it's a bit faster, but there are noticeable jamming at first.

Then I guess I need to rethink this approach.  QB64 just takes too long to decode each sound file, causing the issues you're talking about.  I'll just need to come up with a different way to load resources, which the users won't find too intrusive or time consuming/detrimental.  :)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!