u16 x, y, vx, vy; extern u8 map[32][32]; void perso_init() { x = y = vx = vy = 0; } void perso_handle() { vy += 10; // gravité x += vx, y += vy; } void perso_draw() { OAM[0] = y >> 8; OAM[1] = x >> 8; } void perso_check_col() { if (map[y >> 11][x >> 11]) // Collision bidon vy = 0; }
Tout est clair dans ma tête donc, alors je me mets à l'écrire en ASM. Et là c'est le drâme, jugez par vous même (le moteur fait l'équivalent de ce code C):
; Constantes .GRAVITY = 10 .OAM = 0xfe00 ; Variables .area _BSS .x: ; position 24-bit fixed point (16.8) .ds 3 .y: .ds 3 .vx: ; vitesse 16-bit fixed point (8.8) .ds 2 .vy: .ds 2 .area _CODE ; Initialisation du personnage _perso_init:: xor a ; a = 0 ld hl, #.x ld (hl+), a ; x = 0 ld (hl+), a ld (hl+), a ld (hl+), a ; y = 0 ld (hl+), a ld (hl+), a ld (hl+), a ; vx = 0 ld (hl+), a ld (hl+), a ; vy = 0 ld (hl+), a ret ; Gestion de la physique du personnage _perso_handle:: ld hl, #.vy ; vy += GRAVITY ld b, #.GRAVITY call add16_val8 call load16 ; push vy push bc ld hl, #.vx ; bc = vx call load16 pop de ; de = vy call _perso_move ; move(vx, vy) ret ; Bouge le personnage ; bc = delta X, de = delta Y (1.7.8 signed fixed point) _perso_move:: push de ld d, #2 ; Pour x et y ld hl, #.x move_boucle: bit 7, b ; bc.signe jr nz, move_bc_negatif ld a, (hl) ; partie basse add c ld (hl+), a ld a, (hl) ; partie moyenne adc b ld (hl+), a ld a, (hl) ; partie haute adc #0 ld (hl+), a jr move_suite move_bc_negatif: ld a, b ; cpl ; } ld b, a ; rend bc positif ld a, c ; } cpl ; ld c, a ; ld a, (hl) ; partie basse sub c ld (hl+), a ld a, (hl) ; partie moyenne sbc b ld (hl+), a ld a, (hl) ; partie haute sbc #0 ld (hl+), a move_suite: dec d ret z ; terminé? (y traité) pop bc ; de a été poussé avant jr move_boucle ; Retourne l'adresse de la map pour un point donné ; BC = point voulu (x, y) par rapport au perso ; shared_asm[0].w = adresse de la map get_map_addr: ld hl, #(.x + 1) ; de = (x, y) ld d, (hl) ld hl, #(.y + 1) ld e, (hl) ; (x, y) += (b, c) ld a, d add b ld d, a push af ld a, e add c ld e, a push af ; (x, y) /= 8 srl d srl d srl d srl e srl e srl e ; Retenue pour (x, y) += (b, c) avant pop af ld a, e adc #0 ld e, a pop af ld a, d adc #0 ld d, a ; On peut encore ajouter à (d, e) les 3 bits du haut de la position ld hl, #(.x + 2) ; d += (x.hi & 7) << 5 ld a, (hl+) and #7 swap a sla a add d ld d, a ld hl, #(.y + 2) ; pareil pour e ld a, (hl) and #7 swap a sla a add e ld e, a ; FIXME ld hl, #_bglvl01_map ld a, d ; bc = d % 32 and #31 ld c, a ld b, #0 add hl, bc ; colonne correspondante dans la map ld b, e ; bc = e * 32 (largeur d'une map) srl b ; 3 bits partent sur c srl b srl b ld a, e ; 3 bits du bas -> en haut de c and #7 swap a sla a ld c, a add hl, bc ; ligne correspondante dans la map ret _perso_check_col:: ld b, #0 ld c, #0 call get_map_addr ; check en haut à gauche ld a, (hl) and a ret z ; rien là? ; Collision -> stoppe net ld hl, #.vy ld a, #0 ld (hl+), a ld (hl+), a ret ; Dessin du personnage dans le sprite 0 _perso_draw:: ld hl, #.OAM ld bc, #(.y + 1) ; y ld a, (bc) add #16 ld (hl+), a ld bc, #(.x + 1) ; x ld a, (bc) add #8 ld (hl), a ret ; Retourne la position du perso ; HL = tableau de 6 octets _perso_get_pos:: ; source = .x, dest = hl, count = 6 push hl ld hl, #.x pop de ld bc, #6 call memcpy ret
Je me dis que soit 1) les programmeurs de l'époque avaient sacrément du skill pour faire des jeux complets 2) je suis une buse totale mais je pense qu'il y a beaucoup des deux
