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)
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: