+atari2600land Posted January 6, 2019 Share Posted January 6, 2019 I know about on...goto and on...gosub, but I doubt they'd be of much help for what I'm trying to do here. What I want is a simpler way of making a coin twirl on the screen. Here's the code for what I have now: if cointwirltimer=120 then cointwirltimer=0 if cointwirltimer=0 then print at 29 color $2206, "\313" if cointwirltimer=10 then print at 29 color $2206, "\314" if cointwirltimer=20 then print at 29 color $2206, "\315" if cointwirltimer=30 then print at 29 color $2206, "\316" if cointwirltimer=40 then print at 29 color $2206, "\315" if cointwirltimer=50 then print at 29 color $2206, "\314" if cointwirltimer=60 then print at 29 color $2206, "\313" if cointwirltimer=70 then print at 29 color $2206, "\314" if cointwirltimer=80 then print at 29 color $2206, "\317" if cointwirltimer=90 then print at 29 color $2206, "\318" if cointwirltimer=100 then print at 29 color $2206, "\317" if cointwirltimer=110 then print at 29 color $2206, "\314" Looks ugly and long, doesn't it? Is there a way to simplify this? Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 The problem with that pattern of code is that every condition will be tested, every time. That is, if the cointwirltimer is 110, it'll perform all the tests above it until it encounters the last one that succeeds. Even if the cointwirltimer is 120 and it succeeds on the first test, it'll still do all the other tests and fail them. What you want is a way to say escape the conditionals as soon as a particular test succeeds, and ideally, you would want to test those conditions which are more likely to occur first, so as to improve the chances of skipping a bunch of useless tests. The "ON ... GOTO" or "ON ... GOSUB" statements achieve this but at a linear scale; that is, the values tested against an ordinal sequential set, starting from zero, then one, two, three, etc. You could induce this sort of statement to test your conditions by adjusting your cointwirltimer values to fit in that list. From what I see, the values are increments of 10, so if you divide the value by 10, you'll get a nice ordinal list, like this: ON (cointwirltimer / 10) GOSUB Do0, Do10, Do20, Do30, Do40, Do50, Do60, Do70, Do80, Do90, Do100, Do110, Do120 ' ... rest of your code ... Do0: Procedure print at 29 color $2206, "\313" End Do1: Procedure print at 29 color $2206, "\314" End ' ... Another, and perhaps cheaper, alternative is to use ELSIF. This follows the same pattern as you had, but with the added advantage that it will break out of the conditional tree as soon as it finds a match: if cointwirltimer=120 then cointwirltimer=0 elsif cointwirltimer=0 then print at 29 color $2206, "\313" elsif cointwirltimer=10 then print at 29 color $2206, "\314" elsif cointwirltimer=20 then print at 29 color $2206, "\315" elsif cointwirltimer=30 then print at 29 color $2206, "\316" elsif cointwirltimer=40 then print at 29 color $2206, "\315" elsif cointwirltimer=50 then print at 29 color $2206, "\314" elsif cointwirltimer=60 then print at 29 color $2206, "\313" elsif cointwirltimer=70 then print at 29 color $2206, "\314" elsif cointwirltimer=80 then print at 29 color $2206, "\317" elsif cointwirltimer=90 then print at 29 color $2206, "\318" elsif cointwirltimer=100 then print at 29 color $2206, "\317" else cointwirltimer=110 then print at 29 color $2206, "\314" end if It doesn't look any prettier than what you had, but it works a lot faster on every case except the worse one (when the cointwirltimer is 110). One more alternative is to compute the special output code from the cointwirltimer itself and just use a single PRINT statement to display it. However, this is not always possible since the output code may not be directly derived from the input timer, as is your case. In any case, if you had a means to compute the output code from the cointwirltimer, you could define that in a function and use it like this: DEF FN CoinOutput(timer) = {put your translation function here} PRINT AT 29 COLOR $2206, (GRAM + (CoinOutput(cointwirltimer) * ) There aren't many other options, except by getting really clever with your code, like using a "DO ... LOOP" and things like that, which may obscure the logic itself and obfuscate your code. -dZ. 2 Quote Link to comment Share on other sites More sharing options...
crunchyfrog555 Posted January 6, 2019 Share Posted January 6, 2019 Sorry, im not familiar with intellivision programming, but as a general rule, couldnt you just use variables with a counter? Something like: print at 29 color $2206, <"\" 313+(cointwirltimer/10)> I know thats not correct syntax, but you should get the point. If you can just do a calculation as straightforward as that, its just one line. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 Sorry, im not familiar with intellivision programming, but as a general rule, couldnt you just use variables with a counter? Something like: print at 29 color $2206, <"\" 313+(cointwirltimer/10)> I know thats not correct syntax, but you should get the point. If you can just do a calculation as straightforward as that, its just one line. That's actually my third suggestion above, but as I noticed when I was typing it, the translation between the timer and the output code is not linear. If it can be made linear, then that's what I suggest, although it would be more like: PRINT AT 29 COLOR $2260, GRAM + ((cointwirltimer / 10) * That formula computes a source GRAM card by shifting the code three bits to the left to position it in its proper field within the background table word, and sets the GRAM bit on. To make it simpler, you then wrap it in a user-defined function and use it as a macro. -dZ. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 (edited) And yet another alternative which takes that last one into consideration is to use a translation table. You create a table with the ordered set of codes, and convert the cointwirltimer into an index into that table, i.e., by dividing it by 10. Then look it up in the PRINT statement: ' Macro to convert a value into a formatted BACKTAB character code DEF FN BGCODE(value) = (GRAM + (value * ) ' Test for the special case first IF (cointwirltimer = 120) THEN cointwirltimer = 0 ELSE ' Print the character code PRINT AT 29 COLOR $2206, ScreenCodes(cointwirltimer / 10) END IF ' ... ' We're using the user-defined macro BGCODE to convert the number ' into an actual BACKTAB character code. ScreenCodes: DATA BGCODE(313), BGCODE(314), BGCODE(315), BGCODE(316) DATA BGCODE(315), BGCODE(314), BGCODE(313), BGCODE(314) DATA BGCODE(317), BGCODE(318), BGCODE(317), BGCODE(314) Note that you still need to test for when the timer is 120, since that has a special case that does not print anything. -dZ. Edited January 6, 2019 by DZ-Jay 1 Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 The last one doesn't work for me. It prints for me a constant "<". Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 The last one doesn't work for me. It prints for me a constant "<". My bad. Remove the "GRAM +" from the macro. The values "313" and above already have it. All they need is to be shifted. So it'll be: DEF FN BGCODE(value) = (value * Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 Now it's giving me a constant equal sign. Where do I put the macro? Inside the loop? Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 Now it's giving me a constant equal sign. Where do I put the macro? Inside the loop? Outside your code, at the very top. Or else, remove it completely, and make all the data statements the same value you where printing before, but multiplied by 8:. For example: DATA 2504 ' \313 * 8 Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 I want to use this code since it reduces the size of the code considerably, but I can't seem to get it working correctly. It gives me different constant results depending on where I put the ScreenCodes data. In this code I'm attaching, it's at the very end and it gives me a black square. cranberry3.bas Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 I want to use this code since it reduces the size of the code considerably, but I can't seem to get it working correctly. It gives me different constant results depending on where I put the ScreenCodes data. In this code I'm attaching, it's at the very end and it gives me a black square. I'll take a look. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 OK, first thing I see is that your timer does not increment by 10, which I should have known, so it will try to print even when it's not a power of 10. Then I see that the codes were not composed correctly. Attached is the fixed version. Here are all the fixes: 1. First, we compute the full BACKTAB character code from the GRAM card index. DEF FN BGCODE(value) = GRAM + (value * 2. Then we need to only print when the counter is a multiple of 10, so we add a conditional: IF (cointwirltimer = 120) THEN cointwirltimer = 0 ELSEIF (cointwirltimer % 10 = 0) THEN 3. Then we read the code from the table using the timer computation as an index: ' Print the character code PRINT AT 29, ScreenCodes(cointwirltimer / 10) + CS_YELLOW END IF 4. And finally, the data table includes the GRAM card index computed by the macro for each card in the animation. ScreenCodes: DATA BGCODE(57), BGCODE(58), BGCODE(59), BGCODE(60) DATA BGCODE(59), BGCODE(58), BGCODE(57), BGCODE(58) DATA BGCODE(61), BGCODE(62), BGCODE(61), BGCODE(58) I've tested it and it looks good, although the animation (as you had it) repeats a frame at the end, which seems weird. -dZ. cranberry3.bas 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 What I am not happy about is that we are dividing the timer twice: the Modulo (%) operator divides by 10 and keeps the remainder, discarding the output; and the division in the PRINT statement does the opposite, keeping the output and discarding the remainder. Ideally, we would divide only once, but there doesn't seem to be a direct way in IntyBASIC to get the remainder and output of the division at once with one operation. We could do this in Assembly Language easily, but that would disqualify your program from the next contest. -dZ. Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 I compiled the .bas file you provided and there's now a blank space with no coin or anything. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 I compiled the .bas file you provided and there's now a blank space with no coin or anything. I compiled it without problems here, and it animates the spinning coin. ?? Which version of the compiler are you using? How are you compiling it? avi_0001.avi.zip Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 I got it working. I guess I was using an outdated version of jzINTV. But I don't know why the coin pauses while spinning for a frame. Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 Fixed it so the coin doesn't pause while spinning. cranberry5.bas Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 (edited) I got it working. I guess I was using an outdated version of jzINTV. But I don't know why the coin pauses while spinning for a frame. It's easy: after the last frame in the sequence, it advances 10 iterations later to reach 120, but doesn't print a different card, so it skips another 10 iterations before it starts again. That's my fault, for I mistranslated your IF/THEN block. In essence, it skips one frame. You can change it like this: ' Only animate on every 10th frame IF (cointwirltimer % 10 = 0) THEN ' If we're past the end of the sequence, restart it IF (cointwirltimer >= 120) THEN cointwirltimer = 0 ' Print the character code PRINT AT 29, ScreenCodes(cointwirltimer / 10) + CS_YELLOW END IF et voilà! Edited January 6, 2019 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 Your fix is a lot better than mine. Thank you so much for helping me with this. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 Your fix is a lot better than mine. Thank you so much for helping me with this. No worries. I've been helping someone else with IntyBASIC, which has made me learn how it works, and so I can provide a bit more targeted assistance than before. The coin animation is pretty cool. What will the game do? -dZ. Quote Link to comment Share on other sites More sharing options...
+atari2600land Posted January 6, 2019 Author Share Posted January 6, 2019 I'm going to try to make an adventure game with this. I'd like to have coins come up for the cranberry to collect and use in various situations to purchase stuff. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 Neat-o! Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted January 6, 2019 Share Posted January 6, 2019 (edited) I realize I'm late to the party, but since I'm also learning to code, I tried to do it as an exercise without looking at other answers. For what is worth, here is what I came up with.coin.bas Edited January 6, 2019 by cmadruga Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 6, 2019 Share Posted January 6, 2019 I realize I'm late to the party, but since I'm also learning to code, I tried to do it as an exercise without looking at other answers. For what is worth, here is what I came up with.coin.bas That's very close to the solutioned offered. The main difference is that I used a macro and constants to avoid magic numbers, but it is the same approach. dZ. Sent from my iPad using Tapatalk Pro Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted January 6, 2019 Share Posted January 6, 2019 That's very close to the solutioned offered. The main difference is that I used a macro and constants to avoid magic numbers, but it is the same approach. dZ. Sent from my iPad using Tapatalk Pro Close to YOUR answer? Wow, I will take that as my gold star for the day 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.