Posts: 189
Threads: 22
Joined: Mar 2023
Reputation:
12
Hey coding wizards,
Help! The game I'm working on is misbehaving and I don't understand why. When I go to a certain subroutine it all runs fine, but then if I go back to the beginning of the program - the main loop - the game slows to a crawl and starts crashing over issues that ran perfectly well before that subroutine. I tried using CLEAR, ERASE and RUN in different ways to wipe the slate clean and reload assets, but each of those commands just crashes the program. Thoughts? Suggestions? I'm using QB64 Version 2.0.2 because it runs well on an older Mac I use for coding.
Thanks very much,
Befuddled Ted
Posts: 3,968
Threads: 177
Joined: Apr 2022
Reputation:
219
04-21-2023, 06:42 PM
(This post was last modified: 04-21-2023, 06:43 PM by bplus.)
Code? At least for subroutine changing the main loop progress, is it a Gosub or real Sub?
I bet you are using a Gosub and it is messing with main loop variables.
b = b + ...
Posts: 246
Threads: 44
Joined: May 2022
Reputation:
28
This is described too generally. What does the subroutine do? Doesn't it stay running after you leave it? Does it change the variables somehow? Is it a SUB? If so, do you know that the parameters in parentheses (function arguments) change and return changed if SUB changes them? Are you creating virtual screens there and not freeing memory? Or do you work with fonts? Or with an eight-bit and a 32-bit screen? There are too many questions, I can try to advise you, but you need to be more specific.
Posts: 1,586
Threads: 59
Joined: Jul 2022
Reputation:
52
I don't know how you code. But if you put subroutines at the end please put a lonely "END" or "SYSTEM" statement to define the end of the main program!
If you use $CONSOLE:ONLY then SYSTEM should do it if you don't want the "Press enter to continue" prompt. Otherwise use END.
Trying to use CLEAR just causes trouble anyhow. That statement should be deprecated and made unavailable for anything.
If you put subroutines mingling with other parts of the main program code then I don't know what to tell you. There are no more excuses for spaghetti code much later than the 1980's.
Posts: 382
Threads: 56
Joined: Apr 2022
Reputation:
13
Hi Naked - This happens to me a lot. One thing that I picked up on this site (sorry I'm not sure who to give the credit to) was positioning some code inside a loop when it should have been outside the loop. I've also, and one would wonder how I did this, but I accidentally had a recursive call coded. And don't get me stated on division by zero. If you do find the cause, I'd love to hear how you resolved.
Posts: 189
Threads: 22
Joined: Mar 2023
Reputation:
12
Thanks for the quick responses. I'm using real SUBs not GOSUBs. The subroutine in question creates a moving star field at warp, so there's a lot going on, but the sub has no parameters. It uses 3 large shared arrays of star TYPEs (x,y,z,vector,color) with about 7000 total array elements in play. The sub terminates when the user goes back to the beginning. I have a SYSTEM statement at the end of my main loop. There are a lot of flags to track events, but it all runs fine till after that warp sub. I was inspired by Terry's tutorial, so I've worked hard to do everything the right way and avoid spaghetti coding. I do load fonts, but learned to use ones that don't bog everything down too much with onscreen displaying and moving. I'm not using any virtual screens. I am at a high resolution of 1600 x 900, but again it works fine till after the warp sub. Thnx
Posts: 2,696
Threads: 327
Joined: Apr 2022
Reputation:
217
04-21-2023, 08:23 PM
(This post was last modified: 04-21-2023, 08:24 PM by SMcNeill.)
Without seeing the code itself, my initial guess would be probable corruption via a passed parameter.
Let's say we have some simple code like this:
Code: (Select All) delay = 10 'we start with a limit of 10 loops per second as a manual/visable pause
Do
For pause = 1 To delay 'just a pause for 1 second
_Limit 10 'we'll run this loop 10 times per second, which is how we get a 1 second pause.
Next
k = _KeyHit
Select Case k
Case 32 'call the sub and watch what happens
SlowDown delay
Case 27
System
End Select
Print count, "We had to run the pause loop "; delay; "times, which took "; delay / 10; "seconds."
count = count + 1
Loop
Sub SlowDown (l)
l = l * 2
End Sub
Compile and run the above. You'll see that we start out printing text to the screen every second. Hit the spacebar however, and trigger our SUB, and we double the delay in printing. Our SUB is passing values back and forth via the parameters, and that's changing how the main program works afterwards,
IF this corruption via parameter is your issue, the simple solution is to pass a value and then assign it to a different variable inside the sub afterwards, preserving the original completely.
Code: (Select All) Sub SlowDown (templ)
l = templ 'assign the passed value to a different variable so its value won't change when leaving the sub or function.
l = l * 2
End Sub
Posts: 2,696
Threads: 327
Joined: Apr 2022
Reputation:
217
(04-21-2023, 08:08 PM)NakedApe Wrote: ...the sub has no parameters.
You posted while I was typing a response, so it seems my guess was wrong.
Without seeing the actual code in question, I don't think anyone is going to be of much help in finding/fixing the issue for you. Can you share the program, or at least the problem SUB, with us for reference?
Posts: 3,968
Threads: 177
Joined: Apr 2022
Reputation:
219
04-21-2023, 08:44 PM
(This post was last modified: 04-21-2023, 08:52 PM by bplus.)
Yeah, real sub but no parameters, OK
So look at what is being shared between main and sub, All or nearly all just about like a Gosub (I bet), or none which would make the bogged down issue really curious for sure.
More: The word Restart is in the title. Maybe you have start code in the real sub that should be removed and done once at the beginning separate from the Sub code.
BTW is the Sub basically the entire program? Where is the main loop? In the Sub or the main calling the SUB.
b = b + ...
Posts: 1,586
Threads: 59
Joined: Jul 2022
Reputation:
52
If the SUB-program is the only one being called by the main program, why declare large arrays globally? If it's not needed by main module-level code, then could declare such arrays with STATIC inside the SUB. However, then you would have to initialize it the first time the SUB is called, or when the user of the program "goes back to the beginning".
Otherwise if it's a few variables to share between main program and SUB, and only the large arrays declared globally then everything has been already said here.
If there's only one SUB which involves changing values from a large array, you have to be very careful about those changes. The indexes (subscripts) of the arrays might be going out of bounds. I forgot how to get QB64 to compile with "debug" information enabled so the program returns a runtime error at a subscript less than LBOUND() and greater than UBOUND().
It's easy to be confused by a statement such as LOCATE when the user wants "array(x,y)" and LOCATE terminally insists in "y, x" or "row, column". Then it would be easy to track an out-of-range error when there are way more columns across the screen than rows.
|