The Enigma Of Cutscenes II: The Next Generation

Bucket Mouse
Posts: 179
Joined: Wed Mar 07, 2018 2:25 am

The Enigma Of Cutscenes II: The Next Generation

Post by Bucket Mouse » Mon Jul 02, 2018 3:32 am

I hope the mods don't mind my making a second topic, but a lot has changed since we last discussed how to do this. In the original topic, we didn't know exactly how the NESMaker code would be written regarding movement. Now we do. I feel with the information given in the latest batch of tutorials, we're super-close to coding out scenes where the characters move on their own.

We now know the specific names of the variables used:

LDX player1_object
INC Object_x_hi,x

This moves the player's character right. The same code but with DEC instead of INC moves it left.

ChangeObjectState #$01

This changes the player's animation to a walk cycle. Specific animation for cutscenes could be created in the Animations tool and called up with different numbers when needed.

Creating the movement for cutscenes should be as simple as creating a new variable for the number of frames you want the movement to take, as well as the speed. Four subroutines for Up, Down, Left and Right would allow us to do pretty much everything (except jumping).

There would also need to be a line of code that would shut off every input button except Start (because people will still want to pause the game), and possibly A (which could skip the cutscene). Those lines could be two subroutines, one to shut off input and one to turn it back on.

Nor for what I still don't know....how to get these things into the game! Currently, the only tool in NESMaker that lets you apply scripts is the Input screen. If the Map tool would let us apply scripts directly to a tile on the screen, the cutscene could activate when a character walks across it. Or if a cutscene needs to happen as soon as a screen is loaded, a menu could let us load that script into the screen, and there'd be a checkbox for whether the script was a one-time event or meant to happen each time.

Those things would be nice to have. Hint hint.

PS: if the reply is "not enough memory per frame," think about replacing that one function that separates everything into Night and Day. Very few projects are actually going to use that.
User avatar
dale_coop
Posts: 1272
Joined: Fri Feb 16, 2018 7:05 am
Location: France

Re: The Enigma Of Cutscenes II: The Next Generation

Post by dale_coop » Mon Jul 02, 2018 7:45 am

Yeah, I thought about that too after watched the last tutorial.

I think something doable would be call a cutscene_subroutine when the player trigger a pickup object and or even a tile.
Then for the input scripts, you could check the state of a variable (for ex, initialized to #$00 and changed to #$01 in cutscene_subroutine) and do skip the input part of the script, when not equal to #$00.

Would be very basic but might be fun.
-----
Sorry about my poor english
All I need: A Damn Fine Cup of Coffee
My games: PRESS START GAME / UNDERGROUND ADVENTURE
darkhog
Posts: 252
Joined: Sun May 13, 2018 10:02 am

Re: The Enigma Of Cutscenes II: The Next Generation

Post by darkhog » Mon Jul 02, 2018 12:05 pm

Or maybe a cutscene tool, akin to Tecmo Theater?
User avatar
dale_coop
Posts: 1272
Joined: Fri Feb 16, 2018 7:05 am
Location: France

Re: The Enigma Of Cutscenes II: The Next Generation

Post by dale_coop » Mon Jul 02, 2018 12:38 pm

Yes, but I was talking about what we could do now, with the current version.
-----
Sorry about my poor english
All I need: A Damn Fine Cup of Coffee
My games: PRESS START GAME / UNDERGROUND ADVENTURE
darkhog
Posts: 252
Joined: Sun May 13, 2018 10:02 am

Re: The Enigma Of Cutscenes II: The Next Generation

Post by darkhog » Tue Jul 03, 2018 5:03 pm

Well, you could use custom screens for tecmo theater-like cutscenes, though I'm not sure how would you go to/from those as needed.
Bucket Mouse
Posts: 179
Joined: Wed Mar 07, 2018 2:25 am

Re: The Enigma Of Cutscenes II: The Next Generation

Post by Bucket Mouse » Sun Aug 12, 2018 2:28 am

Presenting my FIRST attempt at independent movement! It didn't work, of course, but I wasn't expecting to get it right immediately. Hopefully with the help of the fine citizens of this forum, I can crack this.

I mapped this code to Button A in the main game. In theory, whenever I pushed button A, my little figure should've walked eight steps in a square shape. Instead the screen froze.

I'm sure there are a ton of rookie mistakes in here -- help me pick them out.

Code: Select all

    ;; change to walking animation
    LDX player1_object 
    ChangeObjectState #$01, #$10

    StartMoving player1_object, MOVE_UP
    loophere:
    LDX player1_object
    LDA MOVE_UP
    ORA #DIR_UP
    STA Object_movement,x
    INX
    CPX #8
    BNE loophere

    StartMoving player1_object, MOVE_RIGHT
    loophere2:
    LDX player1_object
    LDA MOVE_RIGHT
    ORA #DIR_RIGHT
    STA Object_movement,x
    INX
    CPX #8
    BNE loophere2

    StartMoving player1_object, MOVE_DOWN
    loophere3:
    LDX player1_object
    LDA MOVE_DOWN
    ORA #DIR_DOWN
    STA Object_movement,x
    DEX
    CPX #1
    BNE loophere3

    StartMoving player1_object, MOVE_LEFT
    loophere4:
    LDX player1_object
    LDA MOVE_LEFT
    ORA #DIR_LEFT
    STA Object_movement,x
    DEX
    CPX #1
    BNE loophere4

    ;; change to idle animation
    LDX player1_object 
    ChangeObjectState #$00, #$02

    RTS
User avatar
MistSonata
Posts: 231
Joined: Fri Feb 16, 2018 7:10 am

Re: The Enigma Of Cutscenes II: The Next Generation

Post by MistSonata » Sun Aug 12, 2018 3:14 am

I took your code and made it into something that would, in theory, work.

Code: Select all

Dummy_Script:
    ;; change to walking animation
    LDX player1_object 
    ChangeObjectState #$01, #$10

    LDY #$08 ; how many pixels you want to travel
    LDA #UP 
    STA Object_movement,x
    
    charGoUpLoop:
    DEC Object_x_hi,x
    DEY
    CPY #$00
    BNE charGoUpLoop
    
    LDY #$08
    LDA #LEFT
    STA Object_movement,x
    
    charGoLeftLoop:
    DEC Object_y_hi,x
    DEY
    CPY #$00
    BNE charGoLeftLoop
    
    LDY #$08
    LDA #DOWN
    STA Object_movement,x
    
    charGoDownLoop:
    INC Object_x_hi,x
    DEY
    CPY #$00
    BNE charGoDownLoop
    
    LDY #$08
    LDA #RIGHT
    STA Object_movement,x
    
    charGoRightLoop:
    INC Object_y_hi,x
    DEY
    CPY #$00
    BNE charGoRightLoop
    
    ChangeObjectState #$00, #$00
    LDA #DOWN
    STA Object_movement,x
    
    RTS
And while this code does technically work, unfortunately there's a bigger problem with it. If you plug it in and test it, it will seem like it does nothing, and that's because it goes through the code too fast. If you go back into the code and change the numbers before each loop, your character will simply "teleport" to a different spot on the map. It changes the character's x and y position one pixel at a time, but it does it so fast that it's finished by the time the graphics have a chance to update.

You would need to implement some kind of timing, and apart from using your action steps, there's unfortunately no way to do that right now that I know of.

It's cool that you're experimenting with 6502, though! I'd highly recommend checking out things like Easy6502 and "Assembly in one step" to learn more, it will really help in the long run! :)
User avatar
Kasumi
Posts: 137
Joined: Fri Mar 09, 2018 11:13 pm

Re: The Enigma Of Cutscenes II: The Next Generation

Post by Kasumi » Sun Aug 12, 2018 3:21 am

if the value at RAM location player1_object isn't 7, you've created an endless loop

Code: Select all

loophere:
    LDX player1_object;If the value stored here isn't 7, you've created an endless loop.
    LDA MOVE_UP
    ORA #DIR_UP
    STA Object_movement,x
    INX;Add one to X. 
    CPX #8;Compare that new value to 8. 
    BNE loophere;If it's not equal to 8, go to the label
Underneath the loophere label changes the value of X to player1_object. The inx adds 1 to this. But if the branch is taken, it just loops back to loophere which reloads X.

Suppose player1_object is 6. We copy it. We add one to the value of the copy. That's 7. We compare that value to 8. They're not equal, so we...
copy player1_object which is 6. We add one to the value of the copy. That's 7. We compare that value to 8. They're not equal so we...
copy player1_object which is 6. We add one to the value of the copy. That's 7. We compare that value to 8. They're not equal so we...

Even assuming you had no infinite loops here, it would not work like you're expecting. Storing a value to Object_movement,x doesn't actually move the object. It tells some code that runs later to move it. So you can store to it as many times as you like here, and it will only affect movement once.

As well, you do NOT want to modify X. The value of X is used to choose which object's data to store to.

Code: Select all

ldx player1_object
sta Object_movement,x
would affect player1's RAM.

Code: Select all

ldx monste1r_object;as an example, this isn't a real value I'm sure
sta Object_movement,x;would affect that monster's movement RAM. 
But it probably don't even have that RAM, this is just an example of how "sta ram,x" is usually used. It's not meant as a NES Maker tip.

Video games work like this.

They display a frame. While that frame is being displayed, the CPU is running creating the data (positions for sprites, etc.) needed to display the next frame. You can't do the movement all at once in one script, because then all the movement would occur in one frame. NES runs at 60 frames per second.

That is to say that if you did successfully update the object positions 8 times to walk around in the square in this one script, the object would walk around in a square and be back where it started in less than 1/60th of a second. You wouldn't visibly see it move because all of that movement will have occurred in one frame.

You need to go pretty deep into the code to do what you want. At the very least you'd need to add a RAM definition to keep track of how many frames had passed, so you can decide which movement to do across the frames.

I really recommend reading easy6502 as MistSonata said: https://skilldrick.github.io/easy6502/
User avatar
Kasumi
Posts: 137
Joined: Fri Mar 09, 2018 11:13 pm

Re: The Enigma Of Cutscenes II: The Next Generation

Post by Kasumi » Sun Aug 12, 2018 3:36 am

Double post, because why not. MistSonata, you can almost always avoid comparing a number with zero.

Code: Select all

ldy #8;Copy the value 8 to Y
loop:
dey;Subtract 1 from Y
cpy #0;Compare the value in Y to zero.
bne loop;If the result of the last operation was not zero, branch to loop.
Note that bne is "if the result of the last operation was not zero" and not "if the two numbers were not equal". So

Code: Select all

ldy #8;Copy the value 8 to Y
loop:
dey;Subtract 1 from Y
bne loop;If the result of the last operation was not zero, branch to loop.
If Y is 1, dey makes Y equal to zero. Which means the result of the last operation was zero. Which means bne won't branch.

So you get the same result, with one fewer instruction, two fewer bytes, and faster.

Check out this page: http://www.obelisk.me.uk/6502/reference.html
It has a list of which flags are affected for each instruction. When the zero flag is affected, this means cmp/cpy/cpx is sort of implied, and you can use beq or bne to branch based on whether or not it was zero. But it's not ALWAYS affected. Here's an example.

Code: Select all

loop:
lda #0
ldx #$FF
sta RAMLOCATION
bne loop
That bne would absolutely branch.
lda #0; This affects the zero flag. The result is zero, so beq would branch after it, bne would not.
ldx #$FF;This affects the zero flag. The result is NOT zero, so beq would NOT branch, and bne would.
sta RAMLOCATION;Even though 0 is in A, sta is an instruction that does NOT affect the zero flag. So it's unchanged from the above instruction. beq would NOT branch, and bne would.

One of the really key things to understand about branches in 6502. They only care about whatever most recently changed the flag. This reference guide is very helpful for seeing which flags get affected by which instructions and how: http://www.obelisk.me.uk/6502/reference.html
User avatar
MistSonata
Posts: 231
Joined: Fri Feb 16, 2018 7:10 am

Re: The Enigma Of Cutscenes II: The Next Generation

Post by MistSonata » Sun Aug 12, 2018 3:37 am

Thanks Kasumi. I knew there was a way to do it, but I was too lazy to look it up again. xD
Post Reply