locked
Small Basic: Multiple simultaneous loops RRS feed

  • Question

  • Hello.

    How can I write simultaneous while, for, etc. loops?

    Some tries to reach this: ("..." are code lines)

    ... ... ... While "True" ... ... EndWhile While "True" 'This while loop will not be reached because the while loop above.' ... ... EndWhile

    ...
    ...
    ...
    While "True"
      ...             'These 2 codes will only happen 1 time because'
      ...             'the While below never let the update pass the EndWhile.'
      While "True"
        ...
        ...
      EndWhile
      ...             'This will not happen.'
    EndWhile
    ...
    ...
    Goto Loop    'Do not work because Goto do not like more than 1 tags'
    
    While "True"
      Loop:
      ...
      ...
    EndWhile
    
    While "True"
      Loop:
      ...
      ...
    EndWhile

    One way would be by using events, but what event will start automatically when the program starts?

    The Small Basic program where I want to use this: XXZ226

    Thanks for answer.


    Greetings



    • Edited by Benur21 Saturday, July 2, 2016 3:44 PM
    Saturday, July 2, 2016 3:42 PM

Answers

  • I'm not sure what you are actually trying to achieve.  Perhaps multi-threading - 2 thngs happening at the same time.

    A couple suggestions without knowing the use case.

    1] Just do the 2 things one after the other - it depends on what you are tring to do if this won't work.

    2] The Timer event can be started when the program starts and has been used to do muti-threading (parallel programming on multi-core PCs), but it can be tricky (global variable scope, UI thread updates and others).

    • Marked as answer by Benur21 Sunday, July 3, 2016 9:35 PM
    Saturday, July 2, 2016 3:48 PM
  • This probably isn't exactly what you want to do do, but it is fast and is how I would start.  What I mean is parallel While loops isn't the solution.

    gw = 500
    gh = 500
    GraphicsWindow.Width = gw
    GraphicsWindow.Height = gh
    radius = 10
    speed = 0.1
    next = 0
    
    GraphicsWindow.MouseDown = OnMouseDown
    
    While ("True")
      If (mouseDown) Then
        AddBullet()
        mouseDown = ""
      EndIf
      MoveBullets() 
      CheckBullets()
      Program.Delay(20)
    EndWhile
    
    Sub OnMouseDown
      mouseDown = "True"
    EndSub
    
    Sub AddBullet
      mx = GraphicsWindow.MouseX
      my = GraphicsWindow.MouseY
      'New bullet
      next = next+1
      bullet[next] = Shapes.AddEllipse(2*radius, 2*radius)
      'Position
      bulletX[next] = gw/2
      bulletY[next] = gh/2
      'Velocity
      bulletU[next] = mx-bulletX[next]
      bulletV[next] = my-bulletY[next]
      'Update active bullets
      count = Array.GetItemCount(bullet)
      indices = Array.GetAllIndices(bullet)
    EndSub
    
    Sub MoveBullets
      For i = 1 To count
        index = indices[i]
        bulletX[index] = bulletX[index]+speed*bulletU[index]
        bulletY[index] = bulletY[index]+speed*bulletV[index]
        Shapes.Move(bullet[index],bulletX[index]-radius,bulletY[index]-radius)
      EndFor
    EndSub
    
    Sub CheckBullets
      For i = 1 To count
        index = indices[i]
        If (bulletX[index] < -radius Or bulletX[index] > gw Or bulletY[index] < -radius Or bulletY[index] > gh) Then
          Shapes.Remove(bullet[index])
          bulletX[index] = ""
          bulletY[index] = ""
          bulletU[index] = ""
          bulletV[index] = ""
        EndIf
      EndFor
      'Update active bullets
      count = Array.GetItemCount(bullet)
      indices = Array.GetAllIndices(bullet)
    EndSub

    • Marked as answer by Benur21 Sunday, July 3, 2016 9:36 PM
    Saturday, July 2, 2016 4:53 PM

All replies

  • I'm not sure what you are actually trying to achieve.  Perhaps multi-threading - 2 thngs happening at the same time.

    A couple suggestions without knowing the use case.

    1] Just do the 2 things one after the other - it depends on what you are tring to do if this won't work.

    2] The Timer event can be started when the program starts and has been used to do muti-threading (parallel programming on multi-core PCs), but it can be tricky (global variable scope, UI thread updates and others).

    • Marked as answer by Benur21 Sunday, July 3, 2016 9:35 PM
    Saturday, July 2, 2016 3:48 PM
  • I'm not sure what you are actually trying to achieve.  Perhaps multi-threading - 2 thngs happening at the same time.

    A couple suggestions without knowing the use case.

    1] Just do the 2 things one after the other - it depends on what you are tring to do if this won't work.

    2] The Timer event can be started when the program starts and has been used to do muti-threading (parallel programming on multi-core PCs), but it can be tricky (global variable scope, UI thread updates and others).

    What I want is to make an undefined number of bullets, which its postitions will be updated at a constant speed. I am using arrays to get this. Loop for 1 bullet is fast, but what if we fire 5-10 bullets at same time? As you can see in my program, it slows a lot when we put lots of bullets (click to fire bullet).

    Greetings

    Saturday, July 2, 2016 3:52 PM
  • Sorry I didn't see your program first.

    The slowing is probably the SB arrays and bullet objects are not removed after they are finished with (off screen).

    I would start by checking these out, the second is probably the most relevant here.

    http://social.technet.microsoft.com/wiki/contents/articles/20865.small-basic-dynamic-graphics.aspx#Creating_and_Removing_Sprites

    http://social.technet.microsoft.com/wiki/contents/articles/24857.small-basic-sprite-arrays.aspx


    • Edited by litdev Saturday, July 2, 2016 4:04 PM
    Saturday, July 2, 2016 4:03 PM
  • Sorry I didn't see your program first.

    The slowing is probably the SB arrays and bullet objects are not removed after they are finished with (off screen).

    I would start by checking these out, the second is probably the most relevant here.

    http://social.technet.microsoft.com/wiki/contents/articles/20865.small-basic-dynamic-graphics.aspx#Creating_and_Removing_Sprites

    http://social.technet.microsoft.com/wiki/contents/articles/24857.small-basic-sprite-arrays.aspx


    It is removing the bullets when they are too far, and I changed it (days ago) so they are removed earlier if you hit to the right face to help me to see it disappearing.

    EDIT: it was also changing the brush color when the bullet is removed.


    Greetings

    • Edited by Benur21 Sunday, July 3, 2016 2:33 PM
    Saturday, July 2, 2016 4:13 PM
  • OK,

    Do the updating of the positions in the game loop, not the bullet creation.

    Remember to also keep the array sizes not growing as well as the bullet objects.

    Saturday, July 2, 2016 4:24 PM
  • This probably isn't exactly what you want to do do, but it is fast and is how I would start.  What I mean is parallel While loops isn't the solution.

    gw = 500
    gh = 500
    GraphicsWindow.Width = gw
    GraphicsWindow.Height = gh
    radius = 10
    speed = 0.1
    next = 0
    
    GraphicsWindow.MouseDown = OnMouseDown
    
    While ("True")
      If (mouseDown) Then
        AddBullet()
        mouseDown = ""
      EndIf
      MoveBullets() 
      CheckBullets()
      Program.Delay(20)
    EndWhile
    
    Sub OnMouseDown
      mouseDown = "True"
    EndSub
    
    Sub AddBullet
      mx = GraphicsWindow.MouseX
      my = GraphicsWindow.MouseY
      'New bullet
      next = next+1
      bullet[next] = Shapes.AddEllipse(2*radius, 2*radius)
      'Position
      bulletX[next] = gw/2
      bulletY[next] = gh/2
      'Velocity
      bulletU[next] = mx-bulletX[next]
      bulletV[next] = my-bulletY[next]
      'Update active bullets
      count = Array.GetItemCount(bullet)
      indices = Array.GetAllIndices(bullet)
    EndSub
    
    Sub MoveBullets
      For i = 1 To count
        index = indices[i]
        bulletX[index] = bulletX[index]+speed*bulletU[index]
        bulletY[index] = bulletY[index]+speed*bulletV[index]
        Shapes.Move(bullet[index],bulletX[index]-radius,bulletY[index]-radius)
      EndFor
    EndSub
    
    Sub CheckBullets
      For i = 1 To count
        index = indices[i]
        If (bulletX[index] < -radius Or bulletX[index] > gw Or bulletY[index] < -radius Or bulletY[index] > gh) Then
          Shapes.Remove(bullet[index])
          bulletX[index] = ""
          bulletY[index] = ""
          bulletU[index] = ""
          bulletV[index] = ""
        EndIf
      EndFor
      'Update active bullets
      count = Array.GetItemCount(bullet)
      indices = Array.GetAllIndices(bullet)
    EndSub

    • Marked as answer by Benur21 Sunday, July 3, 2016 9:36 PM
    Saturday, July 2, 2016 4:53 PM
  • Thanks, I am looking at this.

    Another problem is: what if I want 2 loops in which one of them I want to loop instantly (no delay) and another I want it with some delay (like 1000s)? The delay of the second loop will delay the first loop too!


    Greetings

    Sunday, July 3, 2016 2:31 PM
  • If we are talking about slow and fast bullets then you could just update at the high frequency with a slower position change (slower velocity).  But I am guessing the reason.

    Or in the game loop, only do the slow frequency stuff every 3rd or 4th time through the loop, or even only if the time since it was last done is greater than some interval.

    Basically, like the previous question, the answer is not parallel programming in most cases.  I think its a case of changing a bit how you think about the problem.

    While ("True")
      start = Clock.ElapsedMilliseconds
      
      DoFast()
      If (start-last > 1000) Then
        DoSlow()
        last = start
      EndIf
      
      'Keep constant frame rate 50 fps
      delay = 20-(Clock.ElapsedMilliseconds-start)
      If (delay > 0) Then
        Program.Delay(delay)
      EndIf
    EndWhile
    
    Sub DoFast
      TextWindow.WriteLine("Fast")
    EndSub
    
    Sub DoSlow
      TextWindow.WriteLine("***** Slow *****")
    EndSub

    Sunday, July 3, 2016 2:49 PM
  • I changed my program like that and it's slowing yet, but not so much now: RXW260


    Greetings

    Sunday, July 3, 2016 3:05 PM
  • PS I had an error that will make the bullet sample slow after a while, I forgot to remove a bullet shape.  The second line below should be added.

          Shapes.Remove(bullet[index])
          bullet[index] = ""
    
    A slightly modified test with tis fix, HNL613


    • Edited by litdev Sunday, July 3, 2016 3:16 PM
    Sunday, July 3, 2016 3:15 PM
  • I want to add a variable handling in this to see how variables are changing. But that needs some delay, like 80ms, to be visible, but that will slow the other loops.

    My Sub-routine variable handling looks like:

    Sub Var_Handling
      TextWindow.Clear()
      TextWindow.WriteLine("var1=" + var1)
      TextWindow.WriteLine("var2=" + var2)
      Program.Delay(80)
    EndSub

    Sometimes this helps me a lot when there's something strange happening.


    Greetings

    Sunday, July 3, 2016 6:23 PM
  • Also, that fix is breaking.

    And the loop in the bullet creation was my try to make each bullet loop its own positions... lol

    My idea about 2 simultaneous loops is because I did some projects in Scratch where it's just possible (and easy) to make simultaneous loops.


    Greetings


    • Edited by Benur21 Sunday, July 3, 2016 6:37 PM
    Sunday, July 3, 2016 6:34 PM
  • You are still thinking the same way.

    If you want to delay the print out while continuing the main program, then just don't print out the next time if it occurs too quickly.

    You cannot run at full speed and print out messages with a delay if the messages occur quickly - the messages will  just build up.

    While you are debugging it is fine for the prgram to slow while errors are displayed.

    I'm not trying to be awkward, but parallel multi-threading is not the answer, especially not SB.

    The following is NOT THE SOLUTION, all sorts of pain will evolve (reentrancy, event queuing...).  I guarantee this will drive you and me mad, but here it is for fun.

    Timer.Interval = 0
    Timer.Pause()
    Timer.Tick = OnTick

    count = 0
    While ("True")
      count = count+1
      GraphicsWindow.Title = count
      If (Math.GetRandomNumber(100) = 1) Then
        Timer.Resume()
      EndIf
      Program.Delay(20)
    EndWhile

    Sub OnTick
      TextWindow.WriteLine("Timer "+count)
      Program.Delay(1000)
      Timer.Pause()
    EndSub

    Sunday, July 3, 2016 7:06 PM
  • I found why it was breaking, my error, now it works better but it slows until the bullets are removed, that make it faster again... ZMQ171

    I have litdev extension installed. Can I use its arrays LDArray. to make it faster? I just don't know how to use it...


    Greetings

    Sunday, July 3, 2016 9:17 PM
  • To get array performance improvemets I would use LDList or the PowerArray extension (both faster than LDArray in most cases).  For arrays less than about 100 to 200 this probably isn't worth the effort.

    For lots of shape updates LDFastShapes batch processes them and may make improvements.

    However, in most cases with array and sprite counts < 100 the improvements are minimal and efficient game loop coding is more important.

    Sunday, July 3, 2016 9:43 PM
  • .. additionally, Programs that use LDArray
    Sunday, July 3, 2016 9:45 PM
    Answerer
  • But this slowness is caused by something in SmallBasic?

    Do you know about the game diep.io (very well known, like agar.io)? Do you think it is using multi-threading to handle that BIG number of bullets, tanks, etc.? Or it works that good because it is programmed in a better language? Super-Server?

    Anyway it is something simple that can still be done in SB but like 5-10 bullets in a screen is enough to make it slower.

    Thanks for your help, litdev, the answers for my questions are here and I can pick this ideas later when I really need them.


    Greetings

    Sunday, July 3, 2016 11:39 PM
  • Yes, Small Basic arrays and graphics updates are slow in general.

    It was designed to be small and simple to use.  The intention is that programmers can graduate to other languages when they want more features or more performance.

    However, there are no magic bullets, bad code in any language will be slow and good coding in SB can be very effective.  So learning the basics is most important and can be achieved in SB.  I actually think that because SB is slow it highlights the difference between efficient and inefficient code and this is a good thing.

    Most games will be written in a C++ or java type language and at some level work directly with the OpenGL, DirectX or GPUs directly.  They will also be carefully coded, may use parallel (sometimes parallel slows things if it is not done right - there is actually a performance hit starting threads approximately equivalent to 1000000 cpu multiplications).

    Parallel may be used for example - to do all the sounds on one thread, network connection on a thread etc, but unlikely to do bullet calculations across threads.

    Monday, July 4, 2016 8:13 AM