Come si evita l '"effetto scala" nel movimento della pixel art?


21

Sto eseguendo il rendering di sprite con esatte coordinate pixel per evitare l'effetto sfocato causato dall'antialias (gli sprite sono pixel art e apparirebbero orribili se filtrati). Tuttavia, poiché il movimento degli oggetti comporta velocità variabile, gravità e interazioni fisiche, la traiettoria viene calcolata con precisione subpixel.

A velocità dello spazio dello schermo sufficientemente grandi (vΔt maggiore di 2 o 3 pixel) funziona molto bene. Tuttavia, quando la velocità è piccola, può apparire un evidente effetto scala, specialmente lungo linee diagonali. Questo non è più un problema a velocità dello schermo molto lente (v << 1 pixel al secondo), quindi sto solo cercando una soluzione per valori di velocità intermedi.

A sinistra è la traiettoria tracciata per una grande velocità, ottenuta per semplice arrotondamento delle coordinate dell'oggetto. Nel mezzo puoi vedere cosa succede quando la velocità si riduce e l'effetto della scala di cui sto parlando. A destra, il luogo della traiettoria che vorrei ottenere.

coordinate pixel per la traiettoria dell'oggetto

Sono interessato alle idee dell'algoritmo per filtrare la traiettoria al fine di minimizzare l'aliasing, mantenendo il comportamento originale a velocità grandi e piccole. Ho accesso a Δt, posizione istantanea e velocità, nonché a un numero arbitrario di valori precedenti, ma poiché si tratta di una simulazione in tempo reale, non conosco i valori futuri (anche se, se necessario, una stima potrebbe essere estrapolata in base a determinati presupposti) . Si noti che a causa della simulazione fisica, possono anche verificarsi improvvisi cambi di direzione.

Risposte:


18

Ecco un rapido schema, dalla parte superiore della mia testa, di un algoritmo che dovrebbe funzionare abbastanza bene.

  1. Innanzitutto, calcola la direzione in cui si sta muovendo l'oggetto e controlla se è più vicino all'orizzontale o verticale.
  2. Se la direzione è più vicina alla verticale (orizzontale), regola la posizione dell'oggetto lungo il vettore di direzione al centro della riga di pixel più vicina (colonna).
  3. Arrotonda la posizione al centro del pixel più vicino.

In pseudocodice:

if ( abs(velocity.x) > abs(velocity.y) ) {
    x = round(position.x);
    y = round(position.y + (x - position.x) * velocity.y / velocity.x);
} else {
    y = round(position.y);
    x = round(position.x + (y - position.y) * velocity.x / velocity.y);
}

Modifica: Sì, testato, funziona abbastanza bene.


+1, funziona sorprendentemente bene! Vedo strani salti all'indietro con movimento circolare a basse velocità, perché la regolazione può essere eseguita nella direzione opposta al vettore di velocità (che di solito è OK, ma non con piccole curvature della traiettoria). Ciò può essere risolto moltiplicando velocity.y / velocity.xper un fattore di correzione proporzionale alla velocità.
Sam Hocevar,

@ Sam: intendi un raggio di sterzata ridotto (= curvatura elevata), giusto? Ciò potrebbe effettivamente causare problemi con l'estrapolazione lineare a basse velocità. (Fondamentalmente, funziona fintanto che la velocità al quadrato per accelerazione è molto più grande di 1 pixel.) Una possibile soluzione (klugey) potrebbe essere quella di ricordare l'ultima posizione arrotondata e riutilizzarla se è più vicina alla posizione reale rispetto a quella appena calcolata. (Si potrebbe anche provare l'estrapolazione di ordine superiore, ma le formule diventano piuttosto brutte.)
Ilmari Karonen,

Anzi, intendevo piccolo raggio. Colpa mia. E grazie per i suggerimenti aggiuntivi; le prestazioni non sono fondamentali, quindi posso permettermi di migliorare la qualità.
Sam Hocevar,

3

Non c'è molto che tu possa davvero fare al riguardo per un mondo basato sulla fisica generale. Se tutti i tuoi oggetti si muovessero lungo linee o cerchi specifici, potresti fare qualcosa. Ma stai operando sotto la fisica reale. L'oggetto è dove la fisica lo mette; stai semplicemente disegnando un'approssimazione basata su pixel di quella posizione.

In genere è qualcosa che devi accettare se vuoi rimanere con le coordinate dei pixel. Non dovrebbe essere troppo evidente a meno che non si stia visualizzando a una risoluzione incredibilmente piccola (inferiore a 640x480, anche se dipende dalla risoluzione e dalle dimensioni native del display).


Anche ad alte risoluzioni, il rendering viene ingrandito (il vicino più vicino) per migliorare l'aspetto della vecchia scuola. Questa è una decisione di direzione artistica.
sam hocevar,

@SamHocevar: Se vuoi un "aspetto oldschool", perché non vuoi un "aspetto oldschool" completo ? Perché il passo delle scale, che qualsiasi gioco "oldschool" avrebbe avuto, non fa parte dell'effetto complessivo che vuoi ottenere?
Nicol Bolas

Non credo che nessun gioco di vecchia scuola decente avrebbe implementato un movimento diagonale che ha quell'effetto scala, perché sarebbe sembrato una schifezza. Non sembrare una merda è una parte importante dell'effetto oldschool che desidero ottenere :-)
sam hocevar,

@SamHocevar: la maggior parte dei giochi di vecchia scuola sono giochi d'azione e quindi non si muovono abbastanza lentamente da accorgersene. Inoltre, tendono a non muoversi lungo le curve. Il gioco in particolare a cui stavo pensando era Solar Jetman, che ha molto effetto quando si muove lentamente. Certo, la fotocamera è sempre centrata su di te, quindi la noti nei movimenti del mondo, ma è davvero lì.
Nicol Bolas,

3

Quando il movimento in sospeso è perpendicolare all'ultimo movimento (nello spazio dello schermo), ignoralo e usa le coordinate dell'ultimo schermo. Se questo porta a una balbuzie che è tanto grave quanto la scala, potresti provare a spostare la somma del movimento in sospeso e dell'ultimo movimento.

Penso che il problema risieda in v <sqrt (2). v> sqrt (2) dovrebbe sempre spostarsi di almeno una diagonale completa, evitando l'effetto scala. Forse utile per la potatura che necessita dei precedenti confronti di movimento.


+1 per indicare un limite superiore per il suggerimento di v. Ilmari è più dettagliato ma stai fornendo informazioni utili.
sam hocevar,
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.