Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Alpine A290 alla prova: un'auto bella che ti fa innamorare, con qualche limite
Alpine A290 alla prova: un'auto bella che ti fa innamorare, con qualche limite
Abbiamo guidato per diversi giorni la Alpine A290, la prima elettrica del nuovo corso della marca. Non è solo una Renault 5 sotto steroidi, ha una sua identità e vuole farsi guidare
Recensione HONOR Magic 8 Lite: lo smartphone indistruttibile e instancabile
Recensione HONOR Magic 8 Lite: lo smartphone indistruttibile e instancabile
Abbiamo provato a fondo il nuovo Magic 8 Lite di HONOR, e per farlo siamo volati fino a Marrakech , dove abbiamo testato la resistenza di questo smartphone in ogni condizione possibile ed immaginabile. Il risultato? Uno smartphone praticamente indistruttibile e con un'autonomia davvero ottima. Ma c'è molto altro da sapere su Magic 8 Lite, ve lo raccontiamo in questa recensione completa.
Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora
Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora
WF-1000X M6 è la sesta generazione di auricolare in-ear sviluppata da Sony, un prodotto che punta a coniugare facilità di utilizzo con una elevata qualità di riproduzione dei contenuti audio e una cura nella riduzione del rumore ambientale che sia da riferimento
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 28-09-2011, 00:14   #1
neutronirt
Member
 
L'Avatar di neutronirt
 
Iscritto dal: Sep 2011
Messaggi: 68
[Java]Problema animazione 2D

Ciao a tutti ragazzi, il mio problema non è prettamente dovuto al codice, ma a come l'applicazione funziona esclusivamente sul MIO pc.
Sostanzialmente da qualche giorno l'applicazione 2d su cui sto lavorando va molto più velocemente di quanto dovrebbe. Mi spiego meglio.
Quando muovo lo sprite lungo lo schermo, un pixel ogni millisecondo circa, il tutto viene fatto molto più velocemente del dovuto, ma ripeto, solo sul mio pc.
Ho pensato che questo potesse essere dovuto alla JRE, ma non ne sono sicuro e non so cosa pensare, spero qualcuno posssa aiutarmi.
Saluti
neutronirt è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 09:42   #2
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da neutronirt Guarda i messaggi
Quando muovo lo sprite lungo lo schermo, un pixel ogni millisecondo circa, il tutto viene fatto molto più velocemente del dovuto, ma ripeto, solo sul mio pc.
A livello di codice, come fai a ottenere le spostamento di 1 pixel/millisec?

Quote:
Originariamente inviato da neutronirt Guarda i messaggi
Ho pensato che questo potesse essere dovuto alla JRE, ma non ne sono sicuro e non so cosa pensare, spero qualcuno posssa aiutarmi.
Senza vedere il codice è impossibile dirti qualcosa di concreto e specifico...
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 12:10   #3
neutronirt
Member
 
L'Avatar di neutronirt
 
Iscritto dal: Sep 2011
Messaggi: 68
Per spostare di un pixel al ms uso un timer che richiama il metodo actionperformed del jpanel che implementa ActionListener.
Ogni millisecondo viene richiamato il metodo actionPerformed che sposta lo sprite. Sicuramente il problema non è dovuto al codice, lo dico perchè aprendo due volte l'eseguibile dell'applicazione(quindi con 2 app aperte) la velocità di entrambe si dimezza...
Segue il codice del jpanel:

Codice:
public class Board extends JPanel implements ActionListener {
	
    private Timer timer;
    private Sprite craft;

    public Board() {

        addKeyListener(new TAdapter());
        setFocusable(true);
        setBackground(Color.BLACK);
        setDoubleBuffered(true);
        
        craft = new Sprite();
        
        //IL TIMER RICHIAMA IL METODO ACTION PERFORMED OGNI VOLTA
        timer = new Timer(1, this);
        timer.start();
    }


    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(craft.getImage(), craft.getX(), craft.getY(), this);
        
        ArrayList<Missile> ms = craft.getMissiles();

        for (int i = 0; i < ms.size(); i++ ) {
            Missile m = (Missile) ms.get(i);
            g2d.drawImage(m.getImage(), m.getX(), m.getY(), this);
        }

        
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }


    public void actionPerformed(ActionEvent e) {
    	
    	ArrayList ms = craft.getMissiles();

        for (int i = 0; i < ms.size(); i++) {
            Missile m = (Missile) ms.get(i);
            if (m.isVisible()) 
                m.move();
            else ms.remove(i);
        }
    	craft.move(); 
    	repaint();
    }


    private class TAdapter extends KeyAdapter {

        public void keyReleased(KeyEvent e) {
            craft.keyReleased(e);
        }

        public void keyPressed(KeyEvent e) {
            craft.keyPressed(e);
        }
    }

}
neutronirt è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 12:36   #4
neutronirt
Member
 
L'Avatar di neutronirt
 
Iscritto dal: Sep 2011
Messaggi: 68
Credo che il problema si manifesti solo quando internet è aperto, non so perchè, ma è così, me ne sono appena accorto.
neutronirt è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 12:56   #5
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da neutronirt Guarda i messaggi
Credo che il problema si manifesti solo quando internet è aperto, non so perchè, ma è così, me ne sono appena accorto.
Puoi postare la versione del JDK che stai utilizzando?
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 13:03   #6
neutronirt
Member
 
L'Avatar di neutronirt
 
Iscritto dal: Sep 2011
Messaggi: 68
1.6.0, grazie mille dell'interessamento comunque
neutronirt è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 15:05   #7
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da neutronirt Guarda i messaggi
Sostanzialmente da qualche giorno l'applicazione 2d su cui sto lavorando va molto più velocemente di quanto dovrebbe.
Ciao.
Posto che il codice da te pubblicato è ok, nel senso che non fa nulla di "strambo", ci sono un paio di considerazioni da fare, relativamente a quello che vuoi ottenere.

Stai implementando una sorta di gioco 2D, appoggiandoti a Swing, almeno stando a quanto fin qui visto. Quindi vuoi fare grafica 2D performante e controllare il frame rate con il quale girerà il gioco. Roba tutto sommato normale.

Le due considerazioni, sulle quali non mi dilungo per motivi di tempo, sono le seguenti:

1) per farla breve, per le immagini da caricare, affinchè siano performanti e accellerate, non basta caricarle semplicemente con i soliti metodi, bisogna anche convertirle in un formato compatibile con il display (GraphicConfiguration del monitor in uso).

2) per la grafica acellerata in Java non basta fare l'override del metodo paint di un JComponent, è invece neccessario usare un BufferStrategy ricavato da un Canvas (AWT) o un JFrame (Swing).

3) Bisogna controllare direttamente il frame rate del rendering loop di un gioco (essendo in Java non hai nessuna garanzia circa il sistema sottostante e le sue politiche di scheduling per i thread, nonchè la granularità del timer di sistema).

Ti posto due link utili:
- tutrial per giochi 2D in Java, che tocca tutti gli aspetti qui citati e va anche oltre;
- un forum specializzato su giochi e grafica ad alte prestazioni in Java, una risorsa eccellente;

Il metodo da te usato per aggiornare la posizione delle sprite (1pixel/ms) non è deterministico perchè non hai nessuna garanzia che il timer lanci effettivamente 1 evento ogni 1 millisecondo. Intanto dipende dal sistema operativo su cui il tuo gioco si trova a girare: se sei sotto Windows, ad esempio, essendo che Timer internamente fa chiamate a System.currentTimeMillis() il risultato è che le pause da 1 millisecondo sono in realtà pause da (circa) 15-16 millisecondi perchè questa è la granularità del timer di sistema in Windows a cui si appoggia quella chiamata.
Il seguente programma lo dimostra in via sperimentale (il mio sistema è un Windows XP):
Codice:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import javax.swing.Timer;

/**
 * Class TimerOneMillisec...
 * @author Francesco Baro
 */
public class TimerOneMillisec implements ActionListener {

    public static void main(String[] args) {
        TimerOneMillisec tom = new TimerOneMillisec();
        tom.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ignored) {
            System.out.println("@" + Time.now() +
                    " (nanos)> main thread has been interrupted");
        }

        tom.stop();
        tom.printResult();
    }

    TimerOneMillisec() {
        timer = new Timer(1, this);
    }

    @Override public void actionPerformed(ActionEvent e) {
        buffer.append(Time.now()).append(" ");
    }

    void start() {
        startTime = Time.now();
        timer.start();
    }

    void stop() {
        timer.stop();
        endTime = Time.now();
    }

    Iterable<String> processResults() {
        List<String> result = new LinkedList<String>();
        long oldTime = startTime;
        String results = buffer.toString().trim();
        StringTokenizer st = new StringTokenizer(results);
        while (st.hasMoreTokens()) {
            long time = Long.parseLong(st.nextToken());
            result.add(String.valueOf(time - oldTime));
            oldTime = time;
        }
        return result;
    }

    void printResult() {
        long t1 = Time.toMillis(startTime);
        long t2 = Time.toMillis(endTime);
        System.out.println("Started at (millis): " + t1);
        System.out.println("Ended at (millis): " + t2);
        System.out.println("Total elapsed (millis): " + (t2 - t1));
        System.out.println("Partials (nanos):");

        Iterable<String> lines = processResults();
        for (String line : lines) System.out.println(line);

        
    }

    private final StringBuilder buffer = new StringBuilder();
    private final Timer timer;
    private long startTime, endTime;


    private static class Time {

        // construction forbidden
        private Time() {}

        static long now() {
            return System.nanoTime();
        }

        static long elapsedFrom(long nanos) {
            return System.nanoTime() - nanos;
        }

        static long toMillis(long nanos) {
            return nanos / 1000000;
        }
    }
}
Una sua tipica esecuzione da me ha prodotto questo risultato:
Quote:
run:
Started at (millis): 21608361
Ended at (millis): 21609362
Total elapsed (millis): 1001
Partials (nanos):
61758408
1160483
11890617
15492472
15683278
15578796
15611202
15591088
15619862
15627964
15653386
15603659
15617348
15638859
15626567
15622936
15684116
15620980
15608408
15588294
15639977
15762338
15491634
15752840
15585780
15580751
15605335
15607850
15606453
15646681
15632434
15572370
15655062
15638859
15650313
15580193
15669030
15619025
15579075
15637183
15614554
15624891
15648357
15611482
16157360
15127901
15622376
15630479
15599748
15635506
15609526
15627126
15737754
15500015
15651710
15607850
15620141
15632155
15638579
15621539
15606732
15642770
BUILD SUCCESSFUL (total time: 2 seconds)
Ma poi anche se il timer effettivamente pubblicasse un action event ogni millisecondo nella coda degli eventi awt, è possibile che più richieste di repaint() in successione vengano fuse/unite in un'unica rischiesta, e l'effetto risultante è quello di vedere un aggiornamento della posizione delle sprite "a singhiozzo", perdendo gli "step" intermedi.

Non so se questo meccanismo sia la causa che produce gli effetti che hai verificato quando lanci due istanze del tuo gioco (che girano sì in due istanze diverse della jvm, ma la scheda grafica, le risorse video e il window manager del so sono sempre singoli)...

Il primo post (quello con i tutorial), può aiutarti davvero molto, è una lettura che ti consiglio caldamente.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 28-09-2011 alle 15:27.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 15:34   #8
neutronirt
Member
 
L'Avatar di neutronirt
 
Iscritto dal: Sep 2011
Messaggi: 68
Caro banryu, ti ringrazio infinitamente per l'immenso aiuto che mi hai dato. Sto iniziando ora, infatti, con la programmazione 2d in java e questa è la primissima applicazione con grafica accelerata che implemento (per quanto riguarda le swing sono piuttosto ferrato, ma non per ciò che concerne la grafica accelerata).
Credo proprio che il problema dell'app sia dovuto a questa mancanza di controllo del tempo.
Comunque sia ora leggerò accuratamente le guide che mi hai sottoposto, da tempo ne cercavo di valide e finalmente posso appoggiarmi a qualcosa di utile!
neutronirt è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 15:52   #9
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Sì, ho visto che nel codice esegui una chiamata a Toolkit.synch(), il che *in teoria* dovrebbe scongiurare l'accumulo di eventi grafici nella coda degli eventi. Dico in teoria, perchè leggendo in giro pare che, come sempre, dipenda dall'implementazione sottostante.

@EDIT: ti segnalo anche un vecchio thread su questo forum, si sa mai che possa contenere info & link utili (ad esempio se cerchi sprite e asset grafici vari da usare nei tuoi giochi, butta un occhio): http://www.hwupgrade.it/forum/showthread.php?t=1817420
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 28-09-2011 alle 15:57.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 28-09-2011, 19:39   #10
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Un timer di 1 ms ha poco senso, non è che da te va più veloce, è probabile che in altri pc vada più piano.
Comunque, se vuoi abbozzare un motore di rendering 2d, non servono timer, detta molto alla buona ti basta un ciclo infinito, calcolare il tempo(delta t) che intercorre tra due esecuzioni del ciclo e in base a quello spostare la roba.
Quello è l'unico modo che ti assicura che gli oggetti si spostino tutti alla stessa velocità in tutti i pc che eseguono il programma.
MEMon è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Alpine A290 alla prova: un'auto bella che ti fa innamorare, con qualche limite Alpine A290 alla prova: un'auto bella che ti fa ...
Recensione HONOR Magic 8 Lite: lo smartphone indistruttibile e instancabile Recensione HONOR Magic 8 Lite: lo smartphone ind...
Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora Sony WF-1000X M6: le cuffie in-ear di riferiment...
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI Snowflake porta l'IA dove sono i dati, anche gra...
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo M...
Tesla festeggia il primo Cybercab prodot...
Desktop piccolo e potente? NZXT H2 Flow ...
Logan Paul vende la sua carta Pokemon &q...
Polestar spinge sull'acceleratore: arriv...
Nuovo record mondiale nel fotovoltaico: ...
L'ultimo baluardo cade: fine supporto pe...
'Il mondo non ha mai visto nulla di simi...
La Commissione europea mette sotto indag...
Arriva il primo computer quantistico ad ...
'Se lavori al PC sei a rischio': la prev...
Windows 11 introduce il supporto nativo ...
Apple AirDrop su Android: dopo Pixel 10,...
Upgrade PC senza spendere una fortuna: G...
Sistema di sblocco alla iPhone anche su ...
29 offerte Amazon, rinnovate: in 2 minut...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 15:56.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v