Search

in:
Print

VixML Cookbook

This page contains descriptions of commonly used VixML techniques and answers to frequently asked questions about developing interactive media with VixML.

Table of contents



How do I make part of a scene invisible? How do I switch the "active" part of a scene?

To make part of a scene invisible, you can set the scene's alpha value to 0, or simply move the object somewhere offscreen. Using this technique, you can create a scene with multiple screens that can be activated and deactivated.

What is the difference between "local state" and "global state"?

The local state dictates the position of an object relative to its parent. The global state dictates the final state of the object when it is drawn onscreen.

Objects in VixML scenes are organized into hierarchies and objects inherit transformations from parent groups all the way through the hierarchy. When specifying the state of an object via a controller, we are setting the object's "local state, or where it appears relative to its parent object. The "global state" depends on the state of all parents through the hierarchy. The global state of an object can change even while the local state stays the same. Unless otherwise specified all controllers operate on the local state of an object.

How are object property values computed relative to the parent's property values?

As described above, object properties are always applied relative to the parent's state to produce the final on-screen state (i.e., global state).

Volume, alpha, color and scale are computed by scaling the object's local values with the parent values. Location is computed by offsetting from the parent's position. Rotation is computed by applying the child's rotation to the parent's rotation.

As a result of these parent transformations, objects often end up being displayed with states quite different from their own local states. In the following example, the sprite object has an alpha of .5, but will ultimately be drawn with an alpha of .05 due to the parent's alpha value of .1:
Sample:
  1. <group alpha=".1">
  2. <sprite name='blue' image='images/blue.png' alpha='.5' />
  3. </group>


How do I draw with a mask?

See the maskset and maskeddraw attributes of the sprite tag.

The maskset attribute will cause a sprite to not be rendered to screen, but instead to be rendered to an invisible mask. A subsequence sprite drawn with maskeddraw tag will then fill in the pixels set in the maskset sprite. A maskeddraw is expected to follow directly after a maskset. Any use of maskset or maskeddraw not executed in the specified order will result in undefined results.

Sample:
  1. <sprite name='circlemask' image='images/circleMask.png' maskset='1' />
  2. <sprite name='bluesolid' image='images/blue.png' maskeddraw='1' />


How do I make an object respond to two different controllers at the same time?

By embedding the object inside of a group, which holds one of the controllers.

Groups in VixML are used for more than just grouping multiple objects. They can also be used for grouping multiple controllers and triggers for a single object. Consider a ball which should bounce up and down according to a sequencecontroller, but which should also be moved left and right according to the user's mouse using an inputmapcontroller. Both controllers cannot be active for one object, but by embedding the object in a group, one of the controllers may be moved there. Because the controllers are operating on different objects, there are no conflicts between the controllers. Both operate independently and the normal rules of the applying transforms down the scene hierarchy will produce the desired effect.

Sample:
  1. <group>
  2. <inputmapcontroller source="localmouse" dest="location" />
  3. <sprite image="image.png">
  4. <!-- these locations are applied relative to the parent group's location, so
  5. both the inputmapcontroller and the sequence controller affect the object. -->
  6. <sequencecontroller repeat="1">
  7. <move location="0,100" duration=".4" />
  8. <move location="0,0" duration=".4" />
  9. </sequencecontroller>
  10. </sprite>
  11. </group>


What is the difference between "scale" and "size" for a sprite?

The size attribute is intended for specifcying precise pixel dimensions for a resized image, while the scale attribute is a general purpose attribute for animating the size of an object while the scene runs.

The size tag cannot be animated and is generally used to specify the "native" size after a source image has been scaled away from its original size (typically done for performance reasons or to save memory). The scale factor, on the other hand, is used to animate the size of objects in the scene. Furthermore, scale can be used for all types of objects, while size is used only for sprites or hotspots.

How do I customize the clickable region of an object?

Use a hotspot object instead.

Clickable regions of objects depend on their bounding boxes and cannot be changed. Hotspots are special objects intended specifically for accepting mouse inputs and they can be sized independently.

How do I manage a set of events intended to take place in a specific sequence?

A sequence of events can be accomplished using a sequencecontroller that waits for messages in a specific sequence, sending another message after each message received. The following example waits for a "mouseclick" message three times in a row, sending a different message after each one.

Sample:
  1. <sequencecontroller>
  2. <wait message="mouseclick" />
  3. <message name="click1" />
  4. <wait message="mouseclick" />
  5. <message name="click2" />
  6. <wait message="mouseclick" />
  7. <message name="click3" />
  8. </sequencecontroller>


How do I make a controller that is activated only once (instead of each time an event occurs)?

Use a sequencecontroller with a wait step that waits for a specific message.

Instead of having a controller that is activated every time a certain message is issued, you can use another sequencecontroller that waits for a certain message and then immediately sends a secondary message to activate the desired controller. Subsequent instances of the first message will not trigger the controller because the controller is not listening to these messages directly. In the following example, the message "onetimecontroller" will be sent only once, regardless of how many times the "onetimetrigger" message is sent.

Sample:
  1. <sequencecontroller>
  2. <wait message="onetimetrigger" />
  3. <message name="onetimecontroller" />
  4. </sequencecontroller>


How do I make the inputmapcontroller map to the right range?

The inputmapcontroller maps arbitrary input ranges to arbitrary output ranges. Each input and output range is a continuous section of the number line, and, by using the scale and offset parameters of the inputmapcontroller, any input range can be mapped to any output range.

The first step is compute the scale by determining the total size of the input and output ranges, and determining what scaling value would make the sizes match. So for example, if mapping an accelerometer input in the range -1 to 1 to a sprite location in the range 100 to 200, the scale s is computed at 2s = 100, or s = 50. A scaling value of 50 will produce the proper magnitude for the mapping. The next step is to apply the scaling factor previously computed, and determine what further offset is required to match the scaled input with the output range. In this case, after scaling, the input is in the range -50 to 50, so to match the desired output range of 100 to 100, we would need an offset of 150.

Sample:
  1. <!--
  2. turn microphone volume into a rotation up to 180 degrees:
  3. map the range 0 to 1 to the range 0 to 180
  4. -->
  5. <inputmapcontroller source='microphone' dest='rotation' scale='180' />
  6.  
  7. <!--
  8. turn accelerometer input into the X coordinate of an object's location, from 0 to 100:
  9. map the range -1 to 1 to the range 0 to 100
  10. -->
  11. <inputmapcontroller source='acceleromter' dest='location' scale='50,0,0' offset='100,0,0' />
  12.  
  13.  
  14. <!--
  15. turn mouse X-coordinate into an alpha value:
  16. map the range -240 to 240 to the range 0 to 1
  17. -->
  18. <inputmapcontroller source='mouse' dest='color' scale='.0020833' offset='.5' />



How does the mapping parameter of inputmapcontroller work?

The mapping parameter specifies how output values are derived from input values in an inputmapcontroller.

Both input and output values of inputmapcontrollers can consist of multiple values or channels. The mouse position, for example, has two components, and accelerometer readings have three. For outputs, location, scale and color each take three components and the volume has just one. As far as the mapping parameter is concerned, these channels are referred to as X, Y and Z. The mapping attribute indicates which input channels are to be used to compute the output channels.

The mapping attribute is a string of up to three elements that specify which input channel is used to generate each output channel. The default mapping is "X,Y,Z", meaning that the X-output uses input channel X, the Y-output uses input channel Y and the Z-output uses input channel Z. If we wanted the X, Y and Z output values to all come from input channel Y, we would use the mapping "Y,Y,Y". The special value of 0 may also be used to indicate that a fixed value of 0 is used for the given channel. For example, mapping "Z,0,Y" specifies that the X-output is taken from input channel Z, and that the Z-output is taken from input channel Y, but that the Y-output is given the value of 0.

Note that the channel mapping is only the first step of an inputmapcontroller and that the scale and offset parameters will further manipulate input values before they are applied to objects.

How do I introduce randomness or variation into a scene

Use a oneofcontroller.

The oneofcontroller accepts all of the same sequence steps of a sequencecontroller, but only one step is chosen at random for execution. The sequence controller may hold actual randomized behavior steps (i.e., move steps or sound steps) or it may contain a list of message steps which in turn trigger a more sophisticated set of randomized behaviors. The following controller will randomly send one of three messages.

Sample:
  1. <oneofcontroller>
  2. <message name='doAnimation1' />
  3. <message name='doAnimation2' />
  4. <message name='doAnimation3' />
  5. </oneofcontroller>



How do I make an object follow the mouse? What is the difference between "mouse" and "localmouse" in the inputmapcontroller?

Use the inputmapcontroller with a source of localmouse and a dest of location in order to make the object follow the mouse. The localmouse input is typically used for the specific mapping of mouse point to object.
Example:
<sprite image="images/myObjectImage.png">
    <inputmapcontroller source="localmouse" dest="location" />
</sprite>

The mouse input of inputmapcontroller uses the raw screen coordinates of the mouse. The localmouseinput transforms the raw coordinates into the coordinate frame of the object being controlled. This means that by using the localmouse input, the destination can be set to location and the object will then follow the finger. If the mouse input is used for such a task, then rotations, scales and offsets of the object may cause the global mouse coordinates to not be aligned with the local coordinate system.

How do I zoom in on a specific location within the scene?

You can zoom in on a location by using a controller to adjust the scale of the top-level group in the scene.
Example:
<scene>
  <group>
    <sprite image="images/background.png" />
    <sequencecontroller>
      <move location="0,0" scale="1.5, 1.5" duration="3" />
    </sequencecontroller>
  </group>
</scene>


How do I deactivate another controller that is currently running on an object?

There are circumstances where you may wish to have one controller animate an object repeatedly, but then stop upon a user event such as a mouse click. Because there can only be one active controller at any time for a single object, this can be accomplished by simply by activating a new controller. When the new controller is activated, all others for that object are deactivated. Therefore, you can create two controllers for an object that respond to different messages, and only one of them will be active at any point in time.

Example:
<sprite image="images/image.png">
 
  <!-- send the "click" message when clicked -->
  <mousedowntrigger message="click" />
 
  <!-- repeatedly fade this image in/out when the scene is loaded -->
  <sequencecontroller repeat="1">
    <move alpha="1.0" duration="2.0" />
    <move alpha="0.0" duration="2.0" />
  </sequencecontroller>
 
  <!-- use an empty controller to stop the fade in/out -->
  <sequencecontroller trigger="click" />
 
</sprite>


How do I animate a sprite backwards or in reverse order?

By setting the frame per second rate to a negative value.
Example:
<sprite image="images/animation#####.png" fps="-20" />


How can I debug and visualize the area of a sprite (or any other object)?

Use the drawbounds attribute to draw the outline of the object.

The drawbounds attribute can be helpful in visually determining the actual size and location of a sprite within the scene. Specify a value of 1 enables bounds drawing.
Example:
<sprite image="images/image.png" drawbounds="1" />


How do I wait for a fixed duration in a sequencecontroller?


Use a move step with the given duration and no motion.

A move step with no motion attributes will simply wait for the given duration.
Example:
<move duration="3" />


What is the duration of an animate step and a sound step? Why don't two subsequent sound or animate steps do what I want?


animate and sound steps have no duration–they execute immediately.

Because these steps have no duration, the effects of one step may be immediately negated by another step. With an animate step, for example, the animation does not play in its entirety before proceeding to the next step, so a subsequent animate step will be executed immediately. If you wish to allow an animation or sound to finish before proceeding to the next step, you should wait the required duration (see this entry for more information).

How do I play two simultaneous sounds? Why does a sound step cut off the current sound being played?


Play the sounds in different objects.

Each object has a single "voice" as far as sound playing is concerned and can only play one sound at a time.

Example:
<sprite image="rockband####.png">
  <!-- when the user clicks on the image, broadcast a "playInstruments" message" -->
  <mousedowntrigger message="playInstruments"/>
</sprite>
 
<!-- group the instruments separately so that both of them can play at the same time -->
<group name="guitarGroup">
  <sequencecontroller trigger="playInstruments">
    <sound file="guitar.wav" />
  </sequencecontroller>
</group>
 
<group name="drumsGroup">
  <sequencecontroller trigger="playInstruments">
    <sound file="drums.wav" />
  </sequencecontroller>
</group>



Okay, what's the real deal with texture and animation sizes? Why is a certain texture or animation causing performance problems on the phone?


The guidelines provided in Building A Scene explain the maximum suggested sizes for textures and animations. The specific rational for these guidelines are explained here.

First, it is important to understand that the size of a texture or animation on disk does not really play much of a role when it comes to the question of what's too big for an animation. What is important is the pixel dimensions of the asset once uncompressed. The maximum texture size on the iPhone is 1024x1024. To get good performance for an animation in VixML, we must be able to internally pack all of the pixels into a 1024x1024 sheet. If we can't do this, then we have to break up each frame into its own texture, which is slower and less efficient.

Furthermore, there's an additional restriction that textures must be powers of two, so for example, individual animation frames of 160x240 are in fact stored internally as 256x256 (the next largest power of two rectangle from 160x240). So each frame of animation is 256x256x4 (4 bytes per pixel) bytes = 262k of data. If we were to render 100 frames of this animation, it would require over 26 Mb of data just for this one animation! Practically speaking, the texture memory available on the phone is about 24 Mb for everything, so this one animation would cause the entire scene to fail.

So, how can one fix this? The general strategy for figuring out ideal animation sizes is to figure out how to make the animation fit into a 1024x1024 square. In our 100 frame animation example, we would want each frame to be no larger than 100x100, which would allow us to pack all 100 frames into the texture.

How do I trigger an event based on the location of two objects intersecting or colliding?

Use the "collisionhandler" tag to detect for collisions between two objects.

Example:
<scene>
     <collisionhandler class1="asteroid" class2="photon" message="collision" />
     <group>
          <hotspot size="50, 50" location="-160,0" class="asteroid" drawbounds="1">
               <sequencecontroller>
                    <!-- move the asteroid to the right to collide with the photon -->
                    <move location="160,0" duration="5" /> 
               </sequencecontroller>
               <sequencecontroller trigger="collision">
                    <!-- these steps will occur when the asteroid and photon class have collided -->
               </sequencecontroller>
          </hotspot>
          <hotspot size="50,50" location="160,0" class="photon" drawbounds="1">
               <sequencecontroller>
                    <!-- move the photon to the left to collide with the asteroid -->
                    <move location="-160,0" duration="5" />
               </sequencecontroller>
               <sequencecontroller trigger="collision">
                    <!-- these steps will occur when the asteroid and photon class have collided -->
               </sequencecontroller>
          </hotspot>
     </group>
</scene>


For more information see "collisionhandler"

How do I implement conditional logic for a mouse click ?

In the following example, a mouse click will do two different things depending on the current state. When in "titlemenu" state, it will give a "startMain" message, which will in turn cause the state to switch to "mainscreen". At that time, the mouse click will have a new behavior — it will trigger "somethingElse".

Example:
<group>
	<mousedowntrigger message="startMain" state="titlemenu" />
	<mousedowntrigger message="somethingElse" state="mainscreen" />
 
	<sequencecontroller trigger="startMain">
		<statechange state="mainscreen" />
	</sequencecontroller>
</group>




Created by: jonklein. Last Modification: Thursday 12 of March, 2009 16:31:07 EDT by tedachtem.