Karoshi MSX Community

Desarrollo MSX => Desarrollo (Español/Spanish) => Mensaje iniciado por: cybernoid en 01 de Mayo de 2009, 11:05:52 am



Título: Deteccion sprite vs caracter
Publicado por: cybernoid en 01 de Mayo de 2009, 11:05:52 am
Hola,

Cual es la mejor manera para detectar sobre que caracter esta un sprite ?

ayer entube haciendo pruebas en CM pero no encuentro ninguna manera que me convenza

aquí posteo mi ultimo código, a ver si alguien me sabe dar una solución mejor, ahora estaba pensando en almacenar en la ram la posición de cada carácter pero en alta resolucion (ej caracter 1 en 100,128  caracter 2 108,128,etc,etc)


Código:
; check collision
;---------------------------------------------------------
; CONSTANTS
;---------------------------------------------------------
; VRAM addresses
        CHRTBL  equ     0000h   ; Pattern table
        NAMTBL  equ     1800h   ; Name table
        CLRTBL  equ     2000h   ; Colour table
        SPRTBL  equ     3800h   ; Sprite pattern table
        SPRATR  equ     1b00h   ; Sprite attributtes
; System variables
        CLIKSW  equ     0f3dbh  ; Keyboard sound
        FORCLR  equ     0f3e9h  ; Foreground colour
;---------------------------------------------------------
; ASSEMBLER DIRECTIVES (asMSX)
;---------------------------------------------------------
        .bios           ; Defines MSX BIOS routines
        .page 2         ; Assembly starts at 8000h
        .rom            ; Selected format
        .db      "CheckCollision",1Ah
                        ; Text header - not MSX standard
        .start  INIT    ; Program start

;---------------------------------------------------------


;---------------------------------------------------------
INIT:
; Program start
;---------------------------------------------------------
        call INIT_GRAPHICS

        call DEFINE_SPRITES
        call INITVARS

        ld de,NAMTBL
        ld hl,MAPA1
        ld bc,912
        call LDIRVM
buc:
        call DRAW_PROTA
        call MOVE_PROTA
        ld a,[protatny]
        ld b,a
        ld a,[protatnx]
        ld c,a
        call GET_POS
       
        ld a,65
        call WRTVRM

        halt




        ld a,[protatny]
        ld b,a
        ld a,[protatnx]
        ld c,a
        ld a,32
        call DRAW_CHAR
        jp buc


;---------------------------------------------------------
INIT_GRAPHICS:

; Initialise the graphic mode and define graphic elements
;---------------------------------------------------------
; Set proper colours
; BASIC: COLOR 15,0,0
        ld      hl,FORCLR
        ld      [hl],15
        inc     hl
        ld      [hl],0
        inc     hl
        ld      [hl],0
; Set text mode II
; BASIC: SCREEN 1
        call    INIT32
; Erase all sprite data
        call    CLRSPR
; 16x16 Sprite mode
; BASIC: SCREEN ,2
        ld      bc,0e201h
        call    WRTVDP
        ret

;---------------------------------------------------------
MOVE_PROTA:
; Mueve la raqueta
;---------------------------------------------------------
      ld a,0
      call GTSTCK
      cp 1
      jp nz,@@PRSDOWN




      ;--  desplaza el muñeco
      ld a,[protay]
      dec a
      ld [protay],a
      ;--
      ld a,[offsety]    ; decrementa offsety
      dec a
      ld [offsety],a
      ;--
      cp 255
      ret nz ; if offsety=255 then offsety=7:protatny-- else ret
      ld a,7
      ld [offsety],a
      ld a,[protatny]
      dec a
      ld [protatny],a
      ret


@@PRSDOWN:
      cp 5
      jp nz,@@PRSLEFT
      ld a,[protay] ; incrementa protay
      inc a
      ld [protay],a
      ;--
      ld a,[offsety] ; incrementa el offsety
      inc a
      ld [offsety],a
      ;--
      cp 8     ; if offsety=8 then offsety=0:protatny++ else ret
      ret nz
      ld a,0
      ld [offsety],a
      ld a,[protatny]
      inc a
      ld [protatny],a
      ret
@@PRSLEFT:
      cp 7
      jp nz,@@PRSRIGHT
      ld a,[protax]
      dec a
      ld [protax],a
      ;--
      ld a,[offsetx]    ; decrementa offsetx
      dec a
      ld [offsetx],a
      ;--
      cp 255
      ret nz ; if offsetx=255 then offsetx=7:protatnx-- else ret
      ld a,7
      ld [offsetx],a
      ld a,[protatnx]
      dec a
      ld [protatnx],a
      ret

@@PRSRIGHT:
      cp 3
      ret nz
      ;-- comprueba que no haya ningun caracter a la derecha
      ld a,[protatnx]
      inc a
      inc a

      ld c,a
      ld a,[protatny]
      ld b,a
      call GET_POS
      call RDVRM
      cp '0'
      ret z
      ;-- desplaza el muñeco     
      ld a,[protax]
      inc a
      ld [protax],a
      ;--
      ld a,[offsetx] ;incrementa offsetx
      inc a
      ld [offsetx],a
      ;--
      cp 8       ; if offsetx=8 then offsetx=0:protatnx++ else ret
      ret nz
      ld a,0
      ld [offsetx],a
      ld a,[protatnx]
      inc a
      ld [protatnx],a
      ret


      ret

;---------------------------------------------------------
DRAW_PROTA:
; Inicializa las variables
;---------------------------------------------------------
      ld hl,SPRATR
      ld a,[protay]
      call WRTVRM
      ld hl,SPRATR+1
      ld a,[protax]
      call WRTVRM
      ld hl,SPRATR+2
      ld a,0
      call WRTVRM
      ld a,15
      ld hl,SPRATR+3
      call WRTVRM
      ret
;---------------------------------------------------------
INITVARS:
; Inicializa las variables
;---------------------------------------------------------
      ; posiciona el sprite del prota
      ld a,88
      ld [protax],a
      dec a
      ld [protay],a

      ; posiciona el prota en relacion a la pantalla de texto
      ld a,11
      ld [protatnx],a
      ld [protatny],a
      ; pone los offsets a 0
      ld a,4
      ld [offsetx],a
      ld [offsety],a

      ret
;---------------------------------------------------------
DEFINE_SPRITES:
; define los sprites
;---------------------------------------------------------
; -Bat
        ld      hl,SPRTBL
        ld      bc,32
        ld      a,129
        call    FILVRM
        ret
;---------------------------------------------------------
GET_POS:
; retorna la direccion de la tabla de nombre seleccionada en X e Y
; B=Y
; C=X
; hl= direccion
;---------------------------------------------------------
        ld a,b
        and 11111000b   ; pilla los 5 ultimos bytes de b
        srl a
        srl a
        srl a           ;  los corre 3 posiciones a la derecha
        ld h,a          ; lo deposita el H
        ld a,b
        and 00000111b   ; pilla los 3 primeros bytes de b
        rl a
        rl a
        rl a
        rl a
        rl a            ; los corre 5 posiciones a la izquierda
        or c            ; lo mezcla con C
        ld l,a          ; lo deposita el L
        ld bc,NAMTBL    ; suma la direccion de la tabla de patrones
        add hl,bc
        ret
;---------------------------------------------------------
; MAPAS
;---------------------------------------------------------
MAPA1:
      db "00000000000000000000000000000000"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                  0           0"
      db "0                  0           0"
      db "0                  0           0"
      db "0                  0           0"
      db "0                  0           0"
      db "0                  0           0"
      db "0                  0           0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "0                              0"
      db "00000000000000000000000000000000"

;---------------------------------------------------------
; VARIABLES
;---------------------------------------------------------
.page 3
; posicion prota
protax:
       .ds 1
protay:
       .ds 1

; posicion del prota en la tabla de nombres
protatnx:
       .ds 1
protatny:
       .ds 1
offsetx:
       .ds 1
offsety:
       .ds 1


Viejo, podrias explicarme como lo haces en Phantomas Saga?

gracias compeñeros :)


Título: Re: Deteccion sprite vs caracter
Publicado por: kabish en 01 de Mayo de 2009, 01:23:35 pm
Yo para TOGK reemplace una rutina que hice por el snippet "Fast NAMTBL address calculation" de jltursan. Lo tienes en la seccion de snippets de este foro, mas concretamente http://msxgamesbox.com/karoshi/index.php?topic=424.0 (http://msxgamesbox.com/karoshi/index.php?topic=424.0).

¿es esto a lo que te referias?


Título: Re: Deteccion sprite vs caracter
Publicado por: Dioniso en 01 de Mayo de 2009, 04:07:56 pm
Viejo, podrias explicarme como lo haces en Phantomas Saga?

Hombre, por fin nos escribimos por aquí también   :)

Estás pensando en hacer un juego tipo Phantomas Saga?...  ;)

Bueno, ya te han respondido. De todos modos, si quisieras hacer una array en RAM (o en ROM), hazlo seguido, no dejes bytes sueltos. Lo de saltar de 100,128 a 108,128 solo sirve para perder 7 bytes de RAM por cada tile. Además, si llegaras a situar tu SPRITE dentro del array, podrías ver fácilmente que tienes a los lados utilizando IX, por ejemplo.

Si sabes la posición del SPRITE en el array (que sería una copia de lo que hay en pantalla, VRAM) y la pasas de HL a IX, por ejemplo (PUSH HL, POP IX), podrías ver fácilmente qué hay en las 4 direcciones (LD A,(IX-1), LD A,(IX+1), LD A,(IX-32), LD A,(IX+32) ), o en alguna posición cercana (IX+128, IX-127). Al tener en A la tile que quieres comprobar, tan sólo debes dibujar las paredes, techo, columnas, a partir de una tile determinada. Es decir, que si tienes esas paredes, techo, columnas, escaleras, y demás tiles que el protagonista no puede atravesar definidas de 200 a 255, por ejemplo, con hacer un CP 200 y comprobar el flag de C puedes saber si el SPRITE puede moverse en esa dirección o no. Así no tienes que hacer demasiadas comprobaciones (es una pared?, es una escalera?, es una columna?, es el techo?).

Y como me estoy dando cuenta de que esta explicación está resultando una caca, y además es una explicación caótica, te digo: "hasta luego".


Título: Re: Deteccion sprite vs caracter
Publicado por: cybernoid en 01 de Mayo de 2009, 09:15:45 pm
Hola Dioniso y kabish

no me explicado bien con la idea, desde luego no pienso dejar 8 bytes sueltos xDD yo lo que decia era guardar las posiciones de los caracteres en una tabla

por ejemplo el carácter 1,1(x,y) en mi tabla estaría en 8,8 y el carácter que esta en 2,1(x,y) estaría en 16,8  como se que cada caracter es de 8 pixeles x 8 pixeles podría hacer boundingbox para comprobar colisiones, pero es un poco mas lió, creo que el sistema que recomienda kabish estará bien :)

igualmente quedo a la espera que viejo me explique como lo hace el :)

Dioniso, tal vez un Phantomas saga no, pero hay que estar preparado  :) por que colisiones fijo que hay :)



Título: Re: Deteccion sprite vs caracter
Publicado por: Jon_Cortazar en 02 de Mayo de 2009, 06:20:09 am
A ver si me se explicar. Te digo como lo hago yo, que probablemente no sea la forma más óptima, pero bueno ;)

Vale, en RAM siempre me guardo la pantalla entera en patrones, (namtbl, es decir, los 768 bytes que componen la pantalla). Esto es importante para chequear, porque si vas a buscar la info en VRAM la cosa se te va a ralentizar cosa mala. Teniendo esa información en RAM, lo que tienes que hacer es ANTES de que tu sprite llegue a PISAR un nuevo patrón, mirar a ver que hay, y si es una tile "pisable", dejarle pasar y si no es "pisable" pues impedir el movimiento.

Yo lo que suelo hacer es definir los patrones "pisables" todos juntos y los "no pisables" todos juntos también, de forma que puedo comprobar fácilmente si puedo atravesarlos o no (si tengo de 0-127 los pisables y de 128-255 los no pisables, es una simple comprobación. Si es mayor que 128, entonces no puedes pasar: si no, si puedes. Así te evitas una lista definiendo que patrones son pisables y cuales no). Además, la comprobación no la hago cada pixel. La hago solo cuando el personaje se va a mover, y solo si se encuentra en una coordenada crítica, es decir, si está a punto de pisar un nuevo patrón. En ese momento, miro lo que va a haber, lo chequeo, y dejo moverse al personaje si veo que es un patrón atravesable.


Título: Re: Deteccion sprite vs caracter
Publicado por: cybernoid en 02 de Mayo de 2009, 07:21:39 am
A ver si me se explicar. Te digo como lo hago yo, que probablemente no sea la forma más óptima, pero bueno ;)

Vale, en RAM siempre me guardo la pantalla entera en patrones, (namtbl, es decir, los 768 bytes que componen la pantalla). Esto es importante para chequear, porque si vas a buscar la info en VRAM la cosa se te va a ralentizar cosa mala. Teniendo esa información en RAM, lo que tienes que hacer es ANTES de que tu sprite llegue a PISAR un nuevo patrón, mirar a ver que hay, y si es una tile "pisable", dejarle pasar y si no es "pisable" pues impedir el movimiento.

Yo lo que suelo hacer es definir los patrones "pisables" todos juntos y los "no pisables" todos juntos también, de forma que puedo comprobar fácilmente si puedo atravesarlos o no (si tengo de 0-127 los pisables y de 128-255 los no pisables, es una simple comprobación. Si es mayor que 128, entonces no puedes pasar: si no, si puedes. Así te evitas una lista definiendo que patrones son pisables y cuales no). Además, la comprobación no la hago cada pixel. La hago solo cuando el personaje se va a mover, y solo si se encuentra en una coordenada crítica, es decir, si está a punto de pisar un nuevo patrón. En ese momento, miro lo que va a haber, lo chequeo, y dejo moverse al personaje si veo que es un patrón atravesable.


y para saber que patron tienes en cada posición utilizas una rutina como la que comenta kabish pero apuntado a ram?  o tienes otro método?

gracias por la explicación:) seguro que me viene bien


Título: Re: Deteccion sprite vs caracter
Publicado por: Jon_Cortazar en 02 de Mayo de 2009, 07:51:12 am
Sip, eso hago gobblin, pero no olvides que no debes mirar el tile de la posición de tu personaje, sino el/las tiles en las que VA A ESTAR tu personaje. Habrá veces que tendrás que comprobar 2 tiles y otras 3 (las más de las veces), siempre hablando de un sprite 16x16. Es decir:



O=cuarta parte de sprite 16x16
X=tile a comprobar
 
---------derecha

  X -?
OOX
OOX

---------izquierda

X   -?
XOO
XOO

---------arriba

XXX-?
OO
OO

---------abajo

OO
OO
XXX-?



En los casos en que la posición X o Y no sea exactamente mútliplo de 8 en el momento de hacer la comprobación, tendrás que leer el valor de 3 tiles, ya que en realidad tu sprite iría a pisar las 3 (aunque parcialmente). Solo en los casos en los que tu sprite esté "centrado" en la rejilla de patrones en la X o en la Y será cuando debas comprobar tan solo 2. Idem para un sprite 8x8... en este caso tendrás que comprobar 2 tiles en vez de 1 si tienes las coordenadas de tu sprite "descentradas" con respecto a las posiciones multiplos de 8 de los tiles de fondo.



Título: Re: Deteccion sprite vs caracter
Publicado por: cybernoid en 02 de Mayo de 2009, 10:30:34 am
Bien bien :) muchas gracias por toda la información con esto ya tengo una buena base de las técnicas utilizadas


Título: Re: Deteccion sprite vs caracter
Publicado por: OKI09 en 02 de Mayo de 2009, 11:23:13 am
Estoy de acuerdo con Viejo y Dioniso, es la forma mas sencilla de hacerlo.

No te compliques la vida con otros metodos gobblin, funciona a la perfeccion. ;)


Título: Re: Deteccion sprite vs caracter
Publicado por: Tragamanzanas en 06 de Mayo de 2009, 07:47:55 pm

En los casos en que la posición X o Y no sea exactamente mútliplo de 8 en el momento de hacer la comprobación, tendrás que leer el valor de 3 tiles, ya que en realidad tu sprite iría a pisar las 3 (aunque parcialmente).


¿Como se comprueba que X ó Y sea múltiplo de 8? Si, ya se, dividiendolo entre 8 y si hay decimales no lo es, pero como se programa eso en ensamblador.


Título: Re: Deteccion sprite vs caracter
Publicado por: SapphiRe_MSX en 06 de Mayo de 2009, 07:54:46 pm
¿Como se comprueba que X ó Y sea múltiplo de 8? Si, ya se, dividiendolo entre 8 y si hay decimales no lo es, pero como se programa eso en ensamblador.

Si tienes el valor en A, simplemente haces AND 7 y si da 0 (se enciende el flag Z) es múltiplo de 8, si no... pues no.