Esempio 1 - Sfere

di il
14 risposte

Esempio 1 - Sfere

Ciao a tutti
Apro per iOS lo stesso esempio che è stato aperto per Windows Phone, dato che conosco il NetFramework e stò studiando l' objective-C credo che questo confronto sarà utile.

L' esempio è molto semplice si tratta di muovere delle immagini sullo schermo, per cominciare credo che vada benone.

14 Risposte

  • Re: Esempio 1 - Sfere

    Ma come pensavi di farlo, una pallina sola o tante che rimbalzano tra di loro?
  • Re: Esempio 1 - Sfere

    Beh, limitarsi ad una sola pallina puo servire a rompere il ghiaccio, vedere come si apre un progetto, inserire una immagine, usare un timer, insomma un sacco di cose che se non hai mai fatto possono presentare dei problemi.

    Però in questo caso il codice diventa molto semplice, il tutto si riduce a scrivere qualche riga nella funzione del timer per muovere l' immagine e invertire la direzione quando raggiunge i bordi.

    Se invece facciamo le palline che rimbalzano tra di loro, magari con dimensioni e massa diverse la cosa diventa più divertente e ti costringe ad usare la programmazione ad oggetti.

    Proporrei di fare tutte e due le cose
  • Re: Esempio 1 - Sfere

    I passi che ho seguito sono stati questi:

    - In XCode creare una nuova applicazione iOS Single View Application.
    - Ho aggiunto al progetto l' immagine di una sfera (trascinandola dentro).
    - Nella View dello storyboard ho inserito un oggetto Image.
    - Ho collegato l' image al ViewController (trascinando col mouse)
    - Nel viewDidLoad ho creato un timer e la funzione associata:
    
    - (void)viewDidLoad
    {
       [super viewDidLoad];
        ....
       [NSTimer scheduledTimerWithTimeInterval: 0.1    // un decimo di secondo
          target: self
          selector:@selector(moveImage)      // funzione da richiamare
          userInfo: nil 
          repeats:YES];   
    }
    
    -(void) moveImage
    {
      double x = image1.center.x + vx;
      double y = image1.center.y + vy;
       
      if ((x < 0) || (x > 400))
         vx = -vx;
    
      if ((y < 0) || (y > 300))
         vy = -vy;
    
      image1.center = CGPointMake(x, y);
    }  
    
    Le due variabili vx e vy sono dichiarate all' inizio e rappresentano la velocità. Quando si raggiunge un bordo la velocità si inverte.

    Come dicevamo questa applicazione è molto semplice (e magari è pure sbagliata), però è servita a rompere il ghiaccio, il passo successivo sono le palline che rimbalzano tra di loro.
  • Re: Esempio 1 - Sfere

    Ecco un fantastico screenshot della pallina in movimento, purtroppo il movimento non si nota.

  • Re: Esempio 1 - Sfere

    barba59 ha scritto:


    Se invece facciamo le palline che rimbalzano tra di loro, magari con dimensioni e massa diverse la cosa diventa più divertente e ti costringe ad usare la programmazione ad oggetti.
    Perchè dici che con le palline che rimbalzano è necessaria la programmazione ad oggetti?
  • Re: Esempio 1 - Sfere

    Orso Bruno ha scritto:


    Perchè dici che con le palline che rimbalzano è necessaria la programmazione ad oggetti?
    Ti dico la mia opinione (ma sono certo che Barba59 non rimarrà a bocca chiusa....)

    Per problemi semplici o semplicissimi si può scrivere un pò come si vuole. Quando però il problema si complica la programmazione ad oggetti è un sistema di organizzare il codice che ha diversi vantaggi.... il codice può essere più semplice da scrivere e da leggere, più facile da manutenere e la relazione fra le entità del problema diventano più chiare. Il discorso ovviamente non si conclude così e potrai ottenere pareri molto diversi se chiedi a persone con esperienze diverse.

    Nel caso specifico, quando hai più palline ed affronti il problema con la programmazione orientata agli oggetti, penso che Barba59 vedesse il vantaggio nel fatto che crei un singolo oggetto pallina e lo istanzi tutte le volte che vuoi mantenendo incapsulate tutte le informazioni di ogni singola pallina nella rispettiva istanza. Senza programmazione orientata agli oggetti invece avresti tutto un pò sparpagliato..... Barba59 ho intuito bene?

    Ciao, g.
  • Re: Esempio 1 - Sfere

    Ciao GianmariaLari, benvenuto!
    Oltre a Obj-C ti occupi di qualche altro linguaggio? Io uso il C# e volevo imparare qualcosa per Apple.
  • Re: Esempio 1 - Sfere

    1 Modificare le coordinate dell'immagine facendo  
    image1.center = CGPointMake(x, y);
    è sufficente per spostare l'immagine? Non c'è da effettuare una chiamata esplicita per ridisegnare l'immagine nella nuova posizione?

    2 Capisco male o il ricalcolo delle coordinate è un operazione separata dal ridisegno dell'immagine e che queste due operazioni potrebbero avere frequenze molto diverse? Per capirsi, io potrei decidere di ricalcolare le coordinate della pallina ogni centesimo di secondo mentre mentre il ridisegno dell'immagine potrebbe avvenire solo ogni decimo di secondo (c'è un valore di default? si può cambiare?)

    3 Inoltre giusto per spaccare il capello in quattro non sarebbe meglio nella funzione MoveImage cambiare l'ordine delle istruzioni da:
      
      double x = image1.center.x + vx;
      double y = image1.center.y + vy;
       
      if ((x < 0) || (x > 400))
         vx = -vx;
    
      if ((y < 0) || (y > 300))
         vy = -vy;
    
      image1.center = CGPointMake(x, y);
    
    a
      
      double x = image1.center.x + vx;
      double y = image1.center.y + vy;
      image1.center = CGPointMake(x, y);
       
      if ((x < 0) || (x > 400))
         vx = -vx;
    
      if ((y < 0) || (y > 300))
         vy = -vy;
    
    O forse mi sfugge qualcosa?
    Grazie, g.
  • Re: Esempio 1 - Sfere

    Orso Bruno ha scritto:


    Ciao GianmariaLari, benvenuto!
    Oltre a Obj-C ti occupi di qualche altro linguaggio? Io uso il C# e volevo imparare qualcosa per Apple.
    Ciao,

    sono qui per imparare. Non conosco Obj-C ma conosco qualche altro vecchio linguaggio. Mi interessa android e vedere come si differenzia da iOS.

    Ciao, g.
  • Re: Esempio 1 - Sfere

    Ciao GianmariaLari,
    benvenuto su questo forum!

    GianmariaLari ha scritto:


    Orso Bruno ha scritto:


    Perchè dici che con le palline che rimbalzano è necessaria la programmazione ad oggetti?
    Ti dico la mia opinione (ma sono certo che Barba59 non rimarrà a bocca chiusa....)

    Per problemi semplici o semplicissimi si può scrivere un pò come si vuole. Quando però il problema si complica la programmazione ad oggetti è un sistema di organizzare il codice che ha diversi vantaggi.... il codice può essere più semplice da scrivere e da leggere, più facile da manutenere e la relazione fra le entità del problema diventano più chiare. Il discorso ovviamente non si conclude così e potrai ottenere pareri molto diversi se chiedi a persone con esperienze diverse.

    Nel caso specifico, quando hai più palline ed affronti il problema con la programmazione orientata agli oggetti, penso che Barba59 vedesse il vantaggio nel fatto che crei un singolo oggetto pallina e lo istanzi tutte le volte che vuoi mantenendo incapsulate tutte le informazioni di ogni singola pallina nella rispettiva istanza. Senza programmazione orientata agli oggetti invece avresti tutto un pò sparpagliato..... Barba59 ho intuito bene?
    Hai intuito benissimo! specie sul fatto che non sarei rimasto a bocca chiusa

    Sull' importanza della programmazione ad oggetti non si insiterà mai abbastanza!

    Muovere una pallina è semplice basta scrivere quattro righe nella funzione del timer. Calcolare come devono rimbalzare delle palline che si scontrano è già più interessante e serve un briciolo di matematica e di fisica.

    Poi sai, quando cominci a prenderci gusto fai evolvere il problema, le palline cominceranno ad avere diametri differenti, saranno fatte di materiali diversi per cui le masse saranno diverse, il trasferimento della quantità di moto dipenderà dalla massa ecc. Poi magari un bel giorno mi salti fuori dicendo che ora vuoi farlo in OpenGL e quindi bisogna riscrivere tutto.

    Per cui da bravi cominciamo a separare quello che è il modello da quello che è la sua rappresentazione grafica.
    Cioè creiamo un mondo di oggetti in cui le sfere si muovono secondo le loro regole, completamente separato da una qualsiasi rappresentazione grafica, si ragionerà solo di posizioni, velocità, masse ecc.

    Poi se voi rappresentare questa scena un un form scriverai qualche riga di codice per trasferire questo modello sul canvas, se invece vuoi rappresentare la scena usando le openGL farai lo stesso nel metodo Update, ma le classi che descrivono il modello rimarranno invariate.
  • Re: Esempio 1 - Sfere

    Ciao GianmariaLari

    GianmariaLari ha scritto:


    1 Modificare le coordinate dell'immagine facendo  
    image1.center = CGPointMake(x, y);
    è sufficente per spostare l'immagine? Non c'è da effettuare una chiamata esplicita per ridisegnare l'immagine nella nuova posizione?
    No, non è necessario, non ti devi preoccupare del ridisegno, basta cambiare le coordinate.

    GianmariaLari ha scritto:


    2 Capisco male o il ricalcolo delle coordinate è un operazione separata dal ridisegno dell'immagine e che queste due operazioni potrebbero avere frequenze molto diverse? Per capirsi, io potrei decidere di ricalcolare le coordinate della pallina ogni centesimo di secondo mentre mentre il ridisegno dell'immagine potrebbe avvenire solo ogni decimo di secondo (c'è un valore di default? si può cambiare?)
    Bravo!!! Se separi le due cose puoi avere delle simulazioni molto più accurate e un sistema più fluido.

    GianmariaLari ha scritto:


    3 Inoltre giusto per spaccare il capello in quattro non sarebbe meglio nella funzione MoveImage cambiare l'ordine delle istruzioni da:
      
      double x = image1.center.x + vx;
      double y = image1.center.y + vy;
       
      if ((x < 0) || (x > 400))
         vx = -vx;
    
      if ((y < 0) || (y > 300))
         vy = -vy;
    
      image1.center = CGPointMake(x, y);
    
    a
      
      double x = image1.center.x + vx;
      double y = image1.center.y + vy;
      image1.center = CGPointMake(x, y);
       
      if ((x < 0) || (x > 400))
         vx = -vx;
    
      if ((y < 0) || (y > 300))
         vy = -vy;
    
    O forse mi sfugge qualcosa?
    Immagino tu lo dica per una ragione di leggibilità o di raggruppamento logico, perchè come risultato non cambia proprio niente. Quindi, giusto per spaccare il capello in otto:

    Nel modo che proponi tu l' assegnamento delle variabili x e y e il loro uso per muovere l' immagine sono raggruppate e questo è sia logico che leggibile.

    Nel modo in cui avevo scritto io invece prima si fanno tutti i calcoli poi si sposta l' immagine, in questo modo la parte di calcolo e di ridisegno sono ben divise. Si vede che mentre lo scrivevo avevo già chiaro che queste due parti andranno separate.

    Bye
  • Re: Esempio 1 - Sfere

    GianmariaLari ha scritto:


    Non conosco Obj-C ma conosco qualche altro vecchio linguaggio.
    Vecchi linguaggi? Allora anche tu hai un po di anni sul groppone!
    Ai vecchi leoni!
  • Re: Esempio 1 - Sfere

    Giove Pluvio ha scritto:


    GianmariaLari ha scritto:


    Non conosco Obj-C ma conosco qualche altro vecchio linguaggio.
    Vecchi linguaggi? Allora anche tu hai un po di anni sul groppone!
    Ai vecchi leoni!
    Io invece sono ancora un ragazzino! Mi fate rimanere a giocare con voi?
  • Re: Esempio 1 - Sfere

    Ciao a tutti,
    ho completato l' esempio delle sfere che rimbalzano, devo dire che è stata una esperienza utile, inizio ad avere una maggior confidenza col linguaggio che non mi sembra più così astruso. Nel programma si vedono delle sfere che si muovono sullo schermo rimbalzando tra di loro quando si urtano, nel rimbalzo si tiene conto dell' angolo di impatto e della massa delle sfere.



    Ho creato delle classi che si occupano delle sfere e dei loro rimbalzi che sono completamente separate dalla parte di ridisegno, l' idea è quella di usare le stesse classi sia in ambiente CocoaTouch che OpenGL. Questo esempio usa Cocoa (cioè il form normale).

    Questo è un pezzo del codice, in particiolare è la classe sfera:
    
    @implementation MySphere
    @synthesize Center;
    @synthesize Velocity;
    @synthesize Radius;
    @synthesize Density;
    @synthesize Flag;
    
    -(id) init
    {
        Center = [[MyPoint alloc] initX:0 AndY:0];
        Velocity = [[MyVector alloc] initX:0 AndY:0];
        Radius = 1;
        Density = 1;
        
        return self;
    }
    
    -(void) CheckCollision: (MyScene*) scene
    {
        for(MySphere* sphere in scene.Spheres)
        {
            if ((sphere != self) && [self Collision:sphere])
            {
                MyVector* centers = [[[MyVector alloc] initPoint:Center AndPoint:sphere.Center] Normalize];
                double c1 = [Velocity DotProduct:centers];
                double c2 = [sphere.Velocity DotProduct:centers];
                
                if (c2 > c1)
                    continue;
                
                double w1;
                double w2;
                [MySphere ElasticCollision_Velocity1: c1
                                           Velocity2: c2
                                               Mass1: [self Mass]
                                               Mass2: [sphere Mass]
                                      FinalVelocity1: &w1
                                      FinalVelocity2: &w2];
                
                MyVector* ortho1 = [Velocity Project: [centers Ortogonal]];
                Velocity = [MyVector Add:[centers Multiply:w1] And: ortho1];
                
                MyVector* ortho2 = [sphere.Velocity Project: [centers Ortogonal]];
                sphere.Velocity = [MyVector Add:[centers Multiply:w2] And: ortho2];
                
                Flag = true;
                sphere.Flag = true;
            }
        }
    }
    
    -(bool) Collision:(MySphere*) other
    {
        double distanceOfCenters = [Center Distance:other.Center];
        return distanceOfCenters <= Radius + other.Radius;
    }
    
    + (void) ElasticCollision_Velocity1:(double) v1 Velocity2:(double) v2 
                                  Mass1:(double) m1 Mass2:(double) m2 FinalVelocity1:(double*) out1 FinalVelocity2:(double*) out2
    {
        *out1 = (v1 * (m1 - m2) + 2 * m2 * v2) / (m1 + m2);
        *out2 = (v2 * (m2 - m1) + 2 * m1 * v1) / (m2 + m1);
    }
    
    - (double) Bottom { return Center.Y - Radius; }
    - (double) Left { return Center.X - Radius; }
    - (double) Right { return Center.X + Radius; }
    - (double) Top { return Center.Y + Radius; }
    
    - (void) CheckBounds:(MyBounds*) bounds
    {    
        if ([self Right] > bounds.Right)
        {
            Center.X -= [self Right] - bounds.Right;
            Velocity.X = -fabs(Velocity.X);
        }
        
        if ([self Top] > bounds.Top)
        {
            Center.Y -= [self Top] - bounds.Top;
            Velocity.Y = -fabs(Velocity.Y);
        }
        
        if ([self Left] < bounds.Left)
        {
            Center.X += bounds.Left - [self Left];
            Velocity.X = fabs(Velocity.X);
        }
        
        if ([self Bottom] < bounds.Bottom)
        {
            Center.Y += bounds.Bottom - [self Bottom];
            Velocity.Y = fabs(Velocity.Y);
        }
    }
    
    -(double) Mass
    {
        return [self Volume] * [self Density];
    }
    
    -(void) Move:(double) elapsedTime
    {
        Center.X += Velocity.X * elapsedTime;
        Center.Y += Velocity.Y * elapsedTime;
    }
    
    -(double) Volume
    {
        return (4.0 * M_PI * Radius * Radius * Radius) / 3.0;
    }
    
    @end
    
    Se servono altre spiegazione o altri pezzi di codice al solito son ben lieto di darle.
Devi accedere o registrarti per scrivere nel forum
14 risposte