Roblox Starling Spritesheets

(This was originally an FNF tutorial)
I decided to take the tutorial down, for the following reasons:

  1. FNF has a new license for it’s assets, and I want to respect the license.
  2. this was a low effort tutorial.
  3. I don’t feel good about teaching people how to copy a game.

However, there was some leftover code that isn’t part of the game that some people might find useful.

This is a sprite class that uses ImageLabels to display Starling-formatted SpriteSheet and XML pairs. This might be useful for 2D objects.

29 Likes

Glad part 2 is finally out! Though, Are you going to make the place you did the tutorial in uncopylocked? Copy and pasting all of those modules from part 1 and part 2 seems rather tiresome.

Thanks!

2 Likes

If it becomes really annoying to everyone who reads it, I guess ill do that, but for now I kinda want people to try to actually read the modules instead of just copying a place. I get what you are saying though, there are so many things, so I can see how tiresome it is lol.

4 Likes

Oh, speaking of… There’s some missing functions in the Util module that you used in this post, Those mainly being Util.Lerp and Util.GetGetXPositionForNoteData, those are the 2 functions I found missing from the Util module, or I’m just blind.

1 Like

As @jamesderrman was saying the tutorial is pretty confusing at least for me and Util.Lerp and Util.GetGetXPositionForNoteData are missing from the Util module

1 Like

Honestly not bad of a tutorial!
It’s really similar to the process I’ve had to go thru the development of my FNF engine, so +1 from me!
Only issue is the sprite not supporting proper centering when it relates to other sprites like the character sprites.

3 Likes

Wow, thanks!

Oh yeah, and about the sprite positioning thing, that is probably something that I will work on and ill put an update or something. I think that it has something to do with the XML values that have more data (like 4 extra values), but ill have to test.

(probably updates in a new post because I hit the 50000 limit exactly.)

EDIT: Wow, I tried your engine, and the gameplay beats every single FNF game on Roblox by a mile! Props to you for getting it that good!

2 Likes

Oh no, Very sorry, I’ll fix it ASAP!

1 Like

Sorry about that! I probably deleted it on accident because I was hitting the 50000 character limit
Here is Util:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Source = ReplicatedStorage:WaitForChild("Source")

local Util = {
	--\\ FNF Screen size: https://github.com/FunkinCrew/Funkin/blob/master/Project.xml
	ScreenSize = Vector2.new(1280, 720); --\\ FNF is in 720p lol
	--\\ AspectRatio = 16:9

	NoteWidth = (166 * 0.7); --\\ all notes are scaled down by 0.7, so NoteWidth is the original pixel size of every note scaled down by 0.7.

	--\\ For keybinds
	KeybindNames = {
		[1] = "Left";
		[2] = "Down";
		[3] = "Up";
		[4] = "Right";
	};

	--\\ For notes
	NoteDataNames = {
		[1] = "Left";
		[2] = "Down";
		[3] = "Up";
		[4] = "Right";
	};
}

function Util.GetXPositionForNoteData(NoteData, ManualSide, PlayerSide)
	NoteData += 1 --\\ Shift it over one for roblox

	if PlayerSide == 2 then
		--\\ Normal PlayerSide
		--\\ Shenanigans for Notes.
		NoteData -= 1 --\\ Shift it back over because we are using modulo

		if ManualSide == 2 then --\\ Player2
			return (Util.ScreenSize.X - ((5 - ((NoteData % 4) + 1)) * (Util.NoteWidth)))
		end

		if ManualSide == 1 then --\\ Player1
			return (((NoteData % 4) + 1) * (Util.NoteWidth))
		end
	else
		--\\ Flip all if PlayerSide is flipped.
		--\\ Shenanigans for Notes.
		NoteData -= 1 --\\ Shift it back over because we are using modulo

		if ManualSide == 1 then --\\ Player2
			return (Util.ScreenSize.X - ((5 - ((NoteData % 4) + 1)) * (Util.NoteWidth)))
		end

		if ManualSide == 2 then --\\ Player1
			return (((NoteData % 4) + 1) * (Util.NoteWidth))
		end
	end

	return 0
end

function Util.Lerp(start, goal, t)
	return start + (goal - start) * t
end

function Util.GetStrumX(StrumIndex)
	StrumIndex += 1

	--\\ For strums
	if StrumIndex > 4 then --\\ Player2
		--\\ get screensize-x and subtract (5-(index-4) * NoteWidth)
		--\\ it's easier to understand this after you look at the one for the opponent
		return (Util.ScreenSize.X - ((5 - (StrumIndex - 4)) * (Util.NoteWidth)))
	end

	if StrumIndex < 5 then --\\ Player1
		--\\ just the product of the index and the NoteWidth
		return (StrumIndex * (Util.NoteWidth))
	end

	return 0
end

return Util
1 Like

That is totally my fault. Sorry for the late response, Here is Util:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Source = ReplicatedStorage:WaitForChild("Source")

local Util = {
	--\\ FNF Screen size: https://github.com/FunkinCrew/Funkin/blob/master/Project.xml
	ScreenSize = Vector2.new(1280, 720); --\\ FNF is in 720p lol
	--\\ AspectRatio = 16:9

	NoteWidth = (166 * 0.7); --\\ all notes are scaled down by 0.7, so NoteWidth is the original pixel size of every note scaled down by 0.7.

	--\\ For keybinds
	KeybindNames = {
		[1] = "Left";
		[2] = "Down";
		[3] = "Up";
		[4] = "Right";
	};

	--\\ For notes
	NoteDataNames = {
		[1] = "Left";
		[2] = "Down";
		[3] = "Up";
		[4] = "Right";
	};
}

function Util.GetXPositionForNoteData(NoteData, ManualSide, PlayerSide)
	NoteData += 1 --\\ Shift it over one for roblox

	if PlayerSide == 2 then
		--\\ Normal PlayerSide
		--\\ Shenanigans for Notes.
		NoteData -= 1 --\\ Shift it back over because we are using modulo

		if ManualSide == 2 then --\\ Player2
			return (Util.ScreenSize.X - ((5 - ((NoteData % 4) + 1)) * (Util.NoteWidth)))
		end

		if ManualSide == 1 then --\\ Player1
			return (((NoteData % 4) + 1) * (Util.NoteWidth))
		end
	else
		--\\ Flip all if PlayerSide is flipped.
		--\\ Shenanigans for Notes.
		NoteData -= 1 --\\ Shift it back over because we are using modulo

		if ManualSide == 1 then --\\ Player2
			return (Util.ScreenSize.X - ((5 - ((NoteData % 4) + 1)) * (Util.NoteWidth)))
		end

		if ManualSide == 2 then --\\ Player1
			return (((NoteData % 4) + 1) * (Util.NoteWidth))
		end
	end

	return 0
end

function Util.Lerp(start, goal, t)
	return start + (goal - start) * t
end

function Util.GetStrumX(StrumIndex)
	StrumIndex += 1

	--\\ For strums
	if StrumIndex > 4 then --\\ Player2
		--\\ get screensize-x and subtract (5-(index-4) * NoteWidth)
		--\\ it's easier to understand this after you look at the one for the opponent
		return (Util.ScreenSize.X - ((5 - (StrumIndex - 4)) * (Util.NoteWidth)))
	end

	if StrumIndex < 5 then --\\ Player1
		--\\ just the product of the index and the NoteWidth
		return (StrumIndex * (Util.NoteWidth))
	end

	return 0
end

return Util
1 Like

suprised you are managing to port a game into Roblox, exciting to see where you can go with this, even though it is just FNF

I watch your career in great interest :smile:

2 Likes

Also the like end part is kind of confusing I liked the part 1 tutorial style more in my opinion!

1 Like

For very long songs, the JSON should be compressed, and removed of all it’s spaces and new lines. If it’s small enough, it could be put in a StringValue. But to reduce logic, it should be kept in a module script.

I can’t comment on anything else in the tutorial, I have something called ‘laziness’.

4 Likes

Thanks! Ill remember that from now on!

Sorry about the confusion! This was probably the hardest part to manage, as I had to delete parts of it after I overshot the 50000 character limit.

3 Likes

you could atleast show where all the scripts go

1 Like

I don’t understand what you are asking. Can you clarify?

1 Like

Not all codes have been shown where they go but it doesn’t matter i just used edited RoFunk

Great tutorial, but how would you check a section that is currently active?
I cant find a way to use mustHitSection value within charts

Here is my version of this that I have worked on:

Features Include:

  • OnSectionHit (this function fires every section and checks the current mustHitSection)
  • Displayable Rating and lower Rating systems can actually be hit
  • Notes actually get destroyed now if you don’t hit them (noticed that instances would just pile up when you miss a note)
  • Psych Engine Events
  • Downscroll Support
  • Opponent Note Light Up
  • and a bunch of other misc things.

fnf game edit.rbxm (244.2 KB)
You can check out my group (The Game Recreators) to see what I have done using this edited version.

5 Likes