Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Today I learned loops are slow
#1
I needed a quick way to calculated the position of a sprite on a sprite sheet if I knew what number sprite it was.  Say you had a sheet that was 40x40 and you wanted the 22nd sprite on it. Something like that. 
I came up with two ways to get it, one was with a double for loop and the other was just using some multiplication.  It doesn't do anything with the xpos, ypos variables other than print the last two calculated.  To get the location of the sprite on the sheet you could just multiply these two numbers by the width and height of the sprite cells respectively.  This was just a speed test.  My second subroutine that relied on pure calculation won out.

Code: (Select All)

''Grid finder - locate a point on a grid from a linear number counting from the origin
''count could run right to left and up to down like pixels on a screen

Option _Explicit
Randomize Timer

''define grid parameters
Const GX = 500 ''width
Const GY = 500 ''height

''initialize points on the grid - load the array
Dim g_points&(30000)
Dim i As Long
For i = 0 To UBound(g_points&)
    g_points&(i) = Int(Rnd * (GX * GY)) + 1
Next

''setup
Dim start_time As Double
Dim end_time As Double
Dim xpos As Long
Dim ypos As Long

''double loop test
Print "Double Loop Test Start."
start_time = Timer

DoubleLoop g_points&(), xpos, ypos, GX, GY
Print "Last coordinates calculated: "; g_points&(UBound(g_points&)); xpos; ypos

end_time = Timer
Print end_time - start_time

''calculation test
Print "Calculation Test Start."
start_time = Timer

GridCalc g_points&(), xpos, ypos, GX, GY
Print "Last coordinates calculated: "; g_points&(UBound(g_points&)); xpos; ypos

end_time = Timer
Print end_time - start_time

Sleep
End


''------------------Subroutines-------------------
Sub DoubleLoop (points&(), xcoord&, ycoord&, gridsizex&, gridsizey&)

    ''find the position of a linear value on a grid using a double loop
    Dim i&
    Dim x&
    Dim y&
    Dim count&

    ''parse the array to get the values for each point
    For i& = 0 To UBound(points&)

        For y& = 0 To gridsizey& - 1
            For x& = 0 To gridsizex& - 1
                ''Calculate the position of the value on the grid
                count& = count& + 1
                If count& = points&(i&) Then
                    xcoord& = x&
                    ycoord& = y&
                    ''reset the count
                    count& = 0

                    GoTo xyloop_exit
                End If
            Next x&
        Next y&
        xyloop_exit:

    Next i&

End Sub ''DoubleLoop


Sub GridCalc (points&(), xcoord&, ycoord&, gridsizex&, gridsizey&)

    ''find the position of a linear value on a grid using math
    Dim i&

    ''parse the array to get the values for each point
    For i& = 0 To UBound(points&)
        ycoord& = Int(points&(i&) / gridsizey&)
        xcoord& = points&(i&) - (ycoord& * gridsizex&) - 1 ''start at 0
    Next i&

End Sub ''GridCalc
Reply
#2
Why would anyone use a loop to find a sprite on a sprite sheet? Its a direct calculation.

And what does creating a bunch of random points have to do with locating a sprite?

Direct Calculation:
let SW = sprite width, SH sprite height, SPR sprites per row, SPC sprites per column
let I be the sprite index of interest
let SX, SY be the top left pixel of Sprite I
then 
SX = (I mod SPC) * SW
SY = int(I / SPR) * SH

Simple (for someone who has done it dozens of times.) Smile
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#3
I just generated a bunch of random numbers for the test.  I thought the loops might be faster because it's just counting up to a number, and then you use the x and y values for the location.  I'm also not that good at math.   Tongue
Reply
#4
S'OK live and learn, give my little forumlas a test, might be helpful to you Smile

The sprite index assumes numbering the sprites left to right, top to bottom starting at 0 for first sprite. I would prefer starting at 1 so the top index is the number of sprites but that complicates the math a bit.

So top index is SPR * SPC -1, minus 1 because we start at 0.

Mod is modulus = the remainder left after dividing index by SPC (sprites per...

Dang I think I switched SPR with SPC, oops sorry
SX = (I mod SPR) * SW
SY = int(I / SPC) * SH

Sprites per row, SPR, is how many sprites across the sheet
Sprites per column, SPC, is how many sprites down the sheet

I will dig up an old proggie to verify these...
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#5
Yikes both forumlas were flawed, glad I checked my formulas. Turns out we only need SPR's Sprites per Row:
    sheetx = (index Mod SPRow) * SW
    sheety = Int(index / SPRow) * SH

OK here is snap of the sprite sheet:
   

We will display the top row of cards by index numbers from 0 to 13

Code: (Select All)
_Title "Card Sprites by Index demo" 'bplus 2025-11-27
CardDeck = _LoadImage("Cards.png")
If CardDeck = -1 Then Print "Cards.png failed to load, bye!": End

' this set
SW = 72: SH = 96: SPRow = 14: SPCol = 4
Screen _NewImage(3 * SW, 3 * SH, 32)  ' magnify each card 3X's its pixel size

For index = 0 To 13
    Cls
    sheetx = (index Mod SPRow) * SW
    sheety = Int(index / SPRow) * SH
    _PutImage , CardDeck, 0, (sheetx, sheety)-Step(SW, SH)
    _Delay .5
Next

Change index = 14 to 27 and see the next row... 28 to 41 next and 42 to 55 for last.

zip with card sheet and code:


Attached Files
.zip   Cards off sprite sheet demo.zip (Size: 47.47 KB / Downloads: 25)
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#6
Nice.  Thanks for the tips.
Reply
#7
nice demonstration.  actually i downloaded the picture on the above forum post.  didn't get the zip file instead.  i was going to complain, "it doesn't work properly.  it doesn't align well."

if you live in the u.s.a.  happy thanksgiving folks.
Reply
#8
Thanks CMR and hsiangch_ong. BTW do index from 0 to 55 and see all the cards in order, why didn't I think of that originally? Wink

I might follow this up with code for doing cards ie assigning values, suits, points, shuffling, dealing... for card games.

I have code ready for gin rummy game worked out years ago awaiting card sprites.
I also have code assessing poker hands awaiting card sprites as well.

Yes happy Thanksgiving to all aboard!
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#9
+1 to CMR for thinking outside the box. I mean if you're like me and think 1 + 1 = bigger 1, then you need to get creative!

Pete Big Grin
Reply
#10
(11-27-2025, 10:52 PM)Pete Wrote: +1 to CMR for thinking outside the box. I mean if you're like me and think 1 + 1 = bigger 1, then you need to get creative!

Pete Big Grin

My solutions to simple problems involving math tend to be imaginatively over complicated.   Tongue
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  I have learned something new: how to get a run-time syntax error TDarcos 2 958 10-02-2024, 07:04 PM
Last Post: TDarcos
  A little bit of spark fun today TerryRitchie 2 834 05-18-2024, 12:59 AM
Last Post: bobalooie
  Loops alternate recursive ways bplus 10 2,013 02-01-2023, 02:05 PM
Last Post: Dimster

Forum Jump:


Users browsing this thread: 1 Guest(s)