Animation technique

vasper

Member
Licensed User
Longtime User
Need help with this. Read on...

I have created a live wallpaper with animation using a photo I took during the holidays of a snow-filled "vista" and a few png images of snowflakes.

My technique to avoid flickering, because I need a large number of snowflakes on screen is to prepare the background image with the pngs on a canvas (from initialized bitmaps) and then update the screen with the result. I don't know however if that is the most efficient way to do this. I would love to hear you comments on that.

This is the code I use (all the main work is done in addNewSnowFlake, AnimateSnowFlakes and FullRefresh)

B4X:
'Service module
Sub Process_Globals
   Dim lwm As LWManager
   Dim x, y, vx, vy As Int
   Dim initialized As Boolean: initialized = False
   Dim boxSize As Int
   Dim FlakeBitmap(8) As Bitmap
   Dim Bgnd As Bitmap
   Dim prevRect As Rect
   Dim prevRectOffSet As Rect
   Dim Degrees As Int
   Dim snowflakes As List
   Dim snowflakesX As List
   Dim snowflakesY As List
   Dim snowflakesVX As List
   Dim snowflakesVY As List
   Dim snowflakesPrev As List
   Dim snowflakesPrevOffset As List
   Dim snowflakesDegrees As List
   Dim snowflakesBoxSize As List
   Dim rndFlake As Int
   Dim fullInfoBM As Bitmap
   Dim maxSnow As Int
   maxSnow = 20
   snowflakes.Initialize
   snowflakesX.Initialize
   snowflakesY.Initialize
   snowflakesVX.Initialize
   snowflakesVY.Initialize
   snowflakesPrev.Initialize
   snowflakesPrevOffset.Initialize
   snowflakesDegrees.Initialize
   snowflakesBoxSize.Initialize
End Sub

Sub Service_Create
   lwm.Initialize("lwm", True)
   lwm.StartTicking(80) 
   vx = 1dip
   vy = 4dip
   boxSize = 16dip
   FlakeBitmap(1).Initialize(File.DirAssets, "Snowflake1.png")
   FlakeBitmap(2).Initialize(File.DirAssets, "Snowflake2.png")
   FlakeBitmap(3).Initialize(File.DirAssets, "Snowflake3.png")
   FlakeBitmap(4).Initialize(File.DirAssets, "Snowflake4.png")
   FlakeBitmap(5).Initialize(File.DirAssets, "Snowflake5.png")
   FlakeBitmap(6).Initialize(File.DirAssets, "Snowflake6.png")
   FlakeBitmap(7).Initialize(File.DirAssets, "Snowflake7.png")
   Bgnd.Initialize(File.DirAssets, "snowvista.png")
   rndFlake = Rnd(1,8)
End Sub

Sub addNewSnowFlake(ax As Int,ay As Int,avx As Int, Engine As LWEngine)
   snowflakes.Add(Rnd(1,8))
   snowflakesX.Add(ax)
   snowflakesY.Add(ay)
   snowflakesVX.Add(avx)
   snowflakesVY.Add(Rnd(1,8))
   snowflakesBoxSize.Add(Rnd(12,32))
   Dim prevRect1 As Rect
   Dim prevRectOffset1 As Rect
   prevRect1.Initialize(0,0,0,0)
   snowflakesPrev.Add(prevRect1)
   prevRectOffset1.Initialize(0,0,0,0)
   snowflakesPrevOffset.Add(prevRectOffset1)   
   snowflakesDegrees.Add(0)
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub


Sub Service_Destroy

End Sub

Sub lwm_SizeChanged (Engine As LWEngine)
   DrawBackground (Engine)
End Sub
Sub DrawBackground (Engine As LWEngine)
   FullRefresh(Engine)
End Sub

Sub FullRefresh (Engine As LWEngine)
   Dim aRectOffSet As Rect
   Dim aRect As Rect
   aRectOffSet.Initialize(0 + Engine.CurrentOffsetX,0,Engine.ScreenWidth + Engine.CurrentOffsetX,Engine.ScreenHeight)
   aRect.Initialize(0,0,Engine.ScreenWidth,Engine.ScreenHeight)
   Engine.Canvas.DrawBitmap(Bgnd,aRectOffSet,aRect)
   Engine.RefreshAll
End Sub

Sub lwm_OffsetChanged (Engine As LWEngine)
   FullRefresh(Engine)
End Sub

Sub lwm_VisibilityChanged (Engine As LWEngine, Visible As Boolean)
   If Visible Then
      DrawBackground (Engine)
   End If
End Sub

Sub AnimateSnowFlakes(Engine As LWEngine)
   Dim i As Int
   If Not (fullInfoBM.IsInitialized) Then
      fullInfoBM.InitializeMutable(Engine.ScreenWidth,Engine.ScreenHeight)
   End If
   Dim aCNV As Canvas
   aCNV.Initialize2(fullInfoBM)
   Dim aRectOffSet As Rect
   Dim aRect As Rect
   aRectOffSet.Initialize(0 + Engine.CurrentOffsetX,0,Engine.ScreenWidth + Engine.CurrentOffsetX,Engine.ScreenHeight)
   aRect.Initialize(0,0,Engine.ScreenWidth,Engine.ScreenHeight)   
   aCNV.DrawBitmap(Bgnd,aRectOffSet,aRect)
   i = 0
   Do While i<snowflakes.Size
      Dim nwRndFlake As Int
      Dim nwX As Int
      Dim nwY As Int
      Dim nwVX As Int
      Dim nwVY As Int
      Dim nwPrevRect As Rect
      Dim nwPrevRectOffset As Rect
      Dim nwDegrees As Int
      Dim nwBoxSize As Int
      nwRndFlake = snowflakes.Get(i)
      nwX = snowflakesX.Get(i)
      nwY = snowflakesY.Get(i)
      nwVX = snowflakesVX.Get(i)
      nwVY = snowflakesVY.Get(i)
      nwPrevRect = snowflakesPrev.Get(i)
      nwPrevRectOffset = snowflakesPrevOffset.Get(i)
      nwDegrees = snowflakesDegrees.Get(i)
      nwBoxSize = snowflakesBoxSize.Get(i)
      If nwX > Engine.ScreenWidth Then
         nwX = 1dip
      Else If nwX < nwboxSize Then
         nwX = nwboxSize + 2dip
      End If
      If nwY  + nwboxSize > Engine.ScreenHeight Then
         snowflakes.RemoveAt(i)
         snowflakesX.RemoveAt(i)
         snowflakesY.RemoveAt(i)
         snowflakesVX.RemoveAt(i)
         snowflakesVY.RemoveAt(i)
         snowflakesPrev.RemoveAt(i)
         snowflakesPrevOffset.RemoveAt(i)
         snowflakesDegrees.RemoveAt(i)
         snowflakesBoxSize.RemoveAt(i)
      Else
         nwX = nwX + nwVX
         nwY = nwY + nwVY   
         Engine.Rect.Top = nwY
         Engine.Rect.Left = nwX
         Engine.Rect.Bottom = nwY + nwboxSize
         Engine.Rect.Right = nwX + nwboxSize         
         nwDegrees = (nwDegrees + 10) Mod 360
         nwPrevRect.Left = Engine.Rect.Left - 2dip
         nwPrevRect.Top = Engine.Rect.Top - vy
         nwPrevRect.Right = Engine.Rect.Right + 2dip
         nwPrevRect.Bottom = Engine.Rect.Bottom
         nwPrevRectOffset.Left = Engine.Rect.Left + Engine.CurrentOffsetX - 2dip
         nwPrevRectOffset.Top = Engine.Rect.Top - vy
         nwPrevRectOffset.Right = Engine.Rect.Right + Engine.CurrentOffsetX + 2dip
         nwPrevRectOffset.Bottom = Engine.Rect.Bottom
         aCNV.DrawBitmapRotated(FlakeBitmap(nwRndFlake), Null, Engine.Rect, nwDegrees)
         snowflakesX.Set(i,nwX)
         snowflakesY.Set(i,nwY)
         snowflakesDegrees.Set(i,nwDegrees)
         Dim selDirection As Int
         selDirection = Rnd(1,10)
         If selDirection == 2 Then
            nwVX = -1 * Abs(nwVX)
         End If
         If selDirection == 8 Then
            nwVX = Abs(nwVX)
         End If         
         snowflakesVX.Set(i,nwVX)
         i = i + 1
      End If         
   Loop
   Engine.Canvas.DrawBitmap(fullInfoBM,aRect,aRect)
   Engine.RefreshAll   
End Sub

Sub lwm_Tick (Engine As LWEngine)
   
   If snowflakes.Size<maxSnow Then
      addNewSnowFlake(Rnd(20dip,Engine.ScreenWidth-60dip),0,vx, Engine)
   End If
   AnimateSnowFlakes(Engine)
End Sub
Sub lwm_Touch (Engine As LWEngine, Action As Int, tx As Float, ty As Float)
   rndFlake = Rnd(1,8)
   addNewSnowFlake(Round(tx),Round(ty),vx, Engine)
End Sub
 
Last edited:
Top