|
Interactive
Simulation Newsletter |
| Vol.
3, No. 1 (January, 2005) |
|
| This
Edition's Contents: |
| This newsletter
is brought to you by Jonathan Kaye and David
Castillo, the authors of "Flash
MX for Interactive Simulation," the first practical
guide to building interactive product simulations and performance-based
training in Flash. |
HAPPY
NEW YEAR!
You may or may not be
wondering what we've been up to in the past few months since the
last newsletter. We wrote our book with the intention of starting
a process to teach other Flash developers effective methodologies
for designing and programming equipment simulations. We are pleased
to announce officially the next step in that process: a
five-week, online class for intermediate to advanced ActionScript
developers. You can find out more about the class, and
register for it, at http://www.FlashSim.com/class/BuildEquipSims.html.
Class begins January 10, so hurry up and sign up!
This edition of the newsletter
presents two popular topics from questions we receive:
- How do you prevent
people from using parts of the simulator they're not supposed
to?
- How can I make a mechanism
to visually demonstrate how to perform actions on a simulator?
Enter
your email address here to receive the accompanying
source code and automatic notification on future newsletter
releases.
|
|
(in fact, we receive
#2 so frequently we decided to make a component to do this, which
we give you newsletter subscribers for free).
If you have a suggestion
for future articles, please let us know!
As always, your comments
and feedback are welcome.
Jonathan & David |
| |
| |
| LET
US HELP YOU WITH YOUR PROJECTS |
| If
you have an interactive-simulation problem or project you
would like to discuss with us, please email
us and we'd be happy to help you. Through our company, Equipment
Simulations LLC, we offer customized workshops and project assistance
to get your projects done quickly and correctly! |
|
| |
| DYNAMICALLY
LIMITING SIMULATOR INTERFACE BEHAVIOR |
| While
there is a deep urge from our technical, inner self when building
a simulator to replicate all or most of the functionality of a device,
we must resist this temptation if your time or other resources (like
money!) are, as they usually are, limited in some way. It may give
us technical satisfaction to build a complete system, but if we
consider that the time spent working out details or functionality
that are not important or directly relevant to the simulator's use
could be spent building other devices, or working to improve the
content, then the extra effort is wasted. Unfortunately, in the
technology-oriented simulator world, often a higher price is paid
to an undue level of fidelity or detail than actual usefulness.
In training, however, our eyes must be squarely set on the minimal
level of detail required to meet performance objectives.
This does not mean that
you must build special-purpose engines for each application. Rather,
using a system like statecharts and UCM (conveniently described
in our book), you can build out certain functionality to an appropriate
level, and later return to expand those features as your training
or application necessitates.
For example, we were
recently building a complex physiological monitor simulator. The
real device has sixty or seventy software screens, with the same
data apearing on several screens. When we examined the tasks that
needed to be taught/practiced on the simulator, we found that we
could greatly reduce the amount of work by not building out functionality
not directly related to the rough sequence of tasks the students
were expected to perform. The trick was, however, that we needed
to implement partial functionality on some of the common screens
for certain tasks, but we didn't want to permit the student to follow
those paths when not related to the current task. If we had let
the student follow all paths for any task, we would have had to
build out much more functionality to make sure the data was completely
consistent across all scenarios, not to mention to tax the SME (Subject
Matter Expert) in getting the right look and numeric data in all
situations.
One complex way would
be to do what we described in our book regarding filtering events
(page 433)--replacing the simulator's centralized event handler
with one that examined the incoming event and decided whether or
not to pass it along to the real handler. The drawback is not only
more work in filtering the events, but also that the interface elements
would not be prevented from making their visual change, such as
a toggle switch thrown, without the corresponding impact on the
functionality. We would have to trap this and set the button back
to its original visual state, and that could get messy.
|
| Example
of behavior and events generated with different settings of
allowEvents
property. |
We figured that the easiest
way to stop the student from going into areas in which he or she
shouldn't be would be to create a mechanism to disable the interface
components dynamically. When we load a particular task, we run through
the interface and selectively enable or disable the interface. We
wished it were as simple as setting the MovieClip's enabled
flag, but we realized we needed an extra feature: when we disabled
an interface element, we still wanted to know if it was manipulated,
so we could present an appropriate message.
Our approach, which we
follow with our
v2 components, is to define a property called allowEvents
(you can see a description of it in our online
v2 component help documentation, by clicking
here). When set to true, this property freezes the functionality
of the component. If the component is manipulated, instead of generating
the component's event, it generates an event named disabled.
The listener(s) can decide whether or not to do anything upon receiving
this event. |
| |
| BACK
TO TOP |
| |
| EVENT
RECORD/PLAYBACK FOR "SHOW ME" AND WIZARDS |
| This
month's download includes
the recorder/playback component SWC (compiled clip) and the
examples from this article. We even throw in the source code
for the component, though it is not necessary to use it.
Sign
up now and get access to download the code through the
subscriber's edition!
If
you do not have our equipment interface component set, you
can buy the whole set by CLICKING
HERE. |
People who have heard
me talk about Flash and simulation no doubt have been subjected
to my story about listening to a simulator toolkit vendor extol
the virtues of a record/playback feature in their toolset, allowing
SME's (Subject Matter Experts) to record a sequence of interactions
with a simulator, for didactic purposes, then let the students play
the interactions back to the simulator at certain moments of the
presentation. This operation was kind of cute, and certainly no
great brain teaser. One simply needs to listen to component events,
timestamp and "mouse"stamp (cursor position) the events
when they come in, then figure out a way to play them back to the
simulator. Playing them back to the simulator means
- Serializing them in
some way to be portable beyond the initial recording
- Making the components
in such a way to "play back" the visuals that occur
when the event was generated
- Animating a cursor
to move among the components to simulate the user's control.
In our book, I describe
and give code as to how to do this (p. 488). After a few emails
requesting more details about this, I decided to encapsulate the
behavior in a component. In the following example, click Record
(the button with the black circle on it) on the yellow panel at
the bottom, then click on some of the components. When you are done,
either press the OUTPUT button (and you can copy-and-paste the text
into a text editor to make it more readable), or simply press the
play button (the right-facing arrow underneath "Playback").
I implemented the v2
component in a very similar way I described in the book. The only
special thing a component needs to use this is to have a method,
I call execEvent
(or
reverse action, from the book), to satisfy #2, above.
This method simulates the visual changes that occur when the event
was generated. It is a very simple method to write for any component,
since all the component has to do is see if the event requested
is one that it can generate, then duplicate the visual and possibly
behavioral action for that event. One could pretty easily write
this method for the Macromedia v2 components and then use the recorder
component for those as well!
The execEvent
method accepts up to three arguments (the documentation is also
in the Help panel with the v2 components, for example, here):
- The name of the event
- any value associated
with the event
- a Boolean value indicating
whether or not to generate the real event in addition to its visual
change.
The recorder/playback
component, called FMXISEventRecorder,
has a couple of properties you can set, such as the cursor graphic,
the starting point for the animated cursor, and a pointer to the
movie clip instance containing the controls. This latter property
means that you can place the simulator in one position on the screen
for recording, then record the events, and sometime later play back
the events even if you have moved the simulator. The way this is
implemented is by recording the mouse position relative to this
movie clip (mc._xmouse,
mc._ymouse) so the
position is correct irrespective of the movie clip's position. The
following example demonstrates this.
We recorded a string
of events, pressed OUTPUT, and stuck the text in the onRelease
method of the button marked PLAY. Here is the output of the recorder:
// Make sure
movie instance clip prop of recorder panel is set to "sim"
var ra = _level0.rec;
ra.resetRec();
ra.recObjs.push(new mx.fmxis.recordedEvent(0, 36, 53, ra.targClip.instance1,
"onDown"));
ra.recObjs.push(new mx.fmxis.recordedEvent(699, 90, 53, ra.targClip.instance2,
"onDown"));
ra.recObjs.push(new mx.fmxis.recordedEvent(618, 142.95, 51, ra.targClip.instance3,
"onDown"));
ra.recObjs.push(new mx.fmxis.recordedEvent(1336, 146.95, 24, ra.targClip.instance3,
"onUp"));
ra.recObjs.push(new mx.fmxis.recordedEvent(714, 97.95, 28, ra.targClip.instance2,
"onUp"));
ra.recObjs.push(new mx.fmxis.recordedEvent(572, 49, 32, ra.targClip.instance1,
"onUp"));
ra.recObjs.push(new mx.fmxis.recordedEvent(477, 44, 43, ra.targClip.instance1,
"onMiddle"));
ra.recObjs.push(new mx.fmxis.recordedEvent(603, 95, 42, ra.targClip.instance2,
"onMiddle"));
ra.recObjs.push(new mx.fmxis.recordedEvent(578, 142.95, 42, ra.targClip.instance3,
"onMiddle"));
ra.playRec();
The output reminds you
at the top to set the movie clip property of the recorder to the
movie clip that contained the controls (it doesn't magically determine
this--you have to set the property before recording the events).
You can see that the ActionScript generated creates a series of
objects of type recordedEvent. The arguments to the recordedEvent
constructor are:
- Milliseconds since
the last event. This is used to know how long to delay between
events.
- X and Y cursor position
when the event occurs, relative to the container movie clip
- Instance name of the
component, relative to the container clip of the controls (targClip,
a property of the recorder, is set to the container movie clip)
- Event name (a string)
- Event value. If the
event has a val property, the recorder uses that value. If that
value is an instance of an Object, the recorder converts the object
to its text representation (i.e., { prop1 : val, prop2 : val,
... }). If you want to see what this looks like, look at the previous
example with the keypad and the potentiometer, record some events,
and look at the resulting event output.
In the example above,
we also hid the recorder since you don't want to show this in your
final piece, but it needs to be there to enable playback. Notice
that currently the animated cursor starts at wherever you begin
the playback, however, you can set a property in the recorder to
start it at a fixed location as well.
The Big Caveat
Up until this point,
I haven't mentioned what is obvious to anyone who plays with the
recorder for more than a few seconds: the recorder captures events,
but it does not record the initial state of the simulator. If you
think about it, you'll see that recording the initial state of a
simulator in a general way requires you to define a certain way
to store the system state. Using statecharts is a good way to prepare
your simulator for capturing system state, but you must set up your
system to ensure when the state is captured, you also record all
pertinent variables/properties. Such a mechanism is beyond this
simple component, but recording and restoring system state doesn't
have to be complex if you make assumptions about how you have set
up your system: store the variables/properties, record which state
is current, and when you want to restore the state, copy the values
back to the variables and transition to the stored state. This usually
will involve adding a few transitions to your simulator beyond the
regular transitions of the state network.
Why Stop There?
You can probably see
how you might use this component to demonstrate how to perform some
task. As I mentioned before, this may or may not be a good thing
to do from a teaching perspective. However, one neat thing that
may have occurred to some of you is that you can make a program
to generate the event strings rather than requiring a SME to record
them. When would you want something like this? How about a wizard!
You will notice that
the ActionScript generated by the recorder could have just as easily
been generated by a program. You could record the x/y position of
the interface elements, keep track of the events they generate,
then dynamically construct the series of recordedEvent instances.
Here is a simple example that someone could use to show how to enter
a number in the display. Enter text (made up of characters 0-8)
into the box at the top, then press TYPE IT.
There are a lot of interesting
possibilities one can imagine for this component. Who wants to make
execEvent methods
for the Macromedia v2 components? Please email me to let me know
how you plan to use it, or are using it!
|
| |
| BACK
TO TOP |
| |
| UPCOMING
EVENTS |
| |
| Do you know
about a simulation event you'd like to announce? Tell
us about it at events@FlashSim.com! |
| |
| |
| |
|
| YOUR
OPINION COUNTS |
| |
| Note:
While we encourage you to join the discussion, we feel we've
heard enough about making money fast, cheap or natural Viagra,
African dignitaries wanting to give us money, low cost insurance,
penis enlargement, dates for married men, Russian girls waiting
to hear from us, reducing wrinkles, tips for exploding our
income, and losing weight rapidly. So if your post was going
to be about one of those or along a similar vein, please post
somewhere else. On the other hand, if you need any of these
services, I'm the man to talk with!
Jonathan |
We constantly run into
all different people around the country and world who have interesting
simulation projects they have in mind or have prepared. We want
to encourage you simulator programmers, instructional designers,
gamers, managers, and other developers to share your stories and
best practices with the rest of us. We invite you to lead or join
the discussion on our FlashSim discussion board:
http://FlashSim.infopop.cc/
We also will monitor
the discussions for particular topics that might make good newsletter
information, so go forth and post!
If you have suggestion
for topics you'd like to see in the newsletter, or links to events
or interesting Flash pieces you've made, please email us at newsletter@FlashSim.com. |
| |
| |
| ADMINISTRATION |
| This newsletter (in
public form) also is available on FlashSim in the
RESOURCES section:
http://www.FlashSim.com/newsletter/v3n1.html
If you'd prefer not to
receive this newsletter, send us your name, your registered e-mail
address, and the message: "Unsubscribe" to removeListener@FlashSim.com.
If you are receiving
this newsletter from a friend and want to subscribe yourself, please
email us a message with the subject "Subscribe" to addListener@FlashSim.com. |
| |
| |
|