Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi
Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi
Con la prima rete 5G Standalone attiva in Italia, WINDTRE compie un passo decisivo verso un modello di connettività intelligente che abilita scenari avanzati per imprese e pubbliche amministrazioni, trasformando la rete da infrastruttura a piattaforma per servizi a valore aggiunto
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh
OPPO Find X9 Pro punta a diventare uno dei riferimenti assoluti nel segmento dei camera phone di fascia alta. Con un teleobiettivo Hasselblad da 200 MP, una batteria al silicio-carbonio da 7500 mAh e un display da 6,78 pollici con cornici ultra ridotte, il nuovo flagship non teme confronti con la concorrenza, e non solo nel comparto fotografico mobile. La dotazione tecnica include il processore MediaTek Dimensity 9500, certificazione IP69 e un sistema di ricarica rapida a 80W
DJI Romo, il robot aspirapolvere tutto trasparente
DJI Romo, il robot aspirapolvere tutto trasparente
Anche DJI entra nel panorama delle aziende che propongono una soluzione per la pulizia di casa, facendo leva sulla propria esperienza legata alla mappatura degli ambienti e all'evitamento di ostacoli maturata nel mondo dei droni. Romo è un robot preciso ed efficace, dal design decisamente originale e unico ma che richiede per questo un costo d'acquisto molto elevato
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 09-05-2006, 18:42   #1
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
[JAVA]Animazioni

Ragazzi non ho ben chiaro come vengono effettuate le animazioni in java(ho appena iniziato), cioè bisogna per forza cancellare quello che si è appena disegnato e ridisegnarlo "di poco" spostato?
Ditemi che non è così...
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2006, 19:06   #2
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Ho letto qualcosa tipo doppio buffer, c'è nessuno che mi da qualche info in più? in rete non sono riuscito a trovare quclsa di veramente chiaro...
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 10-05-2006, 19:26   #3
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Dai raga help!!!!!!!
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 10-05-2006, 20:01   #4
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
L'alternativa allo spostare di poco per volta qualcosa sta nel proiettare l'immagine a video, afferrare il monitor e correre su e giù per la stanza. Inspiegabilmente è pratica poco comune.

Il doppio buffer è una tecnica usata per impacchettare le operazioni di disegno in un solo comando (quello che invia una richiesta di sostituzione del buffer correntemente proiettato a video). Si fa semplicemente eseguendo le singole operazioni di disegno in una regione di memoria non proiettata per poi ordinare la proiezione del risultato globale delle singole operazioni.

Altrimenti detto, disegni tutto su un'immagine fuori schermo e poi disegni quell'immagine sullo schermo.

L'AWT Java offre un gradevole precotto, BufferStrategy, che incorpora l'accelerazione hardware delle superfici (se disponibile), buffer multipli e il meccanismo di sincronizzazione per la sostituzione degli stessi. La documentazione Java è loquace al riguardo: in sintesi si tratta di disegnare usando il contesto grafico (Graphics) restituito da un BufferStrategy anzichè sovrascrivere il metodo paintComponent usando il suo argomento Graphics.

Circa l'animazione, in ogni caso animi mutando ciclicamente un qualche stato (non necessariamente la posizione pur sembrandomi questa la via più intuitiva). Con un minimo d'ordine al sistema che vuoi realizzare il fatto che per muovere qualcosa sposti un poco per volta delle coordinate passa praticamente subito in sordina.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 11-05-2006, 18:15   #5
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Io vorrei utlizzare lo swing non l'awt e il doppio buffer, hai mica un pezzo di codice che mi mostri come fare una semplice animazione con questa tecnica?
Che non sia un'applet xò.
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 11-05-2006, 19:28   #6
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Se preferisci usare Swing allora sei a cavallo. E' "double buffered, hw accelerated, page flipped e chi più ne ha più ne metted" di suo. Idealmente è meno performante perchè oltre al pacco "performance" ti becchi anche il raffinato ma non certo leggero meccanismo per la gestione di bordi, contenimento, decorazioni e via dicendo.

Ho romanzato il codice per cui mi limito ad incollarlo. Naturalmente per qualsiasi curiosità son qui.

Drawable.java
Codice:
package it.tukano.anisample;

/** Un che di disegnabile */
public interface Drawable {

	void draw(java.awt.Graphics2D g);
}
Updatable.java
Codice:
package it.tukano.anisample;

/** Un che di aggiornabile */
public interface Updatable {
	
	void update();
}
Sprite.java
Codice:
package it.tukano.anisample;

/** Sprite è qualcosa che ha un aspetto e un'animazione (in questo caso
solo animazione per spostamento) */
public interface Sprite extends Drawable {

	void move(float dx, float dy);
	
	void setLocation(float x, float y);
}
HorribleSprite.java
Codice:
package it.tukano.anisample;

import java.awt.*;
import java.awt.geom.*;

/** Quando il nome dice tutto */
public class HorribleSprite implements Sprite {
	private Point2D.Float location = new Point2D.Float();
	private Rectangle2D.Float shape = new Rectangle2D.Float(0, 0, 20, 20);
	
	public void move(float dx, float dy) {
		shape.setRect(
			shape.getX() + dx, shape.getY() + dy,
			shape.getWidth(), shape.getHeight());
	}
	
	public void setLocation(float x, float y) {
		shape.setRect(
			x, y,
			shape.getWidth(), shape.getHeight());
	}
	
	public void draw(Graphics2D g) {
			g.setColor(Color.RED);
			g.fill(shape);
	}
}
Behavior.java
Codice:
package it.tukano.anisample;

import java.awt.*;

/** Definizione di un comportamento applicabile ad uno Sprite */
public class Behavior implements Updatable {
	private float speed = 0.1f; //pixel per millisecondo
	private long time0, time1, dTime;
	private Sprite sprite;
	
	public Behavior(Sprite s) {
		sprite = s;
	}

	/** Applica allo sprite uno spostamento calcolato in base al tempo
	trascorso dall'ultima invocazione di questo metodo. */
	public void update() {
		if(time0 == 0) {
			time0 = time1 = System.currentTimeMillis();
		} else {
			time1 = System.currentTimeMillis();
		}
		dTime = time1 - time0;
		time0 = time1;
		float dx = speed * dTime;
		sprite.move(dx, 0);
	}
}
Updater.java
Codice:
package it.tukano.anisample;

import java.awt.event.*;
import java.util.*;

/** Qualcosa che aggiorna periodicamente qualcos'altro */
public class Updater {
	/** Controlla l'inizio e la fine del ciclo di aggiornamento */
	private volatile boolean doUpdate;
	
	/** Periodo di attesa tra un passaggio e l'altro nel ciclo di
	aggiornamento */
	private int updateDelay;
	
	/** Elenco degli oggetti aggiornabili da questo oggetto */
	private ArrayList<Updatable> updatables = new ArrayList<Updatable>();
	private Runnable updateTask = new Runnable() {
		public void run() {
			while(doUpdate) {
				updateAll();
				waitForDelay();
			}
		}
	};
	
	/** @param delay ritardo del ciclo di aggiornamento */
	public Updater(int delay) {
		updateDelay = delay;
	}
	
	/** definizione del compito periodico */
	private void updateAll() {
		for(Updatable u : updatables) {
			u.update();
		}
	}
	
	/** definizione dell'attesa per il ritardo periodico */
	private void waitForDelay() {
		try {
			Thread.sleep(updateDelay);
		} catch(InterruptedException ex) {
			System.err.println("Threadus interruptus!");
			doUpdate = false;
		}
	}
	
	/** Aggiunge un elenco di updatable alla lista di aggiornamento */
	public void appendUpdatables(Updatable...u) {
		updatables.addAll(Arrays.asList(u));
	}
	
	/** Aggiunge un updatable alla lista degli aggiornabili in posizione
	position (0 = prima del primo elemento della lista)*/
	public void addUpdatable(Updatable u, int position) {
		updatables.add(position, u);
	}
	
	/** Avvia il ciclo di aggiornamento */
	public void start() {
		if(!doUpdate) {
			doUpdate = true;
			new Thread(updateTask).start();
		} else {
			System.out.println("Updater on line...");
		}
	}
	
	/** Ferma il ciclo di aggiornamento */
	public void stop() {
		if(doUpdate) {
			doUpdate = false;
		} else {
			System.out.println("Updater offline");
		}
	}
}
Screen.java
Codice:
package it.tukano.anisample;

import java.awt.*;
import java.util.*;
import javax.swing.*;

/** Lo schermo è un oggetto che proietta dei drawable ed è aggiornabile */
public class Screen implements Updatable {
	private ArrayList<Drawable> drawables = new ArrayList<Drawable>();
	
	/** Questo è il componente Swing che concretamente proietterà i
	Drawable sullo schermo...
	@see #draw*/
	private JComponent component = new JPanel() {
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			draw((Graphics2D)g);
		}
	};
	
	public void addDrawable(Drawable...d) {
		drawables.addAll(Arrays.asList(d));
	}
	
	public void update() {
		component.repaint();
	}

	public JComponent getComponent() {
		return component;
	}
	
	/** ... e questo è il metodo in cui è disegnato ciò che il componente
	Swing proietta. */
	private void draw(Graphics2D g) {
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, component.getWidth(), component.getHeight());
		for(Drawable d : drawables) {
			d.draw(g);
		}
	}
}
Main.java
Codice:
package it.tukano.anisample;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main {
	/** C.d. punto d'entrata dell'applicazione. */
	public static void main(String...args) {
		new Main().startAndShow();
	}
	
	/** Un vezzo personale :D */
	private Main() {}
	
	/** Nell'ordine, crea uno HorribleSprite, crea un Behavior (horrible
	pure quello), crea uno Screen, assegna una dimensione allo screen
	(400x400 px), aggiunge lo sprite come "oggetto che sarà disegnato sullo
	schermo", crea un Updater con un periodo ideale di 24ms, aggiunge
	allo updater lo schermo e il behavior come "oggetti che saranno
	aggiornati dall'aggiornatore", crea una finestra, collega alla finestra
	qualcosa che reagirà quanto questa sarà chiusa (per chiudere effettivamente
	la finestra e fermare l'aggiornatore), aggiunge il componente dello schermo
	alla finestra, impacchetta tutto e lo spara sullo schermo. */
	private void startAndShow() {
		HorribleSprite sprite = new HorribleSprite();
		Behavior simpleBehavior = new Behavior(sprite);
		Screen screen = new Screen();
		screen.getComponent().setPreferredSize(new Dimension(400, 400));
		screen.addDrawable(sprite);
		Updater updater = new Updater(24);
		updater.appendUpdatables(simpleBehavior, screen);
		JFrame window = new JFrame("AniSample");
		bindWindowListener(window, updater);
		window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		window.getContentPane().add(screen.getComponent());
		packAndShow(window, updater);
	}
	
	/** Assegna una dimensione al frame in base al suo contenuto, mostra
	la finestra sullo schermo e avvia lo updater */
	private void packAndShow(final JFrame frame, final Updater updater) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				frame.pack();
				frame.setVisible(true);
				updater.start();
			}
		});
	}
	
	/** Aggiunge un ascolatore alla chiusura della finestra frame. */
	private void bindWindowListener(final JFrame frame, final Updater updater) {
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				shutdownApp(frame, updater);
			}
		});
	}
	
	
	/** Invocato alla chiusura della finestra.la distrugge
	e ferma lo updater. Può comportare spegnimento
	dolce della JVM (anzi, l'idea è proprio quella) */
	private void shutdownApp(JFrame frame, Updater upd) {
		upd.stop();
		frame.dispose();
	}
}
L'idea (non mia anche se non ricordo più dove l'ho letta) è che uno sprite è qualcosa che ha un'immagine ed una posizione ed è disegnabile. Il comportamento di uno sprite, che è quello che anima, è un che di aggiornabile idealmente connesso ad uno Sprite (nell'esempio Behavior aggiorna la posizione dello sprite). Lo schermo disegna una serie di cose disegnabili (Drawable) e l'aggiornatore aggiorna una serie di cose aggiornabili. Lo schermo è aggiornabile, il comportamento è aggiornabile, lo sprite è disegnabile...alla fine della fiera vedi un quadrato rosso che parte per la milano sanremo (che, come tutti sanno, si trova a destra dello schermo ).
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 11-05-2006, 21:37   #7
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Intanto ti ringrazio tantissimo per il codice! Vorrei sapere, ma questo è lo stretto necessario per fare un'animazione del genere? O hai aggiunte delle piccole finezze tue?
Io sono proprio alle primi armi con il java e quindi mi sarebbe utile visionare un codice il pìù asciutto possibile, e senza metodi di programazzione troppo avanzati.
Vedo che hai fatto largo uso delle interfaccie, le quali ancora non mi sono chiarissime ma che sto cmq cercando di capire.
Se riesci a ridurlo ulteriormente mi saresti di grande aiuto!
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 11-05-2006, 22:27   #8
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Sul significato di "stretto necessario" potremmo iniziare qui una diatriba da concludersi a barbe bianche .

Il codice precedente non si avvicina neanche ad un che di orientato agli oggetti. E' facile osservare come l'oggetto Main sia in verità indistinto da HorribleSprite, Screen, Updater e Behavior. Abbi cuore, l'ho scritto in fretta .

Si può fare di meno (sul peggio avrei dei dubbi ).

ScreenWithAnimation.java
Codice:
package it.tukano.simpleranimation;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.*;

public class ScreenWithAnimation extends JPanel {
	/** Periodo del ciclo di animazione */
	private final long TIMER_PERIOD = 24;
	
	/** Velocità dello sprite in pixel per millisecondo */
	private final float SPEED = 0.1f;
	
	/** "Sprite" */
	private Rectangle2D.Float fakeSprite =
		new Rectangle2D.Float(0, 0, 20, 20);
		
	/** Variabili per il calcolo del tempo intercorso tra due passaggi nel
	ciclo di aggiornamento */
	private long time0, time1;
	
	/** Compito affidato al timer */
	private TimerTask updateTask = new TimerTask() {
		public void run() {
			long dTime = updateTime();
			updateSprite(dTime);
			repaint();
		}
	};
	
	/** Una specie di Thread che esegue (anche) compiti periodici */
	private java.util.Timer timer;
	
	/** Avvia l'animazione */
	public void start() {
		if(timer == null) {
			timer = new java.util.Timer();
			timer.scheduleAtFixedRate(updateTask, 0, TIMER_PERIOD);
		}
	}
	
	/** Ferma l'animazione */
	public void stop() {
		if(timer != null) {
			timer.cancel();
			timer = null;
		}
	}
	
	/** Restituisce il dT dall'ultima invocazione di updateTime */
	private long updateTime() {
		time1 = System.currentTimeMillis();
		if(time0 == 0) {
			time0 = time1;
		}
		long dTime = time1 - time0;
		time0 = time1;
		return dTime;
	}
	
	/** Aggiorna la posizione dello sprite */
	private void updateSprite(long dTime) {
		fakeSprite.setRect(
			fakeSprite.getX() + dTime * SPEED,
			fakeSprite.getY(),
			fakeSprite.getWidth(),
			fakeSprite.getHeight());
	}

	/** Disegna il componente e lo sprite */
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.RED);
		((Graphics2D)g).fill(fakeSprite);
	}
}
Main.java
Codice:
package it.tukano.simpleranimation;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main {

	public static void main(String...args) {
		new Main().setupAndShow();
	}
	
	private Main() {}
	
	private void setupAndShow() {
		JFrame frame = new JFrame("Simpler Animation");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		ScreenWithAnimation screen = new ScreenWithAnimation();
		screen.setPreferredSize(new Dimension(400, 400));
		screen.setBackground(Color.BLACK);
		frame.getContentPane().add(screen, BorderLayout.CENTER);
		bindWindowListener(frame, screen);
		packAndShow(frame, screen);
	}
	
	private void bindWindowListener(final JFrame f,
		final ScreenWithAnimation s)
	{
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				s.stop(); //<<-- qui si ferma l'animazione
				f.dispose();
			}
		});
	}
	
	private void packAndShow(final JFrame f, final ScreenWithAnimation s) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				f.pack();
				f.setVisible(true);
				s.start(); //<<-- qui parte l'animazione
			}
		});
	}
}
Il Main di questo è praticamente uguale al Main dell'altro, per questo non l'ho commentato.

java.util.Timer è un Thread che può eseguire un particolare Runnable (TimerTask) periodicamente.

Nota che nel nostro caso non è necessario appoggiarsi esplicitamente al Thread AWT Event Dispatcher (quello che deve occuparsi di aggiornare l'aspetto di componenti AWT/Swing visibili) poichè ridisegnamo il componente (ScreenWithAnimation qui e Screen là) usando il metodo repaint(). repaint() in realtà non repaint un bel nulla: quello che fa è premere nella coda degli eventi AWT (consumata dall'Event Dispatcher Thread) una richiesta di aggiornamento del componente.

Io credo che dalla seconda versione, pur più breve, non si evinca il fatto che l'animazione sia un procedimento in senso proprio (cioè la composizione di più atti distinti e collegati): è più un bel minestrone. Che sia più o meno facile da comprendere dipende poi dai punti di vista di chi guardi. Insomma, vedi tu .
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 11-05-2006, 22:38   #9
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Questo mi sembra già meglio ora me lo gurado un po' e vedo cosa chiderti
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 11-05-2006, 22:41   #10
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Ah ecco mi è venuta in mente subito una cosa, come mai nel main fai questo:
Codice:
public class Main {

	public static void main(String...args) {
		new Main().setupAndShow();
	}
	
	private Main() {}
	
	private void setupAndShow(){...}
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 00:31   #11
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Si tratta di una questione "tecnica" ma non di tecnica del linguaggio: in questo secondo caso, lo stesso metodo "main" è solo un suggerimento.

Solitamente la prima cosa che faccio nel metodo main di un programma Java è saltar fuori dal contesto statico in cui il main mi costringe.

Lo faccio perchè metodi e campi statici in Java sono in grado di infarfugliare anche le menti più arzille, soprattutto se mescolati a membri di istanza definiti nella stessa unità di compilazione: lì è l'apoteosi della confusione.

Il modificatore private applicato all'unico costruttore grida "questa classe non è la definizione di un oggetto". E' una collezione di procedure. Lo dico perchè tentare di assorbire nell'orientamento agli oggetti (che pure abbonda in creatività) qualcosa a cui nessuno salvo lui stesso può rivolgersi è da mal di testa.

Molto semplicemente, Main è quell'insieme di operazioni che devono essere fatte affinchè l'applicazione parta. Il fatto, imposto col costruttore private, che non possano essere create istanze di Main al di fuori dell'unità di compilazione Main.java è una specie di pugno sul tavolo: non si può e basta! .

Esiste la possibilità di applicare meccanismi più confacenti alle due O ma l'argomento era "come muovere qualcosa sullo schermo" e non "Elementi della prospettiva orientata agli oggetti: identità, ambiente, comunicazione".

Ecco, questa è la bella copia di quello a cui ho pensato quando ho scritto Main.java .
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 15:01   #12
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Si può costruire un rattangolo o in generale un poligono conoscendone le coordinate dei vertici? Perchè mi servirebbe poi spostare separatemente questi vertici, non tutta la figura insieme.
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 20:42   #13
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Yes.

Puoi usare un GeneralPath come definizione di un poligono generico. Questo dovrebbe essere un rettangolo in posizione (x0, y0) di larghezza (width, height):

Codice:
GeneralPath path = new GeneralPath();
path.moveTo(x0, y0);
path.lineTo(x0 + width, y0);
path.lineTo(x0 + width, y0 + height);
path.lineTo(x0, y0 + height);
path.closePath();
Lo proietti sullo schermo come ogni altro Shape:

graphics2d.fill(path) oppure graphics2d.draw(path)

Per manipolare i punti devi creare un tuo AffineTransform. Ridefinisci il metodo "transform(float[], int, float[], int, int)" del tuo AffineTransform in modo tale che intacchi i punti che ti interessano. Applichi la trasformazione con un:

path.transform(myAffineTransform);
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 20:58   #14
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Ehm mi sa che l'ultima parte me la devi rispiegare
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 21:42   #15
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Supponiamo che, dato lo Shape di tipo GeneralPath su definito, tu voglia spostare solo il primo punto. Per farlo devi trasformare la geometria di quel GeneralPath. Non ci sono AffineTransform pronti per fare un'operazione di questo tipo ragion per cui devi crearne uno da zero:

Codice:
public class FirstPointTranslator extends AffineTransform {
    public void transform(float[] src, int srcOff, float[] dst, int dstOff,
        int numPts)
    {
        if(srcOff == 0 && src.length > 1) {
            float x = src[0];
            float y = src[1];
            dst[dstOff] = x + 5;
            dst[dstOff + 1] = y + 5;
        }
    }
}
Ogni volta che applichi questa trasformazione, il primo punto della figura è spostato di 5 pixel verso destra e 5 pixel verso il basso.

FirstPointTranslator fpt = new FirstPointTranslator();
shape.transform(fpt); //hop, primo punto +5,+5
shape.transform(fpt); //hop, primo punto +5,+5

E' un approccio un po' crudo ma è l'unico se si vogliano sfruttare i "precotti" di Sun in materia di grafica vettoriale. In alternativa puoi definire un tuo oggetto Poligono e lì la strada si apre ai più biechi desideri.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 23:23   #16
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Grazie mille credo di aver capito.
Cosa intendi con "puoi definire un tuo oggetto Poligono"?
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 12-05-2006, 23:49   #17
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Ho cambiato la classe ScreenwhitAniamtion.java così
Codice:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.*;

public class ScreenWithAnimation extends JPanel {
	/** Periodo del ciclo di animazione */
	private final long TIMER_PERIOD = 24;
	
	/** Velocità dello sprite in pixel per millisecondo */
	private final float SPEED = 0.1f;
	
	/** "Sprite" */
	int[] xPoints={100,150,150,100};
	int[] yPoints={1,1,80,80};
	private GeneralPath fakeSprite = new GeneralPath(GeneralPath.WIND_EVEN_ODD,xPoints.length);
	fakeSprite.moveTo(xPoints[0],yPoints[0]);
	for (int index = 1;index < xPoints.length;index++) {
		fakeSprite.lineTo(xPoints[index],yPoints[index]);
	};
	fakeSprite.closePath();

	/** Variabili per il calcolo del tempo intercorso tra due passaggi nel
	ciclo di aggiornamento */
	private long time0, time1;
	
	/** Compito affidato al timer */
	private TimerTask updateTask = new TimerTask() {
		public void run() {
			long dTime = updateTime();
			updateSprite(dTime);
			repaint();
		}
	};
	
	/** Una specie di Thread che esegue (anche) compiti periodici */
	private java.util.Timer timer;
	
	/** Avvia l'animazione */
	public void start() {
		if(timer == null) {
			timer = new java.util.Timer();
			timer.scheduleAtFixedRate(updateTask, 0, TIMER_PERIOD);
		}
	}
	
	/** Ferma l'animazione */
	public void stop() {
		if(timer != null) {
			timer.cancel();
			timer = null;
		}
	}
	
	/** Restituisce il dT dall'ultima invocazione di updateTime */
	private long updateTime() {
		time1 = System.currentTimeMillis();
		if(time0 == 0) {
			time0 = time1;
		}
		long dTime = time1 - time0;
		time0 = time1;
		return dTime;
	}

	/** Aggiorna la posizione dello sprite */
	private void updateSprite(long dTime) {
	FirstPointTranslator fpt = new FirstPointTranslator();
	fakeSprite.transform(fpt);
	}
	
	/** Disegna il componente e lo sprite */
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.RED);
		((Graphics2D)g).fill(fakeSprite);
	}

}
Ma mi da <identifier>expected in corripsondenza di "private GeneralPath fakeSprite = new GeneralPath(GeneralPath.WIND_EVEN_ODD,xPoints.length);
fakeSprite.moveTo(xPoints[0],yPoints[0]);
for (int index = 1;index < xPoints.length;index++) {
fakeSprite.lineTo(xPoints[index],yPoints[index]);
};
fakeSprite.closePath();"
e illegal start of type in corrpisondenza del ciclo for...
Dove sbaglio?
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 13-05-2006, 11:29   #18
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Il corpo di una classe Java può contenere solo dichiarazioni oppure blocchi.

Codice:
class Bingo {

    int x = 30; //ok, dichiarazione con assegnamento contestuale
    GeneralPath x; //ok, dichiarazione
    x = new GeneralPath(...) //Niet!!! l'assegnamento non è dichiarazione
    for(int i = 0; i < 40; i++) { //Nain!!! il ciclo for non è una dichiarazione

    {   //Blocco
        for(int i = 0; i <... //Ok, un blocco può contenere l'istruzione for
    }

    public void doSomenthing() { //Ok, dichiarazione di metodo
}
Nel tuo caso abbiamo due tentate invocazioni di metodo (fakeSprite.moveTo e fakeSprite.closePath) e un ciclo for. Puoi usare un costruttore per "completare" la creazione del tuo GeneralPath:

Codice:
public class ScreenWithAnimation extends JPanel {
    GeneralPath fakeSprite = new GeneralPath(...omissis);

    public ScreenWithAnimation() {
	fakeSprite.moveTo(xPoints[0],yPoints[0]);
	for (int index = 1;index < xPoints.length;index++) {
		fakeSprite.lineTo(xPoints[index],yPoints[index]);
	};
	fakeSprite.closePath();
    }
}
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 13-05-2006, 11:35   #19
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Grazie mille chiarissimo!
Ma nell'esempio che mi hai fatto tu, inserisci il codice per spostare il quadrato qui:
Codice:
/** Aggiorna la posizione dello sprite */
	private void updateSprite(long dTime) {
		fakeSprite.setRect(
			fakeSprite.getX() + dTime * SPEED,
			fakeSprite.getY(),
			fakeSprite.getWidth(),
			fakeSprite.getHeight());
	}
Quindi in pratica il codice che è all'interno di questo metodo viene ripetuto ad intervalli di 24 ms se ho capito bene giusto?
E' quindi plausibile che pure io devo inserire qui il mio codice per spostare ruotare ecc ecc le mie figure?

Poi un altra cosa, diciamo che ora ho materiale a sufficicenza per cominciare a fare qualcosa di semplice, mi potresti spiegare cosa intendevi con crearti un oggetto Poligono? magari potrebbe semplificarmi la vita o comunque farmi capire meglio .
Sempre se non ti è troppo disturbo
Grazie ancora
MEMon è offline   Rispondi citando il messaggio o parte di esso
Old 13-05-2006, 11:40   #20
MEMon
Senior Member
 
Iscritto dal: Dec 2002
Messaggi: 3359
Ho fatto le modifiche che mi hai suggerito, ora compila ma quando esegue sulla console mi esce questo...
Codice:
Exception in thread "Timer-0" java.lang.NullPointerException
        at ScreenWithAnimation.updateSprite(ScreenWithAnimation.java:74)
        at ScreenWithAnimation.access$100(ScreenWithAnimation.java:6)
        at ScreenWithAnimation$1.run(ScreenWithAnimation.java:36)
        at java.util.TimerThread.mainLoop(Timer.java:512)
        at java.util.TimerThread.run(Timer.java:462)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at sun.awt.windows.Win32Renderer.doShape(Win32Renderer.java:217)
        at sun.awt.windows.Win32Renderer.fill(Win32Renderer.java:260)
        at sun.java2d.pipe.ValidatePipe.fill(ValidatePipe.java:142)
        at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2258)
        at ScreenWithAnimation.paintComponent(ScreenWithAnimation.java:81)
        at javax.swing.JComponent.paint(JComponent.java:1005)
        at javax.swing.JComponent.paintChildren(JComponent.java:842)
        at javax.swing.JComponent.paint(JComponent.java:1014)
        at javax.swing.JComponent.paintChildren(JComponent.java:842)
        at javax.swing.JComponent.paint(JComponent.java:1014)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:559)
        at javax.swing.JComponent.paintChildren(JComponent.java:842)
        at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4970)
        at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4916)
        at javax.swing.JComponent.paint(JComponent.java:995)
        at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
        at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
        at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
        at java.awt.Container.paint(Container.java:1709)
        at sun.awt.RepaintArea.paintComponent(RepaintArea.java:248)
        at sun.awt.RepaintArea.paint(RepaintArea.java:224)
        at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:254)
        at java.awt.Component.dispatchEventImpl(Component.java:4031)
        at java.awt.Container.dispatchEventImpl(Container.java:2024)
        at java.awt.Window.dispatchEventImpl(Window.java:1774)
        at java.awt.Component.dispatchEvent(Component.java:3803)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
A cosa si riferisce?
Questo è il codice per aggiornare la posizione dello sprite:
Codice:
	/** Aggiorna la posizione dello sprite */
	private void updateSprite(long dTime) {
	FirstPointTranslator fpt = new FirstPointTranslator();
	fakeSprite.transform(fpt);
	}
MEMon è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi Wind Tre 'accende' il 5G Standalone in Italia: s...
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh OPPO Find X9 Pro: il camera phone con teleobiett...
DJI Romo, il robot aspirapolvere tutto trasparente DJI Romo, il robot aspirapolvere tutto trasparen...
DJI Osmo Nano: la piccola fotocamera alla prova sul campo DJI Osmo Nano: la piccola fotocamera alla prova ...
FUJIFILM X-T30 III, la nuova mirrorless compatta FUJIFILM X-T30 III, la nuova mirrorless compatta
Trump ha graziato il fondatore di Binanc...
Perplexity firma un accordo con Getty Im...
La Polizia di Las Vegas è il prim...
Le nostre chat sono salve, Chat Control ...
Elon Musk promette di presentare il prot...
Rapina al Louvre: la password che proteg...
'L'auto volante' è finalmente rea...
Religione e pirateria: uno studio rivela...
Roborock QV 35A al nuovo minimo storico:...
Arriva Aardvark: il nuovo agente OpenAI ...
Bufera su Rockstar: licenziamenti per 40...
Il Black Friday di HONOR dura un mese! T...
Shadow AI: il lato invisibile dell’innov...
Microsoft tornerà ad assumere, ma...
MSI, tre notebook GeForce RTX in sconto ...
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: 11:33.


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