Saving a Game

Blitz3D Forums/Blitz3D Beginners Area/Saving a Game

Nathaniel(Posted 2006) [#1]
I've never played a real commercial game that can't save. How do I save my game on my hard drive so I can continue where I left off?


Sledge(Posted 2006) [#2]
You have to design it in from the start (well, you *could* add load/save routines after the fact, but it would not be enjoyable). Should the user be able to save at the start of a level (which would involve data about which level he was on and his stats), at at predetermined checkpoint (level, stats, checkpoint and scripted element status) or anywhere he likes (level, stats, scripted element status, enemy status etc)? The more flexible the system, the more data you will have to read and write with the file commands.

You will also have to design your game in such a way that play can be initiated by reading the data off the save game file and having the engine place/update all the elements as needed - I would get that in early, using a dummy file for a new game if needs be.


Sir Gak(Posted 2006) [#3]
Check out the commands like WriteFile, ReadFile. The examples show how to open and close these, along with reading and writing information to them. Other applicable commands are WriteInt, ReadInt, etc.


BlackJumper(Posted 2006) [#4]
I posted something to the code archive a long time back (in the File Utils section)...

http://www.blitzbasic.com/codearcs/codearcs.php?code=1284

Basically, it allows you to very easily save Types. You then write a custom parser to read them back in to your game.


There are some routines for reading/writing XML in there that might be more suitable.


jfk EO-11110(Posted 2006) [#5]
How simple would that be if we could save a snapshot of the ram, program pointer etc. then simply reload the ram etc. and set the program pointer to where it was saved before.

I think this wouldn't work cause of dynamic Ram/Vram management and other inconsistant factors of the OS.

So when you want to have a flexible, powerful SaveGame then I'd suggest you make it saveable from beginning of the game project on, because it's real hard to add it to a full game.


Sir Gak(Posted 2006) [#6]
The savegame function in a game I'm working on was designed from practically the very start. If there is anymore info I need to save, I can always add that later.


Nathaniel(Posted 2006) [#7]
Thanks for all of your answers!


seferey(Posted 2006) [#8]
I want to save my game by pressing F6

And load it by pressing F7

how do you do that?


BlackJumper(Posted 2006) [#9]

;main game loop

repeat
if KeyDown(64) Then SaveGameFunction()
if KeyDown(65) Then LoadGameFunction()

ProcessOtherInput()
ProcessAIandStuff()

RenderWorld
Flip

Until KeyDown(1)


You then need to write your Load and save routines inside the two named functions. You will need a bit of planning to avoid variable scope issues... Putting all variables inside types is one way to achieve this


seferey(Posted 2006) [#10]
thanks black jumper


in a game


How do you save your entities current position in a game

into a save file

just curious :)


(tu) sinu(Posted 2006) [#11]
file = writefile("savegame.dat")

writefloat file,entityx(entity)
writefloat file,entityy(entity)
writefloat file,entityz(entity)

etc...

closefile file

Like mentioned above you need to think about saving/loading early on in the project.
In my engine all entities are saved to file and the way i designed it makes its simple to both save and reload.


seferey(Posted 2006) [#12]
I was playing with Blackjumpers code a bit but it says

"parameter must be positive" I guess I goofed up a bit
What I was trying

also writefloat commands in my way seems to save and
when the program starts up it never gives memory access violation problem like Sinu's above.

here's my code with some of Blackjumpers too

AppTitle "My little box"

Graphics3D 800,600,32,2

SetBuffer BackBuffer()

Type test
	Field x
	Field y
	Field name$
End Type

For count = 1 To 4
	n.test = New test
	n\x = Rand(10)
	n\y = Rand(10)+100
	n\name$ = Chr(Rand(26)+65) +Chr(Rand(26)+65) +Chr(Rand(26)+65)
Next

camera=CreateCamera()

light=CreateLight()

RotateEntity light,0,0,90

cube=CreateCube()

PositionEntity cube,0,0,5	

tex=LoadTexture("IMAGE3.BMP")

brush1=CreateBrush()

BrushTexture brush1,tex

PaintMesh cube,brush1

BrushShininess brush1,1


Repeat

If KeyDown(200)=True Then MoveEntity cube,0,0,1
If KeyDown(203)=True Then MoveEntity cube,-1,0,0
If KeyDown(205)=True Then MoveEntity cube,1,0,0
If KeyDown(208)=True Then MoveEntity cube,0,0,-1

If KeyHit(64) Then save
If KeyHit(65) Then load 

UpdateWorld 
RenderWorld 

Flip 

Until KeyHit(1)
End 

Function save()

fileout = WriteFile("Shay1.SM")
For n.test = Each test
	Print Str$(n)
	WriteString (fileout, Str$(n))
	WriteFloat (fileout,cube)
	WriteFloat (fileout,EntityX)
	WriteFloat (fileout,EntityY)
	WriteFloat (fileout,EntityZ)
Next
CloseFile( fileout ) 
Cls 
Print "game data written to file... press any key to continue"
Print
WaitKey 

End Function

Function load()
Print "... now reading from disk..."
filein = ReadFile("Shay1.SM") 
While Not Eof(filein)
Read1$ = ReadString$( filein ) 
Read1$ = ReadFloat( filein ) 
RestoreTestInfo(Read1$)
Wend 

End Function 

Function RestoreTestInfo( SavedString$ )
	Print "Read from file --> " + SavedString$
	SavedString$ = Mid$( SavedString$, 2, Len(SavedString$)-2) ; remove end square brackets
	
	firstcomma = Instr(SavedString$, ",")
	firstvalue% = Left$(SavedString$, firstcomma-1)   ; convert first value (up to comma) to an int
	
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to 1st comma

	firstcomma = Instr(SavedString$, ",")
	secondvalue% = Left$(SavedString$, firstcomma-1)  ; convert up to new first comma to another int
	
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to new 1st comma
	ThirdString$ = Mid$( SavedString$, 2, Len(SavedString$)-2)                        ; remove quotes from string

	reloaded.test = New test			; make a new type
	reloaded\x = firstvalue%			; and assign the
	reloaded\y = secondvalue%			; reloaded values
	reloaded\name$ = ThirdString$		; to the fields
	
End Function



BlackJumper(Posted 2006) [#13]
Hi sefery,

I have modified your code below to show a working example of saving and loading object positions (using F6 and F7 keys.)

Note that my Str$ saving example save a human readable text file, but you were then trying to save machine-format floats at the end of this... This is probably a bad idea.

This example only saves and loads Ints for position, but as mentioned in my CodeArc entry, there is a float parsing function available.



It would make sense to create specific ParseInt(), ParseFloat() and ParseString() functions and then use these inside RestoreTestInfo() rather than hacking away at the SavedString$ as I have done here... I just think that the above example makes it more obvious what is going on rather than hiding processing away in functions.

I will add the code above to the codeArc entry.

[edit]
BTW, I accidentally spent a couple of hours on this when it repeatedly crashed my machine... I eventually tracked it to a corrupted savefile - the While not EOF... Wend was never exiting !

Moral: be careful if you decide to manually edit that human-readable text file ;-)

Also.... remember that any strings should not be allowed to contain commas ',' or they will wreck the parsing of the saved type !
[/edit]


Sir Gak(Posted 2006) [#14]
I want to save my game by pressing F6

And load it by pressing F7

how do you do that?

As a general rule, I'd NOT put the Load/Save keys immediately next to each other, but put them at least one key apart (ie one key between them). The reason is, I like to play old Sega CD games on my PC using the Wgens emulator. They have a couple of F-keys used to Load and Save, and they are right next to each other. Let me tell you, I hit the wrong one more than once. It's more than merely annoying -- when you are really into your game, and have just mastered some difficult situation in the game, it is really an "aaarrrggghhh" situation when you hit the Load F-key instead of the Save F-key because they're right next to each other. Trust me on this one.


seferey(Posted 2006) [#15]
how Do I write a parse command?


BlackJumper(Posted 2006) [#16]
here is add's Parser function...

http://www.blitzbasic.com/codearcs/codearcs.php?code=161

... and the example of usage...

http://www.blitzbasic.com/codearcs/codearcs.php?code=162


Sir Gak(Posted 2006) [#17]
I created a parser for a game, which is a little different from the above. In essence, I have to print text in a limited width column. My parser searches through text that is wider than the column, looking for spaces, and then prints everything up to the space, and the remainder is moved down to the next line, deleting from the string the text already printed, and repeats until the string is fully printed out.


seferey(Posted 2006) [#18]
I figured out how to get the results I wanted So I'm sharing it with the rest of guys for your input on it.

AppTitle "My little box"

Graphics3D 800,600,32,2

SetBuffer BackBuffer()
Global message$ = "move the boxes... '[' and ']' to change box"
Type test
	Field x
	Field y
	Field z
	Field name$
	Field shape
	Field anim
End Type

For count = 1 To 1
	n.test = New test
	n\x = Rand(10)
	n\y = Rand(10)
	n\z = Rand(10)+10
	n\name$ = Chr(Rand(26)+65) +Chr(Rand(26)+65) +Chr(Rand(26)+65)
	n\shape = LoadAnimMesh("BOX.b3d") 
    Animate n\shape,1,2,0,100
	EntityColor n\shape, count*50, 0,0
Next

camera=CreateCamera()

light=CreateLight()

RotateEntity light,0,0,90

Global reload.test
Global control.test = Last test
maxshape = control\shape
control.test = First test
minshape = control\shape

;box=LoadAnimMesh("BOX.b3d")
ScaleEntity n\shape,.1,.1,.1 
PositionEntity n\shape,0,-.9000,5 
TranslateEntity n\shape,30,-.70,-.70
EntityShininess n\shape,1
EntityBlend n\shape,1
SetAnimKey n\shape,15,True,True,True
AddAnimSeq(n\shape,15)
EntityAutoFade n\shape,80,70

Repeat

If KeyDown(200)=True Then control\y = control\y + 1
If KeyDown(203)=True Then control\x = control\x - 1
If KeyDown(205)=True Then control\x = control\x + 1
If KeyDown(208)=True Then control\y = control\y - 1

If (KeyHit(26)=True And control\shape <> minshape) Then control = Before control
If (KeyHit(27)=True And control\shape <> maxshape) Then control = After control

For update.test = Each test
    PositionEntity update\shape, update\x, update\y, update\z
    EntityColor update\shape,count*50, 0,0
Next

If KeyHit(64) Then save
If KeyHit(65) Then load 

UpdateWorld 
RenderWorld 

Text 20, 20, message$
Flip 

Until KeyHit(1)
End 

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function save()

fileout = WriteFile("Shay1.SM")
For n.test = Each test
	Print Str$(n)
	WriteString (fileout, Str$(n))
Next
CloseFile( fileout ) 
Cls 
message$ = "game data written to file..."
FlushKeys 

End Function
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function load()
Cls
For destroy.test = Each test
    FreeEntity destroy\shape
    Delete destroy
Next

filein = ReadFile("Shay1.SM") 
While Not Eof(filein)
      Read1$ = ReadString$( filein ) 
      If Read1$<>"" Then
        reload.test = RestoreTestInfo(Read1$)
      EndIf
Wend 
DebugLog "finished with loaded file"
FlushKeys
control = First test
End Function 
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function RestoreTestInfo.test( SavedString$ )
	message$ =  "Read from file --> " + SavedString$ + "    ...     "
	DebugLog message$   ; typical type looks like ... [-3,-4,14,"LQT",18898368]
	SavedString$ = Mid$( SavedString$, 2, Len(SavedString$)-2) ; remove end square brackets
	
	firstcomma = Instr(SavedString$, ",")
	xvalue% = Left$(SavedString$, firstcomma-1)   ; convert first value (up to comma) to an int
	
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to 1st comma

	firstcomma = Instr(SavedString$, ",")
	yvalue% = Left$(SavedString$, firstcomma-1)  ; convert up to new first comma to another int
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to new 1st comma

	
	firstcomma = Instr(SavedString$, ",")
	zvalue% = Left$(SavedString$, firstcomma-1)  ; convert up to new first comma to another int

	
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to new 1st comma
	ThirdString$ = Mid$( SavedString$, 2, Len(SavedString$))     ; remove first quote from string

	firstcomma = Instr(SavedString$, ",")
	ThirdString$ = Mid$(SavedString$, 2, firstcomma-3)
	
	message$ = message$ + "x: " + xvalue + "   y: " + yvalue + "   z: " + zvalue + "     name: " + ThirdString$
	DebugLog message$

	reloaded.test = New test			; make a new type
	reloaded\x = xvalue%			    ; and assign the
	reloaded\y = yvalue%		     	; reloaded values
	reloaded\z = zvalue%
	reloaded\name$ = ThirdString$		; to the fields
	reloaded\shape = LoadAnimMesh("BOX.b3d")
	ScaleEntity reloaded\shape,.1,.1,.1  
	Animate reloaded\shape,1,2,0,100
	Return (reloaded)
	
End Function
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



BlackJumper(Posted 2006) [#19]
Great.... now go make us a kick ass "box 'em up" - or whatever!

;-)


seferey(Posted 2006) [#20]

;Initialise Graphics mode
Graphics3D 1024,768,32

SetBuffer BackBuffer()

Const GRAVITY#=-0.01

Global message$ = "move the boxes... '[' and ']' to change box"
Type test
	Field x
	Field y
	Field z
	Field name$
	Field box
	Field update
End Type

For count = 1 To 1
	n.test = New test
	n\x = Rand(10)
	n\y = Rand(10)
	n\z = Rand(10)+10
	n\name$ = Chr(Rand(26)+65) +Chr(Rand(26)+65) +Chr(Rand(26)+65)
	box = LoadAnimMesh("model\box.b3d") 
    Animate box,1,2,0,100
Next

Global reload.test
Global control.test = Last test
maxshape = control\box
control.test = First test
minshape = control\box

;Camera has to be set, so the scene is visible
  
Camera=CreateCamera()
CameraRange Camera,1,8000 
PositionEntity camera,30,0,1,True
 
;Light The Scene, so that it doesn't look flat

Light=CreateLight()

RotateEntity Light,90,0,0

;Create the "Terrain" Entity...
terrain=LoadMesh("Land\Land2.b3d")
PositionEntity terrain,40,17,0
RotateEntity terrain,0,0,0 
TranslateEntity terrain,40,-20,-.1 
;...and texture it
Grass=LoadTexture("Land\terrain-1.jpg")
EntityTexture terrain,Grass

;Create A Border Line 

Wall=CreateCube() 
ScaleMesh Wall,600,600,600
PositionMesh Wall,60,17,0 
EntityAlpha Wall,0
EntityOrder Wall,20
FlipMesh Wall

;Create the "Box" entity and animate it
;box=LoadAnimMesh("model\box.b3d")
ScaleEntity box,.1,.1,.1
PositionEntity box,0,-.9000,5
TranslateEntity box,30,-.70,-.70
EntityShininess box,1
SetAnimKey box,15,True,True,True
AddAnimSeq(box,15)
Animate box,1,2,0,100

;Set Collision types fot the "collisions" command 1-player, 2-ground 3-border
type_box=1
type_terrain=2
type_Wall=2
EntityType box,1
EntityType terrain,2
EntityType Wall,2

;Adjust Radius of Sphere, that's used for Sphere-Polygon collisions
box_radius#=1
EntityRadius box,box_radius
;Initialise Collisions between player,ground and border

Collisions type_box,type_terrain,2,3 
Collisions type_terrain,type_box,2,3
Collisions type_Wall,type_terrain,2,3 
Collisions type_terrain,type_Wall,2,3

;Dither scene, so that it does look good with 16 Bit Color-Depth

; Toggle dither enable value between true and false when F10 is pressed

If KeyHit( 68 )=True Then enable=1-enable

;Dither enable 

;other information about gravity

speed#=0
x_vel#=0:prev_x#=EntityX( box )
y_vel#=0:prev_y#=EntityY( box )
z_vel#=0:prev_z#=EntityZ( box )

;Main Loop

While Not KeyHit(88) ;press F12 To Exit

;Press F11 to see the world in Wireframe mode

 
If KeyHit(87)=True Then enable=1-enable 
  
   WireFrame enable 

;CameraFogRange camera,1,FOG_RANGE

   ;calculate box velocities	
	cx#=EntityX( box ):x_vel=cx-prev_x:prev_x=cx
	cy#=EntityY( box ):y_vel=cy-prev_y:prev_y=cy
	cz#=EntityZ( box ):z_vel=cz-prev_z:prev_z=cz

EntityParent(camera,box,1)  

;Keyboard Input (cursor-keys) For moving the player around
    
If KeyHit(57) 
  If move_entities = True 
    move_entities = False 
  Else 
    move_entities = True   
  EndIf 
EndIf 

If move_entities = False 
  
  ;all of your movement code
  If KeyDown(30) TurnEntity box,0,1,0 
  If KeyDown(32) TurnEntity box,0,-1,0 
  If KeyDown(31) MoveEntity box,0,0,-.01 
  If KeyDown(17) MoveEntity box,0,0,.01 
  If EntityCollided( box,terrain)  
    If KeyDown(17) 
      speed=speed+.00 
      If speed>.0 speed=.0 
    Else If KeyDown(31)
      speed=speed-.02
      If speed<-.5 speed=-.5
    Else
      speed=speed*.9
    EndIf
    MoveEntity box,0,0,speed
    TranslateEntity box,0,GRAVITY#-.01,0
  Else
    TranslateEntity box,x_vel,y_vel+GRAVITY,z_vel
  EndIf
EndIf

For update.test = Each test
    PositionEntity reloaded\box,update\x,update\y,update\z,False  
Next

If KeyHit(64) Then save
If KeyHit(65) Then load 

;Update the animation-Frames and Render the calculated scene, Flip Back- with Frontbuffer after that, so the new frame becomes visible
  UpdateWorld
  RenderWorld
  Flip  

Wend

;Free the Memory and end the program
ClearWorld

End

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function save()

fileout = WriteFile("Shay1.SM")
For n.test = Each test
	Print Str$(n)
	WriteString (fileout, Str$(n))
Next
CloseFile( fileout ) 
Cls 
message$ = "game data written to file..."
FlushKeys 

End Function
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function load()
Cls
For destroy.test = Each test
    FreeEntity destroy\box
    Delete destroy
Next

filein = ReadFile("Shay1.SM") 
While Not Eof(filein)
      Read1$ = ReadString$( filein ) 
      If Read1$<>"" Then
        reload.test = RestoreTestInfo(Read1$)
      EndIf
Wend 
DebugLog "finished with loaded file"
FlushKeys
control = First test
End Function 
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function RestoreTestInfo.test( SavedString$ )
	message$ =  "Read from file --> " + SavedString$ + "    ...     "
	DebugLog message$   ; typical type looks like ... [-3,-4,14,"LQT",18898368]
	SavedString$ = Mid$( SavedString$, 2, Len(SavedString$)-2) ; remove end square brackets
	
	firstcomma = Instr(SavedString$, ",")
	xvalue% = Left$(SavedString$, firstcomma-1)   ; convert first value (up to comma) to an int
	
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to 1st comma

	firstcomma = Instr(SavedString$, ",")
	yvalue% = Left$(SavedString$, firstcomma-1)  ; convert up to new first comma to another int
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to new 1st comma

	
	firstcomma = Instr(SavedString$, ",")
	zvalue% = Left$(SavedString$, firstcomma-1)  ; convert up to new first comma to another int

	
	SavedString$ = Mid$( SavedString$, firstcomma+1, Len(SavedString$)-firstcomma+1)  ; eat up to new 1st comma
	ThirdString$ = Mid$( SavedString$, 2, Len(SavedString$))     ; remove first quote from string

	firstcomma = Instr(SavedString$, ",")
	ThirdString$ = Mid$(SavedString$, 2, firstcomma-3)
	
	message$ = message$ + "x: " + xvalue + "   y: " + yvalue + "   z: " + zvalue + "     name: " + ThirdString$
	DebugLog message$

	reloaded.test = New test			; make a new type
	reloaded\x = xvalue%			    ; and assign the
	reloaded\y = yvalue%		     	; reloaded values
	reloaded\z = zvalue%
	reloaded\name$ = ThirdString$		; to the fields
	reloaded\box = LoadAnimMesh("model\box.b3d")
	ScaleEntity reloaded\box,.1,.1,.1  
	Animate reloaded\box,1,2,0,100
	Return (reloaded)
	
End Function
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++




seferey(Posted 2006) [#21]
and when I change like this

For update.test = Each test
    PositionEntity update\box,update\x,update\y,update\z
Next 



this second version here tells me entity not found


seferey(Posted 2006) [#22]
For update.test = Each test
    PositionEntity update\shape, update\x, update\y,update\z
Next


the tiny snippet above call update.test is giving me a headache it keeps on telling me "variable must be a type"
is there something I missed :(


Stevie G(Posted 2006) [#23]
Your code isn't the clearest but in this section ...

For count = 1 To 1
	n.test = New test
	n\x = Rand(10)
	n\y = Rand(10)
	n\z = Rand(10)+10
	n\name$ = Chr(Rand(26)+65) +Chr(Rand(26)+65) +Chr(Rand(26)+65)
	box = LoadAnimMesh("model\box.b3d") 
    Animate box,1,2,0,100
Next


You should have

n\Box = loadanimmesh( etc.. )

and

Animate n\Box,1,2,0,100


Stevie


seferey(Posted 2006) [#24]
Stevie your n\box works great but because I'm using car velocities and gravity it seems to get in the way of the car velocities


that and I'm using
entityparent(Camera,n\box,1) 


but entity parent doesn't like the above code unless it's like this below

entityparent(Camera,box,1) 



Stevie G(Posted 2006) [#25]
I've no idea what your trying to do but you need to tell blitz that n is of type instance "test"

I'm guessing you get an object does not exist error?

If you put a n.test = first test before the entityparent command and change all instanced of box to n\box in that part of your code then this should work. I'm assuming you will have more than one test type though so it would probably be more appropriate to use a loop ..

for n.test = each test ... etc...

Stevie

Stevie


seferey(Posted 2006) [#26]
I'm a stupid I didn't explain myself here on the forum

okay I have a game with a skybox with blue skies , terrain in blitz3d model format , a square box with a stick in the center of it with one wheel on each side this box with wheels is using gravity from driver blitz3d examples and car velocities
with entity collide etc. sorry


seferey(Posted 2006) [#27]
it seem's that the RestoreTestInfo from black jumper

seem to have problems with


entityparent(camera,n\car,1)


      ;align car to wheels
	zx#=(EntityX( wheels[2],True )+EntityX( wheels[4],True ))/2
	zx=zx-(EntityX( wheels[1],True )+EntityX( wheels[3],True ))/2
	zy#=(EntityY( wheels[2],True )+EntityY( wheels[4],True ))/2
	zy=zy-(EntityY( wheels[1],True )+EntityY( wheels[3],True ))/2
	zz#=(EntityZ( wheels[2],True )+EntityZ( wheels[4],True ))/2
	zz=zz-(EntityZ( wheels[1],True )+EntityZ( wheels[3],True ))/2
	AlignToVector n\car,zx,zy,zz,1
	
	zx#=(EntityX( wheels[1],True )+EntityX( wheels[2],True ))/2
	zx=zx-(EntityX( wheels[3],True )+EntityX( wheels[4],True ))/2
	zy#=(EntityY( wheels[1],True )+EntityY( wheels[2],True ))/2
	zy=zy-(EntityY( wheels[3],True )+EntityY( wheels[4],True ))/2
	zz#=(EntityZ( wheels[1],True )+EntityZ( wheels[2],True ))/2
	zz=zz-(EntityZ( wheels[3],True )+EntityZ( wheels[4],True ))/2
	AlignToVector n\car,zx,zy,zz,3

        ;calculate car velocities	
        cx#=EntityX( n\car  ):x_vel=cx-prev_x:prev_x=cx
	cy#=EntityY( n\car  ):y_vel=cy-prev_y:prev_y=cy
	cz#=EntityZ( n\car  ):z_vel=cz-prev_z:prev_z=cz





BlackJumper(Posted 2006) [#28]
I am guessing that the problem with what you are trying to do is contained in that last section...

You are trying to work out the car's velocity by subtracting where it *was* previously from where it is *now*

That means that you will have to record not only the 'current' state of the game, but also what it was on the previous frame.

So...
(1) are you storing all this info in a Type (see below*) ?
(2) are you saving it using Writefile(destination, Str$)
(3) have you modified RestoreTestInfo to take into account all of the fields (and their order) in your Type definition

* It looks as if the Driver demo stores info directly in the wheel objects - and these are held in an array... hence "EntityX(wheel[1])" is pulling information about X-position directly from wheel number 1. To use the Save/Load code developed above you need to be storing that information in a type OR you need to scrap this and go for writing/reading floats directly to a file. In that case you will need to write the save routine as well as the load routine.


seferey(Posted 2006) [#29]
can you do this in the save and load routines


WriteFloat(fileout,n\car)


readfloat(filein,n\car)




BlackJumper(Posted 2006) [#30]
No.

I assume that n\car holds the mesh you are loading for the car. This is just a number used internally by B3D to locate the actual mesh in memory (n\car is a 'handle' to the mesh.)

You cannot reload a handle as the memory referred to will no longer be valid at a later date.

What you would need to do is something like...

basecar = Loadmesh("car.b3d")


;+++++++++++  Loading +++++++++++++
n.test = new test
n\car = CopyEntity(basecar)

SavedFile = ReadFile("saved.dat")

SavedX# = ReadFloat(SavedFile)
SavedY# = ReadFloat(SavedFile)
SavedZ# = ReadFloat(SavedFile)

CloseFile(SavedFile)

PositionEntity n\car, SavedX, SavedY, SavedZ


Of course you would have to do this for every wheel as well. And based on previous comments you will probably need to do it twice so that the velocity can be worked out from the previous positions