LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

Making the camera follow the character around the map

Root / Programming Questions / [.]

spaceturtlesCreated:
How exactly do I make the "camera" follow the player around a map until the camera reaches an edge of the map using the circle pad? I figured out how to do it one axis at a time but when the character reaches for instance the left edge the camera doesn't follow the character up or down. The same goes for any other edge. Code showing exactly how to do this properly is appreciated.

'try this
INC cam_x,(player_x-cam_x)/10
INC cam_y,(player_y-cam_y)/10

That does make it follow the player around until it hits an edge but how do I keep the camera centered on the player when it's not at an edge? Also my player distance is limited to the screen size so I can't scroll over the whole map with that.

That does make it follow the player around until it hits an edge but how do I keep the camera centered on the player when it's not at an edge? Also my player distance is limited to the screen size so I can't scroll over the whole map with that.
I really have no idea what you mean. Sorry.

How do I scroll the bg map until it hits an edge, move the sprite when the map can't move, allow the map to move along the border it touches, and make the map move again when the player is in the middle of the screen moving away from the edge so that it looks like the view follows the player around with the player in the center of the view until it reaches a border and then the player can move freely towards the border without the area outside of the map being visible? Basically like how player and camera movement works in starbound and terraria.

I haven't actually put this in SmileBasic just a notepad window, so there might be bugs, etc. Anyway, will something like this help?
OPTION STRICT

'Variable declarations
VAR SCREEN_W% = 400, SCREEN_H% = 240	'The size of the screen (width is 320 on the bottom screen)
VAR TILE_W% = 16, TILE_H% = 16		'Tile size, 16 is the default.
VAR MAP_W% = 64, MAP_H% = 64		'The size of our map. Chose the default from the smile tool editor
VAR CAM_MIN_X% = 0			'This the the smallest we allow the camera position.
VAR CAM_MIN_Y% = 0
VAR CAM_MAX_X% = (MAP_W% * TILE_W%) - SCREEN_W% - 1	'This is the largest we allow the camera position.
VAR CAM_MAX_Y% = (MAP_H% * TILE_H%) - SCREEN_H% - 1
VAR CAM_OFFS_X% = (SCREEN_W% - TILE_W%) / 2		'Offset of the camera from the player. Half a screen away minus have a sprite away
VAR CAM_OFFS_Y% = (SCREEN_H% - TILE_H%) / 2
VAR CAM_X% = 0 						'Where is the camera right now.
VAR CAM_Y% = 0
VAR PLAYER%						'Player sprite
VAR PLAYER_SPEED% = 3					'How fast does the player move.
VAR PLAYER_X% = ((MAP_W% * TILE_W%) - TILE_W%) / 2	'Put the player is the center of the map.
VAR PLAYER_Y% = ((MAP_H% * TILE_H%) - TILE_H%) / 2
VAR DX%, DY%, SX#, SY#, B%				'DX, DY = movement offset, SX, SY = circle pad status, B = Button status
VAR GAME_OVER% = FALSE					'Are we still playing the game
VAR I%, J%						'Generic loop counter variables.

ACLS							'Reset everything to default
BGSCREEN 1, MAP_W%, MAP_H%				'Resize the screen

'Fill the background with random junk.
FOR J% = 0 TO MAP_H% - 1
	FOR I% = 0 TO MAP_W% - 1
		BGPUT 1, I%, J%, RND(64) + 127
	NEXT I%
NEXT J%

'Make a sprite for the camera to follow around.
SPSET 413 OUT PLAYER%

WHILE GAME_OVER% = FALSE
	'Get Button Status
	B% = BUTTON()
	'Get CirclePad Status
	STICK OUT SX#, SY#
	'Reset DX/DY to not moving
	DX% = 0
	DY% = 0
	'Calculate how we are moving.
	IF (SX# < -0.5) OR ((B% AND #LEFT) != 0) THEN
		DX% = -1
	ENDIF
	IF (SX# > 0.5) OR ((B% AND #RIGHT) != 0) THEN
		DX% = -1
	ENDIF
	IF (SY# > 0.5) OR ((B% AND #UP) != 0) THEN
		DY% = -1
	ENDIF
	IF (SY# < -0.5) OR ((B% AND #DOWN) != 0) THEN
		DY% = -1
	ENDIF

	'Check if game over
	IF (B% AND #X) != 0 THEN
		GAME_OVER% = TRUE
	ENDIF

	'This could be more compact. Aiming for readability here.
	'
	'Update player position based on the input
	PLAYER_X% = PLAYER_X% + (DX% * PLAYER_SPEED%)	
	PLAYER_Y% = PLAYER_Y% + (DY% * PLAYER_SPEED%)

	'Clip their (world) location to the size of the map
	PLAYER_X% = MIN((MAP_W% * TILE_W%) - TILE_W% - 1, PLAYER_X%)
	PLAYER_X% = MAX(0, PLAYER_X%)
	PLAYER_Y% = MIN((MAP_Y% * TILE_H%) - TILE_H% - 1, PLAYER_Y%)
	PLAYER_Y% = MAX(0, PLAYER_Y%)

	'Make the camera follow the player.
	CAM_X% = PLAYER_X% - CAM_OFFS_X%
	CAM_Y% = PLAYER_Y% - CAM_OFFS_Y%

	'Clip the camera location to the map minus screen size.
	CAM_X% = MIN(CAM_MAX_X%, CAM_X%)
	CAM_X% = MAX(CAM_MIN_X%, CAM_X%)
	CAM_Y% = MIN(CAM_MAX_Y%, CAM_Y%)
	CAM_Y% = MAX(CAM_MIN_Y%, CAM_Y%)
	
	'Move the background to the camera coordinates
	BGOFS 1, CAM_X%, CAM_Y%

	'Move the player to the correct location on screen.
	'PLAYER_X - CAM_X converts things from world coordinates to screen coordinates
	SPOFS PLAYER%, PLAYER_X% - CAM_X%, PLAYER_Y% - CAM_Y%

	'Don't go too fast.
	VSYNC
WEND

'CLEAN UP
ACLS
END

I think that works but the character keeps moving. I'm trying to find what got messed up. I'm still not sure why.

Thanks @seggiepants! I've figured it out and adapted the code.

It looks like the bug was in my circle pad handling. left and down should check that SX# < -0.5 and SY# < -0.5. I will see if I can go back and edit the post.