[4.5.6] Scrolling With Recentering

AllDarnDavey

Active member
ScrollRecenter2.gif

Just posting some Metroidvania scrolling improvements we've been working on in the help forum, where people could find it more easily. Along with my change to speed up the camera when the character is past the "scroll pad" so the camera will start to recenter itself until it reaches the scroll pad for that direction.

First you'll need a new byte added to ZeroPage RAM called camSpeedup.
camSpeedUpVar.PNG

Then you'll want to backup and replace your doUpdateCamera.asm with this one:
Code:
doUpdateCamera:	
	
	LDX camObject
 
	LDA Object_h_speed_lo,x	
	STA tempA
	LDA Object_h_speed_hi,x
	STA tempB
	
	LDA camX
	AND #%11110000
	STA tempz

	LDA scrollByte
	AND #%10100000
	BNE +scrollEngaged
		JMP skipScrollUpdate
+scrollEngaged:
	LDA camX_hi
	STA tempC ;; will hold.  If this is changed by the end of the routine
			;; then we need to update anything that should change when our camera
			;; has crossed the screen boundary, such as screenFlags.

	LDA scrollByte
	AND #%10000000
	BNE doHorizontalCameraUpdate
		JMP noHorizontalCameraUpdate
	doHorizontalCameraUpdate:

	LDA scrollByte
	AND #%01000000
	BNE doRightCameraUpdate
	
		;; is left camera update
		LDA camX_lo
		SEC
		SBC tempA
		SBC camSpeedup	;;add camera speed boost to recenter player
		STA camX_lo
		LDA camX
		SBC tempB
		STA temp
			BCS +skipCheckForScrollScreenEdge
				LDA ScreenFlags00
				AND #%00100000
				BEQ +skipCheckForScrollScreenEdge
					JMP noHorizontalCameraUpdate
		+skipCheckForScrollScreenEdge
		LDA temp
		STA camX
		
		LDA camX_hi
		SBC #$00
		STA camX_hi
		JSR getCamSeam
		JMP noHorizontalCameraUpdate
	doRightCameraUpdate
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;;; Here, we have to check the right side of the screen
	;;; to see if we're lined up with the edge.
		LDA camX
		ADC tempB
		ADC #$FF
			BCC +skipCheckForScrollScreenEdge
				LDA ScreenFlags00
				AND #%00010000
				BEQ +skipCheckForScrollScreenEdge
					JMP skipAllScrollSeamUpdate
		+skipCheckForScrollScreenEdge
	
		LDA camX_lo
		clc
		adc tempA
		ADC camSpeedup	;;add camera speed boost to recenter player
		STA camX_lo
		LDA camX
		adc tempB
  
		STA camX
		LDA camX_hi
		adc #$00
		STA camX_hi
		JSR getCamSeam
	noHorizontalCameraUpdate:
	LDA scrollByte
	AND #%00000001
	BEQ +canUpdateScrollColumn
		JMP skipScrollUpdate
+canUpdateScrollColumn
	LDA scrollByte
	AND #%00000010
	BNE forceScrollColumnUpdate
	LDA camX
	AND #%11110000
	CMP tempz
	BNE +canUpdateScrollColumn2
		JMP skipScrollUpdate
forceScrollColumnUpdate:
	LDA scrollByte
	AND #%11111101
	STA scrollByte
+canUpdateScrollColumn2

		LDA scrollByte
		ORA #%00000101
		STA scrollByte
		;;;;;;;;;; DO SCROLL UPDATE.
		SwitchBank #$16
			LDY scrollUpdateScreen
			LDA warpMap
			BEQ +loadFromMap1
				;; load from map 2
				
				LDA NameTablePointers_Map2_lo,y
				STA temp16
				LDA NameTablePointers_Map2_hi,y
				STA temp16+1
				

				LDA AttributeTables_Map2_Lo,y
				STA pointer
				LDA AttributeTables_Map2_Hi,y
				STA pointer+1
				
				
				LDA CollisionTables_Map2_Lo,y
				STA pointer6
				LDA CollisionTables_Map2_Hi,y
				STA pointer6+1
				
				LDY camScreen
				LDA CollisionTables_Map2_Lo,y
				STA pointer2
				LDA CollisionTables_Map2_Hi,y
				STA pointer2+1
				JMP +doneWithGettingOffset
			+loadFromMap1
			
				LDA NameTablePointers_Map1_lo,y
				STA temp16
				LDA NameTablePointers_Map1_hi,y
				STA temp16+1
				

				LDA AttributeTables_Map1_Lo,y
				STA pointer
				LDA AttributeTables_Map1_Hi,y
				STA pointer+1
				
				
				LDA CollisionTables_Map1_Lo,y
				STA pointer6
				LDA CollisionTables_Map1_Hi,y
				STA pointer6+1
				
				LDY camScreen
				LDA CollisionTables_Map1_Lo,y
				STA pointer2
				LDA CollisionTables_Map1_Hi,y
				STA pointer2+1
			+doneWithGettingOffset:
		ReturnBank
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;; now we have pointers for the fetch.
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;; We can read from the pointers to get metatile data.
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;; jump to the bank
		LDA scrollUpdateScreen	
		LSR
		LSR
		LSR
		LSR
		LSR
		STA temp ; bank
		LDA warpMap
		BEQ +gotWarpMap
			LDA temp
			;; it was underground, add 8 to warp map
			CLC
			ADC #$08
			sta temp
		+gotWarpMap
		
		SwitchBank temp
			; LDX screenState
			; LDY Mon1SpawnLocation,x
			; LDA (pointer6),y
			; STA scrollUpdateObjectLocation
			
			; LDY Mon2SpawnLocation,x
			; LDA (pointer6),y
			; STA scrollUpdateObjectLocation+1
			
			; LDY Mon3SpawnLocation,x
			; LDA (pointer6),y
			; STA scrollUpdateObjectLocation+2
			
			; LDY Mon4SpawnLocation,x
			; LDA (pointer6),y
			; STA scrollUpdateObjectLocation+3
			
			LDX screenState
			LDY Monster1ID,x
			LDA (pointer6),y
			STA tempD
			LDY Mon1SpawnLocation,x
			JSR checkSeamForMonsterPosition
			
			LDX screenState
			LDY Monster2ID,x
			LDA (pointer6),y
			STA tempD
			LDY Mon2SpawnLocation,x
			JSR checkSeamForMonsterPosition
			
			LDX screenState
			LDy Monster3ID,x
			LDA (pointer6),y
			STA tempD
			LDY Mon3SpawnLocation,x
			JSR checkSeamForMonsterPosition
			
			LDX screenState
			LDy Monster4ID,x
			LDA (pointer6),y
			STA tempD
			LDY Mon4SpawnLocation,x
			JSR checkSeamForMonsterPosition
			
			
		
		
			LDA scrollUpdateScreen
			AND #%00000001
			ASL
			ASL
			ORA #%00100000
			STA temp1 ;; temp 1 now represents the high byte of the address to place 
			
			LDA scrollUpdateColumn
			LSR
			LSR
			LSR
			AND #%00011111
			STA temp2 ;; temp 2 now represents the low byte of the pushes.
			
			LDA scrollUpdateColumn
			LSR
			LSR
			LSR
			LSR
			STA temp3
			
			LDA #$00
			STA scrollOffsetCounter			
					
			LDX #$00 ;; will keep track of scroll update ram.
			LDA #$0F
			STA tempA ;; will keep the track of how many tiles to draw.
					;; #$0f is an entire column.
			loop_LoadNametableMeta_column:
				LDY temp3
				LDA (temp16),y
				STA temp
				JSR doGetSingleMetaTileValues
				
				LDA temp1
				STA scrollUpdateRam,x
				INX
				LDA temp2
				STA scrollUpdateRam,x
				INX
				LDA updateTile_00
				STA scrollUpdateRam,x
				INX 
				
				LDA temp1
				STA scrollUpdateRam,x
				INX
				LDA temp2
				CLC
				ADC #$01
				STA scrollUpdateRam,x
				INX
				LDA updateTile_01
				STA scrollUpdateRam,x
				INX 
				
				LDA temp1
				STA scrollUpdateRam,x
				INX
				LDA temp2
				CLC
				ADC #$20
				STA scrollUpdateRam,x
				INX
				LDA updateTile_02
				STA scrollUpdateRam,x
				INX 
				
				LDA temp1
				STA scrollUpdateRam,x
				INX
				LDA temp2
				CLC
				ADC #$21
				STA scrollUpdateRam,x
				INX
				LDA updateTile_03
				STA scrollUpdateRam,x
				INX 
				
				DEC tempA
				LDA tempA
				BEQ +doneWithNtLoad
					;; not done with NT load.  Need more tiles.
					;;;;;;;;;;;;;;;;;;;;;;;;;;
					;; update the 16 bit position of the new place to push tiles to.
					LDA temp2
					CLC
					ADC #$40
					STA temp2
					LDA temp1
					ADC #$00
					STA temp1
					;; update the tile read location.
					LDA temp3
					CLC
					ADC #$10
					STA temp3
					JMP loop_LoadNametableMeta_column	
			+doneWithNtLoad
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;;;;;; add attributes to the update list.
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;;; 23 = 00100011
		;;;; 27 = 00100111
		;;;; so the last bit of scrollUpdateScreen and shift it twice to the left
		;;;; then or it with 00100000 to get the high byte of the attribute update table.
				LDA scrollUpdateScreen
				AND #%00000001
				ASL
				ASL
				;ASL
				ORA #%00100011
				STA temp1 ;; this is now the high byte of the attribute table update
				
				LDA scrollUpdateColumn
				LSR
				LSR
				LSR
				LSR
				LSR
	
				STA temp2 ;; temp 2 now represents the low byte of the pushes.
				;; don't need a temp3 to keep track of pull position, because it will be 1 to 1.
				
				LDA #$08
				STA tempA ;; will keep the track of how many tiles to draw.
					;; #$0f is an entire column.
				loop_LoadAttribute_column:
			
					LDY temp2
					LDA (pointer),y
					STA temp
					
					LDA temp1
					STA scrollUpdateRam,x
					INX
					LDA temp2
					CLC
					ADC #$c0
					STA scrollUpdateRam,x
					INX
					LDA temp
					STA scrollUpdateRam,x
					INX 
					DEC tempA
					LDA tempA
					BEQ +doneWithAtLoad
						LDA temp2
						CLC
						ADC #$08
						STA temp2
						JMP loop_LoadAttribute_column
					+doneWithAtLoad
					
					
				TXA
				STA maxScrollOffsetCounter

				LDA updateScreenData
				ORA #%00000100
				STA updateScreenData

		
				LDA scrollUpdateColumn
				LSR
				LSR
				LSR
				LSR 
				STA temp1 ;; keeps track of where to place on the collision table.
				LSR 
				STA temp2 ;; keeps track of the nubble being pulled from.
				LDX #$0F ;; keep track of how many values to load are left.
			
				LDA scrollUpdateScreen
				AND #%00000001
				BNE +doUpdateOddCt
					;; do update even CT
					;; to ct table 1
					doUpdateCtLoop
						LDA temp1
						AND #%00000001
						BNE +oddCol
							LDY temp2
							LDA (pointer6),y
							LSR
							LSR
							LSR
							LSR
							JMP +pushToCol
						+oddCol
							LDY temp2	
							LDA (pointer6),y
							AND #%00001111
						
						+pushToCol:
							LDY temp1
							STA collisionTable,y
							LDA temp1
							CLC
							ADC #$10
							STA temp1
							LDA temp2
							CLC
							ADC #$08
							STA temp2
							DEX
							BNE doUpdateCtLoop
							JMP +doneWithCtLoad
				+doUpdateOddCt
					;; do update odd ct
					;; to ct table 2
					doUpdateCtLoop2
						LDA temp1
						AND #%00000001
						BNE +oddCol
							LDY temp2
							LDA (pointer6),y
							LSR
							LSR
							LSR
							LSR
							JMP +pushToCol
						+oddCol
							LDY temp2	
							LDA (pointer6),y
							AND #%00001111
						
						+pushToCol:
							LDY temp1
							STA collisionTable2,y
							LDA temp1
							CLC
							ADC #$10
							STA temp1
							LDA temp2
							CLC
							ADC #$08
							STA temp2
							DEX
							BNE doUpdateCtLoop2
							JMP +doneWithCtLoad
				+doneWithCtLoad
		LDA tempC
		CMP camX_hi
		BEQ +skipUpdatingScreenFlags
	
				;; update screen flags.
				LDY #124
				LDA (pointer2),y
				STA ScreenFlags00
				LDY #182
				LDA (pointer2),y
				STA ScreenFlags01
			+skipUpdatingScreenFlags
			;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		ReturnBank
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;; here check camX_hi against tempD
		;;; if they are the same, that means we haven't changed screen boundaries.
		;;; if they have changed, it means we have changed screen boundaries, so 
		;;; we should load in the new screenFlags data.

			
		
		
skipScrollUpdate
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make sure we always update camScreen.
	LDA camY_hi
	ASL
	ASL
	ASL
	ASL
	CLC
	ADC camX_hi
	STA camScreen
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	JSR checkForMonsterCameraClipping
skipAllScrollSeamUpdate:	
	RTS
	
	
	
getCamSeam:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Since we use camScreen in this subroutine, we'll have to make sure it's properly updated
;;; before get our column and screen.
	LDA camY_hi
	ASL
	ASL
	ASL
	ASL
	CLC
	ADC camX_hi
	STA camScreen
	
	LDA scrollByte
	AND #%01000000
	BNE +getRightScrollUpdate
		;; get left scroll update
		
		
		LDA camX
		AND #%11110000
		sec
		sbc #$70
		STA scrollUpdateColumn
		LDA camScreen
		sbc #$00
		STA scrollUpdateScreen

	RTS
	+getRightScrollUpdate

		LDA camX
		AND #%11110000
		CLC
		ADC #$80
		STA scrollUpdateColumn
		LDA camScreen
		ADC #$01
		STA scrollUpdateScreen

	RTS
	
	
	
checkForMonsterCameraClipping:

;;; use temp16 to check for cam clips
	LDA camX_hi
	AND #%00001111
	BNE notOnZeroScreen
	LDA #$00
	STA temp16
	LDA camX_hi
	STA temp16+1
	JMP +gotIt
notOnZeroScreen:

	LDA camX
	SEC
	SBC #$80
	STA temp16 ;; low left cam clip
	LDA camX_hi
	;AND #%00001111
	SBC #$00
	AND #%00001111
	STA temp16+1 ;; high left cam clip
+gotIt:	
	LDA camX
	CLC
	ADC #$80
	STA pointer ;; low right cam clip
	LDA camX_hi
	
	ADC #$01
	AND #%00001111
	STA pointer+1 ;; high right cam clip

	LDX #$00
	skipCheckingThisObject_forEraseColumnLoop
		cpx player1_object
		BEQ doEraseNonPlayerObjectsInThisColumnLoop
			LDA Object_status,x
			AND #%10000000
			BEQ doEraseNonPlayerObjectsInThisColumnLoop
			;; check this monster's position
			LDA Object_x_hi,x
			STA temp
			LDA Object_screen,x
			AND #%00001111
			STA temp1
			Compare16 temp16+1, temp16, temp1, temp
			+	
				DestroyObject
		
				JMP doEraseNonPlayerObjectsInThisColumnLoop
			++
		skipCheckingThisObject_forEraseColumnLoop2:
			Compare16 pointer+1, pointer, temp1, temp
			+
				JMP doEraseNonPlayerObjectsInThisColumnLoop
			++
				DestroyObject
		
			doEraseNonPlayerObjectsInThisColumnLoop
				INX
				CPX #TOTAL_MAX_OBJECTS
				BNE skipCheckingThisObject_forEraseColumnLoop

	RTS
	
checkSeamForMonsterPosition:
	;; y is loaded before subroutine.
			LDA (pointer6),y
			STA temp
			ASL
			ASL
			ASL
			ASL
			STA temp2
			LDA scrollUpdateColumn
			AND #%11110000
			CMP temp2
			BNE +noMonsterToLoadInThisColumn
				LDA temp
				AND #%11110000
				STA temp1
				CMP #%11110000
				BEQ +noMonsterToLoadInThisColumn
					CreateObjectOnScreen temp2, temp1, tempD, #$00, scrollUpdateScreen
			+noMonsterToLoadInThisColumn:
	RTS

You'll also want to backup and replace the normal do_simpleScrollRight.asm input script with this one:
Code:
	RIGHT_SCROLL_PAD = #$30	;; screenspace x position scroll starts and recenters too
	LDX player1_object
	LDA Object_x_hi,x
	SEC
	SBC camX
	STA temp
	CMP #RIGHT_SCROLL_PAD 
	BCC +noScroll
	SBC #$08			;;if player is within this ammount of pixels of scroll pad, normal scroll speed
	CMP #RIGHT_SCROLL_PAD
	BCS +speedUpScroll
	JMP +normalScroll
	+noScroll
		LDA #$00
		STA camSpeedup	
		LDA scrollByte
		AND #%00111111
		STA scrollByte
		RTS	
	+speedUpScroll	
		;PlaySound #sfx_whip  ;;I like to use sounds as code simple debugs for code execution
		LDA #$FF		;;add to camera speed
		STA camSpeedup
		LDA scrollByte
		AND #%01000000
		BNE +
		LDA scrollByte
		ORA #%00000010
	+
		AND #%00111111
		ORA #%11000000  ;; bit one forces an update.
		STA scrollByte
		RTS
	+normalScroll
		;PlaySound #sfx_cursor  ;;I like to use sounds as code simple debugs for code execution
		LDA #$00		;;reset camera speed
		STA camSpeedup
		LDA scrollByte
		AND #%01000000
		BNE +
		LDA scrollByte
		ORA #%00000010
	+
		AND #%00111111
		ORA #%11000000  ;; bit one forces an update.
		STA scrollByte
		RTS

And backup and replace your do_simpleScrollLeft.asm with this version:
Code:
    LEFT_SCROLL_PAD = #$B0 ;; screenspace x position scroll starts and recenters too
    LDX player1_object
    LDA Object_x_hi,x
    SEC
    SBC camX
	STA temp
	CMP #LEFT_SCROLL_PAD
	BCS +noScroll
	ADC #$08			;;if player is within this ammount of pixels of scroll pad, normal scroll speed
	CMP #LEFT_SCROLL_PAD
	BCC +speedUpScroll
	JMP +normalScroll
	+noScroll
		LDA #$00
		STA camSpeedup	
		LDA scrollByte
		AND #%00111111
		STA scrollByte
		RTS
	+speedUpScroll
		;PlaySound #sfx_whip  ;;I like to use sounds as code simple debugs for code execution
		LDA #$FF		;;add to camera speed
		STA camSpeedup
		LDA scrollByte
		AND #%01000000
		BEQ +
		LDA scrollByte
		ORA #%00000010
	+    
		AND #%00111111
		ORA #%10000000  ;; bit one forces an update.
		STA scrollByte
		RTS
	+normalScroll
		;PlaySound #sfx_cursor  ;;I like to use sounds as code simple debugs for code execution
		LDA #$00		;;reset camera speed
		STA camSpeedup
		LDA scrollByte
		AND #%01000000
		BEQ +
		LDA scrollByte
		ORA #%00000010
	+    
		AND #%00111111
		ORA #%10000000  ;; bit one forces an update.
		STA scrollByte
		RTS

TWEAKABLES:
#LEFT_SCROLL_PAD
#RIGHT_SCROLL_PAD

In the scroll input scripts, these set what screen relative x collumn to start scrolling and center the player on. Adjust these for how much space in front of the player you want when scrolling either direction. I gave mine plenty of room for incoming reaction time, but you may want it set differently.
LDA #$FF ;;add to camera speed
This line in each scroll input script sets how fast the camera recenters, mine's is set to max speed, adjust this to your liking.
SBC #$08 ;;if player is within this ammount of pixels of scroll pad, normal scroll speed
This ine in each scroll input (it's ADC #$08 in scroll left and SBC #$08 in scroll right) gives the exact scroll pad a buffer. I was getting slightly jerky scrolling once the camera had recentered at first because it couldn't hit a single pixel target, it would overshoot, stop scrolling for a single frame, start scrolling fast again and overshoot again, over and over. This adds an 8 pixel buffer to the scroll pad target to avoid overshooting it and causing jerky scrolling. Depending on the speed of your character you may need to increase this buffer ammount if your scrolling isn't smooth after the camera recenters on the scroll pad.

POSSIBLE FUTURE IMPROVEMENTS:
There's probably some optimizations that could be made. For instance, because we only need a scroll fast or scroll normal bool check, we could skip needing a new Zero Page RAM byte if we could find an unsed bit on an existing byte to set as our new "scroll fast bit". A single bit check on the "scrollByte" seems like an obvious candidate (if it's not using every bit for something already), but so far I have been unable to decipher what every scrollByte bit is for, and if there's an unused bit we could claim.
 

vanderblade

Active member
I finally got around to using this in my new game. It works like a charm. But for new users, beware, the tweaks to the simplescrolleft and simplescrollright will force you to start bankswitching your other input scripts if you don't want to run into bank overflow problems. It seems that 4.5.X requires this for any game that's more than a out-of-the-box demo. Not sure why there isn't a dedicated video explaining how to do it, but luckily, this isn't my first rodeo, and I learned how to do this on my last project.
 

Jonny

Well-known member
I finally got around to using this in my new game. It works like a charm. But for new users, beware, the tweaks to the simplescrolleft and simplescrollright will force you to start bankswitching your other input scripts if you don't want to run into bank overflow problems. It seems that 4.5.X requires this for any game that's more than a out-of-the-box demo. Not sure why there isn't a dedicated video explaining how to do it, but luckily, this isn't my first rodeo, and I learned how to do this on my last project.

You're using metroidvania base module right? I tried this out. The camera did speed up and re-centre but then just carried on scrolling until the player was off the screen. Probably to do with something else.

Ignore me, I'm a dope. For some reason I took out the constants for scroll padding from stop scrolling. I'm having problems with an unlock scroll tile causing problems. Hoping this or a version of it might help.
 
Last edited:

Jonny

Well-known member
@AllDarnDavey I've run into a quite strange issue with the re-centering. For some reason when I implemented it everything worked as it should eccept when I alter player speed, only moving left changes, so moving right is always slower. Change everything back to double check and now when I alter player max speed it works both directions. I can't figure out why that is.
 

AllDarnDavey

Active member
@AllDarnDavey I've run into a quite strange issue with the re-centering. For some reason when I implemented it everything worked as it should eccept when I alter player speed, only moving left changes, so moving right is always slower. Change everything back to double check and now when I alter player max speed it works both directions. I can't figure out why that is.
What you change the player speed to? I don't think I tested it with a whole lot values too far from default. Kind of sounds like a possible integer overflow or underflow for the camera speed, maybe we're adding or subtracting so much you go over 256 or under 0 and wrap around, and the code isn't properly handling it.
 

Jonny

Well-known member
What you change the player speed to? I don't think I tested it with a whole lot values too far from default. Kind of sounds like a possible integer overflow or underflow for the camera speed, maybe we're adding or subtracting so much you go over 256 or under 0 and wrap around, and the code isn't properly handling it.
It was set to 31. It could be something I've messed with else where, like another scrolling fix so I'll look into that. Being only one way your theory sounds right.

I actually wanted to make something maybe a bit simpler so when a a left side secret room scroll unlocks is triggered the cam moves to put player back in the middle of the screen. I don't really need it to be linked to player movement at all times. I'll try some other stuff out. Thanks.
 
Last edited:

vanderblade

Active member
You're using metroidvania base module right? I tried this out. The camera did speed up and re-centre but then just carried on scrolling until the player was off the screen. Probably to do with something else.

Ignore me, I'm a dope. For some reason I took out the constants for scroll padding from stop scrolling. I'm having problems with an unlock scroll tile causing problems. Hoping this or a version of it might help.
I actually ended up switching back to a modified LR_platforming_scrolling script from my brawler, especially since I only needed to scroll right for my Contra-Like. As a result, I had to drop some of the functionality of this modification, which sucks because the recentering worked great.
 

Jonny

Well-known member
Coming back to this tutorial after a while. I still can't figure out why my scrolling is fast while pushing against a solid (i.e no player object speed) but recentering is painfully slow when player moving left or right freely. Unlike the example, player takes about 10 or more screen to re-centre. Changing the speed works so I know I'm getting to that part of the code but FF only just gets scroll to speed up slightly. Tried messing with the hi byte of cam but that just crashed the game :(
 

Nerdzmania

New member
I tried this in my game (Metroidvania module, 4.5.9) but I can't get the game to compile now. I get the following error message:

Routines\BASE_4_5\\Game\Subroutines\doObjectAction.asm(84): Value out of range.

Not too sure what to do with this. I tried disabling stuff I don<t use in the Zero Page RAM but it doesn't seem to help.

Any ideas?


Update:
I wasn't using the right name for the camSpeedup byte... I am now getting a new error:

Routines\BASE_4_5\System\Vectors.asm(1): Value out of range.

As I always says: getting a new kind of error is a form of progress.
 
Last edited:

kevin81

Active member
Usually a Value out of range error in Vectors.asm indicates that your static bank is full. You'll need to either optimize some code, or move around a few scripts to free up space in bank #$1F.

Here's a post that relatively easily frees up about 15% of the static bank: Move doLoadScreen to Bank 16

Also, there's a nifty tool by Shiru called NES Space Checker, which will show you the amount of space you have left in each bank.
 

Nerdzmania

New member
Usually a Value out of range error in Vectors.asm indicates that your static bank is full. You'll need to either optimize some code, or move around a few scripts to free up space in bank #$1F.

Here's a post that relatively easily frees up about 15% of the static bank: Move doLoadScreen to Bank 16

Also, there's a nifty tool by Shiru called NES Space Checker, which will show you the amount of space you have left in each bank.
Thanks, the NES Space Checker tool indicated that PRG $1F was full, so I opened LoadAllSubRoutines and commented out everything that has to do with the HUD since I don't use it and voilĂ .
 
Top Bottom