B4J Question weird thing happening with b4j and list...

ilan

Expert
Licensed User
Longtime User
hi

i am trying to draw circles on my mainform without to overlap each other.
what i do is i add 50 circles in a loop and on each loop i check if the new circle is overlaping the old circles, if = true it wont be drawn and if = false i draw it and ADD that circle to the list to check it in the next loop.

the problem is that when i want to get the circles from the list i always get the same circle as the new created circle. but why?? i should not get the same coordinate as the new circle!!

something is wrong but i am too tired to understand

this is the code:

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim c As Canvas
    Type crl(x As Float,y As Float,r As Int)
    Dim circle_list As List
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    MainForm.Show
    c.Initialize("canvas")
    circle_list.Initialize
    MainForm.RootPane.AddNode(c,0,0,600,400)
    fill_circles(50)
End Sub

Sub fill_circles(amount As Int)
    Dim overlap As Boolean
   ' Dim circle, old_crl As crl
    circle_list.Clear
  
    For i = 0 To amount - 1
        Dim circle, old_crl As crl
        circle.r = Rnd(2,25)
        circle.x = Rnd(0,MainForm.RootPane.Width-(circle.r*2))
        circle.y = Rnd(0,MainForm.RootPane.Height-(circle.r*2))

        overlap = False
        For j = 0 To circle_list.Size - 1
            old_crl = circle_list.Get(j)
            If distance_x(circle.x,old_crl.x) < circle.r + old_crl.r And distance_y(circle.y,old_crl.y) < circle.r + old_crl.r Then
                overlap = True
                Exit
            End If
        Next  
      
        If Not(overlap) Then
           c.DrawCircle(circle.x,circle.y,circle.r,fx.Colors.ARGB(100,Rnd(0,255),Rnd(0,255),Rnd(0,255)),True,0)  
           circle_list.Add(circle)
        End If
    Next
End Sub

Sub distance_x(x1 As Float,x2 As Float) As Float
    Return(Abs(x1-x2))
End Sub

Sub distance_y(y1 As Float,y2 As Float) As Float
    Return(Abs(y1-y2))
End Sub
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Move the Dim of the circle object inside the loop, you must create a new object to add to the list, simply changing the value won't work.

The list simply holds a reference to the object, unless you keep creating new objects, all the items in the list will point to the same object, and all have the last value set.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
thanx daestrum, i guess i was to tired to figure it out (1:35 am) :)

now we will do it UNTIL we really have 1000 circles that are not overlaping:

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim c As Canvas
    Type crl(x As Float,y As Float,r As Int)
    Dim circle_list As List
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    MainForm.Show
    c.Initialize("canvas")
    circle_list.Initialize
    MainForm.RootPane.AddNode(c,0,0,MainForm.RootPane.Width,MainForm.RootPane.Height)
    fill_circles(1000)
End Sub

Sub fill_circles(amount As Int)
    Dim overlap As Boolean
    circle_list.Clear
    Dim i As Int = 0
 
    Do Until i = amount
        Dim circle, old_crl As crl
        circle.r = Rnd(2,25)
        circle.x = Rnd(circle.r,MainForm.RootPane.Width-(circle.r*2))
        circle.y = Rnd(circle.r,MainForm.RootPane.Height-(circle.r*2))

        overlap = False
        For j = 0 To circle_list.Size - 1
            old_crl = circle_list.Get(j)
            If distance_x(circle.x,old_crl.x) < circle.r + old_crl.r And distance_y(circle.y,old_crl.y) < circle.r + old_crl.r Then
                overlap = True
                Exit
            End If
        Next 
     
        If Not(overlap) Then
           c.DrawCircle(circle.x,circle.y,circle.r,fx.Colors.ARGB(100,Rnd(0,255),Rnd(0,255),Rnd(0,255)),True,0) 
           circle_list.Add(circle)
           i = i + 1
        End If
    Loop
End Sub

Sub distance_x(x1 As Float,x2 As Float) As Float
    Return(Abs(x1-x2))
End Sub

Sub distance_y(y1 As Float,y2 As Float) As Float
    Return(Abs(y1-y2))
End Sub
 
Last edited:
Upvote 0

ilan

Expert
Licensed User
Longtime User
ok and now make a small rain effect on the windshield (and turn the wiper on ;))

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim c As Canvas
    Type crl(x As Float,y As Float,r As Int)
    Dim circle_list As List
    Dim t1, wiper As Timer
    Dim wiperCD As Int = 80
    Dim deg As Double = -90
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    MainForm.Show
    c.Initialize("canvas")
    circle_list.Initialize
    MainForm.RootPane.AddNode(c,0,0,MainForm.RootPane.Width,MainForm.RootPane.Height)
    t1.Initialize("t1",50)
    t1.Enabled = True
    wiper.Initialize("wiper",10)
End Sub

Sub t1_tick
    'c.ClearRect(0,0,c.Width,c.Height)
    fill_circles(50)
    wiperCD = wiperCD - 1
    If wiperCD < 0 Then wiper.Enabled = True
End Sub

Sub wiper_tick
    If deg > 90 Then
        wiper.Enabled = False
        deg = -90
        wiperCD = 80
    Else
        c.DrawRectRotated(MainForm.Width/2,0,20,MainForm.Height*2,fx.Colors.White,True,0,deg)
        deg = deg + 2     
    End If
End Sub

Sub fill_circles(amount As Int)
    Dim overlap As Boolean
    circle_list.Clear
    Dim i As Int = 0
 
    Do Until i = amount
        Dim circle, old_crl As crl
        circle.r = Rnd(2,25)
        circle.x = Rnd(circle.r,MainForm.RootPane.Width-(circle.r*2))
        circle.y = Rnd(circle.r,MainForm.RootPane.Height-(circle.r*2))

        overlap = False
        For j = 0 To circle_list.Size - 1
            old_crl = circle_list.Get(j)
            If distance_x(circle.x,old_crl.x) < circle.r + old_crl.r And distance_y(circle.y,old_crl.y) < circle.r + old_crl.r Then
                overlap = True
                Exit
            End If
        Next 
     
        If Not(overlap) Then
           c.DrawCircle(circle.x,circle.y,circle.r,fx.Colors.ARGB(100,Rnd(0,255),Rnd(0,255),Rnd(0,255)),True,0)
           circle_list.Add(circle)
           i = i + 1
        End If
    Loop
End Sub

Sub distance_x(x1 As Float,x2 As Float) As Float
    Return(Abs(x1-x2))
End Sub

Sub distance_y(y1 As Float,y2 As Float) As Float
    Return(Abs(y1-y2))
End Sub
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
@ilan, now that is cool. I love it. Two points: driving in that rain would be impossible!! Wipers generally go back and forwards.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Wipers generally go back and forwards.

here you go:

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim c As Canvas
    Type crl(x As Float,y As Float,r As Int)
    Dim circle_list As List
    Dim t1, wiper As Timer
    Dim wiperCD As Int = 80
    Dim deg As Double = -90
    Dim now_back As Boolean
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    MainForm.Show
    c.Initialize("canvas")
    circle_list.Initialize
    MainForm.RootPane.AddNode(c,0,0,MainForm.RootPane.Width,MainForm.RootPane.Height)
    t1.Initialize("t1",50)
    t1.Enabled = True
    wiper.Initialize("wiper",10)
End Sub

Sub t1_tick
    'c.ClearRect(0,0,c.Width,c.Height)
    fill_circles(Rnd(10,25))
    wiperCD = wiperCD - 1
    If wiperCD < 0 Then wiper.Enabled = True
End Sub

Sub wiper_tick
    If deg > 90 Then now_back = True
    If now_back =  True Then deg = deg - 2 Else deg = deg + 2  

    If deg < -90 Then
        wiper.Enabled = False
        deg = -90
        wiperCD = 80
        now_back = False
    Else
        c.DrawRectRotated(MainForm.Width/2,0,20,MainForm.Height*2,fx.Colors.White,True,0,deg)  
    End If
End Sub

Sub fill_circles(amount As Int)
    Dim overlap As Boolean
    circle_list.Clear
    Dim i As Int = 0
 
    Do Until i = amount
        Dim circle, old_crl As crl
        circle.r = Rnd(2,25)
        circle.x = Rnd(circle.r,MainForm.RootPane.Width-(circle.r*2))
        circle.y = Rnd(circle.r,MainForm.RootPane.Height-(circle.r*2))

        overlap = False
        For j = 0 To circle_list.Size - 1
            old_crl = circle_list.Get(j)
            If distance_x(circle.x,old_crl.x) < circle.r + old_crl.r And distance_y(circle.y,old_crl.y) < circle.r + old_crl.r Then
                overlap = True
                Exit
            End If
        Next 
     
        If Not(overlap) Then
           c.DrawCircle(circle.x,circle.y,circle.r,fx.Colors.ARGB(100,Rnd(0,255),Rnd(0,255),Rnd(0,255)),True,0)
           circle_list.Add(circle)
           i = i + 1
        End If
    Loop
End Sub

Sub distance_x(x1 As Float,x2 As Float) As Float
    Return(Abs(x1-x2))
End Sub

Sub distance_y(y1 As Float,y2 As Float) As Float
    Return(Abs(y1-y2))
End Sub

Where are the screenshots?

just playing around with b4j, nothing special :) but anyway here is a screenshot:

wiper.jpg
 
Last edited:
Upvote 0
Top