Nei giochi a scorrimento 2D (e in alcuni giochi 3D), è spesso necessario mostrare al giocatore la posizione di un bersaglio fuori dallo schermo, che si tratti di un nemico, di un alleato o di un obiettivo di gioco. Molti giochi usano una freccia che fluttua vicino al bordo dello schermo per indicare in quale direzione si trova il bersaglio. In questo tutorial, spiegherò un metodo che usa l'algebra semplice per trovare dove posizionare una tale freccia indicatore.
La forma di intercettazione della pendenza è un modo per descrivere una retta in 2D con algebra lineare. Usa a pendenza, che normalmente usa il simbolo m
, che definisce la pendenza della linea, e un compensare o intercettare, che usa il simbolo B
, che definisce dove la linea attraversa l'asse y.
\ [y = mx + b \]
Grazie a questa relazione, se abbiamo un valore possiamo usare l'equazione generale per calcolare facilmente l'altro valore, sia concettualmente che matematicamente.
Dal momento che stiamo trovando la posizione relativa allo schermo - una superficie piatta - facciamo tutti i calcoli in 2D, anche se il gioco è in 3D.
Mancia: Se stai lavorando in 3D, dovrai trasformare la posizione del mondo nella posizione dello schermo del tuo oggetto 3D. La maggior parte dei motori tradizionali ha funzioni integrate per fare ciò; consultare la documentazione del motore per ulteriori informazioni.
Se riusciamo a trovare una riga sullo schermo che descrive in quale direzione si trova l'oggetto che stiamo bersagliando, possiamo determinare il punto in cui attraversa ogni dato bordo, e quindi usare un po 'di prove ed errori per scoprire quale lato dello schermo sarà allegato a.
Se immaginiamo che il nostro schermo sia su una griglia e che sia il punto di origine (0, 0)
è proprio al centro dello schermo, quindi è facile calcolare i valori che descrivono la linea.
Poiché la linea passerà attraverso il centro, sappiamo che la nostra intercettazione, B
, deve essere zero E se la griglia è posizionata in questo modo, possiamo facilmente calcolare la pendenza, m
: è semplicemente l'obiettivo y
/X
. (Nell'immagine sopra, il nostro obiettivo è il cursore del mouse.)
Una volta che abbiamo la pendenza, possiamo usare la sostituzione per calcolare dove la linea attraverserebbe i bordi dello schermo. Ad esempio, se vogliamo scoprire quale sia il valore y nel punto in cui la linea attraversa il bordo dello schermo, usiamo la forma originale y = mx
, dove X
è impostato sul bordo dello schermo. Se volessimo trovare dove attraversa la parte superiore o inferiore dello schermo, dividiamo entrambi i lati per m
in modo che l'equazione diventi: x = y / m
- quindi abbiamo appena impostato y
fino al bordo dello schermo.
Mentre la griglia è posizionata in questo modo, il bordo dello schermo sarebbe metà della larghezza dello schermo, negativo per sinistra e positivo per destra. Per l'asse verticale, analogamente, il bordo dello schermo è a metà altezza, ma se è positivo o negativo può variare tra i motori.
Quindi, un gioco 800x600px avrà i bordi dello schermo su x = -400px
, x = + 400 px
, y = -300px
, e y = + 300 px
.
Quanto sopra andrebbe bene se l'origine del sistema di coordinate fosse il centro dello schermo, ma raramente è così. La maggior parte dei motori ha origine nell'angolo superiore sinistro o inferiore sinistro.
Prima di eseguire i nostri calcoli, dobbiamo spostare il nostro spazio di coordinate in modo che tutti i nostri valori siano relativi al centro dello schermo, piuttosto che l'origine predefinita utilizzata dal nostro motore.
Spostamento dello spazio di coordinate. Punti non in scala.Complesso sonoro? Non proprio. Abbiamo solo bisogno di scoprire quanto vogliamo spostare lo spazio delle coordinate e sottrarlo dalla nostra posizione target. Quindi se vogliamo spostare la nostra griglia su metà della larghezza dello schermo, sottraiamo metà della larghezza dello schermo da quella del bersaglio y
valore.
Nell'esempio sopra, la dimensione dello schermo è 800x600px, con lo spazio delle coordinate spostato in modo tale (0, 0)
è al centro del monitor. L'obiettivo fuori campo è a (800, 400)
usando lo stesso spazio di coordinate.
Dato che la coordinata y del bersaglio è positiva (e, in questo motore, l'asse y punta verso l'alto), sappiamo che non si troverà sul bordo inferiore dello schermo, quindi inizialmente troveremo la sua posizione lungo il bordo superiore dello schermo , che è (600, 300)
.
Possiamo dire matematicamente che questo punto è ancora fuori campo perché la sua coordinata x (600
) è maggiore della metà della larghezza (800/2 = 400
), quindi passiamo alla ricerca della sua posizione sul lato dello schermo.
Ancora una volta, dobbiamo solo controllare un lato dello schermo, perché se la nostra coordinata x è positiva, il punto deve trovarsi sul lato destro dello schermo. (Se fosse negativo, dovrebbe essere sul lato sinistro.)
Una volta trovato il punto sul lato destro dello schermo - (400, 200)
- lo sappiamo dovere sii corretto, dal momento che abbiamo escluso ogni altro lato dello schermo attraverso un processo di eliminazione.
Oltre a posizionare l'indicatore, potresti volerlo anche ruotare per ottenere un effetto extra, specialmente se si tratta di una freccia. C'è una comoda funzione che fa parte della maggior parte delle classi matematiche che risolve questo problema piuttosto facilmente: atan2 ()
.
Il atan2 ()
la funzione richiede due parametri: una coordinata x e una coordinata y. Restituisce un angolo che indica la direzione da (0, 0)
a (x, y)
.
rotation = Math.atan2 (centerMouse.top, centerMouse.left); rotazione = rotazione * 180 / Math.PI; // converti i radianti in gradi
Ci sono un paio di cose da tenere a mente atan2 ()
che può variare tra lingue e motori. In primo luogo, gli argomenti sono spesso atan2 (y, x)
, mentre la maggior parte delle altre funzioni matematiche prende prima la coordinata x. Inoltre, la rotazione viene spesso restituita in radianti piuttosto che in gradi.
Mancia: Non entrerò nelle differenze tra i radianti e gradi, tranne per dire che la conversione da uno all'altro è facile: basta moltiplicare i radianti per (180 / Pi)
per trasformarli in gradi e moltiplicarli per (Pi / 180)
se vuoi cambiarli di nuovo.
C'è un'ultima cosa che dobbiamo controllare prima di fare un indicatore fuori campo, e cioè se il nostro obiettivo è effettivamente fuori dallo schermo, dal momento che non ha molto senso indicare la direzione del nostro obiettivo se possiamo già vedere il nostro obiettivo. Di nuovo, useremo una matematica molto semplice per risolvere questo problema.
Dato che il nostro schermo è un rettangolo non ruotato, non abbiamo bisogno di fare nulla con gli angoli, dobbiamo solo controllare se il nostro punto di mira è inferiore a quello superiore, più alto del fondo, a sinistra del bordo destro, e a destra del bordo sinistro dello schermo.
var screen = width: 200; height: 100 // dummy values alert (isTargetOnScreen (left: 50; top: 60)); // True alert (isTargetOnScreen (left: 250; top: 10)); // False function isTargetOnScreen (target) if (target.top> 0 && target.top < screen.height && target.left < screen.width && target.left > 0) // il target è sullo schermo, usa una sovrapposizione o non fa nulla. ritorna vero; else // il target è fuori dallo schermo, trova la posizione dell'indicatore. restituisce falso;
Usando i valori fittizi sopra, troviamo che il bersaglio è sullo schermo. Questi valori possono provenire da qualsiasi luogo in cui sono archiviate informazioni sull'oggetto che stai monitorando.
Si noti che il codice sopra presuppone che ci troviamo nello spazio delle coordinate dove (0, 0)
è nel angolo dello schermo, come la maggior parte dei motori avrà di default. Pertanto, questo passaggio dovrebbe essere fatto prima di spostare lo spazio delle coordinate verso il centro come facciamo quando calcoliamo la posizione dell'indicatore.
Ecco una breve demo per mostrare questi concetti in azione (guarda il codice su GitHub):
Passiamo attraverso il codice:
Ecco qua: un comodo snippet di codice da aggiungere all'interfaccia utente del tuo gioco. Ora che puoi puntare il giocatore nella direzione di un bersaglio, considera come potresti visualizzare anche la distanza.