4.5.9 swim physics in platformer/metroidvania

So i made my player be able to jump in the water and swim about and then jump back out and go back to normal physics.
View: https://youtu.be/KvIPM1aNJZo


this takes up 2 tiles and a very small amount of code in the physics and a couple of input scripts.
im using action step #$06 as my swimming animation so thats what will be checked for these scripts

like usual make backups of existing scripts you are working on.

lets start with the doHandlePhysics_PlatfromBase.asm
here we are going to do somethings that @baardbi has already worked out for us.
follow steps 1, 2,3 and 4
then we will edit the doHandlePhysics scricpt just after the 3 variables mentioned
ADC GRAVITY_LO
STA Object_v_speed_lo,x
LDA Object_v_speed_hi,x
ADC GRAVITY_HI
STA Object_v_speed_hi,x

LDA Object_v_speed_hi,x
CMP MAX_FALL_SPEED

with code like this
Code:
                    notOverFallSpeed:

                       GetActionStep #$00
                       CMP #$06
                       BEQ SWIM
      
                       LDA #$40
                       STA GRAVITY_LO
                       LDA #$00
                       STA GRAVITY_HI
                       LDA #$04
                       STA MAX_FALL_SPEED
                       JMP doneWithGravity

    SWIM:
    LDA #$90
    STA GRAVITY_LO
    JMP doneWithGravity
    
isSolidSoLand:

this will use the swim action step to switch to swim physics and use normal gravity if no swimming.
you could make a whole bunch of gravity changes depending on situations if you wanted.

Now the tiles.
i made a swimtile.asm and assigned it to tile 13
Code:
;;;;SWIM:;;;;;;;;;;;
    GetActionStep #$00
    CMP #$06
    BEQ +skip
    CPX player1_object
    BNE +skip
    ChangeActionStep #$00, #$06
    LDA Object_v_speed_hi,x
    LDA #$01
    STA MAX_FALL_SPEED
    STA Object_v_speed_hi,x
    +skip:
    RTS
this will switch to swim action and reboot a little gravity switch when falling.
next is a return action tile.
mine is set to tile 14 returnaction.asm
Code:
;; return from swim
    CPX player1_object
    BNE +skip
    ChangeActionStep #$00, #$02
    +skip:
    RTS
this tile is placed above the swim tile so that when jumping out of the water it goes to jumping #$02 and normal gravity.

swim.png

0D swim
0E return

lastly we need to make A button in this case cause a jump while in swim state.
so the input script jump_throughPlat.asm will need a tweak around line 24 to check action step #$06

Code:
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Only can jump if the place below feet is free.
    SwitchBank #$1C
    LDY Object_type,x
    LDA ObjectBboxTop,y
    CLC
    ADC ObjectHeight,y
    sta temp2
    
    LDA Object_x_hi,x
    CLC
    ADC ObjectBboxLeft,y
    STA temp
    JSR getPointColTable
    
    LDA Object_y_hi,x
    CLC
    ADC #$02
    CLC
    ADC temp2
    STA temp1
    GetActionStep #$00
    CMP #$06
    BNE +checkMore
    JMP +doJump

    +checkMore
    CheckCollisionPoint temp, temp1, #$01, tempA ;; check below feet to see if it is solid.

next is changeActionToMoving_unlessJumping.asm

Code:
   TXA
    STA temp ;; assumes the object we want to move is in x.
 GetActionStep temp
    CMP #$07
    BNE +notHurt
        RTS
    +notHurt
    CMP #$02 ;; the state of your jump animation
    BNE +notJumping
        RTS
    +notJumping
    CMP #$06
    BNE +notSwim
       RTS
    +notSwim
        ChangeActionStep temp, #$01 ;; assumes that "walk" is in action 1
            ;arg0 = what object?
            ;arg1 = what behavior?
            ;+
            RTS
we r just adding in the CMP #$06 part to each of these scripts to allow movement to change for swimming.
next is changeActionToStop_unlessJumping.asm
Code:
   TXA
    STA temp ;; assumes the object we want to move is in x.
    ;;; It is possible that we are pressing multiple directions, and let go of one of them.
    ;;; If this happens, we would have our behavior change to stop, even though we'd continue to move.
    ;;; What we need to do is checkt o see if the relevant dpad buttons are pressed.  If any buttons
    ;;; are pressed that would counter the change to a stop action upon release, we need to skip the
    ;;; change to stop action. 
    ;GetActionStep temp
    ;CMP #$07
    ;BNE +notHurt
    ; RTS

    
    LDA controllerNumber_hold
    ;BNE weAreCheckingCOntroller2
        ;; we are checking controller 1.
        LDA gamepad
        AND #%11110000
        BEQ changeToStop_NoDpadPressed
           RTS
        ;weAreCheckingCOntroller2:
        ;LDA gamepad2
        ;AND #%11110000
        ;BEQ changeToStop_NoDpadPressed
        ;RTS
    changeToStop_NoDpadPressed:
    GetActionStep temp
    CMP #$06
    BNE +notSwim
       RTS
    +notSwim
    
        ChangeActionStep temp, #$00 ;; assumes that "walk" is in action 1
        ;arg0 = what object?
        ;arg1 = what behavior?
    RTS
again just to clarify we are just adding the
GetActionStep temp
CMP #$06
BNE +notSwim
RTS
+notSwim
stuff to whatever you input script already has
lastly is stopMoving.asm
Code:
;;;;
    TXA
    STA temp ;; assumes the object we want to move is in x.
    StopMoving temp, #$FF, #$00
    TXA
    STA temp ;; assumes the object we want to move is in x.
    GetActionStep temp
    CMP #$07
    BNE +notHurt
        RTS
    +notHurt
    CMP #$06
    BNE +notSwim
       RTS
    +notSwim
    ChangeActionStep #$00, #$00
    RTS
thats about it. obviously it will need adapting for individual games but this will give a good start.
good luck nesmakers!
 

cramske

Member
oh man. This was another way I was thinking of doing a swim type. with tile types. Cool. I need to study more.
 

Ahrevival

New member
Hey @CalFlyheight . I followed your instruction. I'm using 4.5.9 so may something different. My player gets stuck in middle of screen and animation just loops. Can't move left, right, up, down, jump, etc. Thoughts? All other screens without swim tile still work.
 

Ahrevival

New member
If I put a line of swim tiles, I get stuck. If I put just one or two, it works but I switch back to regular gravity as soon as I go to a null tile.
 

baardbi

Well-known member
Maybe @baardbi has an idea?
You mean the thing about placing monsters? I would just put a check at the top of the tiles to make sure they only affect the player like this:

CPX player1_object
BEQ +
JMP +skipTile
+

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Tile code........

+skipTile

Then you could make monsters like fish or something that swim back and forth. They should probably be set up with "Ignore Gravity" on their action steps.
 

dale_coop

Moderator
Staff member
In the tile script, there is already a check for the player object
Code:
    CPX player1_object
    BNE +skip
It means the swimming tile already affects only the player object... and not the monster objects.
 

baardbi

Well-known member
In the tile script, there is already a check for the player object
Code:
    CPX player1_object
    BNE +skip
It means the swimming tile already affects only the player object... and not the monster objects.
Oh. Yes. You're right. I was in a hurry when I read this.
 

dale_coop

Moderator
Staff member
For the monsters... I think you need to change that physics part:
Code:
                    notOverFallSpeed:

                       GetActionStep #$00
                       CMP #$06
                       BEQ SWIM
     
                       LDA #$40
                       STA GRAVITY_LO
                       LDA #$00
                       STA GRAVITY_HI
                       LDA #$04
                       STA MAX_FALL_SPEED
                       JMP doneWithGravity

    SWIM:
    LDA #$90
    STA GRAVITY_LO
    JMP doneWithGravity
   
isSolidSoLand:

Into something like this:
Code:
                    notOverFallSpeed:
                        CPX player1_object  ;; dale_coop: added
                        BNE +notSwimming      ;; dale_coop: added
                       
                        GetActionStep player1_object
                        CMP #$06
                        BEQ SWIM
                       
                        +notSwimming:  ;; dale_coop: added
                       
                        LDA #$40
                        STA GRAVITY_LO
                        LDA #$00
                        STA GRAVITY_HI
                        LDA #$04
                        STA MAX_FALL_SPEED
                        JMP doneWithGravity

    SWIM:
    LDA #$90
    STA GRAVITY_LO
    JMP doneWithGravity
   
isSolidSoLand:


I think it's the source of the issue monster objects.
 
Top Bottom