My 'rhythm' UI attempt

Just set this up quickly, basic UI, etc. Play test first, camera gets set after 2 seconds, and arrows start going. Just have it set to 10 for testing purposes.

Any advice on how to clean it up? Or even how to have multiple arrows going at once and still have it work. I can only seem to get it working with 1 arrow on the screen at a time. Or how I could have set ‘tracks’, so some how call upon a module, that has various different tracks to, that don’t just pick ‘random’ arrows, where it’s a specific order and timed differently, etc.

Sequence Test.rbxl (23.7 KB)

Code as well (inside StarterGui)

-- NinjoOnline

wait(2)

local Camera = workspace.CurrentCamera

Camera.CameraType = Enum.CameraType.Scriptable
Camera.CFrame = CFrame.new(0, 0, 0)

local UserInputService = game:GetService('UserInputService')

local UI = script.Parent

local Bottom = UI:WaitForChild('Bottom')
local Scrolling = UI:WaitForChild('Scrolling')

local TileDirections = {'Left', 'Up', 'Right', 'Down'}

local CurrentTile, TilePosition

local function createTile(tileDirection)
	TilePosition = Bottom:FindFirstChild(tileDirection)
	if not TilePosition then return end
	
	local Tile = Instance.new('Frame')
	Tile.AnchorPoint = Vector2.new(0.5, 0.5)
	Tile.BackgroundTransparency = 1
	Tile.Position = UDim2.new(TilePosition.Position.X.Scale, 0, -2.5, 0)
	Tile.Size = UDim2.new(0.2, 0, 1, 0)
	
	local Text = Instance.new('TextLabel')
	Text.AnchorPoint = Vector2.new(0.5, 0.5)
	Text.BackgroundTransparency = 1
	Text.Position = UDim2.new(0.5, 0, 0.5, 0)
	Text.Size = UDim2.new(1, 0, 1, 0)
	Text.Font = Enum.Font.GothamBlack
	Text.TextColor3 = Color3.fromRGB(255, 255, 255)
	Text.TextScaled = true
	
	if tileDirection == 'Left' then
		Text.Text = '<'
	elseif tileDirection == 'Up' then
		Text.Text = '<'
		Text.Rotation = 90
	elseif tileDirection == 'Right' then
		Text.Text = '>'
	elseif tileDirection == 'Down' then
		Text.Text = '>'
		Text.Rotation = 90
	end
	
	local AspectRatio = Instance.new('UIAspectRatioConstraint')
	
	AspectRatio.Parent = Tile
	
	Text.Parent = Tile
	
	Tile.Parent = Scrolling
	
	CurrentTile = Tile

	spawn(function()
		Tile:TweenPosition(UDim2.new(TilePosition.Position.X.Scale, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 2, true)
		wait(2)
		
		Tile:Destroy()
	end)
end

local function checkPosition()
	if CurrentTile.Position.Y.Scale < 0.7 and CurrentTile.Position.Y.Scale > 0.3 then
		if CurrentTile.Position.Y.Scale < 0.55 and CurrentTile.Position.Y.Scale > 0.45 then
			print('Perfect')
		elseif CurrentTile.Position.Y.Scale < 0.6 and CurrentTile.Position.Y.Scale > 0.4 then
			print('Great')
		else
			print('Ok')	
		end
		
		CurrentTile:Destroy()
	else
		print('Miss')
	end
end

UserInputService.InputBegan:Connect(function(input, GPE)
	if GPE then return end
	
	if not CurrentTile then return end
	
	if input.KeyCode == Enum.KeyCode.Left then
		if TilePosition.Name == 'Left' then
			checkPosition()
		end
	end

	if input.KeyCode == Enum.KeyCode.Up then
		if TilePosition.Name == 'Up' then
			checkPosition()
		end
	end
		
	if input.KeyCode == Enum.KeyCode.Right then
		if TilePosition.Name == 'Right' then
			checkPosition()
		end
	end
		
	if input.KeyCode == Enum.KeyCode.Down then
		if TilePosition.Name == 'Down' then
			checkPosition()
		end
	end
end)

for i = 1, 10 do
	local RandomTileDirection = TileDirections[math.random(1, #TileDirections)]
	
	createTile(RandomTileDirection, i)
	wait(2)
end
2 Likes

Instead of having 4 different identical checks for each of the different keycodes, try checking if the keycode is the same as what’s the tile. For example:

UserInputService.InputBegan:Connect(function(input, GPE)
	if GPE then return end
	
	if not CurrentTile then return end
	
	if input.KeyCode.Name == TilePosition.Name then
		checkPosition()
	end
end

Other than that, it’s reasonably easy to follow and not too repetitive.

3 Likes