Finta grafica isometrica in un gioco spaziale 2D


15

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:

  1. 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?)
  2. 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.
  3. 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.
  4. 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'è rotationl'angolo dello schermo e adjustedRotationora 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".


Congratulazioni. Non dimenticare di prendermi in giro una volta che hai qualcosa di giocabile, mi piacerebbe vedere dove va.
aaaaaaaaaaaa

@eBusiness Come promesso: cell.stat-life.com/images/stories/AsteroidOutpost/… e cell.stat-life.com/images/stories/AsteroidOutpost/AOOhNoes.png Notare come la nave sembra guardare quella torre? : D Grazie!
John McDonald,

@eBusiness, un video youtube.com/watch?v=Q8pR9KDBsCo C'è anche un link da scaricare, da quando hai chiesto.
John McDonald,

Risposte:


4

Dopo aver scelto la prospettiva isometrica, è necessario correggere la scala tra l'asse X e l'asse Y. Se una data distanza viene proiettata su 1 sull'asse Y degli schermi, la stessa distanza verrà proiettata su sqrt (3) sull'asse X degli schermi. Quindi se disegni cose piatte sullo schermo faresti qualcosa del tipo:

draw(object.image, object.x*sqrt(3), object.y)

Note senza risposta:

  • Perché dovresti fare casini con fogli di sprite e cose? Puoi ottenere un renderer 3D per fare isometrico se vuoi.
  • Dato che stai usando i fogli sprite, perché non sono anti-aliasing?
  • Isometrico nello spazio, non credo di aver mai visto un gioco usarlo, non sono sicuro di quanto funzionerà dato la mancanza di un terreno chiaramente isometrico per riferimento visivo.

1
Penso ... Questo potrebbe risolvere tutto. È una soluzione semplice e posso lasciare il foglio da solo. Lo proverò al più presto e ti farò sapere come va. Per rispondere alle tue note: 1) Sto usando il 2D perché è ciò che mi è familiare e sto generando i miei fogli da modelli 3D. 2) I bordi dovrebbero essere nitidi, ma all'interno dei bordi duri potrei usare il canale alfa per l'anti-alias, che verrà. 3) Non ho intenzione di simulare (molto) la terza dimensione, voglio principalmente grafica 2D che non sia dall'alto verso il basso e ti permetta di vedere i lati delle cose.
John McDonald,

5

Come viene generato lo sprite ruotato? Questi screenshot sono di un modello 3D rotante? L'angolo di fronte potrebbe essere disattivato a causa della prospettiva della videocamera dello strumento di modellazione 3D. La prospettiva isometrica non è una rappresentazione accurata dello spazio 3D. Le cose lontane dalla "fotocamera" non si riducono.

Se vuoi solo una soluzione rapida. La soluzione 2 potrebbe essere difficile da ottenere. La soluzione 3 sembra facile, basta scambiare i frame non abbinando l'angolo con uno che si adatta meglio all'angolo.

I laser saranno ancora spenti a volte. Dato che non stai eseguendo una rotazione regolare ma mostrando cornici diverse per determinati intervalli di gradi.

MODIFICARE:

Il tuo problema è che gli screenshot generati non sono una prospettiva isometrica, ma una normale vista della videocamera 3D.

inserisci qui la descrizione dell'immagine

La vista isometrica simula lo spazio 3D ma non è una rappresentazione accurata. Le cose si riducono con l'aumentare della distanza dalla fotocamera. Questo non viene fatto per la prospettiva isometrica in quanto ciò causerebbe brutti artefatti di ridimensionamento nello sprite.

Le schermate delle astronavi sono realizzate con la prospettiva della videocamera 3D. Ecco perché le riprese laser sono disattivate. Confronta la linea rossa in "isometrica" ​​e "prospettiva".

Il generatore di sprite dovrebbe usare Matrix.CreateOrthographic () invece di Matrix.CreatePerspective () per la matrice di proiezione.


Lo sprite viene generato utilizzando uno strumento da 3D a 2D che sto sviluppando, quindi il problema potrebbe benissimo essere in quello strumento. Lo strumento carica semplicemente un modello 3D, quindi per ottenere Spaceship64.png (sopra), ruota il modello di (360/64) = 5,625 gradi, lo salva come una cornice, quindi lo ruota di nuovo della stessa quantità fino a quando non ha tutto 64 fotogrammi. Il codice utilizzato per il rendering del modello è qui: code.google.com/p/sprite-maker/source/browse/trunk/XNAWindow/… La rotazione viene eseguita in un'altra classe. Pensavo anche che la soluzione 2 e 3 fossero l'inverso l'una dell'altra, no?
John McDonald,

Modificato la mia risposta. Vedi sopra.
Stephen,

Penso che potrei aver bisogno di fare entrambe le cose: fare in modo che il mio generatore di sprite usi una proiezione ortografica E modifichi il mio sistema di coordinate del mondo come quello che dice @eBusiness. Ho provato la proiezione ortografica ieri sera, e certamente ha cambiato l'aspetto della mia nave, ma da sola non ha risolto il problema dell'angolo che sto vivendo.
John McDonald,

Ho appena visto la tua modifica. Lo sprite corretto sembra che il centro della nave sia fuori dal centro della linea rossa. Forse è sufficiente disegnare la nave di uno o due pixel più in alto del punto iniziale della linea rossa. L'errore visibile cambia mentre la nave si allontana dalla tua origine mondiale? Quindi il ridimensionamento dell'asse X potrebbe risolvere questo problema.
Stephen,

1

Penso che quello che hai qui sia semplicemente l'aspetto isometrico. Hai ragione in questo, visivamente parlando, sembra esserci una differenza più grande tra 0 ° e 10 ° rispetto a tra 90 ° e 100 °. . . ma questo perché isometrica comprime intrinsecamente un asse. Se non vuoi quello sguardo, non vuoi isometrico.

Detto questo, penso che i problemi visivi che stai riscontrando siano dovuti al fatto di non avere un punto di riferimento visivo. Il tuo cervello presume che tu lo stia guardando dall'alto verso il basso - ehi, è spazio, perché non dovresti essere - e lo sta interpretando come una vista dall'alto verso il basso standard. Per motivi di test, prova ad aggiungere alcuni punti di riferimento olografici mobili. Una griglia inclinata di 45 gradi, ad esempio, o una serie di cerchi di portata attorno al tuo veicolo spaziale. Assicurati che siano opportunamente distorti come se fossero sullo stesso piano isometrico su cui è renderizzata l'astronave. Scommetto che il tuo cervello capirà la prospettiva e all'improvviso sembrerà giusto.

Ora, capire come comunicare ai tuoi utenti. . . questa è un'altra questione.


Non dovrò anche ruotare l'asse mondiale per completare l'illusione usando questo metodo (metodo n. 1 nella domanda)?
John McDonald,

Per quanto ne so, la nave è già stata renderizzata correttamente - le viste laterali mostrano che dovrebbe essere "corretta" nell'isometria. Suppongo di non essere sicuro di cosa intendi per "ruotare l'asse mondiale".
ZorbaTHut,

Con "ruota l'asse del mondo", intendo ruotare il mondo in relazione alla telecamera di 45 gradi per fare in modo che "Nord" sia verso la parte superiore destra o superiore sinistra dello schermo in diagonale anziché "Nord" verso l'alto verso la parte superiore dello schermo.
John McDonald,


Ciò potrebbe aiutare, ma nello spazio non dovrebbe fare comunque molta differenza. A meno che tu non abbia una griglia sovrapposta al mondo, non dovrebbe importare.
ZorbaTHut
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.