How do I iterate through a spritesheet?

Searched the forum, answers are extremely unclear to me. I tried doing it myself, I got completely lost and frustrated. I applied the solutions found on the forum and my image keeps ending up getting distorted.


^ Sprite sheet. Dimensions are 2256x752 in pixels.

7 Likes

Usually this would involve some sort of multiplication.
E.G:
(n being the sprite number, starts at 0 in this code)

Image.ImageRectOffset = Vector2.new(n*SpriteSizeX,0)

But, this would not work for the Y axis, and you would add on a function that automatically adds to the y size and takes from the x size for every line:

local NumberX = n*SpriteSizeX
local n2 = 0
while NumberX > MaximumX do
    NumberX = NumberX - MaximumX
    n2 = n2 + 1
end
local NumberY = n2*SpriteSizeY
Image.ImageRectOffset =Vector2.new(NumberX,NumberY)

That’s the rough idea - you could do it a bit more efficiently with some math.

The main thing you need to understand is that you can multiply the sprite number by the size and you can get the new position.
1*24 = 24 so the position is the theoretical second sprite
2*24 = 48 so it’s the third sprite
0*24 is the first sprite (since the anchor point of ImageRectOffset is on the left).

Sorry I’m on mobile so this may not be as clear as it could be.

4 Likes

First, you might know how to do this but are having an issue because your image is not the same size you uploaded it as. The maximum size for any image uploaded to Roblox is 1024x1024! I even uploaded your image to see what Roblox resized it to, and It’s resized to 1023x341.

You are either going to need multiple spritesheets, fewer segments in your circular loading bar, or smaller resolution sprites.


To iterate through a spritesheet you need to know three things:

  • The size of each image in the sheet
  • How the sheet is organized
  • How many sprites there are

To get a single image from a spritesheet you need to know two things:

  • What pixel position is the top left of the image
  • The size of the image

In this case:

  • Each image is 188x188 big.
  • The sheet puts 12 sprites on a single line going to the right, then repeats for the next line. There is no padding (empty pixels) between each sprite
  • There are 36 sprites.

Knowing this, we can do the following:

local function getSpritePosition(spriteNumber)
	local row = math.floor((spriteNumber - 1)/12)
	-- numbers 1-12 will return 0, numbers 13-24 will return 1, etc.
	-- math.floor returns the number without any decimal
	local column = (spriteNumber - 1)%12
	-- 1 returns 0, 2 returns 1, 3 returns 2, 12 returns 11, etc.
	-- 13 returns 0, 14 returns 1, 15 returns 2, 24 returns 11, etc.
	-- % gets the remainder if you divide the number on the left by the one on the right
	--  for example, 10%6 is 4. 4%6 is also 4. 16%6 is 4 too.
	local position = Vector2.new(row*188, column*188)
	return position
end

---

gui.ImageRectSize = Vector2.new(188, 188)

-- Go through it once:
for i = 1, 36 do
	gui.ImageRectOffset = getSpritePosition(i)
	wait(0.1)
end

-- Go through it repeatedly:
local i = 0
while true do
	gui.ImageRectOffset = getSpritePosition(i%36 + 1)
	i = i + 1
	-- the remainder should always be between (and including) 0 and 35
	-- we can add 1 to that and get 1 through 36, regardless of how big i is.
	wait(0.1)
end
10 Likes

https://devforum.roblox.com/t/im-having-trouble-making-a-sprite-sheet-for-a-circular-progress-bar/43224/3?u=as8d - this looks pretty similar to what you’re trying to do. :slightly_smiling_face:

Though, if your goal is to make your own, Corecii’s reply should suffice.

2 Likes

Sorry to make you guys write out the code. I’m still pretty basic with this kind of stuff and am probably at a basic level rather than member. :neutral_face:

I’ll see if I can apply these solutions later. I’ll need to use this as a reference point for when I actually start making some of my own, if I even can.

You could always use two for loops which you may find easier to read. You can do this in more efficient ways but on this sort of time scale it’s not that important to have two variables vs one.

Another, simpler option would be if you just made the sprite sheet really long. The advantage to having a tiled sprite sheet is typically that the tiled ones are powers of 2 and can fit into whatever simplistic GPU your 90s console is running. It’s not really important to do that anymore, so it might be worth it just to run left to right with this instead of having multiple columns.

local imagewidth = 2256
local imageheight = 752
local rows = 4
local columns = 12
local spritewidth = imagewidth/columns
local spriteheight = imagewidth/rows

--This should be the relevant image label.
--The image label should be imagewidth * imageheight
--and embedded into a frame that is the size of one sprite
--the frame should have clips descendents on

local imagelabel

--Replace this with a relevant loop structure
while looping do
	for row = 0, rows do
		for column = 0, columns do
			local offset = UDim2.new(0, spritewidth*column, 0, spriteheight*row)
			sprite.Position = offset
			--Some kind of delay goes here. If you're using a while loop a wait
			--is probably what you want
			wait()
		end
	end
end

Edit: I forgot to multiply stuff

3 Likes

It’s really up to you how you do it, but if I were you I’d find the size of each image in the sprite sheet as well as how many there are per row, then form an equation for each image that goes through each row at whichever speed you want. I personally think you should try and solve this yourself for the sake of learning but I’ll put you on the right path.

So let’s say that the image for each sprite is 50x50 and there’s 10 in a row as well as 5 rows(perhaps even just 9 at the last row). This means that each row would be 500 pixels long and 50 pixels tall. So you can loop through each image by translating the spritesheet by 50 pixels until you get to the last image in the row(or the tenth image) before you translate it back to the beginning image but 50 pixels lower than the last row. Now say the last row is only 9 images rather than 10, well in this case you would only translate it 9 times that row and end it there.

If you really need a coded example I can try and give you one.

2 Likes