idflyfish Posted July 8, 2011 Share Posted July 8, 2011 Hello, I have been writing little programs to become more familiar with extended basic. The following program draws a checker board on the screen and then uses a sprite to jump from each black square in a loop. I needed to determine if a column was an even or an odd column but I couldn't find a modulus function or operator so a used the code in lines 121 and 125 as a work around. Is there a better way to determine if a number is odd or even using extended basic? 100 CALL CLEAR 120 FOR R=1 TO 20 121 X=R/2 125 IF INT(X) = X THEN S=2 ELSE S=1 130 FOR C=S TO 24 STEP 2 135 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 140 CALL HCHAR(R,C,91) 150 NEXT C 160 NEXT R 220 FOR R=1 TO 20 221 X=R/2 225 IF INT(X) = X THEN S=2 ELSE S=1 230 FOR C=S TO 24 STEP 2 235 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 240 CALL SPRITE(#1,91,4,R*8-7,C*8-7) 250 NEXT C 260 NEXT R 270 GOTO 220 Also, feel free to leave any comments or pointers on how I could better implement this program in extended basic. Thanks! Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 8, 2011 Share Posted July 8, 2011 (edited) Bit twiddling is so much better Edited July 8, 2011 by sometimes99er Quote Link to comment Share on other sites More sharing options...
matthew180 Posted July 8, 2011 Share Posted July 8, 2011 In XB, if you are treating your numbers as integers, you can also use bit-twiddling to isolate the LSb (least significant bit) in the number. The LSb will always be 0 for even numbers and 1 for odd numbers. Test for even: if (num AND 1) = 0 then print "even" Test for odd: if (num AND 1) = 1 then print "odd" 100 FOR I=1 TO 10 110 PRINT I;"IS "; 120 IF (I AND 1)=1 THEN PRINT "ODD" ELSE PRINT "EVEN" 130 NEXT I 1 Quote Link to comment Share on other sites More sharing options...
idflyfish Posted July 8, 2011 Author Share Posted July 8, 2011 (edited) In XB, if you are treating your numbers as integers, you can also use bit-twiddling to isolate the LSb (least significant bit) in the number. The LSb will always be 0 for even numbers and 1 for odd numbers. Test for even: if (num AND 1) = 0 then print "even" Test for odd: if (num AND 1) = 1 then print "odd" 100 FOR I=1 TO 10 110 PRINT I;"IS "; 120 IF (I AND 1)=1 THEN PRINT "ODD" ELSE PRINT "EVEN" 130 NEXT I Oh...I had know idea you could AND the binary value from within XB! That is pretty handy. Thanks for your input. Edited July 8, 2011 by idflyfish Quote Link to comment Share on other sites More sharing options...
unhuman Posted July 8, 2011 Share Posted July 8, 2011 IIRC the Miller's Graphics book on Sprite Programming (or maybe it was Night Mission) has a really good section on optimizing XB (with tricks like this) Quote Link to comment Share on other sites More sharing options...
idflyfish Posted July 9, 2011 Author Share Posted July 9, 2011 IIRC the Miller's Graphics book on Sprite Programming (or maybe it was Night Mission) has a really good section on optimizing XB (with tricks like this) Excellent...ill have a look..thanks Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 9, 2011 Share Posted July 9, 2011 (edited) Should do much the same as yours - and a lot faster. 100 CALL CLEAR::CALL CHAR(91,RPT$("F",16)):$=RPT$("[ ",12) 110 FOR R=1 TO 20::DISPLAY AT(R,2-(R AND 1))$::NEXT R 120 CALL SPRITE(#1,91,4,1,17) 130 FOR R=1 TO 20::FOR C=1 TO 12 140 CALL LOCATE(#1,R*8-7,C*16+9-8*(R AND 1)) 150 NEXT C::NEXT R::GOTO 130 Edited July 9, 2011 by sometimes99er Quote Link to comment Share on other sites More sharing options...
idflyfish Posted July 9, 2011 Author Share Posted July 9, 2011 Should do much the same as yours - and a lot faster. 100 CALL CLEAR::CALL CHAR(91,RPT$("F",16)):$=RPT$("[ ",12) 110 FOR R=1 TO 20::DISPLAY AT(R,2-(R AND 1))$::NEXT R 120 CALL SPRITE(#1,91,4,1,17) 130 FOR R=1 TO 20::FOR C=1 TO 12 140 CALL LOCATE(#1,R*8-7,C*16+9-8*(R AND 1)) 150 NEXT C::NEXT R::GOTO 130 Heck ya it is...shorter too This will give me something to chew on...thanks for the input Quote Link to comment Share on other sites More sharing options...
+RXB Posted July 10, 2011 Share Posted July 10, 2011 (edited) If you make a storage table of where the location of the black squares are you could use CALL MOTION on the SPRITE and a CALL COINC. The SPRITE movement would be smooth not jumpy, unless that is intended. Edited July 10, 2011 by RXB Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 11, 2011 Share Posted July 11, 2011 If you make a storage table of where the location of the black squares are you could use CALL MOTION on the SPRITE and a CALL COINC. The SPRITE movement would be smooth not jumpy, unless that is intended. That sounds interesting. How do you suggest we make the storage table ? Quote Link to comment Share on other sites More sharing options...
+RXB Posted July 11, 2011 Share Posted July 11, 2011 Try this and see what you think. 100 CALL CLEAR 110 RA=8192 120 FOR R=1 TO 20 130 X=R/2 140 IF INT(X)=X THEN S=2 ELSE S=1 150 FOR C=S TO 24 STEP 2 160 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 170 CALL HCHAR(R,C,91) 180 NEXT C 190 NEXT R 200 FOR R=1 TO 20 210 X=R/2 220 IF INT(X)=X THEN S=2 ELSE S=1 230 FOR C=S TO 24 STEP 2 240 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 250 CALL SPRITE(#1,91,4,R*8-7,C*8-7) 260 CALL LOAD(RA,R*8-7,C*8-7) :: RA=RA+2 270 NEXT C 280 NEXT R 290 FOR RA=8670 TO 8192 STEP-2 300 CALL PEEK(RA,R,C) 310 CALL SPRITE(#1,91,4,R,C) 320 NEXT RA 330 FOR RA=8192 TO 8670 STEP 24 340 CALL PEEK(RA,R,C) 350 CALL SPRITE(#1,91,4,R,C) 360 NEXT RA 370 FOR RA=8192 TO 8670 STEP 2 380 CALL PEEK(RA,R,C) 390 CALL SPRITE(#1,91,4,R,C) 400 NEXT RA 410 GOTO 290 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 11, 2011 Share Posted July 11, 2011 Try this and see what you think. 100 CALL CLEAR 110 RA=8192 120 FOR R=1 TO 20 130 X=R/2 140 IF INT(X)=X THEN S=2 ELSE S=1 150 FOR C=S TO 24 STEP 2 160 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 170 CALL HCHAR(R,C,91) 180 NEXT C 190 NEXT R 200 FOR R=1 TO 20 210 X=R/2 220 IF INT(X)=X THEN S=2 ELSE S=1 230 FOR C=S TO 24 STEP 2 240 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 250 CALL SPRITE(#1,91,4,R*8-7,C*8-7) 260 CALL LOAD(RA,R*8-7,C*8-7) :: RA=RA+2 270 NEXT C 280 NEXT R 290 FOR RA=8670 TO 8192 STEP-2 300 CALL PEEK(RA,R,C) 310 CALL SPRITE(#1,91,4,R,C) 320 NEXT RA 330 FOR RA=8192 TO 8670 STEP 24 340 CALL PEEK(RA,R,C) 350 CALL SPRITE(#1,91,4,R,C) 360 NEXT RA 370 FOR RA=8192 TO 8670 STEP 2 380 CALL PEEK(RA,R,C) 390 CALL SPRITE(#1,91,4,R,C) 400 NEXT RA 410 GOTO 290 Well, I get a * SYNTAX ERROR IN 260 I guess you're trying to implement the "storage table" using LOAD and PEEK ? I don't know how complete your example is, but didn't you suggest the use of CALL MOTION and CALL COINC ? Quote Link to comment Share on other sites More sharing options...
+RXB Posted July 11, 2011 Share Posted July 11, 2011 (edited) The CALL LOAD and CALL PEEK use the lower 8K of the 32K. So I guess you do not have 32K? Bare bones a TI like that uses only 16K VDP memory so all program line table, variables, and the program are all crammed that slower memory VDP. Programs running from VDP run much slower then from RAM in the 32K. Here is the problem: Row and Column storage is 968 values at 2 bytes each is 1936 bytes plus tokens for each value means 2904 bytes just to store the tables. Now to access those values in memory you need an array of RA(22,22) but each access will make a copy in memory to work with this slows the program down as you are running from VDP, why RAM is better. Ok instead of your CALL SPRITE(#1,96,4,R,C) you could do CALL SPRITE(#1,96,4,R,C,0,62) :: CALL MOTION(#1,-62,62) :: CALL MOTION(#1,0,62) :: CALL MOTION(#1,62,62) :: C=C+1 :: CALL SPRITE(#1,96,4,R,C) From normal XB almost everything sucks, that is why I wrote RXB. By adding a comma in GMOTION from above is CALL SPRITE(#1,96,4,R,C,0,62) :: CALL MOTION(#1,-62,62,#1,0,62,#1,62,62) :: C=C+1 :: CALL SPRINT(#1,96,4,R,C) (Much less memory used and runs faster as the :: really slows XB down the more you have, even slower is line numbers, the less the better and faster the program runs.) A solution in RXB is CALL SPRITE(#1,96,4,R,C,0,62,#2,32,R+1,C) :: CALL GMOTION(#1,X,Y) FOR X=-62 TO 62 :: CALL MOTION(#1,X,Y) :: CALL DISTANCE(#1,#2,D) :: IF D<8 THEN C=C+1 :: CALL SPRITE(#1,96,4,R,C) NEXT X I am working on a upgrade of RXB so can not spend a lot on time on this, but was just making a suggestion. If you are using no 32K your approach avenues are very limited. Lack of memory means lack of tools to attack the problem. Edited July 11, 2011 by RXB Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted July 11, 2011 Share Posted July 11, 2011 Try this and see what you think. 100 CALL CLEAR 110 RA=8192 120 FOR R=1 TO 20 130 X=R/2 140 IF INT(X)=X THEN S=2 ELSE S=1 150 FOR C=S TO 24 STEP 2 160 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 170 CALL HCHAR(R,C,91) 180 NEXT C 190 NEXT R 200 FOR R=1 TO 20 210 X=R/2 220 IF INT(X)=X THEN S=2 ELSE S=1 230 FOR C=S TO 24 STEP 2 240 CALL CHAR(91,"FFFFFFFFFFFFFFFF") 250 CALL SPRITE(#1,91,4,R*8-7,C*8-7) 260 CALL LOAD(RA,R*8-7,C*8-7) :: RA=RA+2 270 NEXT C 280 NEXT R 290 FOR RA=8670 TO 8192 STEP-2 300 CALL PEEK(RA,R,C) 310 CALL SPRITE(#1,91,4,R,C) 320 NEXT RA 330 FOR RA=8192 TO 8670 STEP 24 340 CALL PEEK(RA,R,C) 350 CALL SPRITE(#1,91,4,R,C) 360 NEXT RA 370 FOR RA=8192 TO 8670 STEP 2 380 CALL PEEK(RA,R,C) 390 CALL SPRITE(#1,91,4,R,C) 400 NEXT RA 410 GOTO 290 Well, I get a * SYNTAX ERROR IN 260 I guess you're trying to implement the "storage table" using LOAD and PEEK ? I don't know how complete your example is, but didn't you suggest the use of CALL MOTION and CALL COINC ? Unless I am mistaken, do you not need a "CALL INIT" prior to using a "CALL LOAD"? Quote Link to comment Share on other sites More sharing options...
+RXB Posted July 11, 2011 Share Posted July 11, 2011 Yes, sorry I use only RXB and it does not need a CALL INIT first, RXB checks to see if CALL INIT is called when CALL LOAD or CALL PEEK is used, if CALL INIT is not used yet it just ignores the CALL LOAD("DSK#.PROGRAM") but still works. This is a XB bug I fixed in RXB. In the last post I used DISTANCE, but you could just use COINC(#1,#2,4.CC) :: IF CC=-1 THEN C=C+1 :: CALL SPRITE(#1,96,4,R,C,0,62) I could post a working video of it later when I get time to do that, but it does work fine. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 12, 2011 Share Posted July 12, 2011 I'm sorry, but I think we use XB. Tried CALL INIT, but it still fails. Quote Link to comment Share on other sites More sharing options...
+RXB Posted July 12, 2011 Share Posted July 12, 2011 Ok you guys got me curious and I dropped off RXB writing to investigate this. Turns out this is a bug in XB. XB has a bad habit of making a SYNTAX errors out of code that has no syntax error and in the CALL LOAD this is one of them. I fixed this in RXB when I first moved the INIT code in RXB to a different GROM and fixed the bugs I found way back in RXB version 1001 (I do not have the source code earlier then 2001 now) You will notice in this video that it gets to the sixth column of working fine when it crashes. If a real syntax error existed then it should have crashed the first time it ran the code, not the sixth time as XB does not re-write itself while running. The original code I posted and said "Try this:" is the same except I added 90 CALL INIT to make the Normal XB program run correctly. (RXB does not require this, that is another bug) Anyway enjoy the show.... Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 13, 2011 Share Posted July 13, 2011 Talking about "call motion" and smooth sprite movement, here's a little something ... 100 CALL CLEAR::CALL CHAR(91,RPT$("F",16)):$=RPT$("[ ",12) 110 FOR R=1 TO 20::DISPLAY AT(R,2-(R AND 1))$::NEXT R 120 R1=1::C1=17::CALL SPRITE(#1,91,13,R1,C1) 130 R2=INT(RND*20)::C2=INT(RND*12)*16+17+(R2 AND 1)*8::R2=R2*8+1 140 CALL SPRITE(#2,91,7,R2,C2)::CALL MOTION(#1,(R2-R1)/8,(C2-C1)/8) 150 CALL POSITION(#1,R,C)::IF ABS(R-R2)>2 OR ABS(C-C2)>2 THEN 150 160 CALL MOTION(#1,0,0)::CALL LOCATE(#1,R2,C2)::R1=R2::C1=C2::GOTO 130 Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 15, 2011 Share Posted July 15, 2011 (edited) Just for kicks, I thought you might be interested to see the code to produce a checker board in TF : CHECKER 1 GMODE \ select 32 column mode 0 \ seed for display/dont display 19 FOR \ 20 rows (starts from 0) 23 FOR \ 24 columns (starts from 0) 1 XOR \ toggle the seed (1-->0 / 0-->1) DUP IF J I 42 1 HCHAR THEN \ display if seed >0 NEXT \ next column 1 XOR \ toggle the seed again NEXT \ next row DROP \ drop the seed ; Or, horizontally, in the more traditional Forth style: : CHECKER 1 GMODE 0 19 FOR 23 FOR 1 XOR DUP IF J I 42 1 HCHAR THEN NEXT 1 XOR NEXT DROP ; Takes just under 1 second (including setting the graphics mode and clearing the screen, which is done by GMODE), which is quite slow I suppose, but I wanted to use the same technique as the original poster. For speed, you'd want to use a similar approach to Sometimes (Sometimes is the master coder ): : 1LINE ." * * * * * * * * * *" CR ; : CHECKER 1 GMODE 0 19 FOR DUP IF SPACE THEN 1LINE 1 XOR NEXT DROP ; Flies! About a quarter of a second, again, that includes setting the VDP mode, and doing a screen clear, before it even begins to run your program Just thought i'd share. Sorry to hijack the thread http://www.youtube.com/watch?v=ftiFADkaDh0 Edited July 15, 2011 by Willsy 2 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.