| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><title>JME3 Cinematics</title><link rel="stylesheet" href="./asciidoctor.css">
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
- <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"><link rel="stylesheet" href="/home/travis/build/jMonkeyEngine/wiki/build/asciidoc/html5/jme3/advanced/twemoji-awesome.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/jme3/advanced/cinematics.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/jme3/advanced/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"></div><h1>JME3 Cinematics</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#sample-code">Sample Code</a></li><li><a href="#how-to-use-a-cinematic">How to Use a Cinematic</a></li><li><a href="#events-cinematicevents">Events(CinematicEvents)</a><ul class="sectlevel2"><li><a href="#motionevent">MotionEvent</a></li><li><a href="#soundevent">SoundEvent</a></li><li><a href="#guievent">GuiEvent</a></li><li><a href="#animationevent">AnimationEvent</a></li><li><a href="#camera-management">Camera Management</a></li><li><a href="#customizations">Customizations</a></li></ul></li><li><a href="#interacting-with-cinematics">Interacting with Cinematics</a><ul class="sectlevel2"><li><a href="#cinematiceventlistener">CinematicEventListener</a></li><li><a href="#physics-interaction">Physics Interaction</a></li></ul></li></ul></div></div><div id="content"><div id="preamble"><div class="sectionbody"><div class="paragraph"><p>JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. You can use cinematics to create <a href="http://en.wikipedia.org/wiki/Cutscene">cutscenes</a> and movies/trailers for your game. Another good use case is efficient “destruction physics: Playing back prerecorded flying pieces of debris for demolitions is much faster than calculating them with live physics.</p></div>
- <div class="paragraph"><p>Internally, Cinematics are implemented as <a href="../../jme3/advanced/application_states.html">AppStates</a>.</p></div>
- <div class="paragraph"><p>Short overview of the cinematic process:</p></div>
- <div class="olist arabic"><ol class="arabic"><li><p>Plan the script of your movie.<br>
- Write down a timeline (e.g. on paper) of which character should be at which spot at which time.</p></li><li><p>Attach the scene objects that you want to remote-control to one Node.<br>
- This Node can be the rootNode, or a Node that is attached to the rootNode.</p></li><li><p>Create a Cinematic object for this movie scene. The Cinematic will contain and manage the movie script.</p></li><li><p>For each line in your script (for each keyframe in your timeline), add a CinematicEvent to the Cinematic.</p></li></ol></div></div></div>
- <div class="sect1"><h2 id="sample-code">Sample Code</h2><div class="sectionbody"><div class="ulist"><ul><li><p><a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/animation/TestCinematic.java">TestCinematic.java</a></p></li></ul></div></div></div>
- <div class="sect1"><h2 id="how-to-use-a-cinematic">How to Use a Cinematic</h2><div class="sectionbody"><div class="paragraph"><p>A Cinematic is like a movie script for a node.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">Cinematic cinematic = <span class="keyword">new</span> Cinematic(sceneNode, duration);
- cinematic.addCinematicEvent(starttime1, event1);
- cinematic.addCinematicEvent(starttime2, event2);
- cinematic.addCinematicEvent(starttime2, event3);
- ...
- stateManager.attach(cinematic);</code></pre></div></div>
- <div class="olist arabic"><ol class="arabic"><li><p>Create one Cinematic per scripted scene.</p><div class="ulist"><ul><li><p><code>sceneNode</code> is the node containing the scene (can be the rootNode).</p></li><li><p><code>duration</code> is the duration of the whole scene in seconds.</p></li><li><p>Each Cinematic is a set of CinematicEvents, that are triggered at a given moment on the timeline.</p></li></ul></div></li><li><p>Create one CinematicEvent for each line of your movie script.</p><div class="ulist"><ul><li><p><code>event</code> is one motion of a moving object. You can add several events. More details below.</p></li><li><p><code>starttime</code> is the time when this particular cinematic event starts on the timeline. Specify the start time in seconds since the beginning of the cinematic.</p></li></ul></div></li><li><p>Attach the Cinematic to the SimpleApplication’s stateManager.</p></li><li><p>Play, stop and pause the Cinematic from your code.</p></li></ol></div>
- <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Method</th><th class="tableblock halign-left valign-top">Usage</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>cinematic.play()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Starts playing the cinematic from the start, or from where it was paused.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>cinematic.stop()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Stops playing the cinematic and rewinds it.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>cinematic.pause()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Pauses the cinematic.</p></div></div></td></tr></tbody></table></div></div>
- <div class="sect2"><h3 id="events-cinematicevents">Events(CinematicEvents)</h3><div class="paragraph"><p>Just like a movie script consists of lines with instructions to the actors, each Cinematic consists of a series of events.</p></div>
- <div class="paragraph"><p>Here is the list of available CinematicEvents that you use as events. Each track remote-controls scene objects in a different way:</p></div>
- <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 20%;"><col style="width: 80%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Events(CinematicEvents)</th><th class="tableblock halign-left valign-top">Description</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>MotionEvent</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Use a MotionEvent to move a Spatial non-linearly over time. A MotionEvent is based on a list of waypoints in a MotionPath. The curve goes through each waypoint, and you can adjust the tension of the curve to modify the roundedness of the path. This is the motion interpolation you are going to use in most cases.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>SoundEvent</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Use a SoundEvent to play a <a href="../../jme3/advanced/audio.html">sound</a> at a given time for the given duration.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>GuiEvent</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Displays a <a href="../../jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <abbr title="Graphical User Interface">GUI</abbr> XML to the cinematic using <code>cinematic.bindUi(“path/to/nifty/file.xml);</code></p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>AnimationEvent</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Use this to start playing a model <a href="../../jme3/advanced/animation.html">animation</a> at a given time (a character walking animation for example)</p></div></div></td></tr></tbody></table>
- <div class="paragraph"><p>You can add custom events by extending AbstractCinematicEvent.</p></div>
- <div class="sect2"><h3 id="motionevent">MotionEvent</h3><div class="paragraph"><p>A MotionEvent moves a Spatial along a complex path.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">MotionEvent events= <span class="keyword">new</span> MotionEvent (thingNode, path);</code></pre></div></div>
- <div class="paragraph"><p>Details of the constructor:</p></div>
- <div class="ulist"><ul><li><p><code>thingNode</code> is the Spatial to be moved.</p></li><li><p><code>path</code> is a complex <a href="../../jme3/advanced/motionpath.html">MotionPath</a>.</p></li></ul></div>
- <div class="paragraph"><p>To create a MotionEvent, do the following:</p></div>
- <div class="olist arabic"><ol class="arabic"><li><p>Create a MotinPath.</p></li><li><p>Create a MotionEvent based on the MotionPath.</p></li><li><p>Configure your MotionEvent (see below).</p></li><li><p>Add the MotionEvent to a Cinematic.</p></li></ol></div>
- <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">MotionEvent configuration method</th><th class="tableblock halign-left valign-top">Usage</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setLoopMode(LoopMode.Loop)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets whether the animation along this path should loop (LoopMode.Loop) or play only once (LoopMode.DontLoop).</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setDirectionType(MotionEvent.Direction.None)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the direction behavior type of the controlled node. Direction.None deactivates this feature. You can choose from the following options: LookAt, Path, PathAndRotation, Rotation.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setDirectionType(MotionEvent.Direction.LookAt)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The spatial turns (rotates) to keep facing a certain point while moving. Specify the point with the <code>setLookAt()</code> method.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setDirectionType(MotionEvent.Direction.Path)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The spatial always faces in the direction of the path while moving.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setDirectionType(MotionEvent.Direction.PathAndRotation)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The spatial faces the direction of the path, plus an added rotation. Use together with the <code>setRotation()</code> method.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setDirectionType(MotionEvent.Direction.Rotation)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The spatial spins (rotates) while moving. You describe the spin by a custom quaternion. Use together with the <code>setRotation()</code> method.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The spatial always faces towards this location. Use together with <code>MotionEvent.Direction.LookAt</code>.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>event.setRotation(quaternion)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the rotation. Use together with <code>MotionEvent.Direction.Rotation</code> or <code>MotionEvent.Direction.PathAndRotation</code>.</p></div></div></td></tr></tbody></table>
- <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>Most likely you remote-control more than one object in your scene. Give the events and paths useful names such as <code>dragonEvent</code>, <code>dragonPath</code>, <code>heroEvent</code>, <code>heroPath</code>, etc.</p></div></td></tr></table></div></div>
- <div class="sect2"><h3 id="soundevent">SoundEvent</h3><div class="paragraph"><p>A SoundEventplays a sound as part of the cinematic.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">SoundEvent( audioPath, isStream, duration, loopMode )</code></pre></div></div>
- <div class="paragraph"><p>Details of the constructor:</p></div>
- <div class="ulist"><ul><li><p><code>audioPath</code> is the path to an audio file as String, e.g. “Sounds/mySound.wav.</p></li><li><p><code>isStream</code> toggles between streaming and buffering. Set to true to stream long audio file, set to false to play short buffered sounds.</p></li><li><p><code>duration</code> is the time that it should take to play.</p></li><li><p><code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</p></li></ul></div></div>
- <div class="sect2"><h3 id="guievent">GuiEvent</h3><div class="paragraph"><p>A GuiEventshows or hide a NiftyGUI as part of a cinematic.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">GuiEvent( screen, duration, loopMode )</code></pre></div></div>
- <div class="paragraph"><p>You must use this together with bindUI() to specify the Nifty <abbr title="Graphical User Interface">GUI</abbr> XML file that you want to load:</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">cinematic.bindUi(<span class="string"><span class="delimiter">"</span><span class="content">Interface/subtitle.xml</span><span class="delimiter">"</span></span>);</code></pre></div></div>
- <div class="paragraph"><p>Details of the constructor:</p></div>
- <div class="ulist"><ul><li><p><code>screen</code> is the name of the Nifty <abbr title="Graphical User Interface">GUI</abbr> screen to load, as String.</p></li><li><p><code>duration</code> is the time that it should take to play.</p></li><li><p><code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</p></li></ul></div></div>
- <div class="sect2"><h3 id="animationevent">AnimationEvent</h3><div class="paragraph"><p>An AnimationEvent triggers an animation as part of a cinematic.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">AnimationEvent( thingNode, animationName, duration, loopMode )</code></pre></div></div>
- <div class="paragraph"><p>Details of the constructor:</p></div>
- <div class="ulist"><ul><li><p><code>thingNode</code> is the Spatial whose animation you want to play.</p></li><li><p><code>animationName</code> the name of the animation stored in the animated model that you want to trigger, as a String.</p></li><li><p><code>duration</code> is the time that it should take to play.</p></li><li><p><code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</p></li></ul></div></div>
- <div class="sect2"><h3 id="camera-management">Camera Management</h3><div class="paragraph"><p>There is a built in system for camera switching in Cinematics. It based on CameraNode, and the cinematic just enable the given CameraNode control at a given time.</p></div>
- <div class="paragraph"><p>First you have to bind a camera to the cinematic with a unique name. You’ll be provided with a CameraNode</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> CameraNode camNode = cinematic.bindCamera(<span class="string"><span class="delimiter">"</span><span class="content">topView</span><span class="delimiter">"</span></span>, cam);</code></pre></div></div>
- <div class="paragraph"><p>then you can do whatever you want with this camera node : place it so that you have a the camera angle you’d like, attach it to a motion event to have some camera scrolling, attach control of your own that give it whatever behavior you’d like.
- In the above example, I want it to be a top view of the scene looking at the world origin.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> <span class="comment">//set its position</span>
- camNode.setLocalTranslation(<span class="keyword">new</span> Vector3f(<span class="integer">0</span>, <span class="integer">50</span>, <span class="integer">0</span>));
- <span class="comment">// set it to look at the world origin</span>
- camNode.lookAt(Vector3F.ZERO, Vector3f.UNIT_Y);</code></pre></div></div>
- <div class="paragraph"><p>Then i just have to schedule its activation in the cinematic. I want it to get activated 3 seconds after the start of the cinematic so I just have to do</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> cinematic.activateCamera(<span class="integer">3</span>,<span class="error">”</span>topView<span class="error">”</span>);</code></pre></div></div></div>
- <div class="sect2"><h3 id="customizations">Customizations</h3><div class="paragraph"><p>You can extend individual CinematicEvents. The <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/animation/SubtitleTrack.java">SubtitleTrack.java example</a> shows how to extend a GuiTrack to script subtitles. See how the subtitles are used in the <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/animation/TestCinematic.java">TestCinematic.java example</a>.</p></div>
- <div class="paragraph"><p>You can also create new CinematicEvent by extending <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/cinematic/events/AbstractCinematicEvent.java">AbstractCinematicEvent</a>. An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc… management. Look at the <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-examples/src/main/java/jme3test/animation/TestCinematic.java">TestCinematic.java example</a> is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter.</p></div></div></div>
- <div class="sect2"><h3 id="interacting-with-cinematics">Interacting with Cinematics</h3><div class="sect2"><h3 id="cinematiceventlistener">CinematicEventListener</h3><div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">CinematicEventListener cel = <span class="keyword">new</span> CinematicEventListener() {
- <span class="directive">public</span> <span class="type">void</span> onPlay(CinematicEvent cinematic) {
- chaseCam.setEnabled(<span class="predefined-constant">false</span>);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">play</span><span class="delimiter">"</span></span>);
- }
- <span class="directive">public</span> <span class="type">void</span> onPause(CinematicEvent cinematic) {
- chaseCam.setEnabled(<span class="predefined-constant">true</span>);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">pause</span><span class="delimiter">"</span></span>);
- }
- <span class="directive">public</span> <span class="type">void</span> onStop(CinematicEvent cinematic) {
- chaseCam.setEnabled(<span class="predefined-constant">true</span>);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">stop</span><span class="delimiter">"</span></span>);
- }
- }
- cinematic.addListener(cel);</code></pre></div></div></div>
- <div class="sect2"><h3 id="physics-interaction">Physics Interaction</h3><div class="paragraph"><p>Upcoming.</p></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2019-12-20 23:30:51 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
- apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
- indexName: 'jmonkeyengine',
- inputSelector: '#doc-search',
- debug: false // Set debug to true if you want to inspect the dropdown
- });</script></body></html>
|