tile scrolling map (diablo 2 like)

Blitz3D Forums/Blitz3D Beginners Area/tile scrolling map (diablo 2 like)

Ok to start you out here is a simple 2D camera system that will let you have multiple viewports each able to zoom in and out.
Global CameraList:TList = CreateList()

Type TCamera
	Field WorldX:Float
	Field WorldY:Float
	Field TargetX:Float
	Field TargetY:Float
	Field ViewX:Float
	Field ViewY:Float
	Field ViewWidth:Float
	Field ViewHeight:Float
	Field ViewZoom:Float
	
	Function Create:TCamera (_WorldX:Float, _WorldY:Float,_ViewX:Float, _ViewY:Float, _ViewWidth:Float, _ViewHeight:Float)
		Local Camera:TCamera = New TCamera
		Camera.WorldX = _WorldX
		Camera.WorldY = _WorldY
		Camera.SetView(_ViewX, _ViewY, _ViewWidth, _ViewHeight)
		Camera.ViewZoom = 1.0
		CameraList.AddLast(Camera)
		If Debug.Enabled Debug.Console.Output("Camera Created",[255,255,255])
		Return Camera
	End Function
	
	Method Cls()
		Local ClsColor:Int [3]
		GetClsColor ClsColor[0],ClsColor[1],ClsColor[2]
		SetColor ClsColor[0],ClsColor[1],ClsColor[2]
		DrawRect ViewX, ViewY,ViewWidth,ViewHeight
	End Method
	
	
	Method SetView(_ViewX:Float, _ViewY:Float, _ViewWidth:Float, _ViewHeight:Float)
		ViewX = _ViewX
		ViewY = _ViewY
		ViewWidth = _ViewWidth
		ViewHeight = _ViewHeight
	End Method

	Method CenterOnPosition(_X:Float, _Y:Float, _Speed:Float = 1.0)
		TargetX = -_X * ViewZoom + (ViewX + (ViewWidth / 2))
		TargetY = -_Y * ViewZoom + (ViewY + (ViewHeight / 2))
		WorldX :+ (TargetX - WorldX) * (_Speed * ViewZoom)
		WorldY :+ (TargetY - WorldY) * (_Speed * ViewZoom) 
	End Method
	
	Method Shake(_Strength:Float)
		WorldX :+ Rnd(-_Strength,_Strength) * ViewZoom
		WorldY :+ Rnd(-_Strength,_Strength) * ViewZoom
	End Method
	
End Type

And here is a tile map system for you.
Global Tiles:TImage [1]
Type TTileMap
	Field Name:String
	Field TileSize:Float
	Field Depth:Int
	Field Width:Int
	Field Height:Int

	Field Data:Int [,,]
	
	Function CreateBlank:TTileMap (_Name:String, _Depth:Int, _Width:Int, _Height:Int, _TileSize:Int = 32)
		Local o:TTileMap = New TTileMap
			o.Name = _Name
			o.TileSize = _TileSize
			o.Depth = _Depth
			o.Width = _Width
			o.Height = _Height
			o.Data = New Int[_Depth, _Width, _Height]
			o.Clear()
		Return o
	End Function
	
	Function CreateFromFile:TTileMap (_File:String)
		Local o:TTileMap = New TTileMap
			o.Load(_File)
		Return o
	End Function
	
	Method LimitCameraToMapBounds(_Camera:TCamera)
		If _Camera.WorldX < -(Width*(TileSize * _Camera.ViewZoom)) + (_Camera.ViewX + _Camera.ViewWidth)
			_Camera.WorldX = -(Width*(TileSize * _Camera.ViewZoom)) + (_Camera.ViewX + _Camera.ViewWidth)
		End If
		If _Camera.WorldY < -(Height*(TileSize *_Camera.ViewZoom)) + (_Camera.ViewY + _Camera.ViewHeight)
			_Camera.WorldY = -(Height*(TileSize * _Camera.ViewZoom)) + (_Camera.ViewY + _Camera.ViewHeight)
		End If
		If _Camera.WorldX > _Camera.ViewX Then _Camera.WorldX = _Camera.ViewX
		If _Camera.WorldY > _Camera.ViewY Then _Camera.WorldY = _Camera.ViewY
	End Method

	Method Load (_File:String)
		Local In:tStream = ReadStream(_File)
		If Not In
			Return False 
		End If
		Name = ReadString(In,16)
		TileSize = Readint(In)
		Depth = Readint(In)
		Width = Readint(In)
		Height = Readint(In)
		Data = New Int[Depth, Width, Height]
		For Local d:Int = 0 To Depth - 1
			For Local x:Int = 0 To Width - 1
				For Local y:Int = 0 To Height - 1
					Data [d,x,y] = Readint(In)
				Next
			Next
		Next
		CloseStream In
	End Method
	
	Method Save (_File:String)
		Local Out:tStream = WriteStream(_File)
		If Not Out
			Return False 
		End If
		WriteString (Out,Name[..16])
		WriteInt (Out,TileSize)
		WriteInt (Out,Depth)
		WriteInt (Out,Width)
		WriteInt (Out,Height)
		For Local d:Int = 0 To Depth - 1
			For Local x:Int = 0 To Width - 1
				For Local y:Int = 0 To Height - 1
					WriteInt(Out,Data [d,x,y])
				Next
			Next
		Next
		CloseStream Out
	End Method
	
		
	Method Clear()
		For Local d:Int = 0 To Depth - 1
			For Local x:Int = 0 To Width - 1
				For Local y:Int = 0 To Height - 1
					Data [d,x,y] = 0
				Next
			Next
		Next
	End Method

	Method Fill(_Depth:Int, _TileIndex:Int)
		For Local x:Int = 0 To Width - 1
			For Local y:Int = 0 To Height - 1
				Data [_Depth,x,y] = _TileIndex
			Next
		Next
	End Method

	Method ScreenToMapCoords(_Camera:TCamera,_ScreenX:Float, _ScreenY:Float, _MapX:Float Var, _MapY:Float Var)
		If  _ScreenX < _Camera.ViewX Or _ScreenX > _Camera.ViewX + _Camera.ViewWidth Or _ScreenY < _Camera.ViewY Or _ScreenY > _Camera.ViewY + _Camera.ViewHeight Then
			_MapX = -1
			_MapY = -1
			Return False
		EndIf
		If _Camera.WorldX > 0 Then
			_MapX = (_ScreenX - _Camera.WorldX)
		Else
			_MapX = (-_Camera.WorldX + _ScreenX)
		EndIf
		If _Camera.WorldY > 0 Then
			_MapY = (_ScreenY - _Camera.WorldY)
		Else
			_MapY = (-_Camera.WorldY + _ScreenY)
		EndIf
		Return True
	End Method
	
	Method ScreenToMapCell(_Camera:TCamera,_ScreenX:Float, _ScreenY:Float, _MapCellX:Int Var, _MapCellY:Int Var)
		Local _MapX:Float
		Local _MapY:Float
		ScreenToMapCoords(_Camera,_ScreenX, _ScreenY, _MapX, _MapY)
		If _MapX <0 Or _MapX > Width * (TileSize * _Camera.ViewZoom) Or _MapY < 0 Or _MapY > Height * (TileSize * _Camera.ViewZoom) Then
			_MapCellX = -1
			_MapCellY = -1
		Else
			_MapCellX = _MapX / (TileSize * _Camera.ViewZoom)
			_MapCellY = _MapY / (TileSize * _Camera.ViewZoom)
		EndIf
	End Method
	
	Method MapToMapCell(_Camera:TCamera,_MapX:Float, _MapY:Float, _MapCellX:Int Var, _MapCellY:Int Var)
		If _MapX < 0 Or _MapX > Width * (TileSize * _Camera.ViewZoom) Or _MapY < 0 Or _MapY > Height * (TileSize * _Camera.ViewZoom) Then
			_MapCellX = -1
			_MapCellY = -1
		Else
			_MapCellX = _MapX / (TileSize * _Camera.ViewZoom)
			_MapCellY = _MapY / (TileSize * _Camera.ViewZoom)
		EndIf
	End Method
	
	Method MapCellToScreenCoords(_Camera:TCamera,_MapX:Float, _MapY:Float, _ScreenX:Float Var, _ScreenY:Float Var)
		_ScreenX = _Camera.WorldX + (TileSize * _Camera.ViewZoom) * _MapX
		_ScreenY = _Camera.WorldY + (TileSize * _Camera.ViewZoom) * _MapY
	End Method

	Method MapToScreenCoords(_Camera:TCamera,_MapX:Float, _MapY:Float, _ScreenX:Float Var, _ScreenY:Float Var)
		_ScreenX = (_MapX * _Camera.ViewZoom) + _Camera.WorldX
		_ScreenY = (_MapY * _Camera.ViewZoom) + _Camera.WorldY
	End Method
		
	Method Render(_Camera:TCamera,_Depth:Int = 0)
		Local ScreenX:Float
		Local ScreenY:Float
		For Local MapX = 0 To Width - 1
			ScreenX = MapX * (TileSize * _Camera.ViewZoom) + _Camera.WorldX
			If ScreenX + (TileSize * _Camera.ViewZoom) >= _Camera.ViewX And ScreenX <= _Camera.ViewX + _Camera.ViewWidth Then
				For Local MapY = 0 To Height - 1
					ScreenY = MapY * (TileSize * _Camera.ViewZoom) + _Camera.WorldY
					If ScreenY + (TileSize * _Camera.ViewZoom) >= _Camera.ViewY And ScreenY <= _Camera.ViewY + _Camera.ViewHeight Then
						Local TileIndex:Int = Data[_Depth, MapX, MapY]
						If TileIndex < 0 TileIndex = 0
						If TileIndex > Tiles.Length - 1 TileIndex = 0
						If Tiles[TileIndex] = Null
							If TileIndex <> 0 Print "Error: Tile does not exist: #"+TileIndex
							Continue
						End If
						SetScale _Camera.ViewZoom,_Camera.ViewZoom
						DrawImage Tiles[TileIndex],ScreenX, ScreenY
						SetScale 1,1
					EndIf
				Next
			EndIf
		Next
	End Method
	
	Method RenderGrid(CurrentCamera:TCamera)
		Local _Size:Float = TileSize * CurrentCamera.ViewZoom
		For Local _X:Float = 0 To Width
			DrawLine _X*_Size+CurrentCamera.WorldX,CurrentCamera.WorldY,_X*_Size+CurrentCamera.WorldX,CurrentCamera.WorldY+(Height*_Size)
		Next
		For Local _Y:Float = 0 To Height
			DrawLine CurrentCamera.WorldX,_Y*_Size+CurrentCamera.WorldY,CurrentCamera.WorldX+(Width*_Size), _Y*_Size+CurrentCamera.WorldY
		Next
	End Method
	
End Type

Let me know if you have questions.