local Players = game:GetService("Players") local RunService = game:GetService("RunService") local CAS = game:GetService("ContextActionService") local lp = Players.LocalPlayer local char = lp.Character or lp.CharacterAdded:Wait() local hum = char:WaitForChild("Humanoid") local root = char:WaitForChild("HumanoidRootPart") -- SPRITES (With Sprite Names) local ASSETS = { mario_idle = "rbxassetid://105805493603160", -- mario_idle_1 mario_walk = { "rbxassetid://116343483466658", -- mario_walk_1 "rbxassetid://117823380604143", -- mario_walk_2 "rbxassetid://137195314043180" -- mario_walk_3 }, mario_jump = "rbxassetid://112767207984016", -- mario_jump_1 mario_crouch = "rbxassetid://132620529740675", -- mario_crouch_1 mario_longjump = { "rbxassetid://88331108429026", -- mario_longjump_1 "rbxassetid://70811988744497", -- mario_longjump_2 "rbxassetid://97346290895187" -- mario_longjump_3 }, mario_punch = { "rbxassetid://138596215883292", -- mario_punch_1 "rbxassetid://135436281313454", -- mario_punch_2 "rbxassetid://71771792388991" -- mario_punch_3 } } -- PHYSICS CONSTANTS local MAX_SPEED = 34 local ACCEL = 1.4 local LJ_POP_FORCE = 35 -- Initial upward spring local LJ_GLIDE_FORCE = 70 -- Forward speed local GLIDE_GRAVITY = -6 -- Soft slow fall local currentSpeed = 0 local isCrouching = false local isPunching = false local isLongJumping = false local ljStartTime = 0 local jumpStage = 0 local lastJump = 0 -- 1. STABLE UI & MARIO SPRITE local sg = Instance.new("ScreenGui", lp:WaitForChild("PlayerGui")) sg.Name = "MarioMobileUI" sg.ResetOnSpawn = false local bb = Instance.new("BillboardGui", root) bb.Size = UDim2.new(4.5, 0, 4.5, 0) bb.AlwaysOnTop = true bb.Adornee = root local img = Instance.new("ImageLabel", bb) img.Size = UDim2.new(1, 0, 1, 0) img.BackgroundTransparency = 1 img.ResampleMode = Enum.ResamplerMode.Pixelated img.Image = ASSETS.mario_idle local function hideRoblox() for _, v in pairs(char:GetDescendants()) do if v:IsA("BasePart") or v:IsA("Decal") then v.Transparency = 1 end end end hideRoblox() -- 2. BUTTONS (B & Z) local function makeBtn(text, pos, color) local b = Instance.new("TextButton", sg) b.Size = UDim2.new(0, 85, 0, 85) b.Position = pos b.Text = text b.BackgroundColor3 = color b.TextScaled = true b.TextColor3 = Color3.new(1,1,1) b.ZIndex = 10 return b end local zBtn = makeBtn("Z", UDim2.new(1, -210, 1, -130), Color3.fromRGB(80, 80, 80)) local bBtn = makeBtn("B", UDim2.new(1, -110, 1, -220), Color3.fromRGB(180, 40, 40)) zBtn.MouseButton1Down:Connect(function() isCrouching = true end) zBtn.MouseButton1Up:Connect(function() isCrouching = false end) bBtn.Activated:Connect(function() if not isPunching then isPunching = true task.delay(0.4, function() isPunching = false end) end end) -- 3. JUMP LOGIC (SPRING TRIGGER) hum.Jumping:Connect(function() local now = tick() if isCrouching and currentSpeed > 5 then isLongJumping = true ljStartTime = now -- Initial Pop Upward root.Velocity = (root.CFrame.LookVector * LJ_GLIDE_FORCE) + Vector3.new(0, LJ_POP_FORCE, 0) task.delay(1.0, function() isLongJumping = false end) return end if now - lastJump < 0.6 then jumpStage = (jumpStage + 1) % 3 else jumpStage = 0 end local heights = {48, 65, 85} root.Velocity = root.Velocity * Vector3.new(1,0,1) + Vector3.new(0, heights[jumpStage+1], 0) lastJump = now end) -- 4. RENDER ENGINE (DYNAMIC PHYSICS & ANIMATION) local animTimer, walkFrame, punchFrame, ljFrame = 0, 1, 1, 1 RunService.RenderStepped:Connect(function(dt) local moveDir = hum.MoveDirection local moving = moveDir.Magnitude > 0 local ljTime = tick() - ljStartTime -- PHYSICS BLOCK if isLongJumping then -- PHASE 1: The Spring (First 0.2 seconds, let the jump carry him up) if ljTime < 0.2 then -- Allow Roblox physics to handle the upward pop else -- PHASE 2: The Glide (Lock the descent into a soft glide) root.Velocity = (root.CFrame.LookVector * LJ_GLIDE_FORCE) + Vector3.new(0, GLIDE_GRAVITY, 0) end else -- Normal Movement if moving and not isCrouching then currentSpeed = math.min(currentSpeed + (ACCEL * dt * 60), MAX_SPEED) elseif moving and isCrouching then currentSpeed = math.max(currentSpeed - (0.5 * dt * 60), 0) else currentSpeed = math.max(currentSpeed - (2.5 * dt * 60), 0) end hum.WalkSpeed = isCrouching and 6 or currentSpeed end -- ANIMATION BLOCK animTimer = animTimer + dt local fps = moving and math.max(0.1, 0.28 - (currentSpeed * 0.006)) or 0.2 if animTimer >= fps then animTimer = 0 if isPunching then img.Image = ASSETS.mario_punch[punchFrame] punchFrame = (punchFrame % #ASSETS.mario_punch) + 1 elseif isLongJumping then img.Image = ASSETS.mario_longjump[ljFrame] ljFrame = (ljFrame % #ASSETS.mario_longjump) + 1 elseif hum:GetState() == Enum.HumanoidStateType.Freefall then img.Image = ASSETS.mario_jump elseif isCrouching then img.Image = ASSETS.mario_crouch elseif moving then img.Image = ASSETS.mario_walk[walkFrame] walkFrame = (walkFrame % #ASSETS.mario_walk) + 1 else img.Image = ASSETS.mario_idle walkFrame, punchFrame, ljFrame = 1, 1, 1 end end end)