Subject: Calimari Carl and SPECTRA2

From: Owen Brand <[email-masked]>
Date: Tue, 7 Sep 2010 12:25:11 -0400

Well, SPECTRA2 is on it's way... I have been working on my 3rd XB  
game, "Calimari Carl," and (with a bit of nudging) I will be  
converting it to assembly using Filip's new game library conventions.   
I am curious to know some practical hints to detect collisions in  
assembly.  I am aware of the status bit--- but what I'm particularly  
interested in is how to efficiently check for WHICH SPRITEs have  
collided and how to differentiate between important collisions and  
consequential ones.  I've viewed the source code for Pitfall (which is  
brilliantly done) and I am currently reading through a few sections of  
Bruce's Art of Assembly to help me out.  I'm curious if someone can  
give me a practical example and explanation of how this works most  
efficiently on our machine.  Thanks in advance.  BTW, Filip, if you're  
reading this--- I would love to get a copy of the documentation for  
the original SPECTRA since 2 isn't quite complete yet.  It might give  
me a head start.  :)

Owen Brand

        **webmaster**
http://www.Opry99er.com

---

From: "Tursi" <[email-masked]>
Date: Tue, 7 Sep 2010 09:52:57 -0700

> brilliantly done) and I am currently reading through a few sections of

There's no magic involved... all you can do is compare the distances between 
the sprites you are interested in, and you just ignore the ones you are not. 
(Technically, there is more you can do, but pixel-based sprite collision in 
software is more than I'm willing to get into right now ;) ).

The collision status bit is not normally used in assembly games for 
precisely the reason you list here - you have no idea WHICH sprites are 
colliding.

I don't know what Filip's library offers (although - collision testing is a 
good function to offer!) The simplest way is to compare each coordinate, and 
if it's close enough, declare a collision. If you are using double-size 
sprites, they are 16 pixels wide, so some number less than 16 usually works 
well (depends how much overlap you want to allow). Then you simply subtract 
the values, absolute value them (to make it positive no matter which way the 
subtraction went), and compare. For instance, something like this off the 
cuff...

* Sprite 1 X in R0, Sprite 1 Y in R1, Sprite 2 X in R2, Sprite 2 Y in R3
* returns R0 as 0 if no collision, or >FFFF if there is. Destroys R1-R3
TSTCOL
 CLR R0   * assume no collision
 S R0,R2  * get the difference in Y
 ABS R2   * make sure it's positive
 CI R1,12  *allow about 4 pixels overlap (16-4 = 12)
 JGT NOHIT * if greater, then we can't be colliding
 S R1,R3  * get the difference in X
 ABS R3   * make sure it's positive
 CI R3,12 * same overlap - doesn't have to be though if your characters 
aren't square ;)
 JGT NOHIT * if it's greater, we can't be colliding
 SETO R0 * both tests passed, so we ARE colliding, set the return
NOHIT
 B *R11   * return to caller

This simple routine won't work for the top of the screen, though - the top 
line is actually row 255, and the second line is row 0. There are some 
simple tricks for that - like incrementing Y by one (make sure you use it as 
a byte then), but for this example, just remember that.

Then you simply have to compare every combination of sprites you are 
interested in colliding.

---

From: Owen Brand <[email-masked]>
Date: Tue, 7 Sep 2010 16:48:04 -0400

Thank you for this excellent explanation!  My question would be,  
should that distance detection take place inside the main loop, or  
should I check the status bit to determine if a collision has happened  
and THEN branch to a subroutine which determines distances and such?   
I hope that made sense, but if it didn't, I'll give you an example of  
what I'm talking about.

In XB, I like to keep the game loop as small and tight as possible---  
and GOSUB out of it to act on COINCs and scoring and such.  Should I  
do something similar in assembly, or would the speed lag be small  
enough to warrant doing everything inside the loop?  I know how fast  
assembly can be, and I seriously doubt losing a few cycles for  
distance checks would hurt me.  It may even help keep game speed even  
and fluid... Am I thinking clearly?

Owen Brand

        **webmaster**
http://www.Opry99er.com

---

From: tursi <[email-masked]>
Date: Tue, 7 Sep 2010 14:51:51 -0700 (PDT)

You can use the status bit to decide whether to call the collision 
function -- doing so will generally improve the pixel accuracy, but most 
people don't bother. (It won't trigger then unless two sprite pixels 
actually touch, but, it could be any two sprite pixels, for instance, two 
sharks touching each other would trigger the test, so nothing is 
guaranteed).

Of course, it depends too on how many sprites you want to check. if you 
need to check all 32 sprites against all other 32 sprites, that's 1024 
comparisons, and is probably too much to do in one loop.

But what you do in that case is spread the work out. You can do this in 
XB, too, but the slow speed of execution means you might only get one shot 
at it, and can't afford to spread the work out. In assembly you are in 
full control, though.

What I mean by that, of course, is let's use a more probable example, 
where Carl needs to be tested against, say, 16 sharks.

You write up your main loop with the full test, that is, every frame you 
check Carl against all 16 sharks. But you find out that the game runs a 
little slower than you would like.

The likelihood is that nothing is moving so fast that it won't be touching 
for a few frames (especially if you are moving it rather than using the 
console interrupt routine, but even then this is likely). So, you can 
divide up the workload. Say, in frame '1' you check Carl against sharks 
0-7, then in frame 2 you check Carl against sharks 8-15, and alternate 
back and forth. This concept can be expanded farther as long as you need 
more performance, and the characters remain touching long enough. To 
expect 16-pixel sprites to remain touching for 3-4 frames at 60 frames per 
second is pretty reasonable.

My example is a little simplified, but the point is that you have the time 
in assembly to divide the work up between frames in the game loop. This 
helps keep the apparent performance and responsiveness high!

> Thank you for this excellent explanation!  My question would be, should that distance
> detection take place inside the main loop, or should I check the status bit to determine
> if a collision has happened and THEN branch to a subroutine which determines distances and
> such?  I hope that made sense, but if it didn't, I'll give you an example of what I'm
> talking about.

---

From: Owen Brand <[email-masked]>
Date: Tue, 7 Sep 2010 18:24:41 -0400

Again, Tursi--- a brilliant and most helpful reply.  I often use  
multiple redundant collision checks in a loop to ensure I don't miss a  
coincidence, but this idea of alternating the checks for multiple  
instances every other cycle is very interesting.  In XB, I tried this  
with Honeycomb Rapture to allow for detection between killer bees and  
the PC and then, alternately,detection between falling DDT SPRITEs.   
This resulted in universal missed coincidences--- when I decided to  
try JUST killer bee coincidences, it worked better, but there were  
still many missed coincidnces.  I then decided to have all enemy  
SPRITEs move parallel to one another, and that allowed me to use CALL  
COINC(ALL) which is super fast.  I also tried to CALL PEEK into the  
status bit, but the speed difference wasn't that noticeable.  This  
helped, but I still missed coincidences.  I then added the second CALL  
COINC(ALL) into the loop after the joystick call and it worked to  
perfection.

I said all this because it's an example of how slow XB is.  You can  
skip checks for collision on an entire loop cycle and it's still more  
accurate than XB.  Wow.

Owen Brand

        **webmaster**
http://www.Opry99er.com

On Sep 7, 2010, at 5:51 PM, tursi <[email-masked]> wrote:

> should that distance

---

From: tursi <[email-masked]>
Date: Tue, 7 Sep 2010 15:35:07 -0700 (PDT)

> I said all this because it's an example of how slow XB is.  You can skip checks for
> collision on an entire loop cycle and it's still more accurate than XB.  Wow.

Yeah.. XB can actually move the sprites numerous times on a single line of 
code. But even more important than that, in assembly you are also in 
control of WHEN the sprites move -- even if you are using the console 
interrupt routine, because YOU decide when to allow it to run (with LIMI 
2) or when to call your own sprite move function. Sprites CAN NOT move 
between lines of assembly unless you tell them to, and that is what really 
gives you the most power.

Of course, this also means that responsibility for smooth movement falls 
on your shoulders. Using the console interrupt routine, this just means 
that your main loop has to be fast enough to call LIMI 2/LIMI 0 60 times 
per second -- and this is pretty easy to accomplish. When your loop runs 
too long, the sprites will slow down rather than you missing collisions. 
This is a bad thing, though, because unless it's carefully controlled, 
you'll have some loops fast enough and some too slow, and the speed of the 
game will speed up and slow down. This is where dividing the work out and 
building the game to a fixed frame rate (with 60 fps being easiest) comes 
in handy. :)

---

From: Owen Brand <[email-masked]>
Date: Tue, 7 Sep 2010 19:12:35 -0400

Sounds like fun.  I am really looking forward to the challenge.  Right  
now I am finishing the XB version and I will then start the assembly  
version.  If you'd like to see progress and try the demo, visit us at  
Atariage and see the thread. :)

Owen Brand

        **webmaster**
http://www.Opry99er.com

---

From: Owen Brand <[email-masked]>
Date: Tue, 7 Sep 2010 23:51:17 -0400

Documentation for Filips brilliant SPECTRA1 assembly library.  I'm  
reading through this now and it's great. 2 is to be more streamlined  
and "scratchpad-efficient.". Can't wait til it's ready!

Owen Brand

        **webmaster**
http://www.Opry99er.com