hello_collision.html 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <meta name="generator" content="Asciidoctor 1.5.4">
  8. <title>jMonkeyEngine 3 Tutorial (9) - Hello Collision</title>
  9. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
  10. <style>
  11. /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
  12. /* Remove comment around @import statement below when using as a custom stylesheet */
  13. /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
  14. article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
  15. audio,canvas,video{display:inline-block}
  16. audio:not([controls]){display:none;height:0}
  17. [hidden],template{display:none}
  18. script{display:none!important}
  19. html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
  20. body{margin:0}
  21. a{background:transparent}
  22. a:focus{outline:thin dotted}
  23. a:active,a:hover{outline:0}
  24. h1{font-size:2em;margin:.67em 0}
  25. abbr[title]{border-bottom:1px dotted}
  26. b,strong{font-weight:bold}
  27. dfn{font-style:italic}
  28. hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
  29. mark{background:#ff0;color:#000}
  30. code,kbd,pre,samp{font-family:monospace;font-size:1em}
  31. pre{white-space:pre-wrap}
  32. q{quotes:"\201C" "\201D" "\2018" "\2019"}
  33. small{font-size:80%}
  34. sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
  35. sup{top:-.5em}
  36. sub{bottom:-.25em}
  37. img{border:0}
  38. svg:not(:root){overflow:hidden}
  39. figure{margin:0}
  40. fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
  41. legend{border:0;padding:0}
  42. button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
  43. button,input{line-height:normal}
  44. button,select{text-transform:none}
  45. button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
  46. button[disabled],html input[disabled]{cursor:default}
  47. input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
  48. input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
  49. input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
  50. button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
  51. textarea{overflow:auto;vertical-align:top}
  52. table{border-collapse:collapse;border-spacing:0}
  53. *,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
  54. html,body{font-size:100%}
  55. body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
  56. a:hover{cursor:pointer}
  57. img,object,embed{max-width:100%;height:auto}
  58. object,embed{height:100%}
  59. img{-ms-interpolation-mode:bicubic}
  60. .left{float:left!important}
  61. .right{float:right!important}
  62. .text-left{text-align:left!important}
  63. .text-right{text-align:right!important}
  64. .text-center{text-align:center!important}
  65. .text-justify{text-align:justify!important}
  66. .hide{display:none}
  67. body{-webkit-font-smoothing:antialiased}
  68. img,object,svg{display:inline-block;vertical-align:middle}
  69. textarea{height:auto;min-height:50px}
  70. select{width:100%}
  71. .center{margin-left:auto;margin-right:auto}
  72. .spread{width:100%}
  73. p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
  74. .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
  75. div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
  76. a{color:#2156a5;text-decoration:underline;line-height:inherit}
  77. a:hover,a:focus{color:#1d4b8f}
  78. a img{border:none}
  79. p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
  80. p aside{font-size:.875em;line-height:1.35;font-style:italic}
  81. h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
  82. h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
  83. h1{font-size:2.125em}
  84. h2{font-size:1.6875em}
  85. h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
  86. h4,h5{font-size:1.125em}
  87. h6{font-size:1em}
  88. hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
  89. em,i{font-style:italic;line-height:inherit}
  90. strong,b{font-weight:bold;line-height:inherit}
  91. small{font-size:60%;line-height:inherit}
  92. code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
  93. ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
  94. ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
  95. ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
  96. ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
  97. ul.square{list-style-type:square}
  98. ul.circle{list-style-type:circle}
  99. ul.disc{list-style-type:disc}
  100. ul.no-bullet{list-style:none}
  101. ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
  102. dl dt{margin-bottom:.3125em;font-weight:bold}
  103. dl dd{margin-bottom:1.25em}
  104. abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
  105. abbr{text-transform:none}
  106. blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
  107. blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
  108. blockquote cite:before{content:"\2014 \0020"}
  109. blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
  110. blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
  111. @media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
  112. h1{font-size:2.75em}
  113. h2{font-size:2.3125em}
  114. h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
  115. h4{font-size:1.4375em}}
  116. table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
  117. table thead,table tfoot{background:#f7f8f7;font-weight:bold}
  118. table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
  119. table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
  120. table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
  121. table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
  122. body{tab-size:4}
  123. h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
  124. h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
  125. .clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
  126. .clearfix:after,.float-group:after{clear:both}
  127. *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
  128. pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
  129. .keyseq{color:rgba(51,51,51,.8)}
  130. kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
  131. .keyseq kbd:first-child{margin-left:0}
  132. .keyseq kbd:last-child{margin-right:0}
  133. .menuseq,.menu{color:rgba(0,0,0,.8)}
  134. b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
  135. b.button:before{content:"[";padding:0 3px 0 2px}
  136. b.button:after{content:"]";padding:0 2px 0 3px}
  137. p a>code:hover{color:rgba(0,0,0,.9)}
  138. #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
  139. #header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
  140. #header:after,#content:after,#footnotes:after,#footer:after{clear:both}
  141. #content{margin-top:1.25em}
  142. #content:before{content:none}
  143. #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
  144. #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
  145. #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
  146. #header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
  147. #header .details span:first-child{margin-left:-.125em}
  148. #header .details span.email a{color:rgba(0,0,0,.85)}
  149. #header .details br{display:none}
  150. #header .details br+span:before{content:"\00a0\2013\00a0"}
  151. #header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
  152. #header .details br+span#revremark:before{content:"\00a0|\00a0"}
  153. #header #revnumber{text-transform:capitalize}
  154. #header #revnumber:after{content:"\00a0"}
  155. #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
  156. #toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
  157. #toc>ul{margin-left:.125em}
  158. #toc ul.sectlevel0>li>a{font-style:italic}
  159. #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
  160. #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
  161. #toc li{line-height:1.3334;margin-top:.3334em}
  162. #toc a{text-decoration:none}
  163. #toc a:active{text-decoration:underline}
  164. #toctitle{color:#7a2518;font-size:1.2em}
  165. @media only screen and (min-width:768px){#toctitle{font-size:1.375em}
  166. body.toc2{padding-left:15em;padding-right:0}
  167. #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
  168. #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
  169. #toc.toc2>ul{font-size:.9em;margin-bottom:0}
  170. #toc.toc2 ul ul{margin-left:0;padding-left:1em}
  171. #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
  172. body.toc2.toc-right{padding-left:0;padding-right:15em}
  173. body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
  174. @media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
  175. #toc.toc2{width:20em}
  176. #toc.toc2 #toctitle{font-size:1.375em}
  177. #toc.toc2>ul{font-size:.95em}
  178. #toc.toc2 ul ul{padding-left:1.25em}
  179. body.toc2.toc-right{padding-left:0;padding-right:20em}}
  180. #content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
  181. #content #toc>:first-child{margin-top:0}
  182. #content #toc>:last-child{margin-bottom:0}
  183. #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
  184. #footer-text{color:rgba(255,255,255,.8);line-height:1.44}
  185. .sect1{padding-bottom:.625em}
  186. @media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
  187. .sect1+.sect1{border-top:1px solid #efefed}
  188. #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
  189. #content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
  190. #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
  191. #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
  192. #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
  193. .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
  194. .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
  195. table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
  196. .paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
  197. table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
  198. .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
  199. .admonitionblock>table td.icon{text-align:center;width:80px}
  200. .admonitionblock>table td.icon img{max-width:none}
  201. .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
  202. .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
  203. .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
  204. .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
  205. .exampleblock>.content>:first-child{margin-top:0}
  206. .exampleblock>.content>:last-child{margin-bottom:0}
  207. .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
  208. .sidebarblock>:first-child{margin-top:0}
  209. .sidebarblock>:last-child{margin-bottom:0}
  210. .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
  211. .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
  212. .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
  213. .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
  214. .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
  215. .literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
  216. @media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
  217. @media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
  218. .literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
  219. .listingblock pre.highlightjs{padding:0}
  220. .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
  221. .listingblock pre.prettyprint{border-width:0}
  222. .listingblock>.content{position:relative}
  223. .listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
  224. .listingblock:hover code[data-lang]:before{display:block}
  225. .listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
  226. .listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
  227. table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
  228. table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
  229. table.pyhltable td.code{padding-left:.75em;padding-right:0}
  230. pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
  231. pre.pygments .lineno{display:inline-block;margin-right:.25em}
  232. table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
  233. .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
  234. .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
  235. .quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
  236. .quoteblock blockquote{margin:0;padding:0;border:0}
  237. .quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
  238. .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
  239. .quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
  240. .quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
  241. .quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
  242. .quoteblock .quoteblock blockquote:before{display:none}
  243. .verseblock{margin:0 1em 1.25em 1em}
  244. .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
  245. .verseblock pre strong{font-weight:400}
  246. .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
  247. .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
  248. .quoteblock .attribution br,.verseblock .attribution br{display:none}
  249. .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
  250. .quoteblock.abstract{margin:0 0 1.25em 0;display:block}
  251. .quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
  252. .quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
  253. table.tableblock{max-width:100%;border-collapse:separate}
  254. table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
  255. table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
  256. table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
  257. table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
  258. table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
  259. table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
  260. table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
  261. table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
  262. table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
  263. table.frame-all{border-width:1px}
  264. table.frame-sides{border-width:0 1px}
  265. table.frame-topbot{border-width:1px 0}
  266. th.halign-left,td.halign-left{text-align:left}
  267. th.halign-right,td.halign-right{text-align:right}
  268. th.halign-center,td.halign-center{text-align:center}
  269. th.valign-top,td.valign-top{vertical-align:top}
  270. th.valign-bottom,td.valign-bottom{vertical-align:bottom}
  271. th.valign-middle,td.valign-middle{vertical-align:middle}
  272. table thead th,table tfoot th{font-weight:bold}
  273. tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
  274. tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
  275. p.tableblock>code:only-child{background:none;padding:0}
  276. p.tableblock{font-size:1em}
  277. td>div.verse{white-space:pre}
  278. ol{margin-left:1.75em}
  279. ul li ol{margin-left:1.5em}
  280. dl dd{margin-left:1.125em}
  281. dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
  282. ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
  283. ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
  284. ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
  285. ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
  286. ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
  287. ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
  288. ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
  289. ul.inline>li>*{display:block}
  290. .unstyled dl dt{font-weight:400;font-style:normal}
  291. ol.arabic{list-style-type:decimal}
  292. ol.decimal{list-style-type:decimal-leading-zero}
  293. ol.loweralpha{list-style-type:lower-alpha}
  294. ol.upperalpha{list-style-type:upper-alpha}
  295. ol.lowerroman{list-style-type:lower-roman}
  296. ol.upperroman{list-style-type:upper-roman}
  297. ol.lowergreek{list-style-type:lower-greek}
  298. .hdlist>table,.colist>table{border:0;background:none}
  299. .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
  300. td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
  301. td.hdlist1{font-weight:bold;padding-bottom:1.25em}
  302. .literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
  303. .colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
  304. .colist>table tr>td:last-of-type{padding:.25em 0}
  305. .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
  306. .imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
  307. .imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
  308. .imageblock>.title{margin-bottom:0}
  309. .imageblock.thumb,.imageblock.th{border-width:6px}
  310. .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
  311. .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
  312. .image.left{margin-right:.625em}
  313. .image.right{margin-left:.625em}
  314. a.image{text-decoration:none;display:inline-block}
  315. a.image object{pointer-events:none}
  316. sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
  317. sup.footnote a,sup.footnoteref a{text-decoration:none}
  318. sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
  319. #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
  320. #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
  321. #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
  322. #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
  323. #footnotes .footnote:last-of-type{margin-bottom:0}
  324. #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
  325. .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
  326. .gist .file-data>table td.line-data{width:99%}
  327. div.unbreakable{page-break-inside:avoid}
  328. .big{font-size:larger}
  329. .small{font-size:smaller}
  330. .underline{text-decoration:underline}
  331. .overline{text-decoration:overline}
  332. .line-through{text-decoration:line-through}
  333. .aqua{color:#00bfbf}
  334. .aqua-background{background-color:#00fafa}
  335. .black{color:#000}
  336. .black-background{background-color:#000}
  337. .blue{color:#0000bf}
  338. .blue-background{background-color:#0000fa}
  339. .fuchsia{color:#bf00bf}
  340. .fuchsia-background{background-color:#fa00fa}
  341. .gray{color:#606060}
  342. .gray-background{background-color:#7d7d7d}
  343. .green{color:#006000}
  344. .green-background{background-color:#007d00}
  345. .lime{color:#00bf00}
  346. .lime-background{background-color:#00fa00}
  347. .maroon{color:#600000}
  348. .maroon-background{background-color:#7d0000}
  349. .navy{color:#000060}
  350. .navy-background{background-color:#00007d}
  351. .olive{color:#606000}
  352. .olive-background{background-color:#7d7d00}
  353. .purple{color:#600060}
  354. .purple-background{background-color:#7d007d}
  355. .red{color:#bf0000}
  356. .red-background{background-color:#fa0000}
  357. .silver{color:#909090}
  358. .silver-background{background-color:#bcbcbc}
  359. .teal{color:#006060}
  360. .teal-background{background-color:#007d7d}
  361. .white{color:#bfbfbf}
  362. .white-background{background-color:#fafafa}
  363. .yellow{color:#bfbf00}
  364. .yellow-background{background-color:#fafa00}
  365. span.icon>.fa{cursor:default}
  366. .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
  367. .admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
  368. .admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
  369. .admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
  370. .admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
  371. .admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
  372. .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
  373. .conum[data-value] *{color:#fff!important}
  374. .conum[data-value]+b{display:none}
  375. .conum[data-value]:after{content:attr(data-value)}
  376. pre .conum[data-value]{position:relative;top:-.125em}
  377. b.conum *{color:inherit!important}
  378. .conum:not([data-value]):empty{display:none}
  379. dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
  380. h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
  381. p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
  382. p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
  383. p{margin-bottom:1.25rem}
  384. .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
  385. .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
  386. .print-only{display:none!important}
  387. @media print{@page{margin:1.25cm .75cm}
  388. *{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
  389. a{color:inherit!important;text-decoration:underline!important}
  390. a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
  391. a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
  392. abbr[title]:after{content:" (" attr(title) ")"}
  393. pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
  394. thead{display:table-header-group}
  395. svg{max-width:100%}
  396. p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
  397. h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
  398. #toc,.sidebarblock,.exampleblock>.content{background:none!important}
  399. #toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
  400. .sect1{padding-bottom:0!important}
  401. .sect1+.sect1{border:0!important}
  402. #header>h1:first-child{margin-top:1.25rem}
  403. body.book #header{text-align:center}
  404. body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
  405. body.book #header .details{border:0!important;display:block;padding:0!important}
  406. body.book #header .details span:first-child{margin-left:0!important}
  407. body.book #header .details br{display:block}
  408. body.book #header .details br+span:before{content:none!important}
  409. body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
  410. body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
  411. .listingblock code[data-lang]:before{display:block}
  412. #footer{background:none!important;padding:0 .9375em}
  413. #footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
  414. .hide-on-print{display:none!important}
  415. .print-only{display:block!important}
  416. .hide-for-print{display:none!important}
  417. .show-for-print{display:inherit!important}}
  418. </style>
  419. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  420. <style>
  421. /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
  422. /*pre.CodeRay {background-color:#f7f7f8;}*/
  423. .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
  424. .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
  425. .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
  426. table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
  427. table.CodeRay td{vertical-align: top;line-height:1.45}
  428. table.CodeRay td.line-numbers{text-align:right}
  429. table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
  430. table.CodeRay td.code{padding:0 0 0 .5em}
  431. table.CodeRay td.code>pre{padding:0}
  432. .CodeRay .debug{color:#fff !important;background:#000080 !important}
  433. .CodeRay .annotation{color:#007}
  434. .CodeRay .attribute-name{color:#000080}
  435. .CodeRay .attribute-value{color:#700}
  436. .CodeRay .binary{color:#509}
  437. .CodeRay .comment{color:#998;font-style:italic}
  438. .CodeRay .char{color:#04d}
  439. .CodeRay .char .content{color:#04d}
  440. .CodeRay .char .delimiter{color:#039}
  441. .CodeRay .class{color:#458;font-weight:bold}
  442. .CodeRay .complex{color:#a08}
  443. .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
  444. .CodeRay .color{color:#099}
  445. .CodeRay .class-variable{color:#369}
  446. .CodeRay .decorator{color:#b0b}
  447. .CodeRay .definition{color:#099}
  448. .CodeRay .delimiter{color:#000}
  449. .CodeRay .doc{color:#970}
  450. .CodeRay .doctype{color:#34b}
  451. .CodeRay .doc-string{color:#d42}
  452. .CodeRay .escape{color:#666}
  453. .CodeRay .entity{color:#800}
  454. .CodeRay .error{color:#808}
  455. .CodeRay .exception{color:inherit}
  456. .CodeRay .filename{color:#099}
  457. .CodeRay .function{color:#900;font-weight:bold}
  458. .CodeRay .global-variable{color:#008080}
  459. .CodeRay .hex{color:#058}
  460. .CodeRay .integer,.CodeRay .float{color:#099}
  461. .CodeRay .include{color:#555}
  462. .CodeRay .inline{color:#000}
  463. .CodeRay .inline .inline{background:#ccc}
  464. .CodeRay .inline .inline .inline{background:#bbb}
  465. .CodeRay .inline .inline-delimiter{color:#d14}
  466. .CodeRay .inline-delimiter{color:#d14}
  467. .CodeRay .important{color:#555;font-weight:bold}
  468. .CodeRay .interpreted{color:#b2b}
  469. .CodeRay .instance-variable{color:#008080}
  470. .CodeRay .label{color:#970}
  471. .CodeRay .local-variable{color:#963}
  472. .CodeRay .octal{color:#40e}
  473. .CodeRay .predefined{color:#369}
  474. .CodeRay .preprocessor{color:#579}
  475. .CodeRay .pseudo-class{color:#555}
  476. .CodeRay .directive{font-weight:bold}
  477. .CodeRay .type{font-weight:bold}
  478. .CodeRay .predefined-type{color:inherit}
  479. .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
  480. .CodeRay .key{color:#808}
  481. .CodeRay .key .delimiter{color:#606}
  482. .CodeRay .key .char{color:#80f}
  483. .CodeRay .value{color:#088}
  484. .CodeRay .regexp .delimiter{color:#808}
  485. .CodeRay .regexp .content{color:#808}
  486. .CodeRay .regexp .modifier{color:#808}
  487. .CodeRay .regexp .char{color:#d14}
  488. .CodeRay .regexp .function{color:#404;font-weight:bold}
  489. .CodeRay .string{color:#d20}
  490. .CodeRay .string .string .string{background:#ffd0d0}
  491. .CodeRay .string .content{color:#d14}
  492. .CodeRay .string .char{color:#d14}
  493. .CodeRay .string .delimiter{color:#d14}
  494. .CodeRay .shell{color:#d14}
  495. .CodeRay .shell .delimiter{color:#d14}
  496. .CodeRay .symbol{color:#990073}
  497. .CodeRay .symbol .content{color:#a60}
  498. .CodeRay .symbol .delimiter{color:#630}
  499. .CodeRay .tag{color:#008080}
  500. .CodeRay .tag-special{color:#d70}
  501. .CodeRay .variable{color:#036}
  502. .CodeRay .insert{background:#afa}
  503. .CodeRay .delete{background:#faa}
  504. .CodeRay .change{color:#aaf;background:#007}
  505. .CodeRay .head{color:#f8f;background:#505}
  506. .CodeRay .insert .insert{color:#080}
  507. .CodeRay .delete .delete{color:#800}
  508. .CodeRay .change .change{color:#66f}
  509. .CodeRay .head .head{color:#f4f}
  510. </style>
  511. </head>
  512. <body class="article toc2 toc-left">
  513. <div id="header">
  514. <h1>jMonkeyEngine 3 Tutorial (9) - Hello Collision</h1>
  515. <div id="toc" class="toc2">
  516. <div id="toctitle">Table of Contents</div>
  517. <ul class="sectlevel1">
  518. <li><a href="#sample-code">Sample Code</a></li>
  519. <li><a href="#understanding-the-code">Understanding the Code</a></li>
  520. <li><a href="#initializing-the-game">Initializing the Game</a>
  521. <ul class="sectlevel2">
  522. <li><a href="#the-physics-controlled-scene">The Physics-Controlled Scene</a></li>
  523. <li><a href="#the-physics-controlled-player">The Physics-Controlled Player</a></li>
  524. <li><a href="#physicsspace">PhysicsSpace</a></li>
  525. </ul>
  526. </li>
  527. <li><a href="#navigation">Navigation</a>
  528. <ul class="sectlevel2">
  529. <li><a href="#1-inputmanager">1. inputManager</a></li>
  530. <li><a href="#2-onaction">2. onAction()</a></li>
  531. </ul>
  532. </li>
  533. <li><a href="#conclusion">Conclusion</a></li>
  534. </ul>
  535. </div>
  536. </div>
  537. <div id="content">
  538. <div id="preamble">
  539. <div class="sectionbody">
  540. <div class="paragraph">
  541. <p>Previous: <a href="hello_picking.html">Hello Picking</a>,
  542. Next: <a href="hello_terrain.html">Hello Terrain</a></p>
  543. </div>
  544. <div class="paragraph">
  545. <p>This tutorial demonstrates how you load a scene model and give it solid walls and floors for a character to walk around.
  546. You use a <code>RigidBodyControl</code> for the static collidable scene, and a <code>CharacterControl</code> for the mobile first-person character. You also learn how to set up the default first-person camera to work with physics-controlled navigation.
  547. You can use the solution shown here for first-person shooters, mazes, and similar games.</p>
  548. </div>
  549. <div class="imageblock" style="text-align: center">
  550. <div class="content">
  551. <img src="images/beginner-scene.png" alt="beginner-scene.png" height="281">
  552. </div>
  553. </div>
  554. </div>
  555. </div>
  556. <div class="sect1">
  557. <h2 id="sample-code">Sample Code</h2>
  558. <div class="sectionbody">
  559. <div class="paragraph">
  560. <p>If you don&#8217;t have it yet, <a href="http://jmonkeyengine.googlecode.com/svn/trunk/engine/town.zip">download the town.zip</a> sample scene.</p>
  561. </div>
  562. <div class="listingblock">
  563. <div class="content">
  564. <pre class="CodeRay highlight"><code>----jMonkeyProjects$ ls -1 BasicGame
  565. assets/
  566. build.xml
  567. town.zip
  568. src/----
  569. Place town.zip in the root directory of your JME3 project. Here is the code:</code></pre>
  570. </div>
  571. </div>
  572. <div class="listingblock">
  573. <div class="content">
  574. <pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">package</span> <span class="namespace">jme3test.helloworld</span>;
  575. <span class="keyword">import</span> <span class="include">com.jme3.app.SimpleApplication</span>;
  576. <span class="keyword">import</span> <span class="include">com.jme3.asset.plugins.ZipLocator</span>;
  577. <span class="keyword">import</span> <span class="include">com.jme3.bullet.BulletAppState</span>;
  578. <span class="keyword">import</span> <span class="include">com.jme3.bullet.collision.shapes.CapsuleCollisionShape</span>;
  579. <span class="keyword">import</span> <span class="include">com.jme3.bullet.collision.shapes.CollisionShape</span>;
  580. <span class="keyword">import</span> <span class="include">com.jme3.bullet.control.CharacterControl</span>;
  581. <span class="keyword">import</span> <span class="include">com.jme3.bullet.control.RigidBodyControl</span>;
  582. <span class="keyword">import</span> <span class="include">com.jme3.bullet.util.CollisionShapeFactory</span>;
  583. <span class="keyword">import</span> <span class="include">com.jme3.input.KeyInput</span>;
  584. <span class="keyword">import</span> <span class="include">com.jme3.input.controls.ActionListener</span>;
  585. <span class="keyword">import</span> <span class="include">com.jme3.input.controls.KeyTrigger</span>;
  586. <span class="keyword">import</span> <span class="include">com.jme3.light.AmbientLight</span>;
  587. <span class="keyword">import</span> <span class="include">com.jme3.light.DirectionalLight</span>;
  588. <span class="keyword">import</span> <span class="include">com.jme3.math.ColorRGBA</span>;
  589. <span class="keyword">import</span> <span class="include">com.jme3.math.Vector3f</span>;
  590. <span class="keyword">import</span> <span class="include">com.jme3.scene.Node</span>;
  591. <span class="keyword">import</span> <span class="include">com.jme3.scene.Spatial</span>;
  592. <span class="comment">/**
  593. * Example 9 - How to make walls and floors solid.
  594. * This collision code uses Physics and a custom Action Listener.
  595. * @author normen, with edits by Zathras
  596. */</span>
  597. <span class="directive">public</span> <span class="type">class</span> <span class="class">HelloCollision</span> <span class="directive">extends</span> SimpleApplication
  598. <span class="directive">implements</span> <span class="predefined-type">ActionListener</span> {
  599. <span class="directive">private</span> Spatial sceneModel;
  600. <span class="directive">private</span> BulletAppState bulletAppState;
  601. <span class="directive">private</span> RigidBodyControl landscape;
  602. <span class="directive">private</span> CharacterControl player;
  603. <span class="directive">private</span> Vector3f walkDirection = <span class="keyword">new</span> Vector3f();
  604. <span class="directive">private</span> <span class="type">boolean</span> left = <span class="predefined-constant">false</span>, right = <span class="predefined-constant">false</span>, up = <span class="predefined-constant">false</span>, down = <span class="predefined-constant">false</span>;
  605. <span class="comment">//Temporary vectors used on each frame.</span>
  606. <span class="comment">//They here to avoid instanciating new vectors on each frame</span>
  607. <span class="directive">private</span> Vector3f camDir = <span class="keyword">new</span> Vector3f();
  608. <span class="directive">private</span> Vector3f camLeft = <span class="keyword">new</span> Vector3f();
  609. <span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) {
  610. HelloCollision app = <span class="keyword">new</span> HelloCollision();
  611. app.start();
  612. }
  613. <span class="directive">public</span> <span class="type">void</span> simpleInitApp() {
  614. <span class="comment">/** Set up Physics */</span>
  615. bulletAppState = <span class="keyword">new</span> BulletAppState();
  616. stateManager.attach(bulletAppState);
  617. <span class="comment">//bulletAppState.getPhysicsSpace().enableDebug(assetManager);</span>
  618. <span class="comment">// We re-use the flyby camera for rotation, while positioning is handled by physics</span>
  619. viewPort.setBackgroundColor(<span class="keyword">new</span> ColorRGBA(<span class="float">0.7f</span>, <span class="float">0.8f</span>, <span class="float">1f</span>, <span class="float">1f</span>));
  620. flyCam.setMoveSpeed(<span class="integer">100</span>);
  621. setUpKeys();
  622. setUpLight();
  623. <span class="comment">// We load the scene from the zip file and adjust its size.</span>
  624. assetManager.registerLocator(<span class="string"><span class="delimiter">&quot;</span><span class="content">town.zip</span><span class="delimiter">&quot;</span></span>, ZipLocator.class);
  625. sceneModel = assetManager.loadModel(<span class="string"><span class="delimiter">&quot;</span><span class="content">main.scene</span><span class="delimiter">&quot;</span></span>);
  626. sceneModel.setLocalScale(<span class="float">2f</span>);
  627. <span class="comment">// We set up collision detection for the scene by creating a</span>
  628. <span class="comment">// compound collision shape and a static RigidBodyControl with mass zero.</span>
  629. CollisionShape sceneShape =
  630. CollisionShapeFactory.createMeshShape((Node) sceneModel);
  631. landscape = <span class="keyword">new</span> RigidBodyControl(sceneShape, <span class="integer">0</span>);
  632. sceneModel.addControl(landscape);
  633. <span class="comment">// We set up collision detection for the player by creating</span>
  634. <span class="comment">// a capsule collision shape and a CharacterControl.</span>
  635. <span class="comment">// The CharacterControl offers extra settings for</span>
  636. <span class="comment">// size, stepheight, jumping, falling, and gravity.</span>
  637. <span class="comment">// We also put the player in its starting position.</span>
  638. CapsuleCollisionShape capsuleShape = <span class="keyword">new</span> CapsuleCollisionShape(<span class="float">1.5f</span>, <span class="float">6f</span>, <span class="integer">1</span>);
  639. player = <span class="keyword">new</span> CharacterControl(capsuleShape, <span class="float">0.05f</span>);
  640. player.setJumpSpeed(<span class="integer">20</span>);
  641. player.setFallSpeed(<span class="integer">30</span>);
  642. player.setGravity(<span class="integer">30</span>);
  643. player.setPhysicsLocation(<span class="keyword">new</span> Vector3f(<span class="integer">0</span>, <span class="integer">10</span>, <span class="integer">0</span>));
  644. <span class="comment">// We attach the scene and the player to the rootnode and the physics space,</span>
  645. <span class="comment">// to make them appear in the game world.</span>
  646. rootNode.attachChild(sceneModel);
  647. bulletAppState.getPhysicsSpace().add(landscape);
  648. bulletAppState.getPhysicsSpace().add(player);
  649. }
  650. <span class="directive">private</span> <span class="type">void</span> setUpLight() {
  651. <span class="comment">// We add light so we see the scene</span>
  652. AmbientLight al = <span class="keyword">new</span> AmbientLight();
  653. al.setColor(ColorRGBA.White.mult(<span class="float">1.3f</span>));
  654. rootNode.addLight(al);
  655. DirectionalLight dl = <span class="keyword">new</span> DirectionalLight();
  656. dl.setColor(ColorRGBA.White);
  657. dl.setDirection(<span class="keyword">new</span> Vector3f(<span class="float">2.8f</span>, -<span class="float">2.8f</span>, -<span class="float">2.8f</span>).normalizeLocal());
  658. rootNode.addLight(dl);
  659. }
  660. <span class="comment">/** We over-write some navigational key mappings here, so we can
  661. * add physics-controlled walking and jumping: */</span>
  662. <span class="directive">private</span> <span class="type">void</span> setUpKeys() {
  663. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Left</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_A));
  664. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Right</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_D));
  665. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Up</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_W));
  666. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Down</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_S));
  667. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Jump</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_SPACE));
  668. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Left</span><span class="delimiter">&quot;</span></span>);
  669. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Right</span><span class="delimiter">&quot;</span></span>);
  670. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Up</span><span class="delimiter">&quot;</span></span>);
  671. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Down</span><span class="delimiter">&quot;</span></span>);
  672. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Jump</span><span class="delimiter">&quot;</span></span>);
  673. }
  674. <span class="comment">/** These are our custom actions triggered by key presses.
  675. * We do not walk yet, we just keep track of the direction the user pressed. */</span>
  676. <span class="directive">public</span> <span class="type">void</span> onAction(<span class="predefined-type">String</span> binding, <span class="type">boolean</span> isPressed, <span class="type">float</span> tpf) {
  677. <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Left</span><span class="delimiter">&quot;</span></span>)) {
  678. left = isPressed;
  679. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Right</span><span class="delimiter">&quot;</span></span>)) {
  680. right= isPressed;
  681. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Up</span><span class="delimiter">&quot;</span></span>)) {
  682. up = isPressed;
  683. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Down</span><span class="delimiter">&quot;</span></span>)) {
  684. down = isPressed;
  685. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Jump</span><span class="delimiter">&quot;</span></span>)) {
  686. <span class="keyword">if</span> (isPressed) { player.jump(); }
  687. }
  688. }
  689. <span class="comment">/**
  690. * This is the main event loop--walking happens here.
  691. * We check in which direction the player is walking by interpreting
  692. * the camera direction forward (camDir) and to the side (camLeft).
  693. * The setWalkDirection() command is what lets a physics-controlled player walk.
  694. * We also make sure here that the camera moves with player.
  695. */</span>
  696. <span class="annotation">@Override</span>
  697. <span class="directive">public</span> <span class="type">void</span> simpleUpdate(<span class="type">float</span> tpf) {
  698. camDir.set(cam.getDirection()).multLocal(<span class="float">0.6f</span>);
  699. camLeft.set(cam.getLeft()).multLocal(<span class="float">0.4f</span>);
  700. walkDirection.set(<span class="integer">0</span>, <span class="integer">0</span>, <span class="integer">0</span>);
  701. <span class="keyword">if</span> (left) {
  702. walkDirection.addLocal(camLeft);
  703. }
  704. <span class="keyword">if</span> (right) {
  705. walkDirection.addLocal(camLeft.negate());
  706. }
  707. <span class="keyword">if</span> (up) {
  708. walkDirection.addLocal(camDir);
  709. }
  710. <span class="keyword">if</span> (down) {
  711. walkDirection.addLocal(camDir.negate());
  712. }
  713. player.setWalkDirection(walkDirection);
  714. cam.setLocation(player.getPhysicsLocation());
  715. }
  716. }</code></pre>
  717. </div>
  718. </div>
  719. <div class="paragraph">
  720. <p>Run the sample. You should see a town square with houses and a monument. Use the WASD keys and the mouse to navigate around with a first-person perspective. Run forward and jump by pressing W and Space. Note how you step over the sidewalk, and up the steps to the monument. You can walk in the alleys between the houses, but the walls are solid. Don&#8217;t walk over the edge of the world! emoji:smiley</p>
  721. </div>
  722. </div>
  723. </div>
  724. <div class="sect1">
  725. <h2 id="understanding-the-code">Understanding the Code</h2>
  726. <div class="sectionbody">
  727. <div class="paragraph">
  728. <p>Let&#8217;s start with the class declaration:</p>
  729. </div>
  730. <div class="listingblock">
  731. <div class="content">
  732. <pre class="CodeRay highlight"><code data-lang="java">----<span class="directive">public</span> <span class="type">class</span> <span class="class">HelloCollision</span> <span class="directive">extends</span> SimpleApplication
  733. <span class="directive">implements</span> <span class="predefined-type">ActionListener</span> { ... }----
  734. You already know that SimpleApplication is the base <span class="type">class</span> <span class="class">for</span> all jME3 games. You make <span class="local-variable">this</span> <span class="type">class</span> <span class="class">implement</span> the <span class="error">`</span><span class="predefined-type">ActionListener</span><span class="error">`</span> <span class="type">interface</span> <span class="class">because</span> you want to customize the navigational inputs later.</code></pre>
  735. </div>
  736. </div>
  737. <div class="listingblock">
  738. <div class="content">
  739. <pre class="CodeRay highlight"><code data-lang="java"> <span class="directive">private</span> Spatial sceneModel;
  740. <span class="directive">private</span> BulletAppState bulletAppState;
  741. <span class="directive">private</span> RigidBodyControl landscape;
  742. <span class="directive">private</span> CharacterControl player;
  743. <span class="directive">private</span> Vector3f walkDirection = <span class="keyword">new</span> Vector3f();
  744. <span class="directive">private</span> <span class="type">boolean</span> left = <span class="predefined-constant">false</span>, right = <span class="predefined-constant">false</span>, up = <span class="predefined-constant">false</span>, down = <span class="predefined-constant">false</span>;
  745. <span class="comment">//Temporary vectors used on each frame.</span>
  746. <span class="comment">//They here to avoid instanciating new vectors on each frame</span>
  747. <span class="directive">private</span> Vector3f camDir = <span class="keyword">new</span> Vector3f();
  748. <span class="directive">private</span> Vector3f camLeft = <span class="keyword">new</span> Vector3f();</code></pre>
  749. </div>
  750. </div>
  751. <div class="paragraph">
  752. <p>You initialize a few private fields:</p>
  753. </div>
  754. <div class="ulist">
  755. <ul>
  756. <li>
  757. <p>The BulletAppState gives this SimpleApplication access to physics features (such as collision detection) supplied by jME3&#8217;s jBullet integration</p>
  758. </li>
  759. <li>
  760. <p>The Spatial sceneModel is for loading an OgreXML model of a town.</p>
  761. </li>
  762. <li>
  763. <p>You need a RigidBodyControl to make the town model solid.</p>
  764. </li>
  765. <li>
  766. <p>The (invisible) first-person player is represented by a CharacterControl object.</p>
  767. </li>
  768. <li>
  769. <p>The fields <code>walkDirection</code> and the four Booleans are used for physics-controlled navigation.</p>
  770. </li>
  771. <li>
  772. <p>camDir and camLeft are temporary vectors used later when computing the walkingDirection from the cam position and rotation</p>
  773. </li>
  774. </ul>
  775. </div>
  776. <div class="paragraph">
  777. <p>Let&#8217;s have a look at all the details:</p>
  778. </div>
  779. </div>
  780. </div>
  781. <div class="sect1">
  782. <h2 id="initializing-the-game">Initializing the Game</h2>
  783. <div class="sectionbody">
  784. <div class="paragraph">
  785. <p>As usual, you initialize the game in the <code>simpleInitApp()</code> method.</p>
  786. </div>
  787. <div class="listingblock">
  788. <div class="content">
  789. <pre class="CodeRay highlight"><code data-lang="java"> viewPort.setBackgroundColor(<span class="keyword">new</span> ColorRGBA(<span class="float">0.7f</span>,<span class="float">0.8f</span>,<span class="float">1f</span>,<span class="float">1f</span>));
  790. flyCam.setMoveSpeed(<span class="integer">100</span>);
  791. setUpKeys();
  792. setUpLight();</code></pre>
  793. </div>
  794. </div>
  795. <div class="olist arabic">
  796. <ol class="arabic">
  797. <li>
  798. <p>You set the background color to light blue, since this is a scene with a sky.</p>
  799. </li>
  800. <li>
  801. <p>You repurpose the default camera control “flyCam as first-person camera and set its speed.</p>
  802. </li>
  803. <li>
  804. <p>The auxiliary method <code>setUpLights()</code> adds your light sources.</p>
  805. </li>
  806. <li>
  807. <p>The auxiliary method <code>setUpKeys()</code> configures input mappings–we will look at it later.</p>
  808. </li>
  809. </ol>
  810. </div>
  811. <div class="sect2">
  812. <h3 id="the-physics-controlled-scene">The Physics-Controlled Scene</h3>
  813. <div class="paragraph">
  814. <p>The first thing you do in every physics game is create a BulletAppState object. It gives you access to jME3&#8217;s jBullet integration which handles physical forces and collisions.</p>
  815. </div>
  816. <div class="listingblock">
  817. <div class="content">
  818. <pre class="CodeRay highlight"><code data-lang="java"> bulletAppState = <span class="keyword">new</span> BulletAppState();
  819. stateManager.attach(bulletAppState);</code></pre>
  820. </div>
  821. </div>
  822. <div class="paragraph">
  823. <p>For the scene, you load the <code>sceneModel</code> from a zip file, and adjust the size.</p>
  824. </div>
  825. <div class="listingblock">
  826. <div class="content">
  827. <pre class="CodeRay highlight"><code data-lang="java"> assetManager.registerLocator(<span class="string"><span class="delimiter">&quot;</span><span class="content">town.zip</span><span class="delimiter">&quot;</span></span>, ZipLocator.class);
  828. sceneModel = assetManager.loadModel(<span class="string"><span class="delimiter">&quot;</span><span class="content">main.scene</span><span class="delimiter">&quot;</span></span>);
  829. sceneModel.setLocalScale(<span class="float">2f</span>);</code></pre>
  830. </div>
  831. </div>
  832. <div class="paragraph">
  833. <p>The file <code>town.zip</code> is included as a sample model in the JME3 sources – you can <a href="http://jmonkeyengine.googlecode.com/svn/trunk/engine/town.zip">download it here</a>. (Optionally, use any OgreXML scene of your own.) For this sample, place the zip file in the application&#8217;s top level directory (that is, next to src/, assets/, build.xml).</p>
  834. </div>
  835. <div class="listingblock">
  836. <div class="content">
  837. <pre class="CodeRay highlight"><code data-lang="java"> CollisionShape sceneShape =
  838. CollisionShapeFactory.createMeshShape((Node) sceneModel);
  839. landscape = <span class="keyword">new</span> RigidBodyControl(sceneShape, <span class="integer">0</span>);
  840. sceneModel.addControl(landscape);
  841. rootNode.attachChild(sceneModel);</code></pre>
  842. </div>
  843. </div>
  844. <div class="paragraph">
  845. <p>To use collision detection, you add a RigidBodyControl to the <code>sceneModel</code> Spatial. The RigidBodyControl for a complex model takes two arguments: A Collision Shape, and the object&#8217;s mass.</p>
  846. </div>
  847. <div class="ulist">
  848. <ul>
  849. <li>
  850. <p>JME3 offers a <code>CollisionShapeFactory</code> that precalculates a mesh-accurate collision shape for a Spatial. You choose to generate a <code>CompoundCollisionShape</code> (which has MeshCollisionShapes as its children) because this type of collision shape is optimal for immobile objects, such as terrain, houses, and whole shooter levels.</p>
  851. </li>
  852. <li>
  853. <p>You set the mass to zero since a scene is static and its mass is irrevelant.</p>
  854. </li>
  855. <li>
  856. <p>Add the control to the Spatial to give it physical properties.</p>
  857. </li>
  858. <li>
  859. <p>As always, attach the sceneModel to the rootNode to make it visible.</p>
  860. </li>
  861. </ul>
  862. </div>
  863. <div class="paragraph">
  864. <p><strong>Tip:</strong> Remember to add a light source so you can see the scene.</p>
  865. </div>
  866. </div>
  867. <div class="sect2">
  868. <h3 id="the-physics-controlled-player">The Physics-Controlled Player</h3>
  869. <div class="paragraph">
  870. <p>A first-person player is typically invisible. When you use the default flyCam as first-person cam, it does not even test for collisons and runs through walls. This is because the flyCam control does not have any physical shape assigned. In this code sample, you represent the first-person player as an (invisible) physical shape. You use the WASD keys to steer this physical shape around, while the physics engine manages for you how it walks along solid walls and on solid floors and jumps over solid obstacles. Then you simply make the camera follow the walking shape&#8217;s location – and you get the illusion of being a physical body in a solid environment seeing through the camera.</p>
  871. </div>
  872. <div class="paragraph">
  873. <p>So let&#8217;s set up collision detection for the first-person player.</p>
  874. </div>
  875. <div class="listingblock">
  876. <div class="content">
  877. <pre class="CodeRay highlight"><code data-lang="java"> CapsuleCollisionShape capsuleShape = <span class="keyword">new</span> CapsuleCollisionShape(<span class="float">1.5f</span>, <span class="float">6f</span>, <span class="integer">1</span>);</code></pre>
  878. </div>
  879. </div>
  880. <div class="paragraph">
  881. <p>Again, you create a CollisionShape: This time you choose a CapsuleCollisionShape, a cylinder with a rounded top and bottom. This shape is optimal for a person: It&#8217;s tall and the roundness helps to get stuck less often on obstacles.</p>
  882. </div>
  883. <div class="ulist">
  884. <ul>
  885. <li>
  886. <p>Supply the CapsuleCollisionShape constructor with the desired radius and height of the bounding capsule to fit the shape of your character. In this example the character is 2*1.5f units wide, and 6f units tall.</p>
  887. </li>
  888. <li>
  889. <p>The final integer argument specifies the orientation of the cylinder: 1 is the Y-axis, which fits an upright person. For animals which are longer than high you would use 0 or 2 (depending on how it is rotated).</p>
  890. </li>
  891. </ul>
  892. </div>
  893. <div class="listingblock">
  894. <div class="content">
  895. <pre class="CodeRay highlight"><code data-lang="java"> player = <span class="keyword">new</span> CharacterControl(capsuleShape, <span class="float">0.05f</span>);</code></pre>
  896. </div>
  897. </div>
  898. <div class="paragraph">
  899. <p>“</p>
  900. </div>
  901. <div class="listingblock">
  902. <div class="content">
  903. <pre class="CodeRay highlight"><code data-lang="java">----bulletAppState.getPhysicsSpace().enableDebug(assetManager);----</code></pre>
  904. </div>
  905. </div>
  906. <div class="paragraph">
  907. <p>Now you use the CollisionShape to create a <code>CharacterControl</code> that represents the first-person player. The last argument of the CharacterControl constructor (here <code>.05f</code>) is the size of a step that the character should be able to surmount.</p>
  908. </div>
  909. <div class="listingblock">
  910. <div class="content">
  911. <pre class="CodeRay highlight"><code data-lang="java"> player.setJumpSpeed(<span class="integer">20</span>);
  912. player.setFallSpeed(<span class="integer">30</span>);
  913. player.setGravity(<span class="integer">30</span>);</code></pre>
  914. </div>
  915. </div>
  916. <div class="paragraph">
  917. <p>Apart from step height and character size, the <code>CharacterControl</code> lets you configure jumping, falling, and gravity speeds. Adjust the values to fit your game situation.</p>
  918. </div>
  919. <div class="listingblock">
  920. <div class="content">
  921. <pre class="CodeRay highlight"><code data-lang="java"> player.setPhysicsLocation(<span class="keyword">new</span> Vector3f(<span class="integer">0</span>, <span class="integer">10</span>, <span class="integer">0</span>));</code></pre>
  922. </div>
  923. </div>
  924. <div class="paragraph">
  925. <p>Finally we put the player in its starting position and update its state – remember to use <code>setPhysicsLocation()</code> instead of <code>setLocalTranslation()</code> now, since you are dealing with a physical object.</p>
  926. </div>
  927. </div>
  928. <div class="sect2">
  929. <h3 id="physicsspace">PhysicsSpace</h3>
  930. <div class="paragraph">
  931. <p>Remember, in physical games, you must register all solid objects (usually the characters and the scene) to the PhysicsSpace!</p>
  932. </div>
  933. <div class="listingblock">
  934. <div class="content">
  935. <pre class="CodeRay highlight"><code data-lang="java"> bulletAppState.getPhysicsSpace().add(landscape);
  936. bulletAppState.getPhysicsSpace().add(player);</code></pre>
  937. </div>
  938. </div>
  939. <div class="paragraph">
  940. <p>The invisible body of the character just sits there on the physical floor. It cannot walk yet – you will deal with that next.</p>
  941. </div>
  942. </div>
  943. </div>
  944. </div>
  945. <div class="sect1">
  946. <h2 id="navigation">Navigation</h2>
  947. <div class="sectionbody">
  948. <div class="paragraph">
  949. <p>The default camera controller <code>cam</code> is a third-person camera. JME3 also offers a first-person controller, <code>flyCam</code>, which we use here to handle camera rotation. The <code>flyCam</code> control moves the camera using <code>setLocation()</code>.</p>
  950. </div>
  951. <div class="paragraph">
  952. <p>However, you must redefine how walking (camera movement) is handled for physics-controlled objects: When you navigate a non-physical node (e.g. the default flyCam), you simply specify the <em>target location</em>. There are no tests that prevent the flyCam from getting stuck in a wall! When you move a PhysicsControl, you want to specify a <em>walk direction</em> instead. Then the PhysicsSpace can calculate for you how far the character can actually move in the desired direction – or whether an obstacle prevents it from going any further.</p>
  953. </div>
  954. <div class="paragraph">
  955. <p>In short, you must re-define the flyCam&#8217;s navigational key mappings to use <code>setWalkDirection()</code> instead of <code>setLocalTranslation()</code>. Here are the steps:</p>
  956. </div>
  957. <div class="sect2">
  958. <h3 id="1-inputmanager">1. inputManager</h3>
  959. <div class="paragraph">
  960. <p>In the <code>simpleInitApp()</code> method, you re-configure the familiar WASD inputs for walking, and Space for jumping.</p>
  961. </div>
  962. <div class="listingblock">
  963. <div class="content">
  964. <pre class="CodeRay highlight"><code data-lang="java">----<span class="directive">private</span> <span class="type">void</span> setUpKeys() {
  965. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Left</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_A));
  966. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Right</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_D));
  967. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Up</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_W));
  968. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Down</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_S));
  969. inputManager.addMapping(<span class="string"><span class="delimiter">&quot;</span><span class="content">Jump</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> KeyTrigger(KeyInput.KEY_SPACE));
  970. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Left</span><span class="delimiter">&quot;</span></span>);
  971. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Right</span><span class="delimiter">&quot;</span></span>);
  972. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Up</span><span class="delimiter">&quot;</span></span>);
  973. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Down</span><span class="delimiter">&quot;</span></span>);
  974. inputManager.addListener(<span class="local-variable">this</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Jump</span><span class="delimiter">&quot;</span></span>);
  975. }
  976. ----
  977. You can move <span class="local-variable">this</span> block of code into an auxiliary method <span class="error">`</span>setupKeys()<span class="error">`</span> and call <span class="local-variable">this</span> method from <span class="error">`</span>simpleInitApp()<span class="error">`</span><span class="error">–</span> to keep the code more readable.</code></pre>
  978. </div>
  979. </div>
  980. </div>
  981. <div class="sect2">
  982. <h3 id="2-onaction">2. onAction()</h3>
  983. <div class="paragraph">
  984. <p>Remember that this class implements the <code>ActionListener</code> interface, so you can customize the flyCam inputs. The <code>ActionListener</code> interface requires you to implement the <code>onAction()</code> method: You re-define the actions triggered by navigation key presses to work with physics.</p>
  985. </div>
  986. <div class="listingblock">
  987. <div class="content">
  988. <pre class="CodeRay highlight"><code data-lang="java"> <span class="directive">public</span> <span class="type">void</span> onAction(<span class="predefined-type">String</span> binding, <span class="type">boolean</span> value, <span class="type">float</span> tpf) {
  989. <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Left</span><span class="delimiter">&quot;</span></span>)) {
  990. <span class="keyword">if</span> (value) { left = <span class="predefined-constant">true</span>; } <span class="keyword">else</span> { left = <span class="predefined-constant">false</span>; }
  991. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Right</span><span class="delimiter">&quot;</span></span>)) {
  992. <span class="keyword">if</span> (value) { right = <span class="predefined-constant">true</span>; } <span class="keyword">else</span> { right = <span class="predefined-constant">false</span>; }
  993. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Up</span><span class="delimiter">&quot;</span></span>)) {
  994. <span class="keyword">if</span> (value) { up = <span class="predefined-constant">true</span>; } <span class="keyword">else</span> { up = <span class="predefined-constant">false</span>; }
  995. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Down</span><span class="delimiter">&quot;</span></span>)) {
  996. <span class="keyword">if</span> (value) { down = <span class="predefined-constant">true</span>; } <span class="keyword">else</span> { down = <span class="predefined-constant">false</span>; }
  997. } <span class="keyword">else</span> <span class="keyword">if</span> (binding.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Jump</span><span class="delimiter">&quot;</span></span>)) {
  998. player.jump();
  999. }
  1000. }----
  1001. The only movement that you <span class="keyword">do</span> not have to implement yourself is the jumping action. The call <span class="error">`</span>player.jump()<span class="error">`</span> is a special method that handles a correct jumping motion <span class="keyword">for</span> your <span class="error">`</span>PhysicsCharacterNode<span class="error">`</span>.
  1002. For all other directions: Every time the user presses one of the WASD keys, you _keep track_ of the direction the user wants to go, by storing <span class="local-variable">this</span> info in four directional Booleans. No actual walking happens here yet. The update loop is what acts out the directional info stored in the booleans, and makes the player move, as shown in the next code snippet:
  1003. === <span class="integer">3</span>. setWalkDirection()
  1004. Previously in the <span class="error">`</span>onAction()<span class="error">`</span> method, you have collected the info in which direction the user wants to go in terms of <span class="error">“</span>forward or <span class="error">“</span>left. In the update loop, you repeatedly poll the current rotation of the camera. You calculate the actual vectors to which <span class="error">“</span>forward or <span class="error">“</span>left corresponds in the coordinate system.
  1005. This last and most important code snippet goes into the <span class="error">`</span>simpleUpdate()<span class="error">`</span> method.
  1006. [source,java]</code></pre>
  1007. </div>
  1008. </div>
  1009. <div class="literalblock">
  1010. <div class="content">
  1011. <pre> public void simpleUpdate(float tpf) {
  1012. camDir.set(cam.getDirection()).multLocal(0.6f);
  1013. camLeft.set(cam.getLeft()).multLocal(0.4f);
  1014. walkDirection.set(0, 0, 0);
  1015. if (left) {
  1016. walkDirection.addLocal(camLeft);
  1017. }
  1018. if (right) {
  1019. walkDirection.addLocal(camLeft.negate());
  1020. }
  1021. if (up) {
  1022. walkDirection.addLocal(camDir);
  1023. }
  1024. if (down) {
  1025. walkDirection.addLocal(camDir.negate());
  1026. }
  1027. player.setWalkDirection(walkDirection);
  1028. cam.setLocation(player.getPhysicsLocation());
  1029. }----
  1030. This is how the walking is triggered:</pre>
  1031. </div>
  1032. </div>
  1033. <div class="olist arabic">
  1034. <ol class="arabic">
  1035. <li>
  1036. <p>Initialize the vector <code>walkDirection</code> to zero. This is where you want to store the calculated walk direction.</p>
  1037. <div class="olist loweralpha">
  1038. <ol class="loweralpha" type="a">
  1039. <li>
  1040. <p>Add to <code>walkDirection</code> the recent motion vectors that you polled from the camera. This way it is posible for a character to move forward and to the left simultaneously, for example!</p>
  1041. </li>
  1042. <li>
  1043. <p>This one last line does the “walking magic:</p>
  1044. <div class="listingblock">
  1045. <div class="content">
  1046. <pre class="CodeRay highlight"><code data-lang="java">----player.setWalkDirection(walkDirection);----
  1047. Always use <span class="error">`</span>setWalkDirection()<span class="error">`</span> to make a physics-controlled object move continuously, and the physics engine handles collision detection <span class="keyword">for</span> you.</code></pre>
  1048. </div>
  1049. </div>
  1050. </li>
  1051. <li>
  1052. <p>Make the first-person camera object follow along with the physics-controlled player:</p>
  1053. <div class="listingblock">
  1054. <div class="content">
  1055. <pre class="CodeRay highlight"><code data-lang="java">----cam.setLocation(player.getPhysicsLocation());----</code></pre>
  1056. </div>
  1057. </div>
  1058. </li>
  1059. </ol>
  1060. </div>
  1061. </li>
  1062. </ol>
  1063. </div>
  1064. <div class="paragraph">
  1065. <p><strong>Important:</strong> Again, do not use <code>setLocalTranslation()</code> to walk the player around. You will get it stuck by overlapping with another physical object. You can put the player in a start position with <code>setPhysicalLocation()</code> if you make sure to place it a bit above the floor and away from obstacles.</p>
  1066. </div>
  1067. </div>
  1068. </div>
  1069. </div>
  1070. <div class="sect1">
  1071. <h2 id="conclusion">Conclusion</h2>
  1072. <div class="sectionbody">
  1073. <div class="paragraph">
  1074. <p>You have learned how to load a “solid physical scene model and walk around in it with a first-person perspective.
  1075. You learned to speed up the physics calculations by using the CollisionShapeFactory to create efficient CollisionShapes for complex Geometries. You know how to add PhysicsControls to your collidable geometries and you register them to the PhysicsSpace. You also learned to use <code>player.setWalkDirection(walkDirection)</code> to move collision-aware characters around, and not <code>setLocalTranslation()</code>.</p>
  1076. </div>
  1077. <div class="paragraph">
  1078. <p>Terrains are another type of scene in which you will want to walk around. Let&#8217;s proceed with learning <a href="hello_terrain.html">how to generate terrains</a> now.</p>
  1079. </div>
  1080. <hr>
  1081. <div class="paragraph">
  1082. <p>Related info:</p>
  1083. </div>
  1084. <div class="ulist">
  1085. <ul>
  1086. <li>
  1087. <p>How to load models and scenes: <a href="hello_asset.html">Hello Asset</a>, <a href="sdk/scene_explorer.html">Scene Explorer</a>, <a href="sdk/scene_composer.html">Scene Composer</a></p>
  1088. </li>
  1089. <li>
  1090. <p><a href="jme3/advanced/terrain_collision.html">Terrain Collision</a></p>
  1091. </li>
  1092. <li>
  1093. <p>To learn more about complex physics scenes, where several mobile physical objects bump into each other, read <a href="jme3/beginner/hello_physics.html">Hello Physics</a>.</p>
  1094. </li>
  1095. <li>
  1096. <p>FYI, there are simpler collision detection solutions without physics, too. Have a look at <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/collision/TestTriangleCollision.java">jme3test.collision.TestTriangleCollision.java</a>.
  1097. &lt;tags&gt;&lt;tag target="beginner" /&gt;&lt;tag target="collision" /&gt;&lt;tag target="control" /&gt;&lt;tag target="intro" /&gt;&lt;tag target="documentation" /&gt;&lt;tag target="model" /&gt;&lt;tag target="physics" /&gt;&lt;/tags&gt;</p>
  1098. </li>
  1099. </ul>
  1100. </div>
  1101. </div>
  1102. </div>
  1103. </div>
  1104. <div id="footer">
  1105. <div id="footer-text">
  1106. Last updated 2016-05-21 23:44:18 UTC
  1107. </div>
  1108. </div>
  1109. </body>
  1110. </html>