;; MIT License
;; 
;; Copyright (c) 2021 capAI / Aitana Devis  Ávila (@AitanaDevis) / Carlos Peñarrubia Morcillo  (@carlospm12) / Pablo Ruiz Ponce (@pabloruizp)
;; 
;; Permission is hereby granted, free of charge, to any person obtaining a copy
;; of this software and associated documentation files (the "Software"), to deal
;; in the Software without restriction, including without limitation the rights
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;; copies of the Software, and to permit persons to whom the Software is
;; furnished to do so, subject to the following conditions:
;; 
;; The above copyright notice and this permission notice shall be included in all
;; copies or substantial portions of the Software.
;; 
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;; SOFTWARE.

;; SISTEMA DE FISICAS
.include "physics.h.s"
.globl sys_render_borrar_player
.globl sys_render_reset_player_pointer_agachado
.globl man_animation_update
.globl _sys_render_draw_player

.area _CODE

MAX_P_JUMP = 2
contador = #30 ;sube 6 frames
P_H_CROUCHED = #11 ;; altura del personaje si está agachado
P_H_INITIAL = #16
P_Y_INITIAL = #170 
FAST_JUMP_VELOCITY = #-3
SLOW_JUMP_VELOCITY = #1


;;///////////////////////////////////////////////////////////////////////
;; FUNCION PARA MODIFICAR LA POSICION DE UNA ENTIDAD
;; DE MOMENTO SOLO MODIFICAMOS EL OFFSET (QUE AHORA MISMO ES COMO UNA POSICION X)
;;
;; PARAMETROS: DE (ENTIDAD), HL(CONTIENE INFORMACION INPORTANTE)
;;
;; REGISTROS MODIFICADOS: HL, DE, IX
;;
;; RETURN: NADA
;;///////////////////////////////////////////////////////////////////////
_sys_physics_update_one_entity::
    push hl     ;; PUNTERO FUNCION (TENEMOS QUE GUARDARLO PARA EL FORALL)

    push de
    pop ix      ;; PUNTERO ENTIDAD (PUNTERO A LA ENTIDAD QUE ESTAMOS MODIFICANDO)

    push de     ;; GUARDAMOS EL PUNTERO A DE

    ld h, 4(ix)
    ld l, 5(ix)        ;; OBTENEMOS EL OFFSET DE LA ENTIDAD
    dec hl
    ld a, #0xFF
    and h
    jp m, _negativo
    jp _positivo

    _negativo:
        pop de
        pop hl
        push hl
        call _sys_render_delete_entity
        pop hl
        call _man_entity_set4destroy    ;; DESTRUIMOS LA ENTIDAD
        ret
    _positivo:                           ;; SI NO ES NEGATIVO MODIFICAMOS EL OFFSET
        ld 4(ix), h
        ld 5(ix), l         ;; MODIFICAMOS EL OFSET

    pop de
    pop hl      ;; RECUPERAMOS LOS DATOS DEL FINAL
ret


;;///////////////////////////////////////////////////////////////////////
;; FUNCION PARA MODIFICAR TODAS LA ENTIDADES
;;
;; PARAMETROS: NADA
;;
;; REGISTROS MODIFICADOS: HL
;;
;; RETURN: NADA
;;///////////////////////////////////////////////////////////////////////
_sys_physics_update::
    call _sys_physics_check_keyboard ;;check if any key is pressed
    call _sys_physics_move_player
    ld hl, #_sys_physics_update_one_entity    
    call _man_entity_forall              ;; LLAMAMOS A ESTA FUNCION QUE LE APLICA LA FUNCION ANTERIOR A TODAS LAS ENTIDADES
ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMPRUEBA SI ALGUNA TECLA (Q, A) ESTÁ PULSADA 
;;
;; INPUT: HL
;;
;; OUTPUT:
;;
;; REGISTROS MODIFICADOS: A, AF, B, BC, DE, HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_sys_physics_check_keyboard::
    ld ix, #_player

;; ------ KEY Q (saltar) ------

    ;; SI ESTA AGACHADO NO PUEDE SALTAR
    ld a, P_STATE(ix)
    dec a
    jr z, _check_a

    ;; COMPROBAMOS SI ESTA EN EL SUELO O EN EL PRIMER SALTO
    ld a, P_JUMP(ix) 
    cp #2
    jr z, _exit

    
    ;; COMPROBAMOS SI SE ESTA PULSANDO LA Q
    call cpct_scanKeyboard_asm 
    ld hl, #Key_Q
    call cpct_isKeyPressed_asm
    jr z, _no_pulsando_q
    jr _pulsado_q


    ;; SI ESTA EN EL AIRE PERO NO PULSA LA Q PASAMOS
    _no_pulsando_q:
    ld a, P_JUMP(ix) 
    dec a
    jr nz, _check_a
    jr _exit


    _pulsado_q:


    ;; COMPROBAMOS SI VA A HACER DOBLE SALTO O NO
    ld a, P_JUMP(ix) 
    dec a
    jr z, _doble_salto
    jr _q_pressed


    ;; HACEMOS QUE EL DOBLE SALTO SOLO SE PUEDA HACER SI ESTA CAYENDO
    _doble_salto:
        ld a, P_VY(ix) ;;si va a saltar
        and #0b10000000
        jr nz, _q_pressed
        ret

    
    ;; REALIZA EL SALTO
    _q_pressed:
        ld P_VY(ix), #7     ;;si va a saltar, la velocidad es 7 (1ª parte: jump fast)
        inc P_JUMP(ix)


    _exit:
        ret
       
        ;;seguimos comprobando el resto de teclas

;; ------ KEY A (agacharse) ------
    _check_a:
        ;;si no está agachado comprobamos si está presionando la tecla
        call cpct_scanKeyboard_asm
        ld  hl, #Key_A              ;; check if the Q key as been pressed (move UP)
        call cpct_isKeyPressed_asm  ;; function to control if the key stored in the hl register is pressed
        jr  z, _reset_height
            ;;pressed
            ld a, P_STATE(ix)
            cp #1
            jr z, finish_check_keyboard
            ;;;Estaba de pie y hay que agacharlo
            ld P_STATE(ix), #1 ;está agachado
            ld P_H(ix), #P_H_CROUCHED ;;quitamos la mitad 
            ld a, P_Y(ix)
            add a, #P_H_CROUCHED ;;como quita la mitad de bajo, modificamos la posición para acercarlo al suelo
            ld P_Y(ix), a
            call man_animation_update
            ret

    _reset_height:
        ld a, P_STATE(ix)
        cp #1
        jr nz, finish_check_keyboard
        ;;; Antes estaba agachado
        ld P_STATE(ix), #0  ;;lo volvemos a dejar en 0 para indicar que está de pie
        ld a, P_Y(ix)
        sub a, #P_H_INITIAL-P_H_CROUCHED 
        ld P_Y(ix), a
        ld P_H(ix), #P_H_INITIAL
        call man_animation_update

        call sys_render_reset_player_pointer_agachado

    finish_check_keyboard:
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ACTUALIZA LA POS DEL JUGADOR TENIENDO EN CUENTA VY 
;;
;; INPUT: 
;;
;; OUTPUT:
;;
;; REGISTROS MODIFICADOS: 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_sys_physics_move_player::
    ld ix, #_player ;;accedo al player
    ld a, P_Y(ix) ;;gets the actual Y position ;;was c
    ld c, P_VY(ix) ;;gets the Y velocity ;;was a
    sub c ;;A-=C
    ld b, a
    
    ld c, #0xE0
    and c
    cp c
    jr nz, holaa

    ld P_Y(ix), #0
    ret

    holaa:
    ld a, P_STATE(ix)
    cp #1
    jr z, agachado

    ld a, b  ;; P_Y del player
    cp #NIVEL_SUELO-P_H_INITIAL
    jr nc, set_PY_suelo_de_pie  ;; Si el player está más abajo que el suelo, se le pone al nivel del suelo
    ld P_Y(ix), a ;;updates the position, adds the velocity to the position
    ret

    set_PY_suelo_de_pie:
    ld P_Y(ix), #NIVEL_SUELO-P_H_INITIAL
    ret

    agachado:  ;;;Hago lo mismo que en el trozo de codigo anterior pero con P_H_CROUCHED
    ld a, b
    cp #NIVEL_SUELO-P_H_CROUCHED
    jr nc, set_PY_suelo_agachado  ;; Si el player está más abajo que el suelo, se le pone al nivel del suelo
    ld P_Y(ix), a ;;updates the position, adds the velocity to the position
    ret
    set_PY_suelo_agachado:
    ld P_Y(ix), #NIVEL_SUELO-P_H_CROUCHED
    ret

