SyntaxGameServer/RCCService2020/ExtraContent/scripts/PlayerScripts/StarterPlayerScripts/ControlScript/MasterControl/Thumbstick.lua

179 lines
6.3 KiB
Lua

--[[
// FileName: Thumbstick
// Version 1.0
// Written by: jmargh
// Description: Implements thumbstick controls for touch devices
--]]
local Players = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')
local GuiService = game:GetService('GuiService')
local MasterControl = require(script.Parent)
local Thumbstick = {}
--[[ Script Variables ]]--
while not Players.LocalPlayer do
wait()
end
local LocalPlayer = Players.LocalPlayer
local IsFollowStick = false
local ThumbstickFrame = nil
local MoveTouchObject = nil
local OnTouchEnded = nil -- defined in Create()
local OnTouchMovedCn = nil
local OnTouchEndedCn = nil
local currentMoveVector = Vector3.new(0,0,0)
--[[ Constants ]]--
local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/TouchControlsSheet.png"
--[[ Public API ]]--
function Thumbstick:Enable()
ThumbstickFrame.Visible = true
end
function Thumbstick:Disable()
ThumbstickFrame.Visible = false
OnTouchEnded()
end
function Thumbstick:Create(parentFrame)
if ThumbstickFrame then
ThumbstickFrame:Destroy()
ThumbstickFrame = nil
if OnTouchMovedCn then
OnTouchMovedCn:disconnect()
OnTouchMovedCn = nil
end
if OnTouchEndedCn then
OnTouchEndedCn:disconnect()
OnTouchEndedCn = nil
end
end
local minAxis = math.min(parentFrame.AbsoluteSize.x, parentFrame.AbsoluteSize.y)
local isSmallScreen = minAxis <= 500
local thumbstickSize = isSmallScreen and 70 or 120
local position = isSmallScreen and UDim2.new(0, (thumbstickSize/2) - 10, 1, -thumbstickSize - 20) or
UDim2.new(0, thumbstickSize/2, 1, -thumbstickSize * 1.75)
ThumbstickFrame = Instance.new('Frame')
ThumbstickFrame.Name = "ThumbstickFrame"
ThumbstickFrame.Active = true
ThumbstickFrame.Visible = false
ThumbstickFrame.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize)
ThumbstickFrame.Position = position
ThumbstickFrame.BackgroundTransparency = 1
local outerImage = Instance.new('ImageLabel')
outerImage.Name = "OuterImage"
outerImage.Image = TOUCH_CONTROL_SHEET
outerImage.ImageRectOffset = Vector2.new()
outerImage.ImageRectSize = Vector2.new(220, 220)
outerImage.BackgroundTransparency = 1
outerImage.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize)
outerImage.Position = UDim2.new(0, 0, 0, 0)
outerImage.Parent = ThumbstickFrame
local StickImage = Instance.new('ImageLabel')
StickImage.Name = "StickImage"
StickImage.Image = TOUCH_CONTROL_SHEET
StickImage.ImageRectOffset = Vector2.new(220, 0)
StickImage.ImageRectSize = Vector2.new(111, 111)
StickImage.BackgroundTransparency = 1
StickImage.Size = UDim2.new(0, thumbstickSize/2, 0, thumbstickSize/2)
StickImage.Position = UDim2.new(0, thumbstickSize/2 - thumbstickSize/4, 0, thumbstickSize/2 - thumbstickSize/4)
StickImage.ZIndex = 2
StickImage.Parent = ThumbstickFrame
local centerPosition = nil
local deadZone = 0.05
local function doMove(direction)
MasterControl:AddToPlayerMovement(-currentMoveVector)
currentMoveVector = direction / (thumbstickSize/2)
-- Scaled Radial Dead Zone
local inputAxisMagnitude = currentMoveVector.magnitude
if inputAxisMagnitude < deadZone then
currentMoveVector = Vector3.new()
else
currentMoveVector = currentMoveVector.unit * ((inputAxisMagnitude - deadZone) / (1 - deadZone))
-- NOTE: Making currentMoveVector a unit vector will cause the player to instantly go max speed
-- must check for zero length vector is using unit
currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y)
end
MasterControl:AddToPlayerMovement(currentMoveVector)
end
local function moveStick(pos)
local relativePosition = Vector2.new(pos.x - centerPosition.x, pos.y - centerPosition.y)
local length = relativePosition.magnitude
local maxLength = ThumbstickFrame.AbsoluteSize.x/2
if IsFollowStick and length > maxLength then
local offset = relativePosition.unit * maxLength
ThumbstickFrame.Position = UDim2.new(
0, pos.x - ThumbstickFrame.AbsoluteSize.x/2 - offset.x,
0, pos.y - ThumbstickFrame.AbsoluteSize.y/2 - offset.y)
else
length = math.min(length, maxLength)
relativePosition = relativePosition.unit * length
end
StickImage.Position = UDim2.new(0, relativePosition.x + StickImage.AbsoluteSize.x/2, 0, relativePosition.y + StickImage.AbsoluteSize.y/2)
end
-- input connections
ThumbstickFrame.InputBegan:connect(function(inputObject)
--A touch that starts elsewhere on the screen will be sent to a frame's InputBegan event
--if it moves over the frame. So we check that this is actually a new touch (inputObject.UserInputState ~= Enum.UserInputState.Begin)
if MoveTouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch
or inputObject.UserInputState ~= Enum.UserInputState.Begin then
return
end
MoveTouchObject = inputObject
ThumbstickFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbstickFrame.Size.X.Offset/2, 0, inputObject.Position.y - ThumbstickFrame.Size.Y.Offset/2)
centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2,
ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2)
local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
end)
OnTouchMovedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed)
if inputObject == MoveTouchObject then
centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2,
ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2)
local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
doMove(direction)
moveStick(inputObject.Position)
end
end)
OnTouchEnded = function()
ThumbstickFrame.Position = position
StickImage.Position = UDim2.new(0, ThumbstickFrame.Size.X.Offset/2 - thumbstickSize/4, 0, ThumbstickFrame.Size.Y.Offset/2 - thumbstickSize/4)
MoveTouchObject = nil
MasterControl:AddToPlayerMovement(-currentMoveVector)
currentMoveVector = Vector3.new(0,0,0)
MasterControl:SetIsJumping(false)
end
OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject, isProcessed)
if inputObject == MoveTouchObject then
OnTouchEnded()
end
end)
GuiService.MenuOpened:connect(function()
if MoveTouchObject then
OnTouchEnded()
end
end)
ThumbstickFrame.Parent = parentFrame
end
return Thumbstick