Saving and loading a race track problem

BlitzMax Forums/BlitzMax Beginners Area/Saving and loading a race track problem

redmoth(Posted 2011) [#1]
Hi, I'm new here.'
I've tried to build my own simple level editor for a racing game, the actually editing of the track works but I'm having problems of when I load usually more than 7 or 8 objects I've saved to a file.

I get 'unhandled exception: Error reading from stream'
I can't figure out whats wrong, maybe if someone could have a quick look for the problem to help me please. THe save and load functions are at the bottom.


I'm saving :
trackObjects (which are tile objects, such as the track pieces
positions from the posArray (which are the x and y of the grid positions for the cars
checkPoints (which are basically the racing line around the course, represented by small 1 pixel boxes)


SuperStrict


Local endgame:Int = 0

Global width:Int = 800
Global height:Int = 600

Global offsetX:Float = 0
Global offsetY:Float = 0
Global tilesize:Int=16 'the size of the tiles
Global numberofObjects:Int = 0
Global currentObject:Int = 1
Global editorMode:Int = 2   '0 = , 1 =, 2 = add objects, 3 = add positions, 4 = add checpoints
Global menuOpen:Int = 0
Global objectnumbers:Int = 0
Global addObject:Int = 1
SetGraphicsDriver(GLMax2DDriver())
Graphics width,height,0,40


SetMaskColor 255,0,255 'set transparent mask colour on images to pink
SetClsColor(43,43,255)

'''MOUSE
Global mouse:TImage=LoadImage("media/mouse.png")
Global mousedot:TImage=LoadImage("media/mouse1.png")
Global mouseadd:TImage=LoadImage("media/mouseadd2.png")
HideMouse()

'''FONT
Global Font_default:TImagefont = LoadImageFont( "media/Vera.ttf", 12)
SetImageFont( Font_default )

Global imgObjectMap:TImage=LoadAnimImage("media/track16.png",tilesize,tilesize,0,16) 'load image graphics


'''''''CREATE tracjObjects Type
Type trackObjects
	Field x:Int
	Field y:Int
	Field id:Int
EndType
'create list of track objects
Global trackList:TList = CreateList()
Global trackObject:trackObjects


''''FOR ADDING GRID POSITIONS
Global positions:Int = 24
Global currentPos:Int = 0
Global posArray:Float[positions,2] 'create Array for the map of tiles

''''CHECK POINTS
Global thisCheckPoint:Int = 0
Global noCheckPoints:Int =200
Global checkPoints:Float[noCheckPoints,5] '0=x,1=y,

'''''''GAME LOOP''''''
While endgame = 0
	
	Cls
		addObjects()
		
	
	
		drawTrack()
		
		DrawImage(imgObjectMap,5,5,currentObject)
		addCheckPoints()
		addPositions()
		moveScreen()
		
		'DrawRect MouseX() / tilesize * tilesize, MouseY() / tilesize * tilesize, 32,32
		
		If editorMode = 1
			showMenu()
			DrawImage(mousedot,MouseX(),MouseY(),0)
			DrawImage(mouse,MouseX(),MouseY(),0)
		Else If editorMode = 2
			DrawImage(mousedot,MouseX()/ tilesize * tilesize,MouseY() / tilesize * tilesize,0)
			DrawImage(mouse,MouseX()/ tilesize * tilesize,MouseY() / tilesize * tilesize,0)
			If addObject = 1 Then DrawImage(mouseadd,MouseX()/ tilesize * tilesize,MouseY() / tilesize * tilesize,0)
		Else If editorMode = 3
			DrawImage(mousedot,MouseX(),MouseY(),0)
			DrawImage(mouse,MouseX(),MouseY(),0)
		Else If editorMode = 4
			DrawImage(mousedot,MouseX(),MouseY(),0)
			DrawImage(mouse,MouseX(),MouseY(),0)
		End If
		
		
		If KeyDown(KEY_P) 
			editormode = 3
		
		
		EndIf
		
		If KeyHit(key_1) Then editorMode = 1 'menu mode
		If KeyHit(key_2) Then editorMode = 2 'add object mode
		If KeyHit(key_3)
			editorMode = 3 'And currentPos = 1'add positions mode
			currentPos = 0
		End If
		If KeyHit(key_4)
			editorMode = 4
			thisCheckPoint = 0
		EndIf
		
		If KeyHit(key_t)
			If tilesize = 16
				tilesize = 32
				'offsetX=0
				'offsetY=0
				imgObjectMap:TImage=LoadAnimImage("media/track32.png",tilesize,tilesize,0,16) 'load image graphics
			Else If tilesize = 32
				tilesize = 16
				imgObjectMap:TImage=LoadAnimImage("media/track16.png",tilesize,tilesize,0,16) 'load image graphics
			EndIf
		EndIf
		
		If KeyHit(key_comma) And currentObject > 0 Then currentObject:-1
		If KeyHit(key_period) Then currentObject:+1
		
		'''OPEN THE MENU
		If KeyHit(KEY_M) 
			If editorMode = 1 
				editorMode = 2
			Else If editorMode = 2
				editorMode = 1
			EndIf
		End If
		
		If KeyDown(key_l) ''LOAD
			loadTrack()
		End If
		
		If KeyDown(key_S) ''''SAVE
			saveTrack()
			DrawText("SAVING...",width/2,width/2)
		End If
		
		DrawText("Grid Position:"+currentPos+"    CheckPoint:"+thisCheckPoint,300,15)
		
		If KeyDown(KEY_ESCAPE) Then endgame = 1
		If AppTerminate() = True Then endgame = 1
	Flip

Wend



Function moveScreen()
	If KeyDown(key_down) Then offsetY = offsetY+tilesize
	If KeyDown(key_up) Then offsetY = offsetY-tilesize
	If KeyDown(key_left) Then offsetX = offsetX-tilesize
	If KeyDown(key_right) Then offsetX = offsetX+tilesize
End Function

Function addPositions()
	If editormode = 3
		If MouseHit(1)
			If currentPos < positions
			posArray[currentPos,0] = (MouseX()+offsetX)/tilesize
			posArray[currentPos,1] = (MouseY()+offsetY)/tilesize
			currentPos:+ 1
			EndIf
		Else If MouseHit(2)
			If currentPos > 0
			currentPos:-1
			
			End If
			
		End If
	
	End If
	
		'SetColor(255,0,0)
	For Local j:Int = 0 To positions-1
		DrawRect((posArray[j,0]*tilesize)-offsetX,(posArray[j,1]*tilesize)-offsetY,1,1)
	Next
		'SetColor(255,255,255)
		

End Function

Function addCheckPoints()
	If editormode = 4
		If MouseHit(1)
			If thisCheckPoint < noCheckPoints
				checkPoints[thisCheckPoint,0] = (MouseX()+offsetX)/tilesize
				checkPoints[thisCheckPoint,1] = (MouseY()+offsetY)/tilesize
				Print checkPoints[thischeckpoint,0] + " " + checkPoints[thischeckpoint,1]
				thisCheckPoint:+1
				
			Else
				noCheckPoints:+1
				checkPoints[thisCheckPoint,0] = (MouseX()+offsetX)/tilesize
				checkPoints[thisCheckPoint,1] = (MouseY()+offsetY)/tilesize
				Print checkPoints[thischeckpoint,0] + " " + checkPoints[thischeckpoint,1]
				thisCheckPoint:+1
				'checkPoints[..,..] = checkPoints[noCheckPoints,5]
				
'				checkPoints = checkPoints[ .. noCheckPoints+1, .. 5]
			
			End If
		
		Else If MouseHit(2)
		
		End If
	
	End If
	SetColor(255,0,0)
	For Local j:Int = 0 To noCheckPoints-1
		DrawRect((checkPoints[j,0]*tilesize)-offsetX,(checkPoints[j,1]*tilesize)-offsetY,1,1)
	Next
	SetColor(255,255,255)

End Function

''''Function to add objects to the game
Function addObjects()
	If editormode = 2 And addObject = 1
		If MouseDown(1)
			trackObject = New trackObjects
			trackObject.x = ((MouseX()/tilesize*tilesize)+offsetX)/tilesize
			trackObject.y = ((MouseY()/tilesize*tilesize)+offsetY)/tilesize
			trackObject.id = currentObject
			ListAddLast trackList,trackObject
		
		End If
		'End If
	End If
	
	
End Function



''DRAW THE OBJECTS
Function drawTrack()
	objectnumbers = 0
	For Local trackObject:trackObjects = EachIn trackList
	'only draw tiles inside the view (and a little outside of the screen
	objectnumbers:+1'to count the number of objects on screen
	If (trackObject.x*tilesize)-offsetX  > 0-(tilesize*2) And (trackObject.x*tilesize)-offsetX < width+(tilesize*2)
		If (trackObject.y*tilesize)-offsetY > 0-(tilesize*2) And (trackObject.y*tilesize)-offsetY < height+(tilesize*2)
				DrawImage(imgObjectMap,(trackObject.x*tilesize)-offsetX,(trackObject.y*tilesize)-offsetY,trackObject.id)
				If editorMode = 2
				If ImagesCollide(mousedot,MouseX(),MouseY(),0,imgObjectMap,(trackObject.x*tilesize)-offsetX,(trackObject.y*tilesize)-offsetY,trackObject.id)
					addObject=0
					If MouseDown(2) Then ListRemove(trackList,trackObject) 'delete object
			
				Else 
					addObject=1
					
				End If
				EndIf
		End If
	End If
	Next
	If objectnumbers = 0 Then addObject = 1
	DrawText(objectnumbers,20,height-50)

End Function


Function showMenu() 'THe tile editor menu

	SetColor(25,25,25)
	SetBlend ALPHABLEND
	SetAlpha 0.9
	DrawRect(0,50,200,300)
	SetColor(100,100,100)
	DrawLine(5,120,195,120,0)
	SetColor(255,255,255)
	SetBlend MASKBLEND
	
	DrawText("Selected",5,74)
	DrawImage(imgObjectMap,160,74,currentObject)
	
	DrawText("Select:",70,130)
	DrawText("Tiles:",15,160)
	DrawImage(imgObjectMap,160,162,currentObject)
	
	If ImagesCollide(mousedot,MouseX(),MouseY(),0,imgObjectMap,160,162,currentObject)
		If MouseHit(1)
			currentObject = currentObject + 1
		Else If MouseHit(2)
			If currentObject > 0 Then currentObject = currentObject-1
		EndIf
	End If
	
	DrawText ("or",70,215)
	DrawText("Objects:",15,255)

	

End Function



Function saveTrack()

	Local ts_savemap:TStream = WriteFile("media/map1.trk")
	
	WriteInt(ts_savemap,objectnumbers) 'number of ovjects saved
	
	For Local trackObject:trackObjects = EachIn trackList 'save the track
		WriteInt(ts_savemap,trackObject.id)
		WriteInt(ts_savemap,trackObject.x)
		WriteInt(ts_savemap,trackObject.y)
		Print("Object saved")	
	Next
	
	For Local j:Int = 0 To positions-1
		WriteFloat(ts_savemap,posArray[j,0])
		WriteFloat(ts_savemap,posArray[j,1])
	Next
	
	WriteInt(ts_savemap,noCheckPoints)

	For Local k:Int = 0 To noCheckPoints-1
		WriteFloat(ts_savemap,checkPoints[k,0]) 'x coard of starting positions
		WriteFloat(ts_savemap,checkPoints[k,1]) 'y coard of starting positions
		
	Next
	
	CloseStream ts_savemap

End Function


Function loadTrack()
	
	For Local trackObject:trackObjects = EachIn trackList
		ListRemove(trackList,trackObject)
	Next
	
	thisCheckPoint = 0
	currentPos = 0
	
	
	Local ts_loadmap:TStream = ReadFile("media/map1.trk")'load the file
	
	
	Local noobjects:Int = ReadInt(ts_loadmap)
	For Local i:Int = 0 To noobjects
		trackObject = New trackObjects
		trackObject.id = ReadInt(ts_loadmap)
		trackObject.x = ReadInt(ts_loadmap)
		trackObject.y = ReadInt(ts_loadmap)
		ListAddLast trackList, trackObject
	Next
	
	For Local j:Int = 0 To positions-1
		posArray[j,0] = ReadFloat(ts_loadmap)
		posArray[j,1] = ReadFloat(ts_loadmap)
		
	Next
	noCheckPoints = ReadInt(ts_loadmap)
	For Local k:Int = 0 To noCheckPoints-1
		checkPoints[k,0] = ReadFloat(ts_loadmap)
		checkPoints[k,1] = ReadFloat(ts_loadmap)
		
	Next
	
		
	CloseStream ts_loadmap
	
End Function



Last edited 2011


GfK(Posted 2011) [#2]
For Local i:Int = 0 To noobjects
....should be....
For Local i:Int = 0 To noobjects - 1
--shouldn't it? Otherwise you're trying to read one more object than has been saved, hence a stream error.

Also, instead of
	For Local trackObject:trackObjects = EachIn trackList
		ListRemove(trackList,trackObject)
	Next
...use...
tracklist.Clear()



redmoth(Posted 2011) [#3]
Oh my, In learning the language I guess I also need to learn to have an eye for small errors like that. ~

As for the second part, that's a lot easier

Thank you for helping me.


Brucey(Posted 2011) [#4]
If you don't want to add -1 to the end ...
For Local i:Int = 0 To noobjects - 1


you can use Until instead, which is equivalent :
For Local i:Int = 0 Until noobjects


and looks neater, I think.


redmoth(Posted 2011) [#5]
thanks, that's good to know!