Complicated ladder problem.

SuperNatetendo

New member
I'm just going to post what I did on facebook - https://www.facebook.com/groups/NESmakers/permalink/836766030011057/

Essentially, I'm getting multiple jumps on ladder. Right now I've removed code that changes you to idle from the ExtraControllScript, but then I'm just stuck in falling. Since I'd rather not describe what all I've done, I'll just post my relevant code to ladder climbing.

It's a mess, yes. I'm not a great coder.

ExtraInputControl -

Code:
ExtraInputControl:

    ;;; occasionally, there is input code that may be very specific, and it may be 
    ;;; difficult to implement via the visual interface and accompanying scripts.
    ;;; this is a code that runs after all input checks, and allows for custom ASM.
    LDA gameState
    CMP #GS_MainGame
    BEQ doMainGameUpdates
    JMP skipMainGameExtraInputControl
doMainGameUpdates:  
    LDX player1_object

    GetCurrentActionType player1_object
    STA temp
    LDA Object_physics_byte,x
    AND #%00000010
    BEQ isNotClimbing
    LDA temp
    CMP #$03
    BNE isNotClimbing

noDirWhileClimbing:
    ;;; is climbing.
    ;;; which means don't check to change to idle.
   JMP skipMainGameExtraInputControl
isNotClimbing:
    LDA temp
    CMP #$04 ;; is it shooting (shooting is same anim in air and on ground)
    BNE isNotAttackingAction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    JMP skipMainGameExtraInputControl
isNotAttackingAction:   


dontskipMainGameExtraInputControl:
    ;;; if left and right are not pressed
    
    LDA screenFlags
    AND #%00100000 ;; does it use gravity?
                    ;; if it does not, it would not have jumping or ducking, so
                    ;; skip state updates for jumping and ducking.
    BEQ notDucking ;; just will change to idle.

    LDA Object_physics_byte,x
    AND #%00000011 ;; if is in air
    BNE notInAir
    
    ChangeObjectState #$02, #$04
    JMP skipMainGameExtraInputControl
notInAir:
    LDA Object_h_speed_lo,x
    ORA Object_h_speed_hi,x
    BNE skipMainGameExtraInputControl
    ;;;; controller is not pressed
    ;;;; horizontal speed is zero.
    ;; check to see if in air, shooting, etc.
    ;; LDA gamepad
    ;;AND #%00100000 ; if down is pressed
    JMP notDucking
    ;;ChangeObjectState #$05, #$04

    skipMainGameExtraInputControl:
    RTS

notDucking:
    
    ;; NATE E - this following check just stops you from walking.
    ;; It's not in the input script, because I was tired of writing animation checks.

    LDA gamepad
    AND #%11000000
    BNE landedOnGroundCheck
    GetCurrentActionType player1_object    
    CMP #$01 ;;walking
    BNE landedOnGroundCheck
    LDA Object_animation_timer,x
    CMP #$03 ;; checks the timer, and waits a little bit to allow for skid.
    BMI landedOnGroundCheck
    
    ChangeObjectState #$00, #$00
    

    landedOnGroundCheck:
    

    
    ladderVariableSwitch:
    

   
    RTS

    
;; I MOVED ALL THE LADDER SCRIPTS HERE. MAKES MORE SENSE THAN PHYSICS

DoLadderStuff:
    CPX player1_object
    BEQ dontSkipLadderStuff
    JMP skipLadderStuff
    
dontSkipLadderStuff:

    LDA gamepad
    AND #%11000000
    BEQ ++
    JMP skipLadderStuff
    
    ++
    
    LDA Object_physics_byte,x
    ORA #%00000010
    STA Object_physics_byte,x
    
    LDA Object_right,x
    ADC xHold_hi
    AND #%11110000
    STA temp
    
    LDA Object_left,x
    ADC xHold_hi
    AND #%11110000
    STA temp1
    
    LDA temp
    CMP temp1
    BEQ dontSkipLadderSnap
    JMP skipLadderStuff
    
    dontSkipLadderSnap:
    
    LDA gamepad
    AND #%00010000 ; if up is pressed
    BEQ notPressingUpOnLadder
    GetCurrentActionType player1_object
    CMP #$03 ;; action state of climbing ladder #OBJ_INDEX_LADDER ;; compare to ladder type
    BEQ dontChangeToLadderState ;; already is in ladder state
    ChangeObjectState #$03, #$04
    
dontChangeToLadderState:
    LDA Object_y_lo,x
    SEC
    SBC #LADDER_SPEED_LO 
    STA Object_y_lo,x
    LDA Object_y_hi,x
    SBC #LADDER_SPEED_HI
    STA Object_y_hi,x
    STA yHold_hi
    CMP #BOUNDS_TOP
    BCS hasNotReachedTop
    
    LDA Object_scroll,x
    CMP xScroll_hi
    BEQ + ;; need to reverse
    ;; forward auto scroll
    LDA #%00000000
    JMP ++
+ ;; need to reverse
    LDA #%10000000
++
    ORA #$02
    STA align_screen_flag

    LDA #ALIGN_TIMER
    STA genericTimer
    LDA #$01
    STA prevent_scroll_flag
    ;JSR doTopBounds_player
hasNotReachedTop:
    
    
    JMP skipLadderStuff
notPressingUpOnLadder:
    LDA gamepad
    AND #%00100000 ; if down is pressed
    BEQ notPressingDownOnLadder

    GetCurrentActionType player1_object
    CMP #$03 ; #OBJ_INDEX_LADDER ;; compare to ladder type
    BEQ dontChangeToLadderState2 ;; already is in ladder state
    ChangeObjectState #$03, #$04
    
dontChangeToLadderState2:
    LDA Object_y_lo,x
    clc
    adc #LADDER_SPEED_LO 
    STA Object_y_lo,x
    LDA Object_y_hi,x
    adc #LADDER_SPEED_HI
    STA Object_y_hi,x
    CMP #BOUNDS_BOTTOM
    CLC
    ADC Object_bottom,x
    BCC skipLadderStuff
    LDA Object_scroll,x
    CMP xScroll_hi
    BEQ + ;; need to reverse
    ;; forward auto scroll
    LDA #%00000000
    JMP ++
+ ;; need to reverse
    LDA #%10000000
++
    ORA #$01
    STA align_screen_flag

    LDA #ALIGN_TIMER
    STA genericTimer
    LDA #$01
    STA prevent_scroll_flag
    
    JMP skipLadderStuff
notPressingDownOnLadder:
skipLadderStuff:


    RTS

Pre-Draw:

Code:
;; sprite pre-draw
;;; this will allow a user to draw sprites
;;; before object sprites are drawn.
;;; keep in mind, there are still only 64 sprites
;;; that can be drawn on a screen, 
;;; and still only 8 per scan line!

;;; you can use DrawSprite macro directly using the following scheme:
;DrawSprite arg0, arg1, arg2, arg3, arg4
    ;arg0 = x
    ;arg1 = y
    ;arg2 = chr table value
    ;arg3 = attribute data
    ;arg3 = starting ram position
    
;; x and y are the direct positions on the screen in pixels.
;; chr table value is which sprite you'd like to draw from the ppu table.
;; attribute data is a binary number (starts with #%), and here are how the bits work:
    ;;; bit 7 - Flip sprite vertically
    ;;; bit 6 - Flip sprite horizontally
    ;;; bit 5 - priority (0 in front of background, 1 behind background)
    ;;; bit 4,3,2 - (null)
    ;;; bit 1,0 - subpalette used (00, 01, 10, 11)
    
    
;;; for starting ram position, use spriteOffset.
;; this is set to 0 just before entering this script (or 4 if sprite 0 hit was used).
;; ***remember to increase spriteOffset by 4 for every sprite that is drawn,
;; including after the last one drawn*****, so that the first object's sprite begins
;; in the next available spot.

;; I have created a macro function to handle updating to the next sprite.  So, to update to the next sprite position,
;; all that you have to do is use the function UpdateSpritePointer

;;EXAMPLE:
; DrawSprite #$80, #$80, #$10, #%00000000, spriteOffset
; UpdateSpritePointer

;;;; DRAW SPRITE ZERO FOR SPRITE ZERO HIT
    LDA gameState
    CMP #GS_MainGame    
    BNE + ;dont draw sprite zero
    ;DrawSprite #$f8, #$1e, #$7F, #%00000000, spriteOffset
                ;248   30    127   bit 5 = priority
    DrawSprite #SPRITE_ZERO_X, #SPRITE_ZERO_Y, #SPRITE_ZERO_INDEX, #%00100000, spriteOffset
    UpdateSpritePointer
;dont draw sprite zero.
+

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; NATE E - janky object parenting w/ melee weapon

    LDX player1_object
    
    LDA Object_animation_frame,x
    STA temp
    
    LDA Object_movement,x
    AND #%00000111
    STA temp3
    TAY
    
    LDA Object_x_hi,x
    SEC 
    SBC #$10 ;; width of melee weapon 
    CLC
    ADC weaponOffsetTableX,y
    STA temp1
    
    LDA Object_y_hi,x    
    CLC
    ADC weaponOffsetTableY,y
    SEC
    SBC #$18 ;; height of melee weapon
    STA temp2
    
    ;;now to try to update the melee position.
    LDX currentObjectMelee
    LDA temp1
    STA Object_x_hi,x
    LDA temp2
    STA Object_y_hi,x
    
    LDA Object_movement,x
    ORA temp3
    STA Object_movement,x

    LDA temp
    STA Object_animation_frame,x
    
    
;;NATE E - ladder snap code test
    
    GetCurrentActionType player1_object
    CMP #$03
    BNE noLadderSnap
    
    LDX currentObjectMelee
    DeactivateCurrentObject
    
    LDX player1_object
    
    LDA Object_left,x
    ADC Object_x_hi,x ;;snap to ladder
    AND #%11110000
    STA Object_x_hi,x
    
    noLadderSnap:
      

;; basically, this is an animation check that runs if you are holding jump through the
;; whole period of time when you're jumping. It'll change back to the fall animation.

GetCurrentActionType player1_object
CMP #$02
BNE endFallAnimation

LDA Object_v_speed_hi,x
BMI jumpAnimation

LDA #$01
STA Object_animation_frame,x
JMP endFallAnimation

jumpAnimation:
LDA #$00
STA Object_animation_frame,x

endFallAnimation:

RTS

a_simple_jump:

Code:
; a jumps
 
   LDX player1_object
   ;;; let's check for if we are standing on a jumpthrough platform,
   ;;; for which "down and jump" will jump downwards through
   ;;; comment this out if you do not want that functionality
    LDA screenFlags
    AND #%00100000 ;; does it use gravity?
    BNE +
    JMP dontJump
    
   +
   
   LDA Object_physics_byte,x
   AND #%00000010
   BEQ noLadder
   GetCurrentActionType player1_object ;;check for jump animation
   CMP #$02
   BNE noLadder
   JMP dontJump
   
   
   noLadder:
   
   LDA Object_physics_byte,x
   AND #%00001000
   BEQ notStandingOnJumpThroughPlatform
   LDA gamepad
   AND #%00100000
   BEQ notStandingOnJumpThroughPlatform
   LDA Object_y_hi,x
   CLC
   ADC #$09
   STA Object_y_hi,x
   JMP dontJump
notStandingOnJumpThroughPlatform:
   
   LDA Object_physics_byte,x
   AND #%00000001
   BNE canJump
   LDA Object_physics_byte,x
   AND #%00000100
   BEQ dontJump

canJump:
    

    ;;; TURN OFF "STANDING ON JUMPTHROUGH PLATFORM" if it is on
    LDA Object_physics_byte,x
    AND #%11110111
    STA Object_physics_byte,x
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    LDA #$00
    SEC
    SBC #JUMP_SPEED_LO
    STA Object_v_speed_lo,x
    LDA #$00
    SEC
    SBC #JUMP_SPEED_HI
    STA Object_v_speed_hi,x
    
    GetCurrentActionType player1_object ;;check for attack animation
    CMP #$04
    BEQ dontJump
    
    ChangeObjectState #$02, #$FF
    
    
    PlaySound #SND_JUMP
dontJump:

    LDX currentObjectMelee
    DeactivateCurrentObject
    
    RTS
 

dale_coop

Moderator
Staff member
You right, Nate, your script is really... complex (to test).
I can't even use it in my project :p It doesn't compile... or my player flies away :p
Will try again tomorrow, when I will have more time.
 

dale_coop

Moderator
Staff member
Ok will try that.
Your scripts look correct, might not be too difficult find the good “adjustments” for the behavior you want.
 

dale_coop

Moderator
Staff member
Tried again... but without the context of your project (your player properties, your input mappings, your melee... I have very weird results when running the game.

Sorry >_<
 

dale_coop

Moderator
Staff member
I think you could try....
In your a_jump script, if on ladder, you should jump only if left or right is pressed (when jumping), you could have better results I think..

Code:
	LDA Object_physics_byte,x
	AND #%00000010
	BEQ noLadder
	
	;; on ladder, check if Left or Right is pressed:
	LDA gamepad
	AND #%11000000
	BNE +
	;; if not, don't jump
	JMP dontJump
	+
	
	GetCurrentActionType player1_object ;;check for jump animation
	CMP #$02
	BNE noLadder
	JMP dontJump
 
Top Bottom