Back to Knowledge Base

Advanced Movement

The second way that textures can be animated is by redefining the textureCoords or data points. These methods are very similar to basic plot animation, where points are recalculated and updated.

Example 1

In this example, a rocket texture is shifted in the X and Y directions using sliders. The data points are cleared, recalculated, and updated each time a slider is moved.

<xyPlot name="plot">
  <style>
    <aspectRatio>1</aspectRatio>
  </style>
  <axis dim="x" auto="growOnly" min="0" max="1" />
  <axis dim="y" auto="growOnly" min="0" max="1" />
  <texture name="rocketTexture">
    <image src="resources/rocket.png" />
  </texture>
  <series name="rocket" draw="radialFill" style="trueColor" manual="true">
    <textureCoords ref="rocketTexture">0 0; 0 1; 1 1; 1 0</textureCoords>
    <data>0.3 0.6; 0.3 0.4; 0.7 0.4; 0.7 0.6</data>
  </series>
</xyPlot>

<p>X</p>
<slider name="xSlider" min="-0.5" max="0.5">
  <onValueChanged>
    xVal = value
    yVal = ySlider.Value

    -- Add each new data point separately
    plot.rocket:Clear();
    plot.rocket:Add(0.3 + xVal, 0.6 + yVal);
    plot.rocket:Add(0.3 + xVal, 0.4 + yVal);
    plot.rocket:Add(0.7 + xVal, 0.4 + yVal);
    plot.rocket:Add(0.7 + xVal, 0.6 + yVal);
    plot.rocket:Update()
  </onValueChanged>
</slider>

<p>Y</p>
<slider name="ySlider" min="-0.5" max="0.5">
  <onValueChanged>
    xVal = xSlider.Value
    yVal = value

    -- Add each new data point to a matrix, add at once
    local shift = matrixf({ {0.3 + xVal, 0.6 + yVal}, {0.3 + xVal, 0.4 + yVal}, {0.7 + xVal, 0.4 + yVal}, {0.7 + xVal, 0.6 + yVal}  });

    plot.rocket:Clear();
    plot.rocket:Add(shift);
    plot.rocket:Update()
  </onValueChanged>
</slider>
 
 

Example 2

This example updates the textureCoords of an image to simulate movement. Given an image of a character in multiple stages of walking, it is possible to shift between each frame of the image quickly to give the appearance of walking.

Dog_Walking.png
<xyPlot name="plot">
  <style>
    <aspectRatio>1</aspectRatio>
  </style>
  <axis dim="x" auto="fixed" min="0" max="1" />
  <axis dim="y" auto="fixed" min="0" max="1" />
  <texture name="walkingTexture">
    <image src="resources/Dog_Walk.png" />
  </texture>
  <series name="dog" draw="triangles" style="trueColor" manual="true">
    <!-- Texture coordinates only capture first 1/10 of the image (one frame of the dog) -->
    <textureCoords ref="walkingTexture">0 0; 0.1 0; 0.1 1; 0 0; 0 1; 0.1 1</textureCoords>
    <data>0.25 0.5; 0.5 0.5; 0.5 0.25; 0.25 0.5; 0.25 0.25; 0.5 0.25</data>
  </series>
</xyPlot>

<simulation name="sim">
  <onActivePageChanged>
     if active then
         sim:Start();
     else
         sim:Stop();
     end
  </onActivePageChanged>
  <onUpdate>
     -- Cycle through all 10 images every 0.75 seconds, then return to the beginning (the % operator ensures that after 10 frames, we return to frame 1)
     local xd = (1/10) * math.floor((10/0.75) * (time % 0.75))
     
     local walkingCoords = matrixf({ {xd, 0}, {xd + (1/10), 0}, {xd + (1/10), 1}, {xd, 0}, {xd, 1}, {xd + (1/10), 1} });  
     
     plot.dog.TextureCoordinates.Points:Clear();
     plot.dog.TextureCoordinates.Points:Add(walkingCoords);

     plot.dog:Update();
  </onUpdate>
</simulation>
 
 

Example 3

In this example, the textureCoords of a background image are updated in small increments to create a continuous background. Given an image of a repeating texture, the coordinates can be continuously shifted to simulate the appearance of movement.

trees_background.png
<drawing name="plot">
  <style>
    <aspectRatio>1</aspectRatio>
  </style>
  <axis dim="x" auto="fixed" min="0" max="1" />
  <axis dim="y" auto="fixed" min="0" max="1" />
  <texture name="walkingTexture">
    <image src="resources/Dog_Walk.png" />
  </texture>
  <texture name="backgroundTexture">
    <image src="resources/trees.png" />
  </texture>
  <!-- Sky color -->
  <series name="sky" draw="radialFill">
    <style>
      <foreground color="lightCyan" />
    </style>
    <data>0 0; 1 0; 1 1; 0 1</data>
  </series>
  <series name="trees" draw="triangles" style="trueColor" manual="true">
    <textureCoords ref="backgroundTexture">0 0; 1 0; 1 1; 0 0; 0 1; 1 1</textureCoords>
    <data>0 0; 1 0; 1 0.6; 0 0; 0 0.6; 1 0.6</data>
  </series>
  <series name="dog" draw="triangles" style="trueColor" manual="true">
    <textureCoords ref="walkingTexture">0 0; 0.1 0; 0.1 1; 0 0; 0 1; 0.1 1</textureCoords>
    <data>0.25 0.27; 0.5 0.27; 0.5 0.02; 0.25 0.27; 0.25 0.02; 0.5 0.02</data>
  </series>
</drawing>

<simulation name="sim">
  <onActivePageChanged>
     if active then
         sim:Start();
     else
         sim:Stop();
     end
  </onActivePageChanged>
  <onUpdate>
      -- Dog movement
      local xd = (1/10) * math.floor((10/0.75) * (time % 0.75))
      
      local walkingCoords = matrixf({ {xd, 0}, {xd + (1/10), 0}, {xd + (1/10), 1}, {xd, 0}, {xd, 1}, {xd + (1/10), 1} });  
    
      plot.dog.TextureCoordinates.Points:Clear();
      plot.dog.TextureCoordinates.Points:Add(walkingCoords);
      
     -- Since background is repeated 3 times, shift the coordinates until the image is 2/3 of the way through, which occurs every 20 seconds
      local xb = (time % 20) / 30
      local shiftBG = (1/3)
      local backgroundCoords = matrixf({ {xb, 1}, {xb + shiftBG, 1}, {xb + shiftBG, 0}, {xb, 1}, {xb, 0}, {xb + shiftBG, 0} });        
      
      plot.trees.TextureCoordinates.Points:Clear();
      plot.trees.TextureCoordinates.Points:Add(backgroundCoords);

      plot.dog:Update();
      plot.trees:Update();
  </onUpdate>
</simulation>