Conveyor Belt Tiles 4.5.9

9Panzer

Well-known member
All right, I'm throwing my hat out there.
I cannot for the life of me figure out conveyor belt tiles. Hoping someone can pull a rabbit out of there hat. I know Mugi had a working one back in 4.1 but that doesn't seem to translate very well into 4.5.9. Hoping someone can put together something :)
 

kevin81

Well-known member
Here's what I came up with as a proof of concept:


I've only tested it in the Arcade platformer base, but it should work similarly in other (scrolling) platformer modules, as long as the conveyor belt doesn't span over multiple screens. Also, since it is just a PoC, the conveyor belt doesn't animate - I'd suggest you look up JamesNES' CHR-RAM switching technique if you want to do that.

Step 1. Choose a tile number for your conveyor belt
I picked 13 (or #$0D) for "Conveyor right":

conveyor-1.png


Step 2. Modify the doHandlePhysics subroutine
Open up the doHandlePhysics.asm script your module is using and find the part where the object's bottom collision is checked; the code snippet looks like this:

Code:
    GetCollisionPoint temp, temp1, tempA ;; is it a solid?
        CMP #$01
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid

Replace this code with the following:

Code:
    GetCollisionPoint temp, temp1, tempA
        CMP #$0D ;; is it a conveyor?
        BNE +
            JMP +isConveyor
        +
        CMP #$01 ;; is it a solid?
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid

Apply the same change to the next collision point check, about 15 lines lower:

Code:
    GetCollisionPoint temp3, temp1, tempA
        CMP #$0D ;; is it a conveyor?
        BNE +
            JMP +isConveyor
        +
        CMP #$01 ;; is it a solid?
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid

Finally, scroll down in the script to the line that says +isLadderSolid. Just above that line, paste the following:

Code:
    +isConveyor:
        LDA Object_v_speed_hi,x
        BPL +
            JMP +notSolid ;; a conveyor belt is not solid if moving up through it.
        +
   
        TYA
        AND #%11110000
        CLC
        ADC Object_v_speed_hi,x
        CMP temp1
        BEQ +doConvey
        BCS +doConvey
        JMP +notSolid
   
    +doConvey:
        LDA xHold_lo
        CLC
        ADC #$40 ;; this is the conveyor belt's subpixel speed - adjust to your liking
        STA xHold_lo
        STA Object_x_lo,x
       
        LDA xHold_hi
        ADC #$01 ;; this is the conveyor belt's pixel speed - adjust to your liking
        STA xHold_hi
        STA Object_x_hi,x


Step 3. Modify the jump input script

The conveyor belt now works, but you can't jump off of it yet. For this you need to modify the jump script of your game.
Open up the input script file that's linked to pressing A (usually jump_throughPlat.asm for platform games). If this script is unmodified, around line 24 you'll find the following code:

Code:
    CheckCollisionPoint temp, temp1, #$01, tempA ;; check below feet to see if it is solid.
                                        ;;; if it is (equal), can jump.
                                        ;;; if not, skips jumping.
     BNE +noJumpYet
        JMP +doJump
     +noJumpYet

This checks if the object is on a solid tile. Copy this part, paste it below and change the #$01 into #$0D (or the tile number you're using for the conveyor):

Code:
    CheckCollisionPoint temp, temp1, #$01, tempA ;; check below feet to see if it is solid.
                                        ;;; if it is (equal), can jump.
                                        ;;; if not, skips jumping.
     BNE +noJumpYet
        JMP +doJump
     +noJumpYet

    CheckCollisionPoint temp, temp1, #$0D, tempA ;; check below feet to see if it is a conveyor.
                                        ;;; if it is (equal), can jump.
                                        ;;; if not, skips jumping.
     BNE +noJumpYet
        JMP +doJump
     +noJumpYet

A little lower in code, you'll find a second collision point check which needs to also be copy/pasted for the conveyor:

Code:
CheckCollisionPoint temp, temp1, #$01, tempA ;; check below feet to see if it is solid.
                                        ;;; if it is (equal), can jump.
                                        ;;; if not, skips jumping.         
    BEQ +doJump
   
    ;;;;;;;;;;;;;;;;;;;
    ;; Added these lines
    CheckCollisionPoint temp, temp1, #$0D, tempA ;; check below feet to see if it is conveyor.
                                        ;;; if it is (equal), can jump.
                                        ;;; if not, skips jumping.         
    BEQ +doJump
    ;;;;;;;;;;;;;;;;;;;

This modification may result in a "Branch out of range" error. If so, find the row number where this occurs and change:
Code:
    BEQ +doJump   ;; check second point.
...into:
Code:
    BNE +
        JMP +doJump   ;; check second point.
    +


And you're done! You now have a right-moving conveyor belt tile type. If you need another one that moves left, you can assign a different tile number and repeat these steps with a different subroutine that subtracts instead of adds the speed.

Hope this helps!
 

9Panzer

Well-known member
Woah that worked like a charm! I think the part I was struggling with is having the object speed save and not get overridden by the standard physics! Thank you so much for sharing this @kevin81 now I just need to get the scroll to follow the player :)
 

9Panzer

Well-known member
This is the code I'm currently using. But its not going to be as pretty as you expect. Just add the last bit to the park after +doConvey

+doConvey:
LDA xHold_lo
SEC

SBC #64
;SBC #$40 ;; this is the conveyor belt's subpixel speed - adjust to your liking ;;64
STA xHold_lo
STA Object_x_lo,x

LDA xHold_hi
SBC #01 ;; this is the conveyor belt's pixel speed - adjust to your liking
STA xHold_hi
STA Object_x_hi,x

;;;;; NEWSTUFF

LDA #00
STA Object_h_speed_lo,x
LDA #01
STA Object_h_speed_hi,x
 

Shyartist

New member
heres my edited parts of doHandlePhysics

Code:
    ;;; CHECK FOR SOLID TILE, which is tile type 1 in this module.
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;; In this module, we have
        ;; 1 = solid
        ;; 7 = one way platform
        ;; 9 = prize block, which behaves as a solid
        ;; 10 (0A) = ladder, whose top behaves like a solid.
        ;; Here is where we handle the "landing" scenario for all of those possibilities.
     
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit pt1;;;;;;;;;;;;;;;;;;;;;;;     
;    GetCollisionPoint temp, temp1, tempA ;; is it a solid?
;        CMP #$01
;        BNE +isNotSolid
;            JMP +isSolid
;        +isNotSolid
    GetCollisionPoint temp, temp1, tempA
        CMP #$09 ;; is it a conveyor?
        BNE +
            JMP +isConveyor
        +
        CMP #$01 ;; is it a solid?
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit pt1;;;;;;;;;;;;;;;;;;;;;
        CMP #$07
        BNE +isNotOneWaySolid
            JMP +isOneWaySolid
        +isNotOneWaySolid
        CMP #$01
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid
;        CMP #$0A
        ;BEQ +isLadderSolid
     
;        BNE +isNotSolid
;            JMP +isSolid
;        +isNotSolid
     
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit pt 2;;;;;;;;;;;;;     
;    GetCollisionPoint temp3, temp1, tempA ;; is it a solid?
;        CMP #$01
;        BNE +isNotSolid
;            JMP +isSolid
;        +isNotSolid
    GetCollisionPoint temp, temp1, tempA
        CMP #$09 ;; is it a conveyor?
        BNE +
            JMP +isConveyor
        +
        CMP #$01 ;; is it a solid?
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit pt 2;;;;;;;;;;;;
        CMP #$07
        BNE +isNotSolid
            JMP +isOneWaySolid
        +isNotSolid
        CMP #$01;;;;;;;;;;;
        BNE +isNotSolid
            JMP +isSolid
        +isNotSolid
        CMP #$0A
        BEQ +isLadderSolid
            JMP +notSolid
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit pt3;;;;;;;;;;;;;;;;
    +isConveyor:
        LDA Object_v_speed_hi,x
        BPL +
            JMP +notSolid ;; a conveyor belt is not solid if moving up through it.
        +
 
        TYA
        AND #%11110000
        CLC
        ADC Object_v_speed_hi,x
        CMP temp1
        BEQ +doConvey
        BCS +doConvey
        JMP +notSolid
 
    +doConvey:
        LDA xHold_lo
        CLC
        ADC #$40 ;; this is the conveyor belt's subpixel speed - adjust to your liking
        STA xHold_lo
        STA Object_x_lo,x
    
        LDA xHold_hi
        ADC #$01 ;; this is the conveyor belt's pixel speed - adjust to your liking
        STA xHold_hi
        STA Object_x_hi,x
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit pt 3;;;;;;;;;;;;;;;;;;;;;;; 
    +isLadderSolid
        LDA Object_v_speed_hi,x
        BEQ +checkSolid
        BPL +checkSolid
            JMP +notSolid
        +checkSolid
        LDA temp1
        SEC
        SBC #$02
        SEC
        SBC Object_v_speed_hi,x
        STA tempy
        GetCollisionPoint temp, tempy, tempA ;; is it a solid
            BEQ +checkForSecondPoint
            CMP #$0A
            BEQ +notSolid
        GetCollisionPoint temp3, tempy, tempA ;; is it a solid? 
            BEQ +checkForFirstPoint
            CMP #$0A
            BEQ +notSolid
            JMP +isSolid
                +checkForSecondPoint
                    GetCollisionPoint temp3, tempy, tempA ;; is it a solid?
                    BEQ +isSolid
                    JMP +notSolid
                +checkForFirstPoint
                    GetCollisionPoint temp, tempy, tempA ;; is it a solid?
                    BEQ +isSolid
                    JMP +notSolid
                 
                 
    +isOneWaySolid
        ;; a special kind of solid
        LDA Object_v_speed_hi,x
        BMI +notSolid ;; a jumpthrough platform is definitely not solid if moving up through it.
            ;;; however, it is not solid if we haven't cleared it yet.
            TYA
            AND #%11110000
            CLC
            ADC Object_v_speed_hi,x
            CMP temp1
            BEQ +isSolid
            BCS +isSolid
            JMP +notSolid
         
    +isSolid

        JMP isSolidSoLand
 
 
 
        +notSolid:
     
 
            ;; is not solid, don't land.
            LDA Object_y_lo,x
            CLC
            ADC Object_v_speed_lo,x
            STA yHold_lo
            LDA Object_y_hi,x
            ADC Object_v_speed_hi,x
            STA Object_y_hi,x
            STA yHold_hi
         
            LDA Object_v_speed_lo,x
            CLC
            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
                BNE notOverFallSpeed
                    ;; is at least max fall speed.
                    LDA #$00
                    STA Object_v_speed_lo,x
                notOverFallSpeed:
             
             
         
            JMP doneWithGravity
 
isSolidSoLand:
    ;; move to position
    ;;; load the top of the tile that is being run into.
 
 
        ;; force y to tile boundary. 
;            LDA tileY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;         AND #%11000000;;edit
;         SEC
;         SBC self_bottom
;         SEC
;         SBC #$01
;         STA Object_y_hi,x
;         STA yHold_hi;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;edit;;;;;;;;;;;;;;;;;;;;;;;;;;
 
        LDA #$00
        STA Object_v_speed_lo,x
        STA Object_v_speed_hi,x
doneWithGravity:

skipPhysics:speed_hi,x
    STA Object_h_speed_lo,x
 

skipDoHdec:


    LDA directionByte
    AND #%00001111
    STA directionByte

    LDA Object_h_speed_lo,x
    STA tempA
    LDA Object_h_speed_hi,x
    STA tempB
 

    LDA Object_direction,x
    AND #%01000000
    BNE isMovingRight
    ;isMovingLeft
 
 
    ;;; set to check points 0 and 3 (top left and bottom left.)
    LDA collisionsToCheck
    ORA #%00001111
    STA collisionsToCheck
 
        LDA tempA
        CLC
        ADC tempB
 
Last edited:
Top Bottom