reaktor24 wrote:I can see now there is a lot more to NES development than I realised! lol.
Yeah, but as long as you do things step by step and understand all the code you put into your project (i.e. don't blindly copy code or make random changes until it appears to work), you'll be fine.
Nevertheless I am not put off and enjoying it very much!
I find it very rewarding to engineer these programs bit by bit and see them come to life!
You're code worked a treat (albeit with a strange little glitch on the centre far left side of the screen when the frame changes - but I should be able to fix that).
I can't tell what's going on just from this description, but like I said before, be sure to track down the source of the bug and to understand WHY exactly it's happening.
2/3 work fine but setting frame index to 2 causes some odd behaviour - a few extra tiles appearing - but the main sprite looks fine to me.
Again, hard to tell without seeing code or a ROM, but be sure to pinpoint the exact cause. Learn how to step through code in an emulator's debugger, if you're not doing this already. This is the best way to tell whether your code is doing what you want you want it to be doing.
Ps. Any hints where I should start with the timing between frames? Run some sort of counter in the draw code between frames?
Yes, you need a counter, which will tell you how long to wait before advancing to the next animation frame. You don't use this in a time-wasting loop though, because if you did this you'd freeze the entire game. You're basically going to "clock" this counter once per frame, and when it expires, you can move on to the next frame.
Any versatile engine will let you specify a delay for each animation frame, so the animation_frames array seems like a good place to put that information:
Code: Select all
animation_frames:
.db $04
.dw run_right_frame_1
.db $03
.dw run_right_frame_2
.db $04
.dw run_right_frame_3
.db $80+0 ; code for "loop back to frame 0"
The bad part of doing it like this is that multiplying by 3 isn't as friendly as multiplying by 2 in assembly, but still not too bad. You can do this:
Code: Select all
GetFramePointer:
lda frame_index
asl ;multiply by 2
adc frame_index ;add one more to make x3
tay
lda animation_frames+0, y ;get the duration
bpl SkipLoop
and #%01111111 ;clear the "loop" bit
sta frame_index ;set the frame as instructed
jmp GetFramePointer ;start over
SkipLoop:
sta frame_counter ;save the counter
lda animation_frames+1, y ;get the low byte
sta frame_pointer+0
lda animation_frames+2, y ;get the high byte
sta frame_pointer+1
rts
One important thing to note is that when you add multiple animations for multiple characters, access to animation_frames will have to be made via indirect indexed addressing too, so you can have a pointer indicate which animation script is currently being used.
Another important thing is that each active object will need its own animation pointer, animation frame and animation counter, because each one has its own animation. We normally allocate chunks of RAM for all active objects dynamically, so they have a place to keep track of their state.
Anyway, to animate the sprite you can just decrement each object's frame_counter once per frame, and advance frame_index when it expires:
Code: Select all
dec frame_counter
bne FrameReady
inc frame_index
jsr GetFramePointer
FrameReady:
This is the basic idea, but you should obviously arrange the code in the way that makes the most sense to you.