Punch wrote:
I spent the day trying to code something better, and since I dropped the "multiple boxes per metasprite" requirement, I did just as tokumaru said. No more indirection for what I'm doing, at least. It's buggy and not working properly but I'll see what I can do tomorrow.
Compare the old collision table with the new one:
Old:
https://gitlab.com/aleff/BrixBattle/blo ... lision.txtNew:
https://gitlab.com/aleff/BrixBattle/blo ... lision.txtWay simpler huh? This is the new collision code:
https://gitlab.com/aleff/BrixBattle/blo ... lision.asm . Less stupider.
tomaitheous wrote:
psycopathicteen wrote:
I noticed that most of his code is spent looking up "collision box data" and setting everything up to do the collision detection.
Oh wow, you're right.
Punch: That looks waaaaay over kill. What are you trying to do? (Something out of the norm?)
Why are you doing position translations of all corners? ;Obj2.x1 + Obj2.Posx
What is OBJ_COLLISION, x and what is OBJ_METASPRITE, x ? Are these projectiles? Destructible player objects? Enemy projectiles? Enemy objects?
It is now that I think about it. The translations are done because the center of the object is arbitrary, it's not always the left corner of the sprite. See
https://gitlab.com/aleff/BrixBattle/blo ... r/anim.txt for the format.
OBJ_COLLISION is a byte for registering which object from the list is currently colliding with the object. I might think of something better later but that will do for now.
OBJ_METASPRITE is the metasprite id for the object. One metasprite is paired with one or more bounding boxes. (now just one box per metasprite)
The objects can be anything, from projectiles to enemies to players to static sprites to anything really. They all have the same attributes for now since I have lots of free RAM.
Is there any particular reason why you need center points?
As far as collision design goes, I think it should be tailored specifically to your game. If enemies collision don't affect one another, or enemy bullets don't affect other enemies - then don't check for them. In other words, have multiple collision routines. For instance, I have one that checks player projectiles only with enemies and their bullets. It doesn't check enemy projectiles against other enemy projectiles or other enemies (unless they are supposed to be destructible, but then I have them as spawns "enemies" rather than projectiles), and I don't check collision with other friendly projectiles or the player (or other player objects). In other words, I don't check for friendly fire collisions.
I also tend to avoid center point positions for objects, because
if you have to cycle through all those objects more than once, then you have the overhead of translating them into a box
every time. But then again, that depends on the design of your game. You might have no projectiles and only the player to check collision against (no attacks, only dodging).
Anyway, the idea is to remove redundancy in the collision routines. And like others have said, best to avoid using indirection of you can.
Also, since this is 65x related - I'm gonna post this here (I'm surprised sik didn't post this)
Quote:
Sik, on another forum, brought up a method he uses for his game logic on his work (Genesis). He uses a center coord system. So you only have Ax, Ay, and width/height. The compare logic is as follows; if [Ax-Bx]<= ((AxWidth+BxWidth)/2) then check Y. Although, he doesn't use the absolute value of Ax-Bx. If the value is negative, he uses the negative of (AxW+BxW)/2 as the compare. Now, that takes care of checking both Xn values (normally two compares) in a single compare, so you cut out one potential process right there. But now there's the added overhead of (AxW+BxW)/2, which can be optimize to (AxW+BxW)>>1 but it's still has additional overhead on every compare. Here's where he optimizes his engine; (AxW+BxW)/2 is not calculated on a per object box compare basis but rather it's calculated once and at assemble time. Now you're probably thinking that means he can only have one bounding size. He gets around this be having a set of box collision sizes. Usually, in a game of the PCE era, collision doesn't happen between every object. Or rather, only certain objects only interact with other objects. So there isn't a general need to check every object against every other object. And so you can write a few different collision routines to compare two hardcoded box sizes against each other. The other advantage is that you don't have to add movement offset to 4 coords, but only two coords (for when the object moves onscreen).
Though on the 65x, 4 corner compares should be relatively fast..
A simple 4 corner 8bit value check system:
Code:
CollisionAB:
lda ObjAx2,y
cmp ObjBx1,x
bcc .nohit
lda ObjBx2,y
cmp ObjAx1,x
bcc .nohit
lda ObjAy2,y
cmp ObjBy1,x
bcc .nohit
lda ObjBy2,y
cmp ObjAy1,x
bcc .nohit
;hit
jsr DoCollisionAB
.nohit
And obviously that can be optimized further if the routine is comparing one object to the whole list of other object (using a preload of 4 zp regs before the loop). Have lots of different arrays with all sorts of flags and attributes, but make sure they all have the same index value for the main object. Though that might be easier said than done if you're limited to the stock 2k ram of the NES.
The last thing I would check is; does optimizing your collision routine slow down
other parts of object handling code? If so, is the trade off worth it? Maybe you're keeping track of objects that exist in a larger virtual map; everyone one of their positions would need to be evaluated and changed as you scroll about the camera window. If that's the case, and these objects stopping moving around (become inactive), outside of the camera view, it might be worth using a center point system on those - and then switch to corner offset positioning once active (moved to an active list). Dunno. But things like that weigh in on how you optimize your collision routine(s).