Android Example Raindrop/Snow effect

Hi all,
Just a small sharing.
Using a timer to make a raindrop or snow effect.I don't know whether it's the correct way to do this. =D
B4X:
Sub Timer_rain_Tick
    Dim image As ImageView
    image.Initialize("")
    'image.Bitmap =LoadBitmap(File.DirAssets, "drop.png")
    image.Bitmap =LoadBitmap(File.DirAssets, "snow.png")
    Dim left As Int =Rnd(0,100)
    Panel1.AddView(image,(left*Panel1.Width)/100,-20%x,16dip,16dip)
    Dim a As Int = Rnd(0,10)
    If a >5  Then 'If there is already an image/logo in screen, make it randomly fall from front/back
        image.SendToBack
    Else
        image.BringToFront
    End If
    image.SetLayoutAnimated(5000,image.Left,120%y,image.Width,image.Height)
    image.SetVisibleAnimated(5000,False)
    Sleep(5000)
    image.RemoveView
End Sub
 

Attachments

  • Screenshot_2017-12-12-09-14-57-481_b4a.rain.png
    Screenshot_2017-12-12-09-14-57-481_b4a.rain.png
    38.9 KB · Views: 1,293
  • Screenshot_2017-12-12-09-20-51-513_b4a.rain.png
    Screenshot_2017-12-12-09-20-51-513_b4a.rain.png
    59.2 KB · Views: 968
  • rain.zip
    9.1 KB · Views: 552

wonder

Expert
Licensed User
Longtime User
Please don't take it in a negative manner, as I only want to help, but there are many problems with this code.

Let's start with the basics. What is a Timer object? Well, it's basically an asynchronous infinite loop where each iteration occurs every X milliseconds. Why are you loading (and destroying) the same bitmap file infinite times? Why are you creating (and destroying) an ImageView object infinite times? Why are you adding and removing View objects to Panel1 infinite times? These operations should never be done inside a loop. Also, why are you using Sleep inside a Timer tick event?

Secondly, if you want to use nothing more than the core library, you should use the Canvas object instead of Panels and ImageViews, which were not designed for this kind utilization.

I'm only trying to help, I've made many mistakes in the past as well. Please take my words as constructive criticism.
 
Last edited:

hongbii khaw

Member
Licensed User
Longtime User
Please don't take it in a negative manner, as I only want to help, but there are many problems with this code.

Let's start with the basics. What is a Timer object? Well, it's basically an asynchronous infinite loop where each iteration occurs every X milliseconds. Why are you loading (and destroying) the same bitmap file infinite times? Why are you creating (and destroying) an ImageView object infinite times? Why are you adding and removing View objects to Panel1 infinite times? These operations should never be done inside a loop. Also, why are you using Sleep inside a Timer tick event?

Secondly, if you want to use nothing more than the core library, you should use the Canvas object instead of Panels and ImageViews, which were not designed for this kind utilization.

I'm only trying to help, I've made many mistakes in the past as well. Please take my words as constructive criticism.
Hi wonder,
Thanks for your advice, I appreciate that you point out my mistake and I will try to improve this example with canvas.
Please comment on the new code.
Again, thank you very much.
B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim Canvas1 As Canvas
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("Layout1")
    Canvas1.Initialize(Activity)
    Rainning(10)
   
End Sub

Sub Raindrop
    Dim left As Int =Rnd(0,100) 'Random starting position
    Dim speed As Int = Rnd(40,50)
    Dim DestRect As Rect
    Dim image As Bitmap 
    image.Initialize(File.DirAssets,"drop.png")
    DestRect.Initialize((left/100)*100%x, -16dip, (left/100*100%x)+16dip,0) 'Initial position
    Canvas1.DrawBitmap(image,Null,DestRect) 'Initial image
    Do While True
    Sleep(10)
        Canvas1.DrawRect(DestRect, Colors.Transparent, True, 0dip) 'Cover/Clear the last image
        DestRect.Top =    DestRect.Top +speed'Changing position
        DestRect.Bottom =DestRect.Bottom+speed'Changing position
        Canvas1.DrawBitmap(image,Null,DestRect)'Draw new image to new position
        Activity.Invalidate
    If DestRect.Top > 100%y Then 'Back to top when reached bottom
        DestRect.Top = -16dip
        DestRect.Bottom =0
        DestRect.Left =(Rnd(0,100)/100)*100%x
        DestRect.Right = DestRect.Left+16dip
    End If
    Loop
End Sub

Sub Rainning(heavy As Int)
    For a=0 To heavy
        Raindrop
    Next
End Sub
 

Attachments

  • rain_canvas.zip
    8.1 KB · Views: 359
Last edited:

hongbii khaw

Member
Licensed User
Longtime User
Nice job.

I like to see everything that has anything to do with animations :)

If you are interested i could show you a different way how to make those animations.

Regards, ilan :)
Hi ilan,
I'm interested in discovering the new horizon of coding and I'm still learning.
I appreciate if you can show me:D:D:D
Thank you very much
 

ilan

Expert
Licensed User
Longtime User
Hi ilan,
I'm interested in discovering the new horizon of coding and I'm still learning.
I appreciate if you can show me:D:D:D
Thank you very much

here is my example for a raining day (i hope it will be raining here in my country soon, we are in the end of December but we have 22 degrees outside and almost no rain for this winter)

in my opinion, if you will make an Android Live Wallpaper out of it you should use a rendering library like libgdx. because adding lots of drops will also drop your FPS :)
there is a Live Wallpaper Libgdx example from @Informatix so you may have a look at it.
 

Attachments

  • rain.zip
    63.7 KB · Views: 338

ilan

Expert
Licensed User
Longtime User
ps: some pieces of advice about your code.

1' if you make animations that should run always then dont use Sleep() or the build in Animations for views. They are only meant to show short animations but not run in loops so use a Timer (if you are making it with a canvas!)

2' if you dont show anything in your layout you dont need to create a blank layout file and load it.

3' since all your drops use the same image file create a bitmap and refer to it instead of loading each drop creation the image

4' i dont understand the "Do While True ... Loop" in your code. what should be true and what returns true? anyway i dont recommend using do while .. in animations. you can get very easily into an infinite loop

5' when you are using canvas you need to clear your canvas on each draw. i dont see where you are doing it.

6' its not clear to me why you create a new rect and then try to move it when it hits the ground. if it is a new rect you create it where ever you want. if you want to change the position of an object or view it needs to be created outside that sub because you call it on each drop creation.

anyway i find it very good that you try doing it and not just request a ready to use code. so keep trying and learning (we all do every day :) )
 
Last edited:

ilan

Expert
Licensed User
Longtime User
But if you find code for rain ready, you could just take care of animating a character with an umbrella :D

yes but if you need then a code for a snowy day and you only know 3 keys on your keyboard (CRTL + C and CRTL + V) then you will need more then an umbrella.
so the best way to learn coding so to try first by your self and compare with another code you found in the forum and see if you can improve yours.

but because you are a pro i dont need to tell you that, right? o_O
 

wonder

Expert
Licensed User
Longtime User
Hi wonder,
Thanks for your advice, I appreciate that you point out my mistake and I will try to improve this example with canvas.
Please comment on the new code.
Again, thank you very much.
I make @ilan's words (post #14) my own.

What you basically need to do is:

In ProcessGlobals:

- Create 1 custom type Snowflake (see code below)

In Globals:
- Create 1 timer object
- Create 1 canvas object
- Create 1 rect object
- Create 1 image object
- Create an array of Snowflake objects

In Activity_Create:
- Initialize the canvas
- Initialize the rect object
- Initialize the image object with the corresponding bitmap
- Initialize the Snowflake array (see code below)
- Finally, initialize the timer with a 16 millisecond interval (= 60 frames per second) <---- LAST STEP!!!

In Timer_Tick:
- Draw the snowflakes using a For Each loop
- For every snowflake that reaches the bottom, its Y-coordinate reverts back to -sizeY (= zero minus snowflake vertical size) and its X-coordinate to Rnd(0%x, 100%x)

B4X:
'Creating a custom type (in ProcessGlobals)
'-------------------------------------------------
Type Snowflake(          _
    texture   As Bitmap, _
    positionX As Float,  _
    positionY As Float,  _
    sizeX     As Float,  _
    sizeY     As Float   _
)
'-------------------------------------------------


'Creating an abstract Snowflake array (in Globals)
'-------------------------------------------------
Dim snowflakes() as Snowflake
'-------------------------------------------------


'Initializing (in Activity_Create)
'-------------------------------------------------
Dim imgSnowflake As Image
imgSnowflake.Initialize(File.DirAssets, "drop.png")
Dim amount = 32 As Int 'for example
Dim snowflakes(amount) as Snowflake
For Each sf In Snowflakes
    sf.Initialize
    sf.texture   = imgSnowflake
    sf.sizeX     = 5dip 'for example
    sf.sizeY     = 5dip 'for example
    sf.positionX = rnd(0%x, 100%x - sf.sizeX)
    sf.positionY = rnd(0%y, -50%y)
Next
'-------------------------------------------------


'Drawing (in Timer_Tick)
'-------------------------------------------------
'Clear the canvas
For Each sf In Snowflakes
    'Update snowflake positionXY
    '...
    '...
    'Whenever a snowflake hits the bottom, bring it back up
    If sf.positionY > 100%y Then
        sf.positionX = rnd(0%x, 100%x - sf.sizeX)
        sf.positionY = -sf.sizeY
    End If
    'Finally, CanvasDraw(sf.texture) at [sf.positionX, sf.positionY]
Next
'-------------------------------------------------
 
Last edited:
Top