|
function FlickInput() constructor { |
|
// Deadzone used for the joystick |
|
deadzone = 0.24; |
|
// If a flick was detected |
|
detected = false; |
|
|
|
// Axis information |
|
axis = { |
|
// Left-stick x-axis value |
|
x: 0, |
|
// Left-stick y-axis value |
|
y: 0, |
|
// Raw value of the left-stick axis |
|
value: 0, |
|
// Angle of the left-stick |
|
angle: 0, |
|
// Difference in value from the current and last frame |
|
difference: 0 |
|
}; |
|
// Flick information |
|
flick = { |
|
// If a flick was detected |
|
detected: false, |
|
// Flick value |
|
value: 0, |
|
// Flick value on the last frame |
|
value_previous: 0, |
|
// Flick angle |
|
angle: 0, |
|
// Flick angle on the last frame |
|
angle_previous: 0, |
|
}; |
|
// Stashed flick information |
|
last_flick = { |
|
// Last successful flick value |
|
value: 0, |
|
// Last successful flick angle |
|
angle: 0 |
|
}; |
|
|
|
|
|
/// Reads values from the joystick |
|
/// @param {real} _device Device ID to read input from |
|
/// @return {struct.FlickInfo} |
|
static read = function(_device = 0) { |
|
// Update axis information |
|
axis.x = gamepad_axis_value(_device, gp_axislh); |
|
axis.y = gamepad_axis_value(_device, gp_axislv); |
|
axis.value = clamp(point_distance(0, 0, axis.x, axis.y), 0, 1); |
|
axis.angle = point_direction(0, 0, axis.x, axis.y); |
|
axis.difference = flick.value_previous - axis.value; |
|
|
|
// Reset flick value and angle |
|
flick.value = 0; |
|
flick.angle = 0; |
|
|
|
// Check if conditions are met to detect a flick |
|
if (not detected) && (axis.difference >= deadzone) { |
|
flick.value = remap(deadzone, 1.0, 0.0, 1.0, flick.value_previous); |
|
flick.angle = flick.angle_previous; |
|
|
|
last_flick.value = flick.value; |
|
last_flick.angle = flick.angle; |
|
detected = true; |
|
} else { |
|
// Reset flick detection |
|
detected = false; |
|
} |
|
|
|
// Update previous values if axis value is over the deadzone threshold |
|
if (not detected) && (axis.value > deadzone) { |
|
flick.value_previous = axis.value; |
|
flick.angle_previous = axis.angle; |
|
} else { |
|
// Clear previous flick value |
|
flick.value_previous = 0; |
|
} |
|
|
|
// Return the flick information |
|
return new FlickInfo( |
|
clamp(remap(deadzone, 1.0, 0.0, 1.0, axis.value), 0, 1), // Remapped axis value with the deadzone |
|
axis.angle, |
|
flick.value, |
|
flick.angle, |
|
detected |
|
); |
|
} |
|
|
|
|
|
/// Draws a debug view of the controller joystick |
|
/// @param {real} _x X-position |
|
/// @param {real} _y Y-position |
|
/// @param {real} _radius Radius |
|
static draw_debug = function(_x, _y, _radius) { |
|
// The deadzone |
|
draw_set_color(c_red); |
|
draw_circle(_x, _y, _radius * deadzone, true); |
|
|
|
// The outmost circle |
|
draw_set_color(c_white); |
|
draw_circle(_x, _y, _radius, true); |
|
|
|
draw_set_color(axis.value > deadzone ? c_white : c_red); |
|
// The sticks current position |
|
var _stick_x = _x + lengthdir_x(axis.value * _radius, axis.angle); |
|
var _stick_y = _y + lengthdir_y(axis.value * _radius, axis.angle); |
|
draw_circle(_stick_x, _stick_y, _radius * 0.2, false); |
|
|
|
draw_set_color(c_white); |
|
// Last successful flick detected |
|
var _flick_x = _x - lengthdir_x(last_flick.value * _radius, last_flick.angle); |
|
var _flick_y = _y - lengthdir_y(last_flick.value * _radius, last_flick.angle); |
|
draw_arrow(_x, _y, _flick_x, _flick_y, _radius * 0.3); |
|
|
|
// Current axis value remapped to the deadzone, and last successful flick value |
|
draw_set_halign(fa_center); |
|
draw_text(_x - 32, _y + _radius, clamp(remap(deadzone, 1.0, 0.0, 1.0, axis.value), 0, 1) ); |
|
draw_text(_x + 32, _y + _radius, last_flick.value); |
|
} |
|
} |
|
|
|
|
|
/// Container for flick information |
|
/// @param {real} _axis_value |
|
/// @param {real} _axis_angle |
|
/// @param {real} _flick_value |
|
/// @param {real} _flick_angle |
|
/// @param {bool} _successful |
|
function FlickInfo(_axis_value, _axis_angle, _flick_value, _flick_angle, _successful) constructor { |
|
// Value of the axis |
|
axis_value = _axis_value; |
|
// Angle of the axis |
|
axis_angle = _axis_angle; |
|
// Value of the flick |
|
flick_value = _flick_value; |
|
// Angle of the flick |
|
flick_angle = _flick_angle; |
|
// Whether the last flick was successful or not |
|
successful = _successful; |
|
} |
|
|
|
|
|
/// Returns a fraction t, based on a value between a and b |
|
/// @param {real} _a Start value |
|
/// @param {real} _b End value |
|
/// @param {real} _t Fraction |
|
/// @return {real} |
|
function inverse_lerp(_a, _b, _t) { |
|
return (_t - _a) / (_b - _a); |
|
} |
|
|
|
|
|
/// Returns a value within a given input range into a given output range |
|
/// @param {real} _imin Input minimum |
|
/// @param {real} _imax Input maximum |
|
/// @param {real} _omin Output minimum |
|
/// @param {real} _omax Output maximum |
|
/// @param {real} _value Value to be remapped |
|
/// @return {real} |
|
function remap(_imin, _imax, _omin, _omax, _value) { |
|
var _t = inverse_lerp(_imin, _imax, _value); |
|
return lerp(_omin, _omax, _t); |
|
} |