PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java Animation mit Threads



realtec
17-01-2004, 09:41
Hallo, ich habe folgendes Problem, ich will ein Programm erstellen, in dem 4 Rechtecke (Threads) sich ein Wettrennen abhalten. Wie kann ich das realisieren, im Moment bewegen sich alle Rechtecke gleich schnell....



import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class AnimationPanel1 extends JPanel
{
private int x;
private int y = 10;
boolean right = true;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillRect(x, y, 50, 20);
g.fillRect(x, 40, 70, 20);
g.fillRect(x, 70, 50, 20);
g.fillRect(x, 100, 50, 20);
// g.drawOval(10, 50, 300, 300);
// g.fillArc(10, 50, 300, 300, 0, x);

}
public void next()
{
if(right)
{
x++;
if(x == 360)
right = false;
}
else
{
x--;
if(x == 0)
right = true;
}
repaint();
}
}

class Animator1 extends Thread
{
private AnimationPanel1 animPanel;

public Animator1(AnimationPanel1 animPanel)
{
this.animPanel = animPanel;
}
public synchronized void run()
{
while(true)
{
animPanel.next();
try
{
Thread.sleep(60);
}
catch(InterruptedException e) {}
}
}
}

class Animator2 extends Thread
{
private AnimationPanel1 animPanel;

public Animator2(AnimationPanel1 animPanel)
{
this.animPanel = animPanel;
}
public void run()
{
while(true)
{
animPanel.next();
try
{
Thread.sleep(180);
}
catch(InterruptedException e) {}
}
}
}
public class Wettrennen
{
public static void main(String argv[])
{
JFrame f = new JFrame("Animation");
AnimationPanel1 a = new AnimationPanel1();
f.getContentPane().add(a);
f.setLocation(100, 100);
f.setSize(450, 400);
f.setVisible(true);
Animator1 animThread = new Animator1(a);
Animator2 animThread1 = new Animator2(a);
animThread.start();
animThread1.start();
}
}

peschmae
17-01-2004, 16:00
Ich verstehe nicht ganz wieso du zwei Threads hast.

Egal. Hier ein Beispiel, bei dem zufällig alle "speedChangeCount" Züge die Geschwindigkeit jedes der Rechtecke zufällig auf einen Wert zwischen 0 und 5 Pixel gesetzt wird. Da also die Rechtecke bis zu 5 Pixel/Zug vorwärtskommen ruckelt es ein klein bisschen.


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
class AnimationPanel1 extends JPanel
{
private int[] x = {0, 0, 0, 0};
private final int y = 10;
private boolean[] right = {true, true, true, true};

private final int speedChangeCount = 2;
private int speedCount = 0;

private final int maxSpeed = 5; //maximal speed in pixels
private final Random random = new Random();

private int[] speed = {0, 0, 0, 0};

public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillRect(x[0], y, 50, 20);
g.fillRect(x[1], 40, 50, 20);
g.fillRect(x[2], 70, 50, 20);
g.fillRect(x[3], 100, 50, 20);
// g.drawOval(10, 50, 300, 300);
// g.fillArc(10, 50, 300, 300, 0, x);

}
public void next()
{
for (int i = 0; i < x.length; i++)
{
if(right[i])
{
x[i] += speed[i];
if(x[i] >= 360)
right[i] = false;
}
else
{
x[i] -= speed[i];
if(x[i] <= 0)
right[i] = true;
}
}
repaint();

speedCount++;
if (speedCount == speedChangeCount) {
speedCount = 0;
for (int i = 0; i < x.length; i++)
speed[i] = random.nextInt(maxSpeed);
}
}
}

class Animator1 extends Thread
{
private AnimationPanel1 animPanel;

public Animator1(AnimationPanel1 animPanel)
{
this.animPanel = animPanel;
}
public synchronized void run()
{
while(true)
{
animPanel.next();
try
{
Thread.sleep(50);
}
catch(InterruptedException e) {}
}
}
}

public class Wettrennen
{
public static void main(String argv[])
{
JFrame f = new JFrame("Animation");
AnimationPanel1 a = new AnimationPanel1();
f.getContentPane().add(a);
f.setLocation(100, 100);
f.setSize(450, 400);
f.setVisible(true);
Animator1 animThread = new Animator1(a);
animThread.start();
}
}


Alternativ machst du für jedes der Rechtecke einen eigenen Thread (aber nicht eigenen Klassen für jeden Thread) der alle paar Züge zufällig die Wartezeit zwischen zwei "repaint()" neu berechnet.
Allerdings gibts dann vielleicht synchronisationsprobleme - da musst du wohl Methoden, die von verschiedenen Threads gleichzeitig aufgerufen werden können als "synchronized" deklarieren...

MfG Peschmä

realtec
17-01-2004, 16:25
Original geschrieben von peschmae


Alternativ machst du für jedes der Rechtecke einen eigenen Thread (aber nicht eigenen Klassen für jeden Thread) der alle paar Züge zufällig die Wartezeit zwischen zwei "repaint()" neu berechnet.
Allerdings gibts dann vielleicht synchronisationsprobleme - da musst du wohl Methoden, die von verschiedenen Threads gleichzeitig aufgerufen werden können als "synchronized" deklarieren...

MfG Peschmä [/B]

Hallo,
vielen Dank für den ersten Ansatz.
Ich will aber eigentlich 4 Threads erstellen, die mit unterschiedlichen Geschwindigkeiten laufen. Ich habe aber keine Ahnung, wie ich vorgehen muss, da alle Rechtecke im gleichen Panel sind....

Gruss
Christian

Lin728
17-01-2004, 16:30
Nun, pschmae hat dir doch eh schon gesagt wies geht.

Deiner Thread-Kasse übergibst du per Konstruktor dein Panel und die Wartezeit zwischen den einzelnen Paint-Aufrufen.

realtec
17-01-2004, 16:45
Sorry, stehe auf dem Schlauch.
Ich weiß nicht was ihr meint.... Habe allerdings auch nicht die größte Ahnung von Java :(

peschmae
17-01-2004, 16:45
immer noch peschmae :D

Die Wartezeit würde ich nicht dem Konstruktor übergeben sondern in der Klasse jeweils ab und zu per Random.nextInt(200) bestimmen - dann laufen die nämlich nicht immer gleich schnell.

Das Panel würd ich mal per Konstruktor übergeben und ausprobieren obs Synchronisationsprobleme gibt. Musst halt die Zeichnungsmethode ein bisschen anpassen, dass sie jeweils nur 1 Rechteck verschiebt.

MfG Peschmä

Lin728
17-01-2004, 17:09
O.K, mal ganz easy in java-pseudocode...


public class grundklasse extends JComponent
{
public void initThreads()
{
rectdraer rect1 = new rectdrawer(this);
rect1.start();
rectdrawer rect2 = ne wrectdrawer(this);
.......

}
}

public class rectdrawer extends Thread
{
JComponent comp;

public rectdrawer(JComponent comp)
{
this.comp = comp;
}

public void run()
{
while(true)
{
Thread.sleep(Variable Zeit);
comp.getGraphics.drawblablabla
}

}
}