Can someone point out my noob mistake here?

kcorey

Member
Licensed User
Longtime User
Hi All,

I am building a card game. I would like to show some fireworks when the user wins.

The way I imagined doing it was to overlay a panel with a Colors.Transparent background, and then draw particles on the panel.

So, the code below is my first naive attempt...but I'm not getting anything on the screen as expected. (There are no Designer screens, just cut/paste the code but watch out for the wrap).

So, I put a label on the Activity (to make sure the panel is covering things), and then lay a panel over it. So far, so good.

Then I initialise 100 particles, and start a timer that is supposed to update them 5 times per second (higher framerate later...I just wanted to see it working before tweaking).

With breakpoints, the timer does the tick, the particles are attempting to be drawn...it's just that they never seem to appear.

I'm sure it's me being naive...what have I done wrong here?

Thanks,

-Ken

----------------------------------------------


'Activity module
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.

Type Particle(x,y,dx,dy As Int, g As Int,life,dlife As Int, Colour, dColour As Int, size As Int)

End Sub

Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.

Dim particles(256) As Particle
Dim particlelist As List
Dim particlecanvas As Canvas
Dim particleview As View
Dim particletmr As Timer
End Sub

Sub initps(vw As View)
Dim r As Rect
r.Initialize(0,0,vw.Width,vw.Height)

particlelist.Initialize

For i=0 To 255
particles(i).Initialize
finishparticle(i)
Next
particleview = vw
particlecanvas.Initialize(particleview)
'particlecanvas.DrawRect(r, Colors.Transparent,True,0)
End Sub

Sub newparticle(x As Int,y As Int,dx As Int,dy As Int,g As Int,life As Int,dlife As Int,c As Int,dc As Int,size As Int) As Int
Dim i As Int
i = particlelist.Get(0)
particlelist.RemoveAt(0)
particles(i).x = x
particles(i).y = y
particles(i).dx = dx
particles(i).dy = dy
particles(i).g = g
particles(i).life = life
particles(i).dlife = dlife
particles(i).Colour = c
particles(i).dColour = dc
particles(i).size = size
Return i
End Sub

Sub finishparticle(i As Int)
particles(i).x=0
particles(i).y=0
particles(i).dx=0
particles(i).dx=0
particles(i).g=0
particles(i).life=0
particles(i).dlife=0
particles(i).Colour=0
particles(i).dColour=0
particles(i).size=0
particlelist.Add(i)
End Sub

Sub runparticles
Dim p As Particle
For i = 0 To 255
If particles(i).life>0 Then
' erase the old particle
Dim r As Rect
r.Initialize(particles(i).x,particles(i).y,particles(i).size,particles(i).size)
'particlecanvas.DrawRect(r,Colors.Transparent,True,0)
'particleview.Invalidate2(r)

' age particle, draw if still alive.
particles(i).life=particles(i).life-particles(i).dlife
If particles(i).life<=0 Then
finishparticle(i)
Else
particles(i).x = particles(i).x + particles(i).dx
particles(i).y = particles(i).y + particles(i).dy
If particles(i).x<0 OR particles(i).x>100%x OR particles(i).y<0 OR particles(i).y>100%y Then
finishparticle(i)
Else
r.Initialize(particles(i).x,particles(i).y,particles(i).size,particles(i).size)
particlecanvas.DrawRect(r,particles(i).Colour,True,0)
particleview.Invalidate2(r)
End If
End If
End If
Next
DoEvents
End Sub

Sub Activity_Create(FirstTime As Boolean)
Dim pnl As Panel
Dim lbl As Label

pnl.Initialize("")
pnl.Color = Colors.ARGB(255,0,68,0)

lbl.Initialize("")
lbl.Text="Testing."
lbl.textsize=36
lbl.TextColor=Colors.White
Activity.AddView(lbl, 20%x, 40%y, 60%x, 60dip)

Activity.AddView(pnl,0,0,100%x,100%y)

initps(pnl)

particletmr.Initialize("particletmr",200)

particletmr.Enabled = True

Activity.Invalidate

For i = 0 To 100
newparticle(i,100%y,0,-1-(i/2),0,100%y,1,Colors.ARGB(Rnd(0,256),Rnd(0,256),Rnd(0,256),Rnd(0,256)),0,Rnd(2,5))
Next
End Sub

Sub particletmr_tick
runparticles
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
 

kcorey

Member
Licensed User
Longtime User
fireworks.zip

Okay, here's the .zip file.

:sign0163:

Can anyone spot my mistake? Do I not understand how views/canvases work?

-Ken
 

Attachments

  • fireworks.zip
    6.3 KB · Views: 225
Upvote 0

Djembefola

Active Member
Licensed User
Longtime User
As a first step, change the "as view" declarations to "as Panel"

For example

B4X:
Dim particleview As View
should be
B4X:
Dim particleview As Panel

you will also need something like

B4X:
particleview.initialize("")
Activity.Addview(particleview,...)

and some other changes.

If you have done this, something will happen on your screen. Not exactly, what you wanted to achieve, maybe)
 
Upvote 0

kcorey

Member
Licensed User
Longtime User
Hi Djembefola,

Thanks for writing.

turns out the problem was more fundamental...

If I change the runparticles sub to simply invalidate the whole panel rather than trying to be clever then I do indeed see "something"...

The other problem is that I was confused by the different between a left,top,width,height spec for a view, and a left,top,right,bottom of a rect.

Once, I sorted that out, I got something close to what I wanted.

Of course, this isn't nearly as nice as if it were done in OpenGL or something, but that seems a bit heavyweight just for a few gratuitous sparkles.

-Ken
 

Attachments

  • fireworks.zip
    6.7 KB · Views: 201
Upvote 0

Djembefola

Active Member
Licensed User
Longtime User
If I change the runparticles sub to simply invalidate the whole panel rather than trying to be clever then I do indeed see "something"...

-Ken

Invalidating only the drawn rectangles works fine.
I saw "something" without invalidating the whole panel.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Attached you find a modified version of your original program from post#3.
You have already found the problem with the rectangle definition.
You dont need to transfer the Panel in the initps routine you can use it directly. Normally it's faster to invalidate small rectangles rather than the whole panel but in your case invalidating the whole panel once per timer tick is faster than invalidating a lot of small rectangles.

Best regards.
 

Attachments

  • fireworks1.zip
    6.3 KB · Views: 248
Upvote 0

kcorey

Member
Licensed User
Longtime User
Well, it turns out that when this panel is sitting on top of another panel with 25 or so views on it, and you kick off a few fireworks the framerate slows to a crawl, even with a Nexus 7.

Obviously, this isn't the right way to go. Would the animation run much faster using OpenGL?

Can I layer a transparent OpenGL layer over my interface the way I'm talking about doing?

-Ken
 
Upvote 0

kcorey

Member
Licensed User
Longtime User
The short answer is, yes, of course you can do this in OpenGL. Once the code I'm working on is satisfactory, I'll post it to this thread for anyone else who might need it.

-Ken
 
Upvote 0

kcorey

Member
Licensed User
Longtime User
The code for fireworksGL

Here's the code for fireworks GL. Depending on device it can handle significantly more sparkles than before. A nexus 7 will easily handle 200-300 sparkles at the same time.

-Ken
 
Upvote 0
Top