[4.5.6+] Minor Bugfix for metroVania Projectile Initialization

TakuikaNinja

Active member
(Edit: I was hinted at by someone on discord that there was a better way to fix this, so I did.)
(Edit 2: Optimized the entire initialization script.)
(Edit 3: Further optimizations using the START_SCREEN constants.)
Did you ever notice this bug?
When you export and run a metroVania game, try shooting a projectile without moving your player sprite.
The projectile will simply not move! If you're a perfectionist like me, that's completely unacceptable!

So here's a simple fix for it.
Copy + paste the following code into a new asm file and assign it as the initialization script instead of "initialization.asm":
Code:
;;initialization
;;; on a game to game basis, what data needs to be initialized will change.
	.include "ScreenData\init.ini"
	;;; this contains CONSTANTS information, like the starting screen and the game object palettes.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	
	LDA #$00
	STA soft2001
	JSR doWaitFrame
		;;; turn off rendering to load graphics.
		
	LDA #$FF
	STA songToPlay ;;; this will force "none" to play.
					;; which means that the first screen with a song that is not none
					;; will not be seen as the "Same songToPlay value", so it will play.
					;;; do this BEFORE screen loads.
		
	LDA #START_ON_SCREEN
	STA continueScreen
	STA currentNametable
	STA camScreen
	
	LDA #START_SCREEN_X
	STA camX_hi
	LDA #START_SCREEN_Y
	STA camY_hi
	
	LDA #START_LEVEL ;; right now, this is set up backwards, where 0 is underground.
	EOR #%00000001
	STA warpMap

	LDA gameHandler
	ORA #%10000000
	STA gameHandler

	LDX #$00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		CreateObject #START_POSITION_PIX_X, #START_POSITION_PIX_Y, #$00, #$00
		STX player1_object	
		STX camObject
		LDA currentNametable
		STA Object_screen,x
		LDA #FACE_RIGHT ;; default facing direction
		STA Object_direction,x
		LDA #START_POSITION_PIX_X
		STA newX
		STA continueX
		LDA #START_POSITION_PIX_Y
		STA newY
		STA continueY

	LDA #$00
	STA scrollTrigger
	;;;;; this sets up to ignore "screen edge" behavior
	;;;;; for scrolling games.
	;;Bit 7 = up
	;;Bit 6 = Down
	;;Bit 5 = left
	;;Bit 4 = right
	
	
	
	SwitchBank #$1B ;; switch to the music bank
					;; which contains the initializtion scripts.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; THIS SETS UP THE MUSIC ENGINE.
;;;; IF YOU USE A DIFFERENT MUSIC ENGINE
;;;; CHANGE THIS TO FIT YOUR NEEDS OF INITIALIZING YOUR MUSIC ENGINE.	
	lda #SOUND_REGION_NTSC ;or #SOUND_REGION_PAL, or #SOUND_REGION_DENDY
    sta sound_param_byte_0
    lda #<(song_list)
    sta sound_param_word_0
    lda #>(song_list)
    sta sound_param_word_0+1
    lda #<(sfx_list)
    sta sound_param_word_1
    lda #>(sfx_list)
    sta sound_param_word_1+1
    lda #<(instrument_list)
    sta sound_param_word_2
    lda #>(instrument_list)
    sta sound_param_word_2+1
    ;lda #<dpcm_list
    ;sta sound_param_word_3
    ;lda #>dpcm_list
    ;sta sound_param_word_3+1
    jsr sound_initialize


	ReturnBank
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Obtainable weapons
;; right now "bosses defeated" translates to weapons unlocked at start of the game.
;; this is found in the game info, and can be set there for a starting state.

	LDA #BOSSES_DEFEATED
	STA weaponsUnlocked
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Triggers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	LDA #INIT_TRIG_00
	STA screenTriggers+0
	LDA #INIT_TRIG_01
	STA screenTriggers+1
	LDA #INIT_TRIG_02
	STA screenTriggers+2
	LDA #INIT_TRIG_03
	STA screenTriggers+3
	LDA #INIT_TRIG_04
	STA screenTriggers+4
	LDA #INIT_TRIG_05
	STA screenTriggers+5
	LDA #INIT_TRIG_06
	STA screenTriggers+6
	LDA #INIT_TRIG_07
	STA screenTriggers+7
	LDA #INIT_TRIG_08
	STA screenTriggers+8
	LDA #INIT_TRIG_09
	STA screenTriggers+9
	LDA #INIT_TRIG_0a
	STA screenTriggers+10
	LDA #INIT_TRIG_0b
	STA screenTriggers+11
	LDA #INIT_TRIG_0c
	STA screenTriggers+12
	LDA #INIT_TRIG_0d
	STA screenTriggers+13
	LDA #INIT_TRIG_0e
	STA screenTriggers+14
	LDA #INIT_TRIG_0f
	STA screenTriggers+15
	LDA #INIT_TRIG_10
	STA screenTriggers+16
	LDA #INIT_TRIG_11
	STA screenTriggers+17
	LDA #INIT_TRIG_12
	STA screenTriggers+18
	LDA #INIT_TRIG_13
	STA screenTriggers+19
	LDA #INIT_TRIG_14
	STA screenTriggers+20
	LDA #INIT_TRIG_15
	STA screenTriggers+21
	LDA #INIT_TRIG_16
	STA screenTriggers+22
	LDA #INIT_TRIG_17
	STA screenTriggers+23
	LDA #INIT_TRIG_18
	STA screenTriggers+24
	LDA #INIT_TRIG_19
	STA screenTriggers+25
	LDA #INIT_TRIG_1a
	STA screenTriggers+26
	LDA #INIT_TRIG_1b
	STA screenTriggers+27
	LDA #INIT_TRIG_1c
	STA screenTriggers+28
	LDA #INIT_TRIG_1d
	STA screenTriggers+29
	LDA #INIT_TRIG_1e
	STA screenTriggers+30
	LDA #INIT_TRIG_1f
	STA screenTriggers+31
	
	;;;;;;;;;;;;;;DELETE ME
	.include "GameData\InitializationScripts\hudVarInits.asm"
	
	
	LDA #%00011110 ;;
	STA soft2001

This ensures the projectiles will move to the right when the game starts.
I hope y'all are as relieved as I am now.
 
Last edited:

weapon121

Member
Actually, this is in pretty much every MOD I think. It was happening in the Brawler MOD but I hadn't looked into it yet. This did the trick, thx!
 

TakuikaNinja

Active member
Edit: This is a little redundant for me now since optimizing the initialization script solved my NMI issue, but I'll leave this here anyway.
Here's an alternate solution which might be useful if you're messing with code in the fixed banks (initialization, main game loop, NMI, etc.).
Create a new .asm file and copy the following code in:
Code:
;;; Create a Projectile.
;;; Assumes that the projectile you want to create is in GameObject Slot 01.
;;; Assumes variable called myAmmo exists.
;;; assumes myAmmo is in hud element 8.
    LDA myAmmo
    BNE +canShootMega
        LDA #$01 ;; assumes normal projectile is in 1
        STA tempz ;; we will use tempz to hold which type of projectile.
                    ;;; if I had no special ammo, i'll just use normal projectile
        JMP +shootThing
    +canShootMega:
        ;;; but if i DID have ammo, I'll shoot mega shot!
        LDA #$02 ;; assumes mega projectile is in 2.
        STA tempz
    ;; there is ammo here.
    DEC myAmmo
  ;  UpdateHudElement #$03 ;; change this to which element shows myAmmo.
    +shootThing
    TXA
    PHA
    TYA
    PHA
        LDX player1_object
        LDA Object_x_hi,x
            CLC
        ADC #$04
        STA tempA
        LDA Object_screen,x
        ADC #$00
        STA tempD
        LDA Object_y_hi,x
            CLC
        ADC #$04
        STA tempB
        LDA Object_direction,x
	BNE +
		LDA #FACE_RIGHT
	+
        AND #%00000111
        STA tempC
        CreateObjectOnScreen tempA, tempB, tempz, #$00, tempD
            ;;; x, y, object, starting action.
            ;;; and now with that object, copy the player's
            ;;; direction and start it moving that way.
            LDA tempC
            STA Object_direction,x
            TAY
            LDA DirectionTableOrdered,y
            STA temp1
            TXA
            STA temp
            StartMoving temp, temp1
    PLA
    TAY
    PLA
    TAX
+canNotShoot:
    RTS
After that, it's simply a matter of using this script instead of "shootProjectile_scrolling_SuperAmmo.asm" in the input linker.
I also found another bug with the projectiles tonight. If you shoot enough projectiles at the right edge of the screen, you'll eventually be unable to shoot until you scroll the screen. I managed to make the game crash through this. I wonder if this has to do with the fact that there is no hard-coded limit for the number of projectiles on-screen at once?
If anyone can figure that one out, I'd love to hear it.
 

mouse spirit

Well-known member
Hmm . Maybe they arent "destroyed". If your game has scrolling, it may even have to do with that.does it happen on every screen or every other?
 

AllDarnDavey

Active member
TakuikaNinja said:
I also found another bug with the projectiles tonight. If you shoot enough projectiles at the right edge of the screen, you'll eventually be unable to shoot until you scroll the screen. I managed to make the game crash through this. I wonder if this has to do with the fact that there is no hard-coded limit for the number of projectiles on-screen at once?
If anyone can figure that one out, I'd love to hear it.

Yeah, I'm finding that too. I think you're right, they are not get properly destroyed at screen edge until the scroll seam updates. A crash is rare, but it did happen to me once as well, being unable to shoot after a bit until the screen is scrolled though is 100% reproducible. You could work around it by having short range projectiles that destroy themselves before reaching screen edge, kinda lame workaround though.
 

TakuikaNinja

Active member
I think I'll have to use that workaround for now, I guess.
Edit: Decreasing the number of animation frames for the projectiles seems to properly despawn them before reaching the scroll seam, so I'll stick with that.
 
Top Bottom