Individuazione di celle nel raggio d'azione sulla griglia esagonale


8

Prima di tutto, so di essere super denso qui.

A parte questo, sto cercando di scrivere un'implementazione C # di questo algoritmo:

var results = []
for each -N  dx  N:
  for each max(-N, -dx-N)  dy  min(N, -dx+N):
    var dz = -dx-dy
    results.append(cube_add(center, Cube(dx, dy, dz)))

L'ho preso da questa straordinaria risorsa.

Il mio problema è che ogni implementazione di questo che ho provato finora ha avuto risultati folli. Ad esempio, il codice mostrato di seguito attualmente risulta in questo:

1

e questo:

2

Il mio codice attualmente si trova così:

for (int x = this.CellPositionX - distance; x <= this.CellPositionX + distance; x++)
    {
        for (int y = this.CellPositionY - Math.Max(-distance, -x - distance); y <= this.CellPositionY + Math.Min(distance, -x + distance); y++)
        {
            HexPosition rangePosition = new HexPosition(x, y);
            range.Add(rangePosition);
        }
    }

Qualcuno può individuare qualcosa di sbagliato qui? Tutti i suggerimenti sono benvenuti. Ci sto sbattendo la testa da un po 'ormai.

Grazie!

Nota aggiornata: sto usando le coordinate assiali nella griglia. Aggiornamento n. 2: come indicato di seguito, ho sbagliato il ciclo for..each e non ho utilizzato delta per l'allenamento. Grazie per l'aiuto!

Attualmente ho un problema come mostrato di seguito con l'implementazione dalle risposte: inserisci qui la descrizione dell'immagine

Continuerò a indagare: se lo scoprirò, pubblicherò i risultati completi qui. Ringrazia tutti!


1
Grazie per quella risorsa sembra davvero buono! Sono rimasto un po 'sbalordito quando mi sono reso conto che quasi tutta la grafica era interagibile. :)
Christer,

3
L'esempio che fornisce usa le coordinate del cubo, mentre sembra che tu stia usando coordinate offset o assiali. Devi convertire x, y, z dalle coordinate cubiche che ha in qualunque sistema di coordinate stai usando.
Alex Sherman,

1
@ Vector57 Sto usando Axial. Dalla sezione di conversione c'è menzionato che non ho bisogno di fare nulla con la proprietà Z e che q / r e x / y sono intercambiabili ... o l'ho capito male?
aaron-bond

Sembra così, anche se negli esempi usa r = z ma non vedo perché dovrebbe importare quale scegli.
Alex Sherman,

Risposte:


4

Quindi, dopo un'ulteriore ispezione, il problema in realtà non ha nulla a che fare con le conversioni del sistema di coordinate. Ciò avrebbe potuto essere più chiaro non nominando le coordinate assiali X e Y ma piuttosto Q e R. Il problema che si sta effettivamente verificando è in condizioni di loop errate. L'esempio di codice originale produce delta q e r che provi a convertire, nei tuoi per i loop, in coordinate assolute e hai fatto un errore. L'algoritmo dovrebbe invece apparire come segue:

for (int dx = -distance; dx <= distance; dx++)
{
    for (int dy = Math.Max(-distance, -dx - distance); dy <= Math.Min(distance, -dx + distance); dy++)
    {
        HexPosition rangePosition = new HexPosition(
            this.CellPositionX + dx, this.CellPositionY + dy);
        range.Add(rangePosition);
    }
}

Oh derp ... l'articolo menziona persino che sono valori delta :( Lo proverò ora e vedremo come va. Grazie :)
aaron-bond

Grazie per questo. È decisamente molto più vicino al modo giusto di farlo. Sto ancora incasinando qualcosa con le coordinate ma almeno ho il numero giusto! Per qualche ragione sto finendo con una cella troppo alta su -x e una troppo bassa su + x. Ho pubblicato una foto in alto se ne sai qualcosa ma continuerò comunque a indagare su di me :) Grazie per il tuo aiuto!
aaron-bond

Stai interpretando correttamente le coordianti assiali? Ricorda che hai scelto di usare xey anziché xe z, quindi se il resto del codice non tiene conto di questa modifica dagli esempi, può comportare un comportamento strano.
Alex Sherman,

Sì, ho cambiato in modo che sia x e z. dx diventa xe z = -dx - dy ...
aaron-bond

1
La nuova immagine che hai pubblicato mostra 7 esagoni evidenziati. Questo è ciò che ti aspetteresti con la distanza = 1. Prova a stampare i valori. Con CellPosition impostato su 0,0 e distanza 1, gli esagoni che ottieni dovrebbero essere (-1, 0); (-1, 1); (0, -1); (0, 0); (0, 1); (1, -1); (1, 0)
entro il

7

Come notato da Vector57 , il problema è che stai usando un sistema di coordinate errato . L'algoritmo descritto deve essere utilizzato con le coordinate del cubo , che hanno componenti x, ye z :

coordinate del cubo

Questo potrebbe non essere ovvio dallo pseudocodice dell'algoritmo, ma è perché è una semplificazione di questo :

var results = []
for each -N  dx  N:
    for each -N  dy  N:
        for each -N  dz  N:
            if dx + dy + dz = 0:
                results.append(cube_add(center, Cube(dx, dy, dz)))

... un semplice ciclo nidificato su x, ye z, cosa ti aspetteresti da un algoritmo di intervallo.

Non so quale sistema di coordinate stai usando, ma suppongo sia uno dei sistemi di "coordinate coordinate", che sono popolari perché sono facili da implementare posizionando le celle della griglia all'interno di un array 2D:

offset q layout verticali

Questo non significa che non puoi usare questi algoritmi cubi; significa solo che devi convertire dalle coordinate del cubo alle tue . Ad esempio, per convertire in / dal layout verticale "dispari-q", utilizzare questi:

# convert cube to odd-q offset
col = x
row = z + (x - (x&1)) / 2

# convert odd-q offset to cube
x = col
z = row - (col - (col&1)) / 2
y = -x-z

Ho avuto la sensazione che fosse qualcosa del genere. C'era una parte di quella pagina che menzionava la conversione da Cubo ad Assiale e diceva di rimuovere semplicemente la parte z e le restanti q e r diventano x e y. Penso di aver semplificato troppo lì. Grazie per questo. Ottima spiegazione di ciò che mi mancava. Ci proverò più tardi! :)
aaron-bond

Ho appena dato un'occhiata e sto usando assiale. Sicuramente poiché l'algoritmo non fa menzione di Z, è anche una scala q = xe anche un r = ysistema?
aaron-bond
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.