Loading and saving "Map" files...

Blitz3D Forums/Blitz3D Beginners Area/Loading and saving "Map" files...

psychicbottle(Posted 2012) [#1]
ok so recently i was told that i should focus more on my editor for my game than pathfinding so i am switching gears to that for awhile now. I don't mean to just ask a question and expect you guys to "baby me" but I am indeed only posting when I get super lost so please bare with me.

I am currently trying to find a way that I can create a map by placing a set of entitys in my Map-Editor, and then load them into my "Game". I obviously know i will be writing to and reading from some files haha but other than that i am kinda lost on what to do, am I looking at types in types to transfer everything well? alright, thank you ahead of time for everyone's patience with me.


Mikorians(Posted 2012) [#2]
My assumption was that you use your editor to create geometry, then export it to either an .x file, .3ds file, or b3d file, and that anything other than geometry should go into a separate data file that you then read/parse into your b3d program.

But here's a tip:
Don't make your geometry too large or things may seem to vanish on you.
See my threads below.

Some of these folks seem to be 'algorithm huggers' for geometry creation--- Not that there's anything wrong with that, but...


psychicbottle(Posted 2012) [#3]
Well, it will actually be used to place geometry not create it. I.E. i have a torch that i want to place on a wall and save the wall x,y,z ect. and then the torches x,y,z ect. into a text file so that i can reload into the game.
using this text file (load/save) so i am coding my own editor and in it i will make it so you place entitys and save them to a text probably using types. any hel? :D

EDIT: oops actually you were right i just skipped over the part about parsing code on accident But so far i am having no luck with this venture..

Last edited 2012


psychicbottle(Posted 2012) [#4]
here this may help you understand, i need to be able to place cubes on the grid (LMB) and save all of them to a file to be reloaded in at another time.

main.bb

world.bb



updates.bb


Last edited 2012


stanrol(Posted 2012) [#5]
you seem to have quite the nack for it.


psychicbottle(Posted 2012) [#6]
For what?

Edit: credit to RemiD for the neat grid :D

Last edited 2012


psychicbottle(Posted 2012) [#7]
Ok, Well i took a crack at it and kinda got loading and saving working... i Don't think this code is very flexible though... cause say i wanted to add a torch then i would want the torch to be lit on fire with an animation but idk where i would even start with loading and saving that information...

LOAD|SAVE FUNCTIONS...



Last edited 2012


Yasha(Posted 2012) [#8]
If you want a simple, generic data file reader/writer, you can use this: http://www.blitzbasic.com/codearcs/codearcs.php?code=2863

There are also XML and JSON libs floating around somewhere, but I haven't used them and therefore won't make a recommendation.


psychicbottle(Posted 2012) [#9]
i looked into it a bit and to be honest don't totally understand it haha im but as i search around it looks like im not going to be getting much help on this and im gonna have to figure it out on my own.


Midimaster(Posted 2012) [#10]
If you are interested in a very simple data system, I would suggest to write TXT-files. The advantage is, that you can control and manipulate them with any txt-EDITOR.

I would suggest: One line is one object. The paramters are separated by semikolons or TAB:

ID=1;MESH=Cube;X=3;Y=2.4;COLOR=244;.....
ID=2;MESH=Tree.3ds;X=3;Y=2.4;SIZE=3.4;.....


This is very easy to handle, but flexible in parameters. Not each line must have the same number of parameter nether the same parameters

You can add as many lines as you want. After a test run you can have a look on the script and see, whether the save functions are working perfect.

You can enter new lines, or sort the line without loosing the logic during reading back into Blitz3D

In Blitz3D you would have to ReadLine(), then divide the string by semikolons in "parameter pairs", then divide each parameter pair by "=" into PARAMETERNAME and VALUE.

if you are interested, I would write some sample code lines here...

Well writing in BlitzBasic is easy:

WriteLine "ID=" +id+ ";MESH=" +"Cube"+  ";X=" + x + ".....


The reading is more complicated:

; just a test string:
WholeString$="a=1;b=333;CC=12"

; a aray for our parameters:
Dim Parameter$(99)
Local i%=0

While WholeString<>""
	; find the position of the next semikolon:
	Cut=Instr(WholeString,";")
	If Cut=0 Then
		; if none take the whole string
		Cut=Len(WholeString)+1
	EndIf

	; now save the left part as one parameter pair
	Parameter(i)=Left(WholeString,Cut-1)
  
	; keep only the rest of the string for the next round:
	WholeString=Mid(WholeString,Cut+1,-1)
	Print Parameter(i)
	i=i+1
Wend



to divide paramatername from value:
; through all parameter pairs:
For j=0 To i

	; find the next "=":
	Cut=Instr(Parameter(j),"=")

	; left side will become name:
	ParameterName$=Left(Parameter(j),Cut-1)

	;right side will become value:
	Value=Mid(Parameter(j),Cut+1,-1)
	Print "Name=" + ParameterName + "       Value=" + Value
Next



Last edited 2012

Last edited 2012


psychicbottle(Posted 2012) [#11]
so from brushing over it, i write actual code into the file of which is then read then directly executed, i assume this would not only be neater but far faster than say reading 3000 files like i have done in my tests? :P

So this is kinda off topic but is there a way to hide Tris that the camera cannot see I.E. behind another entity, from what i see blitz will only load tris that the camera is facing but still loads them even if they are behind other things.

Last edited 2012


psychicbottle(Posted 2012) [#12]
Bug? i think i found a bug. when i run it it gives me correct results BUT it ends the program with an error "parameter must be posative" on the line "ParameterName$=Left(Parameter(j),Cut-1)" i did some debugging and found it was trying to add an invisible variable to the end of the original input string at the top of the code. i fixed it by changing

For j=0 To i


to

For j=0 To i-1


cant seem to find a way around it... any help?


also i am actually a GIANT fan of this simple data solution but i have a few simple questions about it.


is there a way to store variables that contain strings in the files this way? (along with int and floats) also i am having trouble actually using the variables that i store with this, cause although they are saved when i load in, for example, "ID=24" then when i say 'Print ""+ID' i would like it to print "24" but i can't seem to find a way to do that. sorry about all the questions, i have a lot i know. i really like this and hope i can use it.

Last edited 2012


Mikorians(Posted 2012) [#13]
Perhaps the CR/LF symbols or a terminating 0 cause your woes here.
I agree with midimaster. It is the method I use - even for my .ani files.
Str(number)

Last edited 2012


psychicbottle(Posted 2012) [#14]
ok, how do you make it actually effect your variables though? say i wanted to save "ID=24" how can i load that in so that "ID" actually = 24 cause right now it saves id as a temporary variable and same with the actual id(24)

e.g parametername = id
parameter = 24

i need some sort of function that would make blitz actually RUN the code "ID = 24"

maybe i am missing something here but i dont see a way of doing this


Mikorians(Posted 2012) [#15]
Sorry I'm brief - many pots on the fire...
What you're writing is a script parser then...
Some pseudo code:
a=replace(a," ","") ;pulls out the spaces
i=instr(a,"ID=")
if i<>0 then ID=floor(mid(a,i+3))

floor, ceil, or float to convert strings to numbers here... No Val function...
str(value) converts numerics to strings for output....
Instr searches for occurrences within a string
Left,Mid,Right for pieces of a string...

Careful how you order your script files, too much flexibility can lead to too much complexity in the parser.

Last edited 2012


Mikorians(Posted 2012) [#16]
Another method is to output your data in a known size and loop it.

x=24
a=writefile("test.dat")
writestring(a,x)
for t=0 to x:writestring(a,str(ID(t)):next
closefile(a)

(Haven't tested the read)

x=-1;Not necessary
a=readfile("test.dat")
readstring(a,b)
x=floor(b)
for t=0 to x:readstring(a,b)
ID(t)=floor(b)
next
closefile(a)

Last edited 2012

Last edited 2012


psychicbottle(Posted 2012) [#17]
hmm i am kinda lost... what is a? cause it seems you have it as two seperate variables? "replace(a," ","") but you use a as another variable in there? excuse my lack of knowledge on this topic please, I am just starting to branch out in blitz and learn new things so im not too good at it yet

EDIT: sorry i haven't ready your last post i posted this then saw that

Last edited 2012


Mikorians(Posted 2012) [#18]
a is your file channel id number


Mikorians(Posted 2012) [#19]
a is a placeholder reference that is returned by bb when you open a file to read or write, just like when you create an entity, only this is a file stream.


Mikorians(Posted 2012) [#20]
Be sure to reload this page since I made numerous changes to my example (there might still be mistakes, heh)


Mikorians(Posted 2012) [#21]
in original basic, the a would be the #1 in print#1
Open "test.dat" for output as #1
print #1,x
close#1
heh.


Mikorians(Posted 2012) [#22]
Hope I helped.


Midimaster(Posted 2012) [#23]
You are right: It has to be "to j=i-1". My mistake!

Strings?

Yes you already see it in the sample. There are parts which are strings:

ID=1;MESH=Cube;X=3;Y=2.4;COLOR=244;.....


"Cube" is a string. You can store it with
WriteLine "MESH" + Any$ + ";X=....


and there should no problem in re-reading it again. As long as you know, which paramter is String and which is number you can care about it:

	; left side will become name:
	ParameterName$=Left(Parameter(j),Cut-1)

	;right side will become value:
	Value$=Mid(Parameter(j),Cut+1,-1)
	Print "Name=" + ParameterName + "       Value=" + Value

	; now care about the values:
	Select ParameterName
		Case "ID"
			Id%=Int(Value)
		Case "X"
			X#=Float(Value)
		Case "MESH"
			MeshTyp$=Value
	End Select



In your case you would use my example lines modified into functions that handle the object properties:

Type World_objects
 Field x#,y#,z#,mesh,ID%
End Type

.....
If MouseHit(1)
	w.World_Objects = New World_Objects
	    w\mesh = CreateCube()
	    ScaleMesh w\mesh, 1.0/2, 1.0/2, 1.0/2
        PositionMesh w\mesh, 1.0/2, 1.0/2, 1.0/2
		w\x# = x#
		w\y# = y#
		w\z# = z#
		PositionEntity w\mesh ,w\x#,0,w\z#
       SavingAll()
EndIf

Function SavingAll()
	;openfile
	....

	; now write all lines:
	For w.World_Objects = each w.World_Objects
		tempString$= "ID=" + w\ID + ";MESH=Cube" + ";X=" + w\X
                WriteLine tempString.....
	Next

	;closefile
End Function


And reading them back like this:

For j=0 To i
	; left side will become name:
	ParameterName$=Left(Parameter(j),Cut-1)

	;right side will become value:
	Value$=Mid(Parameter(j),Cut+1,-1)
	Print "Name=" + ParameterName + "       Value=" + Value

	; now care about the values:
	Select ParameterName
		Case "ID"
			locId%=Int(Value)
		Case "X"
			locX#=Float(Value)
		Case "MESH"
			locMeshTyp$=Value
	End Select
Next

Select locMeshTyp

Case "Cube"
	w.World_Objects = New World_Objects
	    w\mesh = CreateCube()
	    w\ID=locID
	    ScaleMesh w\mesh, 1.0/2, 1.0/2, 1.0/2
        PositionMesh w\mesh, 1.0/2, 1.0/2, 1.0/2
		w\x# = locX#
		w\y# = locY#
		w\z# = locZ#
		PositionEntity w\mesh ,w\x#,0,w\z#

End Select



Last edited 2012

Last edited 2012


psychicbottle(Posted 2012) [#24]
hmm now im lost on "b" what is that a var for? :P sorry haha

P.S. i have managed to under stand how to read and write in single lines per object and then parse them apart using this (below), but i am still not understanding how to make it actually change the variable....

heres an example of what i mean


I Edited the code so make sure you refresh and get the new one

Last edited 2012


Midimaster(Posted 2012) [#25]
the "asigning" of values back to variable names is the last step.

You only have to do it:

		DebugLog "Parameter(j): "+Parameter(j)
		ParameterName$=Left(Parameter(j),Cut-1)
		DebugLog "ParameterName$: "+ParameterName$
	
		;right side will become value:
		Value=Mid(Parameter(j),Cut+1,-1)
		Print "Name=" + ParameterName + "       Value=" + Value

		If ParameterName="ID" Then
			Id=Value
		Endif



But in my post #23 you already can find more about this.

Last edited 2012


Mikorians(Posted 2012) [#26]
Snort... Gmph? I'm awake now, sorry...
Oh. B was because you're bringing in a string from the file.
X gets set to the value of the b string.
Bear in mind you might need to use float instead of floor if you need a decimal point type of value.

Normal basic used to have a split function that does what you've written.
You're doing fine bottle... I haven't examined midimaster's article yet...

Ah.. Yes. Quite correct.

Last edited 2012


psychicbottle(Posted 2012) [#27]
so i will infact need to type a snippet of code for each variable i want to load in? Eg: If ParameterName="ID" Then
Id=Value hmm... unfortunate, i was hoping this would be very flexible but! what must be done must be done.


Yasha(Posted 2012) [#28]
Not that I want to toot my own horn, but the library I linked in post #8 literally does all of this stuff for you. No extra code necessary.


Mikorians(Posted 2012) [#29]
Heh, Yasha is the local genius around here. I think it's a bit much for psychicbottle to utilize yet. I hope he can figure this all out.
Tell us what troubles you next, 'bottle. Midimaster 'n I 'll help you figure it out somehow.

I saw that midimaster mentioned in the data file having:
ID=1;MESH=Cube;X=3;Y=2.4;COLOR=244;.....
ID=2;MESH=Tree.3ds;X=3;Y=2.4;SIZE=3.4;...

What he's implied is that you're using an array to hold the relevant data much like the array I suggested in my post #16

An array can hold entire scenes if you used something like
scene(t)=loadanimmesh(b)
and then the other parameters on that line would be applied to THAT array item as you load the lines of text from the data file.
You mightn't even need to parse parameters at all if you leave blanks in the line.

Think like you're making a list or table:
Scenename xpos ypos zpos xrot yrot zpos xsca ysca zsca
==================================================
tree.3ds 5 0 -5 0 0 0 1 1 1

Notable here is that the data line in the file aways has a fixed number of parameters.
readstring and writestring just use a terminating 0 to mark where each part of the data ends.
If you're not editing the data file with notepad or something, it doesn't matter what the text in it actually looks like, does it?

Last edited 2012


Mikorians(Posted 2012) [#30]
If you use the help file->Command reference->2D- category and examine:
File
Filestream
String
Maths

If you haven't tried this yet, I use it all the time.

You can put your data in a binary file in any format you like, sir.

Last edited 2012


psychicbottle(Posted 2012) [#31]
mmk i will look into Yasha's library, and yes i understand how it parses and stores all the data, that is my current problem and i guess i will just either take the long way around or if i can im going to use yasha's library. the next problem im gonna have here is creating versatile GUI for my map editor...


Mikorians(Posted 2012) [#32]
May I recommend DevilGUI


psychicbottle(Posted 2012) [#33]
I have looked into it and that should work for most of the editors assuming it is simple enough, but is there any way of "re-skinning" the GUI or no? i couldn't see a way to do so.

hmm i dont see FileStream in there.. but i use that all the time, my problem isn't exactly the functions. it's combining them :)-EDIT never mind.

Last edited 2012

Last edited 2012


psychicbottle(Posted 2012) [#34]
Yasha, your library apears to be perfect but i don't see how i could "reload" these back into the game. i know im being a pain but any chance you could give me a really quick Tut on it? :D just like how i would write to a "file" and then read the variables and load them in,


Yasha(Posted 2012) [#35]
Here ya go! Hopefully this is fairly self-documenting.



Take note of the LogError function that has to be provided to suit your program's error handling system.

Do take a look at the outputted data file. If you open it in something like Notepad++, it should be automatically syntax-highlighted and so on for you.

Last edited 2012


gradualcheetah(Posted 2012) [#36]
I am currently having issues with my account but just a heads up i am psychicbottle still here just on a different account since mine has been possibly hacked..? im not sure. Yasha, i don't suppose there is an easy way to make this work with types is there? :) i use types a lot and prefer them over Arrays mainly cause i know how to use them ;)


Yasha(Posted 2012) [#37]
Eh? The code above doesn't use an array...?

Fields of a type and cells of an array are just value slots like variables. You put values in and take 'em out. You'll have to give an example of what you want done, because "working with" types in general shouldn't involve any significant changes to the above.


gradualcheetah(Posted 2012) [#38]
hmm i may have jumped to conclusions from too quick a glance at the code... one moment please :D haha sorry for being so "questiony", by the way.


gradualcheetah(Posted 2012) [#39]
ok some small tweaks to the demo here:



my question now is, say in my game engine(the place i will load and run my maps) if i create a cube and give it "c\secName$ = "Cube.01" then can i manipulate that type in the engine (after it has been loaded in) by going mmm for c.cube = each cube
if c\secName = cube.01 then positionentity c\mesh,100,100,100
next



gradualcheetah(Posted 2012) [#40]
holy crap you are a local genius here. im kinda slow at first haha but im wipping through the library so i can grasp it, and i think i found a way to do what i need :) ill get back to you in a sec, if you are still up/on

EDIT: hmmm is there any way through this problem: i want to add a variable called c\meshhandle with the value of CreateCube() any way i could do this or not really?
thanks for all your help so far!

Last edited 2012

Last edited 2012


Yasha(Posted 2012) [#41]
hmmm is there any way through this problem: i want to add a variable called c\meshhandle with the value of CreateCube() any way i could do this or not really?


To the data file?

(Adding a variable to a section is as easy as calling INI_AddProperty with whatever key name you want, but -)

Saving the handle of a 3D entity (or for that matter any asset represented by a handle) is a really bad idea: the entity won't have been created next time the program is run, so the value won't refer to anything unless CreateCube runs again anyway; and if it does run again, it probably won't return the same handle because the engine isn't required to be at all consistent about that (handles aren't really numbers, they're memory addresses, which happen to be representable as numbers so B3D does that for simplicity; you should never depend on a newly-returned address being anything specific).

The only true way to "save" an entity is to save all of the "constant" information needed in order to recreate it.

Last edited 2012


gradualcheetah(Posted 2012) [#42]
ok, thank you very much. I think i know basically what i need to so i can write some simple save/load functions for my Map-Editor.then im on to trying to use the devil GUI system... oofta.

one last question, so say i want to be able to manipulate the physical mesh later on. even though i cant actually put the function "createcube()" in and rely on it to create a cube to the variable, would it work to make a field "meshhandle" save it as zero always then after loading in all properties do c\meshhandle = createcube()
and apply all properties to that mesh?

P.S. bwahaha i love you this is seeming to work very very well...(No homo) but for real this is a very nice system and it is really quite flexible, you should maybe consider making it into a DLL and what not to add to the userlib in the Blitz3d files (i would but i dont know how to)


gradualcheetah(Posted 2012) [#43]
hmm im not trying to be picky but it seems very slow... any way to speed it up or any tips on how to? or not really

Nevermind, i had a glitch in my code that was saving all the data for EACH cube (cube.1,cube.2,cube.3 ect.) to the first cube. im not sure why it lagged the process so much... but just thought id let you know i did a comparison of my old method and my optimized version of yours, and it runs more than ten times faster. Great work there :)

Last edited 2012