Jump to content

Recommended Posts

170 DIM E$(13)
180 CALL CHARSET :: CALL CLEAR :: CALL SCREEN(2)
190 !MAN
200 L$="00233123213F0303033F20202020E0000080808080F888889888808080FC0404"
210 L2$="0003010B09090F010101011F10101070008080808080F8888880808080FC0404"
220 R$="000303037F43434303030202023E303000880888F880808080F8080808080E0E"
230 R2$="00030303070F172747070707FCFCC0C0008000808080FC000000E0E060607878"
280 C$="000302030F0B1B03030302020202060600808080E0A0B080808080808080C0C0"
290 C2$="000302030F0B1B03030302020202060600808080E0A0B080808080808080C0C0"
300 !ENEMY ANIMATIONS
305 D$="00003C3C3C3C0000"!DOT
310 M$="00000000000F10204980A0829041221C0000000000C020A02020204080000000"!METEOR
320 A$="08040F1B3F2F280600000000000000002040E0B0F8E828C00000000000000000"!ALIEN
330 B$="0000001818000000"!ALIENS BULLET
340 P$="804020100F080B0A0A0B080F1020408001020408F010D05050D010F008040201"!PULSAR
350 R$=""!SUNRAY
360 !ALL CHAR(124,D$,128,M$,136,A$,140,B$,72,P$,76,R$)!ENEMIES
365 CALL CHAR(128,M$,136,A$,140,B$,72,P$,76,R$)!ENEMIESTEST
380 CALL CHAR(64,RPT$("F",16))!GREY FLOOR
390 CALL HCHAR(21,1,64,128)!GREY FLOOR
400 !CLR CENTER LEFT RIGHT
410 !CENTER 96 LEFT 100 RIGHT 116 CENTER B 112 LEFT B 104 RIGHT B 120
420 CALL CHAR(96,C$,100,L$,104,L2$)!MAN 96-120 CHARSETS 9-12
440 CALL CHAR(112,C2$,116,R$,120,R2$)
450 !DRAW EARTH 645-760,970-1010
460 CALL COLOR(2,6,1,3,6,1,4,3,6,5,15,2)
465 RESTORE 500
470 FOR I=6 TO 14 :: CALL COLOR(I,16,2) :: NEXT I
480 FOR I=0 TO 13 :: READ E$(I) :: CALL CHAR(40+I,E$(I)) :: NEXT I
490 FOR I=0 TO 7 :: READ E$(I) :: CALL CHAR(I+56,E$(I)) :: NEXT I
500 DATA 0000000000000F7F,000000000000F0FE,01030F1F3F7FFFFF
510 DATA 80C0F0F8FCFEFFFF,0001010103030303,FFFFFFFFFFFFFFFF
520 DATA 00808080C0C0C0C0,0303030301010100,C0C0C0C080808000
530 DATA FF7F3F3F1F0F0703,FFFEFCFCF8F0E0C0,7F0F000000000000
540 DATA FEF0000000000000,0800667C18666810
550 DATA E0F07F7F7FFFFFFF,0818F8F8F0F8F0F0,7F7F7F3D1C0E0201
560 DATA F0F0908800180000,03070F0F0F070703,F0FFFFFEFCFCF8F0
570 DATA 0303010101010101,E0C0C0C080808000
580 DISPLAY AT(2,24):CHR$(40)&CHR$(41) :: DISPLAY AT(3,23):CHR$(42)&CHR$(56)&CHR$(57)&CHR$(43)
590 DISPLAY AT(4,22):CHR$(44)&CHR$(45)&CHR$(58)&CHR$(59)&CHR$(45)&CHR$(46)
600 DISPLAY AT(5,22):CHR$(47)&CHR$(45)&CHR$(60)&CHR$(61)&CHR$(45)&CHR$(48)
610 DISPLAY AT(6,23):CHR$(49)&CHR$(62)&CHR$(63)&CHR$(50)
620 DISPLAY AT(7,24):CHR$(51)&CHR$(52)
630 !MAN SPRITE
633 DR=130 :: DC=1 :: MEN=3 :: MDR=193 :: MDC=1
634 CALL SPRITE(#1,96,16,DR,DC) :: CALL MAGNIFY(4)
635 !ALL SPRITE(#2,124,6,193,1)!DOT
636 CALL SPRITE(#3,128,16,MDR,MDC)!METEOR 1,169,20,-20
637 CALL SPRITE(#4,136,4,193,1)!ALIEN 1,1,0,10
638 CALL SPRITE(#5,140,4,193,1)!BULLET AR+10,AC,20,0
639 CALL SPRITE(#6,72,6,193,1)!PULSAR 18,1,0,20
640 !ALL SPRITE(#7,76,?,193,1)!RAY
642 MDR=1 :: MDC=169
643 CALL LOCATE(#3,MDR,MDC) :: CALL MOTION(#3,10,-10)
645 !MAIN LOOP
650 CALL METEOR(MDR,MDC)
660 ANIM=ABS(ANIM-4) :: CALL JOYST(1,X,Y) :: DC=DC+X*4 :: CALL LOCATE(#1,(DR AND 255)+1,(DC AND 255)+1)
661 CALL COINC(#1,#2,10,HIT) :: IF HIT THEN CALL SOUND(300,-1,10) :: CALL DELSPRITE(#1)
663 CALL KEY(1,K,S) :: IF K=18 THEN CALL JUMP(DR,DC,MEN)
664 IF X<>0 THEN CALL PATTERN(#1,ANIM+X*2+108) :: FACE=SGN(X+4) :: GOTO 650
665 CALL PATTERN(#1,FACE*16+96) :: GOTO 650
770 !ENDOFMAINLOOP
775 !ENDING ROUTINE
780 CALL CLEAR :: CALL DELSPRITE(ALL) :: CALL CHARPAT :: CALL SCREEN(5)
785 CALL SOUND(300,-2,10) :: CALL SAY("PLAY AGAIN")
790 DISPLAY AT(12,16):"PLAY AGAIN? PRESS Y OR N"
800 ACCEPT AT(14,16)BEEPVALIDATE("YN"):Z$ :: IF Z$="Y" THEN 160 ELSE END
804 END
805 !///SUBPROGRAMS///
810 SUB JUMP(DR,DC,MEN)
840 SDR=DR :: A=1
844 DISPLAY AT(16,12):"DC= ";DC
850 CALL KEY(1,K,S) :: IF K=18 THEN DR=DR-4 :: DC=DC+(A*PI/45)*5 :: IF DC>240 THEN DC=1
853 !F MEN=0 THEN 775
855 CALL COINC(#1,#2,10,CO) :: IF CO THEN CALL SOUND(150,-2,4) :: CALL DELSPRITE(#1) :: MEN=MEN-1 :: GOTO 630
860 !DISPLAY AT(23,1):A;" ";SIN(A*PI/45)
870 IF DR<8 THEN 890
880 CALL LOCATE(#1,DR,DC) :: IF S<0 THEN A=A+1 :: GOTO 850
890 IF DR<SDR THEN DR=DR+4 :: DC=DC+1 :: CALL LOCATE(#1,DR,DC) :: IF DC>240 THEN DC=17
895 CALL COINC(#1,#2,10,CO) :: IF CO THEN CALL SOUND(150,-2,4) :: CALL DELSPRITE(#1) :: MEN=MEN-1 :: GOTO 630
900 IF DR<SDR THEN 890
910 SUBEND
980 SUB DOT
1000 CALL COLOR(#2,12)
1030 DX=INT(RND*256)+1 :: DY=INT(RND*192)+1!DOT ROWS?
1050 CALL COINC(#1,#2,10,C)!TOUCH DOT
1060 COUNT=1
1065 IF C=0 THEN 1030
1067 IF C THEN CALL SOUND(500,110,15) :: CALL DELSPRITE(#2)
1069 !GOTO 1075 HOLD ON SCREEN
1070 SUBEND
1071 SUB METEOR(DR,DC)
1072 DR=1 :: DC=169
1075 CALL COINC(#1,#3,10,CO) :: IF CO THEN CALL SOUND(300,-2,10) :: CALL DELSPRITE(#1)
1076 CALL POSITION(#3,DR,DC) :: IF DR>130 THEN CALL DELSPRITE(#3)
1078 !HOWLONGSHOULDMETEORLAST?
1079 SUBEND
1081 SUB ALIEN
1082 AR,AC=1
1083 CALL LOCATE(#4,AR,AC) :: CALL MOTION(#4,0,10)!ALIEN
1084 CALL LOCATE(#5,AR+10,AC) :: CALL MOTION(#5,20,0)!BULLET
1086 !ALL SOUND(XX,XX,XX)!FILL IN
1087 CALL POSITION(#4,AR,AC)
1097 CALL COINC(#4,#1,10,A) :: CALL COINC(#5,#1,10,B)!B=BULLET
1098 IF A OR B THEN CALL SOUND(XX,XX,XX) :: CALL DELSPRITE(#1,#5)
1099 SUBEND
1100 SUB PULSAR
1120 CALL LOCATE(#6,18,1) :: CALL MOTION(#6,0,20)
1135 P1=6 :: P2=7
1165 FOR I=1 TO 100
1170 CALL COLOR(#6,P1) :: CALL COLOR(#6,P2)
1172 CALL SOUND(100,-1,10,200,5)
1180 CALL COINC(#1,#6,10,C) :: IF C THEN CALL SOUND(300,-1,10) :: CALL DELSPRITE(#1)
1185 NEXT I
1200 SUBEND

 

Basically the gameplay idea is to collect several dots one at a time until you reach a certain number and the game ends. While running around the screen after a dot, one enemy would always be on screen pestering you. After a short time, a new enemy would appear. A series of enemies would just repeat over and over, one enemy at a time. Kind of like the Spider on Centipede keeps popping up again every few minutes after you killed it. Except there would be a gnat, and then an earwig, followed by another bug in this games' logic. Not actually bugs, just any "enemies" for the player.

 

The program doesn't work, and as you can tell this is my first game. Currently, you can move left or right and wrap around, do a buggy jump, and get some coincidences out of a meteor that disappears when it hits the ground. (Intended) The collision detection is a mess, and I'm not sure which of the several CALL COINCs are working and which ones aren't. I think the ones in the SUBPROGRAMS aren't. It seems like nothing I put in a subprogram works, and it gets confusing when it comes to what variables and values need to be passed from SUB to MAIN and what ones don't need to be passed. Not understanding Subprograms so far.

Share this post


Link to post
Share on other sites

I didn't mean for you to post all your code, just smaller working examples with maybe emphasis on one single problem. I know this may be difficult to do.

 

SUB, COINC and flow seems to confuse a little. I've already listed several issues, and one thing is, you're still not passing and using FACE in JUMP.

 

Another thing is, you shouldn't really leave a SUB with a GOTO (line (853,) 855 and 895). I guess it works, but you're leaving unresolved layers of subroutines. I think there's a limited to the number of subroutine levels.

 

If you want to jump out of a SUB, hence making it spaghetti (I do that myself, but it's dangerous practice), then use GOTO all around instead of SUB and SUBEND (you seem to have SUBEND end/goto the same place anyway). An alternative to SUB is GOSUB. With GOSUB all variables are available, no need to pass them. It's nice to be able to name subroutines.

 

Well, I think we should only fix one thing at a time. If you try and go back and fix several issues, there's a good chance of new issues popping up.

 

Sometimes when "trail and error" still produces errors, like the JUMP still can cause bad value in 880, where dc is then out of range for LOCATE, then instead of applying more and more IF statements to correct the flaws, you should consider a rewrite/redesign and maybe even do some math on paper. I know the latter may not be an option.

 

Why not try the pseudo code approach. Write pseudo and replace one thing at a time with real code. As you see, there is only one COINC between man and enemy/meteor.

 

Setup things (graphics, variables and screen)

 

Place man

Place enemy

Place dot

 

Loop start

Move enemy (has JOYST and KEY)

Move man

If collision with enemy go to Hit enemy

If collision with dot go to Hit dot

If enemy counter has run out go to Place enemy

If dot counter has run out go to Place dot

Loop repeat

 

Hit enemy

Do something

Update lives

If lives then go to Place man

End game

 

Hit dot

Do something

Update score

Go to Place dot

Edited by sometimes99er

Share this post


Link to post
Share on other sites

You can't use variables in GOTO or GOSUB, so names is out of the question. ON GOTO and ON GOSUB are however interesting and strong commands.

 

You can name all of the stuff with the sprites though - if that would clear up anything:

 

100 MAN=1::MANCHR=33::MANCOLOR=2::MANY,MANX=100
110 CALL SPRITE(#MAN,MANCHR,MANCOLOR,MANY,MANX)
120 GOTO 120

Edited by sometimes99er

Share this post


Link to post
Share on other sites

A question on CALL COINC. Does it matter if CALL COINC is called from the MAIN or called from a SUBPROGRAM? Is it better to have it in both main and sub like I do now, as you mentioned about Line 661, or is it overkill/unnecessary? I thought the more you call it, the more likely to catch a coincidence, but perhaps only one CALL COINC per subprogram is necessary? If I call all those subprograms from the game loop, won't it slow the game loop action down considerably? Is there a way to CALL the Subprograms outside of the main game loop?

Share this post


Link to post
Share on other sites

Does it matter if CALL COINC is called from the MAIN or called from a SUBPROGRAM?

 

Not really.

 

Subroutines are usually put into use when you want structure or are using the same piece of code, maybe with some slight modification, many times.

 

I believe subroutines as GOSUB have a slight overhead, as opposed to inline code, and SUB can have more overhead when passing variables (and I guess even more when by value).

 

If you later try and optimize to have things happen as close to real time as possible, then dumping the subroutines for inline code might be an option to consider.

 

I thought the more you call it, the more likely to catch a coincidence, but perhaps only one CALL COINC per subprogram is necessary?

 

If your main loop takes too long (that's including the subs), and you can't optimize any more, then having more COINCs might be a solution. It's a question about what you want and what you can achieve. Some of your COINCs are different anyway (as I recall, man versus enemy and man versus dot).

Share this post


Link to post
Share on other sites

As author of RXB I do have a unique perspective on how XB works. In RXB a routine called Garbage Collection is used much more often and this reduces the overhead problem of Variables a bit.

Whenever you see XB or Basic do that Pause and be unresponsive for a second that is the Garbage Collection routine that resides in the ROMs and is used to rearrange VDP memory for Stack and Variables.

How it works is it finds duplicate variables or temporary variables or strings or PABs (Peripheral Access Block) or used buffers then deletes these and repairs VDP.

 

Your problem with COINC is to use RXB and a single CALL COINC(#1,#2,10,TMP,#1,#4,10,TMP2) on one line in the main loop and then do the IF value THEN lines after.

 

The reason your program is so slow is that you are attempting to find a COINC bye sheer luck at the same time that it happens.

So a better approach is to do a scan for any COINC as often as you can and then look to see if you get a value and branch to that.

The reason for doing this way is you maximize the number of COINC and get less misses.

Share this post


Link to post
Share on other sites

As author of RXB I do have a unique perspective on how XB works ...

 

I remember when I discovered the pause, I thought something wrong with the darn computer.

 

Any idea about on average how often the garbage collector kicks in, and how long it takes, relatively, with TI Basic and XB with and without 32K ?

 

Does the 32K have any significant impact on, let's say a 10K average program/game - or does the XB handle the program very much the same when it resides in VDP versus in 24K ?

Share this post


Link to post
Share on other sites

I remember when I discovered the pause, I thought something wrong with the darn computer.

 

Any idea about on average how often the garbage collector kicks in, and how long it takes, relatively, with TI Basic and XB with and without 32K ?

 

Does the 32K have any significant impact on, let's say a 10K average program/game - or does the XB handle the program very much the same when it resides in VDP versus in 24K ?

 

COMPCT EQU >70 PREFORM A GARBAGE COLLECTION

 

This is the GPL one being used the most in XB:

<0411>			   ***********************************************************
<0412>			   * Search and clean up stack and symbol table to not allow
<0413>			   * garbage to accumulate
<0414>			   ***********************************************************
<0415> 767F BD,52,6E CLEAN  DST  @VSPTR,@FAC8	  Get a temporary stack pointer
<0416> 7682 C5,52,24 CLEAN1 DCH  @STVSPT,@FAC8	 While not end of stack
<0417> 7685 56,BE		   BR   G76BE
<0418> 7687 BC,58,E0	    ST   [email protected](@FAC8),@FAC14 Get stack ID byte
   768A 02,52
<0419> 768C A6,58,66	    SUB  >66,@FAC14	    Check the range
<0420> 768F C6,58,04	    CH   >04,@FAC14	    If string, numeric, >70, >72
<0421> 7692 56,98		   BR   G7698
<0422> 7694 0F,78		   XML  VPOP			  Throw it away (Must be on top
<0423> 7696 56,7F		   BR   CLEAN
<0424> 7698 8A,58    G7698  CASE @FAC14
<0425> 769A 56,A7		   BR   CLEANG		    GOSUB entry			    >6
<0426> 769C 56,AD		   BR   CLEANF		    FOR   entry			    >6
<0427> 769E 56,B7		   BR   CLEANU		    UDF   entry			    >6
<0428> 76A0 56,A4		   BR   CLEANE		    ERROR entry			    >6
<0429> 76A2 56,B1		   BR   CLEANS		    SUB   entry			    >6
<0430> 76A4 06,A0,14 CLEANE CALL SQUISH		    ERROR Entry - squish it out
<0431> 76A7 A7,52,00 CLEANG DSUB 8,@FAC8		   Go down 1 entry
   76AA 08
<0432> 76AB 56,82		   BR   CLEAN1		    Go on to next entry
<0433>			   * Jump always
<0434> 76AD A7,52,00 CLEANF DSUB 16,@FAC8		  Keep it around but get below
   76B0 10
<0435> 76B1 A7,52,00 CLEANS DSUB 16,@FAC8		  16 bytes further down
   76B4 10
<0436> 76B5 56,82		   BR   CLEAN1		    FOR or SUB entry
<0437>			   * Jump always
<0438> 76B7 87,4E    CLEANU DCLR @FAC4			 Cause delink to work right
<0439> 76B9 06,A0,10	    CALL DELINK		    Delink the symbol table entry
<0440> 76BC 56,A7		   BR   CLEANG
<0441> 76BE 00	   G76BE  RTN

 

In Basic it would be DATA >0038 Get String space and in XB it in ROMs. You could do a GPLLINK to GROM address >767F and it would do the CLEAN command.

And yea if you run programs from RAM you get less use of VDP. But the more variables and stack (GOSUB or CALLs) the more often it used CLEAN command.

The soulution would be a 64K VDP memory as it would hardly ever have to call the CLEAN routine.

At 16K and over 1/3rd already used for screen/buffers/files it gets called alot.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...