Skip to content

DEZ80: Nivel 3

Juan Gonzalez-Gomez edited this page Oct 9, 2021 · 132 revisions

Índice

Introducción

Nivel 3: Práctica

Vídeo 3.P01: Introducción al nivel 3

Click to see the youtube video

Introducción a todo lo que se va a ver en este segundo nivel

Vídeo 3.P02: RETO: Ensambla con WinApe

Click to see the youtube video

  • Reto 1.1: 4 primeros pixeles, en ensamblador
  • Reto 1.2: Vagoneta de 8x8 píxeles, en la línea 12 de caracteres. Se debe poder dibujar en cualquier parte de la fila
  • Reto 1.3: Crear rail. Tile de 4x4 píxeles. Bonus: Patrones

Vídeo 3.P03: EJEMPLO: Reto 1.1

Click to see the youtube video

Reto 1.1: Pintar píxeles en ensamblador

  • Pintar 4 píxeles rojos, en ensamblador. En la fila 1, posición 1
; Reto 1.1: Pintar 4 pixeles rojos

org #4000
run #4000

;; Al almacenar #FF en la memoria de video se 
;; pintan 4 pixeles rojos
;; La memoria de video comienza en #C000

ld a, #FF
ld (#C000), a

;; Terminar (Bucle infinito)
jr $
  • Resultado:

Ejemplo: Relleno de la memoria de video

Se rellena la memoria de vídeo con el valor 0xFF, que hace que se pongan todos los píxeles rojos

;; Rellenar toda la memoria de video

org #4000
run #4000

ld hl, #C000  ;; Primera direccion de la memoria de video

ld b,#45
repetir2:

ld a,#F0  ;; Contador: posiciones a rellenar
repetir:

  ;--- Pintar 4 pixeles ojos
  ld (hl), #FF

  inc hl ;-- Apuntar a la siguiente posicion
  dec a  ;-- Decrementar contador

  jr nz, repetir

dec b
jr nz, repetir2
  
;; Terminar (Bucle infinito)
jr $
  • Resultado:

Reto 1.2: Vagoneta de 8x8

  • Este es el sprite a hacer:

;; Reto 1.2: Sprite de la vagoneta  

org #4000
run #4000

;;-- Fila 12. Posicion 1: #C410

;-- Dibujar 8x4 pixeles izquierdos
ld hl,#C420
ld (hl), #88

ld h,#CC
ld (hl), #F8

ld h,#D4
ld (hl), #FE

ld h, #DC
ld (hl), #FF

ld h, #E4
ld (hl), #BB

ld h, #EC
ld (hl), #15

ld h, #F4
ld (hl), #4A

ld h, #FC
ld (hl), #04

;;-- Dibujar 8x4 pixeles derechos

inc hl

ld h,#C4
ld (hl), #11

ld h,#CC
ld (hl), #F1

ld h,#D4
ld (hl), #F7

ld h, #DC
ld (hl), #FF

ld h, #E4
ld (hl), #DD

ld h, #EC
ld (hl), #8A

ld h, #F4
ld (hl), #25

ld h, #FC
ld (hl), #02


;--- Terminar
jr $
  • Resultado:

Reto 1.3: Rail

  • Esta es la baldosa (tile) para el rail

;; Reto 1.3: Suelo de tiles  

org #4000
run #4000

;-- Dibujar Vagoneta
ld hl,#C410
ld (hl), #88

ld h,#CC
ld (hl), #F8

ld h,#D4
ld (hl), #FE

ld h, #DC
ld (hl), #FF

ld h, #E4
ld (hl), #BB

ld h, #EC
ld (hl), #15

ld h, #F4
ld (hl), #4A

ld h, #FC
ld (hl), #04

inc hl

ld h,#C4
ld (hl), #11

ld h,#CC
ld (hl), #F1

ld h,#D4
ld (hl), #F7

ld h, #DC
ld (hl), #FF

ld h, #E4
ld (hl), #DD

ld h, #EC
ld (hl), #8A

ld h, #F4
ld (hl), #25

ld h, #FC
ld (hl), #02

;;-- Dibujar el rail

ld a, #50  ;; Contador para repeticion

ld l, #60  ;; Posicion inicial

repetir:
  ld h, #c4
  ld (hl), #5F

  ld h,#CC
  ld (hl), #40

  ld h, #D4
  ld (hl), #60

  ld h, #DC
  ld (hl), #50

  inc hl
  dec a
  jr nz, repetir

;--- Terminar
jr $
  • Resultado:

Bonus: Patrones

  • Dibujar el suelo con un patrón de tiles...
;; Reto 1.3: Suelo de tiles  (BONUS: Patrones)

org #4000
run #4000

;-- Dibujar Vagoneta
ld hl,#C410
ld (hl), #88

ld h,#CC
ld (hl), #F8

ld h,#D4
ld (hl), #FE

ld h, #DC
ld (hl), #FF

ld h, #E4
ld (hl), #BB

ld h, #EC
ld (hl), #15

ld h, #F4
ld (hl), #4A

ld h, #FC
ld (hl), #04

inc hl

ld h,#C4
ld (hl), #11

ld h,#CC
ld (hl), #F1

ld h,#D4
ld (hl), #F7

ld h, #DC
ld (hl), #FF

ld h, #E4
ld (hl), #DD

ld h, #EC
ld (hl), #8A

ld h, #F4
ld (hl), #25

ld h, #FC
ld (hl), #02

;;-- Dibujar el rail

ld l, #60  ;; Posicion inicial

ld b,#8  ;;-- Contador para repetir patron

patron:
  ld a, #9  ;; Contador para repeticion

repetir:
  ;;-- Dibujar rail normal
  ld h, #c4
  ld (hl), #5F

  ld h,#CC
  ld (hl), #40

  ld h, #D4
  ld (hl), #60

  ld h, #DC
  ld (hl), #50

  inc hl
  dec a
  jr nz, repetir

;;-- Dibujar rail roto
ld h,#c4
ld (hl), #00

ld h,#00
ld (hl), #04

ld h, #D4
ld (hl), #06

ld h, #DC
ld (hl), #05

inc hl
dec b
jr nz, patron


;--- Terminar
jr $

Vídeo 3.P04: PRACTICA: Animación de movimiento

Click to see the youtube video

  • Sprite de la bola:

;; Video 3.P04
;; Animacion de una bola

org #4000
run #4000

;; Cargar en HL direccion de la memoria de video
ld hl, #C000

repetir:
  ;; Dibujar sprite de la bola
  ;; HL debe apuntar a la primera linea

  ld (hl), %01100000            ; Sprite bola Linea 1

  ld h, #C8                     ; Siguiente linea
  ld (hl), %11110110            ; Linea 2

  ld h, #D0
  ld (hl), %11110110            ; Linea 3

  ld h, #D8
  ld (hl), %01100000            ; Linea 4

  ld h,#C0                      ; HL apunta a la primera linea

;; *** Hacer una pausa **

ld b, 16
wait:
  halt    
  dec b
  jr nz, wait

;;  **** Borrar la bola ***

ld (hl), #00     ; Sprite bola Linea 1

ld h, #C8        ; Siguiente linea
ld (hl), #00     ; Linea 2

ld h, #D0
ld (hl), #00     ; Linea 3

ld h, #D8
ld (hl), #00     ; Linea 4

ld h,#C0         ; HL apunta a la primera linea

;; Avanzar a la siguiente posicion
inc hl

jp repetir

;; Bucle infinito (Terminar)
jr $
  • Resultado:

Vídeo 3.P05: RETO: Usa el teclado

Click to see the youtube video

  • Reto 2.1: Vagoneta se mueve si A=1. Se mueve hasta el centro y termina. Bonus: BuenaFrenada
  • Reto 2.2: Vagoneta parada. Al apretar ESPACIO se mueve a la derecha y se para. Bonus: SuperVeloz
  • Reto 2.3: R para resetear. Rutinas de dibujado. Bonus: TeclasVariables

Reto 2.1: Vagoneta (I)

Se han utilizado rutinas, para luego poder reutilizar el código en otros retos:

  • Programa completo:
;; Reto 2.1: Vagoneta en movimiento
;; La vagoneta se mueve si A=1
;; Se mueve hasta el centro
;; Si A=0 permanece parada

org #4000
run inicio

inicio:

;; Dibujar el suelo
call dibujar_suelo

;; Dibujar vagoneta en posicion inicial
ld hl, #C410
call dibujar_vagoneta

;; Asignar un valor a A
ld a, 1  ;;  1=Se mueve. 0=Se queda parada


;;-- Comprobar el valor de A
dec a
jr nz, parar   ; Si A-1 !=0, terminar (vagoneta parada)

;;-- A vale 1. Animar vagoneta!
call animar_vagoneta

parar:

;; Terminar (bucle infinito)
jr $



;;-------------------------------------------------------------
;; Animar la vagoneta
;;
;; ENTRADAS:
;;   HL: Posicion inicial (donde esta la vagoneta)
;;
;; MODIFICA
;;  B, 
;;-------------------------------------------------------------
animar_vagoneta:

  ;;-- Contador de repeticiones
  ld a, #28

  ;;-- Bucle de animacion
  next_pos:

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Incrementar la posicion
    inc hl

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Esperar
    ld b, #6
    call wait

    ;;-- Una posicion menos
    dec a
    jr nz, next_pos

    ;;-- Vagoneta ha finalizado el recorrido
  ret

;;-------------------------------------------------------------
;; Dibujar Vagoneta en posicion dada en HL
;; 
;; ENTRADAS:
;;   HL: Posicion de la vagoneta
;;
;; MODIFICA:
;; -
;;--------------------------------------------------------------
dibujar_vagoneta:

  ;;-- Fila 1
  ld (hl), #88  ;-- Izquierda
  inc hl
  ld (hl), #11  ;-- Derecha

  ;;-- Fila 2
  ld h,#CC
  ld (hl),#F1  ;-- Derecha
  dec hl
  ld (hl),#F8 ; -- Izquierda
  
  ;;-- Fila 3
  ld h, #D4
  ld (hl), #FE  ;-- Izquierda
  inc hl
  ld (hl), #F7  ;-- Derecha

  ;;-- Fila 4
  ld h, #DC
  ld (hl), #FF  ;-- Derecha
  dec hl
  ld (hl), #FF  ;-- Izquierda

  ;;-- Fila 5
  ld h, #E4
  ld (hl), #BB  ;-- Izquierda
  inc hl
  ld (hl), #DD ;-- Derecha

  ;;-- Fila 6
  ld h, #EC
  ld (hl), #8A  ;-- Derecha
  dec hl
  ld (hl), #15  ;-- Izquierda

  ;;-- Fila 7
  ld h, #F4  ;-- Izquierda
  ld (hl), #4A
  inc hl
  ld (hl), #25  ;-- Derecha
  
  ;;-- Fila 8
  ld h, #FC  ;-- Derecha
  ld (hl), #02
  dec hl
  ld (hl), #04 ;-- Izquierda

  ;;-- Establecer la posicion de partida en HL
  ld h, #C4   
  ret

;;-------------------------------------------------------------
;; Rutina de pausa
;;
;; ENTRADAS:
;;   B: Unidades a pausar (1 unidad = 3.3ms aprox)
;;
;; MODIFICA
;;  -
;;-------------------------------------------------------------
wait:

  halt
  dec b
  jr nz, wait

  ret

;;-----------------------------------------------------------
;; Borrar el sprite 8x8 situado en la posicion dada
;; por HL
;;
;; ENTRADAS: 
;;   HL: Posicion donde borrar
;;
;; MODIFICA:
;; -
;;------------------------------------------------------------
borrar_sprite_8x8:

   ;;-- Fila 1
  ld (hl), #00  ;-- Izquierda
  inc hl
  ld (hl), #00  ;-- Derecha

  ;;-- Fila 2
  ld h,#CC
  ld (hl),#00  ;-- Derecha
  dec hl
  ld (hl),#00 ; -- Izquierda
  
  ;;-- Fila 3
  ld h, #D4
  ld (hl), #00  ;-- Izquierda
  inc hl
  ld (hl), #00  ;-- Derecha

  ;;-- Fila 4
  ld h, #DC
  ld (hl), #00  ;-- Derecha
  dec hl
  ld (hl), #00  ;-- Izquierda

  ;;-- Fila 5
  ld h, #E4
  ld (hl), #00  ;-- Izquierda
  inc hl
  ld (hl), #00 ;-- Derecha

  ;;-- Fila 6
  ld h, #EC
  ld (hl), #00  ;-- Derecha
  dec hl
  ld (hl), #00  ;-- Izquierda

  ;;-- Fila 7
  ld h, #F4  ;-- Izquierda
  ld (hl), #00
  inc hl
  ld (hl), #00  ;-- Derecha
  
  ;;-- Fila 8
  ld h, #FC  ;-- Derecha
  ld (hl), #00
  dec hl
  ld (hl), #00 ;-- Izquierda

  ;;-- Establecer la posicion de partida en HL
  ld h, #C4   
  ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibujar el suelo. Esta compuesto por 160 
;; tiles de suelo
;;
;; ENTRADAS:
;;  Ninguna
;;
;; MODIFICA:
;; -HL, B
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibujar_suelo:

  ld hl, #C460  ;; Posicion inicial del suelo

  ld b, #50  ;; Numero de tiles a colocar

  next_tile:
    call dibujar_tile_suelo ;; Dibujar una baldosa
    inc hl  ;; Poner la proxima en la derecha
    dec b   ;; Queda una menos
    jr nz, next_tile  ;; Repetir si todavia quedan tiles por poner

  ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibujar el Tile del suelo en la fila 12
;; ENTRADAS:
;;   HL: Contiene la posicion donde dibujar el tile
;; MODIFICA:
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibujar_tile_suelo:

  
  ld (hl), #5F ;; Fila 1

  ld h,#CC    ;; Fila 2
  ld (hl), #40

  ld h, #D4   ;;  Fila 3
  ld (hl), #60

  ld h, #DC   ;; Fila 4
  ld (hl), #50

  ld h, #c4  ;; Posicionar de vuelta en la fila 1
  ret

Cuando A vale 1, este es el resultado: (La vagoneta se mueve)

Cuando A vale 0 la vagoneta permanece en reposo:

Bonus: BuenaFrenada

  • Cuando la vagoneta alcance una determinada posición, deberá ir frenando hasta alcanzar la posición final

  • Algoritmo:

    • Rutina de animación normal hasta la posicion 0x28-x (en vez de hasta 0x28)
    • Otra rutina de animación con frenada,en la que en cada pasada del bucle se incrementa el retardo (Se realiza x veces)
  • Programa completo: reto-2-1-BuenaFrenada.asm

  • Rutina: wait:

;;-------------------------------------------------------------
;; Rutina de pausa
;;
;; ENTRADAS:
;;   B: Unidades a pausar (1 unidad = 3.3ms aprox)
;;
;; MODIFICA
;;  -
;;-------------------------------------------------------------
wait:

  halt
  dec b
  jr nz, wait

  ret
  • Rutina: animacion_vagoneta2: Anima la vagoneta desde el extremo izquierdo hasta la posición 29 (0x1D)
;;-------------------------------------------------------------
;; Animar la vagoneta
;;
;; ENTRADAS:
;;   HL: Posicion inicial (donde esta la vagoneta)
;;
;; MODIFICA
;;  B, A
;;-------------------------------------------------------------
animar_vagoneta2:

  ;;-- Contador de repeticiones
  ld a, #1D

  ;;-- Bucle de animacion
  next_pos:

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Incrementar la posicion
    inc hl

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Esperar
    ld b, #8
    call wait

    ;;-- Una posicion menos
    dec a
    jr nz, next_pos

    ;;-- Vagoneta ha finalizado el recorrido
  ret
  • Rutina: animar_vagoneta_freno:
;;------------------------------------------------------------------
;; Animar la vagoneta con frenada
;;
;; ENTRADAS:
;;  HL: Posicion actual
;;
;; MODIFICA
;;  A,B
;;--------------------------------------------------------------------
animar_vagoneta_freno:

  ld a, #B  ;;-- Posiciones a avanzar con frenada
  ld c,#8   ;;-- Retardo inicial

  ;;-- Bucle de animacion
  next_pos_freno:
    
  ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Incrementar la posicion
    inc hl

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Ahora el retardo es variable
    ;;-- Se va incrementando
    ld b,c
    call wait

    inc c
    inc c
    inc c
    inc c
    inc c

    ;;-- Una posicion menos
    dec a
    jr nz, next_pos_freno

  ret
  • Programa principal: main:
inicio:

;; Dibujar el suelo
call dibujar_suelo

;; Dibujar vagoneta en posicion inicial
ld hl, #C410
call dibujar_vagoneta

;; Asignar un valor a A
ld a, 1  ;;  1=Se mueve. 0=Se queda parada


;;-- Comprobar el valor de A
dec a
jr nz, parar   ; Si A-1 !=0, terminar (vagoneta parada)

;;-- A vale 1. Animar vagoneta!
call animar_vagoneta2
call animar_vagoneta_freno

parar:

;; Terminar (bucle infinito)
jr $
  • Resultado:

Reto 2.2: Vagoneta y teclas

  • La animación comienza cuando se aprieta la tecla de Espacio

  • Programa final: reto-2.2.asm

Para eliminar las caminonetas que quedan de la última ejecución, y no tener que estar dando al reset, he creado la rutina borrar_vagonetas

  • Rutina: borrar_vagonetas:
;;=====================================
;; Borrar vagonetas. Pintar una linea de 8x8 pixeles de fondo
;; sobre el rail para eliminar vagonetas anteriores
;;
;; MODIFICA:
;;   hl,A
;;=====================================
borrar_vagonetas:
  ld hl, #C410

  ;;-- En la linea hay 40 caracteres
  ld a, 40
  borrar_next:

    ;;-- Borrar la posicion actual
    call borrar_sprite_8x8:

    ;;-- Incrementar hl en 2 para apuntar al siguiente sprinte
    inc hl
    inc hl

    dec a
    jr nz, borrar_next

  ret
  • Programa principal: main:
main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, #C410
  call dibujar_vagoneta

   ;;-- Guardar posicion actual de la vagoneta
   push hl

  comprobar_teclado:

    ;;  Comprobar si se pulsa espacio
     ld a, 47
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

  ;;-- Tecla no pulsada. Repetir
  jr comprobar_teclado

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

   ;;-- Recuperar posicion inicial de la vagoneta
   pop hl

    ;;--  Animar vagoneta!
    call animar_vagoneta

parar:

;; Terminar (bucle infinito)
jr $
  • Resultado: Ahora la vagoneta sólo se mueve al apretar la tecla espacio

Bonus: SuperVeloz

  • En vez de empezar con el espacio, se comienza con las teclas 1-5. La 1 es la velocidad lenta y la 5 la rápida

He modificado la rutina animar_vagoneta para que adminta como parámetro el registro C, que contiene la pausa a realizar en el bucle de animación, controlando así la velocidad

main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, #C410
  call dibujar_vagoneta

   ;;-- Guardar posicion actual de la vagoneta
   push hl

  comprobar_teclado:

    ;;  Comprobar si se pulsa tecla 1
     ld a, 64
     call #BB1E
     jr nz, tecla_1_pulsada  ;; Tecla 1 : Velocidad lenta

    ;;-- Tecla 2?
    ld a, 65
    call #BB1E
    jr nz, tecla_2_pulsada

    ;;-- Tecla 3??
    ld a,57
    call #BB1E
    jr nz, tecla_3_pulsada

    ;;-- Tecla 4??
    ld a,56
    call #BB1E
    jr nz, tecla_4_pulsada   

    ;;-- Tecla 4??
    ld a,49
    call #BB1E
    jr nz, tecla_4_pulsada
   
    ;;-- Tecla 5??
    ld a,48
    call #BB1E
    jr nz, tecla_5_pulsada 


  ;;-- Tecla no pulsada. Repetir
  jr comprobar_teclado

  ;;-- Tecla 1: Velocidad lenta
tecla_1_pulsada:
  ld c,#40    ;;-- Establecer pausa
  jr animar   

tecla_2_pulsada:
  ld c, #30
  jr animar

tecla_3_pulsada:
  ld c, #20
  jr animar

tecla_4_pulsada:
  ld c, #10
  jr animar

tecla_5_pulsada:
  ld c, #6

animar:   
   ;;-- Recuperar posicion inicial de la vagoneta
   pop hl

    ;;--  Animar vagoneta!
    call animar_vagoneta

parar:

;; Terminar (bucle infinito)
jr $
  • Resultado final, cuando se aprieta la tecla 1 (lento):

  • Resultado final, cuando se aprieta la tecla 5 (rápido):

Reto 2.3: Vagoneta (II)

Igual que reto 2.2, pero ahora cuando la vagoneta llega al final y se para, se vuelve a comenzar si se pulsa la tecla R (de reset)

  • Programa principal:
main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, #C410
  call dibujar_vagoneta

   ;;-- Guardar posicion actual de la vagoneta
   push hl

  comprobar_teclado:

    ;;  Comprobar si se pulsa espacio
     ld a, 47
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

  ;;-- Tecla no pulsada. Repetir
  jr comprobar_teclado

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

   ;;-- Recuperar posicion inicial de la vagoneta
   pop hl

    ;;--  Animar vagoneta!
    call animar_vagoneta

parar:

  ;; Comprobar el teclado
  ld a, 50
  call #BB1E
  jr nz, tecla_r_pulsada

  ;;-- Esperar a que se pulse tecla R
  jr parar

  tecla_r_pulsada:
    jr main
  • Resultado:

Bonus: TeclasVariables

  • Las teclas para mover la vagoneta y reiniciarla se deben poder redefinir en unas variables, de forma que cambiando su valor se eligen otras teclas

  • Programa principal:

org #4000
run main


;;==============================
;; VARIABLES
;;==============================
tecla_start:
  db 18   ;;-- 47:Spacio

tecla_reset:
  db 79  ;;-- 50: Tecla R

main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, #C410
  call dibujar_vagoneta

   ;;-- Guardar posicion actual de la vagoneta
   push hl

  comprobar_teclado:

    ;;  Comprobar si se pulsa espacio
     ld a, (tecla_start)
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

  ;;-- Tecla no pulsada. Repetir
  jr comprobar_teclado

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

   ;;-- Recuperar posicion inicial de la vagoneta
   pop hl

    ;;--  Animar vagoneta!
    call animar_vagoneta

parar:

  ;; Comprobar el teclado
  ld a, (tecla_reset)
  call #BB1E
  jr nz, tecla_r_pulsada

  ;;-- Esperar a que se pulse tecla R
  jr parar

  tecla_r_pulsada:
    jr main

Video 3.P06: PRACTICA: Saltos condicionales (II)

Click to see the youtube video

Dibujar un dado por la cara que se indique en el registro A

org #4000

run inicio

inicio:

ld a,2  ;;-- Numero de cara a dibujar
call dibuja_cara_A  ;;-- Dibujar la cara indicaa en A
jr $


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  Dibujar la Cara indicada en el registro A
;;
;;  ENTRADA:
;;    A: Numero de cara a dibujar (1-6)
;;  MODIFICA:
;;    HL, A
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_A:

  ld hl, #C000  ;; Posicion donde dibujar la cara

  dec a           ;; Restar 1 a A
  jr z, era_un_1  ;-- Si A-1 = 0,entonces saltar

  ;;-- Comprobar si es 2
  dec a           ;;-- Restar 1 a A
  jr z, era_un_2  ; Si A-2 = 0, saltar

 ;;-- Es > 2
 ;; Comprobar si es 3
 dec a           ;; Restar 1 a A
 jr z, era_un_3  ; Si A-3 = 0, saltar

  ;; Es > 3
  ;; Comprobar si es 4
  dec a
  jr z, era_un_4

 ;; Es > 4
 ;; Comprobar si es 5
  dec a
  jr z, era_un_5

  call dibuja_cara_6
  jr fin

  era_un_5:
    call dibuja_cara_5
    jr fin

 era_un_4:
  call dibuja_cara_4
  jr fin

 era_un_3:
   call dibuja_cara_3
   jr fin

 era_un_2:
  call dibuja_cara_2
  jr fin

  era_un_1:
    call dibuja_cara_1

fin:
  ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibuja un dado mostrando la cara 1, en la posicion 
;; en que se encuentra HL, asumiendo que esta en 
;; la primera fila de caracteres de pantalla (C000-C04A)
;; ENTRADA:
;;  HL: Posicion donde dibujar el dado
;; MODIFICA
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_1:

  ld (hl), #F0   ;; 4 Pixeles a la izquierda
  inc hl          ;; +1 Avanzar a la derecha
  ld (hl), #E0  ;; 4 Pixeles derecha
  ld h, #C8    ;; Bajar a fila 2

  ;; Fila 2
  ld (hl), #E0
  dec hl        ;;  -1 Retroceder a la izquierda
  ld (hl), #F0
  ld h, #D0  ; Bajar a fila 3

  ;; Fila 3
  ld (hl), #F3
  inc hl
  ld (hl), #E8
  ld h, #D8  ; Bajar a fila 4

  ;; Fila 4
  ld (hl), #E8
  dec hl
  ld (hl), #F3
  ld h, #E0  ; Bajar a fila 5

  ;; Fila 5
  ld (hl), #F3
  inc hl
  ld (hl), #E8 
  ld h, #E8  ; Bajar a fila 6

  ;; Fila 6
  ld (hl), #E0
  dec hl
  ld (hl), #F0
  ld h, #F0  ; Bajar a fila 7

  ;; Fila 7
  ld (hl), #F0
  inc hl
  ld (hl), #E0
  ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibuja un dado mostrando la cara 2
;; ENTRADA:
;;  HL: Posicion donde dibujar el dado
;; MODIFICA
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_2:

ld (hl), #F0   ;; 4 Pixeles a la izquierda
inc hl          ;; +1 Avanzar a la derecha
ld (hl), #E0  ;; 4 Pixeles derecha
ld h, #C8    ;; Bajar a fila 2
ld (hl), #E0
dec hl        ;;  Retroceder a la izquierda
ld (hl), #F0
ld h, #D0  ; Bajar a fila 3
ld (hl), #F6
inc hl
ld (hl), #EC
ld h, #D8  ; Bajar a fila 4
ld (hl), #EC
dec hl
ld (hl), #F6
ld h, #E0  ; Bajar a fila 5
ld (hl), #F6
inc hl
ld (hl), #EC 
ld h, #E8  ; Bajar a fila 6
ld (hl), #E0
dec hl
ld (hl), #F0
ld h, #F0  ; Bajar a fila 7
ld (hl), #F0
inc hl
ld (hl), #E0
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibuja un dado mostrando la cara 3
;; ENTRADA:
;;  HL: Posicion donde dibujar el dado
;; MODIFICA
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_3:

ld (hl), #F0   ;; 4 Pixeles a la izquierda
inc hl          ;; +1 Avanzar a la derecha
ld (hl), #E0  ;; 4 Pixeles derecha
ld h, #C8    ;; Bajar a fila 2
ld (hl), #EC
dec hl        ;;  Retroceder a la izquierda
ld (hl), #F6
ld h, #D0  ; Bajar a fila 3
ld (hl), #F6
inc hl
ld (hl), #EC
ld h, #D8  ; Bajar a fila 4
ld (hl), #E0
dec hl
ld (hl), #F0
ld h, #E0  ; Bajar a fila 5
ld (hl), #F1
inc hl
ld (hl), #E8 
ld h, #E8  ; Bajar a fila 6
ld (hl), #E8
dec hl
ld (hl), #F1
ld h, #F0  ; Bajar a fila 7
ld (hl), #F0
inc hl
ld (hl), #E0
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibuja un dado mostrando la cara 4
;; ENTRADA:
;;  HL: Posicion donde dibujar el dado
;; MODIFICA
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_4:

ld (hl), #F0   ;; 4 Pixeles a la izquierda
inc hl          ;; +1 Avanzar a la derecha
ld (hl), #E0  ;; 4 Pixeles derecha
ld h, #C8    ;; Bajar a fila 2
ld (hl), #EC
dec hl        ;;  Retroceder a la izquierda
ld (hl), #F6
ld h, #D0  ; Bajar a fila 3
ld (hl), #F6
inc hl
ld (hl), #EC
ld h, #D8  ; Bajar a fila 4
ld (hl), #E0
dec hl
ld (hl), #F0
ld h, #E0  ; Bajar a fila 5
ld (hl), #F6
inc hl
ld (hl), #EC 
ld h, #E8  ; Bajar a fila 6
ld (hl), #EC
dec hl
ld (hl), #F6
ld h, #F0  ; Bajar a fila 7
ld (hl), #F0
inc hl
ld (hl), #E0
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibuja un dado mostrando la cara 5
;; ENTRADA:
;;  HL: Posicion donde dibujar el dado
;; MODIFICA
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_5:

ld (hl), #F0   ;; 4 Pixeles a la izquierda
inc hl          ;; +1 Avanzar a la derecha
ld (hl), #E0  ;; 4 Pixeles derecha
ld h, #C8    ;; Bajar a fila 2
ld (hl), #EC
dec hl        ;;  Retroceder a la izquierda
ld (hl), #F6
ld h, #D0  ; Bajar a fila 3
ld (hl), #F0
inc hl
ld (hl), #E0
ld h, #D8  ; Bajar a fila 4
ld (hl), #E8
dec hl
ld (hl), #F1
ld h, #E0  ; Bajar a fila 5
ld (hl), #F0
inc hl
ld (hl), #E0 
ld h, #E8  ; Bajar a fila 6
ld (hl), #EC
dec hl
ld (hl), #F6
ld h, #F0  ; Bajar a fila 7
ld (hl), #F0
inc hl
ld (hl), #E0
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibuja un dado mostrando la cara 6
;; ENTRADA:
;;  HL: Posicion donde dibujar el dado
;; MODIFICA
;;  -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibuja_cara_6:

ld (hl), #F0   ;; 4 Pixeles a la izquierda
inc hl          ;; +1 Avanzar a la derecha
ld (hl), #E0  ;; 4 Pixeles derecha
ld h, #C8    ;; Bajar a fila 2
ld (hl), #EC
dec hl        ;;  Retroceder a la izquierda
ld (hl), #F6
ld h, #D0  ; Bajar a fila 3
ld (hl), #F0
inc hl
ld (hl), #E0
ld h, #D8  ; Bajar a fila 4
ld (hl), #EC
dec hl
ld (hl), #F6
ld h, #E0  ; Bajar a fila 5
ld (hl), #F0
inc hl
ld (hl), #E0 
ld h, #E8  ; Bajar a fila 6
ld (hl), #EC
dec hl
ld (hl), #F6
ld h, #F0  ; Bajar a fila 7
ld (hl), #F0
inc hl
ld (hl), #E0
ret
  • Resultado:

Video 3.P07: PRACTICA: Pulsaciones de teclado

Click to see the youtube video

  • Códigos de las teclas

Al apretar la tecla de espacio se dibujan 4 píxeles rojos. Al soltarla se borran

org #4000

run inicio

inicio:

   ;;  Comprobar si se pulsa espacio
   ld a, 47
   call #BB1E
   jr nz, pulsada  ;  Si Z no activo (tecla pulsada), saltar a pulsada

     ;; No pulsada
     ;; Borrar la vagoneta
     ld hl, #C000
     call borrar_8x8   ;;  Dibuja un cuadrado 8x8 color fondo
     jr continuar      ;;-- Continuar la ejecucion

pulsada:
   ;; Dibujar vagoneta
   ld hl, #C000
   call dibujar_vagoneta

continuar:

  jr inicio


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  Borrar los pixeles
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
borrar_8x8:
  ld (hl), 00
  ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dibujar los pixeles
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dibujar_vagoneta:
  ld (hl), #FF
  ret
  • Resultado:

Video 3.P08: PRACTICA: Usando variables

Click to see the youtube video

Video 3.P09: RETO: Primer minijuego

Click to see the youtube video

  • Reto 3.1: Barril 4x8 al final. Bonus: Posición variable
  • Reto 3.2: Barriles hasta el final
  • Reto 3.3: Espacio para Frenar
  • Reto 3.4: Explosion al chocar

Reto 3.1: Barril 4x8

  • Sprite del Barril:

  • Rutina: dibujar_barril
;;========================================
;; Dibujar barril
;;
;; ENTRADA:
;;   HL: Posicion del barril en memoria de video
;;
;; MODIFICA:
;;
;;========================================
dibujar_barril:

   ;;-- Fila 1
  ld (hl), #99

  ;;-- Fila 2
  ld h,#CC
  ld (hl),#6F
  
  ;;-- Fila 3
  ld h, #D4
  ld (hl), #9F  

  ;;-- Fila 4
  ld h, #DC
  ld (hl), #FF  

  ;;-- Fila 5
  ld h, #E4
  ld (hl), #6F

  ;;-- Fila 6
  ld h, #EC
  ld (hl), #9F  

  ;;-- Fila 7
  ld h, #F4 
  ld (hl), #F6
  
  ;;-- Fila 8
  ld h, #FC
  ld (hl), #60

  ;;-- Establecer la posicion de partida en HL
  ld h, #C4   
  ret
  • Programa principal:
;;==============================
;; VARIABLES
;;==============================
tecla_start:
  db 47   ;;-- 47:Spacio

tecla_reset:
  db 50  ;;-- 50: Tecla R

vagoneta_home:
  dw #C410

barril_home:
  dw #C43A

main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, (vagoneta_home)
  call dibujar_vagoneta

  ;; Dibujar el barril
  ld hl, (barril_home)
  call dibujar_barril

  comprobar_teclado:

    ;;  Comprobar si se pulsa espacio
     ld a, (tecla_start)
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

  ;;-- Tecla no pulsada. Repetir
  jr comprobar_teclado

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

   ;;-- Recuperar posicion inicial de la vagoneta
   ld hl, (vagoneta_home)

    ;;--  Animar vagoneta!
    call animar_vagoneta

parar:

  ;; Comprobar el teclado
  ld a, (tecla_reset)
  call #BB1E
  jr nz, tecla_r_pulsada

  ;;-- Esperar a que se pulse tecla R
  jr parar

  tecla_r_pulsada:
    jr main
  • Resultado:

Bonus: PosicionVariable

  • Programa principal:
;;==============================
;; VARIABLES
;;==============================
tecla_start:
  db 47   ;;-- 47:Spacio

tecla_reset:
  db 50  ;;-- 50: Tecla R

vagoneta_home:
  dw #C410

;;-- Direccion de memoria donde colocar barril
barril_home:
  dw #0000

;;-- Posicion del barril en la fila
x_inicio:
  db #30

main:

  ;; Calcular la posicion del barril
  ;; barril_home = #C410 + x_inicio
  ld hl,#C410
  ld a, (x_inicio)
  add l  ;; A = x_inicio + L
  ld l,a  ;; L = x_inicio + L
  ld (barril_home), hl

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, (vagoneta_home)
  call dibujar_vagoneta

  ;; Dibujar el barril
  ld hl, (barril_home)
  call dibujar_barril

  comprobar_teclado:

    ;;  Comprobar si se pulsa espacio
     ld a, (tecla_start)
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

  ;;-- Tecla no pulsada. Repetir
  jr comprobar_teclado

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

   ;;-- Recuperar posicion inicial de la vagoneta
   ld hl, (vagoneta_home)

    ;;--  Animar vagoneta!
    call animar_vagoneta

parar:

  ;; Comprobar el teclado
  ld a, (tecla_reset)
  call #BB1E
  jr nz, tecla_r_pulsada

  ;;-- Esperar a que se pulse tecla R
  jr parar

  tecla_r_pulsada:
    jr main
  • Resultado: Barril colocado en posición 0x30

Reto 3.2: Barriles hasta el final

  • Rutina: dibujar_barriles
;;========================================
;; Dibujar barriles
;; 
;; MODIFICA:
;;  HL, A
;;========================================
dibujar_barriles:

   ;;-- Obtener posicion inicial en memoria de video
   ld hl, (barril_home)

   ;;-- Contador de barriles
   ld a, #13

   dibujar_sig_barril:

     ;; Dibujar un barril
     call dibujar_barril

     ;; Apuntar a la siguiente posicion
     inc hl
     inc hl

     ;;-- Un barril menos por dibujar
     dec a
     jr nz, dibujar_sig_barril

  ret

En el programa principal simplemente se llama a dibujar barriles:

main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, (vagoneta_home)
  call dibujar_vagoneta

  ;;-- Dibujar los barriles
  call dibujar_barriles
...
...
  • Resultado:

Reto 3.3: Espacio para frenar

  • Este es el programa principal:
;;==============================
;; VARIABLES
;;==============================
tecla_start:
  db 47   ;;-- 47:Spacio

tecla_reset:
  db 50  ;;-- 50: Tecla R

vagoneta_home:
  dw #C410

barril_home:
  dw #C43A

;;-- Posicion final de la vagoneta
pos_vagoneta:
  db #28

;;-- Posicion de la vagoneta en la memoria de video
pos_vagoneta_video:
  dw 00

;;========
;; MAIN
;;========
main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, (vagoneta_home)
  call dibujar_vagoneta

  ;;-- Dibujar los barriles
  call dibujar_barriles

  ;;-- Inicializar variables
  ld a,#28
  ld (pos_vagoneta), a  ;;-- Posicion inicial vagoneta
  ld hl, (vagoneta_home)
  ld (pos_vagoneta_video), hl ;;-- Posicion vagoneta en memoria video

  ;;-- Espera incial
  ld b, #80
  call wait

 
  ;;--  Animar vagoneta!

  ;;-- Bucle de animacion
  next_pos:

    ;;-- Recuperar posicion inicial de la vagoneta
    ld hl, (pos_vagoneta_video)

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Incrementar la posicion
    inc hl

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Guardar la posicion de la vagoneta
    ld (pos_vagoneta_video), hl

    ;;-- Esperar
    ld b, #6
    call wait

    ;;-- Comprobar el teclado
     ld a, (tecla_start)
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

    ;;-- Una posicion menos
    ld a, (pos_vagoneta)
    dec a
    ld (pos_vagoneta),a
    
    jr nz, next_pos

    ;;-- Vagoneta ha finalizado el recorrido (HAS PERDIDO!!!!)
    

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

parar:

  ;; Comprobar el teclado
  ld a, (tecla_reset)
  call #BB1E
  jr nz, tecla_r_pulsada

  ;;-- Esperar a que se pulse tecla R
  jr parar

  tecla_r_pulsada:
    jr main
  • Resultado:

Reto 3.4: Explosión al chocar

  • Sprites de la explosión:

Desde el programa principal se llama a la rutina animacion_explosion:

  • Programa principal
;;========
;; MAIN
;;========
main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, (vagoneta_home)
  call dibujar_vagoneta

  ;;-- Dibujar los barriles
  call dibujar_barriles

  ;;-- Inicializar variables
  ld a,#28
  ld (pos_vagoneta), a  ;;-- Posicion inicial vagoneta
  ld hl, (vagoneta_home)
  ld (pos_vagoneta_video), hl ;;-- Posicion vagoneta en memoria video

  ;;-- Espera incial
  ld b, #80
  call wait

 
  ;;--  Animar vagoneta!

  ;;-- Bucle de animacion
  next_pos:

    ;;-- Recuperar posicion de la vagoneta
    ld hl, (pos_vagoneta_video)

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Incrementar la posicion
    inc hl

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Guardar la posicion de la vagoneta
    ld (pos_vagoneta_video), hl

    ;;-- Esperar
    ld b, #6
    call wait

    ;;-- Comprobar el teclado
     ld a, (tecla_start)
     call #BB1E
     jr nz, espacio_pulsado  ;  Si Z no activo (tecla pulsada), saltar a pulsada

    ;;-- Una posicion menos
    ld a, (pos_vagoneta)
    dec a
    ld (pos_vagoneta),a
    
    jr nz, next_pos

    ;;-- Recuperar posicion de la vagoneta
    ld hl, (pos_vagoneta_video)

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    inc hl

    ;;-- Vagoneta ha finalizado el recorrido (HAS PERDIDO!!!!)
    call animacion_explosion

  ;;-- Espacio pulsado! Animar vagoneta
  espacio_pulsado:

parar:

  ;; Comprobar el teclado
  ld a, (tecla_reset)
  call #BB1E
  jr nz, tecla_r_pulsada

  ;;-- Esperar a que se pulse tecla R
  jr parar

  tecla_r_pulsada:
    jr main

En esta rutina se hace la animación de la explosión. Rutina: animacion_explosion:

;;========================================
;; Animacion explosion
;;
;; ENTRADAS:
;;   HL: posicion memoria video donde dibujar
;;
;; MODIFICA:
;;
;;========================================
animacion_explosion:
  
  ;;-- Fotograma 1
  call dibujar_explosion_1

  ld b,#20
  call wait

  ;;-- Fotograma 2
  call dibujar_explosion_2

  ld b,#20
  call wait

  ;;-- Fotograma 3
  call dibujar_explosion_3

  ld b,#20
  call wait

  ;;-- Fotograma 4 (Blanco)
  call borrar_sprite_8x8

  ret

Esta rutina a su vez llama a las rutinas dibujar_explosion_1, 2 y 3 para dibujar los fotogramas de la explosión

  • Resultado:

Video 3.P10: RETO: Toma el control

Click to see the youtube video

  • Reto 4.1: Mover a la derecha. Rutina mover
  • Reto 4.2: Mover a la izquierda. Rutina Teclado
  • Reto 4.3: Colisión lado izquierdo
  • Reto 4.4: Colision con barriles

Reto 4.1: Mover a la derecha

  • Mientras P esté pulsada, la vagoneta se mueve a la derecha. Al soltar la tecla se para. Rutina de mover que se invoca al pulsar la tecla. Mover con la tecla P. Bonus: LetraVariable

  • Rutina para mover a la derecha:

;;========================================
;; Mover la vagoneta 4 pixeles a la derecha
;;
;; MODIFICA:
;;   HL, B, A
;;========================================
vagoneta_derecha:

    ;;-- Recuperar posicion de la vagoneta
    ld hl, (pos_vagoneta_video)

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Incrementar la posicion
    inc hl

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Guardar la posicion de la vagoneta
    ld (pos_vagoneta_video), hl

    ;;-- Esperar
    ld b, #6
    call wait

    ;;-- Una posicion menos
    ld a, (pos_vagoneta)
    dec a
    ld (pos_vagoneta),a

  ret

El Bonus LetraVariable está también implementado. ESte es el programa principal:

;==============================
;; VARIABLES
;;==============================
tecla_start:
  db 47   ;;-- 47:Spacio

tecla_reset:
  db 50  ;;-- 50: Tecla R

tecla_derecha:
  db  27 ;; Tecla P

vagoneta_home:
  dw #C410

barril_home:
  dw #C43A

;;-- Posicion final de la vagoneta
pos_vagoneta:
  db #28

;;-- Posicion de la vagoneta en la memoria de video
pos_vagoneta_video:
  dw 00

;;========
;; MAIN
;;========
main:

  ;; Borrar vagonetas: Eliminar vagonetas de la ejecucion anterior
  call borrar_vagonetas

  ;; Dibujar el suelo
  call dibujar_suelo

  ;; Dibujar vagoneta en posicion inicial
  ld hl, (vagoneta_home)
  call dibujar_vagoneta

  ;;-- Dibujar los barriles
  call dibujar_barriles

  ;;-- Inicializar variables
  ld a,#28
  ld (pos_vagoneta), a  ;;-- Posicion inicial vagoneta
  ld hl, (vagoneta_home)
  ld (pos_vagoneta_video), hl ;;-- Posicion vagoneta en memoria video

  ;;-- Espera incial
  ld b, #80
  call wait

  ;;-- Bucle principal
  bucle_main:
    
     ;;-- Comprobar tecla ir a la derecha
     ld a, (tecla_derecha)
     call #BB1E
     jr nz, mover_derecha

     ;;-- Comprobar tecla de reinicio
     ld a, (tecla_reset)
     call #BB1E
     jr nz, reiniciar

     jr bucle_main

  ;;-- Reiniciar el juego
  reiniciar:
    ;;-- Saltar al comienzo
    jr main

  ;;-- Mover a la derecha
  mover_derecha:
     call vagoneta_derecha
    
     ;;-- Continuar con el bucle principal
     jr bucle_main
  • Resultado:

Reto 4.2: Mover a la izquierda

  • Mover a la izquierda con la tecla O. Crear una rutina específica de teclado

La rutina de mover a la izquierda es la misma que la de ir a la derecha, pero en vez de incrementar hl, se decrementa
La rutina del teclado es la siguiente:

;;========================================
;;  Rutina de teclado. Comprobar que teclas se han pulsado  
;; y llamar a las rutinas correspondientes
;;========================================
leer_teclas:

     ;;-- Comprobar tecla ir a la derecha
     ld a, (tecla_derecha)
     call #BB1E
     jr nz, mover_derecha

     ;;-- Comprobar tecla ir a la izquierda
     ld a, (tecla_izquierda)
     call #BB1E
     jr nz, mover_izquierda

     ;;-- Comprobar tecla de reinicio
     ld a, (tecla_reset)
     call #BB1E
     jr nz, reiniciar

     ;;-- Terminar
     jr leer_teclas_fin

  ;;-- Reiniciar el juego
  reiniciar:
    or a  ;;-- Poner flag z a 0
    jr leer_teclas_fin

  ;;-- Mover a la izquierda
  mover_izquierda:
    call vagoneta_izquierda
    jr flag_z_set

  ;;-- Mover a la derecha
  mover_derecha:
     call vagoneta_derecha

flag_z_set:
  xor a ;;-- Poner flag z a 1

  ;;-- Fin de la rutina
leer_teclas_fin:

  ret
  • Este es el bucle principal:
;;-- Bucle principal
  bucle_main:
    
     ;;-- Comprobar las teclas pulsadas
     call leer_teclas
     
     ;;-- Saltar al comienzo si el flag z NO esta activado
     ;;-- (Esto ocurre cuando se aprieta la tecla de reset)
     jr nz,main
    
     ;;-- Continuar con el bucle principal
     jr bucle_main
  • Resultado:

Bonus: Paramétrico

Unificar las dos rutinas de movimiento de la vagoneta en una única rutina que reciba como parámetro de entrada el incremento de la posición: +1 (ir a la derecha) y -1 (ir a la izquierda)

  • Rutina mover_vagoneta
;;========================================
;; Mover la vagoneta 4 pixeles a la izquierda o la derecha
;;
;; ENTRADA:
;;   A: Incremento a aplicar:  1 (derecha). -1 (izquierda)
;;
;; MODIFICA:
;;   HL, B, A
;;========================================
mover_vagoneta:

    ;;-- Recuperar posicion de la vagoneta
    ld hl, (pos_vagoneta_video)

    ;;-- Borrar la vagoneta
    call borrar_sprite_8x8

    ;;-- Actualizar la posicion
    ;; hl = hl + a
    add l  ;;-- a = a + l
    ld l,a  ;;-- l = l + a

    ;;-- Dibujar la vagoneta en la nueva posicion
    call dibujar_vagoneta

    ;;-- Guardar la posicion de la vagoneta
    ld (pos_vagoneta_video), hl

    ;;-- Esperar
    ld b, #6
    call wait

    ;;-- Una posicion menos
    ld a, (pos_vagoneta)
    dec a
    ld (pos_vagoneta),a

  ret

Reto 4.3: Colisión lado izquierdo

  • Cuando llega al lado izquierdo no se permite que se siga moviendo, aunque se apriete la tecla

  • La rutina Leer_tecla se modifica para añdir una comparación en la posicion:

...
  ;;-- Mover a la izquierda
  mover_izquierda:

    ;;-- Hay que comprobar en que posicion estamos
    ld hl, (pos_vagoneta_video)
    ld a,l
    cp #10  ;;-- Vagoneta en la posicion inicial?
    jr nz, mover_izquierda_ok

    ;;-- Estamos colisionando con la parez izquierda!!
    ;;-- No permitir movimiento
    jr flag_z_set

mover_izquierda_ok:

    ld a,#FF  ;;  (a=-1)
    call mover_vagoneta
    jr flag_z_set
...
  • Resultado:

Bonus: Impactante

  • Si la vagoneta está en la izquierda y la tecla O está pulsada, se debe reproducir alguna animación para indicar que no puede seguir

  • Resultado:

Reto 4.4: Colisión con barriles

  • Rutina principal:
;;===================
;;  VARIABLES
;;===================

;; Posicion de la vagoneta (0 - 79)
vagoneta_pos:
  db 0

barril1_pos:
  db 0

barril2_pos:
  db 0

tecla_start:
  db 47   ;;-- 47:Spacio

tecla_reset:
  db 50  ;;-- 50: Tecla R

tecla_derecha:
  db  27 ;; Tecla P

tecla_izquierda:
  db 34  ;; Tecla O

;;====================
;; MAIN
;;====================
main:

   ;;-- Inicializar variables
   ld a, 40
   ld (vagoneta_pos), a

   ld a, 12
   ld (barril1_pos),a
 
   ld a,60
   ld (barril2_pos),a

   ;;-- Borrar el escenario anterior
   call borrar_escenario

   ;; Dibujar el suelo
   call dibujar_suelo

   ;; Dibujar vagoneta
   call dibujar_vagoneta

   ;;-- Dibujar barriles
   call dibujar_barril1
   call dibujar_barril2

   ;;-- Bucle principal
  bucle_main:
    
     ;;-- Comprobar las teclas pulsadas
     call leer_teclas

     ;;-- Comprobar colisiones
     ;;  vagoneta_pos == barril1_pos?
     ld a, (barril1_pos)
     ld b, a
     ld a, (vagoneta_pos)
     cp b
     jr z, colision

     ;; vagoneta_pos == barril2_pos?
     ld a, (barril2_pos)
     ld b, a
     ld a, (vagoneta_pos)
     cp b
     jr z, colision

     jr bucle_main

colision:
     
  ;;-- Inicializar HL con la posicion 0
  ld hl, #C410

  ;;-- Calcular la direccion de video sumando la posicion
  ld a, (vagoneta_pos)
  add l
  ld l,a  ;;-- L = L + barril1_pos
  call animacion_explosion
    
muerto:

  ;;-- Comprobar tecla de reinicio
  ld a, (tecla_reset)
  call #BB1E
  jr nz, main

   jr muerto

Se ha implementado directamente el Bonus MasVariable

  • Resultado:

Video 3.P11: DESAFIO: Tu primer juego

Click to see the youtube video

  • Sprites del videojuego:

Dificultad 1

Aquí se muestra a velocidad lenta, para que sea fácil terminalo y comprobar que funciona:

Y en esta animación se muestra a velocidad normal, que es más difícil de acabar

Dificultad 2

Pantalla de inicio:

Animación del juego:

Animación a pantalla completa:

Clone this wiki locally