Movement of the player a few tiles

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Movement of the player a few tiles
by on (#155922)
How to make to move the whole area and not one piece of it?

Attachment:
week3.zip [39.09 KiB]
Downloaded 75 times
Re: Movement of the player a few tiles
by on (#155934)
As I mentioned in the last thread, the problem is that you're using controller input to change the draw location of a single sprite.

Your game object, as most game objects tend to be, is made up of more than one sprite.

You need a variable for the X position of your object and a variable for the Y position of your object which are separate from your values for sprite OAM.

Then, the position of each individual sprite within that object actually becomes the position of that particular sprite relative to the object's position.

Example:

Let's say your object is at position 0,0, and is composed of four sprites in a square pattern. Let's also say that an object's actual position refers to it's top left corner.

The first sprite will be at 0,0, because it falls at the same point as your object position.

The next sprite will be at 8,0, because it falls 8 pixels to the right of your object position.

The next sprite will be at 0,8, because it falls 8 pixels below your object position.

The last sprite will be at 8,8, because it falls 8 pixels to the right and 8 pixels below your object position.


Does this make sense? If you get closer to getting it to work, I don't mind to help you find some of the bugs in your code, but I don't want to do it for you from scratch or I won't feel like I'm actually helping you much.

If you can understand this concept, see if you can get it to work and we can go from there. If you don't understand the concept I'll try to explain it better.
Re: Movement of the player a few tiles
by on (#155941)
You do this by first updating the X and Y positions of the "Dominant" sprite like what you've been doing (In your controller reading code). I usually make the dominant sprite the most upper-left one. Then you jump to a subroutine to update what's called the "meta sprite". If you haven't learned about subroutines yet, basically they allow you to reuse code in different places. They go after the RTI of your NMI routine so that they aren't called every frame in the infinite loop.

Code:

;(in the main game engine)
ReadRight:
  lda $4016
  and #%00000001
  beq ReadRightDone
  lda $0203
  clc
  adc #$01
  sta $0203
  jsr UpdatePlayerMetaSprite
ReadRightDone:
  ...
  ...
  ...
  rti ;exit NMI


;(outside game loop)
UpdatePlayerMetaSprite:
  lda $0200 ;first sprite's Y position
  sta $0204 ;same as second sprite's Y position
  clc
  adc #$08 ;8 pixels down
  sta $0208 ;third sprite's Y position
  sta $020C ;same as fourth sprite's Y position
 
  lda $0203 ;first sprite's X position
  sta $020B ;same as third sprite's X position
  clc
  adc #$08 ;8 pixels to the right
  sta $0207 ;second sprite's X position
  sta $020F ;fourth sprite's X position
  rts ;go back to where we were when the subroutine was called

That should update your metasprite no matter what direction you move :)

Also, just as a suggestion, I'd recommend going over Nerdy Nights again and re-reading each lesson carefully until you understand everything it's talking about. I sped through it the first time and it came back to bite me in the ass when I tried to make a scrolling platformer without having even made pong. I'd also recommend reading this to give yourself a better idea of how to structure your code and to get a good idea of how graphics on the nes really work. If there's anything you don't understand on there, I and I'm sure others would be glad to help explain it better, as it is a bit ambiguous at times, but very informative.
Re: Movement of the player a few tiles
by on (#156122)
My piece of metasprite code:

Code:
; Metasprite addon lib for PPU.s
; (c) 2014-2015 Peter Santing
;
;

; OAM is always 0x0500 in my engine so place meta sprites there.
; also NEVER TOUCH 0x00 (SPRITE #0)

   WRITEBUF   EQU $C      ; zeropage address counters.
   XBUF      EQU $D;
   
   
add_meta_sprite:   ; ($00) = holds metasprite addr.
               ; $02 = x pos, $03 = y pos.
               ; meta data is as follows. x, y, tile, bgcolor and attr
               ; sprite is as follows: y, tile, attr, x

   ldx      WRITEBUF
   ldy      #0
-   lda      $02         ; load x pos.
   clc
   adc      ($00), Y   ; add meta x pos.
   sta      XBUF
   iny
   lda      $03         ; load y pos
   clc
   adc      ($00), Y   ; add meta y pos.
   sta      ($0500), X   ; save byte Y
   inx
   iny
   lda      ($00), Y   ; load tile number.
   sta      ($0500), x   ; save tile number.
   inx
   iny
   lda      ($00), Y   ; load attribute.
   sta      ($0500), X   ; save attribute.
   inx
   lda      XBUF
   sta      ($0500), X   ; save x position.
   iny
   inx
   lda      ($00), Y   ; load x pos?
   cmp      #128      ; if x = 128
   bne      -         ; then end loop
   stx      WRITEBUF
   rts   
   
prep_write_meta_sprites:
   lda    #$4         ; always ignore spr #0 (hard set for scrollbars, etc)
   sta      WRITEBUF
   rts
   
done_write_meta_sprites:
   lda      #0
   ldx      WRITEBUF   
   inx      ; goto tile.
-   sta      ($0500), X
   inx
   inx
   inx
   inx
   cpx      #$01
   bne      -
   rts


How a meta-sprite table is built:
Code:
spr0:
   .db   -8, -16, 1, 2,   0, -16, 2, 2,   -8, -8, $11, 2
   .db   0, -8, $12, 2,   -8, 0, $21, 2, 0, 0, $22, 2, 0, 8, $32, 2, 128

the table works as follows: delta-x, delta-y, sprite-tile, attributes&color. thus SPR0 is like:
sprite 1: x=-8, y=-16, tile=1, attributes&color =2
sprite 2: x=0, y=-16, tile=2, attributes&color = 2
sprite 3, x=-8, y=-8, tile=$11, attributes&color = 2
........
sprite 7, x=0, y=8, tile=$32, attributes&color= = 2
sprite_end_marker = 128

to render the meta sprite use the following code:
Code:
   jsr   prep_write_meta_sprites
   lda #<spr0
   sta $00
   iny
   lda #>spr0
   sta $01   
   lda PLAYERX
   sta $02
   lda   PLAYERY
   sta $03
   jsr   add_meta_sprite   
   jsr done_write_meta_sprites

then DMA $500 to your OAM buffer.