Prima di tutto, so esattamente qual è il mio problema di disegno e ho varie idee su come approcciarlo. Sono qui per capire come regolare quale cornice è disegnata in modo tale da mantenere l '"illusione" isometrica.
Sto scrivendo un gioco 2D a volo d'uccello che si svolge nello spazio. Sto cercando di usare la grafica isometrica in un mondo in cui Up is North, nessuna rotazione del mondo di gioco come nei tradizionali giochi isometrici (ricorda, il gioco si svolge nello spazio, senza terreno). Ecco un esempio di sprite che sto cercando di utilizzare: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.png Ruotato di 64 volte attorno al proprio asse verticale con un angolo di visione di 35 gradi (aka, iso). L'immagine è stata generata, quindi può essere cambiata.
Per motivi di chiarezza, ho dettato che Nord (su) è 0 gradi e est (destra) è 90.
Il mio problema è che il mio sprite non sembra sempre essere rivolto verso il punto in cui il gioco pensa che sia dovuto a una differenza negli aerei 3D utilizzati. Non sono sicuro se sto usando correttamente la terminologia, ma la mia astronave è stata ruotata su un piano e il piano della vista si aspetta che le cose vengano ruotate sul proprio piano. Ecco una rappresentazione del problema:
http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectionIssue.png A sinistra, ho viste laterali, a destra ho viste dall'alto verso il basso. In cima, ho la nave spaziale / sprite vista del mondo. In fondo, ho l' aspetto di uno sprite quando viene disegnato sullo schermo.
In alto a destra c'è una versione semplificata di come è stata ruotata la mia astronave (anche gradi di separazione tra ciascun fotogramma). In basso a destra è l'angolo con cui lo sprite sembra essere rivolto verso l'alto quando viene disegnato un angolo particolare sullo schermo. Il problema è più evidente a circa 45 gradi. Ecco un'immagine che è sovrapposta a una linea di "piano dello schermo" che è puntata nella direzione in cui dovrebbe trovarsi la nave: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.png La linea rossa dovrebbe sempre essere puntata esattamente nella stessa direzione della nave, ma come puoi vedere, il problema di proiezione sta causando un problema. Spero di descrivere abbastanza bene il problema.
EDIT: la linea rossa viene ruotata sul piano dello schermo, mentre la nave spaziale viene ruotata sul "piano della nave", quindi la grande differenza tra l'angolo della nave e l'angolo dello schermo quando viene disegnato. MODIFICA FINE
Sembra piuttosto strano quando questa nave sta sparando un raggio laser su un bersaglio che si trova su un lato, quando dovrebbe sparare dritto.
Quindi ... le soluzioni che ho escogitato sono:
- Smetti di provare a simulare una vista isometrica, vai alla grande o vai a casa. Ruota già il mio mondo. (PS: questo risolverà il mio problema, giusto?)
- Modifica il mio foglio sprite (in qualche modo) per avere dei frame che rappresentino l '"angolo dello schermo" in cui il modello verrà visualizzato. Quindi, quando chiedo un'immagine a 45 gradi, sembrerà effettivamente che sia rivolta a 45 gradi sullo schermo.
- Modifica il mio sistema di rendering sprite per prendere un frame diverso dal foglio sprite (in qualche modo), sapendo che afferrare il frame "normale" sembrerà divertente. Quindi, invece di afferrare la cornice a 45 gradi, afferrerà la cornice a ... 33 gradi (solo indovinando) in modo che appaia corretta per l'utente.
- Usa il 3D! È molto più facile, amico
Per uno: quale soluzione consiglieresti? Mi sto inclinando verso il 2, anche se so che è sbagliato. Ricorda che ho pieno accesso allo strumento di generazione degli sprite. Il metodo 3 sarebbe la mia seconda scelta. Entrambi questi metodi richiedono semplicemente che io applichi un po 'di matematica agli angoli per ottenere il risultato desiderato. A proposito, ho aggiunto il n. 4 come scherzo, non voglio passare al 3D.
Per due: usando i metodi 2 o 3, come dovrei regolare gli angoli di input o output? Non sono poi così bravo con le proiezioni 3D e le matrici 3D (per non parlare delle matrici 2D) e qualunque altra matematica possa essere usata per ottenere il risultato desiderato.
Pensare ad alta voce qui: se prendo un vettore unitario rivolto nella direzione in cui voglio che la nave guardi (sul piano dello schermo), quindi lo proietto sul piano della nave, quindi capisco quale sia l'angolo tra quella linea proiettata e quella del piano a nord, dovrei avere l'angolo del grafico della nave che voglio visualizzare. Giusto? (soluzione per # 3?) Amico ... Non riesco a risolverlo.
MODIFICARE:
So che il problema è difficile da visualizzare con immagini statiche, quindi ho rispettato il mio Visual Test Tester della Sprite Library per visualizzare il problema: http://cell.stat-life.com/downloads/SpriteLibVisualTest.zip Richiede XNA 4.0 Questa applicazione è semplicemente ruotando lo sprite e disegnando una linea dal suo punto centrale verso l'esterno nell'angolo in cui il gioco pensa che la nave dovrebbe essere rivolta.
MODIFICA 8 settembre
Continuando dal mio paragrafo "pensare ad alta voce": invece di usare una proiezione (perché sembra difficile) sto pensando che potrei prendere un vettore di unità rivolto a nord (0x, 1y, 0z), usare una matrice per ruotarlo sull'angolo lo sprite è effettivamente rivolto, quindi ruotalo di nuovo dal "piano di osservazione" verso l'esterno al "piano di sprite" attorno all'asse X, quindi ... appiattisci? il vettore (essenzialmente lo proietta) di nuovo sul piano di visualizzazione usando solo X e Y (ignorando Z). Quindi usando quel nuovo vettore appiattito, ho potuto determinarne l'angolazione e usarlo per ... qualcosa. Ci penserò più tardi.
EDIT 8 settembre (2)
Ho provato a seguire la mia idea dall'alto con un certo successo, yay! Quindi ... per far sembrare che una linea rossa stia uscendo direttamente dalla mia astronave (solo a scopo di test), ho fatto quanto segue:
Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);
float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));
Dov'è rotation
l'angolo dello schermo e adjustedRotation
ora l'angolo dello schermo appare sul piano dello sprite. Non so perché avessi bisogno di ruotare Y invece di X, ma è probabilmente qualcosa a che fare con il 3D di cui non sono a conoscenza.
Quindi, ora ho un'informazione aggiuntiva, ma come posso usarla per scegliere una cornice più appropriata? Forse invece di ruotare dal piano di visualizzazione al piano di sprite, quindi proiettare indietro, dovrei provare a farlo al contrario. Ecco il mio sprite con una linea rossa corretta, ma quello che voglio davvero fare è regolare il modello, non la linea: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png
MODIFICA 9 settembre
Horay! È sistemato! Descriverò cosa ho fatto per risolverlo:
Ho seguito il consiglio di eBusiness e "schiacciato" dal sistema di coordinate del mondo (o allungato ...?). Questa è essenzialmente la soluzione n. 1, anche se avevo l'impressione che avrei dovuto ruotare il mio sistema di coordinate del mondo in relazione al sistema di coordinate dello schermo. Non vero! Su è ancora + y e Destra è ancora + x. Ho modificato i miei metodi WorldToScreen e ScreenToWorld per convertirli correttamente tra il mondo e le coordinate dello schermo. Questi metodi potrebbero non essere ottimali, ma qui sono gli unici due metodi nella mia base di codice che hanno dovuto cambiare.
public Vector2 ScreenToWorld(float x, float y)
{
float deltaX = x - (size.Width / 2f);
float deltaY = y - (size.Height / 2f);
deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
deltaY = deltaY * scaleFactor;
return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}
public Vector2 WorldToScreen(float x, float y)
{
float deltaX = x - focusWorldPoint.X;
float deltaY = y - focusWorldPoint.Y;
deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
deltaY = deltaY / scaleFactor;
return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}
Questo è stato! La modifica di questi due metodi ha influito su tutto il resto: ciò che stavo guardando, dove gli oggetti erano disegnati, dove stavo facendo clic, tutto. La mia astronave ora guarda direttamente il bersaglio che sta sparando e tutto sta andando a posto. Sperimenterò la proiezione ortografica, vedremo se tutto sembra più "reale".