Recargas de combustible – parte 2

Seguimos con la segunda parte de las “recargas de combustible”. En la primer parte vimos como implementar un generador de números aleatorios, algo que es trivial en cualquier lenguaje de programación, pero en ensamblador es un pequeño dolor de cabeza.
En esta segunda parte vamos a ver el código para que cada cierto intervalo de tiempo caiga un tanque de combustible desde el cielo, que puede ser tomado por cualquiera de los jugadores o destruido a tiros, para que no la agarre nadie.

Vamos a hacer, como en anteriores ocasiones, una máquina de estados, la cual tendrá 5 ‘status’ (status0 – status4). Esta máquina utilizará las siguientes variables/posiciones de memoria (que definiremos convenientemente en vars.asm):

; direcciones de fuel, sprite 4
sprcolorfuel = $d02b
sprpointfuel = $07fc
sprxfuel = $d008          
spryfuel = $d009
FUEL      = $10       ; 16, constante sprite 4 (00010000) 
cantFUEL  = 10        ; cantidad de combustible de cada fuel 
statusFuel = $c0a0
fuelCounter = $c0a1

;255 mas grande el valor, mas tiempo tarda en aparecer
delayEntreFuels = 32    

Para que haya mas claridad en la explicación primero voy a hacer un “resumen” de la maquina de estados, y luego voy a desglosar cada parte.

@status0
    decrementa el contador 'fuelCounter', cuando llega a 0 pasa a status1

@status1
    inicializa el 'fuel' (obtiene posicion x aleatoria, posiciona en y, etc

@status2
    caida libre hasta que llega al piso

@status3
    espera en el piso, hasta que alguien lo agarre o lo destruyan

@status4
    apaga el sprite, reinicia contadores, cambia a status0

Status 0

Aqui solamente esperamos un cierto tiempo, para ello decrementamos un contador ‘fuelCounter‘, con la particularidad que lo haremos cada 64 frames (para ello usaremos un ‘generador de ticks’ que previamente usamos en otra parte). Cuando llegue a 0 pasamos a status1

@status0                
          ; si statusFuel == 0 sigue, si no pasa al siguiente
          ldx            statusFuel
          cpx            #0        
          bne            @status1  

          ; Si hay un tick64 entonces decremento en 1 el fuelCounter
          lda            tick64 
          cmp            #0        
          bne            @decrementFuelCounter
          jmp            @exitFuel 
          
@decrementFuelCounter          
          dec            fuelCounter
          ; Si el fuelCounter llego a 0 cambio a status1
          beq            @setStatus1
          jmp            @exitFuel 
          
@setStatus1
          ldx            #1        
          stx            statusFuel

Status 1

Cuando el fuelCounter llega  a 0 cambiamos de status,  e inicializamos el tanque de combustible. Para ello  activo el sprite 4, pongo en 0 la posición y, borro el bit8 (ya que puede haber quedado seteado de un tanque anterior), obtengo un numero aleatorio y le sumo 48, para centrarlo un poco. Esto es porque nuestro generador tira números de 0 a 255, pero nuestra pantalla tiene 320 px de ancho.
Para no complicar demasiado todo, y considerando que de 0 a 24  y de 320 en adelante el tanque no se mostraría en pantalla, decidí simplemente restringirlo a un área centrada de la pantalla, de  255 pixels, que abarca la posición entre 48 y 303.
Luego que inicializé todo paso a status2.

@status1                
          ldx            statusFuel
          cpx            #1        
          bne            @status2  

          ; Pongo posicion y en 0
          ldy            #0        
          sty            spryfuel  

          ; activo sprite 4
          lda            spractive 
          ora            #FUEL
          sta            spractive 
          
          ; posicion x fuel (random entre 48 y 303)
          ; borro el bit8 del sprxfuel (por si quedo seteado anteriormente)
          lda            sprxBit8   
          and            #%11101111
          sta            sprxBit8  
          
          ; obtengo un numero del generador random
          jsr            randomGenerator
          clc
          lda            random    

          ; lo centro un poco
          adc            #48       
          sta            sprxfuel  
          ; si tengo carry, entonces voy a tener que setear Bit8
          bcs            @setBit8  
          
          jmp            @setStatus2  
@setBit8                           
          lda            sprxBit8  
          ora            #%00010000
          sta            sprxBit8  

@setStatus2
          ; finalmente paso a status2
          ldx            #2
          stx            statusFuel

Status 2

Aqui comienza la caída libre, incrementando la posición y del sprite cada cuatro frames (usamos el mismo tick4 que previamente definimos para la gravedad de los jetpacks). Una vez que llega al piso pasamos a status3

@status2                
          ldx            statusFuel
          cpx            #2
          bne            @status3  

          ; incremento cada 4 frames
          lda            tick4
          cmp            #0        
          bne            @incrementFuel_y
          jmp            @exitFuel 

@incrementFuel_y
          inc            spryfuel  
          ldy            spryfuel  

          ; si llego al piso (un poquito mas, ya que es mas corto el sprite)
          cpy            #floorPosition + 3
          beq            @setStatus3
          jmp            @exitFuel 
          
@setStatus3          
          ldx            #3
          stx            statusFuel

Status 3

Este status no hace nada, ni me molesto en poner codigo, el sprite se queda en el piso hasta que, por detección de colisiones, lo agarre alguien o lo destruyan de un tiro.

Status 4

A este status se llega desde la detección de colisiones (que lo explicaré en la próxima entrega). Básicamente reinicializa el contador fuelCounter, apaga el sprite y pone el status en 0, para que comience nuevamente todo.

@status4                
          ;reinicializa statusFuel a 0
          ldx            #0        
          stx            statusFuel

          ; inicializa fuelCounter con el valor de delayEntreFuels
          ldx            #delayEntreFuels 
          stx            fuelCounter

          ; apago sprite 4
          lda            spractive 
          and            #255 - FUEL
          sta            spractive 

Y no me tengo que olvidar de inicializar algunas de las variables previamente definidas, en initVars.asm

          ldx            #0        
          stx            statusFuel
          
          ldx            #delayEntreFuels
          stx            fuelCounter

Y con esto ya estamos…
En la próxima entrega vamos a finalizar esta parte de las recargas, vamos a editar el detectCollision.asm para que detecte cuando un jugador agarra el combustible, o cuando lo destruyen.

Como siempre, el codigo completo lo pueden bajar desde el repositorio:
https://github.com/moonorongo/jp_wars.git
Hasta la próxima!

Anuncios

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