chronicleroflegends
Member
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:
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.
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!
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!