-- FNF Recreation --made by yourstraight_idk local Players = game:GetService("Players") local UIS = game:GetService("UserInputService") local RunService = game:GetService("RunService") local player = Players.LocalPlayer -- DEFAULT SETTINGS local NOTE_SPEED = 380 local NOTE_COLOR = Color3.fromRGB(255,0,0) local HIT_WINDOW = 55 local NOTE_SIZE = 48 local BUTTON_SIZE = 60 -- RANDOM DELAY SETTINGS local MIN_DELAY = 0.4 local MAX_DELAY = 1.5 local MULTI_NOTE_DELAY = 0.18 -- GAME STATE local score = 0 local combo = 0 local misses = 0 local notes = {} local playing = false local paused = false local mode = "Easy" local resumeTimer = 0 local isResuming = false local spawnTimer = 0 local spawnDelay = math.random(MIN_DELAY * 100, MAX_DELAY * 100) / 100 local gameTime = 120 local timerRunning = false local notesHit = 0 local notesSpawned = 0 -- HIT SOUND local hitSoundId = "" local hitSound = Instance.new("Sound") hitSound.Parent = player:WaitForChild("PlayerGui") hitSound.Volume = 1 -- GUI local gui = Instance.new("ScreenGui") gui.Parent = player.PlayerGui gui.ResetOnSpawn = false -- ========================= -- RESULTS UI -- ========================= local resultFrame = Instance.new("Frame", gui) resultFrame.Size = UDim2.fromScale(0.4,0.5) resultFrame.Position = UDim2.fromScale(0.3,0.25) resultFrame.BackgroundColor3 = Color3.fromRGB(20,20,20) resultFrame.Visible = false Instance.new("UICorner", resultFrame).CornerRadius = UDim.new(0,20) local resultTitle = Instance.new("TextLabel", resultFrame) resultTitle.Size = UDim2.fromScale(1,0.2) resultTitle.Position = UDim2.fromScale(0,0) resultTitle.BackgroundTransparency = 1 resultTitle.Text = "RESULTS" resultTitle.TextScaled = true resultTitle.TextColor3 = Color3.new(1,1,1) local resultText = Instance.new("TextLabel", resultFrame) resultText.Size = UDim2.fromScale(1,0.6) resultText.Position = UDim2.fromScale(0,0.2) resultText.BackgroundTransparency = 1 resultText.TextScaled = true resultText.TextColor3 = Color3.new(1,1,1) resultText.Text = "" local replayBtn = Instance.new("TextButton", resultFrame) replayBtn.Size = UDim2.fromScale(0.5,0.15) replayBtn.Position = UDim2.fromScale(0.25,0.8) replayBtn.Text = "REPLAY" replayBtn.TextScaled = true replayBtn.BackgroundColor3 = Color3.fromRGB(120,120,120) -- ========================= -- MENU SCREEN -- ========================= local menu = Instance.new("Frame", gui) menu.Size = UDim2.fromScale(0.5,0.6) menu.Position = UDim2.fromScale(0.25,0.2) menu.BackgroundColor3 = Color3.fromRGB(20,20,20) menu.Visible = false Instance.new("UICorner", menu).CornerRadius = UDim.new(0,20) local menuTitle = Instance.new("TextLabel", menu) menuTitle.Size = UDim2.fromScale(1,0.25) menuTitle.Position = UDim2.fromScale(0,0) menuTitle.BackgroundTransparency = 1 menuTitle.Text = "RHYTHM GAME" menuTitle.TextScaled = true menuTitle.TextColor3 = Color3.new(1,1,1) local playBtn = Instance.new("TextButton", menu) playBtn.Size = UDim2.fromScale(0.6,0.15) playBtn.Position = UDim2.fromScale(0.2,0.35) playBtn.Text = "PLAY" playBtn.TextScaled = true playBtn.BackgroundColor3 = Color3.fromRGB(120,120,120) local settingsBtn = Instance.new("TextButton", menu) settingsBtn.Size = UDim2.fromScale(0.6,0.15) settingsBtn.Position = UDim2.fromScale(0.2,0.55) settingsBtn.Text = "SETTINGS" settingsBtn.TextScaled = true settingsBtn.BackgroundColor3 = Color3.fromRGB(120,120,120) local menuBackBtn = Instance.new("TextButton", menu) menuBackBtn.Size = UDim2.fromScale(0.6,0.15) menuBackBtn.Position = UDim2.fromScale(0.2,0.75) menuBackBtn.Text = "BACK TO GAME" menuBackBtn.TextScaled = true menuBackBtn.BackgroundColor3 = Color3.fromRGB(120,120,120) -- ========================= -- SETTINGS SCREEN -- ========================= local settings = Instance.new("Frame", gui) settings.Size = UDim2.fromScale(0.5,0.6) settings.Position = UDim2.fromScale(0.25,0.2) settings.BackgroundColor3 = Color3.fromRGB(20,20,20) settings.Visible = false Instance.new("UICorner", settings).CornerRadius = UDim.new(0,20) local settingsTitle = Instance.new("TextLabel", settings) settingsTitle.Size = UDim2.fromScale(1,0.25) settingsTitle.Position = UDim2.fromScale(0,0) settingsTitle.BackgroundTransparency = 1 settingsTitle.Text = "SETTINGS" settingsTitle.TextScaled = true settingsTitle.TextColor3 = Color3.new(1,1,1) -- Note Speed local speedLabel = Instance.new("TextLabel", settings) speedLabel.Size = UDim2.fromScale(0.9,0.12) speedLabel.Position = UDim2.fromScale(0.05,0.3) speedLabel.BackgroundTransparency = 1 speedLabel.Text = "Note Speed: "..NOTE_SPEED speedLabel.TextScaled = true speedLabel.TextColor3 = Color3.new(1,1,1) local speedUp = Instance.new("TextButton", settings) speedUp.Size = UDim2.fromScale(0.2,0.1) speedUp.Position = UDim2.fromScale(0.7,0.42) speedUp.Text = "+" speedUp.TextScaled = true speedUp.BackgroundColor3 = Color3.fromRGB(120,120,120) local speedDown = Instance.new("TextButton", settings) speedDown.Size = UDim2.fromScale(0.2,0.1) speedDown.Position = UDim2.fromScale(0.1,0.42) speedDown.Text = "-" speedDown.TextScaled = true speedDown.BackgroundColor3 = Color3.fromRGB(120,120,120) speedUp.MouseButton1Click:Connect(function() NOTE_SPEED += 20 speedLabel.Text = "Note Speed: "..NOTE_SPEED end) speedDown.MouseButton1Click:Connect(function() if NOTE_SPEED > 100 then NOTE_SPEED -= 20 speedLabel.Text = "Note Speed: "..NOTE_SPEED end end) -- Note Color Buttons local colorLabel = Instance.new("TextLabel", settings) colorLabel.Size = UDim2.fromScale(0.9,0.12) colorLabel.Position = UDim2.fromScale(0.05,0.55) colorLabel.BackgroundTransparency = 1 colorLabel.Text = "Note Color" colorLabel.TextScaled = true colorLabel.TextColor3 = Color3.new(1,1,1) local colors = { {Color3.fromRGB(255,0,0), "RED"}, {Color3.fromRGB(0,255,0), "GREEN"}, {Color3.fromRGB(0,0,255), "BLUE"}, {Color3.fromRGB(255,255,0), "YELLOW"}, {Color3.fromRGB(255,0,255), "PINK"}, {Color3.fromRGB(0,255,255), "CYAN"}, {Color3.fromRGB(255,128,0), "ORANGE"}, {Color3.fromRGB(128,0,255), "PURPLE"} } for i, v in ipairs(colors) do local btn = Instance.new("TextButton", settings) btn.Size = UDim2.fromScale(0.2,0.1) btn.Position = UDim2.fromScale(0.1 + ((i-1)%4)*0.3, 0.67 + math.floor((i-1)/4)*0.12) btn.Text = v[2] btn.TextScaled = true btn.BackgroundColor3 = v[1] btn.MouseButton1Click:Connect(function() NOTE_COLOR = v[1] end) end -- HIT SOUND SETTING local soundLabel = Instance.new("TextLabel", settings) soundLabel.Size = UDim2.fromScale(0.9,0.12) soundLabel.Position = UDim2.fromScale(0.05,0.82) soundLabel.BackgroundTransparency = 1 soundLabel.Text = "Hit Sound ID:" soundLabel.TextScaled = true soundLabel.TextColor3 = Color3.new(1,1,1) local soundBox = Instance.new("TextBox", settings) soundBox.Size = UDim2.fromScale(0.6,0.12) soundBox.Position = UDim2.fromScale(0.05,0.92) soundBox.PlaceholderText = "Paste Sound ID here" soundBox.TextScaled = true soundBox.TextColor3 = Color3.new(1,1,1) soundBox.BackgroundColor3 = Color3.fromRGB(60,60,60) local soundApply = Instance.new("TextButton", settings) soundApply.Size = UDim2.fromScale(0.3,0.12) soundApply.Position = UDim2.fromScale(0.68,0.92) soundApply.Text = "Apply" soundApply.TextScaled = true soundApply.BackgroundColor3 = Color3.fromRGB(120,120,120) soundApply.MouseButton1Click:Connect(function() local id = soundBox.Text if id ~= "" then hitSoundId = id hitSound.SoundId = "rbxassetid://" .. hitSoundId end end) local backToMenu = Instance.new("TextButton", settings) backToMenu.Size = UDim2.fromScale(0.6,0.15) backToMenu.Position = UDim2.fromScale(0.2,0.85) backToMenu.Text = "BACK TO MENU" backToMenu.TextScaled = true backToMenu.BackgroundColor3 = Color3.fromRGB(120,120,120) backToMenu.MouseButton1Click:Connect(function() settings.Visible = false menu.Visible = true end) -- ========================= -- GAME SCREEN -- ========================= local main = Instance.new("Frame", gui) main.Size = UDim2.fromScale(0.45, 0.7) main.Position = UDim2.fromScale(0.275, 0.15) main.BackgroundColor3 = Color3.fromRGB(20,20,20) main.Visible = false Instance.new("UICorner", main).CornerRadius = UDim.new(0,20) -- DRAGGABLE TOGGLE BUTTON local toggle = Instance.new("TextButton", gui) toggle.Size = UDim2.fromOffset(64,64) toggle.Position = UDim2.fromScale(0.02,0.45) toggle.Text = "🎵" toggle.TextScaled = true toggle.BackgroundColor3 = Color3.fromRGB(255,90,90) toggle.Active = true toggle.Draggable = true Instance.new("UICorner", toggle).CornerRadius = UDim.new(1,0) Instance.new("UIAspectRatioConstraint", toggle).AspectRatio = 1 -- TOGGLE BUTTON (ONLY HIDES/SHOWS GAME UI) toggle.MouseButton1Click:Connect(function() main.Visible = not main.Visible menu.Visible = false settings.Visible = false resultFrame.Visible = false -- START GAME IF SHOW BUTTON PRESS if main.Visible and not playing then playing = true timerRunning = true end end) -- INFO local info = Instance.new("TextLabel", main) info.Size = UDim2.fromScale(1,0.08) info.BackgroundTransparency = 1 info.TextColor3 = Color3.new(1,1,1) info.TextScaled = true -- MODE LABEL local modeLabel = Instance.new("TextLabel", main) modeLabel.Size = UDim2.fromScale(1,0.08) modeLabel.Position = UDim2.fromScale(0,0.08) modeLabel.BackgroundTransparency = 1 modeLabel.TextColor3 = Color3.new(1,1,1) modeLabel.TextScaled = true modeLabel.Text = "Mode: Easy" -- RESET FUNCTION (CALLED WHEN MODE CHANGES) local function resetGame() score = 0 combo = 0 misses = 0 notesHit = 0 notesSpawned = 0 gameTime = 120 timerRunning = true paused = false isResuming = false for _, v in ipairs(notes) do v.obj:Destroy() end notes = {} end -- START GAME FUNCTION local function startGame() playing = true timerRunning = true paused = false isResuming = false end -- PAUSE BUTTON local pauseBtn = Instance.new("TextButton", main) pauseBtn.Size = UDim2.fromScale(0.2,0.08) pauseBtn.Position = UDim2.fromScale(0.4,0.18) pauseBtn.Text = "Pause" pauseBtn.TextScaled = true pauseBtn.BackgroundColor3 = Color3.fromRGB(120,120,120) pauseBtn.MouseButton1Click:Connect(function() if isResuming then return end if paused then isResuming = true resumeTimer = 4 pauseBtn.Text = "Resuming..." else paused = true pauseBtn.Text = "Resume" for _, v in ipairs(notes) do v.obj:Destroy() end notes = {} end end) -- MODE BUTTONS local function createModeButton(text, pos) local btn = Instance.new("TextButton", main) btn.Size = UDim2.fromScale(0.25,0.08) btn.Position = pos btn.Text = text btn.TextScaled = true btn.BackgroundColor3 = Color3.fromRGB(80,80,80) btn.MouseButton1Click:Connect(function() mode = text modeLabel.Text = "Mode: "..text resetGame() end) return btn end createModeButton("Easy", UDim2.fromScale(0.05,0.26)) createModeButton("Medium", UDim2.fromScale(0.375,0.26)) createModeButton("Hard", UDim2.fromScale(0.7,0.26)) createModeButton("Extreme", UDim2.fromScale(0.375,0.34)) -- MENU BUTTON local menuBtn = Instance.new("TextButton", main) menuBtn.Size = UDim2.fromScale(0.25,0.08) menuBtn.Position = UDim2.fromScale(0.7,0.34) menuBtn.Text = "MENU" menuBtn.TextScaled = true menuBtn.BackgroundColor3 = Color3.fromRGB(120,120,120) menuBtn.MouseButton1Click:Connect(function() menu.Visible = true main.Visible = false settings.Visible = false resultFrame.Visible = false end) -- HIT LINE local hitLine = Instance.new("Frame", main) hitLine.Size = UDim2.fromScale(1,0.02) hitLine.Position = UDim2.fromScale(0,0.75) hitLine.BackgroundColor3 = Color3.new(1,1,1) -- LANES + WASD BUTTONS local lanes = {} local keys = {"A","S","W","D"} for i = 1,4 do local lane = Instance.new("Frame", main) lane.Size = UDim2.fromScale(0.25,1) lane.Position = UDim2.fromScale((i-1)*0.25,0) lane.BackgroundTransparency = 1 lanes[i] = lane local btn = Instance.new("TextButton", main) btn.Size = UDim2.fromOffset(BUTTON_SIZE,BUTTON_SIZE) btn.Position = UDim2.fromScale((i-1)*0.25 + 0.125,0.9) btn.AnchorPoint = Vector2.new(0.5,0.5) btn.Text = keys[i] btn.TextScaled = true btn.TextColor3 = Color3.new(1,1,1) btn.BackgroundColor3 = Color3.fromRGB(60,60,60) Instance.new("UICorner", btn).CornerRadius = UDim.new(1,0) Instance.new("UIAspectRatioConstraint", btn).AspectRatio = 1 btn.MouseButton1Click:Connect(function() pressLane(i) end) end -- SPAWN NOTE AT A HEIGHT function spawnNote(laneIndex) local note = Instance.new("Frame") note.Size = UDim2.fromOffset(NOTE_SIZE,NOTE_SIZE) -- SPAWN height note.Position = UDim2.fromScale(0.5,-1) note.AnchorPoint = Vector2.new(0.5,0) note.BackgroundColor3 = NOTE_COLOR note.Parent = lanes[laneIndex] Instance.new("UICorner", note).CornerRadius = UDim.new(1,0) Instance.new("UIAspectRatioConstraint", note).AspectRatio = 1 table.insert(notes,{ obj = note, lane = laneIndex }) notesSpawned += 1 end -- SPAWN MULTIPLE NOTES WITH DELAY BETWEEN EACH NOTE function spawnMultipleNotes() local amount = 1 if mode == "Easy" then amount = 1 elseif mode == "Medium" then amount = 2 elseif mode == "Hard" then amount = 3 elseif mode == "Extreme" then amount = 4 end local usedLanes = {} for i = 1, amount do local lane = math.random(1,4) while usedLanes[lane] do lane = math.random(1,4) end usedLanes[lane] = true spawnNote(lane) if i < amount then wait(MULTI_NOTE_DELAY) end end end -- HIT CHECK (closest note) function pressLane(lane) if paused then return end local closestNote = nil local closestDist = math.huge local closestIndex = nil for i, data in ipairs(notes) do if data.lane == lane then local dy = math.abs(data.obj.AbsolutePosition.Y - hitLine.AbsolutePosition.Y) if dy < closestDist then closestDist = dy closestNote = data.obj closestIndex = i end end end if closestNote and closestDist <= HIT_WINDOW then closestNote:Destroy() table.remove(notes, closestIndex) score += 100 combo += 1 notesHit += 1 -- PLAY HIT SOUND if hitSoundId ~= "" then hitSound:Play() end end end -- KEYBOARD INPUT local keyMap = { A = 1, S = 2, W = 3, D = 4 } UIS.InputBegan:Connect(function(input,gp) if gp or not playing then return end local lane = keyMap[input.KeyCode.Name] if lane then pressLane(lane) end end) -- REPLAY BUTTON replayBtn.MouseButton1Click:Connect(function() resetGame() resultFrame.Visible = false main.Visible = true menu.Visible = false settings.Visible = false playing = true timerRunning = true end) -- MENU BACK BUTTON menuBackBtn.MouseButton1Click:Connect(function() menu.Visible = false main.Visible = true end) -- PLAY BUTTON playBtn.MouseButton1Click:Connect(function() menu.Visible = false main.Visible = true startGame() end) settingsBtn.MouseButton1Click:Connect(function() menu.Visible = false settings.Visible = true end) -- GAME LOOP RunService.RenderStepped:Connect(function(dt) info.Text = "Score: "..score.." | Combo: "..combo.." | Misses: "..misses .. " | Time: "..math.floor(gameTime) if not playing then return end -- TIMER if timerRunning and not paused and not isResuming then gameTime -= dt if gameTime <= 0 then gameTime = 0 timerRunning = false paused = true resultText.Text = "Score: "..score.. "\nNotes Hit: "..notesHit.. "\nNotes Spawned: "..notesSpawned resultFrame.Visible = true main.Visible = false return end end -- RESUME TIMER if isResuming then resumeTimer -= dt if resumeTimer <= 0 then isResuming = false paused = false pauseBtn.Text = "Pause" end return end -- SPAWN NOTES if not paused then spawnTimer += dt if spawnTimer >= spawnDelay then spawnTimer = 0 spawnDelay = math.random(MIN_DELAY * 100, MAX_DELAY * 100) / 100 spawnMultipleNotes() end for i = #notes,1,-1 do local n = notes[i] n.obj.Position += UDim2.fromOffset(0,NOTE_SPEED*dt) if n.obj.AbsolutePosition.Y > hitLine.AbsolutePosition.Y + HIT_WINDOW then n.obj:Destroy() table.remove(notes,i) combo = 0 misses += 1 end end end end)