Translate a sprite in a cell matrix space

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
User avatar
kikutano
Posts: 100
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Translate a sprite in a cell matrix space

Post by kikutano » Sat Nov 09, 2019 3:24 am

Hello to everyone, I've a "matrix" space where i translate the player by 16 pixel at time on X and Y, as you can see in the image attached. Now I need to translate an object ( sprite, pickable object, enemy etc etc ) by N cells. The first thing that I do is to put the object on the cell 0, 0 and so translate it by 16 pixel in a loop, as you can see in this code:

Code: Select all

;Occupational Matrix:
level_0_room_0_occ:
  .db $80,$80,$02,$80,$80,$80,$03,$80
  .db $80,$90,$00,$00,$00,$00,$00,$80
  .db $80,$00,$00,$00,$00,$80,$00,$80
  .db $80,$00,$00,$00,$00,$80,$00,$80
  .db $80,$00,$00,$00,$00,$80,$00,$80
  .db $80,$00,$00,$00,$00,$00,$00,$80
  .db $80,$00,$00,$00,$00,$00,$00,$80
  .db $80,$80,$80,$80,$80,$80,$80,$80

set_player_on_next_door:
    ;Find the enter door on the matrix ( $03 ) and put the player on it
    ldx #$00
    .room_enter_search_loop:
        lda RAM_ROOM_CELLS, x
        cmp PLAYER_ON_CELL_VALUE
        beq .room_enter_search_loop_exit
        inx
        cpx #$FF
        bne .room_enter_search_loop

    .room_enter_search_loop_exit:
        txa 
        sta CURRENT_CELL_POINTER
        
    ;Put the player on the 0,0 Cell
    lda #$40
    sta RAM_PLAYER
    sta RAM_PLAYER + 4
    lda #$48
    sta RAM_PLAYER + 8
    sta RAM_PLAYER + 12
    lda #$20
    sta RAM_PLAYER + 3
    sta RAM_PLAYER + 11
    lda #$28    
    sta RAM_PLAYER + 7
    sta RAM_PLAYER + 15

    ;Translate on the right by 16 pixels
    ldx #$00
    ldy #$00
    .player_set_on_door_loop:
        m_inc_by RAM_PLAYER + 3 , #$10
        m_inc_by RAM_PLAYER + 11, #$10
        m_inc_by RAM_PLAYER + 7 , #$10
        m_inc_by RAM_PLAYER + 15, #$10
        
        iny 
        cpy #$08
        bne .skip_inc_y
        
        ;Increment by on cell on the vertical side
        m_inc_by RAM_PLAYER + 0 , #$10
        m_inc_by RAM_PLAYER + 4 , #$10
        m_inc_by RAM_PLAYER + 8 , #$10
        m_inc_by RAM_PLAYER + 12, #$10 
        
        ;Reset X on 0
        lda #$20
        sta RAM_PLAYER + 3
        sta RAM_PLAYER + 11
        lda #$28    
        sta RAM_PLAYER + 7
        sta RAM_PLAYER + 15

        ldy #$00

        .skip_inc_y:
            inx 
            cpx CURRENT_CELL_POINTER
            bne .player_set_on_door_loop
            
    rts
I think this cose is really slow, but it works fine. I'm still a noob on Nes Dev, so I what to ask you if there is a better way to put a sprite on a cell avoiding a cycle. Any idea?

Thanks!
Attachments
Screenshot (28).png

User avatar
rainwarrior
Posts: 7680
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Translate a sprite in a cell matrix space

Post by rainwarrior » Sat Nov 09, 2019 1:31 pm

Yes, in general for unwrapping a linear coordinate onto a grid there are methods that will get you to your answer more directly:

Code: Select all

// pseudo-C

cx = CURRENT_CELL_POINTER % 8
cy = CURRENT_CELL_POINTER / 8
rx = (cx * 16) + ox
ry = (cy * 16) + oy

; for x

lda CURRENT_CELL_POINTER
and #7 ; A % 8
asl
asl
asl
asl ; A * 16
clc
adc #$20 ; A + ox
sta RAM_PLAYER + 3
sta RAM_PLAYER + 11
clc
adc #8 ; A + 8
sta RAM_PLAYER + 7
sta RAM_PLAYER + 15

; for y

lda CURRENT_CELL_POINTER
lsr
lsr
lsr ; A / 8
asl
asl
asl
asl ; A * 16
clc
adc #$40 ; A + oy
etc...
Modulo % and division / aren't directly available on NES, but if the number is a power of 2, AND can be used as a modulo. AND #N-1 is the same as % N if N is a power of 2.

Division and multiplication by 2 can similarly can be done with bit shift operations like LSR and ASL.

One final optimization, if you notice on the Y coordinate I am shifting right to divide by 8, and then shifting back to the left to multiply by 16, most of those shifts kinda cancel each other out.

Code: Select all

; original
lsr
lsr
lsr ; A / 8
asl
asl
asl
asl ; A * 16

; is the same as
and #%11111000 ; clear out the low 3 bits which were supposed to be dropped off the right side by LSR
asl ; A * 2 (3x ASL cancels 3x LSR, so only 1x ASL is left)
Also, the CLC instructions above aren't necessary since the results are guaranteed to never have a carry here (unless the player is off the grid). I left them in just because generically for 8-bit addition CLC/ADC come as a pair. If you're careful, you can skip the CLC sometimes when you have a guarantee about the carry flag..

User avatar
kikutano
Posts: 100
Joined: Sat May 26, 2018 6:14 am
Location: Italy

Re: Translate a sprite in a cell matrix space

Post by kikutano » Sun Nov 10, 2019 3:31 am

Oh thanks, I will try! :)

Post Reply