I need help rotating a 2D vector to achieve accurate gamepad movement

I’ve been working on a Minecraft Dungeons styled game for a while, and now I’m rewriting the roblox movement code from scratch in order to make the player move with the mouse instead of WASD. To achieve this I had to set the DevComputerMovementMode to Scriptable, but as a side-effect it also completely disabled the gamepad thumbstick movement, thus forcing me to remake it from scratch (Thanks Roblox!)

Minecraft Dungeons locks your camera to a 45° topdown view (example below), so in order to re-add the gamepad movement I’d have to rotate the gamepad’s thumbstick vector in order to match the current camera angle

The way I’m currently handling movement is by inserting a part that the character is constantly moving towards (example below, again), so instead of moving the character I’m moving the part since it simplifies a lot of things


I’m running this code every frame in order to rotate the thumbstick’s direction relative to the camera rotation, and then move the part according to the rotated thumbstick direction

local movePart = workspace:WaitForChild('MovePart') --The part the character is moving towards
local rotation = - player:GetAttribute('Rotation') --The camera's rotation (negative)
local partDistance = 10 --Distance between the MovePart and the Humanoid when moving

local abs = math.abs --Just making my life easier
local sin = math.sin
local cos = math.cos

function module.Move() --Called every frame if LastInputType == Enum.UserInputType.Gamepad1
	for i,v in uis:GetGamepadState(Enum.UserInputType.Gamepad1) do --Gets all buttons currently pressed by the gamepad
		if v.KeyCode ~= Enum.KeyCode.Thumbstick1 then continue end --Saves me some yucky nesting

		--Raw thumbstick direction
		local xPos = v.Position.X * partDistance
		local yPos = - v.Position.Y * partDistance

		--Deadzone stuff, feel free to ignore it		
		if abs(xPos) <= deadZone and abs(yPos) <= deadZone then
			yPos = 0
			xPos = 0
		end
		
		--The thumbstick direction rotated using the Rotation Matrix formula I got from wikipedia cuz I don't know linear algebra lol
		local xRot = xPos * cos(rotation) - yPos * sin(rotation) 
		local yRot = xPos * sin(rotation) + yPos * cos(rotation)
		
		gamepadDelta = Vector2.new(xRot, yRot) --Rotated thumbstick direction
	end

	movePart.Position = hrp.Position + Vector3.new(gamepadDelta.X, 0, gamepadDelta.Y) --Finally, moves the part
end

Although this code works well when the camera is rotated either 0 or 45 degrees, it breaks in every other angle for some reason (example below, I had DS4Windows open in the left so you can see that the movement does not match my thumbstick’s position most of the times), I’ve been scratching my head over this for the past day and I still can’t figure out why

I’ve seen a lot of different solutions to similar problems but none of them really work. I’m guessing that the problem comes when I rotate the thumbstick’s direction but I still can’t figure out what’s wrong

In case you’re wondering, this is the code for the camera, I’m pretty sure this works fine though.

local player = game:GetService('Players').LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hum = char:WaitForChild('Humanoid')
local hrp = char:WaitForChild('HumanoidRootPart')

local cam = workspace.CurrentCamera
cam.CameraType = Enum.CameraType.Scriptable

local camOffset = 22
local camHeight = 28

player:SetAttribute('Rotation', 45) --Dummy rotation angle

local heartbeat = runService.Heartbeat:Connect(function(dt)	
	if cam.CameraType ~= Enum.CameraType.Scriptable then return end
	
	local camRotation = player:GetAttribute('Rotation')
	
	local cframe = CFrame.new(hrp.Position) * CFrame.Angles(0, math.rad(camRotation), 0) * CFrame.new(0, camHeight, camOffset) 
	cam.CFrame = CFrame.lookAt(cframe.Position, hrp.Position)
end)

English isn’t my first language so let me know if I had any grammar mistakes lol

2 Likes

The amount of self-teaching I did just to finally come to the conclusion that required none…

player:SetAttribute('Rotation', 45) --Dummy rotation angle

That’s a nice non-raidan number you got there, be a shame if you forgot to convert it to radians to be used appropriately with trig functions…

local xRot = xPos * cos(rotation) - yPos * sin(rotation) 
local yRot = xPos * sin(rotation) + yPos * cos(rotation)

-- oops all berries

Here you go

local xRot = xPos * cos(math.rad(rotation)) - yPos * sin(math.rad(rotation)) 
local yRot = xPos * sin(math.rad(rotation)) + yPos * cos(math.rad(rotation))
1 Like

Oh my god I can’t believe it was such a simple fix lol. I’ll try to stay as far away as possible from linear algebra in the future, thanks !

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.