Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2007
    Messaggi
    10

    Swing, timers e animazioni

    Ciao a tutti...
    Vorrei sviluppare un'animazione per il mio progetto di un gioco da tavolo con java.
    Classico tabellone, classici dadi random che si tirano e classico movimento della pedina.
    Riesco bene a togliere la pedina dalla posizione iniziale e posizionarla in quella di arrivo.
    Riesco meno bene a simulare il movimento in tutte le caselle intermedie...
    Ho provato a implementare un timer. Le caselle sono jpanels in un array. Le pedine jlabel con imageicons. Il metodo muovi prende come parametri il giocatore (la sua posizione nell'arraylist per la verità), la posizione iniale nel tabellone e quella finale. Lo scorrimento lo gestisco nell'ActionPerformed della classe, in modo che ad ogni "colpo" del timer calcoli la casella successiva, tolga la pedina dalla casella corrente (remove), la metta in quella successiva (add) e aggiorni il tutto (repaint). Ciò che fa il metodo muovi quando viene invocato è inizializzare le variabili, start del timer, ciclare a "vuoto" con un while fino a che in qualche modo (appunto grazie all'actionperformed) la posizione corrente corrisponda a quella finale e stop del timer.
    Mi pare che abbia senso... Ma invece a quanto pare no.
    Invocare il muovi vuol dire impallare tutto, senza nessuna eccezione lanciata, e con il mio lieve sospetto che da quel while non riesca proprio ad uscirne.

    Pareri?

    codice:
    public class Tabellone extends JPanel implements ActionListener... {
    	
    	...
    	private JPanel caselle[] = new JPanel[20]; //ben caratterizzato nel costruttore
    	private ArrayList <JLabel> simboli = new ArrayList <JLabel> (); //ben caratterizzato nel costruttore
    	private Timer timer = new Timer(500,this); //timer.addActionListener(this); nel costruttore
    	private int giocatore,corr;
            ...
    
            public void muovi(int giocatore, int iniziale, int finale) {
    		
    		this.giocatore = giocatore;
    		timer.start();
    		corr = iniziale;
    		while (corr != finale);
    		timer.stop();
    			
    	}
             ...
            public void actionPerformed(ActionEvent e) {
    		int succ;
    		if (corr == 19)
    			succ = 0;
    		else
    			succ = corr + 1;
    		
    		caselle[corr].remove((Component)simboli.get(giocatore));
    		caselle[succ].add(simboli.get(giocatore));
    		repaint();
    		
    		corr = succ;
    	}

  2. #2
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Non puoi mettere un for dentro muovi.
    Qualcosa tipo per i cha va da iniziale a finale
    codice:
    caselle[i].remove((Component)simboli.get(giocatore));
    caselle[i+1].add(simboli.get(giocatore));
    repaint();
    Thread.sleep(500);
    Ti blocca l'applicazione durante l'animazione, ma credo che per te vada bene.
    Naturalmente devi gestirti il caso in cui iniziale sia > di finale splittandolo in due cicli, uno da iniziale a 19, l'altro da 0 a finale.
    Nel codice che hai postato tu, non riesco ad individuare l'errore.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2007
    Messaggi
    10
    Ho risolto lasciando il timer... e togliendo il ciclo while. Praticamente l'ultima cosa che fa muovi è timer.start() al che, ad ogni colpo dello stesso, l'actionperformed incrementa un contatore poi confrontandolo col valore finale... In caso di uguaglianza, timer.stop(). Ora funziona, ma incredibilmente va avanti a 2 a 2 In caso di dadi dispari, va avanti a 2 a 2 fino al penultimo ugualmente per poi fortunatamente fare correttamente l'ultimo passo. Provando a debuggare con delle println sembra sia tutto apposto, il repaint viene invocato ad ogni singolo passo, ma il risultato a video dice diversamente, deve esserci qualche problema con l'aggiornamento.

    codice:
    private int giocatore,corr,finale;
    
    public void muovi(int giocatore, int iniziale, int finale) {
    		
    		this.giocatore = giocatore;
    		corr = iniziale;
    		this.finale = finale;
    		timer.start();
    		
    	}	
    
    
    public void actionPerformed(ActionEvent e) {
    		
    		if (corr != finale) {
    			int succ;
    			if (corr == 39)
    				succ = 0;
    			else
    				succ = corr + 1;
    
    			caselle[corr].remove((Component)simboli.get(giocatore));
    			caselle[corr].repaint();
    			caselle[succ].add(simboli.get(giocatore));
    			caselle[succ].repaint();
    			corr = succ;
    		}
    		else {
    			timer.stop();
    			
    		}			
    
    	}

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Bizzarro, ti fa il repaint ogni due iterazioni. Hai provato a chiamare il repaint su tutto il pannello principale alla fine di ogni "botta" di timer?

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2007
    Messaggi
    10
    Sia sulle singole caselle che sull'intero tabellone... nisba

  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    codice:
    private Timer timer = new Timer(500,this); //timer.addActionListener(this); nel costruttore
    Non e' che hai messo due actionListener identici sullo stesso timer e fai due incrementi alla volta (quindi non fai in tempo a vedere l'incremento dispari perche' ti fa il repaint istantaneamente del successivo).
    Togli timer.addActionListener(this); dal costruttore, new Timer(500,this); ti associa gia' l'actionListener this al timer.

  7. #7
    Utente di HTML.it
    Registrato dal
    Jun 2007
    Messaggi
    10
    ......
    ...
    .
    VVoVe:

    Era proprio quello! Sei un grande

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.