Discord
Login
Community
DARK THEME

Is there any way to reverse animation?

Wonder if there is way to play sprite animation in "reverse" mode?

I want to play animation normal way first and then wait a second or two and play it in reverse way

No native way that I could find in microScript.

This is my way, though:

https://microstudio.io/Martellus/llfcspritemutations/ZPNNNXDR/

(Ignore the walking mutated wobbles... they are part of other code in the project not included in the code below).

Full code:

init = function()
  s = createGameSprite("animtest")  
end
update = function()
  // update the frame number depending on the direction
  if s.animSpeedCounter < 0 then
    s.animSpeedCounter = s.animSpeed
    s.onFrame += s.frameDir
    if s.onFrame < 0 then
      s.frameDir *= -1 // reverse the direction
      s.onFrame = 0
    end
    if s.onFrame > s.numFrames-1 then // dont forget that -1 cause array ia zero based.
      s.frameDir *= -1 // reverse the direction
      s.onFrame = s.numFrames-1 // dont forget that -1 cause array ia zero based.
    end
  else
    s.animSpeedCounter -= 1 // count down until next frame change
  end
end
draw = function()
  screen.clear("#000")
  // draw the sprite at 0/0
  s.oSprite.setFrame(s.onFrame)
  screen.drawSprite(s.name,s.x,s.y,s.w,s.h)
  local t = ""
  if s.frameDir > 0 then t = "Forwards"else t = "Backwards" end
  screen.drawText(t,0,30,10,"#FF0")
  screen.drawText("All sprite frames:",0,-20,10,"#FF0")
  for i = 0 to s.numFrames-1
    s.oSprite.setFrame(i)
    screen.drawSprite(s.name,(((s.numFrames-1)*s.w)/2)*-1+(i*s.w),-40,s.w,s.h)
  end
end
// createGameSprite() :: create our own sprite wrapper
createGameSprite = function(sName)
  local newS = object
    oType = "sprite"
    name = sName
    // x,y: where to draw the sprite
    x = 0
    y = 0
    // oSprite:: this will hold the reference to our sprite GFX
    oSprite = sprites[sName]
    // h,w: dimensions of the sprite
    w = sprites[sName].width
    h = sprites[sName].height
    // animSpeed/animSpeedCounter:: how long to wait before changing the frame
    animSpeed = floor(60 /sprites[sName].fps) // roughly calculated based on how often update() is called, which is normally around 60/second.
    animSpeedCounter = 20 // used to track wshen we can change the frame number. 
    // numFrames:: number of frames - remeber, starts with 0 (zero)
    numFrames = sprites[sName].frames.length
    // onFrame:: which frame to show
    onFrame = 0 
    // frameDir:: the direction the animation should run: 1 forwards, -1 backwards, and 0 (zero) for pause on the current frame!    
    frameDir = 1 
  end
  return newS
end

Second method - clone the sprite into a new sprite object, and reverse the animation.

That way you can just flip between the sprites shown, and less complex code.

In the demo app, click on "2" to see the example live. https://microstudio.io/Martellus/llfcspritemutations/ZPNNNXDR/

init = function()
  s = createGameSprite("animtest")
  s2 = createGameSprite("animtest")  
  s2.hid = 1
  cloneSprite(s2)
  reverseAnim(s2)  
end

update = function()
// nothing here
end

draw = function()
  screen.clear("#000")
  screen.drawText("Method 2 to reverse animation with cloned sprite",0,75,8,"#FFF")
  screen.drawText("Original Sprite",-50,0,10,"#FF0")
  screen.drawSprite(s.name,-50,-20,s.w,s.h)
  screen.drawText("Revered Clone",50,0,10,"#FF0")
  screen.drawSprite(s2.name,50,-20,s.w,s.h)
  for i = 0 to s.numFrames-1
    screen.drawImage(sprites[s.name].frames[i],-100,-80+i*s.h,s.w,s.h)
    screen.drawSprite(sprites[s2.name].frames[i],100,-80+i*s.h,s.w,s.h)
  end  
end
// make a new sprite based of an existing sprite: ie a clone!
cloneSprite = function(w)
  local s = sprites[w.name]
  local numFrames = s.frames.length
  //print(s.name+"::nf["+numFrames+"]")
  local s2 = new Sprite(s.width,s.height)
  if s2 then
    //s2.name = s.name+"_"+w.hid
    w.name = s.name+"_"+w.hid
    s2.name = w.name
    s2.fps = s.fps
    w.oSprite = s2
    sprites[w.name] = s2
    //print("New>"+w.name+"<")
    hue = random.nextInt(360)
    for i = 0 to numFrames-1
      local bf = s.frames[i]
      local buffer = new Image(s.width,s.height)
      buffer.drawImage(bf,0,0,s.width,s.height)
      if i < s2.frames.length  then
        //print(s2.name+"["+i+"] ==== use existing")
        local bf2 = s2.frames[i]
        // bf2.drawRect(0,0,s.width,s.height,"rgb(1,1,1)")
        bf2.setBlending("destination-out")
        bf2.fillRect(0,0,s.width,s.height,"rgba(0,0,0,1)")
        bf2.setBlending("source-over")
        bf2.drawImage(buffer,0,0,s.width,s.height)
      else
        //print("---> push")
        s2.frames.push( buffer )      
      end
    end
  end
end
// Reverse the frames
reverseAnim = function(w)
  local s = sprites[w.name]
  local numFrames = s.frames.length
  local midPoint = floor(numFrames/2)
  //print(s.name+"::nf["+numFrames+"];mix["+mix+"]")
  for i = 0 to midPoint-1
    local ff = s.frames[i]
    s.frames[i] = s.frames[numFrames-1-i]
    s.frames[numFrames-1-i] = ff
  end
end

I like your second example, wonder if there is any way to clone animation in "reverse order". In this case, I imagine we can just play cloned animation normally to get "reverse" effect.

Yarko

Sure there are many ways to clone a sprite and reverse it.

Here is one quick tinker:

init = function()
  tmpSpr = sprites["right"]
  sprites["left"] = new Sprite(tmpSpr.width, tmpSpr.height)
  newSpr = sprites["left"]
  count = tmpSpr.frames.length-1
  for i=0 to count
    newSpr.frames[i] = tmpSpr.frames[count-i]
  end
  newSpr.fps = tmpSpr.fps
end

draw = function()
    screen.clear()
    screen.drawSprite("right",-35,0,40)
    screen.drawSprite("left" , 35,0,40)    
end

"right" is the sprite with the original animation. "left" will be created from that.
For sure it should be nicely wrapped up in a function :)

Live Long and Tinker

This is nice and and clear approach ! Like it, thank you for your time and code example.

Yarko

Post a reply

Progress

Status

Preview
Cancel
Post
Validate your e-mail address to participate in the community