Sprite collision detection or manually calculation sprite coordinates? (Development Foros MSX)MSX Resource Center MSXdev 2008 - MSX1 development bonanza!           
                       
English Nederlands Español Português Russian                  
 Noticias
   Página principal
  Almacén de noticias
  Temas de noticias

 Recursos
   Foros MSX
  Artículos
  Analisis
  Informe de ferias/RUs
  Álbum de fotos
  Ferias y encuentros
  Encuestas
  Enlaces
  Buscar

 Software
   Descargas
  Tienda Online

 MRC
   Quiénes somos
  Únete a nuestro equipo
  Donar
  Políticas
  Contacta con nosotros
  Enlázanos
  Estadísticas

 Buscar
 
  

  

 Login
 

Login

Contraseña




¿Aún no tienes una cuenta? ¡Conviértete en miembro del MSX Resource Center! ¡Únete a nosotros!.


 Estadísticas
 

Hay 86 invitados y 2 miembros en línea

Eres un usuario anónimo.
 

Foros MSX


Foros MSX

Development - Sprite collision detection or manually calculation sprite coordinates?

Ir a la página ( Página anterior 1 | 2 | 3 | 4 | 5 Siguiente página )
Autor

Sprite collision detection or manually calculation sprite coordinates?

ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 04 2005, 23:51   
@AuroraMSX

Ok, you can use multiple swapping to sort the list (e.g. bubblesort).
The cost of one swap is the same both if you use an array of
pointes or if you use chained lists.

Assume the usual SPRT structure

               struct 	SPRT
p_Y		db 	Y
p_X		dw 	X
p_DX		db 	DX
p_DY		db 	DY
p_attribute1 	dw	attribute1
p_attribute2 	dw	attribute2
etc.
etc.
                        ends	


and the usual list of pointers ordered with Y coordinate

Array_SPRT_pointers:

dw 	p_record_SPRT0
dw 	p_record_SPRT1
dw 	p_record_SPRT2
dw 	p_record_SPRT3
dw 	p_record_SPRT4
....
dw 	p_record_SPRT31



If YC is the data (s#6,s#5) and YN and DYN are the data of the generic enemy, we need to find the objects in the list that respect the condition

(YN+DYN>= YC >= YN)

As the list of pointers is ordered in ascending Y, they are all adjacent: do you see this point?

If we renounce the VDP we need to find the objects in the list that respect the condition

(YN+DYN>= Y0 >= YN or YN+DYN >= Y0+DY0 >= YN)

where Y0 and DY0 are data for the main sprite.


We try to sketch the loop for bin search in both cases in order to evaluate pros and contra.
Sorry for mixing C and sjasm notation.

Let’s start from the case of :

(YN+DYN>= YC >= YN)

p_head =	Array_SPRT_pointers
p_tail	  =	Array_SPRT_pointers + 32*2
p_mid	 =	(p_tail + p_head) /2


for ( ; ; )
  {
  if   *(*p_mid + SPRT. p_Y)  < YC  
    {
    p_tail  = p_mid
    p_mid = (p_tail + p_head) /2

    }
  else if 	*(*p_mid + SPRT. p_Y) + *(*p_mid + SPRT. p_DY)  > YC  
    {
    p_head = p_mid
    p_mid  = (p_tail + p_head) /2

    }
  else break
  }




As far as I understand the pointers

p_head and p_tail,

at the break should comprise all the
pointers in

Array_SPRT_pointers

to the records for which holds:

(YN+DYN>= YC >= YN)


What do you think ? Does it works?

AuroraMSX

msx master
Mensajes: 1231
Publicado: Agosto 05 2005, 09:53   
Quote:

What do you think ? Does it works?



Yup. No doubt about it
ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 05 2005, 13:09   
@Magoo
@GhostP
Have you seen the loop? Any suggestion or comments before going to ASM?

ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 05 2005, 15:47   
No answers. I go on.

Assume the usual SPRT structure



               struct 	SPRT
p_Y		db 	Y
p_X		dw 	X
p_DX		db 	DX
p_DY		db 	DY
p_attribute1 	dw	attribute1
p_attribute2 	dw	attribute2
etc.
etc.
                        ends	



and the usual list of pointers ordered with Y coordinate

Array_SPRT_pointers:

dw 	p_record_SPRT0
dw 	p_record_SPRT1
dw 	p_record_SPRT2
dw 	p_record_SPRT3
dw 	p_record_SPRT4
....
dw 	p_record_SPRT31



the C like code is

p_head =	Array_SPRT_pointers
p_tail	=	Array_SPRT_pointers + 32*2

for ( ; ; )  
{   p_mid  = (p_tail + p_head) /2      
     if   *(*p_mid + SPRT.p_Y) < YC      
        {    p_tail  = p_mid    }  
     else if 	*(*p_mid + SPRT.p_Y) + *(*p_mid + SPRT.p_DY) > YC      
        {    p_head = p_mid    }  
     else break  
}


The ASM equivalent is

ld     hl, array_SPRT_pointers
ld     de, array_SPRT_pointers + 32*2

loop:
push     hl        ;        p_head
push     de       ;        p_tail

sll     hl
sll     de
add   hl,de     ;        hl = p_mid
push  hl         ;        p_mid

ld     bc,(hl)     ;       bc = *p_mid
ld     hl,SPRT.p_Y
add  hl,bc       ;      hl = *p_mid + SPRT.p_Y
ld    a,(hl)       ;      a = *(*p_mid + SPRT.p_Y)
cp    YC
jr    nc,elseif

pop    de        ;       p_tail  = p_mid
pop    af         ;       drop previous p_tail
pop    hl         ;        p_head

jr    loop

elseif:

ld     bc, SPRT.p_DY-SPRT.p_Y
add   hl,bc      ;      hl = *p_mid + SPRT.p_DY
add   a,(hl)     ;      a = *(*p_mid + SPRT.p_Y) + *(*p_mid + SPRT.p_DY)
ld      b,a
ld      a,YC
cp     b
jr    nc,else

pop    hl         ;       p_head  = p_mid
pop    de        ;       p_tail
pop    af         ;       drop previous p_head

jr    loop

else: 

pop       af      ;       drop previous p_mid
pop       de     ;        p_tail
pop       hl      ;        p_haed




Any comment ???

In case not, the next step is to scan the list within HL and DE in order to find the sprites
such that

(XN+DNX >= XC > XN)

AuroraMSX

msx master
Mensajes: 1231
Publicado: Agosto 05 2005, 16:00   
Quote:

What do you think ? Does it works?



Actually, there's a small flaw in the algorithm.
Quote:

(YN+DYN>= YC >= YN)


That means, that YC is not a single value you can test against; you need to test agians the edges of the range (YN and YN+DYN). And I think you've got the comparisons mixed up:
while(1) {
  if((*p_mid)->p_Y > YN+DYN) {
    p_tail = p_mid;
    p_mid = (p_head + p_tail) / 2;
  } else if((*p_mid)->p_Y + (*p_mid)->p_DY  < YN) {
    p_head = p_mid;
    p_mid = (p_head + p_tail) / 2;
  } else {
    break;
  }
}




ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 05 2005, 16:10   
YC is the coordinate of the collision from VDP (s#6,s#5)
XC is the coordinate of the collision from VDP (s#4,s#3)

I started depicting that two option are possible:
1) using VDP's XC,YC
2) avoiding it

where in this case we need to find all the sprites witch respect

(YN+DYN>= Y0 >= YN or YN+DYN >= Y0+DY0 >= YN)

Let me two minutes for studing you loop, I need to check.

ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 05 2005, 16:56   
Let's try your solution: I assume you mean YN, YN+DYN are position
and size of the main sprite (???)
the data are:

*p0Y   *p1Y   *p0y+*p0DY              *p1Y+*p1DY                *p2Y           *p2Y+*p2DY
|--------|-------|-------------|--------|-------------|----------|-------------------|
                                yn                  yn+dyn


If your loop works the solution is a list of the sole element p1Y
let's run your loop

phead = p0Y
ptail = p2Y
pmid = p1Y

loop1
as *pmid > yn+dyn thus ptail = pmid (i.e. p1Y)
pmid = (p0y+p1y)/2 (i.e. p0y)

loop2
as *pmid > yn+dyn thus ptail = pmid (i.e. p0Y) (solution lost !!)
pmid = (p0y+p1y)/2 (i.e. p0y)

loop3
as *pmid > yn+dyn thus ptail = pmid (i.e. p0Y)
pmid = (p0y+p1y)/2 (i.e. p0y)

...
No exit : infinite interactions!!!!

Still sure your loop works?? :-)
AuroraMSX

msx master
Mensajes: 1231
Publicado: Agosto 06 2005, 20:27   
Quote:

Let's try your solution: I assume you mean YN, YN+DYN are position
and size of the main sprite (???)


I guess so. I didn't introduce the names
Quote:

the data are:

*p0Y   *p1Y   *p0y+*p0DY              *p1Y+*p1DY                *p2Y           *p2Y+*p2DY
|--------|-------|-------------|--------|-------------|----------|-------------------|
                                yn                  yn+dyn


If your loop works the solution is a list of the sole element p1Y
let's run your loop

phead = p0Y
ptail = p2Y
pmid = p1Y

loop1
as *pmid > yn+dyn thus ptail = pmid (i.e. p1Y)


Erh, *pmid = p1Y is definitely < yn+dyn in your graph

Quote:

Still sure your loop works?? :-)


Rather
norakomi
msx professional
Mensajes: 861
Publicado: Agosto 24 2005, 21:03   
ok,

so, there is screen 5,
I readout sprite collision st. r#0, at several lines several times per frame (on the Vblank, on the line split, outside the int.,
BUT the sprite collision detection doesnt work fine.
Whenever there is a collision I set the computer to play a SFX, so I know there is collision.

However, between some lines it seems to work perfectly (likesay between y=50 and y=100,
and y=130 and y=150,
but on all the other lines there is simply no collision detection.
I made sure I never ever readout s.r#0 anywhere else (because this resets the colision bit, right)

what to do???????????

ps, everybody get ready, because it wont take long for the first test version of SPACEMANBOW 2 LEVEL 1 !!!!!!!!!

cheers !
ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 25 2005, 12:10   
Quote:


I readout sprite collision st. r#0, at several lines several times per frame (on the Vblank, on the line split, outside the int.,
BUT the sprite collision detection doesnt work fine.



Actually the manual of v9938 says that only bit F is reset reading S#0.
In theory reading S#0 multiple times per frame shold return if there are
collisions till at the point the raster has arrived in the frame, and should
not be reset untill a new raster scan starts.

In any case I am not sure how things are really working and as I have only
openMSX, the only suggestion I have is to avoid to read the collision bit
multiple times per frame.

Try reading S#0 once per frame, at the bottom of the screen,
the best is at Vblank, when all the frame is completed.

norakomi
msx professional
Mensajes: 861
Publicado: Agosto 28 2005, 14:35   
i readout s#0 once per frame \, at VBLANK (do you think using the Bios changes things???),
But sprite collision works in between certain lines (also depending 50 or 60 hrtz),

However, and this is weird, if I do not disable sprites at y=212 and enable at y=24 (scoreboard)
the spritecollision seems to be working better (still not fine)

anyone familiar with this problem?
ARTRAG
msx master
Mensajes: 1592
Publicado: Agosto 29 2005, 00:19   
Could you detail the whole sequence?
when do you disable sprites?
when do you read S#0 ?
and all the related stuff?

How do you read s#0 and how do you set the registers?
norakomi
msx professional
Mensajes: 861
Publicado: Septiembre 02 2005, 16:27   
to make things more easy I disabled the screensplit and the backgroundscroll.

there is the VBLANK int, on which I:
put the (32) sprites on screen.

and outside the int, I:
1) have the routine which makes my ship move (using the arrowkeys)
2) make enemy enter/leave the screen.
3) readout st.r#0 for sprite collision

Thats all, and still, the sprite collision only works in between certain lines ... ???
approx. in between y=50 and y=80

and, if I put the sprite collision detection routine ON the interrupt it doesn´t even work at all........
ARTRAG
msx master
Mensajes: 1592
Publicado: Septiembre 02 2005, 19:47   
Quote:


and outside the int, I:
1) have the routine which makes my ship move (using the arrowkeys)
2) make enemy enter/leave the screen.
3) readout st.r#0 for sprite collision



Do this:

In the int routine at vblank, before doing anything, read s#0 and store it in RAM,
put your sprites and do all the staff you need in to do at vblank.
NOTE!!
As far as I remember that the BIOS, when calls hFD9F, has already red S#0!!!
It is passed in register A, and, as far I remember, it is not jet stored in hF3E7!!!
This means that you do not need to read the VDP by yourself, just use the value in A.
Remember !! The bios, on exit from your interrupt, will store in hF3E7 any value
you pass in A. If you want meaningful values in that location, on exit, you need to
pass in A the same value you have found.


Outside the int routine use the copy of S#0 you stored in RAM.
NOTE
Take care to use some kind of synchronization between the int routine and
the main loop outside the int. This is in order to avoid to use the value of S#0
corresponding to one frame two o tree times.

norakomi
msx professional
Mensajes: 861
Publicado: Septiembre 02 2005, 23:44   
wow, cool info. thanx, I´m gonna work with it right away....
bit 5 of status register 0 is used to readout spritecollision.

So, if I get your info correct, then AT VBLANK I simply do:

vblank:
bit 5,a
call z,collision
...
...
...
ei
ret


 
Ir a la página ( Página anterior 1 | 2 | 3 | 4 | 5 Siguiente página )
 







(c) 1994 - 2008 Fundación MSX Resource Center. MSX es una marca registrada de MSX Licensing Corporation