New post because I don't want to keep updating my old one and my new version of the script is relatively inelegant. But here's y-axis support:
Download Mouse2Move.luaLanguage: lua
-- The sign of a scalar.
local function sign(x)
return (x>0) and 1 or ((x<0) and -1 or 0)
end
-- Sums over a vector.
local function sum(v)
local total=0
for i=1,#v do
total=total+v[i]
end
return total
end
-- Did we just press this key?
local function justpressed(keys, last, button)
return keys[button] and not(last[button])
end
-- Inner product of two vectors. If not the same length, just uses the shorter of the two. To capture the most recent values, multiplies only the last elements.
local function inner(v1, v2)
local prod = {}
for i=0,math.min(#v1, #v2)-1 do
table.insert(prod, v1[#v1-i]*v2[#v2-i])
end
return sum(prod)
end
-- Updates the mouse's history.
local function updatemouse(history, axis)
local curr=input.getmouse()
table.remove(history, 1)
table.insert(history, curr[axis])
return history
end
-- Returns the difference between adjacent x values, effectively the mouse velocity.
local function getdeltas(history)
local delta_x = {}
for i=1,#history-1 do
table.insert(delta_x, history[i+1]-history[i])
end
return delta_x
end
-- Returns a sort of weighted average of the mouse's movement based on the window function.
local function windowavg(v, window)
local denom = sum(window)
local num = inner(v, window)
return num/denom
end
-- Makes a window function. Exponential with time.
local function makewindow(length, lambda)
local window={}
for i=1,length do
table.insert(window, math.exp(lambda*(i-length)))
end
return window
end
-- Updates the joypad input based on the threshold and its history. Also updates and returns the history.
local function gameinput(threshold, mouseavg, joyhist, joyavg, buttons)
local curr=false
if math.abs(mouseavg)>threshold*(1+math.abs(joyavg)) then -- "1+math.abs(joyavg)" is just a guess. It maybe needs to be refined.
curr=true
end
local lorr = sign(mouseavg)
if curr then
joypad.set({[buttons[lorr]]=curr})
end
table.remove(joyhist, 1)
table.insert(joyhist, curr and lorr or 0)
return joyhist
end
-- Adjusts a single parameter according to whether we press some keys.
local function adjustparam(param, keys, last, downkey, upkey, mini, maxi, interval, eps)
eps=eps or 0.0001
if justpressed(keys, last, upkey) then
param = (param>=maxi-eps) and maxi or param+interval
elseif justpressed(keys, last, downkey) then
param = (param<=mini+eps) and mini or param-interval
end
return param
end
local function updatevalues(last, mouselambda, joylambda, length, threshold, debugmode)
local keys = input.get()
mouselambda = adjustparam(mouselambda, keys, last, "Number6", "Number7", 0, 1, 0.1)
joylambda = adjustparam(joylambda, keys, last, "Y", "U", 0, 1, 0.1)
length = adjustparam(length, keys, last, "H", "J", 2, 10, 1)
threshold = adjustparam(threshold, keys, last, "N", "M", 10, 50, 2)
if justpressed(keys, last, "B") then
gui.clearGraphics()
debugmode = not(debugmode)
end
return keys, mouselambda, joylambda, length, threshold, debugmode
end
-- Initialization
local last = input.get()
local mouselambda = 0.2
local joylambda = 0.2
local length = 5
local threshold = 20
local mousestart = input.getmouse()
local mousexhist, mouseyhist, joyxhist, joyyhist = {}, {}, {}, {}
local buttonsx = {"Right", [-1]="Left"}
local buttonsy = {"Down", [-1]="Up"} -- Inverted because the y coordinate is read from the top of the screen.
local debugmode = false
for i=1,10 do -- Keep a history of the last 10 mouse locations and joypad buttons. Changing length only changes the window.
table.insert(mousexhist, mousestart.X)
table.insert(mouseyhist, mousestart.Y)
table.insert(joyxhist, 0)
table.insert(joyyhist, 0)
end
while true do
mousexhist = updatemouse(mousexhist, "X")
mouseyhist = updatemouse(mouseyhist, "Y")
delta_x = getdeltas(mousexhist)
delta_y = getdeltas(mouseyhist)
mousewindow = makewindow(length-1, mouselambda)
local mousexavg = windowavg(delta_x, mousewindow)
local mouseyavg = windowavg(delta_y, mousewindow)
local joywindow = makewindow(length, joylambda) -- Note that the joypad window and mouse window are different lengths. I assume this either doesn't matter or makes very little difference.
local joyxavg = windowavg(joyxhist, joywindow)
local joyyavg = windowavg(joyyhist, joywindow)
joyxhist = gameinput(threshold, mousexavg, joyxhist, joyxavg, buttonsx)
joyyhist = gameinput(threshold, mouseyavg, joyyhist, joyyavg, buttonsy)
emu.frameadvance()
keys, mouselambda, joylambda, length, threshold, debugmode = updatevalues(keys, mouselambda, joylambda, length, threshold, debugmode)
-- Print all the parameters and history for troubleshooting purposes.
if debugmode then
gui.drawRectangle(0,0,240,160,"gray","gray")
gui.pixelText(180,20,mouselambda)
gui.pixelText(180,28,joylambda)
gui.pixelText(180,36,length)
gui.pixelText(180,44,threshold)
for i=1,length-1 do
gui.pixelText(180,44+8*i,delta_x[i])
gui.pixelText(20,44+8*i,delta_y[i])
gui.pixelText(200,44+8*i,joyxhist[i])
gui.pixelText(40,44+8*i,joyyhist[i])
gui.pixelText(220,44+8*i,mousexhist[i])
gui.pixelText(60,44+8*i,mouseyhist[i])
end
gui.pixelText(200,44+8*length,joyxhist[length])
gui.pixelText(40,44+8*length,joyyhist[length])
gui.pixelText(220,44+8*length,mousexhist[length])
gui.pixelText(60,44+8*length,mouseyhist[length])
end
end
Basically, I just copied all of the variables line-by-line. What I perhaps should have done instead was put both x and y values into a single table but... I didn't feel like it.
Same request as above: run the script and tweak the parameters to your liking, then let me know what I should change.