Domanda

Al momento scrivendo un roguelike saperne di più su Objective-C / Cocoa. Sono davvero molto finora e ho imparato tonnellate.

Questo codice sposta il origin della bounds della vista, in modo che segua il giocatore mentre si muove. Il codice funziona perfettamente, stavo solo chiedendo se ci fosse un modo migliore rispetto all'utilizzo di quattro for di.

Ho visto anche in alcuni casi che è meglio fare le cose separatamente invece di tutto in uno, soprattutto dove il disegno e nsbezierpath è interessato, perché?

Modifica :. La gente stava avendo difficoltà a capire esattamente quello che sto facendo, così ho intenzione di scomposizione per quanto mi è possibile

Il view è una griglia 30x30 (0-29,0-29) di piastrelle, 20x20 ciascuno. La mappa può essere grande o piccolo, come deve essere.

In primo luogo, si ottiene il [player_ location], insieme con la origin del bounds per la view. E 'diviso per 20 perché il formato delle mattonelle è 20, così quando è al (1,2), in realtà è a (20,40). L'unica ragione per cui lo faccio è quello di rendere più facile da manipolare (E 'più facile contare in unità di 1 invece di 20). I quattro for di passare attraverso e controllare che il [player_ location] è a piastrelle 15 del centro (bounds + 15) del view. Se il giocatore si sta muovendo verso uno dei bordi dello schermo, e bounds.x/y + 30 è inferiore all'altezza della corrente mappa / larghezza, si muove l'origin in modo che il giocatore è ancora centrata e visualizzato sulla mappa.

Il codice funziona perfetto, e ho spostato il setbounds al dopo della for accadere, e solo uno c'è. Non è stato lasciato in drawRect, ho appena avuto qui per cercare di capire cosa dovevo fare. E 'ora in un suo posto e viene chiamato solo quando il giocatore si muove in realtà.

Ecco il nuovo codice:

- (void)keepViewCentered
{
    NSPoint pl = [player_ location];
    NSPoint ll;
    NSPoint location = [self bounds].origin;
    ll.x = location.x / 20;
    ll.y = location.y / 20;
    for ( pl.y = [player_ location].y; pl.y >= ll.y + 15 && ll.y + 30 < [currentMap_ height]; ll.y++ )
    {
        location.y = ll.y * 20;
    }
    for ( pl.x = [player_ location].x; pl.x >= ll.x + 15 && ll.x + 30 < [currentMap_ width]; ll.x++ )
    {
        location.x = ll.x * 20;
    }
    for ( pl.y = [player_ location].y; pl.y <= ll.y + 15 && ll.y >= 0; ll.y-- )
    {
        location.y = ll.y * 20;
    }
    for ( pl.x = [player_ location].x; pl.x <= ll.x + 15 && ll.x >= 0; ll.x-- )
    {
        location.x = ll.x * 20;
    }
    [self setBoundsOrigin: location];
}

Ecco le immagini di esso in azione!

Figura 1: Questo è il giocatore a 1,1. Niente di speciale. http://sneakyness.com/stackoverflow/SRLbounds1.png

Figura 2: I 3 pezzi d'oro rappresentano quanto il giocatore può muoversi prima bounds.origin della vista si sposterà per rimanere centrato sul lettore. Anche se irrilevante, si noti che il giocatore non può effettivamente vedere l'oro. Risulta campo programmazione di visione è un campo di dibattito e ci sono diversi algoritmi che si possono usare, nessuno dei quali non hanno lati negativi, o sono stati portati su Objective-C. Attualmente è solo un quadrato. Vedere attraverso i muri e tutto il resto. http://sneakyness.com/stackoverflow/SRLbounds2.png

Figura 3: La visualizzazione con un bounds.origin diversa, centrata sul lettore. http://sneakyness.com/stackoverflow/SRLbounds3.png

È stato utile?

Soluzione

  

E 'ora in un suo posto e viene chiamato solo quando il giocatore si muove in realtà.

Yay!

  

Stavo solo chiedendo se ci fosse un modo migliore di utilizzare quattro for di.

Ecco il mio consiglio:

  1. Imposta il basso a sinistra per la posizione del giocatore meno 15.
    ll.x = [player_ location].x - 15.0;
    ll.y = [player_ location].y - 15.0;
  2. Assicurarsi che non superi i limiti della vista.
    if (ll.x < 0.0)
        ll.x = 0.0;
    if (ll.y < 0.0)
        ll.y = 0.0;
    if (ll.x > [currentMap_ width] - 30.0)
        ll.x = [currentMap_ width] - 30.0;
    if (ll.y > [currentMap_ height] - 30.0)
        ll.y = [currentMap_ height] - 30.0;
  3. Moltiplicare per la dimensione piastrella e impostare come nuova origine limiti. location.x = ll.x * 20,0; location.y = ll.y * 20,0; [Auto setBoundsOrigin: location];

Propongo inoltre che non hard-code il formato delle mattonelle ed il giocatore di vista gamma.

Per il formato delle mattonelle, si può scegliere di dare la vostra vista un paio di proprietà che esprimono la larghezza e l'altezza in piastrelle, quindi utilizzando il marchio comunitario di scalare a (widthInPoints / widthInTiles), (heightInPoints / heightInTiles). Poi si può permettere all'utente di ridimensionare la finestra per modificare le dimensioni delle piastrelle.

Per la gamma di vista del giocatore (attualmente 30 piastrelle quadrato), si consiglia di rendere questa una proprietà del giocatore, in modo che possa cambiare con statistiche di abilità, oggetti equipaggiati, e gli effetti di pozioni, attacchi di mostri, e ire degli dei. Un avvertimento: se gamma di vista del giocatore può diventare più lunga della finestra di gioco si adatta (soprattutto in verticale), si vorrà aggiungere un assegno per che al codice di cui sopra, e gestirlo mettendo il giocatore punto morto e, eventualmente, lo zoom fuori.

Altri suggerimenti

Non ho chiaro che cosa si sta cercando di fare qui, ma è molto, molto inefficiente. Si sta chiamando setBoundsOrigin: più volte, il che significa che solo l'ultima chiamata in realtà sta facendo nulla. Impostazione origine a metà del drawRect: non provoca nulla di muoversi. Un'intera serie di drawRect: disegna un singolo "frame" se stai pensando a questo come un'animazione.

Ricordate, non siete responsabile del ciclo di disegno. drawRect: viene chiamato dal framework quando si decide che è necessario disegno. Ci sono vari suggerimenti si possono dare al quadro (come setNeedsDisplay:), ma alla fine è il quadro che vi chiama quando ha bisogno di qualcosa.

Se il vostro intento è l'animazione, ti consigliamo di leggere la Nucleo Guida Animation programmazione . Sarà discutere modi molto semplici ed efficienti per gestire le animazioni. Animare le cose intorno allo schermo è uno dei grandi punti di forza di cacao, e le cose abbastanza complesse può essere fatto molto facilmente.

  

in alcuni casi ... è meglio farlo separatamente invece di tutto in uno ...

Sì. Avere un metodo drawBackgroundTile:, e forse un metodo drawItem: e un metodo drawPlayer:, e chiamare questi in un ciclo entro drawRect:-che dovrebbe richiamare tutto il forum per il livello. Questa è la soluzione non basata su livelli.

L'altro, come ho notato nel mio commento sulla risposta di Rob, è quello di utilizzare Core Animation. Si potrebbe quindi ascia drawRect: del tutto, e hanno la visualizzazione ospitare uno strato radice, che conterrebbe posatori, alcuni dei quali conterrebbe strati voce e l'attore (lettore / mostro / animale).

  

Perché?

Perché è una soluzione adeguata, efficiente e leggibile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top