Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa pagina descrive le nozioni di base della programmazione per i volanti da corsa su Xbox One usando Windows.Gaming.Input.RacingWheel e le API correlate per la piattaforma UWP (Universal Windows Platform).
Leggendo questa pagina, si apprenderà quanto segue:
- come raccogliere un elenco di volanti da corsa collegati e i relativi utenti
- come individuare quando un volante da corsa è stato aggiunto o rimosso
- come leggere l'input da uno o più volanti da corsa
- come inviare comandi force feedback
- come i volanti da corsa si comportano come dispositivi di navigazione dell'interfaccia utente
Panoramica del volante da corsa
I volanti da corsa sono dispositivi di input che assomigliano all'aspetto di una vera cabina di guida da corsa. I volanti da corsa sono il dispositivo di input perfetto per i giochi di corsa sia in stile arcade che in stile simulazione, che includono automobili o camion. I volanti da corsa sono supportati nello spazio dei nomi Windows.Gaming.Input in Windows 10 o Windows 11 e nelle app UWP di Xbox One.
I volanti da corsa sono offerti a una gamma di prezzi e in genere acquisiscono più e migliori capacità di input e feedback di forza man mano che il prezzo sale. Tutti i volanti da corsa sono dotati di un volante analogico, di acceleratore analogico, di controlli analogici del freno, e alcuni pulsanti sul volante. Alcuni volanti da corsa sono inoltre dotati di frizione analogica e controlli del freno a mano, cambi a schema e funzionalità di feedback tattile. Non tutti i volanti da corsa sono dotati delle stesse caratteristiche e possono variare anche nel supporto per determinate funzionalità, ad esempio i volanti potrebbero supportare diversi intervalli di rotazione e i cambi sequenziali potrebbero supportare diverse quantità di marce.
Funzionalità del dispositivo
Diversi volanti da corsa offrono diversi set di funzionalità di dispositivo facoltative e diversi livelli di supporto per tali funzionalità; questo livello di variazione tra un singolo tipo di dispositivo di input è univoco tra i dispositivi supportati dall'API Windows.Gaming.Input . Inoltre, la maggior parte dei dispositivi che incontrerai supporterà almeno alcune funzionalità facoltative o altre varianti. Per questo motivo, è importante determinare le funzionalità di ogni volante da corsa collegato singolarmente e supportare la variazione completa delle funzionalità che hanno senso per il gioco.
Per altre informazioni, vedere Determinazione delle funzionalità del volante da corsa.
Forzare il feedback
Alcuni volanti da corsa offrono un vero feedback di forza, ovvero possono applicare forze effettive su un asse di controllo, ad esempio il volante, non solo una semplice vibrazione. I giochi usano questa capacità per creare un maggiore senso di immersione (simulato danni all'incidente, "sensazione di strada") e aumentare la sfida di guidare bene.
Per ulteriori informazioni, vedere la panoramica del feedback di forza .
Navigazione nell'interfaccia utente
Per semplificare il carico di supporto dei diversi dispositivi di input per lo spostamento dell'interfaccia utente e per incoraggiare la coerenza tra giochi e dispositivi, la maggior parte dei dispositivi di input fisici fisica agisce simultaneamente come un dispositivo di input logico chiamato un controller di spostamento interfaccia utente . Il controller di navigazione dell'interfaccia utente fornisce un vocabolario comune per i comandi di navigazione dell'interfaccia utente attraverso i dispositivi di input.
Grazie alla loro particolare attenzione ai controlli analogici e al grado di variazione tra diversi volanti da corsa, sono generalmente dotati di un D-pad digitale, View, Menu, A, B, X, e pulsanti Y che assomigliano a quelli di un game pad ; questi pulsanti non sono progettati per supportare i comandi di gioco e non possono essere facilmente accessibili come pulsanti del volante da corsa.
Come controller di navigazione dell'interfaccia utente, i volanti da corsa associano il set richiesto di comandi di navigazione al thumbstick sinistro, al D-pad, Visualizza, Menu, Ae ai pulsanti B.
Comando di navigazione | Input volante da corsa |
---|---|
Attivo | D-pad su |
Giù | D-pad giù |
Sinistra | D-pad a sinistra |
Giusto | D-pad a destra |
Visualizza | Pulsante Visualizza |
Menù | Pulsante del Menu |
Accettare | Un pulsante |
Annulla | Pulsante B |
Inoltre, alcuni volanti da corsa potrebbero mappare alcuni dei set opzionali di comandi di navigazione ad altri input supportati, ma le mappature dei comandi possono variare da dispositivo a dispositivo. Prendi in considerazione anche il supporto di questi comandi, ma assicurati che questi comandi non siano essenziali per esplorare l'interfaccia del tuo gioco.
Comando di navigazione | Input volante da corsa |
---|---|
Pagina su | varia |
Pagina giù | varia |
Pagina a sinistra | varia |
Pagina a destra | varia |
Scorrere verso l'alto | varia |
Scorrere verso il basso | varia |
Scorri verso sinistra | varia |
Scorrimento a destra | varia |
Contesto 1 | Pulsante X (comunemente) |
Contesto 2 | Pulsante Y (comunemente) |
Contesto 3 | varia |
Contesto 4 | varia |
Rilevare e monitorare i volanti da corsa
Il rilevamento e il tracciamento dei volanti da corsa funzionano esattamente allo stesso modo dei gamepad, tranne che con la classe RacingWheel invece della classe Gamepad. Per ulteriori informazioni, vedi il gamepad e la vibrazione.
Lettura del volante da corsa
Dopo aver identificato i volanti da corsa a cui si è interessati, si è pronti a raccogliere l'input da essi. Tuttavia, a differenza di altri tipi di input a cui potresti essere abituato, i volanti da corsa non comunicano il cambiamento di stato generando eventi. Si accettano invece letture regolari degli stati correnti di polling.
Interrogazione del volante da corsa
Il processo di polling rileva un'istantanea del volante da corsa in un momento preciso. Questo approccio alla raccolta di input è ideale per la maggior parte dei giochi perché la loro logica viene in genere eseguita in un ciclo deterministico anziché essere guidati dagli eventi; è anche in genere più semplice interpretare i comandi del gioco dall'input raccolto contemporaneamente rispetto a molti input singoli raccolti nel corso del tempo.
Si interroga un volante da corsa chiamando GetCurrentReading; questa funzione restituisce RacingWheelReading che contiene lo stato del volante da corsa.
Nell'esempio seguente si interroga un volante da corsa per ottenere il suo stato attuale.
auto racingwheel = myRacingWheels[0];
RacingWheelReading reading = racingwheel->GetCurrentReading();
Oltre allo stato del volante da corsa, ogni lettura include un timestamp che indica esattamente quando è stato recuperato lo stato. Il timestamp è utile per la correlazione tra la tempistica delle letture precedenti o la tempistica della simulazione del gioco.
Determinazione delle funzionalità del volante da corsa
Molti dei controlli del volante da corsa sono facoltativi o supportano variazioni diverse anche nei controlli richiesti, quindi è necessario determinare le funzionalità di ogni volante da corsa singolarmente prima di poter elaborare l'input raccolto in ogni lettura del volante da corsa.
I controlli facoltativi sono il freno a mano, la frizione e il cambio a griglia; è possibile determinare se un volante da corsa collegato supporta questi controlli leggendo le proprietà HasHandbrake, HasClutche HasPatternShifter del volante da corsa, rispettivamente. Il controllo è supportato se il valore della proprietà è true; in caso contrario, non è supportato.
if (racingwheel->HasHandbrake)
{
// the handbrake is supported
}
if (racingwheel->HasClutch)
{
// the clutch is supported
}
if (racingwheel->HasPatternShifter)
{
// the pattern shifter is supported
}
Inoltre, i controlli che possono variare sono il volante e il cambio. Il volante può variare in base al grado di rotazione fisica che la ruota effettiva può supportare, mentre il selettore di marcia può variare in base al numero di marce in avanti distinte supportate. È possibile determinare l'angolo di rotazione più grande supportato dalla ruota effettiva leggendo la proprietà MaxWheelAngle
del volante da corsa; il suo valore è l'angolo fisico massimo supportato in gradi (positivo) che è supportato in modo analogo nella direzione in senso antiorario (gradi negativi). È possibile determinare la marcia più alta che il cambio a schema supporta leggendo la proprietà MaxPatternShifterGear
del volante da corsa; il suo valore è la marcia in avanti più alta supportata, compresa, ovvero se il valore è 4, il cambio a schema supporta la retromarcia, la folle, la prima, la seconda, la terza e la quarta marcia.
auto maxWheelDegrees = racingwheel->MaxWheelAngle;
auto maxShifterGears = racingwheel->MaxPatternShifterGear;
Infine, alcuni volanti da corsa supportano il force feedback attraverso il volante. È possibile determinare se un volante da corsa collegato supporta il force feedback leggendo la proprietà WheelMotor del volante da corsa. Il feedback forzato è supportato se WheelMotor
non è null; in caso contrario, non è supportato.
if (racingwheel->WheelMotor != nullptr)
{
// force feedback is supported
}
Per informazioni su come usare la funzionalità di feedback di forza dei volanti da corsa che supportano questa funzionalità, vedere Panoramica del feedback di forza.
Lettura dei pulsanti
Ognuno dei pulsanti del volante da corsa—le quattro direzioni del D-pad, i pulsanti Previous Gear e Next Gear, e 16 pulsanti aggiuntivi—fornisce una lettura digitale che indica se è premuto (giù) o rilasciato (su). Per efficienza, le letture dei pulsanti non sono rappresentate come singoli valori booleani; sono invece tutte raggruppate in un singolo campo di bit rappresentato dall'enumerazione RacingWheelButtons.
Annotazioni
I volanti da corsa sono dotati di pulsanti aggiuntivi usati per lo spostamento dell'interfaccia utente, ad esempio i pulsanti Visualizzazione e Menu. Questi pulsanti non fanno parte dell'enumerazione RacingWheelButtons
e possono essere letti solo accedendo al volante da corsa come dispositivo di navigazione dell'interfaccia utente. Per ulteriori informazioni, consultare dispositivo di navigazione dell'interfaccia utente.
I valori del pulsante vengono letti dalla proprietà Buttons
della struttura RacingWheelReading. Poiché questa proprietà è un campo di bit, il mascheramento bit per bit viene usato per isolare il valore del pulsante di cui sei interessato. Il pulsante viene premuto (verso il basso) quando viene impostato il bit corrispondente; se no, viene rilasciato (in alto).
Nell'esempio seguente viene determinato se il pulsante ingranaggio successivo è stato premuto.
if (RacingWheelButtons::NextGear == (reading.Buttons & RacingWheelButtons::NextGear))
{
// Next Gear is pressed
}
Nell'esempio seguente, si verifica se il pulsante "Next Gear" è stato rilasciato.
if (RacingWheelButtons::None == (reading.Buttons & RacingWheelButtons::NextGear))
{
// Next Gear is released (not pressed)
}
A volte potresti voler determinare quando un pulsante passa da premuto a rilasciato o da rilasciato a premuto, se più pulsanti vengono premuti o rilasciati o se un insieme di pulsanti è disposto in modo particolare, con alcuni premuti e altri no. Per informazioni su come rilevare queste condizioni, vedere Rilevamento delle transizioni dei pulsanti e Rilevamento di disposizioni complesse dei pulsanti.
Lettura della rotellina
Il volante è un controllo obbligatorio che fornisce un valore analogico tra -1,0 e +1,0. Il valore -1,0 corrisponde alla posizione della ruota più a sinistra; il valore +1,0 corrisponde alla posizione più a destra. Il valore del volante viene letto dalla proprietà Wheel
della struttura RacingWheelReading.
float wheel = reading.Wheel; // returns a value between -1.0 and +1.0.
Anche se le letture delle ruote corrispondono a diversi gradi di rotazione fisica nel volante effettivo a seconda dell'intervallo di rotazione supportato dal volante da corsa fisico, in genere non si desidera ridimensionare le letture delle ruote; i volanti che supportano gradi di rotazione maggiori offrono semplicemente una maggiore precisione.
Lettura dell'acceleratore e del freno
L'acceleratore e il freno sono controlli necessari che forniscono letture analogiche con valori tra 0,0 (rilasciato completamente) e 1,0 (premuto completamente) rappresentati come valori a virgola mobile. Il valore del controllo dell'acceleratore viene letto dalla proprietà Throttle
della struttura RacingWheelReading; il valore del controllo del freno viene letto dalla proprietà Brake
.
float throttle = reading.Throttle; // returns a value between 0.0 and 1.0
float brake = reading.Brake; // returns a value between 0.0 and 1.0
Verifica del freno a mano e della frizione
Il freno a mano e la frizione sono controlli opzionali che forniscono misurazioni analogiche tra 0,0 (rilasciato completamente) e 1,0 (impegnato completamente) rappresentate come valori in virgola mobile. Il valore del controllo freno a mano viene letto dalla proprietà Handbrake
della struttura RacingWheelReading; il valore del controllo della frizione viene letto dalla proprietà Clutch
.
float handbrake = 0.0;
float clutch = 0.0;
if(racingwheel->HasHandbrake)
{
handbrake = reading.Handbrake; // returns a value between 0.0 and 1.0
}
if(racingwheel->HasClutch)
{
clutch = reading.Clutch; // returns a value between 0.0 and 1.0
}
Lettura del cambiatore di schema
Lo spostamento del pattern è un controllo facoltativo che fornisce una lettura digitale tra -1 e MaxPatternShifterGear rappresentata come valore intero con segno. Un valore di -1 o 0 corrisponde rispettivamente al inverso
if (racingwheel->HasPatternShifter)
{
gear = reading.PatternShifterGear;
}
Annotazioni
Il selettore di pattern, dove supportato, è presente insieme ai pulsanti Marcia Precedente e Marcia Successiva, che influiscono anche sulla marcia corrente della macchina del giocatore. Una semplice strategia per unificare questi input, quando entrambi sono presenti, consiste nell'ignorare il selettore a griglia (e la frizione) quando un giocatore sceglie una trasmissione automatica per la propria auto, e di ignorare i pulsanti Precedente e Avanti Marcia quando un giocatore sceglie una trasmissione manuale per la propria auto solo se il volante da corsa è dotato di un controllo del cambio a griglia. Puoi implementare una strategia di unificazione diversa se questo non è adatto per il tuo gioco.
Prova l'esempio di InputInterfacing
L'app di esempio InputInterfacingUWP su GitHub illustra come usare i volanti da corsa e diversi tipi di dispositivi di input in congiunzione, oltre a come questi dispositivi di input si comportano come controller di navigazione nell'interfaccia utente.
Panoramica del feedback di forza
Molti volanti da corsa sono dotati di tecnologia di force feedback per offrire un'esperienza di guida più coinvolgente e stimolante. I volanti da corsa che supportano il force feedback sono in genere dotati di un singolo motore che applica forza al volante lungo un singolo asse, l'asse della rotazione della ruota. Il feedback forzato è supportato nelle app UWP di Windows 10 o Windows 11 e Xbox One tramite lo spazio dei nomi Windows.Gaming.Input.ForceFeedback .
Annotazioni
Le API force feedback sono in grado di supportare diversi assi di forza, ma nessun volante da corsa supporta attualmente qualsiasi asse di feedback diverso da quello della rotazione delle ruote.
Uso del feedback forzato
Queste sezioni descrivono le nozioni di base su come programmare gli effetti di feedback di forza per i volanti da corsa. Il feedback viene applicato utilizzando effetti, che vengono prima caricati sul dispositivo di force feedback e quindi possono essere avviati, sospesi, ripresi e arrestati in modo simile agli effetti sonori; tuttavia, devi prima determinare le funzionalità di feedback del volante da corsa.
Determinazione delle funzionalità di force feedback
È possibile determinare se un volante da corsa collegato supporta il force feedback leggendo la proprietà WheelMotor del volante da corsa. Il feedback forzato non è supportato se WheelMotor
è Null; in caso contrario, il feedback forzato è supportato ed è possibile procedere per determinare le funzionalità di feedback specifiche del motore, ad esempio gli assi che può influire.
if (racingwheel->WheelMotor != nullptr)
{
auto axes = racingwheel->WheelMotor->SupportedAxes;
if(ForceFeedbackEffectAxes::X == (axes & ForceFeedbackEffectAxes::X))
{
// Force can be applied through the X axis
}
if(ForceFeedbackEffectAxes::Y == (axes & ForceFeedbackEffectAxes::Y))
{
// Force can be applied through the Y axis
}
if(ForceFeedbackEffectAxes::Z == (axes & ForceFeedbackEffectAxes::Z))
{
// Force can be applied through the Z axis
}
}
Caricamento degli effetti di Force Feedback
Gli effetti di force feedback vengono caricati sul dispositivo di feedback, dove vengono "riprodotti" in modo autonomo al comando del tuo gioco. Viene fornito un certo numero di effetti di base; gli effetti personalizzati possono essere creati tramite una classe che implementa l'interfaccia IForceFeedbackEffect
Classe effetto | Descrizione dell'effetto |
---|---|
EffettoForzatoCondizione | Un effetto che applica una forza variabile in risposta al sensore attuale all'interno del dispositivo. |
Effetto di Forza Costante | Effetto che applica la forza costante lungo un vettore. |
EffettoDiForzaPeriodica | Effetto che applica la forza variabile definita da una forma d'onda, lungo un vettore. |
RampForceEffect | Effetto che applica una forza che aumenta o diminuisce in modo lineare lungo un vettore. |
using FFLoadEffectResult = ForceFeedback::ForceFeedbackLoadEffectResult;
auto effect = ref new Windows.Gaming::Input::ForceFeedback::ConstantForceEffect();
auto time = TimeSpan(10000);
effect->SetParameters(Windows::Foundation::Numerics::float3(1.0f, 0.0f, 0.0f), time);
// Here, we assume 'racingwheel' is valid and supports force feedback
IAsyncOperation<FFLoadEffectResult>^ request
= racingwheel->WheelMotor->LoadEffectAsync(effect);
auto loadEffectTask = Concurrency::create_task(request);
loadEffectTask.then([this](FFLoadEffectResult result)
{
if (FFLoadEffectResult::Succeeded == result)
{
// effect successfully loaded
}
else
{
// effect failed to load
}
}).wait();
Uso degli effetti di force feedback
Dopo il caricamento, gli effetti possono essere tutti avviati, sospesi, ripresi e arrestati in modo sincrono chiamando funzioni sulla proprietà WheelMotor
del volante da corsa o singolarmente chiamando funzioni sull'effetto feedback stesso. In genere, devi caricare tutti gli effetti che vuoi usare sul dispositivo di feedback prima dell'inizio del gioco e quindi usa le rispettive funzioni SetParameters
per aggiornare gli effetti man mano che avanza il gioco.
if (ForceFeedbackEffectState::Running == effect->State)
{
effect->Stop();
}
else
{
effect->Start();
}
Infine, è possibile abilitare, disabilitare o reimpostare in modo asincrono l'intero sistema di force feedback su un particolare volante da corsa ogni volta che è necessario.