Quando dovrei rappresentare punti e dimensioni come strutture?


9

Come parte del mio semplice framework di sviluppo di giochi in Ruby 2D, i miei oggetti di gioco hanno posizione (valori xey) e dimensioni (larghezza e altezza).

class MyGameObject
  attr_accessor :x
  attr_accessor :y
  attr_accessor :width
  attr_accessor :height
  ...

Un altro approccio che ho visto è stato trattare la posizione come una Pointstruttura e le dimensioni come una Sizestruttura:

Point = Struct.new(:x, :y)
Size = Struct.new(:width,:height)

class MyGameObject
  attr_accessor :position   # Point instance
  attr_accessor :size       # Size instance
  ...

Alcuni framework usano il primo (penso GDX, Gosu ...). Altri usano quest'ultimo (cocos2d-iphone). Il problema è che non mi è del tutto chiaro i vantaggi e gli svantaggi di entrambi i comportamenti (nello sviluppo del gioco) - Non so perché alcuni framework abbiano scelto l'uno e non l'altro.

Ci sono differenze significative che dovrei considerare?

Risposte:


8

Alcuni addirittura usano la Rectangleclasse:

class Rectangle
{
    float x, y, w, h;
}
class GameObject
{
    Rectangle dimensions;
}

È solo una scelta di design, non importa. Se stai facendo il tuo codice, rendi ciò che ritieni più confortevole. Se stai usando qualche API, framework o motore, o modificando / modificando un gioco, prova ad essere coerente con il resto del codice e fai come nel codice vicino.

Direi di andare con due vettori separati, in questo modo:

class Vector2
{
    float x, y;
    //helper functions like operator overload, dot, length, distance, etc.
}

class GameObject
{
    Vector2 position;
    Vector2 size;
    Vector2 direction;
}

In questo modo puoi gestire più facilmente cose come l'angolo tra gli oggetti, in questo modo:

GameObject foe;
GameObject player;
Vector2 dist = player.position - foe.position;
dist.normalize();
float angleBetween = acos(dist.dot(foe.direction));

invece di dover estrarre i vettori dai rettangoli o crearli da semplici float.


2

In generale, utilizzare sempre una struttura dati separata. Semplifica notevolmente l'utilizzo, la lettura e la manutenzione del codice. Quanto spesso hai bisogno di xseparare da yvs quanto spesso devi calcolare un offset vettoriale, lunghezza, punto prodotto, ecc.? Obiettivo per il caso comune; rendere il codice con cui si scrive ripetutamente più facile da utilizzare, che per punti e vettori sarà in genere operazioni sull'intero "oggetto" anziché operazioni su singoli componenti.

L'unica eccezione che vorrei fare è che, dopo aver profilato correttamente , la struttura separata è troppo lenta. Lingue come Ruby non rendono possibile un semplice "per valore" definito dall'utente e, nella mia esperienza, avere punti e vettori come tipi "per riferimento" a volte è sia una seccatura che può essere un enorme rallentamento senza un'attenta attenzione ai provvisori . Può essere vantaggioso, ad esempio, avere due matrici di ints, una per xe una per y, quindi avere una sola matrice di Pointoggetti; è molto più complicato lavorare con questo, quindi fallo solo se hai metriche prestazionali valide per indicare che ne vale la pena!


+1, ma vorrei menzionare che la preottimizzazione è la radice di tutti i mali.
Gustavo Maciel,

3
@GustavoMaciel: davvero. Fatto: Cruella de Vil stava solo cercando di ottimizzare il suo guardaroba prima di ripulire la sua personalità e guardare dove l'aveva portata.
Sean Middleditch,
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.