Autor Tema: Colisiones sprite<>sprite por software  (Leído 8969 veces)

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1008
  • SYS 8*4096
    • Ver Perfil
Re:Colisiones sprite<>sprite por software
« Respuesta #15 en: Mayo 05, 2018, 18:50:29 »
Acabo de hacer unas pruebas con sprites y las colisiones.

Como comenté más arriba, desplazo varias veces los sprites durante un refresco de pantalla para así poder acelerar el ritmo del juego. Es un simple bucle contador.

Si la velocidad de movimiento (pixéles desplazados) no excede del tamaño de la bola (6 pixéles) , me reconoce todas las colisiones sin problemas.

Naturalmente, si a la vez estas desplazando el otro sprite con que colisiona (un pad o barrera de 2 pixeles de grueso por 22 de largo) , la suma de ambos consigue que se cuele entre esos 2 pixéles sin detectar colisión. Sí me detecta colisión con otro sprite que tengo justo debajo del pad haciendo de cuerpo.

Como desplazo la bola 1 pixél por cada 2 que se desplaza el pad, la velocidad máxima (pixeles desplazados) que puedo poner está entre 8 o 10. Contra más pixeles desplace la bola, mayores probabilidades de que aparezcan fallos en la detección.

Por las pruebas que he hecho, no detecta las colisiones hasta que no pasa el barrido por la pantalla, o eso parece.
Borrando la bandera de colisiones justo al entrar (con una colisión sprites activada) a la rutina de movimiento fuera de pantalla y leyendola de nuevo al finalizar , me da 0 colisiones (raster aún fuera de pantalla visible) a pesar de que ha habido colisión.

Una vez ya ha mostrado la pantalla, detecta la colisión.
 
« última modificación: Mayo 05, 2018, 19:09:32 por Maniako »
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

Scooter

  • Commodorista
  • ***
  • Mensajes: 89
  • SYS 0
    • Ver Perfil
Re:Colisiones sprite&lt;&gt;sprite por software
« Respuesta #16 en: Mayo 05, 2018, 22:35:08 »
Pues a lo mejor es un lío que te mueres pero...
Hacer una rutina de movimiento que mueva las variables de dónde se encuentra el Sprite pero no escriba los registros hasta que pase el raster para evitar posible flikeos, que salga repetido un Sprite por moverlo a una posición que está detrás del raster cuando ya había salido.
En los movimientos que no se realizan se hace una verificación por software aunque sea "de caja", o "de núcleo" mientras que en la que si que se pinta se hace caso a la interrupción.
Quizás la interrupción del raster pueda servir de reloj para controlar las velocidades de los movimientos.

No tengo claro que esté esquema sea más rápido o no. Lo que está claro es que complica el código pero puede que deje más tiempo libre ya que solo escribes en el VIC cuando avisa el raster y el resto del tiempo lo tienes par todo lo demás.

Para juegos lentos con la interrupción vale pero para los rápidos está claro que sí o sí hay que hacer algo por software.
« última modificación: Mayo 05, 2018, 22:40:03 por Scooter »

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1008
  • SYS 8*4096
    • Ver Perfil
Re:Colisiones sprite<>sprite por software
« Respuesta #17 en: Mayo 06, 2018, 02:46:59 »
Soy complicado  ;D

Cada vez que me meto en un proyecto, aprovecho para probar cosas nuevas.
No me gusta usar bucles en el programa para hacer de freno, así que pensé en este sistema de control de velocidad por raster.
Está claro que me deja muchisimo tiempo de proceso fuera de las interrupciones para otras faenas como animar chars variables , puntuaciones y otros menesteres.

El sistema de detección por coordenadas es excelente, pero como ayuda a las colisiones multiples ya que si a cada ciclo compruebas las colisiones de 8 sprites a la vez con todas sus posibles combinaciones (creo que 28 posibles), debe de chupar una buena cantidad de recursos. Aunque está claro que nunca se van a utilizar todas, como mucho Bala contra malosos y protagonista contra todo XD.

Consultar las colisiones o hacer que activen una Interrupción hasta la rutina de comprobacion ayudaria a disminuir ese consumo de recursos consultando el valor devuelto, ayudaria a limitar la cantidad de comprobaciones entre coordenadas de sprites. 

Llevo haciendo pruebas de colisiones entre sprites todo el día y nunca me han fallado si los desplazamientos de estos no se sobrepasan, impidiendo que los pixeles que los componen se toquen.

Dejo aqui un programilla que hice para trastear y tratar de sacar en claro como trabajan las interrupciones y los sprites.
Lo he comentado todo lo que he podido pero a estas horas ya no me queda combustible XD.


Código: [Seleccionar]
;CBM PRG STUDIO 3.12.0
;Programa para jugar con el raster y la detección de sprites.
;Main es el código normal que espera por comparación del raster a continuar.
;IRQ1 Se ejecuta por interrupción cuando el raster llega al valor establecido en RAS desde la subrutina IRQRASTER.
;Podeís jugar a variar los valores de ambos puntos raster para ver como afecta.
;Tened en cuenta que a cada lectura de colision de sprites, esta se pone a 0 automáticamente, así que
;si la rutina IRQ acaba de leer las colisiones, MAIN no leerá colisión alguna, pero lo muestro para tratar
;de hacer visible lo que ocurre a cada modificación que se haga en los valores de rasters.
;Al parecer , jugando con la zona a mostar sprites (RAS1=180 y RAS2=240) , la detección de colisiones ignora los sprites superiores y solo detecta los inferiores. 
;Como podéis ver, activo o desactivo las colisiones por sprites mientras está dentro de IRQ1 ya que si estas están activas, al colisionar los sprites volverian
;a llamar a IRQ1 dando "tirones" en su ejecución.
;Espero que saquéis más cosas en claro que yo XD. Lo que si nunca ha fallado es la detección.

; 10 SYS4096
*=$0801
        BYTE    $0B, $08, $0A, $00, $9E, $34, $30, $39, $36, $00, $00, $00
*=$1000
start   lda #00         ;Fondo y marco a negro
        sta $d020
        sta $d021
        jsr putsprites  ;Prepara y coloca los sprites.
        jsr IRQRASTER   ;Activa las interupciones.

MAIN    lda $d012       ;RASTER
RAS1    cmp #100        ;Si no ha legado a la linea deseada, repite lectura.
        bne MAIN
        dec $d020       ;Cámbio de color del marco como pista de lo que está ocurriendo en pantalla.
        inc SP2X        ;Muevo sprite
        lda SPSPCL      ;Leer colisiones sprite sprite.
        sta $0608       ;Muestra el valor de la colisión entre sprites.LInea superior.
        inc $d020       ;Devuelve el color anterior al marco.
        jmp MAIN
       
;-----------------------------------------------------------------------------
IRQ1    lda #04         ;Conectando IRQ por sprites. Evitas doble llamada a irq1
        sta $d01a
        inc $d020       ;Cambia color marco para mostar raster
        asl $D019       ;Necesario para "reset raster"
        inc SP0X        ;Mover sprite.
        lda SPSPCL      ;Leer colision sprite sprite.
        sta $0798       ;Muestra el valor de la colisión entre sprites. Linea inferior
        lda #01         ;Conectando IRQ por RASTER
        sta $d01a
        dec $d020       ;Devuelve el color anterior al marco.
        jmp $EA31       ;Salir de las interrupciones.
;SUBRUTINAS---SUBRUTINAS---SUBRUTINAS---SUBRUTINAS---SUBRUTINAS---
IRQRASTER
        sei                                   
        lda #%00011011  ;27 original. 26 no flickea.Hibyte del raster pero                             
        sta $D011       ;si no es 27 aparecen "pelos" en los bordes pantalla.
        lda #<irq1      ;IRQ1=Raster
        sta $0314                           
        lda #>irq1                           
        sta $0315                           
        lda #%00000001  ;#127 en el ejemplo. Basta con activar el timer A #1     
        sta $DC0D       ;Registro control de la cia                   
        lda #01         ;Conecta IRQ por raster.
        sta $D01A       ;Registro mascara IRQ activada. IRQ ON. Col.Sprite ON
        cli 
RAS2    lda #240        ;linea activar barrido irq en la linea XX
        sta $d012
        rts
;-------------------------------------------------------------
PUTSPRITES              ;Conectar sprites y colocarlos.
        lda #15         ;8+4+2+1
        sta SPENA       ;Conectar sprite 0 , 1 , 2 , 3 y 4 Pad's' y bola
;Punteros de los sprites. 128
        lda #128
        sta POINSP0     
        sta POINSP1
        sta POINSP2
        sta POINSP3
        lda #04
        sta SP0COL
        sta SP1COL
        sta SP2COL
        sta SP3COL
;Coordenadas X e Y sprites.
        lda #140
        sta SP0X
        lda #231
        sta SP0Y
        lda #180
        sta SP1X
        lda #231
        sta SP1Y
        lda #140
        sta SP2X
        lda #150
        sta SP2Y
        lda #190
        sta SP3X
        lda #150
        sta SP3Y
        rts
;---------------------------------------------------------
*=$2000   ;SPRITE puntero 128
          BYTE $3F,$FC,$00,$7F,$FE,$00,$FF,$FF,$00
          BYTE $FF,$FF,$00,$FF,$FF,$00,$FF,$FF,$00
          BYTE $7F,$FE,$00,$3F,$FC,$00,$00,$00,$00
          BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00
          BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00
          BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00
          BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00
          BYTE $05
;***************************************************************************
;Constantes universales
;       $D000-$D010 SPRITE HORIZONTAL AND VERTICAL POSITION REGISTERS
SP0X    =       $D000   ; SPRITE 0 X POSITION
SP0Y    =       $D001   ; SPRITE 0 Y POSITION
SP1X    =       $D002   ; SPRITE 1 X POSITION
SP1Y    =       $D003   ; SPRITE 1 Y POSITION
SP2X    =       $D004   ; SPRITE 2 X POSITION
SP2Y    =       $D005   ; SPRITE 2 Y POSITION
SP3X    =       $D006   ; SPRITE 3 X POSITION 
SP3Y    =       $D007   ; SPRITE 3 Y POSITION
SP4X    =       $D008   ; SPRITE 4 X POSITION
SP4Y     =      $D009   ; SPRITE 4 Y POSITION
SP5X    =       $D00A   ; SPRITE 5 X POSITION
SP5Y    =       $D00B   ; SPRITE 5 Y POSITION
SP6X    =       $D00C   ; SPRITE 6 X POSITION
SP6Y    =       $D00D   ; SPRITE 6 Y POSITION
SP7X    =       $D00E   ; SPRITE 7 X POSITION
SP7Y    =       $D00F   ; SPRITE 7 Y POSITION
MSIGX   =       $D010   ; MSB'S OF SPRITES 0-7 HORIZONTAL POSITIONS
;       POINTER SPRITES
POINSP0 =       $07F8   ; POINTER 2040 SPRITE O
POINSP1 =       $07F9   ; POINTER 2041 SPRITE 1
POINSP2 =       $07FA   ; POINTER 2042 SPRITE 2
POINSP3 =       $07FB   ; POINTER 2043 SPRITE 3
POINSP4 =       $07FC   ; POINTER 2044 SPRITE 4
POINSP5 =       $07FD   ; POINTER 2045 SPRITE 5
POINSP6 =       $07FE   ; POINTER 2046 SPRITE 6
POINSP7 =       $07FF   ; POINTER 2047 SPRITE 7
;       $D011-$D012 SCROLL & RASTER
SCROLY  =       $D011   ; VERTICAL FINE SCROLLING AND CONTROL REGISTER
RASTER  =       $D012   ; READ CURRENT RASTER SCAN LINE/WRITE LINE TO COMPARE
                                        ; FOR RASTER IRQ

SPENA   =       $D015   ; SPRITE ENABLE REGISTER
SCROLX  =       $D016   ; HORIZONTAL FINE SCROLLING AND CONTROL REGISTER
YXPAND  =       $D017   ; SPRITE VERTICAL EXPANSION REGISTER
VMCSB   =       $D018   ; VIC-II CHIP MEMORY CONTROL REGISTER
VICIRQ  =       $D019   ; VIC INTERRUPT FLAG REGISTER
IRQMSK  =       $D01A   ; IRQ MASK REGISTER
SPBGPR  =       $D01B   ; SPRITE TO FOREGROUND DISPLAY PRIORITY REGISTER
SPMC    =       $D01C   ; SPRITE MULTICOLOR REGISTERS
XXPAND  =       $D01D   ; SPRITE HORIZONTAL EXPANSION REGISTER
;       $D01E-$D01F SPRITE COLLISION DETECTION REGISTERS
SPSPCL  =       $D01E   ; SPRITE TO SPRITE COLLISION REGISTER
SPBGCL  =       $D01F   ; SPRITE TO FOREGROUND COLLISION REGISTER
;       $D020-$D026 VIC-II COLOR REGISTER
EXTCOL  =       $D020   ; BORDER COLOR REGISTER
BGCOL0  =       $D021   ; BACKGROUND COLOR 0
SPMC0   =       $D025   ; SPRITE MULTICOLOR 0
SPMC1   =       $D026   ; SPRITE MULTICOLOR 1
;       $D027-$D02E SPRITE COLOR REGISTERS
SP0COL  =       $D027   ; SPRITE 0 COLOR
SP1COL  =       $D028   ; SPRITE 1 COLOR
SP2COL  =       $D029   ; SPRITE 2 COLOR
SP3COL  =       $D02A   ; SPRITE 3 COLOR
SP4COL  =       $D02B   ; SPRITE 4 COLOR
SP5COL  =       $D02C   ; SPRITE 5 COLOR
SP6COL  =       $D02D   ; SPRITE 6 COLOR
SP7COL  =       $D02E   ; SPRITE 7 COLOR
;       $D02F-$D03F NOT CONNECTED
;       $D040-$D3FF VIC-II REGISTER IMAGES
;       $D419-$D41A GAME PADDLE INPUTS
;       $D41D-$D41F NOT CONNECTED
;       $D420-$D7FF SID REGISTER IMAGES
;       $D800-$DBFF COLOR RAM
COLRAM  =       $D800
; $DC00-$DC0F CIA #1
CIAPRA  =       $DC00   ; DATA PORT REGISTER A joy2
CIAPRB  =       $DC01   ; DATA PORT REGISTER B joy1
CIDDRA  =       $DC02   ; DATA DIRECTION REGISTER A
CIDDRB  =       $DC03   ; DATA DIRECTION REGISTER B
CIASDR  =       $DC0C   ; SERIAL DATA PORT
CIAICR  =       $DC0D   ; INTERRUPT CONTROL REGISTER
CIACRA  =       $DC0E   ; CONTROL REGISTER A
CIACRB  =       $DC0F   ; CONTROL REGISTER B
; $DC10-$DCFF CIA #1 REGISTER IMAGES
; $DD00-$DD0F CIA #2
; $DD10-$DDFF CIA #2 REGISTER IMAGES
LECOL   =   $0286   ; LETTER COLOR
GETIN   =   $FFE4
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1008
  • SYS 8*4096
    • Ver Perfil
Re:Colisiones sprite<>sprite por software
« Respuesta #18 en: Mayo 06, 2018, 03:16:39 »
Aclarar que lo de apagar y desconectar las IRQ de colisiones no está completo.
Las IRQ de raster las envio a una rutina de movimiento y las de sprites a la rutina de comprobar colision.
Se puede hacer comprobando los bites de $D019, pero me gusta experimentar XD
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 13628
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Colisiones sprite<>sprite por software
« Respuesta #19 en: Mayo 06, 2018, 05:01:20 »
Muy bueno Maniako!
www.retroinvaders.com | www.commodoreplus.org  | josepzin.blogspot.com

Dashiad

  • Commodoremaníaco
  • ****
  • Mensajes: 160
  • SYS 0
    • Ver Perfil
Re:Colisiones sprite<>sprite por software
« Respuesta #20 en: Mayo 06, 2018, 14:07:20 »
Hay que tener en cuenta que en un juego como el que propone Maniako, tipo Arkanoid, si se hace por bounding box, la caja donde se metiera la bola deberia ser tan pequeña como la bola. Lo mismo para el pad. Si se utilizara una caja demasiado grande para cualquiera de los dos, quedaría muy inexacto.

Y, si es así, y simplemente se suman pixeles de movimiento, y se calculan colisiones, el problema es el mismo: la bola puede "saltarse" el pad.Y daría lo mismo que se haga por bounding boxes o por hardware, ya que las bounding boxes son pequeñas.
Por fuerza hay que interpolar la posición de la bola a la altura en la que se encuentra el pad, para ver si colisionaria o no.

En general, una cosa es la trayectoria que siguen los objetos, y otra es lo que se pinta en pantalla.Si cada punto de la trayectoria se va a pintar (cada uno de los pixeles), las interrupciones no deberian fallar nunca (otra cosa es que las bounding boxes deberian seguir usandose para saber qué sprites han colisionado entre si, si son más de dos).