Tutorial de ZX Basic + Fourspriter #25: Moviendo el boomerang

Bueno, como dijimos, ahora vamos a rellenar la cáscara con chicha bien apretá para que nuestro boomerang deje de ser un amasijo de variables, constantes, y esqueletos y se convierta en un arma mortífera de matar con el boomerang de matar.

Empecemos por el principio: crear el boomerang. Si recordamos, al pulsar SPACE o M (detección que se hace en el bucle principal del programa, en feoncio.bas), llamamos a una función fireBoomerang en boomerang.bas para que, si es posible, crée el boomerang y lo ponga en estado BOOESTAVANZANDO. El boomerang tendrá una dirección u otra dependiendo de adónde esté mirando nuestro muñecajo. Además, habrá que comprobar que podemos lanzar el boomerang en esa dirección (por ejemplo, ¿para qué lanzarlo si estamos mirando a la pared?). Además, todo esto lo haremos si y sólo si el boomerang está en estado BOOESTIDLE (o sea, que no está volando por ahí). Recordemos que para saber adónde mira el muñeco tenemos que mirar la variable pFacing, que valdrá 0 para abajo, 16 para arriba, 32 para la derecha y 48 para la izquierda.

El código podría ser algo parecido a esto:

Sub fireBoomerang ()
    ' Lanzaremos el boomerang sólo si está en estado Idle
    ' Lo crearemos en una posición y en una dirección que 
    ' vendrán dadas por pFacing.
    ' Además, sólo lo crearemos si hay espacio libre en 
    ' la dirección a la que mire el player.
    
    If booState = BOOESTIDLE Then
        booMX = 0
        booMY = 0
        If pFacing = 0 Then
            ' Abajo
            If getCharBehaviourAt (pX, pY + 2, nPant) < 4 And _
                getCharBehaviourAt (pX + 1, pY + 2, nPant) < 4 Then
                booMY = 1
            End If
        ElseIf pFacing = 16 Then
            ' Arriba
            If getCharBehaviourAt (pX, pY - 1, nPant) < 4 And _
                getCharBehaviourAt (pX + 1, pY - 1, nPant) < 4 Then
                booMY = -1
            End If
        ElseIf pFacing = 32 Then
            ' Derecha
            If getCharBehaviourAt (pX + 2, pY, nPant) < 4 And _
                getCharBehaviourAt (pX + 2, pX + 2, nPant) < 4 Then
                booMX = 1
            End If
        Else
            ' Izquierda
            If getCharBehaviourAt (pX - 1, pY, nPant) < 4 And _
                getCharBehaviourAt (pX - 1, pY + 1, nPant) < 4 Then
                booMX = -1
            End If
        End If
        
        ' Si hemos cambiado algo, es que se lanza el boomerang:
        If booMX + booMY <> 0 Then
            booX = pX
            booY = pY
            booFrame = 136
            booState = BOOESTAVANZANDO
            booCt = BOOAVANCE
            fsp21BorraSprites ()
            fsp21ActivateSprite (2)
            fsp21MoveSprite (2, booX, booY)
            fsp21DuplicateCoordinatesSprite (2)
            fsp21ColourSprite (2, 71, 71, 71, 71)
            fsp21InitSprites ()
        End If
    End If
End Sub

Como vemos, hay dos secciones: la primera inicializa booMX y booMY a 0, y acto seguido hace las comprobaciones pertinentes dependiendo de adónde esté mirando el personaje principal (recordad nuestro muy trillado diagramilla). En el caso de que sea posible lanzar el boomerang en la dirección concreta, daremos los valores pertinentes a booMX o booMY.

La segunda sección del código detecta si booMX o booMY tienen ahora un valor. Eso significa que hemos podido lanzar el boomerang. En ese caso, se pasa al estado BOOESTAVANZANDO, se inicializa el contador booCt y las coordenadas del boomerang booX y booY para que salga de donde está el muñeco, y finalmente se inicializa el sprite 2, que es el que vamos a usar para el boomerang.

Ahora toca programar la máquina de estados. Como hicimos con los bicharracos, sencillamente veremos qué debemos hacer en cada estado, y lo iremos codificando.

En primer lugar nos damos cuenta de que para el estado BOOESTIDLE no tenemos que hacer nada, ya que en este estado el boomerang ni siquiera está en la pantalla. Por ello lo quitamos del IF que planteamos en el anterior capítulo y empezamos directamente con BOOESTAVANZANDO:

Sub mueveBoomerang ()
    ' Máquina de estados!
    If booState = BOOESTAVANZANDO Then
        ' Podemos avanzar?
        If booMX = 1 Then
            If booX < MAPSCREENWIDTH + MAPSCREENWIDTH - TILESIZE And _
                getCharBehaviourAt (booX + 2, booY, nPant) < 4 And _
                getCharBehaviourAt (booX + 2, booY + 1, nPant) < 4 Then
                booX = booX + 1
            Else
                booState = BOOESTVOLVIENDO
            End If
        ElseIf booMX = -1 Then
            If booX > 0 And _
                getCharBehaviourAt (booX - 1, booY, nPant) < 4 And _
                getCharBehaviourAt (booX - 1, booY + 1, nPant) < 4 Then
                booX = booX - 1
            Else
                booState = BOOESTVOLVIENDO
            End If
        End If
        
        If booMY = 1 Then
            If booY < MAPSCREENHEIGHT + MAPSCREENHEIGHT - TILESIZE And _
                getCharBehaviourAt (booX, booY + 2, nPant) < 4 And _
                getCharBehaviourAt (booX + 1, booY + 2, nPant) < 4 Then
                booY = booY + 1
            Else
                booState = BOOESTVOLVIENDO
            End If
        ElseIf booMY = -1 Then
            If booY > 0 And _
                getCharBehaviourAt (booX, booY - 1, nPant) < 4 And _
                getCharBehaviourAt (booX + 1, booY + 2, nPant) < 4 Then
                booY = booY - 1
            Else
                booState = BOOESTVOLVIENDO
            End If
        End If
        
        ' Fin de la cuenta
        booCt = booCt - 1
        If booCt = 0 Then
            booState = BOOESTVOLVIENDO
        End If

¿Qué estamos haciendo? Muy sencillo. Hemos dicho que el boomerang va a avanzar sólo hasta que se cumpla la cuenta, colisionemos con el escenario, o colisionemos con un enemigo. La primera parte del código sirve para comprobar las colisiones con el escenario. Si os fijáis, dependiendo de la dirección en la que avanza el boomerang, y que nos dictan las variables booMX y booMY, miramos unas casillas u otras (de nuevo, consultando el diagramilla más famoso de la historia de los videogüegos). Si chocamos con algo, simplemente pasamos al siguiente estado (BOOESTVOLVIENDO). Si no, avanzamos en la dirección que sea.

Posteriormente, decrementamos el contador booCt para que, si llega a cero, pasemos también al estado BOOESTVOLVIENDO. Esto significa que, en ausencia de obstáculos, el boomerang avanzará booCt casillas en la dirección en la que se haya lanzado.

La tercera condición para pasar a BOOESTVOLVIENDO (colisión con un bicharraco) la vamos a colocar luego en el manejador de bicharracos, y así nos ahorramos tener que poner un bucle aquí para recorrerlos todos y comprobar uno por uno. Como en el manejador de bicharracos ya tenemos un bucle que los recorre, simplemente colocaremos la comprobación de colisión en el estado activo de los mismos y a otra cosa, mariposa.

Dando el estado BOOESTAVANZANDO por concluido, pasamos al estado BOOESTVOLVIENDO. En este estado, simplemente tendremos que avanzar hasta donde esté el personaje, sin fijarnos en colisiones ni nada por el estilo. Este comportamiento ya lo hemos programado: corresponde con el de los bicharracos de tipo BICHTIPOACOSADOR pero simplificado (no comprobamos colisiones), con lo que no nos detendremos demasiado en explicar esto:

    ElseIf booState = BOOESTVOLVIENDO Then
        ' Seguir al jugador:
        If booX < pX Then
            booX = booX + 1
        ElseIf booX > pX Then   
            booX = booX - 1
        End If
        
        If booY < pY Then
            booY = booY + 1
        ElseIf booY > pY Then
            booY = booY - 1
        End If
        
        If booX = pX And booY = pY Then
            booState = BOOESTIDLE
            fsp21BorraSprites ()
            fsp21DeactivateSprite (2)
        End If
    End If

Primero avanzamos en la dirección que nos dicte la posición del boomerang con respecto a la del personaje principal (para perseguirle) y seguidamente comprobamos si hemos llegado. En ese caso, volvemos al estado idle y desactivamos el sprite del boomerang.

Sólo queda actualizar el frame de animación. Avanzamos de 4 en 4 como hemos visto otras veces. Mirando al spriteset, vemos que el primer frame del boomerang empieza en el bloque 136 y el último en el 152. Por tanto:

    booFrame = booFrame + 4
    If booFrame >= 152 Then booFrame = 136: End If
End Sub

De acuerdo, ya hemos terminado de programar el boomerang. Ahora vamos a integrarlo. Lo primero es darle sentido al boomerang: integrarlo con los bicharracos, de forma que mueran cuando choquen con él. Como hemos dicho antes, esto lo haremos en el manejador de los bicharracos, por lo que nos vamos a bicharracos.bas y añadimos las comprobaciones en el estado BICHESTACTIVO: no tiene sentido matar a los bicharracos si están en otro estado.

Recordad la comprobación de colisión entre jugador y bicharraco que hicimos hace un par de capítulos: es lo mismo. La rama del IF del manejador de bicharracos correspondiente al estado BICHESTACTIVO debería quedar así:

        ElseIf enState (i) = BICHESTACTIVO Then
            ' Llamamos a una subrutina que contenga la IA
            ' Según el valor de enType (i), y le pasamos
            ' "i", el número de enemigo que estamos procesando.
            If enType (i) = BICHTIPOREBOTANTE Then
                iaRebotante (i)
            ElseIf enType (i) = BICHTIPOACOSADOR Then
                iaAcosador (i)
            Else
                iaPasoDeTuCulo (i)
            End If
            
            ' Colisión con el boomerang!
            If booState <> BOOESTIDLE Then 
                If booX >= enX (i) - 1 And booX <= enX (i) + 1 And _
                    booY >= enY (i) - 1 And booY <= enY (i) + 1 Then
                    mataBicharraco (i)
                    booState = BOOESTVOLVIENDO
                End If
            End If

¿Qué hacemos? En primer lugar, comprobar que el boomerang está activo (o sea, no está en estado BOOESTIDLE). En ese caso, comprobamos la colisión. Si existe colisión, llamaremos a la función de matar al bicharraco que hicimos hace poco y haremos que el estado del boomerang pase a BOOESTVOLVIENDO.

¡Sólo nos queda un detalle! Actualizar el sprite del boomerang. Esto lo vamos a hacer en el bucle principal de feoncio.bas, en la sección donde movemos y actualizamos los sprites. Por ejemplo, justo debajo del bloque que actualiza los sprites de los bicharracos. En primer lugar, comprobamos que no estamos en el estado BOOESTIDLE. Luego, movemos el sprite y le actualizamos el frame de animación.

    ' Actualizar sprite del boomerang
    If booState <> BOOESTIDLE Then
        fsp21MoveSprite (2, MAPOFFSETX + booX, MAPOFFSETY + booY)
        fsp21SetGfxSprite (2, booFrame, booFrame + 1, booFrame + 2, booFrame + 3)
    End If

¡Y listo! Ya tenemos que tener a nuestro boomerang activo. Probadlo, está super chulo.

Ahora nos damos cuenta de que cada vez que aparece o desaparece un sprite de pantalla hay un leve parpadeo en los demás. Esto queda muy feo, y en el próximo capítulo veremos cómo solucionarlo. ¿habrá que modificar fourspriter? ¿Será cuestión de mover cosas de sitio? ¡Próximo episodio en tu casa!

Mientras tanto, puedes jugar un poco con el archivillo de este capítulo.

3 Responses to Tutorial de ZX Basic + Fourspriter #25: Moviendo el boomerang

  1. joanra dice:

    Gracias por todas estas lecciones. Cuando tenga vacaciones voy a poner en práctica todo…🙂

  2. na_th_an dice:

    Espero que te sirvan🙂

  3. Pingback: Zx | TagHall

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: