How should I make a working control surface using the mouse?

Hello. I am working on a game called FlightPoint. Right now, it’s some stupid remake of Plane Crazy

At the moment, I am trying to add a control surface block that can be interacted with using the mobile thumbstick or the mouse if the player is on the computer. Could I have help on what I should do and where I should start?

I have searched through lots of different forums about mouse movement and hinges, but no forum post is made specifically for a mouse following hinge that has to behave differently according to where on the plane it is.

1 Like

Well what you could do is weld the control surface to the plane and then rotate the weld. How it moves depends on the control surface. For the ailerons example, the roll rate would presumably be controlled by the X Coordinate of the mouse cursor. I would simply scale the angle of the left aileron with that

Something like

Camera = workspace.CurrentCamera
SCREEN_WIDTH = Camera.ViewportSize.X
RS = game:GetService("RunService")
UIS = game:GetService("UserInputService")
MAX_ANGLE = 20
AileronWeld = Aileron.Weld


RS.Stepped:Connect(function()
    local MouseX = UIS:GetMouseLocation().X --Get the X coordinate of the mouse
    AileronWeld.C0 *= CFrame.Angles(0, (MouseX/SCREEN_WIDTH) * MAX_ANGLE, 0) --Convert the mouse X position to a number between 0 and 1.  Then multiply that number by the max desired angle.
end)

Not entirely sure that the weld will rotate on the correct axis but you’ll have to play around with that.

I’m using weld constraints to connect touching blocks to each other, and I’m using hingeconstraints for the surface.

can you cleanify more on what could be the issue have you tried anything what ive understood that you want to do some stuff with mouse and touch inputs but not really why does it have to do with plane controlls? and how do you want to controll surfaces?

Well if you’re using constraints, just apply rotation to the target angle on the hinge instead of the weld CFrame

Greatings Chiseled_Cheese,

I see that you need an script, for make it that you have a control surface block and an aircraft model in your game, I hope you have it, if not just ask me again. :smile: I’m here, new as posting, and also for help people with scripts.

So let’s assume that you have the control surface block and an aircraft model in your game, so the script could be:

--[[ So here you will be able to define the control surface block and hinge joint of the spawn ]]--
local controlSurface = script.Parent
local hingeJoint = controlSurface.HingeJoint --[[ Replace with the name of your hinge joint ]]--

 --[[ Define the maximum rotation angle for the control surface block ]]--
local maxRotationAngle = 45

--[[ Define the input parameters ]]--
local inputDelta = Vector3.new()
local inputStart = Vector3.new()

--[[ Define the update function ]]--
local function update()
	--[[ Calculate the rotation angle based on the input delta ]]--
	local rotationAngle = math.clamp(inputDelta.Y, -1, 1) * maxRotationAngle
	
	--[[ Set the hinge joint target angle ]]--
	local hingeTargetAngle = math.rad(rotationAngle)
	hingeJoint.TargetAngle = hingeTargetAngle
	
	--[[ Apply the hinge joint target angle to the control surface block ]]--
	hingeJoint:Apply()
end

--[[ Define the input event handlers for mobile and desktop devices ]]--
if UserInputService.TouchEnabled then
	--[[ Define the touch input event handlers ]]--
	local thumbstick = nil
	
	local function onTouchStarted(input, gameProcessedEvent)
		if gameProcessedEvent then return end
		
		--[[ Initialize the input parameters ]]--
		inputStart = input.Position
		inputDelta = Vector3.new()
		
		--[[ Create the thumbstick GUI ]]--
		thumbstick = Instance.new("ImageLabel")
		thumbstick.Name = "Thumbstick"
		thumbstick.Image = "Chiseled_Cheese, add your img here"
		thumbstick.Size = UDim2.new(0, 64, 0, 64)
		thumbstick.AnchorPoint = Vector2.new(0.5, 0.5)
		thumbstick.Position = UDim2.new(0, inputStart.X, 0, inputStart.Y)
		thumbstick.Parent = game:GetService("Players").LocalPlayer:WaitForChild("PlayerGui")
	end
	
	local function onTouchMoved(input, gameProcessedEvent)
		if gameProcessedEvent then return end
		
		--[[ Update the input delta ]]--
		inputDelta = input.Position - inputStart
		
		--[[ Update the thumbstick position ]]--
		thumbstick.Position = UDim2.new(0, input.Position.X, 0, input.Position.Y)
	end
	
	local function onTouchEnded(input, gameProcessedEvent)
		if gameProcessedEvent then return end
		
		--[[ Destroy the thumbstick GUI ]]--
		thumbstick:Destroy()
		
		--[[ Reset the input parameters ]]--
		inputDelta = Vector3.new()
		inputStart = Vector3.new()
	end
	
	--[[ Connect the touch input event handlers ]]--
	UserInputService.TouchStarted:Connect(onTouchStarted)
	UserInputService.TouchMoved:Connect(onTouchMoved)
	UserInputService.TouchEnded:Connect(onTouchEnded)
else
	--[[ Define the mouse input event handlers ]]--
	local mouseDown = false
	
	local function onMouseButton1Down(input)
		mouseDown = true
		inputStart = input.Position
		inputDelta = Vector3.new()
	end
	
	local function onMouseMoved(input)
		if not mouseDown then return end
		
		--[[ Update the input delta ]]--
		inputDelta = input.Position - inputStart
		
		--[[ Update the mouse cursor position ]]--
		local cursor = game:GetService("Players").LocalPlayer:GetMouse()
		cursor.Icon = "Chiseled_Cheese, add your thumbstick img here"
		cursor.IconSize = Vector2.new(32, 32)
        cursor.Position = input.Position
end
local function onMouseButton1Up(input)
	mouseDown = false
	inputDelta = Vector3.new()
	inputStart = Vector3.new()
	
	--[[ Reset the mouse cursor position ]]--
	local cursor = game:GetService("Players").LocalPlayer:GetMouse()
	cursor.Icon = "Chiseled_Cheese, add your img here"
	cursor.IconSize = Vector2.new(0, 0)
end

--[[ Connect the mouse input event handlers ]]--
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		onMouseButton1Down(input)
	end
end)

UserInputService.InputChanged:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		onMouseMoved(input)
	end
end)

UserInputService.InputEnded:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		onMouseButton1Up(input)
	end
end)

end

--[[ Connect the update function to the heartbeat event ]]--
RunService.Heartbeat:Connect(update)

The use of this script:

This script creates a control surface block that can be interacted with using a mouse or mobile thumbstick. When the player moves their input device, the block rotates accordingly. The script includes event handlers that detect player input and update the block’s rotation every frame.

Hope that works for you,
If you need more help with that script or other questions just let me know.

– TheGod

This looks good, but I took a quick look at the code and a lot of stuff doesn’t make sense as in it wouldn’t work out like the thumbstick gui. The code should be accessing the players builtin roblox thumbstick instead of making a new one and parenting it some a folder (not a screengui)

Just wondering, did you get ChatGPT to do this?

We can say that I used for a second option. I was writting one for this, but I would need to check the other parts and so. I can get an script ready for it, but need to get some stuff. Like a model or something for so. ChatGTP was the second option for give a fast answer. My bad to give my work to an IA.