Skip to content

Commit acbb2cb

Browse files
committed
Scale touch steering to the display and add a center dead zone
Drag-steering was too sensitive: full lock took a horizontal drag of 0.12 * min(width, height) px, but the drag delta was measured against width -- so on a landscape phone (min = height) full lock landed at only ~6% of screen width. Base the travel on window width instead (g_steerTravelFrac = 0.16): SDL touch-X is width-normalized, so the pixel dimensions cancel and full lock is a consistent 16%-of-width drag that scales with any display. Add a 10% center dead zone with rescale-to-full (g_steerDeadZoneFrac), mirroring the gamepad axis dead zone in dinput.cpp's ScaleAxis (which the touch override otherwise bypasses), so a resting thumb no longer weaves the car while holding throttle. Factor the drag->steer math into a shared SteerFromFinger helper, and render the origin ring as a compact min-based thumb-well (g_steerRingFrac) decoupled from the travel so the calmer steering does not inflate the overlay; the thumb dot maps the steer value onto the ring (centered in the dead zone, at the edge at full lock). The MiniwinTouch_GetSteer contract is unchanged ([-1, 1], positive steers left), so PlayerControls' rate shaping consumes it as before. No decomp or game-side code touched.
1 parent e8d3fb1 commit acbb2cb

2 files changed

Lines changed: 41 additions & 26 deletions

File tree

miniwin/include/miniwin/touch.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ void MiniwinTouch_SetLocalPlayerCount(unsigned p_count);
3939

4040
// Analog steering for the owning player: true while a steering finger is down, with
4141
// *p_steer set to the drag deflection in [-1, 1] using the game's analog convention
42-
// (positive steers left, like the negated device axis). Feeds the analog branch of
43-
// PlayerControls::UpdateSteering, so the existing rate shaping applies unchanged.
42+
// (positive steers left, like the negated device axis). Full lock is a horizontal drag
43+
// of a fixed fraction of the window width (so it scales with the display), past a small
44+
// center dead zone. Feeds the analog branch of PlayerControls::UpdateSteering, so the
45+
// existing rate shaping applies unchanged.
4446
bool MiniwinTouch_GetSteer(void* p_owner, float* p_steer);
4547

4648
// Race-button edges for the owning player, polled once per PlayerControls::Update.

miniwin/src/dinput/touch.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@
3737

3838
// --- Layout tunables (fractions of min(drawableW, drawableH) unless noted) ---
3939

40-
static const float g_steerRadiusFrac = 0.12f; // drag distance for full steering lock
41-
static const float g_brakeSizeFrac = 0.16f; // BRAKE, bottom-right anchor
42-
static const float g_primarySizeFrac = 0.14f; // POWER-UP / SLIDE
40+
// Steering travel is a fraction of window WIDTH (the horizontal gesture axis) so full
41+
// lock scales with the display; everything below is a fraction of min(drawableW, drawableH).
42+
static const float g_steerTravelFrac = 0.16f; // horizontal drag (fraction of width) for full lock
43+
static const float g_steerDeadZoneFrac = 0.10f; // center dead zone, rescaled to full (cf. dinput ScaleAxis)
44+
static const float g_steerRingFrac = 0.12f; // overlay thumb-well radius (visual only; not the travel)
45+
static const float g_brakeSizeFrac = 0.16f; // BRAKE, bottom-right anchor
46+
static const float g_primarySizeFrac = 0.14f; // POWER-UP / SLIDE
4347
static const float g_clusterGapFrac = 0.035f;
4448
static const float g_clusterMarginFrac = 0.04f;
4549
static const float g_cornerSizeFrac = 0.10f; // PAUSE / LOOK-BACK
@@ -186,7 +190,10 @@ static void ComputeLayout(TouchLayout& p_layout)
186190
float margin = g_clusterMarginFrac * unit;
187191
float dialog = g_dialogSizeFrac * unit;
188192

189-
p_layout.m_steerRadiusPx = g_steerRadiusFrac * unit;
193+
// Compact thumb-well for the overlay only (min-based like the buttons, so it stays
194+
// small in landscape); the real full-lock travel is g_steerTravelFrac of the width.
195+
// The thumb dot maps the steer value onto this ring, filling it as you near full lock.
196+
p_layout.m_steerRadiusPx = g_steerRingFrac * unit;
190197

191198
// The game HUD owns three corners — race position (top-left), lap/time (top-right)
192199
// and the minimap (bottom-right) — so the touch controls stay clear of them: the
@@ -517,6 +524,27 @@ void MiniwinTouch_ReleasePlayer(void* p_owner)
517524
}
518525
}
519526

527+
// [library:input] Steer finger drag -> game analog value in [-1, 1] (positive steers
528+
// left, the negated device axis). Full lock after a horizontal drag of g_steerTravelFrac
529+
// of the window width (m_nx is width-normalized, so pixel size cancels and the feel
530+
// scales with the display); the center dead zone is removed and the remainder rescaled
531+
// to full range, mirroring the gamepad axis dead zone in dinput.cpp's ScaleAxis.
532+
static float SteerFromFinger(const TouchFinger& finger)
533+
{
534+
float raw = -(finger.m_nx - finger.m_originNX) / g_steerTravelFrac;
535+
float mag = raw < 0.0f ? -raw : raw;
536+
if (mag <= g_steerDeadZoneFrac) {
537+
return 0.0f;
538+
}
539+
if (g_steerDeadZoneFrac < 1.0f) {
540+
mag = (mag - g_steerDeadZoneFrac) / (1.0f - g_steerDeadZoneFrac);
541+
}
542+
if (mag > 1.0f) {
543+
mag = 1.0f;
544+
}
545+
return raw < 0.0f ? -mag : mag;
546+
}
547+
520548
bool MiniwinTouch_GetSteer(void* p_owner, float* p_steer)
521549
{
522550
if (!p_owner || p_owner != g_playerOwner || g_drawableW <= 0 || g_drawableH <= 0) {
@@ -527,18 +555,7 @@ bool MiniwinTouch_GetSteer(void* p_owner, float* p_steer)
527555
if (finger.m_role != TouchRole::Steer) {
528556
continue;
529557
}
530-
float unit = (float) (g_drawableW < g_drawableH ? g_drawableW : g_drawableH);
531-
float radius = g_steerRadiusFrac * unit;
532-
float deltaPx = (finger.m_nx - finger.m_originNX) * (float) g_drawableW;
533-
// Game analog convention: positive steers left (the negated device axis).
534-
float steer = -deltaPx / radius;
535-
if (steer > 1.0f) {
536-
steer = 1.0f;
537-
}
538-
else if (steer < -1.0f) {
539-
steer = -1.0f;
540-
}
541-
*p_steer = steer;
558+
*p_steer = SteerFromFinger(finger);
542559
return true;
543560
}
544561
return false;
@@ -760,17 +777,13 @@ bool MiniwinTouch_GetOverlay(MiniwinTouchOverlayState* p_state, int p_drawableW,
760777
}
761778
float originX = finger.m_originNX * (float) g_drawableW;
762779
float originY = finger.m_originNY * (float) g_drawableH;
763-
float deltaPx = (finger.m_nx - finger.m_originNX) * (float) g_drawableW;
764-
if (deltaPx > layout.m_steerRadiusPx) {
765-
deltaPx = layout.m_steerRadiusPx;
766-
}
767-
else if (deltaPx < -layout.m_steerRadiusPx) {
768-
deltaPx = -layout.m_steerRadiusPx;
769-
}
780+
// Place the thumb from the final steer value so it honours the dead zone:
781+
// centered while inside it, at the ring edge at full lock (positive = left).
782+
float steer = SteerFromFinger(finger);
770783
p_state->m_steerActive = true;
771784
p_state->m_steerOriginX = originX;
772785
p_state->m_steerOriginY = originY;
773-
p_state->m_steerThumbX = originX + deltaPx;
786+
p_state->m_steerThumbX = originX - steer * layout.m_steerRadiusPx;
774787
p_state->m_steerThumbY = originY;
775788
p_state->m_steerRadius = layout.m_steerRadiusPx;
776789
break;

0 commit comments

Comments
 (0)