XmlParticles.htm 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. <html xmlns:MSHelp="http://msdn.microsoft.com/mshelp" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xanx="http://schemas.microsoft.com/developer/xanx/2005"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="save" content="history" /><title>Authoring Particle Systems Using XML and the Content Pipeline</title>
  2. <style><!--
  3. /***********************************************************
  4. * SCRIPT-SUPPORTING STYLES
  5. ***********************************************************/
  6. /* Defines the userData cache persistence mechanism. */
  7. .userDataStyle
  8. {
  9. behavior: url(#default#userData);
  10. }
  11. /* Used to save the scroll bar position when navigating away from a page. */
  12. div.saveHistory
  13. {
  14. behavior: url(#default#saveHistory);
  15. }
  16. /* Formats the expand/collapse images for all collapsible regions. */
  17. img.toggle
  18. {
  19. border: 0;
  20. margin-right: 5;
  21. }
  22. /* Formats the Language filter drop-down image. */
  23. img#languageFilterImage
  24. {
  25. border: 0;
  26. margin-left: 0;
  27. vertical-align: middle;
  28. }
  29. /* Formats the Members Options filter drop-down image. */
  30. img#membersOptionsFilterImage
  31. {
  32. border: 0;
  33. margin-left: 0;
  34. vertical-align: middle;
  35. }
  36. /* Formats the Collapse All/Expand All images. */
  37. img#toggleAllImage
  38. {
  39. margin-left: 0;
  40. vertical-align: middle;
  41. }
  42. /* Supports XLinks */
  43. MSHelp\:link
  44. {
  45. text-decoration: underline;
  46. color: #0000ff;
  47. hoverColor: #3366ff;
  48. filterString: ;
  49. }
  50. body
  51. {
  52. background: #FFFFFF;
  53. color: #000000;
  54. font-family: Verdana;
  55. font-size: medium;
  56. font-style: normal;
  57. font-weight: normal;
  58. margin-top: 0;
  59. margin-bottom: 0;
  60. margin-left: 0;
  61. margin-right: 0;
  62. width: 100%;
  63. /*font-size: 110%;*/
  64. }
  65. div.section
  66. {
  67. margin-left: 15px;
  68. }
  69. div.hxnx5
  70. {
  71. margin-left: 1.5em;
  72. }
  73. /* Font for all headings */
  74. h1, h2, h3, h4, h5, h6
  75. {
  76. font-family: Verdana, Arial, Helvetica, sans-serif;
  77. margin-top: 18;
  78. margin-bottom: 8;
  79. font-weight: bold;
  80. }
  81. h1
  82. {
  83. font-size: 130%;
  84. color: #003399;
  85. }
  86. div#scrollyes h1 /* Changes font size for full-scrolling topic */
  87. {
  88. font-size: 150%;
  89. }
  90. h2
  91. {
  92. font-size: 122%;
  93. }
  94. h3
  95. {
  96. font-size: 115%;
  97. margin-top: 9;
  98. margin-bottom: 4;
  99. }
  100. h4
  101. {
  102. font-size: 115%;
  103. margin-top: 9;
  104. margin-bottom: 4;
  105. }
  106. h5
  107. {
  108. font-size: 100%;
  109. margin-top: 9;
  110. margin-bottom: 4;
  111. }
  112. h6
  113. {
  114. font-size: 100%;
  115. margin-top: 9;
  116. margin-bottom: 4;
  117. }
  118. ul p, ol p, dl p
  119. {
  120. margin-left: 0em;
  121. }
  122. p
  123. {
  124. margin-top: .6em;
  125. margin-bottom: .6em;
  126. }
  127. td p
  128. {
  129. margin-top: 0.0em;
  130. margin-bottom: 0.6em;
  131. }
  132. dd p
  133. {
  134. margin-top: 0.0em;
  135. margin-bottom: 0.6em;
  136. }
  137. .image
  138. {
  139. text-align: center;
  140. }
  141. dl
  142. {
  143. margin-top: 0em;
  144. margin-bottom: 1.3em;
  145. }
  146. dd
  147. {
  148. margin-bottom: 0em;
  149. margin-left: 1.5em;
  150. }
  151. dl.glossary dd
  152. {
  153. margin-bottom: 0em;
  154. margin-left: 1.5em;
  155. }
  156. dt
  157. {
  158. margin-top: .6em;
  159. margin-bottom: 1;
  160. }
  161. ul, ol
  162. {
  163. margin-top: 0.6em;
  164. margin-bottom: 0.6em;
  165. }
  166. ol
  167. {
  168. margin-left: 2.5em;
  169. }
  170. ul
  171. {
  172. list-style-type: disc;
  173. margin-left: 1.9em;
  174. }
  175. li
  176. {
  177. margin-bottom: 0.4em;
  178. }
  179. ul ol, ol ol
  180. {
  181. list-style-type: lower-alpha;
  182. }
  183. pre
  184. {
  185. margin-top: .6em;
  186. margin-bottom: .6em;
  187. font: 105% Lucida, mono;
  188. color: #000066;
  189. }
  190. code
  191. {
  192. font-family: Monospace, Courier New, Courier;
  193. font-size: 105%;
  194. color: #000066;
  195. }
  196. table.userdata td
  197. {
  198. background: #ffffff;
  199. background-color: #F5F5F5;
  200. border-color: #ffffff;
  201. border: none;
  202. }
  203. table.clsWarning
  204. {
  205. background: #ffffff;
  206. padding: 0px;
  207. margin: 0px;
  208. border: none;
  209. }
  210. table.clsWarning td
  211. {
  212. padding: 0px;
  213. margin: 0px;
  214. background: #ffffff;
  215. vertical-align: middle;
  216. font-size: 70%;
  217. }
  218. div#mainSection table
  219. {
  220. width: 95%;
  221. background: #ffffff;
  222. margin-top: 5px;
  223. margin-bottom: 5px;
  224. }
  225. div#mainSection table th
  226. {
  227. padding: 5px 6px;
  228. background: #EFEFF7;
  229. text-align: left;
  230. font-size: 70%;
  231. vertical-align: bottom;
  232. border-bottom: 1px solid #C8CDDE;
  233. }
  234. div#mainSection table td
  235. {
  236. padding: 5px 5px;
  237. background: #F7F7FF;
  238. vertical-align: top;
  239. font-size: 70%;
  240. border-bottom: 1px solid #D5D5D3;
  241. }
  242. div#syntaxCodeBlocks table th
  243. {
  244. padding: 1px 6px;
  245. color: #000066;
  246. }
  247. div#syntaxCodeBlocks table td
  248. {
  249. padding: 1px 5px;
  250. }
  251. /* Applies to the running header text in the first row of the upper table in the
  252. non-scrolling header region. */
  253. span#runningHeaderText
  254. {
  255. color: #003399;
  256. font-size: 90%;
  257. padding-left: 13;
  258. }
  259. /* Applies to the topic title in the second row of the upper table in the
  260. non-scrolling header region. */
  261. span#nsrTitle
  262. {
  263. color: #003399;
  264. font-size: 120%;
  265. font-weight: 600;
  266. padding-left: 13;
  267. }
  268. /* Applies to everything below the non-scrolling header region. */
  269. div#mainSection
  270. {
  271. font-size: 70%;
  272. width: 100%;
  273. }
  274. /* Applies to everything below the non-scrolling header region, minus the footer. */
  275. div#mainBody
  276. {
  277. font-size: 90%;
  278. margin-left: 15;
  279. margin-top: 10;
  280. padding-bottom: 20;
  281. }
  282. /* Adds right padding for all blocks in mainBody */
  283. div#mainBody p, div#mainBody ol, div#mainBody ul, div#mainBody dl
  284. {
  285. padding-right: 5;
  286. }
  287. div#mainBody div.alert, div#mainBody div.code, div#mainBody div.tableSection
  288. {
  289. width:98.9%;
  290. }
  291. div.alert p, div.code p
  292. {
  293. margin-top:5;
  294. margin-bottom:8;
  295. }
  296. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  297. div#mainSection div.alert table
  298. {
  299. border: 0;
  300. }
  301. div#mainSection div.alert table th
  302. {
  303. padding-top: 0;
  304. padding-bottom: 0;
  305. padding-left: 5;
  306. padding-right: 5;
  307. }
  308. div#mainSection div.alert table td
  309. {
  310. padding-left: 5;
  311. padding-right: 5;
  312. }
  313. img.note
  314. {
  315. border: 0;
  316. margin-left: 0;
  317. margin-right: 3;
  318. }
  319. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - End Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  320. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Non-scrolling Header Region Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  321. /* Applies to the entire non-scrolling header region. */
  322. div#header
  323. {
  324. background-color: #D4DFFF;
  325. padding-top: 0;
  326. padding-bottom: 0;
  327. padding-left: 0;
  328. padding-right: 0;
  329. width: 100%;
  330. }
  331. /* Applies to both tables in the non-scrolling header region. */
  332. div#header table
  333. {
  334. margin-top: 0;
  335. margin-bottom: 0;
  336. border-bottom-color: #C8CDDE;
  337. border-bottom-style: solid;
  338. border-bottom-width: 1;
  339. background: #D4DFFF;
  340. width: 100%;
  341. }
  342. /* Applies to cells in both tables in the non-scrolling header region. */
  343. div#header table td
  344. {
  345. color: #0000FF;
  346. font-size: 70%;
  347. padding-right: 20;
  348. padding-top: 1;
  349. padding-bottom: 1;
  350. border: none;
  351. background: #D4DFFF;
  352. }
  353. /* Applies to the last row in the upper table of the non-scrolling header region. Text
  354. in this row includes See Also, Constructors, Methods, and Properties. */
  355. div#header table tr#headerTableRow3 td
  356. {
  357. padding-bottom: 2;
  358. padding-top: 5;
  359. padding-left: 15;
  360. }
  361. /* Applies to the lower table in the non-scrolling header region. Text in this table
  362. includes Collapse All/Expand All, Language Filter, and Members Options. */
  363. div#header table#bottomTable
  364. {
  365. border-top-color: #FFFFFF;
  366. border-top-style: solid;
  367. border-top-width: 1;
  368. text-align: left;
  369. padding-left: 15;
  370. }
  371. blockquote
  372. {
  373. margin-left: 3.8em;
  374. margin-right: 3.8em;
  375. margin-top: .6em;
  376. margin-bottom: .6em;
  377. }
  378. sup
  379. {
  380. text-decoration: none;
  381. font-size: smaller;
  382. }
  383. a:link
  384. {
  385. color: #0000FF;
  386. /* font-weight: bold */
  387. }
  388. a:visited
  389. {
  390. color: #0000AA;
  391. /* font-weight: bold */
  392. }
  393. a:hover
  394. {
  395. color: #3366FF;
  396. /* font-weight: bold */
  397. }
  398. .label
  399. {
  400. font-weight: bold;
  401. margin-top: 1em;
  402. margin-left: -26px;
  403. }
  404. .tl
  405. {
  406. margin-bottom: .75em;
  407. }
  408. .atl
  409. {
  410. padding-left: 1.5em;
  411. padding-bottom: .75em;
  412. }
  413. .cfe
  414. {
  415. font-weight: bold;
  416. }
  417. .mini
  418. {
  419. font-size: smaller;
  420. }
  421. .dt
  422. {
  423. margin-bottom: -.6em;
  424. }
  425. .indent
  426. {
  427. margin-left: 1.9em;
  428. margin-right: 1.9em;
  429. }
  430. .product
  431. {
  432. text-align: right;
  433. color: #333333;
  434. font-size: smaller;
  435. font-style: italic;
  436. }
  437. .buttonbarshade
  438. {
  439. position: relative;
  440. margin: 0;
  441. left: 0px;
  442. top: 2;
  443. width: 50%;
  444. height: 40px;
  445. }
  446. .buttonbartable
  447. {
  448. position: absolute;
  449. margin: 0;
  450. padding:0;
  451. border:0;
  452. left:0px;
  453. top: 2;
  454. width: 100%;
  455. height: 40px;
  456. }
  457. /* background color, font for header */
  458. table.buttonbartable td, table.buttonbarshade td
  459. {
  460. background: #ffffff; /*#5177B8; #80C615;*/
  461. border-left: 0px solid #80C615;
  462. margin: 0;
  463. padding: 0px 0px 0px 0px;
  464. font-family: Impact, sans-serif;
  465. font-size: 14pt;
  466. }
  467. table.buttonbartable td.button1
  468. {
  469. background: #5177B8; /*#80C615;*/;
  470. padding: 0;
  471. font-weight: bold;
  472. text-align: center;
  473. cursor: hand;
  474. }
  475. table.buttonbartable td.button2
  476. {
  477. background: #5177B8; /*#80C615;*/;
  478. font-weight: bold;
  479. text-align: center;
  480. }
  481. table.buttonbartable td.button3
  482. {
  483. background: #5177B8; /*#80C615;*/;
  484. font-weight: bold;
  485. text-align: center;
  486. }
  487. table.buttonbartable td.runninghead
  488. {
  489. padding-left: 0px;
  490. font-style: italic;
  491. text-align: left;
  492. }
  493. .version
  494. {
  495. text-align: left;
  496. color: #000000;
  497. margin-top: 3em;
  498. margin-left: -26px;
  499. font-size: smaller;
  500. font-style: italic;
  501. }
  502. .lang, .ilang
  503. {
  504. color: #0000ff;
  505. font: normal 7pt Arial, Helvetica, sans-serif;
  506. }
  507. div.langMenu
  508. {
  509. position: absolute;
  510. z-index: 1;
  511. width: 96pt;
  512. padding: 8pt;
  513. visibility: hidden;
  514. border: 1px solid #000000;
  515. background: #ffffd0;
  516. }
  517. div.langMenu ul
  518. {
  519. padding-left: 2em;
  520. margin-left: 0;
  521. }
  522. div.filtered
  523. {
  524. margin: 4pt 0 8pt -26px;
  525. padding: 4px 4px 8px 26px;
  526. width: 100%;
  527. border: 2px solid #aaaacc;
  528. background: #ffffff;
  529. }
  530. div.filtered2
  531. {
  532. margin: 4pt 0 8pt -26px;
  533. padding: 4px 4px 8px 26px;
  534. width: 100%;
  535. border: none;
  536. background: #ffffff;
  537. }
  538. div.filtered h1, div.filtered h2, div.filtered h3, div.filtered h4
  539. {
  540. margin-left: -22px;
  541. }
  542. div.filtered span.lang
  543. {
  544. position: relative;
  545. left: -22px;
  546. }
  547. div.reftip
  548. {
  549. position: absolute;
  550. z-index: 1;
  551. padding: 8pt;
  552. visibility: hidden;
  553. border: 1px solid #000000;
  554. background: #ffffd0;
  555. }
  556. a.synParam
  557. {
  558. color: #0000FF;
  559. /*color: #3F7800;*/
  560. /*color: #8DC54F;*/
  561. text-decoration: none;
  562. font-weight: normal;
  563. }
  564. a.synParam:hover
  565. {
  566. text-decoration: underline;
  567. font-weight: normal;
  568. }
  569. div.sapop
  570. {
  571. position: absolute;
  572. z-index: 1;
  573. left: 26px;
  574. width: 100%;
  575. padding: 10px 10px 10px 36px;
  576. visibility: hidden;
  577. border: 1px solid #000000;
  578. background: #ffffd0;
  579. }
  580. div.footer
  581. {
  582. width: 100%;
  583. border: none;
  584. background: #ffffff;
  585. margin-top: 18pt;
  586. padding-bottom: 12pt;
  587. color: #0000FF;
  588. /*color: #228B22; */
  589. text-align: center;
  590. font-size: 76%;
  591. }
  592. div.preliminary
  593. {
  594. margin-top: 8pt;
  595. padding-bottom: 12pt;
  596. color: #A0A0A0;
  597. }
  598. /* A procedure section. eg. 'To create a file', 'To add a value' */
  599. div.proc
  600. {
  601. margin-left: 0.5em;
  602. }
  603. /* The title of a 'procedure' section. */
  604. div.proc h3
  605. {
  606. font-family: Verdana, Arial, Helvetica, sans-serif;
  607. font-weight: bold;
  608. font-size: 115%;
  609. margin-top: 1em;
  610. margin-bottom: 0.4em;
  611. margin-left: -0.5em;
  612. color: #003399;
  613. }
  614. div.proc ul
  615. {
  616. margin-left: 1.5em;
  617. }
  618. div.proc ol
  619. {
  620. margin-left: 2.0em;
  621. }
  622. .note
  623. {
  624. margin-left: 14pt;
  625. margin-right: 12pt;
  626. }
  627. .indent1
  628. {
  629. margin-left: 12pt;
  630. }
  631. .indent2
  632. {
  633. margin-left: 24pt;
  634. }
  635. .indent3
  636. {
  637. margin-left: 36pt;
  638. }
  639. p.proch
  640. {
  641. padding-left: 16px;
  642. }
  643. p.proch img
  644. {
  645. position: relative;
  646. vertical-align: top;
  647. left: -18px;
  648. margin-right: -14px;
  649. margin-bottom: -18px;
  650. }
  651. div.clsPlatSpec
  652. {
  653. background-color:#FFF8DC;
  654. border-style:solid;
  655. border-width:1pt 0pt 0pt 1pt;
  656. border-color:#ffE4C4;
  657. margin-top:0.6em;
  658. width:100%;
  659. }
  660. /* Applies to the language labels in the Language Filter drop-down list. */
  661. .languageFilter
  662. {
  663. color: #0000FF;
  664. cursor:hand;
  665. text-decoration:underline;
  666. padding-bottom:4;
  667. }
  668. /* Dropdown areas */
  669. #languageSpan {
  670. position: absolute;
  671. visibility: hidden;
  672. border-style: solid;
  673. border-width: 1px;
  674. border-color: #C8CDDE;
  675. background: #d4dfff;
  676. padding: 4px;
  677. font-size: 70%;
  678. }
  679. #membersOptionsSpan {
  680. position: absolute;
  681. visibility: hidden;
  682. border-style: solid;
  683. border-width: 1px;
  684. border-color: #C8CDDE;
  685. background: #d4dfff;
  686. padding: 4px;
  687. font-size: 70%;
  688. }
  689. --></style>
  690. <xml>
  691. <MSHelp:TOCTitle Title="Authoring Particle Systems Using XML and the Content Pipeline" />
  692. <MSHelp:RLTitle Title="Authoring Particle Systems Using XML and the Content Pipeline" />
  693. <MSHelp:Keyword Index="A" Term="O:Microsoft.Xna.XmlParticles" />
  694. <MSHelp:Keyword Index="A" Term="d2906078-b9b9-d492-e407-001884cc1d76" />
  695. <MSHelp:Keyword Index="K" Term="Authoring Particle Systems Using XML and the Content Pipeline" />
  696. <MSHelp:Attr Name="AssetID" Value="d2906078-b9b9-d492-e407-001884cc1d76" />
  697. <MSHelp:Attr Name="Locale" Value="en-us" />
  698. <MSHelp:Attr Name="CommunityContent" Value="1" />
  699. <MSHelp:Attr Name="TopicType" Value="kbOrient" />
  700. </xml>
  701. </head><body><div id="mainSection"><div id="mainBody">
  702. <h1>Authoring Particle Systems Using XML and the Content Pipeline</h1>
  703. <p>
  704. This tutorial teaches you how to extend the Particle 3D Sample so the particle systems are defined using XML files loaded with the Content Pipeline.
  705. It contains the following sections:
  706. </p>
  707. <ul><li><a href="#ID2EP">Introduction</a></li><li><a href="#ID2ELB">Getting Started</a></li><li><a href="#ID2EZC">Updating the Game Code</a></li><li><a href="#ID2E5G">Creating a Settings Assembly</a></li><li><a href="#ID2EVBAC">Creating XML Settings Files</a></li><li><a href="#ID2E2BAE">Final Result</a></li></ul>
  708. <a id="ID2EP" name="ID2EP"> </a><h1 class="heading">Introduction</h1><div id="ID2EP" class="hxnx1">
  709. <p>
  710. In the original version of the Particle 3D Sample, we defined each particle system by creating a separate class that derived from the abstract <code>ParticleSystem</code> base class. Each new class overloaded the <code>InitializeSettings</code> method to specify how to display the particle system. This meant you had to create a new class each time you wanted to add a new type of particle. Furthermore, you had to recompile your game each time you modified one of these classes to alter the particle behavior. This tutorial shows you how to make that process more efficient. Using external XML files enables you to create and tweak any number of different particle systems without changing the main game executable.
  711. </p>
  712. <p>
  713. The easiest approach would be to use the .NET <b>XmlSerializer</b> to load the <code>ParticleSettings</code> data from an XML file. However, you are going to use the Content Pipeline instead. This offers several advantages:
  714. </p>
  715. <ol>
  716. <li>
  717. XML files are bulky and can be slow to load. The Content Pipeline enables you to compile your XML data into a compact binary XNB file as part of the content build process.
  718. </li>
  719. <li>Building the XML settings into a binary format makes it harder for anyone to modify your data.</li>
  720. <li>
  721. Using the Content Pipeline enables you to move a lot of setup code out of the main game and into a custom content processor. Doing this work ahead of time during the content build process keeps the game nice and simple. It also ensures good load times.
  722. </li>
  723. </ol>
  724. </div>
  725. <a id="ID2ELB" name="ID2ELB"> </a><h1 class="heading">Getting Started</h1><div id="ID2ELB" class="hxnx1">
  726. <p>
  727. You are going to use the Windows version of the Particle 3D Sample as a starting point. Begin by downloading version 4.0 of the sample, and then make a copy of the sample that you can edit.
  728. </p>
  729. <p>The flow of data through the Content Pipeline goes like this:</p>
  730. <ol>
  731. <li>
  732. <p>During the content build process:</p>
  733. <ol>
  734. <li>The <code>ContentImporter</code> reads data from external files.</li>
  735. <li>The <code>ContentProcessor</code> processes the data.</li>
  736. <li>The data is serialized into a binary XNB file.</li>
  737. </ol>
  738. </li>
  739. <li>Inside the game itself, the <code>ContentManager.Load</code> method deserializes data from the XNB file.</li>
  740. </ol>
  741. <p>
  742. You do not need to write your own <code>ContentImporter</code>. XNA Game Studio comes
  743. with a built-in <b>XmlImporter</b> that will work well for you. Also, for this
  744. purpose you need not bother with a <code>ContentProcessor</code> because you do not
  745. need to do any special processing on your data. For now, you are going to concentrate
  746. on the basic flow of moving data from XML files into your game.
  747. </p>
  748. </div>
  749. <a id="ID2EZC" name="ID2EZC"> </a><h1 class="heading">Updating the Game Code</h1><div id="ID2EZC" class="hxnx1">
  750. <p>You need to make some changes inside ParticleSystem.cs.</p>
  751. <ol>
  752. <li>
  753. Remove the <b>abstract</b> keyword from the declaration of the <code>ParticleSystem</code>
  754. class. You are going to be loading XML settings data directly into the base <code>ParticleSystem</code>
  755. class, rather than deriving specialized particle system classes from it, so this should no longer be abstract.
  756. </li>
  757. <li>
  758. <p>
  759. Inside the <code>Fields</code> region near the top of the <code>ParticleSystem</code> class,
  760. add a new field to store the name of the XML settings file.
  761. </p>
  762. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>// Name of the XML settings file describing this particle system.
  763. string settingsName;</pre></pre></td></tr></table></span></div>
  764. <p>At line 32, change this existing field declaration:</p>
  765. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>ParticleSettings settings = new ParticleSettings();</pre></pre></td></tr></table></span></div>
  766. <p>to:</p>
  767. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>ParticleSettings settings;</pre></pre></td></tr></table></span></div>
  768. <p>
  769. Since you are going to be loading settings using the <code>ContentManager</code>,
  770. you no longer need to create a blank settings descriptor here.
  771. </p>
  772. </li>
  773. <li>
  774. <p>
  775. Find the <code>ParticleSystem</code> constructor at line 162, and change it to store the settings name.
  776. </p>
  777. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>/// &lt;summary&gt;
  778. /// Constructor.
  779. /// &lt;/summary&gt;
  780. public ParticleSystem(Game game, ContentManager content, string settingsName)
  781. : base(game)
  782. {
  783. this.content = content;
  784. this.settingsName = settingsName;
  785. } </pre></pre></td></tr></table></span></div>
  786. </li>
  787. <li>Delete the <code>Initialize</code> and <code>InitializeSettings</code> methods. You will not need them any more.</li>
  788. <li>
  789. <p>
  790. In the <code>LoadContent</code> method (line 173), insert these new lines, which are
  791. highlighted in bold. The first line loads your settings data via the <code>ContentManager</code>.
  792. The others initialize the particles array.
  793. </p>
  794. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>/// &lt;summary&gt;
  795. /// Loads graphics for the particle system.
  796. /// &lt;/summary&gt;
  797. protected override void LoadContent()
  798. {
  799. <b>settings = content.Load&lt;ParticleSettings&gt;(settingsName);
  800. // Allocate the particle array, and fill in the corner fields (which never change).
  801. particles = new ParticleVertex[settings.MaxParticles * 4];
  802. for (int i = 0; i &lt; settings.MaxParticles; i++)
  803. {
  804. particles[i * 4 + 0].Corner = new Short2(-1, -1);
  805. particles[i * 4 + 1].Corner = new Short2(1, -1);
  806. particles[i * 4 + 2].Corner = new Short2(1, 1);
  807. particles[i * 4 + 3].Corner = new Short2(-1, 1);
  808. }</b>
  809. LoadParticleEffect();
  810. ...</pre></pre></td></tr></table></span></div>
  811. </li>
  812. <li>
  813. <p>
  814. Now, for something fun. In <b>Solution Explorer</b>, delete the ParticleSystems folder along with all the old hard-coded particle system classes inside it. You no longer need these!
  815. </p>
  816. <p>Open Game.cs, go to line 94, and replace this section, which created several different hard-coded classes:</p>
  817. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>// Construct our particle system components.
  818. explosionParticles = new ExplosionParticleSystem(this, Content);
  819. explosionSmokeParticles = new ExplosionSmokeParticleSystem(this, Content);
  820. projectileTrailParticles = new ProjectileTrailParticleSystem(this, Content);
  821. smokePlumeParticles = new SmokePlumeParticleSystem(this, Content);
  822. fireParticles = new FireParticleSystem(this, Content);</pre></pre></td></tr></table></span></div>
  823. <p>
  824. with this new version that creates multiple instances of our new data driven <code>ParticleSystem</code> class, specifying a different settings file for each one:
  825. </p>
  826. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>// Construct our particle system components.
  827. explosionParticles = new ParticleSystem(this, Content, "ExplosionSettings");
  828. explosionSmokeParticles = new ParticleSystem(this, Content, "ExplosionSmokeSettings");
  829. projectileTrailParticles = new ParticleSystem(this, Content, "ProjectileTrailSettings");
  830. smokePlumeParticles = new ParticleSystem(this, Content, "SmokePlumeSettings");
  831. fireParticles = new ParticleSystem(this, Content, "FireSettings");</pre></pre></td></tr></table></span></div>
  832. <p>And that is it! We're done.</p>
  833. </li>
  834. </ol>
  835. <p>
  836. At least we are done changing our game code. Of course, it won't actually run yet. If we press F5 to launch it, we will get a <b>ContentLoadException</b> with the message <code>Error loading "ExplosionSettings." File not found</code>. This is because we haven't actually created any settings data for the game to load yet.
  837. </p>
  838. </div>
  839. <a id="ID2E5G" name="ID2E5G"> </a><h1 class="heading">Creating a Settings Assembly</h1><div id="ID2E5G" class="hxnx1">
  840. <p>
  841. To build particle system settings data using the Content Pipeline, you must move the <b>ParticleSettings</b> class into a second assembly. You cannot leave this directly inside the main game project for several reasons.
  842. </p>
  843. <ol>
  844. <li>The Content Pipeline code runs as part of the build process. It does not run inside the game itself. To be able to build settings data, the definition of the settings class must be available while this data is being built. At the time when the data is built, the game itself has not been built yet! So if the settings data was defined inside the game, there would be an impossible circular dependency.</li>
  845. <li>Because the Content Pipeline code runs as part of the build, you must always run it on Windows, even if the game itself is for Xbox. This means that when you are building an Xbox game, there must be two versions of the settings class: a Windows version for use during the Content Pipeline data build, and an Xbox version that can be used at run time by the game itself.</li>
  846. </ol>
  847. <p>Putting the settings class into a separate assembly from the game is an elegant way to satisfy both these requirements.</p>
  848. <div class="proc"><h3 class="subHeading">To add a second project</h3><div class="subSection">
  849. <ol>
  850. <li>In <b>Solution Explorer</b>, right-click the <b>Solution</b> node, click <b>Add</b>, click <b>New project</b>, and then select the <b>Windows Game Library</b> template.</li>
  851. <li>Enter <b>ParticleSettings</b> as the name of your new project.</li>
  852. <li>Delete the Class1.cs file that the project template gives you by default. You will not need it.</li>
  853. <li>Move your <code>ParticleSettings</code> class from the original game project to this new assembly. Drag and drop the ParticleSettings.cs file from one project to the other inside the Solution Explorer pane, and then delete the original version.
  854. </li>
  855. <li>
  856. <p>
  857. Because we need to use the <b>ParticleSettings</b> class both when building content and at run time, you must
  858. reference the new project twice: once from the main game project, then again from your Content project.
  859. </p>
  860. <ol>
  861. <li>
  862. Under <b>Particle3DSampleWindows</b>, right-click the <b>References</b> node, and click <b>Add Reference</b>.
  863. </li>
  864. <li>
  865. Next, click the <b>Projects</b> tab, and then select the <b>ParticleSettings</b> project.
  866. </li>
  867. <li>
  868. Repeat these actions, adding to the <b>References</b> node in the <b>Particle3DSampleContent</b> project.
  869. </li>
  870. </ol>
  871. </li>
  872. </ol>
  873. </div></div>
  874. </div>
  875. <a id="ID2EVBAC" name="ID2EVBAC"> </a><h1 class="heading">Creating XML Settings Files</h1><div id="ID2EVBAC" class="hxnx1">
  876. <p>Here we run into a small problem. Most of the data stored in the <b>ParticleSettings</b> class can be automatically serialized by the Content Pipeline, but it has one field of type <b>BlendState</b>, which is a complex GPU type that cannot be automatically serialized. To work around this, we will use Content Pipeline control attributes to tell the pipeline not to bother serializing this field, and instead use a helper property that will convert the blend state setting into a simple string that the serializer will be able to store for us.</p>
  877. <p>To do this, open ParticleSettings.xml, and then add the <b>Microsoft.Xna.Framework.Content</b> namespace to the using statements near the top of the file. At the end of the class, replace this code:</p>
  878. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>// Alpha blending settings.
  879. public BlendState BlendState = BlendState.NonPremultiplied;</pre></pre></td></tr></table></span></div>
  880. <p>with this code:</p>
  881. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>// Alpha blending settings.
  882. [ContentSerializerIgnore]
  883. public BlendState BlendState = BlendState.NonPremultiplied;
  884. [ContentSerializer(ElementName = "BlendState")]
  885. private string BlendStateSerializationHelper
  886. {
  887. get { return BlendState.Name.Replace("BlendState.", string.Empty); }
  888. set
  889. {
  890. switch (value)
  891. {
  892. case "AlphaBlend": BlendState = BlendState.AlphaBlend; break;
  893. case "Additive": BlendState = BlendState.Additive; break;
  894. case "NonPremultiplied": BlendState = BlendState.NonPremultiplied; break;
  895. default:
  896. throw new ArgumentException("Unknown blend state " + value);
  897. }
  898. }
  899. }</pre></pre></td></tr></table></span></div>
  900. <p>These control attributes tell the serializer to skip the <b>BlendState</b> field, and instead to use our private <b>BlendStateSerializationHelper</b> property, which converts the name of the blend state to and from an easily serialized string representation.</p>
  901. <p>
  902. Nearly there! For your final step, you must create some actual XML files that contain particle settings data. You are going to import these XML files into our <code>ParticleSettings</code> class. You need to ensure they match exactly the layout of that class in order for the deserialization to work. How do we know what this XML should look like? One way is to guess. A much more reliable approach, however, is to write a little test program that constructs an object of the type of which you are interested. After that, you can serialize the object out into the XML format. You can look at the resultant XML file to see how you should format the data.
  903. </p>
  904. <p>To test the XML serializer, add a TempMain.cs file to the <b>ParticleSettings</b> project, and then insert this code:</p>
  905. <div class="code"><span codeLanguage="CSharp"><table><tr><th>C# </th></tr><tr><td><pre><pre>using System.Xml;
  906. using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;
  907. namespace Particle3DSample
  908. {
  909. public static class TempMain
  910. {
  911. public static void Main()
  912. {
  913. object testValue = new ParticleSettings();
  914. XmlWriterSettings settings = new XmlWriterSettings();
  915. settings.Indent = true;
  916. using (XmlWriter xmlWriter = XmlWriter.Create("test.xml", settings))
  917. {
  918. IntermediateSerializer.Serialize(xmlWriter, testValue, null);
  919. }
  920. }
  921. }
  922. } </pre></pre></td></tr></table></span></div>
  923. <p>
  924. In order to run this program, you must temporarily change the <b>ParticleSettings</b>
  925. project from a DLL to an executable, and add a reference to the Content Pipeline assembly.
  926. </p>
  927. <div class="proc"><h3 class="subHeading">To change the ParticleSettings project from a DLL to an executable</h3><div class="subSection">
  928. <ol>
  929. <li>In <b>Solution Explorer</b>, right-click the <b>ParticleSettings</b> project, and then click <b>Properties</b>.</li>
  930. <li>In the <b>Application</b> tab, change the <b>Output type</b> from <b>Class Library</b> to <b>Console Application</b>,
  931. and then change the <b>Target profile</b> setting from <b>.NET Framework 4 Client Profile</b> to <b>.NET Framework 4</b>.</li>
  932. <li>Right-click the <b>References</b> node under <b>ParticleSettings</b>, and then click <b>Add Reference</b>.</li>
  933. <li>On the <b>.NET</b> tab, select <b>Microsoft.Xna.Framework.Content.Pipeline</b>.</li>
  934. <li>
  935. <p>Right-click the <b>ParticleSettings</b> project, click <b>Debug</b>, and then click <b>Start new instance</b>.</p>
  936. <p>A console window appears briefly.</p>
  937. </li>
  938. </ol>
  939. </div></div>
  940. <p>Look in your ParticleSettings\bin\x86\Debug directory. You will see that it created this test.xml file.</p>
  941. <pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  942. &lt;XnaContent&gt;
  943. &lt;Asset Type="Particle3DSample.ParticleSettings"&gt;
  944. &lt;BlendState&gt;NonPremultiplied&lt;/BlendState&gt;
  945. &lt;TextureName Null="true" /&gt;
  946. &lt;MaxParticles&gt;100&lt;/MaxParticles&gt;
  947. &lt;Duration&gt;PT1S&lt;/Duration&gt;
  948. &lt;DurationRandomness&gt;0&lt;/DurationRandomness&gt;
  949. &lt;EmitterVelocitySensitivity&gt;1&lt;/EmitterVelocitySensitivity&gt;
  950. &lt;MinHorizontalVelocity&gt;0&lt;/MinHorizontalVelocity&gt;
  951. &lt;MaxHorizontalVelocity&gt;0&lt;/MaxHorizontalVelocity&gt;
  952. &lt;MinVerticalVelocity&gt;0&lt;/MinVerticalVelocity&gt;
  953. &lt;MaxVerticalVelocity&gt;0&lt;/MaxVerticalVelocity&gt;
  954. &lt;Gravity&gt;0 0 0&lt;/Gravity&gt;
  955. &lt;EndVelocity&gt;1&lt;/EndVelocity&gt;
  956. &lt;MinColor&gt;FFFFFFFF&lt;/MinColor&gt;
  957. &lt;MaxColor&gt;FFFFFFFF&lt;/MaxColor&gt;
  958. &lt;MinRotateSpeed&gt;0&lt;/MinRotateSpeed&gt;
  959. &lt;MaxRotateSpeed&gt;0&lt;/MaxRotateSpeed&gt;
  960. &lt;MinStartSize&gt;100&lt;/MinStartSize&gt;
  961. &lt;MaxStartSize&gt;100&lt;/MaxStartSize&gt;
  962. &lt;MinEndSize&gt;100&lt;/MinEndSize&gt;
  963. &lt;MaxEndSize&gt;100&lt;/MaxEndSize&gt;
  964. &lt;/Asset&gt;
  965. &lt;/XnaContent&gt; </pre>
  966. <p>
  967. So <i>this is</i> what your XML should look like. Now, undo your temporary changes to the <b>ParticleSettings</b> project:
  968. </p>
  969. <ul>
  970. <li>Change the <b>Output type</b> from <b>Console Application</b> to <b>Class Library</b>.</li>
  971. <li>Change <b>Target profile</b> from <b>.NET Framework 4</b> to <b>.NET Framework 4 Client Profile</b>.</li>
  972. <li>Delete the TempMain.cs file.</li>
  973. <li>Remove the Microsoft.Xna.Framework.Content.Pipeline reference.</li>
  974. <li>Press F6 just to make sure everything still builds correctly.</li>
  975. </ul>
  976. <p>
  977. Obviously, a particle system with just those default settings will not be very interesting. We can make an ExplosionSettings.xml file by copying across the hard-coded settings from the original Particle 3D Sample.
  978. </p>
  979. <pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  980. &lt;XnaContent&gt;
  981. &lt;Asset Type="Particle3DSample.ParticleSettings"&gt;
  982. &lt;BlendState&gt;Additive&lt;/BlendState&gt;
  983. &lt;TextureName&gt;explosion&lt;/TextureName&gt;
  984. &lt;MaxParticles&gt;100&lt;/MaxParticles&gt;
  985. &lt;Duration&gt;PT2S&lt;/Duration&gt;
  986. &lt;DurationRandomness&gt;1&lt;/DurationRandomness&gt;
  987. &lt;EmitterVelocitySensitivity&gt;1&lt;/EmitterVelocitySensitivity&gt;
  988. &lt;MinHorizontalVelocity&gt;20&lt;/MinHorizontalVelocity&gt;
  989. &lt;MaxHorizontalVelocity&gt;30&lt;/MaxHorizontalVelocity&gt;
  990. &lt;MinVerticalVelocity&gt;-20&lt;/MinVerticalVelocity&gt;
  991. &lt;MaxVerticalVelocity&gt;20&lt;/MaxVerticalVelocity&gt;
  992. &lt;Gravity&gt;0 0 0&lt;/Gravity&gt;
  993. &lt;EndVelocity&gt;0&lt;/EndVelocity&gt;
  994. &lt;MinColor&gt;FF808080&lt;/MinColor&gt;
  995. &lt;MaxColor&gt;FFA9A9A9&lt;/MaxColor&gt;
  996. &lt;MinRotateSpeed&gt;-1&lt;/MinRotateSpeed&gt;
  997. &lt;MaxRotateSpeed&gt;1&lt;/MaxRotateSpeed&gt;
  998. &lt;MinStartSize&gt;10&lt;/MinStartSize&gt;
  999. &lt;MaxStartSize&gt;10&lt;/MaxStartSize&gt;
  1000. &lt;MinEndSize&gt;100&lt;/MinEndSize&gt;
  1001. &lt;MaxEndSize&gt;200&lt;/MaxEndSize&gt;
  1002. &lt;/Asset&gt;
  1003. &lt;/XnaContent&gt; </pre>
  1004. <p>
  1005. In addition to the ExplosionSettings.xml file, you need to create the new files ExplosionSmokeSettings.xml, FireSettings.xml, ProjectileTrailSettings.xml, and SmokePlumeSettings.xml. Repeat this process of copying and pasting the parameter values from the original sample. Add these five files to the <b>Particle3DSampleContent</b> project.
  1006. </p>
  1007. </div>
  1008. <a id="ID2E2BAE" name="ID2E2BAE"> </a><h1 class="heading">Final Result</h1><div id="ID2E2BAE" class="hxnx1">
  1009. <p>Press F5 to run the game.</p>
  1010. <p>If you followed the previous steps correctly, the results will look the same as the original Particle 3D Sample. One difference is you can now edit your particle systems by modifying the XML files. If you look in the Particle3DSample\bin\x86\Debug\Content directory, you will notice the directory does not contain any XML files. The Content Pipeline was used to compile the settings data into the XNB format.</p>
  1011. <p>See the XmlParticles directory for the complete code that you should have ended up with after following this tutorial.</p>
  1012. </div>
  1013. </div><div class="footer" id="footer"><p>© 2010 Microsoft Corporation. All rights reserved.<br />Send feedback to <a href="mailto:[email protected]?subject=Documentation Feedback: Authoring Particle Systems Using XML and the Content Pipeline">[email protected]</a>.</p></div></div></body></html>