Jump to content
IGNORED

A better CALL COINC (For XB compiler?)


Bones-69

Recommended Posts

From the XB Handbook in regards to the CALL COINC command;

Format
CALL COINC( #sprite-number, #sprite-number, tolerance, numeric-variable )
CALL COINC( #sprite-number, dot-row, dot-column, tolerance, numeric-variable )
CALL COINC( ALL, numeric-variable )
If the keyword ALL is given, sprites are coincident only if one or more of the dots which make them up occupy the same position on the screen. If two sprites or a sprite and a location are given, then tolerance must be specified, and two sprites are coincident if their upper left hand corners are within the value specified by tolerance. A sprite and a location are coincident if the upper left hand corner of the sprite and the position specified by dot-row and dot-column are within the value specified by tolerance. These coincidents are reported even if there is no apparent overlap of the sprites or the sprite and the position.
I created the following little program to get a better visual. Use the arrow keys to move the blue sprite onto/around the red sprite. Note when the two sprites are properly aligned that there is no coincidence under the ALL keyword (due to there being no actual dot overlap). BTW- The white background is not a sprite - only two sprites are used.
100 CALL CLEAR :: CALL SCREEN(2)::FOR I=1 TO 12::CALL COLOR(I,15,2)::NEXT I::CALL MAGNIFY(3)::CALL HCHAR(18,15,125,2)::CALL HCHAR(19,15,125,2)
110 CALL CHAR(124,"E0E0E0E0FFFFFFFFFFFFFFFFFFFFFFFF07070707878787878787CFCFCFFFFFFF",128,"1F1F1F1F000000000000000000000000F8F8F8F8787878787878303030000000")
120 Y=118 :: X=113 :: CALL SPRITE(#2,124,7,137,113,#1,128,5,Y,X)::A$="CALL COINC(#1,#2,"::B$(0)="YES"::B$(1)="NO"
130 CALL KEY(0,A,B)::IF A<8 OR A>11 THEN 130
140 ON A-7 GOTO 150,160,170,180
150 X=X-1::GOTO 190
160 X=X+1::GOTO 190
170 Y=Y+1::GOTO 190
180 Y=Y-1
190 CALL LOCATE(#1,Y,X)
200 FOR I=0 TO 12::CALL COINC(#1,#2,I,A)::DISPLAY AT(I+1,1):A$&STR$(I)&","&B$(A+1)&")"::NEXT I
210 CALL COINC(ALL,A)::DISPLAY AT(I+1,1):A$&"ALL,"&B$(A+1)&")"
220 GOTO 130
It would be a wonderful thing to be able to specify particular sprites (say #1 & #5) and have the function behave as it currently does when the keyword ALL is specified. ie- Be able to check a true coincidence between sprites *only* when two dots occupy the same screen position, rather than the scatter-gun approach of using the upper left hand corner plus a specified tolerance.
Does anyone have any ideas on how this might be achieved in XB? I imagine the processing might be too much for a regular XB program, but I doubt it would overwhelm an XB compiled program. I am basically trying to work out a method to detect a dot-to-dot coincidence without being forced to use the ALL Keyword (the use of multicoloured sprites make the ALL command mostly impractical).
Any ideas?
Full XB Reference;

COINC subprogram
Format
CALL COINC( #sprite-number, #sprite-number, tolerance, numeric-variable )
CALL COINC( #sprite-number, dot-row, dot-column, tolerance, numeric-variable )
CALL COINC( ALL, numeric-variable )
Description
The COINC subprogram detects a coincidence between a sprite and another sprite or a position on the screen. The value returned in numeric-variable is -1 if there is a coincidence and 0 if there is no coincidence.
If the keyword ALL is given, the coincidence of any two sprites is reported. If two sprites are identified by #sprite-number, their coincidence is reported. If #sprite-number and a location are identified, their coincidence is reported.
If the keyword ALL is given, sprites are coincident only if one or more of the dots which make them up occupy the same position on the screen. If two sprites or a sprite and a location are given, then tolerance must be specified, and two sprites are coincident if their upper left hand corners are within the value specified by tolerance. A sprite and a location are coincident if the upper left hand corner of the sprite and the position specified by dot-row and dot-column are within the value specified by tolerance. These coincidents are reported even if there is no apparent overlap of the sprites or the sprite and the position.
Dot-row and dot-column are numbered consecutively starting with 1 in the upper left hand corner of the screen. Thus the dot-row can be from 1 to 192 and the dot-column can be from 1 to 256, (Actually the dot-row can go up to 256, but the positions from 193 through 256 are off the bottom of the screen.) If any part of the sprite occupies the position given, then there is a coincidence.
Whether or not a coincidence is detected depends on several variables. If the sprites are moving very quickly, COINC may not be able to detect their coincidence. Also, COINC checks for a coincidence only when it is called, so a program may miss a coincidence that occurs when the program is executing some other statement.

 


 

 

post-26079-0-61344300-1547177082_thumb.jpg

Link to comment
Share on other sites

Honestly this is a more of a hardware problem of design of Sprite location detection using top left number 1 pixel of the 8x8 grid of a character.

 

Now is RXB I have new routines for dealing with joystick and sprite collisions that does help with joystick with sprite control.

 

 

 

What I have done is combined the commands

 

CALL JOYSTICK :: CALL MOTION or CALL LOCATE and IF KEY=FIRE THEN line-number

 

into a single GPL XB command and the speed increase is very noticable.

 

Working on release of this new version of RXB 2019

Edited by RXB
  • Like 1
Link to comment
Share on other sites

It would be a wonderful thing to be able to specify particular sprites (say #1 & #5) and have the function behave as it currently does when the keyword ALL is specified. ie- Be able to check a true coincidence between sprites *only* when two dots occupy the same screen position, rather than the scatter-gun approach of using the upper left hand corner plus a specified tolerance.

 

Does anyone have any ideas on how this might be achieved in XB? I imagine the processing might be too much for a regular XB program, but I doubt it would overwhelm an XB compiled program. I am basically trying to work out a method to detect a dot-to-dot coincidence without being forced to use the ALL Keyword (the use of multicoloured sprites make the ALL command mostly impractical).

 

Any ideas?

 

The ALL command must rely on a hardware register in the VDP (Video Display Processor). Technically I suppose XB reads and clears this bit of information from the VDP once every frame-update (on the ISR). So, as you've mentioned, any sprite overlaying any other sprite with one or more pixels will set this bit. And maybe a collision is held by XB (for more than one frame) until it is read using the COINC. On the other hand, when you use "tolerance", I think the value returned is calculated on the spot / fly.

 

With Assembly you can try and detect on which raster-lines pixel collisions occur. I don't think this will be implemented in XB256.

 

If you want to go with ALL, then you can cleverly arrange your sprites and paths so that only one collision can occur. Otherwise, if you can limit the number and types of collisions possible, then some pixel-points can be tested using ordinary calculations, but that takes processing power and won't be bulletproof.

 

Let's take Space Invaders as an example, and let's assume it's all sprites. ALL will work perfectly, but we're soon having a hard time finding which hit what. Let's forget about shields. And then let's change the invader droppings to background graphics. And let's ensure that the invaders never overlap. And let's assume that you only got one missile going up at a time (it could be guided), well, any collision using ALL must be at the missile's position. More than one missile at a time is probably not impossible - as long as they don't overlap (with a reasonable gap). Other games may be simplified like this one way or another.

 

 

  • Like 3
Link to comment
Share on other sites

Using software to test if two pixels overlap is really too time consuming even in assembly. I think the best approach is to use ALL first to test if any pixels overlap, and if so use tolerance to detect the involved sprites. If more than two sprites are close together you might end up detecting the wrong sprite, but that is usually acceptable. As Sometimes wrote it depends on how the sprites are organized. If two sprites always overlap, for instance, the ALL check is useless.

 

Edit: If a F18A library for XB is ever developed the GPU could be used to provide a pixel accurate COINC function between one or more sprites.

Edited by Asmusr
  • Like 3
Link to comment
Share on other sites

Thinking about doing sprite bits COINC in assembly. This is a good fit for the CZC, COC, or SOCB instructions.

It might be too cycle intensive to test all sprites, so pick the ones to test.

It can also be effective at testing sprites against background chars.


Bitwise Sprite COINC


This code demonstrates testing for overlap between two 8x8 sprite patterns in CPU RAM.

Assume you did coord testing and their 8x8 boundaries overlap.

Sprite #2 is asssumed to be down and to the right of sprite #1.

Other situations are left for later. 16x16 sprites are left for later.

If you have multicolor (2 sprites together) it is probably best to create 1 combined dummy char pattern to test against.

It will be an advantage to operate on everything in CPU RAM (keep SATB in CPU RAM, write the whole SATB to VDP on each "tick".)




Here is a picture of an 8x8 ball hitting an 8x8 ship:




R1-> 1111 R0 ^
111111 <--> |
11111111 | R3
11111111 v
R2->1111111*2 * = collision
1111111*2
11111122
1111 22
22
222222
22222222
22222222


PAT DATA >3C7E,>FFFF,>FFFF,>7E3C
DATA >1818,>1818,>187E,>FFFF


...
LI R0,4 x separation. needed in R0 for SLA
LI R1,PAT sprite#1 pattern address
LI R2,PAT+8 sprite#2 pattern address
LI R3,4 y separation
BL @HT
JNE GOTHIT
...
...


HT
A R3,R1
LI R4,8 #rows to test
S R3,R4
CLR R5 test/shift register
CLR R6 test register
HL
MOVB *R1+,R5
SLA R5,0 shift #1 pat left by R0 places
MOVB *R2+,R6
CZC R6,R5 if the 1s in #2 are all 0s in #1
JNE HX
DEC R4
JNE HL
HX
RT return status: EQ if no hit, NE if hit.

  • Like 2
Link to comment
Share on other sites

 

Thinking about doing sprite bits COINC in assembly. This is a good fit for the CZC, COC, or SOCB instructions.
It might be too cycle intensive to test all sprites, so pick the ones to test.
It can also be effective at testing sprites against background chars.
Bitwise Sprite COINC
This code demonstrates testing for overlap between two 8x8 sprite patterns in CPU RAM.
Assume you did coord testing and their 8x8 boundaries overlap.
Sprite #2 is asssumed to be down and to the right of sprite #1.
Other situations are left for later. 16x16 sprites are left for later.
If you have multicolor (2 sprites together) it is probably best to create 1 combined dummy char pattern to test against.
It will be an advantage to operate on everything in CPU RAM (keep SATB in CPU RAM, write the whole SATB to VDP on each "tick".)
Here is a picture of an 8x8 ball hitting an 8x8 ship:




R1->  1111   R0   ^
     111111 <-->  |
    11111111      | R3
    11111111      v
R2->1111111*2  * = collision
    1111111*2
     11111122
      1111 22
           22
         222222
        22222222
        22222222


PAT DATA >3C7E,>FFFF,>FFFF,>7E3C
    DATA >1818,>1818,>187E,>FFFF


    ...
 LI   R0,4      x separation. needed in R0 for SLA
 LI   R1,PAT    sprite#1 pattern address
 LI   R2,PAT+8  sprite#2 pattern address
 LI   R3,4      y separation
 BL   @HT
 JNE  GOTHIT
 ...
 ... 


HT
 A    R3,R1
 LI   R4,8      #rows to test
 S    R3,R4     
 CLR  R5        test/shift register
 CLR  R6        test register
HL
 MOVB *R1+,R5
 SLA  R5,0     shift #1 pat left by R0 places
 MOVB *R2+,R6  
 CZC  R6,R5    if the 1s in #2 are all 0s in #1
 JNE  HX
 DEC  R4
 JNE  HL
HX
 RT            return status: EQ if no hit, NE if hit.

 

 

This is why I wanted help on XB ROMs and adding routines to RXB ROMs like moving CALL COINC from GPL to Assembly.

Same for some other routines while remaining backwards compatible mostly.

 

Some may be way faster like my new CALL JOYMOTION or JOYLOCATE then XB but easy to adjust in XB programs.

When I combine CALL JOYST & CALL KEY & CALL MOTION & IF KEY=Fire button THEN line-number

 

CALL JOYMOTION(keyunit,X,Y,#sprite,Rindex,Cindex,KEY) GOTO line-number

 

That is a hell of a faster routine all in GPL then XB normal:

 

CALL JOYST(1,X,Y) :: CALL KEY(1,S,S) :: CALL MOTION(#1,X*-4,Y*-4) :: IF S THEN line-number

 

As you can see everytime you come back to XB has to look up the name of the routine and start processing it in the line vs RXB all done from a single GPL command.

Now if I can use assembly this would really fly.

 

Edited by RXB
  • Like 1
Link to comment
Share on other sites

Thanks for the feedback and links guys - all very helpful stuff. I hadn't anticipated it would be this hard. For XB to not support dot-coincing between specified sprites I probably should have realised there was more to it.... I tried a few ideas on paper most of which were complicated, impractical, and took an absurd amount of steps and processing - but one idea seemed to have some potential, especially if it was XB compiled;

 

It would be effortless using CALL POSITION to determine if the 64 dots of any MAGNIFY 3 sprite were in a situation where they might overlap with a second sprite. This could be determined from the the Upper Left Hand Corner position of each sprite. A minim overlap of one dot creates a potential 46 x 46 grid with the reference sprite being centered at position 16,16 (46 is determined by 16+15+15).

 

If the two sprites fall within the 46 x 46 grid, the relative position of one sprite to the other sprite could be stored as a string. If the known positions for a coincidence were determined in advance, a "master string" could then act as a reference point for all such Y/X coordinates. Determining a dot-to-dot coincidence would then just be a case of searching one string within the other.

 

So I think the steps would be;

-Initial check to see if a coincidence is possible (if two sprites fall within the 46 x 46 grid), and if so;

-Store relative coordinates of second sprite as a string

-Search "master" string for the second sprite coordinate string using the POS command

-If the returned variable in the POS statement is not equal to zero, a coincidence between two sprites has taken place.

 

This idea seems like it might work although some effort in advance would be required to create the character "Coincidence Strings". Not sure if the concept is clear so I have Illustrated the idea in my attachment.

 

*For the illustrated example I have not "stringified" the center of the cross, this would probably be necessary - especially to dot-check sprites that were in motion.

post-26079-0-38729100-1547516207_thumb.jpg

  • Like 2
Link to comment
Share on other sites

Quick little test & seems to work OK! Is detecting a dot/dot coincidence between two specific sprites, without using CALL COINC.

 

Use arrow keys;

 

100 CALL CLEAR :: CALL SCREEN(2):: FOR I=1 TO 12 :: CALL COLOR(I,15,2):: NEXT I :: CALL MAGNIFY(3):: DISPLAY AT(24,1):"COINC:"
110 S$="!-30!-31!-21!-12!-13!03!13!12!21!31!30!3-1!2-1!1-2!1-3!0-3!-1-3!-1-2!-2-1!-3-1!20!02!0-2!-20!10!00!-10!01!0-1"::Y=100 :: X=100
120 CALL CHAR(124,"0000000000010107070101000000000000000000008080E0E0808",128,"0000000000000001010000000000000000000000000000808")
130 CALL SPRITE(#2,124,7,80,X,#1,128,5,Y,X,#3,124,14,50,50,0,10,#4,124,14,50,50,0,-5,#5,124,14,50,50,0,5)
140 CALL KEY(0,A,B):: IF A<8 OR A>11 THEN 140
150 ON A-7 GOTO 160,170,180,190
160 X=X-1 :: GOTO 200
170 X=X+1 :: GOTO 200
180 Y=Y+1 :: GOTO 200
190 Y=Y-1
200 CALL LOCATE(#1,Y,X):: CALL POSITION(#2,A,B):: A=A-Y :: B=B-X :: A$="!"&STR$(A)&STR$(B):: C=POS(S$,A$,1):: IF C=0 THEN A$="NO" ELSE A$="YES"
210 DISPLAY AT(24,7):A$ :: GOTO 140
  • Like 3
Link to comment
Share on other sites

Interesting. Looking good. Unfortunately it will miss more than what's mentioned. And I'm thinking these are then rather simple sprites.

gallery_11132_2341_220.png

FarmerPotato might have something that can be used in XB256. Like when ALL has detected a collision (could be many sprites overlapping), now then take a look at only sprite #3 and #10 and see if they are really overlapping.

With some games there may even be the case where sprites seems to pass through each other, but are not overlapping in any individual frames. This can happen even with sprites only moving at 1 pixel per frame. Well, that's another story.

gallery_11132_2341_884.gif


  • Like 1
Link to comment
Share on other sites

This is a HARDWARE PROBLEM not a software problem.

 

Sprites use upper left pixel 1 and then add a tolerance that SUCKS it goes in full circle around that 1st pixel the width of the tolerance.

 

So you get hits from pixel 1 of a sprite that looks like it missed as they are not touching, but the Tolerance says they are?

 

If you go to this video at minute 8:00 you will see RXB CALL COINC in RXB vs normal XB CALL COINC comparison. I improved it in RXB.

 

Also keep going and I show the imporvement on RXB CALL DISTANCE in RXB vs normals XB CALL DISTANCE. Again I improved it in RXB.

 

 

 

 

This was in RXB 2001 since then I have added more commands.

Edited by RXB
Link to comment
Share on other sites

Interesting. Looking good. Unfortunately it will miss more than what's mentioned. And I'm thinking these are then rather simple sprites.

 

gallery_11132_2341_220.png

 

FarmerPotato might have something that can be used in XB256. Like when ALL has detected a collision (could be many sprites overlapping), now then take a look at only sprite #3 and #10 and see if they are really overlapping.

 

With some games there may even be the case where sprites seems to pass through each other, but are not overlapping in any individual frames. This can happen even with sprites only moving at 1 pixel per frame. Well, that's another story.

 

gallery_11132_2341_884.gif

 

 

 

I had overlooked the diagonal possibility during my original thought process but ended up correcting it in the code (post #9). So in that example a coinc is detected in all positions that it should

 

I have the situation of not being able to use ALL to drill down at almost any point., I have a design where sprites hide behind other sprites to give the effect of "popping up". I guess there is always a workaround, but I am trying very much to avoid it....

Link to comment
Share on other sites

Quick little test & seems to work OK! Is detecting a dot/dot coincidence between two specific sprites, without using CALL COINC.

 

Use arrow keys;

 

100 CALL CLEAR :: CALL SCREEN(2):: FOR I=1 TO 12 :: CALL COLOR(I,15,2):: NEXT I :: CALL MAGNIFY(3):: DISPLAY AT(24,1):"COINC:"
110 S$="!-30!-31!-21!-12!-13!03!13!12!21!31!30!3-1!2-1!1-2!1-3!0-3!-1-3!-1-2!-2-1!-3-1!20!02!0-2!-20!10!00!-10!01!0-1"::Y=100 :: X=100
120 CALL CHAR(124,"0000000000010107070101000000000000000000008080E0E0808",128,"0000000000000001010000000000000000000000000000808")
130 CALL SPRITE(#2,124,7,80,X,#1,128,5,Y,X,#3,124,14,50,50,0,10,#4,124,14,50,50,0,-5,#5,124,14,50,50,0,5)
140 CALL KEY(0,A,B):: IF A<8 OR A>11 THEN 140
150 ON A-7 GOTO 160,170,180,190
160 X=X-1 :: GOTO 200
170 X=X+1 :: GOTO 200
180 Y=Y+1 :: GOTO 200
190 Y=Y-1
200 CALL LOCATE(#1,Y,X):: CALL POSITION(#2,A,B):: A=A-Y :: B=B-X :: A$="!"&STR$(A)&STR$(B):: C=POS(S$,A$,1):: IF C=0 THEN A$="NO" ELSE A$="YES"
210 DISPLAY AT(24,7):A$ :: GOTO 140

 

I had overlooked the diagonal possibility during my original thought process but ended up correcting it in the code (post #9). So in that example a coinc is detected in all positions that it should

It still says no.

 

I have the situation of not being able to use ALL to drill down at almost any point., I have a design where sprites hide behind other sprites to give the effect of "popping up". I guess there is always a workaround, but I am trying very much to avoid it....

There's probably more to it, but here goes. Make the sprites you hide behind part of the background characters, and have the sprites that "pop up", have different patterns, so they appear to "pop up" from behind something.

Link to comment
Share on other sites

You are absolutely right. In fixing the inside of the cross I forgot about the 4 "quadrants". It's an easy fix, just need to add 4 more coordinates to the string.

 

I will get around to clarifying the challenge with an image in the next day or two. Thanks Sometimes.

  • Like 1
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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...