10 D%=100
20 REPEAT
30 FOR I%=0 TO D%:NEXT
(game logic)
90 UNTIL0
It works fine, however I'd really like it to be as fast as possible when D% gets down to zero, having just spent most of the morning optimising my main loop for speed!
But of course the FOR statement is taking processing time even when D% is zero, so my main loop is only getting up to about 97% of possible speed.
Basically (no pun intended), I've removed the >0 check, so it's true if D% is non-zero. it just means that if D% goes negative the FOR loop will do one iteration, but the IF test should be faster.
Basically (no pun intended), I've removed the >0 check, so it's true if D% is non-zero. it just means that if D% goes negative the FOR loop will do one iteration, but the IF test should be faster.
That is faster, thanks.
I've gone from almost 98% full speed to almost 99% full speed:)
Double up the REPEAT statement to create two nested loops, and have the delay loop between two UNTIL statements: UNTIL D% followed by FORI%=0TOD%:NEXT:UNTIL 0.
That will have the inner loop execute exactly once as long as D% is bigger than 0; but once D% reaches zero, the inner loop will begin repeating forever without ever dropping back to the outer loop.
Whether the inner REPEAT ..... UNTIL has a worse speed penalty than using IF ..... THEN around the FOR ..... NEXT loop, or even just letting BASIC jump straight to the statement after the NEXT associated with a redundant FOR, is a matter probably best settled by experimentation!
10 D%=100
20 REPEAT
30 FOR I%=0 TO D%:NEXT
(game logic)
90 UNTIL0
That will take different amounts of time on different machines, in different weather, during different phases of the moon, when a disk is still rotating, when a network packet flies past, when a cosmic partical hits the serial ULA, and during any amount of other events. What you need is:
T%=TIME+delay:REPEAT UNTIL TIME>T%
It works fine, however I'd really like it to be as fast as possible when D% gets down to zero, having just spent most of the morning optimising my main loop for speed!
IF delay THEN T%=TIME+delay:REPEAT UNTIL TIME>T%
compacted to:
IFD%:T%=TIME+D%:REP.UN.TIME>T%
Double up the REPEAT statement to create two nested loops, and have the delay loop between two UNTIL statements: UNTIL D% followed by FORI%=0TOD%:NEXT:UNTIL 0.
That will have the inner loop execute exactly once as long as D% is bigger than 0; but once D% reaches zero, the inner loop will begin repeating forever without ever dropping back to the outer loop.
Whether the inner REPEAT ..... UNTIL has a worse speed penalty than using IF ..... THEN around the FOR ..... NEXT loop, or even just letting BASIC jump straight to the statement after the NEXT associated with a redundant FOR, is a matter probably best settled by experimentation!
The seems cunning, but should that be UNTIL NOT D%? If not then I don't think I'm understanding this. Either way I tried it (with a NOT) and it was a bit slower than the IF approach earlier.
That will take different amounts of time on different machines, in different weather, during different phases of the moon, when a disk is still rotating, when a network packet flies past, when a cosmic partical hits the serial ULA, and during any amount of other events. ...
Gosh. I suspect you and me both need to brace ourselves for the thread I'm about to start on the fact I've just let a GOTO slip into this program:)
If you're really trying to save every byte, the colon after the first D% is superfluous (U. is also an acceptable abbreviation for UNTIL, but that doesn't make any difference to the resulting tokenised program):
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
The seems cunning, but should that be UNTIL NOT D%? If not then I don't think I'm understanding this. Either way I tried it (with a NOT) and it was a bit slower than the IF approach earlier.
No; if D% is non-zero, you want the inner loop to execute just once and then fall through to the FOR loop before the outer UNTIL. If D% is zero, then you want the inner loop to repeat forever, without getting as far as the FOR loop.
Or, consider bypassing the delay loop with IF NOT D% GOTO <the number of the line immediately following the REPEAT>.
That will take different amounts of time on different machines, in different weather, during different phases of the moon, when a disk is still rotating, when a network packet flies past, when a cosmic partical hits the serial ULA, and during any amount of other events. What you need is:
T%=TIME+delay:REPEAT UNTIL TIME>T%
I'm finding that doesn't give me the kind of resolution I was hoping for.
When delay is 1/100th of a second, it can get roughly a play speed that feels right, but 2/100th of a second then makes it feel far too slow.
On my BBC B under normal conditions a simple for...next loop with an integer counter can get to about 33 in 1/100th of a second.
Is there a good-practice way from within BASIC which gets better resolution?
Since each machine runs at different speeds (and co-processors can make this even worse) maybe you should start your program with a simple counter loop and see how many times you loop
LET foobar=wanted*A/2:LET X=0:REPEAT:LET X=X+1:UNTIL X>foobar
You get consisent speed across platforms, but you'll never get to 100% speed with code like this, but you might be able to do some of the earlier optimisations to short-cut in the case where "wanted" is zero.
Is there a good-practice way from within BASIC which gets better resolution?
For resolutions less than 1/100 second it will be platform-dependent. As far as my BASICs are concerned these will give you a delay in milliseconds (but bear in mind that the OS only guarantees a minimum delay of the specified amount):
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Since each machine runs at different speeds (and co-processors can make this even worse) maybe you should start your program with a simple counter loop and see how many times you loop
Going back to the original question, the optimum way of achieving that doesn't involve a variable delay.
The fundamental 'timebase' in a any kind of video game is the display refresh rate (typically 50 or 60 frames per second depending on platform). To achieve smooth animation you should update the positions of moving objects at that rate - anything slower and the movement will not be smooth and anything faster will either be wasted effort - the resulting frame(s) will never be displayed - or you may get 'tearing' part way down the screen, depending on how the display refresh happens.
So in an ideal world you should have a fixed update rate, synchronised with the display refresh rate, and then the speed of the game depends on how far objects move in that fixed period (velocity = ds/dt). To arrange that the game gets gradually faster what you need to do is to gradually increase the distance moved in a given time (ds) not reduce the time taken to move a given distance (dt).
Of course if you're working with a slow machine like a BBC Micro you may well not have the luxury of being able to animate everything at the display refresh rate, or even at (say) half that rate - especially in BASIC - and non-smooth movement may therefore be unavoidable. But it's still worth considering the approach of keeping the update rate more-or-less constant and changing the distance moved by objects in that time, rather than having a variable delay.
On a modern platform updating the entire screen at 60 frames per second may be entirely practical, even in BASIC. This is one of David Williams's prizewinning games which is 100% BBC BASIC code (no assembler):
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Going back to the original question, the optimum way of achieving that doesn't involve a variable delay.
The fundamental 'timebase' in a any kind of video game is the display refresh rate (typically 50 or 60 frames per second depending on platform). To achieve smooth animation you should update the positions of moving objects at that rate - anything slower and the movement will not be smooth and anything faster will either be wasted effort - the resulting frame(s) will never be displayed - or you may get 'tearing' part way down the screen, depending on how the display refresh happens.
So in an ideal world you should have a fixed update rate, synchronised with the display refresh rate,
My comment was a general one, not specifically related to the BBC Micro. I don't know precisely how one synchronises with display refresh on that machine (on an Archimedes etc. one can use WAIT, in BBC BASIC for SDL 2.0 one can use *REFRESH) but it must be possible because there are programs like Elite that rely on it.
Coming from a TV background (the same applies in computer graphics and film) I just wanted to emphasise that in any animation the update rate should be kept constant and variable velocity achieved by changing the distance moved in that time, not by moving a fixed distance and changing the update rate by using a variable delay.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.