Give your player a shadow [4.5.9]

SciNEStist

Well-known member
If you want your player character to cast a shadow on the ground, this is how I was able to do it. It's a great way to add some polish to your game, but it also has the functionality of helping players in platform games calculate their jumps easier. It was written to be compatible with the sloped tiles tutorial found HERE. If anyone has suggestions on making it more efficient, I would love to hear it.

STEP 1: in your gameobjects tiles, draw a small shadow and a large shadow. like so:
shadows.png

Remember where you put them, cause you will need to edit some code later to point to the right tile.

step 2: in Nesmaker. navigate to Scripts > defined Scripts, then go Game >post sprite draw. it should open up DoPostSpriteDraw.asm. Paste the following code:

Code:
;THIS PART CHECKS IF YOU ARE IN THE RIGHT GAME STATE
LDA gameState
CMP #$00
BEQ +
    JMP +nohit
+

THIS PART GETS THE X AND Y POSITIONS OF THE PLAYER
LDX player1_object
LDA Object_x_hi,x ; get player x coord
ADC #$08
STA tempx
LDA Object_y_hi,x; get player y coord
ADC #$04
STA tempy

; THIS PART FIGURES OUT WHAT SCREEN YOU ARE ON AND GETS THE COLLISION TABLE FOR THE ONE YOU ARE ON
LDA Object_screen, x
AND #%00000001
BNE +othertable
    LDA #$00
    JMP +
    +othertable
    LDA #$01
+
STA tempA ;;this saves the collision table for later use

;THIS SECTION STARTS AT THE THE PLAYER POSITION AND MOVES DOWNWARD 8 PIXELS AT A TIME IN A LOOP UNTIL IT FINDS A SOLID TILE

LDX #$00 ;; x will be our counter for how many checks we have done.
floorcheckloop: ; this loop checks under the player for tiles we want to cast a shod on, if it doesnt see it, it check lower and tries again
    CPX #$0F ;;this is the check counter, to keep track of how many times we went through this loop
    BNE +
        JMP +nohit ;; if the check counter gets too high, we give up and theres no shadow.
    +
    LDA tempy
    ADC #$08  ;; go down 8 more pixels
    STA tempy
    CheckCollisionPoint tempx, tempy, #$01, tempA ; check for a solid tile
    BNE +
        LDA #$01
        STA tempB
        JMP +hitsolid
    +
    CheckCollisionPoint tempx, tempy, #$07, tempA ; check for a jumpthrough tile
    BNE +
        LDA #$07
        STA tempB
        JMP +hitsolid
    +
    CheckCollisionPoint tempx, tempy, #$0B, tempA ; check for left slope
    BNE +
        LDA #$0B
        STA tempB
        JMP +hitsolid
    +
    CheckCollisionPoint tempx, tempy, #$0C, tempA ;; check for right slope
    BNE +
        LDA #$0C
        STA tempB
        JMP +hitsolid
    +
    ;nothing got hit, so we move down more and try again
        INX ; increase out check count, which will come in handy later to tell us how far down the tile is
        JMP floorcheckloop ;;no hit yet, go back and try again


;THIS PART IS TRIGGERED WHEN A SOLID TILE IS DETECTED
+hitsolid
floorcheckloop2: ;;in this loop, we go back up 1 pixel at a time until we are no longer hitting the tile. this will give us the very top of the tile.
    LDA tempy
    SBC #$01
    STA tempy
    CheckCollisionPoint tempx, tempy, tempB, tempA
    BNE +
        JMP floorcheckloop2
    +
    LDA tempB
    CMP #$0B
        BEQ IsSlope_L
    CMP #$0C
        BEQ IsSlope_R
    JMP +solidblockhit

    SlopeTileTable_L:  ;;left slope table that lists our offsets, taken from Knietfeld's MUST HAVE script!
        .db #$0f, #$0e, #$0d, #$0c, #$0b, #$0a, #$09, #$08, #$07, #$06, #$05, #$04, #$03, #$02, #$01, #$00
    SlopeTileTable_R:  ;;right slope table that lists our offsets, taken from Knietfeld's MUST HAVE script!
        .db #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07, #$08, #$09, #$0a, #$0b, #$0c, #$0d, #$0e, #$0f      
   
    IsSlope_L:   ;;pulls the offset from the left slope table
        lda tempx
        and #%00001111
        tay
        lda SlopeTileTable_L,y
        jmp SlopeshadopwOffsetFound  
    IsSlope_R:  ;;pulls the offset from the right slope table
        lda tempx          
        and #%00001111
        tay
        lda SlopeTileTable_R,y
   
    SlopeshadopwOffsetFound: ; this section combines the top of the tile and the offset from the table, creating the slope
        sta temp
        LDA tempy
        AND #%11110000
        clc
        adc temp
        SEC
        ADC #$10
        sta tempy
+solidblockhit ; now that we have the x and y coord along with how many blocks down it is, we can draw the shadow
        LDA tempx
        SBC camX ;;adjust for camera offset (important if scrolling)
        SBC #$04 ;; center it a bit by moving right 4 pixels
        STA tempx

        CPX #$04 ;x is our counter for how manyu times we went through the loop
        BCS +drawsmall ;; is the height more or less than 4 checks
            DrawSprite tempx, tempy, #$08, #%00000010, #$00 ;;draws a big shadow
            JMP +nohit
        +drawsmall
            DrawSprite tempx, tempy, #$28, #%00000010, #$00 ;; draws a small shadow
+nohit

STEP 3: edit the 3rd arguments on the DrawSprite lines near the end of the previous code so they are pointing to your big and small shadow sprites that you drew in the gameobject spritesheet.

now whenever you play, the shadow will be drawn large when the ground is close to the player, small when they are farther, and not at all when they are too far.
 

Amune138

New member
I love this.
Is there a way to get the shadow below the player when you walk below a jump through platform tile?
Thank You!!!
 

SciNEStist

Well-known member
this script should put a shadow below you if you are above a solid tile, a jump-through platform tile, or either a left or right slope tile. Are you saying it's not working if you are standing below a jump-through tile?
 

Amune138

New member
this script should put a shadow below you if you are above a solid tile, a jump-through platform tile, or either a left or right slope tile. Are you saying it's not working if you are standing below a jump-through tile?
yes walking through/underneath a jump-through platform i get a shadow on top of the player which is the bottom of the jump through platform [if that makes since].Screenshot 2023-09-22 084031.png
 

SciNEStist

Well-known member
in that case, you will want to start the checks a bit lower, so the line # 14 that currently looks like this:
Code:
ADC #$04
STA tempy

could be moved lower like this:

Code:
ADC #$0A
STA tempy
 

9Panzer

Well-known member
Excellent tutorial @SciNEStist ! I don’t think I can use this one for panzer though… I don’t think panzer would allow a shadow to overcast him. You know …
 

SciNEStist

Well-known member
no worries there, as long as you put the code in "post sprite draw" , itll draw UNDER the player (pre sprite draw would go over the player) ;P
 
Top Bottom