OSDN Git Service

SDK:
[mikumikustudio/MikuMikuStudio.git] / sdk / jme3-documentation / src / com / jme3 / gde / docs / jme3 / advanced / save_and_load.html
1
2 <h1><a>Saving and Loading Games (.j3o)</a></h1>
3 <div>
4
5 <p>
6
7 Spatials (that is Nodes and Geometries) can contain audio and light nodes, particle emitters, controls, and user data (player score, health, inventory, etc). For your game distribution, you must convert all original models to a faster binary format. You save individual Spatials as well as scenes using <code>com.jme3.export.binary.BinaryExporter</code>. 
8 </p>
9
10 <p>
11 The jMonkeyEngine&#039;s binary file format is called <code>.j3o</code>. You can convert, view and edit .j3o files and their materials in the jMonkeyEngine <a href="/com/jme3/gde/docs/sdk.html">SDK</a> and compose scenes (this does not include editing meshes). For the conversion, you can either use the BinaryExporters, or a context menu in the <acronym title="Software Development Kit">SDK</acronym>.
12 </p>
13
14 <p>
15 <p><div>The jMonkeyEngine&#039;s serialization system is the <code>com.jme3.export.Savable</code> interface. JME3&#039;s BinaryExporter can write standard Java objects, JME3 objects, and primitive data types that are included in a <a href="/com/jme3/gde/docs/jme3/advanced/spatial.html">spatial&#039;s user data</a>. If you use custom game data classes, see below how to make them &quot;Savable&quot;.
16 </div></p>
17 </p>
18
19 <p>
20 There is also a com.jme3.export.xml.XMLExporter and com.jme3.export.xml.XMLImporter that similarly converts jme3 spatials to an <acronym title="Extensible Markup Language">XML</acronym> format. But you wouldn&#039;t use that to load models at runtime (quite slow).
21 </p>
22
23 </div>
24 <!-- EDIT1 SECTION "Saving and Loading Games (.j3o)" [1-1239] -->
25 <h2><a>Sample Code</a></h2>
26 <div>
27 <ul>
28 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/tools/TestSaveGame.java"><param name="text" value="<html><u>TestSaveGame.java</u></html>"><param name="textColor" value="blue"></object></div>
29 </li>
30 </ul>
31
32 </div>
33 <!-- EDIT2 SECTION "Sample Code" [1240-1397] -->
34 <h2><a>Saving a Node</a></h2>
35 <div>
36
37 <p>
38
39 The following example overrides <code>stop()</code> in SimpleApplication to save the rootNode to a file when the user quits the application. The saved rootNode is a normal .j3o binary file that you can open in the <a href="/com/jme3/gde/docs/sdk.html">SDK</a>.
40 </p>
41
42 <p>
43 <p><div>Note that when you save a model that has textures, the references to those textures are stored as absolute paths, so when loading the j3o file again, the textures have to be accessible at the exact location (relative to the assetmanager root, by default the <code>assets</code> directory) they were loaded from. This is why the <acronym title="Software Development Kit">SDK</acronym> manages the conversion on the project level.
44 </div></p>
45 </p>
46 <pre>  /* This is called when the user quits the app. */
47   @Override
48   public void stop&#40;&#41; &#123;
49     String userHome = System.getProperty&#40;&quot;user.home&quot;&#41;;
50     BinaryExporter exporter = BinaryExporter.getInstance&#40;&#41;;
51     File file = new File&#40;userHome+&quot;/Models/&quot;+&quot;MyModel.j3o&quot;&#41;;
52     try &#123;
53       exporter.save&#40;rootNode, file&#41;;
54     &#125; catch &#40;IOException ex&#41; &#123;
55       Logger.getLogger&#40;Main.class.getName&#40;&#41;&#41;.log&#40;Level.SEVERE, &quot;Error: Failed to save game!&quot;, ex&#41;;
56     &#125;
57     super.stop&#40;&#41;; // continue quitting the game
58   &#125;</pre>
59
60 </div>
61 <!-- EDIT3 SECTION "Saving a Node" [1398-2548] -->
62 <h2><a>Loading a Node</a></h2>
63 <div>
64
65 <p>
66
67 The following example overrides <code>simpleInitApp()</code> in SimpleApplication to load <code>Models/MyModel.j3o</code> when the game is initialized.
68 </p>
69 <pre>  @Override
70   public void simpleInitApp&#40;&#41; &#123;
71      String userHome = System.getProperty&#40;&quot;user.home&quot;&#41;;
72      assetManager.registerLocator&#40;userHome, FileLocator.class&#41;;
73      Node loadedNode = &#40;Node&#41;assetManager.loadModel&#40;&quot;Models/MyModel.j3o&quot;&#41;;
74      loadedNode.setName&#40;&quot;loaded node&quot;&#41;;
75      rootNode.attachChild&#40;loadedNode&#41;;
76   &#125;
77 &nbsp;</pre>
78
79 <p>
80 <p><div>Here you see why we save user data inside spatials ??? so it can be saved and loaded together with the .j3o file. If you have game data outside Spatials, you have to remember to save() and load(), and get() and set() it yourself.
81 </div></p>
82 </p>
83
84 </div>
85 <!-- EDIT4 SECTION "Loading a Node" [2549-3302] -->
86 <h2><a>Custom Savable Class</a></h2>
87 <div>
88
89 <p>
90
91 JME&#039;s BinaryExporter can write standard Java objects (String, ArrayList, buffers, etc), JME objects (Savables, such as Material), and primitive data types (int, float, etc). If you are using any custom class together with a Spatial, then the custom class must implement the <code>com.jme3.export.Savable</code> interface. There are two common cases where this is relevant:
92
93 </p>
94 <ul>
95 <li><div> The Spatial is carrying any <a href="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">Custom Controls</a>. <br/>
96 Example: You used something like <code>mySpatial.addControl(myControl);</code></div>
97 </li>
98 <li><div> The Spatial&#039;s user data can contain a custom Java object. <br/>
99 Example: You used something like <code>mySpatial.setUserData(&quot;inventory&quot;, myInventory);</code></div>
100 </li>
101 </ul>
102
103 <p>
104 If your custom classes (the user data or the Controls) do not implement Savable, then the BinaryImporter/BinaryExporter cannot save the Spatial!
105 </p>
106
107 <p>
108 So every time you create a custom Control or custom user data class, remember to implement Savable:
109 </p>
110 <pre>import com.jme3.export.InputCapsule;
111 import com.jme3.export.JmeExporter;
112 import com.jme3.export.JmeImporter;
113 import com.jme3.export.OutputCapsule;
114 import com.jme3.export.Savable;
115 import com.jme3.material.Material;
116 import java.io.IOException;
117 &nbsp;
118 public class MyCustomClass implements Savable &#123;
119     private int      someIntValue;   // some custom user data
120     private float    someFloatValue; // some custom user data
121     private Material someJmeObject;  // some custom user data
122 &nbsp;
123     ...
124     // your other code...
125     ...
126 &nbsp;
127     public void write&#40;JmeExporter ex&#41; throws IOException &#123;
128         OutputCapsule capsule = ex.getCapsule&#40;this&#41;;
129         capsule.write&#40;someIntValue,   &quot;someIntValue&quot;,   1&#41;;
130         capsule.write&#40;someFloatValue, &quot;someFloatValue&quot;, 0f&#41;;
131         capsule.write&#40;someJmeObject,  &quot;someJmeObject&quot;,  new Material&#40;&#41;&#41;;
132     &#125;
133 &nbsp;
134     public void read&#40;JmeImporter im&#41; throws IOException &#123;
135         InputCapsule capsule = im.getCapsule&#40;this&#41;;
136         someIntValue   = capsule.readInt&#40;    &quot;someIntValue&quot;,   1&#41;;
137         someFloatValue = capsule.readFloat&#40;  &quot;someFloatValue&quot;, 0f&#41;;
138         someJmeObject  = capsule.readSavable&#40;&quot;someJmeObject&quot;,  new Material&#40;&#41;&#41;;
139     &#125;
140 &#125;</pre>
141
142 <p>
143 To make a custom class savable:
144 </p>
145 <ol>
146 <li><div> Implement <code>Savable</code> and add the <code>write()</code> and <code>read()</code> methods as shown in the example above.</div>
147 </li>
148 <li><div> Do the following for each non-temporary class field: </div>
149 <ul>
150 <li><div> Add one line that <code>write()</code>s the data to the JmeExport output capsule. </div>
151 <ul>
152 <li><div> Specify the variable to save, give it a String name (can be the same as the variable name), and specify a default value.</div>
153 </li>
154 </ul>
155 </li>
156 <li><div> Add one line that <code>read???()</code>s the data to the JmeImport input capsule. </div>
157 <ul>
158 <li><div> On the left side of the assignment, specify the class field that you are restoring</div>
159 </li>
160 <li><div> On the right side, use the appropriate <code>capsule.read???()</code> method for the data type. Specify the String name of the variable (must be the same as you used in the <code>write() method</code>), and again specify a default value.</div>
161 </li>
162 </ul>
163 </li>
164 </ul>
165 </li>
166 </ol>
167
168 <p>
169
170 <p><div>As with all serialization, remember that if you ever change data types in custom classes, the updated read() methods will no longer be able to read your old files. Also there has to be a constructor that takes no Parameters.
171 </div></p>
172 </p>
173 <div><span>
174         <a href="/wiki/doku.php/tag:convert?do=showtag&amp;tag=tag%3Aconvert">convert</a>,
175         <a href="/wiki/doku.php/tag:j3o?do=showtag&amp;tag=tag%3Aj3o">j3o</a>,
176         <a href="/wiki/doku.php/tag:models?do=showtag&amp;tag=tag%3Amodels">models</a>,
177         <a href="/wiki/doku.php/tag:load?do=showtag&amp;tag=tag%3Aload">load</a>,
178         <a href="/wiki/doku.php/tag:save?do=showtag&amp;tag=tag%3Asave">save</a>,
179         <a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
180         <a href="/wiki/doku.php/tag:serialization?do=showtag&amp;tag=tag%3Aserialization">serialization</a>,
181         <a href="/wiki/doku.php/tag:import?do=showtag&amp;tag=tag%3Aimport">import</a>,
182         <a href="/wiki/doku.php/tag:export?do=showtag&amp;tag=tag%3Aexport">export</a>,
183         <a href="/wiki/doku.php/tag:spatial?do=showtag&amp;tag=tag%3Aspatial">spatial</a>,
184         <a href="/wiki/doku.php/tag:node?do=showtag&amp;tag=tag%3Anode">node</a>,
185         <a href="/wiki/doku.php/tag:mesh?do=showtag&amp;tag=tag%3Amesh">mesh</a>,
186         <a href="/wiki/doku.php/tag:geometry?do=showtag&amp;tag=tag%3Ageometry">geometry</a>,
187         <a href="/wiki/doku.php/tag:scenegraph?do=showtag&amp;tag=tag%3Ascenegraph">scenegraph</a>,
188         <a href="/wiki/doku.php/tag:sdk?do=showtag&amp;tag=tag%3Asdk">sdk</a>
189 </span></div>
190
191 </div>
192 <!-- EDIT5 SECTION "Custom Savable Class" [3303-] -->
193 <p><em><a href="http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:save_and_load?do=export_xhtmlbody">view online version</a></em></p>