Recargas de combustible – parte 2 #Mauro Cifuentes

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!



Editar

Josepzin

No hay comentarios:

Publicar un comentario