I think I should post the code for array add and remove functions.
Writing them was the only inconvenient thing about pointerarrays ever.
Once getting used to it, it is more like comfort programming than trickery programming - while heading for Aleste speed 
Pointerarrays can be made from your existing things.
From whatever scattered things you get a linear view to walk thru without checks.
An array of addresses - simple and powerful.
The array descriptor (called "struct Arr" in the code) :
16bit address of the array
16bit size of the array, the amount of things added
16bit capacity (max size) of the array
The size values are the amount of things, and as the array contains 16bit pointers, the array takes twice the space as the size values. Before using arradd/arrremove, in the descriptor set the address, set the size to 0, set the capacity.
Walking a pointerarray with z80 stackpointer, comfortable and fast:
DI
ld iy,0
add iy,sp
ld sp,(array) ;SP points to array
ld a,(array+2) ;the size word. only loading 8bit, max 256 things,
;while add remove functions work up to 64k.
ld b,a ;maybe add some check in case zero, nothing in the array
loop:
pop HL ;next thing gotten in 11 cycles
;now HL points to thing. do something.
djnz loop
ld sp,iy
EI
Add your things to the array. And whenever a thing dies, remove it from the array. Doing that you can walk an array free of holes.
Specialize at will. For example have an array "scrollable" where you add sprites that get moved by the scroller. Register the address of the Y of all sprites in question. Then, walking thru the "scrollable" pointerarray, you move the right sprites without hole checks and without ID checks.
Generally recommended is an object pool with slots of e.g. 32 byte size. And that pool is the place where you get the holes from allocation/deallocation.
The objects may look like this, e.g. some two sprites object:
ID, Y,X,P,C , Y2,X2,P2,C2, direction
registering e.g. the turtle that scrolls with the background:
register Y and Y2 in "RAMSAT" and "scrollables". all sprites of the turtle to be scrolled and dumped to SAT.
register Y in "enemy bounding boxes": only register one sprite of a colorsprite (maybe. depends on your patterns).
Knowing the base address of the pool and having ID bytes, you also can do things without pointerarrays. Pointerarrays easily co-exist, get added to existing projects.
In below code, _R1 and _R2 are RAM variables (I got _R0 to _R7 in my projects).
And "error" does enter a loop that toggles border color between H and L.
;hl: struct Arr , de:pointer to thing to add .globl arradd arradd: ld iy,0 add iy,sp ld sp,hl ;->struct pop hl ;array pop bc ;length add hl,bc add hl,bc ld (hl),e inc hl ld (hl),d inc bc push bc ;store back length pop bc pop hl ;capacity and a sbc hl,bc jr c,arradderr ld sp,iy ret arradderr: ld hl,0x0a08 jp error ;R1: struct Arr, R2: pointer to thing ;run with disabled interrupt arrremove: ld iy,0 add iy,sp ld sp,(_R1) pop hl ;array content pop bc ;array length ld a,b or c jr z,armnullexit ld sp,hl ld a,b ld b,c ld c,a inc b dec b jp z,armincskip inc c ;double jp nz . c is counter hi byte armincskip: ld de,(_R2) ld a,e arml: pop hl cp l jr z,armlofound armnotfound: djnz arml dec c jp nz,arml armnullexit: scf ;set carry flag if not found ld sp,iy ret armlofound: ld a,d cp h ld a,e jp nz,armnotfound ;move tail up 2 bytes push af ;2x dec sp, overwriting what is to be killed anyways. ld hl,0 add hl,sp ex de,hl ld hl,2 add hl,de inc b dec b jp z,armdecskip dec c ;bc back to normal armdecskip: ld a,b ld b,c ld c,a sla c rl b ;length x 2 : pointers ldir ;todo bc = 0 ? ;dec array.length ld sp,(_R1) pop hl pop bc dec bc push bc and a ;clear carry ld sp,iy ret

If I face problems i might take a look on it on future. Thanks for the code. 