Multi-step player animation?

I wanted to have my player have a multi-step animation for movement. Basically, what I want is when you start moving in a direction, there is a transition animation that plays once, followed by their movement animation that loops until they stop or change direction. This is easy enough with action steps for enemies, but the player object doesn't use action steps in the same way. I tried playing around with the action steps and looking at the input code, but what seemed like potentially intuitive solutions didn't work.
 

jorotroid

Member
Probably a lot of ways you could go about this, but this is what first came to my mind. You could set up a new variable that gets set to some value on direction pressed. The transition animation would be set to play here, too. Then on direction held, you decrement that variable by one and do a check to see if the variable has reached zero. If it has, switch to the movement animation. I think a value of 255 would give you about a 4.25 second timer, so a pretty low value should work fine for what you are doing.
 
Ugh, I've spent so much time tinkering with this :/ At least I feel like I have learned something about different commands and stuff, but still can get it to do what I want. I'm a bit lost as to how to set the value of the variable. Do I set it when I create it under "user variables", or set it in the asm? Does DEC or SBC continuously subtract until it gets to the number you specify with CMP, or does it just subtract 1?
 

jorotroid

Member
BentPawGames said:
Ugh, I've spent so much time tinkering with this :/ At least I feel like I have learned something about different commands and stuff, but still can get it to do what I want. I'm a bit lost as to how to set the value of the variable. Do I set it when I create it under "user variables", or set it in the asm? Does DEC or SBC continuously subtract until it gets to the number you specify with CMP, or does it just subtract 1?

Create it in the user variables. Unlike modern languages, you don't really ever "create" variables in code. For the most part you give names to variables through NESmaker. There are some
borderline esoteric differences between DEC and SBC, but the gist of it is that DEC is a somewhat convenient way of of subtracting by 1 and it doesn't affect the value in the accumulator. For that second tidbit, that means if you use DEC and then want to use a CMP opcode, you'll have to LDA your variable in between the DEC and CMP lines. That said, DEC does affect the processor flag that determines if a value has reached zero that the BEQ command uses. This means you don't even need to use a CMP opcode to check if your variable has reached zero if you use the DEC opcode.

Here is an example of how I might write the timer decremented:
Code:
	DEC transitionTimer
	BNE +
	;; put code here to change animation
+
	;; continue with the help direction code

You'll probably also want to do a check before this to make sure you are not already in the final looping animation, so when you are, it won't keep running the timer.
 
Much appreciated! looks like I wasn't too far off with what I was doing, albeit over-complicating things with unncessary LDAs and CMPs. Still figuring out ASM but even with just this exercise the logic is clicking a bit more where it didn't before.
 
jorotroid said:
You could set up a new variable that gets set to some value on direction pressed. The transition animation would be set to play here, too. Then on direction held, you decrement that variable by one and do a check to see if the variable has reached zero. If it has, switch to the movement animation. I think a value of 255 would give you about a 4.25 second timer, so a pretty low value should work fine for what you are doing.

Is this just a matter of literally loading that variable (whose value is established in User Variable tab of Nesmaker) in the direction pressed script? I wasn't sure if loading it would do anything if it then switches to the hold left script.
 

jorotroid

Member
Well, first a bit of background information. So the way variables work is that RAM has a bunch of slots called addresses that can hold a value. In a modern programming language, you can define a variable mid-program which will run some background process to find a free spot in RAM and use that address going forward for variable you are using. On the NES, there is no functionality to find a free spot of RAM, so you have to define all your variables outside of the program like in NESmaker. By "define" what I mean is that an address is given a name for it to be easier to know which address you are using to store a value. You could use and address without giving it a name, but that would make your code harder to read. You define your variable outside of the program, but you initialize it within the program. When you give it an initial value in NESmaker, at the beginning of the game's code there is a routine that runs through all the variables you have defined in NESmaker and sets them to their initial value. The addresses are always there where you uses them or not, and you can use any of them at any time.

What I think I am trying to get at is that you don't really need to worry about the initial value of your variable when you set up your variable in NESmaker. The only time that you want this timer code running is when you are holding down a direction. So any time a direction is not being held the value in that address doesn't matter. What matters is when you set the variable. In your on direction pressed code, you should store a value into that variable. Something like this:

Code:
LDA #$40 	;; The amount of time you want your timer to last
STA transitionTimer

If you are doing a platformer, then you don't need to worry about what happens when the player switches going from left to right or right to left because when they switch you should have the same timer setting code in the on left pressed as you do in the on right pressed code. If you are doing a top down game were it could be possible to go in two directions at once like up and left, then this could get a little more complicated.

I hope this answered your question.

Also for convenience you could set up a constant in NESmaker for your timer length add use that in both your left and right pressed code so you can change the constant to tweak the timer length instead of having to change it in both the left and right pressed scripts every time you want to tweak it. It would look something like this:

Code:
LDA #TRANSITION_TIMER_LENGTH
STA transitionTimer
 
Great thanks! This is similar-ish to what I was attempting. I found an older thread where MistSonata explained timers, LDA the number, etc.

This should hopefully get me there. Thanks for explaining it and walking through it in detail.
 
IT WORKS! :eek: :lol: Still a few quirks to sort out. Sometimes it skips this and seems to go straight to the idle animation while still moving left, but I think I can sort that out easily enough now. Thanks a ton! It's just a small little detail in the movement but I really wanted it for this game. :D

For the press left script I have:

Code:
LDX player1_object
    GetCurrentActionType player1_object
CMP #$01
BEQ +

ChangeObjectState #$06,#$02

LDA #$10 	;; The amount of time you want your timer to last
STA TransitTimer

And then for the hold left script I have:

Code:
LDX player1_object
    GetCurrentActionType player1_object
	CMP #$01
	BEQ ++
	;;;;;; Then, we will begin moving.
    StartMoving player1_object, MOVE_LEFT
++ ;; skipped the start movement.
;;;;;; Lastly, we will change the facing direction.
	;; comment out if you do not want this dpad push to change
	;; the facing direction.
    FaceDirection player1_object, FACE_LEFT
   
DEC TransitTimer
	BNE +
ChangeObjectState #$01, #$04 ;;
+
	
++
 
Hmm, so I made a copy of the press and hold scripts for the right direction and made the necessary changes (e.g., changing MOVE_LEFT to MOVE_RIGHT). I made sure I added the necessary animations for moving right, and added the inputs for the scripts. But now I can only move right. Even when I put in the normal right input, pressing left makes me go right (that wasn't an issue before). Still happens when I remove the right input all together. Only thing that fixes it is outright removing the right movement code from the input scripts all together.

UPDATE: Hmm looks like not have RTS at the end was the issue...although I swear I didn't have it there to begin with? *shrugs*
 

dale_coop

Moderator
Staff member
You need a RTS at the end of your input scripts... else, when this script is executed, the next script is ALSO executed (the next script in your "Input Scripts" list). That can cause a lot of issues, yeah ;)
 
That makes a lot of sense in relation to what I was seeing XD

I don't have a strong understanding of RTS, only that I see it all the time so I have been adding it when tinkering around with code. In this case I guess I forgot to (although I swear I did initially)

I am ridiculously happy with cobbling this together without literally being told "here's all the code you need copy and paste it in". :D
 
Top Bottom