Karoshi MSX Community
05 de Julio de 2021, 08:28:45 pm *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias:
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1]
  Imprimir  
Autor Tema: Deteccion sprite vs caracter  (Leído 5608 veces)
0 Usuarios y 1 Visitante están viendo este tema.
cybernoid
Karoshi Maniac
****
Mensajes: 368



WWW
« : 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 Smiley
« Última modificación: 01 de Mayo de 2009, 11:15:44 am por gobblin » En línea
kabish
Karoshi Maniac
****
Mensajes: 470


caspaflims@hotmail.com
« Respuesta #1 : 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.

¿es esto a lo que te referias?
En línea
Dioniso
Visitante
« Respuesta #2 : 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   Smiley

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

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".
En línea
cybernoid
Karoshi Maniac
****
Mensajes: 368



WWW
« Respuesta #3 : 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 Smiley

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

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

En línea
Jon_Cortazar
Administrator
Karoshi Forum's God
********
Mensajes: 2777



WWW Email
« Respuesta #4 : 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 Wink

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.
En línea

Jon Cortázar Abraido (aka El Viejo Archivero)
RELEVO Videogames
[Dioniso: La cafeína está haciendo su trabajo; yo espero hacer el mío.]
[pitpan: Me sigue pareciendo más productivo jugar al SNAIL MAZE que seguir esta discusión.]
cybernoid
Karoshi Maniac
****
Mensajes: 368



WWW
« Respuesta #5 : 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 Wink

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
« Última modificación: 02 de Mayo de 2009, 07:43:21 am por gobblin » En línea
Jon_Cortazar
Administrator
Karoshi Forum's God
********
Mensajes: 2777



WWW Email
« Respuesta #6 : 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.

« Última modificación: 02 de Mayo de 2009, 07:53:22 am por Viejo_archivero » En línea

Jon Cortázar Abraido (aka El Viejo Archivero)
RELEVO Videogames
[Dioniso: La cafeína está haciendo su trabajo; yo espero hacer el mío.]
[pitpan: Me sigue pareciendo más productivo jugar al SNAIL MAZE que seguir esta discusión.]
cybernoid
Karoshi Maniac
****
Mensajes: 368



WWW
« Respuesta #7 : 02 de Mayo de 2009, 10:30:34 am »

Bien bien Smiley muchas gracias por toda la información con esto ya tengo una buena base de las técnicas utilizadas
En línea
OKI09
Karoshi Maniac
****
Mensajes: 275



WWW Email
« Respuesta #8 : 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. Wink
En línea

La derrota no es una opción y no hay excusas.
"Parasiempre"
Tragamanzanas
Karoshi Fan
**
Mensajes: 71


« Respuesta #9 : 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.
En línea
SapphiRe_MSX
Visitante
« Respuesta #10 : 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.
En línea
Páginas: [1]
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2013, Simple Machines XHTML 1.0 válido! CSS válido!