Add 'skip top collision' to tile collisions.

Hey guys, my project for the day was to get the skip top collision flag to work with tile collisions too.
The reason you may want this is to add areas that your character cannot normally walk through, but they can move through if they crawl/slide through.
Mega-Man dash style.

As the code exists, there are no checks in the tile collision scripts to do this, the flag only affects collisions with other objects.
Here are the changes you need to make to let this work:

In CheckForHorizontalCollision.asm (in macros folder):
Make a backup of your original and replace the script with this one:
Code:
MACRO CheckForHorizontalCollision

;;;; RESET SOLID
	LDA #$00
    STA tile_solidity
	Sta collisionPoint0
	STA collisionPoint1
	STA collisionPoint2
	STA collisionPoint3
	STA collisionPoint4
	STA collisionPoint5
	
;;; RESET LADDER STATE	
	LDA Object_physics_byte,x
	AND #%11111101
	STA Object_physics_byte,x
	
	LDA Object_h_speed_lo,x
	CLC
	ADC #$00
	LDA Object_h_speed_hi,x
	ADC #$00
	BMI doLeftHorColCheck
	JMP doRightHorColCheck
doLeftHorColCheck:
	;;; check top left point
	
	;; Are we ducking? if so skip this check.
	LDA Object_vulnerability,x
    AND #%10000000
    BEQ +
	JMP ++
+

    LDA xHold_hi
    CLC
    ADC Object_left,x
    STA tileX

    LDA Object_y_hi,x
    CLC
    ADC Object_top,x
    STA tileY
	
    JSR GetTileAtPosition
    ;JSR DetermineCollisionTable
	LDA #$00
	STA temp
	DetermineCollisionTableOfPoints temp
	
    STA collisionPoint0
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    JMP HandleSolidCollision ;; hit a solid so won't update position. 
+   
	LDA tile_solidity
	AND #%00000010
	BEQ +
	LDA Object_physics_byte,x
	AND #%00000010
	BNE +
	;;; DO LADDER STUFF
	JSR DoLadderStuff
+
++
	;;; check bottom left point

    LDA xHold_hi
    CLC
    ADC Object_left,x
    STA tileX

    LDA Object_y_hi,x
    CLC
    ADC Object_bottom,x
    STA tileY
    
    JSR GetTileAtPosition
   ; JSR DetermineCollisionTable
   	LDA #$00
	STA temp
	DetermineCollisionTableOfPoints temp

    STA collisionPoint3
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    ;LDA Object_physics_byte,x
    ;ORA #%01000000 ;; solid was at top.
    ;STA Object_physics_byte,x
    JMP HandleSolidCollision ;; hit a solid so won't update position.
+

    LDA tile_solidity
	AND #%00000010
	BEQ +
	LDA Object_physics_byte,x
	AND #%00000010
	BNE +
	;;; DO LADDER STUFF
	JSR DoLadderStuff
+
;;;;; left middle
	LDA Object_bottom,x
    SEC
    SBC Object_top,x
    LSR 
    STA temp3 ;; temp 3 now equals half of the height of the object, so top+temp3 = mid point vertically.
  
	
    LDA xHold_hi
    CLC
    ADC Object_left,x
    STA tileX

    LDA Object_y_hi,x
    CLC
    ADC Object_top,x
    CLC
    ADC temp3
    STA tileY
    
    JSR GetTileAtPosition
    ;JSR DetermineCollisionTable
	  LDA #$00
	STA temp
	DetermineCollisionTableOfPoints temp
    STA collisionPoint4
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    JMP HandleSolidCollision ;; hit a solid so won't update position.
+
    	LDA tile_solidity
	AND #%00000010
	BEQ +
	LDA Object_physics_byte,x
	AND #%00000010
	BNE +
	;;; DO LADDER STUFF
	JSR DoLadderStuff
+
	JMP doneWithHorColCheck
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
doRightHorColCheck:
	;; Top Right
	
	;; Are we ducking? if so skip this check.
	LDA Object_vulnerability,x
    AND #%10000000
    BEQ +
	JMP ++
+

    LDA xHold_hi
	CLC
    ADC Object_right,x
    STA tileX

    LDA Object_y_hi,x
    CLC
    ADC Object_top,x
    STA tileY
    
    JSR GetTileAtPosition
   ; JSR DetermineCollisionTable
   	LDA Object_right,x
	STA temp
	DetermineCollisionTableOfPoints temp
    STA collisionPoint1
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    JMP HandleSolidCollision ;; hit a solid so won't update position.
+
	LDA tile_solidity
	AND #%00000010
	BEQ +
	LDA Object_physics_byte,x
	AND #%00000010
	BNE +
	;;; DO LADDER STUFF
	JSR DoLadderStuff
+
++
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	

    LDA xHold_hi
    CLC
    ADC Object_right,x
    STA tileX
   
    LDA Object_y_hi,x
    CLC
    ADC Object_bottom,x

    STA tileY
    
    JSR GetTileAtPosition
    ;JSR DetermineCollisionTable
	LDA Object_right,x
	STA temp
	DetermineCollisionTableOfPoints temp
    STA collisionPoint2
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    ;LDA Object_physics_byte,x
    ;ORA #%01000000 ;; solid was at top.
    ;STA Object_physics_byte,x
    JMP HandleSolidCollision ;; hit a solid so won't update position.
+
    	LDA tile_solidity
	AND #%00000010
	BEQ +
	LDA Object_physics_byte,x
	AND #%00000010
	BNE +
	;;; DO LADDER STUFF
	JSR DoLadderStuff
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
    ;;; IF YOU NEED TO FIND OUT THE MID POINT HORIZONTALLY
    ;LDA Object_right,x
    ;SEC
    ;SBC Object_left,x
    ;LSR
    ;STA temp2 ;; temp 2 now equals half the width of the object, so left+temp2 = mid point horizontally.
    
    LDA Object_bottom,x
    SEC
    SBC Object_top,x
    LSR 
    STA temp3 ;; temp 3 now equals half of the height of the object, so top+temp3 = mid point vertically.
    

    LDA Object_y_hi,x
    CLC
    ADC Object_top,x
    CLC
    ADC temp3
    STA tileY

	LDA xHold_hi
    CLC
    ADC Object_right,x
    STA tileX
     
    JSR GetTileAtPosition
    ;JSR DetermineCollisionTable
	LDA Object_right,x
	STA temp
	DetermineCollisionTableOfPoints temp
    STA collisionPoint5
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    JMP HandleSolidCollision ;; hit a solid so won't update position.
+
	LDA tile_solidity
	AND #%00000010
	BEQ +
	LDA Object_physics_byte,x
	AND #%00000010
	BNE +
	;;; DO LADDER STUFF
	JSR DoLadderStuff
+
doneWithHorColCheck:
	ENDM

Now in CheckForVerticalEjection.asm (in macro folder)
Make a backup of your original and replace the script with this one. MAKE SURE you change the two lines that set the crouched action state to accurately point to your own crouched state.
I have them marked with comments in the script.
Code:
MACRO CheckForVerticalEjection
	;;; we only want to eject solid objects, and likely do not want to eject projectiles and weapons
	LDA Object_flags,x
	AND #%00010100
	BEQ doMacroEjection
	JMP doneEjecting
doMacroEjection:
    LDA #$00
    STA tile_solidity
    
		

    LDA Object_x_hi,x
    CLC
    ADC Object_left,x
    STA tileX
    LDA #$00
    BCC +
    LDA #$01
+

    STA tempCol
    
    LDA yHold_hi
    CLC
    ADC Object_top,x
    STA tileY
    JSR GetTileAtPosition
    JSR DetermineCollisionTable
    STA collisionPoint0 ;; comment this out?
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    
	;; If trapped under a wall, force crouch animation  !!!! ==== Change this to your crouched action state!!! ==== !!!!
	ChangeObjectState #$03, #$04
	
	;; Are we touching the ground?
	LDA Object_physics_byte,x
    AND #%00000001
    BNE +
	
    JSR ejectDown
	
    JMP doneEjecting
+
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    LDA Object_x_hi,x
    CLC
    ADC Object_right,x
    STA tileX
    LDA #$00
    BCC +
    LDA #$01
+
    STA tempCol
    
    LDA yHold_hi
    CLC
    ADC Object_top,x
    STA tileY
    JSR GetTileAtPosition
    JSR DetermineCollisionTable
    STA collisionPoint1
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
	
	;; If trapped under a wall, force crouch animation  !!!! ==== Change this to your crouched action state!!! ==== !!!!
	ChangeObjectState #$03, #$04
	
	;; Are we touching the ground?
	LDA Object_physics_byte,x
    AND #%00000001
    BNE +
	
    JSR ejectDown
	
    JMP doneEjecting
+   
++
LDA #$00
STA tempPlrTunnel
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; check for ejecting up.

	LDA #$00
	STA tile_solidity

    LDA Object_x_hi,x
    CLC
    ADC Object_left,x
    STA tileX
    LDA #$00
    BCC +
    LDA #$01
+
    STA tempCol
    
    LDA yHold_hi
    CLC
    ADC Object_bottom,x

    STA tileY
    JSR GetTileAtPosition
    JSR DetermineCollisionTable
    ;STA collisionPoint0
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
    JSR ejectUp 
    JMP doneEjecting
+   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	 LDA tile_solidity
	  AND #%00000010 ;; check ladder type
	  BEQ +
	LDA #$00
	  STA tile_solidity
	; ; ;;; is a ladder type so now we need to do more checks.
	
	  LDA tileY
	  SEC
	  SBC #$04
	  STA tileY
	 JSR GetTileAtPosition
	 JSR DetermineCollisionTable
	 JSR CheckForCollision
	 LDA tile_solidity
	 AND #%00000010
	 BNE +
	 LDA Object_v_speed_lo,x
	 CLC
	 ADC #$00
	 LDA Object_v_speed_hi,x
	 ADC #$00
	 BMI +
	 ;;; now, check to see if we're pressing down, to "enter" the ladder 
	 LDA gamepad
	AND #%00100000 ; if down is pressed
	BEQ ++

	LDA Object_physics_byte,x
	ORA #%00000010
	STA Object_physics_byte,x
	jmp ++++ ;; jump to checking other point.
++
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	LDA tileY
	CLC
	ADC #$04
	STA tileY
	JSR ejectUp
	LDA Object_physics_byte,x
	AND #%11111101
	STA Object_physics_byte,x
	JMP doneEjecting
 +
;;;;;;;;;;;;; WAS NOT A LADDER TYPE
	;;; check to see if there is a jumpthrough platform below us.
	LDA tile_solidity
	AND #%00000100
	BEQ ++++
	;;;we are colliding with a one way platform.
	;;; we need to check to see if we are on top of the platform.
	LDA Object_v_speed_lo,x
	CLC
	ADC #$00
	LDA Object_v_speed_hi,x
	ADC #$00
	BMI ++++
	;;;; check the space just above to make sure it is clear 
	LDA #$00
	STA tile_solidity
	  LDA tileY
	  SEC
	  SBC #$08
	  STA tileY
	 JSR GetTileAtPosition
	 JSR DetermineCollisionTable
	 JSR CheckForCollision
	 LDA tile_solidity
	 AND #%00000100
	 BNE ++++
	 LDA Object_physics_byte,x
	 ORA #%00001000
	 STA Object_physics_byte,x
	 LDA tileY
	 CLC
	 ADC #$08
	 STA tileY
	JSR ejectUp
	JMP doneEjecting

++++
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	LDA #$00
	STA tile_solidity
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    LDA Object_x_hi,x

    CLC
    ADC Object_right,x
    STA tileX
    LDA #$00
    BCC +
    LDA #$01
+
    STA tempCol
    
    LDA yHold_hi
    CLC
    ADC Object_bottom,x
    
    STA tileY
    JSR GetTileAtPosition
    JSR DetermineCollisionTable
    ;STA collisionPoint0
    JSR CheckForCollision
    LDA tile_solidity
	AND #%00000001
    BEQ +
	LDA Object_physics_byte,x
	AND #%11111101
	STA Object_physics_byte,x
    JSR ejectUp
    JMP doneEjecting
+   

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	 LDA tile_solidity
	 AND #%00000010 ;; check ladder type
	 BEQ +
	LDA #$00
	 STA tile_solidity
	; ; ;;; is a ladder type so now we need to do more checks.
	 LDA tileY
	 SEC
	 SBC #$04
	 STA tileY
	 JSR GetTileAtPosition
	 JSR DetermineCollisionTable
	 JSR CheckForCollision
	 LDA tile_solidity
	 AND #%00000010
	 BNE +
	 LDA Object_v_speed_lo,x
	 CLC
	 ADC #$00
	 LDA Object_v_speed_hi,x
	 ADC #$00
	 BMI +
	 	 ;;; now, check to see if we're pressing down, to "enter" the ladder 
	 LDA gamepad
	AND #%00100000 ; if down is pressed
	BEQ ++

	LDA Object_physics_byte,x
	ORA #%00000010
	STA Object_physics_byte,x
	jmp doneEjecting
++
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	LDA tileY
	CLC
	ADC #$04
	STA tileY
	JSR ejectUp
	 LDA Object_physics_byte,x
	 AND #%11111101
	 STA Object_physics_byte,x
	JMP doneEjecting
 +
 
 ;;;;;;;;;;;;; WAS NOT A LADDER TYPE
	;;; check to see if there is a jumpthrough platform below us.
	LDA tile_solidity
	AND #%00000100
	BEQ ++++
	;;;we are colliding with a one way platform.
	;;; we need to check to see if we are on top of the platform.
	LDA Object_v_speed_lo,x
	CLC
	ADC #$00
	LDA Object_v_speed_hi,x
	ADC #$00
	BMI ++++
	;;;; check the space just above to make sure it is clear 
	LDA #$00
	STA tile_solidity
	  LDA tileY
	  SEC
	  SBC #$08
	  STA tileY
	 JSR GetTileAtPosition
	 JSR DetermineCollisionTable
	 JSR CheckForCollision
	 LDA tile_solidity
	 AND #%00000100
	 BNE ++++
	 LDA Object_physics_byte,x
	 ORA #%00001000
	 STA Object_physics_byte,x
	 LDA tileY
	 CLC
	 ADC #$08
	 STA tileY
	JSR ejectUp
	JMP doneEjecting

++++
    ;JMP noEjection
doneEjecting:

    LDX currentObject   
    LDY tempy
    ;rts 
;;===============================================
;;===============================================   
noEjection:;;;;;;;;;;;;;;;;;;;
;   JMP UpdatePositionToHold
    
	ENDM

Now tiles should work with the 'skip top collision' flag, allowing your player to duck underneath them.
You will still likely need to play around with the scripts controlling your action states to get it working just right. Make sure you have an action that can get the player out of a 'tunnel' if they get stuck. (In my game, the player cannot walk when they are stuck in a tunnel, but they can slide/dash again in either direction)

Gif of change in action coming soon!
 

dale_coop

Moderator
Staff member
Hey chronicleroflegends, looks great! Thanks for sharing.
Will try your script when I will have some time.
 
Top Bottom