Che cos'è il "codice logico di gioco?"


50

Sto usando C # / XNA e mi è stato detto molte volte di non mescolare il codice di aggiornamento con il codice di disegno - e sono certo che non lo sono! Ma qualcuno potrebbe descrivere cos'è esattamente il "codice logico"?

Come visto qui: http://blogs.msdn.com/b/shawnhar/archive/2007/07/25/understanding-gametime.aspx

[...] assicurati di inserire tutta la tua logica di gioco all'interno del metodo Update (non in Draw!) e tutto funzionerà a una buona velocità costante.

Lo sto chiedendo poiché la velocità del mio gioco è variabile rispetto all'FPS. FPS lento equivale a oggetti a movimento lento e viceversa. E sì, sto includendo il position += speed * (float)gt.ElapsedGameTime.TotalSeconds;codice previsto .

Questa è probabilmente una grande domanda da principiante, ma voglio solo essere assolutamente chiaro sulla definizione di questo.


Penso che volevi dire position = speed * ...TotalSeconds. Si noti che =non lo è +=. Se fosse +=esattamente come hai digitato, la tua posizione volerebbe fuori dallo schermo quasi istantaneamente.
DrZ214,

Ho un codice che assomiglia a 'position + = direction * speed * ... TotalSeconds' e che funziona molto bene. Potrei aver sbagliato a scrivere qualcosa, ma position = speed gli assegnerebbe ogni aggiornamento. La tua strada potrebbe funzionare, ma il mio codice funziona in questo modo. (Nota che la direzione è normalizzata)
Timido Guy

Ho pensato che fosse gt.ElapsedGameTime.TotalSecondsil numero di secondi trascorsi dall'avvio del programma (gioco). Se stai moltiplicando la tua velocità per quella, quindi dopo 5 secondi di gioco, la tua velocità sarà 5 volte più veloce (tranne il caso speciale in cui la velocità è impostata su 0). Non sono sicuro di cos'altro potresti rendere ciò non vero, ma sono incuriosito.
DrZ214,

1
Ah, è dall'ultimo aggiornamento. gamedev.stackexchange.com/questions/67968/…
Timido ragazzo

2
Affascinante che non avrei mai immaginato. Non ho mai avuto bisogno di una cosa del genere in pochi secondi, perché uso personalmente la mia variabile chiamata iiiche incremento manualmente ogni aggiornamento, perché non la voglio in pochi secondi, voglio passaggi o frame. Vedo che la tua strada è comunque un modo valido per codificare le cose.
DrZ214,

Risposte:


102

Cambia lo stato del tuo mondo di gioco? È un codice logico.

Mostra lo stato del mondo di gioco? È il codice di rendering.


Esaminerò il mio codice per essere sicuro al 100%. Buona spiegazione, grazie.
Timido Guy

38
Gestisce l'input? Il suo codice controller. Separare il controllo dalla logica, in modo da poter utilizzare la stessa logica con diversi tipi di controlli. Ad esempio un FPSInputController + CharacterMotor vs. AIInputController + CharacterMotor vs NetworkInputController (ad esempio altri giocatori in un'istanza multiplayer) + CharacterMotor. Il motore (codice logico) non si preoccupa di come ottiene le istruzioni, ma solo che vengono fornite (questo tipo di disaccoppiamento consente una facile transizione dal giocatore al bot AI (pensa a Left 4 Dead e giocatori inattivi) e viceversa, tra le altre cose).
Draco18s

10
Draco solleva un buon punto. Esistono molte diverse divisioni che puoi inserire nel codice. La divisione di Nils è quella che considererei la divisione archetipica tra logica e rendering, ma ci sono molti altri livelli che vedrai. Il vero motivo per separarli in livelli è che ogni livello è costituito da azioni simili che richiedono uno stile di codice simile con requisiti simili. Ad esempio, in molti giochi, è possibile cavarsela con la logica di gioco che richiede 2 o 3 fotogrammi per il completamento, ma se non si esegue il rendering di ciascun fotogramma, l'occhio dell'utente noterà rapidamente.
Cort Ammon,

Mantenerli distinti ti aiuterà a gestire le tue esigenze quando iniziano a diventare fonte di stress.
Cort Ammon,

6
E ricorda che se ci lanci troppo MVC può rallentare fino a gattonare, quindi cerca sempre un equilibrio tra manutenibilità e ottimizzazione. Ma non ottimizzare troppo presto, a meno che tu non sia assolutamente sicuro di ciò che stai facendo. E ricorda che puoi sempre refactoring. E ... Uh, fai molti giochi e impara dai tuoi errori.
Maurycy,

24

La tua separazione è corretta se:

  • Chiamare Draw () più volte di seguito senza chiamate intervallate a Update () non comporterebbe mai cambiamenti visibili tra le chiamate.
  • Chiamare Update () più volte di seguito senza una chiamata intervallata a Draw () sarebbe come giocare con lo schermo spento: tutto si muove perfettamente e coerentemente, semplicemente non riesci a vederlo.

5
Scritto correttamente Draw()può disegnare immagini diverse col passare del tempo. Ad esempio, i frame di sprite animati potrebbero continuare a cambiare. Inoltre, gli oggetti possono continuare a spostarsi visivamente in avanti se il codice di rendering utilizza un trucco comune e si aggiunge velocity * time since last update / period of updatealla posizione visibile degli oggetti (mentre la loro posizione reale rimane invariata).
HolyBlackCat,

2
iffche significa if-and-only-if?
BalinKingOfMoria,

3
@HolyBlackCat: è discutibile. Cosa succede se desidero mettere in pausa la grafica? Cosa succede se i frame di animazione influenzano il gioco (animazioni di attacco corrispondenti a hitbox, ecc.)? L'interpolazione visiva implica ancora che il "tempo" (come nel delta time del gioco) stia passando, ma se il tempo passa e non lo stai facendo, Updatecos'altro sta andando fuori sincrono? Input del lettore mancati, eventi di rete non elaborati, ecc.? Il gioco dovrebbe essere rimosso da un singolo clock, con "tick" fissi per la logica di gioco o la fisica derivata da quel clock, e lo stato grafico derivato guidato anche da quello stesso clock.
Sean Middleditch,

@SeanMiddleditch Sono d'accordo, quasi sempre puoi scrivere Draw()in modo tale che disegna sempre la stessa immagine quando viene chiamato più volte di seguito. Uno dovrebbe farlo se possibile. Ma ci sono casi in cui non sai a quale frequenza Draw()verrà chiamato. Ad esempio, se si desidera il supporto completo (120 FPS effettivi) per i nuovi monitor da 120 Hz e si attiva vsync. What if I want to pause graphics?Quindi si passa 0 invece del tempo delta effettivo al Draw().
HolyBlackCat,

2
@HolyBlackCat: nulla a cui stavo arrivando precludeva l'uso del rendering a 120 Hz. Non raccomandavo assolutamente un tasso di prelievo fisso; è solo amatoriale. Dovrebbe esserci un clock di gioco globale il cui delta è misurato in termini di frame di rendering che alimenta il valore di accumulo per il tick di logica di gioco a tasso fisso. Quell'orologio globale guida la grafica, compresa l'interpolazione. È possibile mettere in pausa la grafica impostando la scala dell'orologio su 0. Puoi avere orologi gerarchici, ad esempio l'interfaccia utente viene comunque eseguita e animata mentre l'interpolazione dei caratteri si arresta anche molto molto facilmente.
Sean Middleditch,

7

Il punto qui è la separazione delle cose del Modello che non sono il modello.

La logica di gioco è il modello come indicato in

Questi sono tutti modelli di architettura software diversi, correlati. Ma in ogni caso il Modello è la stessa cosa, è la vera logica e lo stato reale.

È quando si realizza un software aziendale che a volte viene chiamato logica aziendale e codifica alcune delle politiche aziendali. Ad esempio, se stai codificando qualcosa per una banca, per calcolare le fatture delle carte di credito, quindi la funzionalità per impedire a qualcuno di pagare gli interessi se liquidano il debito in meno di 30 giorni, fa parte della logica aziendale, vive nel modello. Ad esempio, non vive su uno dei livelli di visualizzazione. Il codice per la stampa di una fattura, ad esempio, non modifica il testo in base alle loro azioni. Questo esempio forse evidenzia perché potresti voler organizzare il tuo codice in questo modo.

Lo stesso vale per la logica di gioco.

Immagina che a un certo punto il tuo gioco sia stato portato su un'altra console. Potrebbe aiutare a immaginare qualcosa di veramente diverso dal tuo attuale obiettivo. Ad esempio, se stai prendendo di mira qualcosa con un gamepad / controller, immagina che il tuo gioco venga trasferito su un tablet touchscreen. La logica di gioco è la parte del codice che non cambia quando lo porti.

Se il tuo gioco fosse qualcosa di simile a un gioco di strategia militare, immagina di essere convertito nel gioco da tavolo più complesso del mondo. La logica del gioco sono le sezioni del codice, che corrispondono direttamente alle righe del libro delle regole. (Non tutte le righe del libro delle regole, non quelle sulle parti in movimento, ma alcune.).

La logica del gioco è la cosa che non cambia mai, indipendentemente dalla forma.

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.