[SOLVED!][Help Request] Animation Guidance

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

[SOLVED!][Help Request] Animation Guidance

Post by eskayelle » Sun Aug 02, 2020 1:58 pm

One more question for this weekend. The Nerdy Nights tutorials don't really cover animation.

My pong paddle is being held by two characters. Ideally, I'd like each of their feet to move (perhaps each frame, maybe every two?) as the paddle moves up and down. Based on how the pixels are lined up, I imagine this means either creating a new sprite with some minor pixel edits and overlaying it over the original sprite (or somehow swapping between the two) each frame... or simply overlaying one or two sprites over the original sprite, making sure the overlaid sprites' movements align with the original sprite.

Example mock up of a character frame 1 and 2 here (exact size). Conceptually, how might this animation work, and is there some example code anyone might have that I'd be able to play with?

Image
Last edited by eskayelle on Fri Aug 07, 2020 7:17 pm, edited 1 time in total.

User avatar
Controllerhead
Posts: 148
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Animation Guidance

Post by Controllerhead » Sun Aug 02, 2020 2:55 pm

You've been busy! Ill answer quickly and go into more detail in later posts if necessary.

You want to take your existing sprite and store a different tile. That is the second entry of each sprite. It would be (roughly) something like this:
Image

For homework, you need to make .db entries of tile values, figure out which animation you're on, figure out which part of which animation you're on, figure out when to change your animation, and update each existing sprite graphic accordingly.

I'll go into more detail later if you need. You got this!
Image

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Animation Guidance

Post by eskayelle » Sun Aug 02, 2020 6:22 pm

Thanks! I'm going to slow down my pace a bit so I can better understand all the goings on with this one.

Here's the updated ASM and CHR.
For homework, you need to make 1) .db entries of tile values, 2) figure out which animation you're on, 3) figure out which part of which animation you're on, 4) figure out when to change your animation, and 5) update each existing sprite graphic accordingly.
1) I set up a table in bank 1, based on your animationTile reference:

Code: Select all

animationTile:
     		;vert tile attr horiz
  .db PADDLE1YINIT-$08, $0C, $80, PADDLE1X   		; $0288?
  .db PADDLE1YINIT, $12, $01, PADDLE1X-$10  		; $028C
  .db PADDLE1YINIT, $13, $01, PADDLE1X-$08 		; $0290
  .db PADDLE1YINIT, $14, $00, PADDLE1X   		; $0294
  .db PADDLE1YINIT+$08, $15, $00, PADDLE1X-$10   	; $0298
  .db PADDLE1YINIT+$08, $16, $01, PADDLE1X-$08   	; $029C
  .db PADDLE1YINIT+$08, $17, $00, PADDLE1X   		; $02A0
  .db PADDLE1YINIT+$10, $18, $02, PADDLE1X-$10   	; $02A4
  .db PADDLE1YINIT+$10, $19, $02, PADDLE1X-$08   	; $02A8
  .db PADDLE1YINIT+$10, $1A, $00, PADDLE1X   		; $02AC
  .db PADDLE1YINIT+$18, $1B, $00, PADDLE1X-$10   	; $02B0
  .db PADDLE1YINIT+$18, $1C, $02, PADDLE1X-$08   	; $02B4
  .db PADDLE1YINIT+$18, $1D, $00, PADDLE1X   		; $02B8
  .db PADDLE1YINIT+$20, $0C, $00, PADDLE1X   		; $02BC

;overlay palette sprite
  .db PADDLE2YINIT+1, $0E, $43, PADDLE2X-$05   		; $02C0
  .db PADDLE2YINIT+$12, $0F, $43, PADDLE2X-$05   	; $02C4
  .db PADDLE2YINIT-$08, $0C, $80, PADDLE2X-$11   	; $02C8
  .db PADDLE2YINIT, $14, $40, PADDLE2X-$10   		; $02CC
  .db PADDLE2YINIT, $13, $42, PADDLE2X-$08   		; $02D0
  .db PADDLE2YINIT, $12, $42, PADDLE2X   		; $02D4
  .db PADDLE2YINIT+$08, $17, $40, PADDLE2X-$10   	; $02D8
  .db PADDLE2YINIT+$08, $16, $42, PADDLE2X-$08   	; $02DC
  .db PADDLE2YINIT+$08, $15, $40, PADDLE2X   		; $02E0
  .db PADDLE2YINIT+$10, $1C, $40, PADDLE2X-$10   	; $02E4
  .db PADDLE2YINIT+$10, $1B, $42, PADDLE2X-$08   	; $02E8
  .db PADDLE2YINIT+$10, $1A, $42, PADDLE2X   		; $02EC
  .db PADDLE2YINIT+$18, $0B, $40, PADDLE2X-$10   	; $02F0
  .db PADDLE2YINIT+$18, $0A, $42, PADDLE2X-$08   	; $02F4
  .db PADDLE2YINIT+$18, $09, $40, PADDLE2X   		; $02F8
  .db PADDLE2YINIT+$20, $0C, $00, PADDLE2X-$11   	; $02FC
Any concerns with my reusing certain tiles, e.g., the sprite overlays for player 2 (I use them to get one more color in my palette) or the tips of the paddles?

(Thinking through this, there are only two 8x8 sprite tiles per player that'd actually appear animated. Does the table need to reflect all the tiles (and can they be the same ones in animation 0 as animation 1), or is some kind of swap of two tiles per player per frame?)

2) I also set up an .rs 1 for the currentAnimation variable for ater. I'm thinking it'll cycle between 0 and 1 (two animations only) as the up/down buttons are pressed. So my starting animation will be the original sprite, then I want to cycle to the other sprite, then back to original.

3) I'm not 100% sure of the concept here. If I'm putting the sprite together via the looping function I currently have, will the 2nd animation (animation 1) overlay same as the 1st (animation 0)? How is the 1st set of sprites cleared (or does it matter since the transparent pixels should align exactly)?

4) My goal would be to have the animation change at button press. So... should there by some code in each button cycling the currentAnimation variable between 0 and 1?

5) Is this part the current commented out code, to be built upon as I get through 1-4 above?

Code: Select all

moveloop1right:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
; load and store the current tile here
; LDX currentAnimation   ; rotates between 0 for animation 0 and 1 for animation 1?  (2 animations total)
; LDA animationTile, x	 ; table inserted below in bank 1
; STA $0200, y		 ; NOTE: 2nd animation starts at $0288

  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$38		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1right   
ReadRight1Done: 	 ; handling this button is done
  RTS
  

User avatar
pubby
Posts: 557
Joined: Thu Mar 31, 2016 11:15 am

Re: [Help Request] Animation Guidance

Post by pubby » Tue Aug 04, 2020 11:42 pm

Sometimes it's easiest to tie the animation to the x/y position. You probably don't need tables/subroutines at all.

Code: Select all

lda player_y
lsr
lda #SPRITE_TILE_INDEX
adc #0
sta $200, x
If you want it slower, just add another 'lsr' or whatever.

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Animation Guidance

Post by eskayelle » Wed Aug 05, 2020 12:20 pm

Interesting. In this context, player_y is the y coordinate of that selected player (perhaps paddle1ytop in my case), correct?

If I have sprite overlays for player 2 (I needed them to get one more color... like Mega Man), would that impact this code snippit?

If my sprite tables look like this, how might I need to alter that suggested code? Or... do I need to optimize these sprite tables further?

Code: Select all

sprites:
     		;vert tile attr horiz
  .db PADDLE1YINIT-$08, $0C, $80, PADDLE1X   		; sprite 01; RAM $0200 ; p1 
  .db PADDLE1YINIT, $00, $01, PADDLE1X-$10  		; sprite 02; RAM $0204
  .db PADDLE1YINIT, $01, $01, PADDLE1X-$08 		; sprite 03; RAM $0208
  .db PADDLE1YINIT, $02, $00, PADDLE1X   		; sprite 04; RAM $020C
  .db PADDLE1YINIT+$08, $03, $00, PADDLE1X-$10   	; sprite 05; RAM $0210
  .db PADDLE1YINIT+$08, $04, $01, PADDLE1X-$08   	; sprite 06; RAM $0214
  .db PADDLE1YINIT+$08, $05, $00, PADDLE1X   		; sprite 07; RAM $0218
  .db PADDLE1YINIT+$10, $06, $02, PADDLE1X-$10   	; sprite 08; RAM $021C
  .db PADDLE1YINIT+$10, $07, $02, PADDLE1X-$08   	; sprite 09; RAM $0220
  .db PADDLE1YINIT+$10, $08, $00, PADDLE1X   		; sprite 10; RAM $0224
  .db PADDLE1YINIT+$18, $09, $00, PADDLE1X-$10   	; sprite 11; RAM $0228
  .db PADDLE1YINIT+$18, $0A, $02, PADDLE1X-$08   	; sprite 12; RAM $022C
  .db PADDLE1YINIT+$18, $0B, $00, PADDLE1X   		; sprite 13; RAM $0230
  .db PADDLE1YINIT+$20, $0C, $00, PADDLE1X   		; sprite 14; RAM $0234 

;overlay palette sprite
  .db PADDLE2YINIT+1, $0E, $43, PADDLE2X-$05   		; sprite 0E; RAM $0270
  .db PADDLE2YINIT+$12, $0F, $43, PADDLE2X-$05   	; sprite 0F; RAM $0274

  .db PADDLE2YINIT-$08, $0C, $80, PADDLE2X-$11   	; sprite 01; RAM $0238 ; p2
  .db PADDLE2YINIT, $02, $40, PADDLE2X-$10   		; sprite 02; RAM $023C
  .db PADDLE2YINIT, $01, $42, PADDLE2X-$08   		; sprite 03; RAM $0240 ; 64 = flip sprite horizontally
  .db PADDLE2YINIT, $00, $42, PADDLE2X   		; sprite 04; RAM $0244 ; using same sprite tiles as p1!!!
  .db PADDLE2YINIT+$08, $05, $40, PADDLE2X-$10   	; sprite 05; RAM $0248
  .db PADDLE2YINIT+$08, $04, $42, PADDLE2X-$08   	; sprite 06; RAM $024C
  .db PADDLE2YINIT+$08, $03, $40, PADDLE2X   		; sprite 07; RAM $0250
  .db PADDLE2YINIT+$10, $08, $40, PADDLE2X-$10   	; sprite 08; RAM $0254
  .db PADDLE2YINIT+$10, $07, $42, PADDLE2X-$08   	; sprite 09; RAM $0258
  .db PADDLE2YINIT+$10, $06, $42, PADDLE2X   		; sprite 10; RAM $025C
  .db PADDLE2YINIT+$18, $0B, $40, PADDLE2X-$10   	; sprite 11; RAM $0260
  .db PADDLE2YINIT+$18, $0A, $42, PADDLE2X-$08   	; sprite 12; RAM $0264
  .db PADDLE2YINIT+$18, $09, $40, PADDLE2X   		; sprite 13; RAM $0268
  .db PADDLE2YINIT+$20, $0C, $00, PADDLE2X-$11   	; sprite 14; RAM $026C 


animationTile:
     		;vert tile attr horiz
  .db PADDLE1YINIT-$08, $0C, $80, PADDLE1X   		; $0288?
  .db PADDLE1YINIT, $12, $01, PADDLE1X-$10  		; $028C
  .db PADDLE1YINIT, $13, $01, PADDLE1X-$08 		; $0290
  .db PADDLE1YINIT, $14, $00, PADDLE1X   		; $0294
  .db PADDLE1YINIT+$08, $15, $00, PADDLE1X-$10   	; $0298
  .db PADDLE1YINIT+$08, $16, $01, PADDLE1X-$08   	; $029C
  .db PADDLE1YINIT+$08, $17, $00, PADDLE1X   		; $02A0
  .db PADDLE1YINIT+$10, $18, $02, PADDLE1X-$10   	; $02A4
  .db PADDLE1YINIT+$10, $19, $02, PADDLE1X-$08   	; $02A8
  .db PADDLE1YINIT+$10, $1A, $00, PADDLE1X   		; $02AC
  .db PADDLE1YINIT+$18, $1B, $00, PADDLE1X-$10   	; $02B0
  .db PADDLE1YINIT+$18, $1C, $02, PADDLE1X-$08   	; $02B4
  .db PADDLE1YINIT+$18, $1D, $00, PADDLE1X   		; $02B8
  .db PADDLE1YINIT+$20, $0C, $00, PADDLE1X   		; $02BC

;overlay palette sprite
  .db PADDLE2YINIT+1, $0E, $43, PADDLE2X-$05   		; $02C0
  .db PADDLE2YINIT+$12, $0F, $43, PADDLE2X-$05   	; $02C4
  .db PADDLE2YINIT-$08, $0C, $80, PADDLE2X-$11   	; $02C8
  .db PADDLE2YINIT, $14, $40, PADDLE2X-$10   		; $02CC
  .db PADDLE2YINIT, $13, $42, PADDLE2X-$08   		; $02D0
  .db PADDLE2YINIT, $12, $42, PADDLE2X   		; $02D4
  .db PADDLE2YINIT+$08, $17, $40, PADDLE2X-$10   	; $02D8
  .db PADDLE2YINIT+$08, $16, $42, PADDLE2X-$08   	; $02DC
  .db PADDLE2YINIT+$08, $15, $40, PADDLE2X   		; $02E0
  .db PADDLE2YINIT+$10, $1C, $40, PADDLE2X-$10   	; $02E4
  .db PADDLE2YINIT+$10, $1B, $42, PADDLE2X-$08   	; $02E8
  .db PADDLE2YINIT+$10, $1A, $42, PADDLE2X   		; $02EC
  .db PADDLE2YINIT+$18, $0B, $40, PADDLE2X-$10   	; $02F0
  .db PADDLE2YINIT+$18, $0A, $42, PADDLE2X-$08   	; $02F4
  .db PADDLE2YINIT+$18, $09, $40, PADDLE2X   		; $02F8
  .db PADDLE2YINIT+$20, $0C, $00, PADDLE2X-$11   	; $02FC


User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Animation Guidance

Post by eskayelle » Fri Aug 07, 2020 7:17 pm

Think I've got this reasonably solved, thanks to some additional guidance. Went with something like this:

Code: Select all


animation:		 ; each time controller 1 movement occurs, change animation state
  LDA currentAnimation   ; load animation # into accumulator (0 or 1)
  EOR #$01		 ; flips a 1 to a 0 or a 0 to a 1
  STA currentAnimation   ; this will change the animation
  RTS
  
left1_button_subroutine:
  LDA gamestate
  CMP #STATE_PLAYING
  BNE ReadLeft1Done
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL		 ; if it's above the ceiling, do nothing
  BCC ReadLeft1Done 
  LDA paddle1ybot
  SEC
  SBC #SPEED2
  STA paddle1ybot
  LDA paddle1ytop
  SEC
  SBC #SPEED2 
  STA paddle1ytop 

moveloop1left:
  JSR animation
  LDA currentAnimation
  CMP #$00
  BNE leftanim1

leftanim0:
  LDY #$00		 ; RAM address $02xx
leftanim0loop:
  LDA $0200, y		 ; load sprite Y position
  SEC        		 ; make sure the carry flag is clear
  SBC #SPEED2  		 ; sub SPEED2 from accumulator     
  STA $0200, y 		 ; save sprite Y position
  INY			 ; bump y register up one (to $0201)
  LDA sprites, y	 ; load the tile ID attribute from the table
  STA $0200, y		 ; save tile ID ($0201)
  INY			 ; bump y register up one (to $0202)
  LDA sprites, y	 ; load the mirror/flip attribute from the table
  STA $0200, y		 ; save attributes ($0202)
  INY			 ; bump y register up one (to $0203)
  LDA sprites, y	 ; load the X coordinate from the table
  STA $0200, y		 ; save X ($0203)
  INY			 ; increase x y times for 4 attibute bytes per sprite
  CPY #$38		 ; 56 bytes (14 sprites at 4 bytes of attribute each) later than #$00...
  BCC leftanim0loop      ; continue loop till hitting end of the table
  JMP ReadLeft1Done

leftanim1:
  LDY #$00 
leftanim1loop:
  LDA $0200, y		 ; load sprite Y position
  SEC        		 ; make sure the carry flag is clear
  SBC #SPEED2  		 ; sub SPEED2 from accumulator      
  STA $0200, y 		 ; save sprite Y position
  INY			 ; bump y register up one (to $0201)
  LDA animationTile, y
  STA $0200, y		 ; save tile ID ($0201)
  INY			 ; bump y register up one (to $0202)
  LDA animationTile, y
  STA $0200, y		 ; save attributes ($0202)
  INY			 ; bump y register up one (to $0203)
  LDA animationTile, y
  STA $0200, y		 ; save X ($0203)
  INY			 ; increase y 4 times for 4 attibute bytes per sprite
  CPY #$38		 ; 56 bytes (14 sprites at 4 bytes of attribute each) later than #$00...
  BCC leftanim1loop      ; continue loop till hitting end of the table
ReadLeft1Done:
  RTS  		


Post Reply