[LUASprites] Spritesheet generator with Lua output

LUASprites

Example Place | SpriteSheet Manager Module | PyPi | Source Code

Generate spritesheets and code at the same time

Why you should use sprite sheets

Sprite sheets increase the performance of your game, reduce loading/startup time, and use less memory overall (Which is especially beneficial on mobile devices). They are also a pain to create/handle/manage on Roblox. I wanted to compile images onto sprite sheets and then quickly reference them in code so that sprite sheets are just as easy to use as decals, thus the creation of this tool. As a side note, this tool can also be used to import gifs and there is an example at the Example Place

I have also modified Roblox’s Controller Image Library to be used as a general purpose sprite sheet manager for easy access/instantiation of images from your sprite sheets. A big organizational feature of this modified module is the concept of virtual sprite sheets. For example: you might have a lot of plant images that won’t fit onto a single 1024x1024(Roblox image size limit) sprite sheet. The python tool will split the sprites(plant images) onto multiple spritesheets but in your Lua code it can be considered the same sheet.

This is a CLI (command line interface) tool meaning that you run the program from your terminal (Mac OS/Linux) or command prompt (Windows). If you have never used a CLI before, don’t worry this tool is designed to be user friendly with verbose input and output.

SpriteSheet Manager API

SpriteSheetManager:GetImageButton(Sheet, Index)

Sheet is the sprite sheet where your image/sprite is on
Index is the name of the sprite you are
Returns an image button sized to the dimensions of the sprite

SpriteSheetManager:GetImageLabel(Sheet, Index)

Sheet is the sprite sheet where your image/sprite is on
Index is the name of the sprite you are
Returns an image label sized to the dimensions of the sprite

Installation

This is a python tool so python installed on your computer is required to use this tool. Download the latest version of python here.

The LUASprite project is stored on the PyPi repsoitory so it can be installed using pythons default pack manager, pip. Simply run pip3 install LUASprites in your terminal. On windows you may have to run your command prompt as an administrator to install.

How to use

Video walkthrough
^This was filmed on a Mac but the process should be nearly identical on a windows machine

Watching the video and looking at the example place will make the most sense for how to use this tool.

On windows you may have to close and open a new terminal window after installing LUASprites
Run this command in your terminal

$ luasprites [IMAGE_FOLDER_HERE]

Where the brackets are have a path to a folder containing all the images you want in the sprite sheet.

After that the application will ask you for a name and what kind of Lua output you want. Should be fairly user friendly. Upload the sprite sheet images found [IMAGE_FOLDER_HERE]/output to Roblox and put the asset ids in the appropriate variable found in the .lua script generated. Finally put the newly created module script inside the spritesheets folder (inside the SpriteSheet manager linked at the top of the post) and you have finished setting up your sprite sheet.

35 Likes

i need a little help :sweat_smile:
image_2022-08-22_163504420

did you install it by pip3 install LUASprites

And one more thing, type cd <pathtotheparentof(loadingimahes)> before running that command, as administrator prompt by default goes to system32 folder.

1 Like

I found that on windows sometimes you have to close and open a new terminal window after installation

i already installed it, but its not making me able to use it

Also the command is luasprites you forgot the s at the end

1 Like

so make sure its the full path to the loadingImages folder.

1 Like

Thank you so much man. I’m making a street fighter replica and this is perfect.

1 Like

Actually can you order them cause like my sprites are not in order (alphabetically)…

They’re in order of size of the image size.x * size.y.

Does it matter very much to make them alphabetical? The output is a hash map which is not stored or accessed in any particular order so I don’t see what the benefit would be.

1 Like

Well, yeah cause when you’re looping through different sprites, instead of having to select each individual sprite you could just repeat iterating to the next sprite instead.

Does it matter very much to make them alphabetical? The output is a hash map which is not stored or accessed in any particular order so I don’t see what the benefit would be.

That means that (hash maps)/dictionaries are not stored like arrays where if you run a loop the order is always 1, 2, 3, …, n. Dictionaries work by hashing the key(the string that you set the data equal to) and then mapping that onto an internal array data structure(Usually a modified array of some sort). Calling the pairs method does not iterate through dictionary based on when the key was added but how it is mapped. From an external position this makes it seem as if looping through the dictionary is in completely random order, and for most cases it is.

So making the list alphabetical would not do you any benefit, however we can still achieve what you want by using another hash map.

local AnimationDataTable = GetSpriteSheetMethodOrSomething()

local AnimationLengths = {-- Name = (NumberOfFramesInAnimation)
	turn = 7,
	forward = 6,
	... 
}

local function PlayAnimation(Animation)
	local FrameLength = AnimationLengths[Animation]
	for i = 1,FrameLength do
		local AnimationDataKey = string.format("%s (%d)", Animation, i)
		local AnimationData = AnimationDataTable[AnimationDataKey]
		--Change the image ImageRectOffset and ImageRectSize based on size
	end
end



3 Likes

I updated the example place with a different use case for the project. (Playing Gifs)

Setting up gifs to play in studio only takes a couple of mins with this tool. All you have to do is extract the gif into its source images and use the LUASprites tool to load it in.

Here is a tweet video I posted if you don’t want to check out the example place.
https://twitter.com/roblox_reteach/status/1642054455288815620

Do these images get uploaded to your decals and moderated? Is there a risk of moderation when using this (as in the AI material generator)?

Yes, they got moderated. At the end of the day you’re uploading images that are subject to Roblox’s moderation policies, so keep them in mind if you have small text in your images.

Building tree...
Spritesheet 0 will be [1024, 1024] pixels
Traceback (most recent call last):
  File "D:\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "D:\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 386, in _make_request
    self._validate_conn(conn)
  File "D:\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 1042, in _validate_conn
    conn.connect()
  File "D:\Python\Python310\lib\site-packages\urllib3\connection.py", line 414, in connect
    self.sock = ssl_wrap_socket(
  File "D:\Python\Python310\lib\site-packages\urllib3\util\ssl_.py", line 449, in ssl_wrap_socket
    ssl_sock = _ssl_wrap_socket_impl(
  File "D:\Python\Python310\lib\site-packages\urllib3\util\ssl_.py", line 493, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "D:\Python\Python310\lib\ssl.py", line 513, in wrap_socket
    return self.sslsocket_class._create(
  File "D:\Python\Python310\lib\ssl.py", line 1071, in _create
    self.do_handshake()
  File "D:\Python\Python310\lib\ssl.py", line 1342, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:997)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Python\Python310\lib\site-packages\requests\adapters.py", line 489, in send
    resp = conn.urlopen(
  File "D:\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 787, in urlopen
    retries = retries.increment(
  File "D:\Python\Python310\lib\site-packages\urllib3\util\retry.py", line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.countapi.xyz', port=4JUdGzvrMFDWrUUwY3toJATSeNwjn54LkCnKBPRzDuhzi5vSepHfUckJNxRL2gjkNrSqtCoRUrEDAgRwsQvVCjZbRyFTLRNyDmT1a1boZVSSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:997)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Python\Python310\Scripts\luasprites-script.py", line 33, in <module>
    sys.exit(load_entry_point('LUASprites==0.0.23', 'console_scripts', 'luasprites')())
  File "D:\Python\Python310\lib\site-packages\spritegen\cli.py", line 295, in main
    packImages(trees,name, outputFolder)
  File "D:\Python\Python310\lib\site-packages\spritegen\cli.py", line 115, in packImages
    usageTrack("imageCreated")
  File "D:\Python\Python310\lib\site-packages\spritegen\cli.py", line 279, in usageTrack
    requests.get('https://api.countapi.xyz/hit/SpriteSheetGenerator_Deploy1/' + usecase)
  File "D:\Python\Python310\lib\site-packages\requests\api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "D:\Python\Python310\lib\site-packages\requests\api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "D:\Python\Python310\lib\site-packages\requests\sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
  File "D:\Python\Python310\lib\site-packages\requests\sessions.py", line 701, in send
    r = adapter.send(request, **kwargs)
  File "D:\Python\Python310\lib\site-packages\requests\adapters.py", line 563, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.countapi.xyz', port=4JUdGzvrMFDWrUUwY3toJATSeNwjn54LkCnKBPRzDuhzi5vSepHfUckJNxRL2gjkNrSqtCoRUrEDAgRwsQvVCjZbRyFTLRNyDmT1a1boZVSSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:997)')))

Very useful application, but your stupid tracking API throws an exception which disables all the other features…
Remove it.
For anyone having the same issue : in cli.py remove any usageTrack(...) and the function usageTrack

1 Like