# Frage zu Hütchenspielprogrammierung!



## Rich (15. Dez 2009)

Hallo liebe Leute,

ich bin neu hier und noch anfänger in der Java-Programmierung.

Ich muss von der Schule aus Spiel proggen, wo ich mir ein Hütchenspiel ausgesucht hab.

Leider komme ich bei der Animation der Hütchen nicht weiter. Ich weiß einfach nicht, wie ich das Hütchen von Koordinate A zu Koordinate B bewegen kann und dabei eine Kugel darunter verstecken kann.

Das Prog geht nur bis jetzt nur bis zum eigentlichen Spiel, also die Kontenberechnung geht nicht

Wer sich das Spiel anschauen möchte hier:

```
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Line2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ImageIcon;

public class Huetchen extends JFrame implements ActionListener {
	JButton weiterButton;
	JButton einsatzSetzeButton;
	JTextField spielerName;
	JTextField einsatz;
	JPanel panel1;
	JPanel panel2;
	JFrame rahmen;
	JButton bt2;
	Checkbox Cbox1;
	Checkbox Cbox2;
	JLabel label1;
	JLabel label2;
	JLabel ueberschrift;
	JLabel bild;
	JLabel halloUser;
	JLabel einsatzText;
	JLabel kontostandText;
	JLabel kontostand;
	JLabel eurozeichen1;
	JLabel eurozeichen2;
	JLabel huetchen1;
	JLabel huetchen2;
	JLabel huetchen3;
	String myfile;
	String myfile2;
	String username;
	

	/*****************
	 * Konstruktor *
	 ****************/
	public Huetchen() {

		this.setTitle("Hütchenspiel");
		this.setSize(600, 600);
		this.setResizable(false);

		// Neue Panel erzeugen + panel hinzufuegen und sichtbar machen
		panel1 = new JPanel();
		panel2 = new JPanel();
		add(panel1);
		panel1.setVisible(true);

		// Layout Manager einrichten
		panel1.setLayout(null);
		panel2.setLayout(null);

		// alles mögliche zu Panel1 hinzufuegen
		panel1.setBackground (new Color ( 181, 181, 181));
		ueberschrift = new JLabel("Das Hütchenspiel");
		ueberschrift.setFont(ueberschrift.getFont().deriveFont(26f));
		ueberschrift.setBounds(200, 20, 300, 26);
		panel1.add(ueberschrift);
		label1 = new JLabel("Bitte gib deinen Spielernamen an:");
		label1.setBounds(80, 400, 200, 20);
		panel1.add(label1);
		myfile = "C:/Users/sam/Desktop/Hütchenspiel/huetchen.gif";
		bild = new JLabel(new ImageIcon(myfile));
		bild.setBounds(160, 70, 280, 306);
		panel1.add(bild);
		spielerName = new JTextField("Spielername", 20);
		spielerName.setBounds(280, 400, 130, 20);
		panel1.add(spielerName);
		panel1.add(weiterButton = new JButton("Weiter"));
		weiterButton.setBounds(280, 430, 130, 20);
		panel1.add(weiterButton);
		

		// alles mögliche zu Panel2 hinzufuegen
		panel2. setBackground (new Color ( 181, 181, 181));
		ueberschrift.setBounds(200, 20, 300, 26);
		panel2.add(ueberschrift);
		einsatzText = new JLabel("Wieviel möchtest du setzen?");
		einsatzText.setBounds(30, 390, 200, 20);
		panel2.add(einsatzText);
		kontostandText = new JLabel("Dein Kontostand:");
		kontostandText.setBounds(30, 430, 200, 20);
		panel2.add(kontostandText);
		kontostand = new JLabel("XXX");//Kontostand wird angezeigt
		kontostand.setBounds(240, 430, 50, 20);
		panel2.add(kontostand);
		einsatz = new JTextField("XXX", 20);
		einsatz.setBounds(240, 390, 50, 20);
		panel2.add(einsatz);
		eurozeichen1 = new JLabel("€");//Eurozeichen1
		eurozeichen2 = new JLabel("€");//Eurozeichen2
		eurozeichen1.setBounds(300, 390, 10, 20);
		eurozeichen2.setBounds(300, 430, 10, 20);
		panel2.add(eurozeichen1);
		panel2.add(eurozeichen2);
		myfile2 = "C:/Users/sam/Desktop/Hütchenspiel/huetchen.png";
		huetchen1 = new JLabel(new ImageIcon(myfile2));
		huetchen1.setBounds(80, 150, 86, 95);
		panel2.add(huetchen1);
		huetchen2 = new JLabel(new ImageIcon(myfile2));
		huetchen2.setBounds(260, 150, 86, 95);
		panel2.add(huetchen2);
		huetchen3 = new JLabel(new ImageIcon(myfile2));
		huetchen3.setBounds(440, 150, 86, 95);
		panel2.add(huetchen3);
		
		
		
		

		// ActionListener hinzufuegen
		weiterButton.addActionListener(this);
		
		// WindowListener hinzufuegen
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent we) {
				System.exit(0);
			}
		});

	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	// Button Event
	public void actionPerformed(ActionEvent ae) {
		//Object quelle = ae.getSource();
		//if (quelle == bt1) {
			String a = spielerName.getText();
			

			if (a.length()>0) {
				setUsername(spielerName.getText());
				
				// altes panel unsichtbar machen
				panel1.setVisible(false);
				panel1.removeAll();
				
				// panel hinzufügen und sichtbar machen
				add(panel2);
				panel2.setVisible(true);
				halloUser = new JLabel("<html><span style=\"font-size:14px\">Hallo "+
"<span style=\"color:red\">"+getUsername()+"</span></span></html>");//Namen uebergeben
				halloUser.setBounds(30, 350, 200, 20);
				panel2.add(halloUser);
				
				
			} else {
				this.label2 = new JLabel("Bitte gib deinen Spielernamen an!!!");
				this.label2.setForeground(Color.red);
				this.label2.setFont(label2.getFont().deriveFont(16f));
				this.label2.setBounds(110, 480, 300, 20);
				this.panel1.add(label2);
				
				
			}
		}

	/****************
	 * Startpunkt *
	 ***************/
	public static void main(String[] args) {
		JFrame rahmen = new Huetchen();
		rahmen.setVisible(true);
	}
}
```

Wäre echt schön wenn mir jemand das proggen könnte, wodurch ich mir anschauen könnte wie das ganze geht.

Achso, ich möchte es sozusagen so haben, das ein Spieler einen Kontobetrag X hat, dann man eine Betrag eingibt den man setzen möchte, dann auf starten klickt, sich das Hütchen hebt(jetzt der Ball sichtbar wird). Sich dann das Hütchen wieder drauf setzt und die Hütchen sich verschieben.
Dann soll man auf das Hütchen klicken, wo man denkt das die Kugel darunter ist. Und dann die Meldung kommt gewonnen oder verloren.


Ich bedanke mich schoneinmal vielmals Voraus!

(Ich hoffe ich hab alles angegeben)

MfG
Rich


----------



## SlaterB (15. Dez 2009)

arbeite dich durch
http://www.ralf-bauer.org/java/tutorial/Tutorial.zip
das sollte paar Grundlagen zur 2D-Grafik enthalten


----------



## javimka (15. Dez 2009)

Du solltest vermeiden, Swing und AWT zu mischen. Verwende JCheckbox statt der Checkbox.


----------



## Steev (16. Dez 2009)

Hi,

erst mal Grundsätzlich: Bitte niemals absolute Pfade verwenden!!!
[Java]"C:/Users/sam/Desktop/Hütchenspiel/huetchen.gif"[/Java]

Verwende lieber etwas in der Art, da du dies dann später ohne weiteres portieren kannst:
[Java]URL yourUrl = getClass().getResource("huetchen.gif");[/Java]

Dein "huetchen.gif" wird relativ zu deiner Main-Klasse abgelegt.

Zur Animation:
Du brauchst einfach nur ein Objekt mit dem du dein Hütchen verwalten kannst.
[Java]public class Hat {
  private int x = 0;
  private int y = 0;
  private BufferedImage image; // Bitte nur referenzial, nie ein Bild pro Objekt!!!
  public Hat(int x, int y, BufferedImage image) {
    this.x = x;
    this.y = y;
    this.image = image;
  }

  public void move(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public int getX() {
    return x;
  }

  public int getY() {
    return y;
  }

  public BufferedImage getImage() {
    return image;
  }

  public void setImage(BufferedImage image) {
    this.image = image;
  }

  // Wichtig: Hier wird gezeichnet:
  public void paint(Graphics g) {
    if(img == null) return;
    g.drawImage(x, y, img, null);

    // Nur Test, damit Bewegung in dein Bild kommt 
    x++;
  }
}[/Java]

Dann brauchst du nur noch eine Anzeigeklasse. Das hier ist natürlich nur ein Ansatz:
[Java]
public class YourGameArea extends JPanel implements Runnable {
  LinkedList<Hat> hats = new LinkedList<Hat>();

  public YourGameArea() throws Exception {
    new Thread(this).start();

    // Nur Test:
    BufferedImage img = ImageIO.read(getClass().getResource("yourImage.gif"));
    Hat hat = new Hat(100, 100, img);
    hats.add(hat);
  }

  public void run() {
    while(true) {
      try {
        repaint();
        Thread.sleep(120);
      } catch (Exception e) {}
    }
  }

  public void paint(Graphics g) {
    if (hats != null && !hats.isEmpty())
      for (Hat hat : hats)
        if (hat != null)
          hat.paint(g);
  }
}
[/Java]

Gruß
Steev


----------



## Rich (19. Dez 2009)

So ich mal wieder, also hab das Zeichnen jetzt hinbekommen:

Hier meine Klasse, wo dei Hütchen bewegt werden:


```
import java.awt.*;

import javax.swing.*;

public class HuetchenBewegungen extends JPanel implements Runnable{
	

	private static final long serialVersionUID = 1L;
	
	//JFrame frame;   //das Fenster
	int imageX1;
	int imageY1;
	int imageX2;
	int imageY2;
	int imageX3;
	int imageY3;
	int imageWidth;
	int imageHeight;
	
	boolean test=true;
	
	Image img = Toolkit.getDefaultToolkit().getImage("C:/Users/sam/Desktop/Hütchenspiel/huetchen.png");
	
	int dx1 = 1; //Bewegungsänderung in x1
	int dy1 = 1; //Bewegungsänderung in y1
	int dx2 = 1; //Bewegungsänderung in x2
	int dy2 = 1; //Bewegungsänderung in y2
	int dx3 = 1; //Bewegungsänderung in x3
	int dy3 = 1; //Bewegungsänderung in y3
	
	
	
	
	public HuetchenBewegungen(){
		
		
		setBackground (new Color ( 121, 121, 121));
		
		imageX1 = 162; 
		imageY1 = 150;
		imageX2 = 260; 
		imageY2 = 150;
		imageX3 = 358; 
		imageY3 = 150;
		imageWidth = 80;
		imageHeight = 88;

		
		Thread t = new Thread(this); //Schleife im eigenen Thread
		t.run();
	}
	

	
	
	
	public void run() {
	
		while(test==true){  
			
			/*tauscheLinkRechts();
			
			try {
				Thread.sleep(5);  //Päuschen
			} catch (InterruptedException e) {}
			
			repaint();  //Repaint
			if(imageY1<151){
				test=!test; // Thread wird bei dieser Bedingung beendet
			}
			
			tauscheMitteRechts();
			
			try {
				Thread.sleep(5);  //Päuschen
			} catch (InterruptedException e) {}
			
			repaint();  //Repaint
			if(imageY2<151){
				test=!test; // Thread wird bei dieser Bedingung beendet
			}
			
			}*/
		
			tauscheLinksMitte();
			
			try {
				Thread.sleep(5);  //Päuschen
			} catch (InterruptedException e) {}
			
			repaint();  //Repaint
			if(imageY1<151){
				test=!test; // Thread wird bei dieser Bedingung beendet
			}
			
			}
		
	}
	
	private void tauscheLinkRechts(){
		
		if(imageX1==260){
			dy1 = -1;
		}
		if(imageX3==260){
			dy3 = -1;
		}
		
		imageX1 += dx1;
		imageY1 += dy1;
		imageX3 -= dx3;
		imageY3 -= dy3;

	}
	private void tauscheMitteRechts(){
		
		if(imageX2==309){
			dy2 = -1;
		}
		
		if(imageX3==309){
			dy3 = -1;
		}
		imageX2 += dx2;
		imageY2 += dy2;
		imageX3 -= dx3;
		imageY3 -= dy3;

	}
	
	private void tauscheLinksMitte(){
		
		if(imageX1==211){
			dy1 = -1;
		}
		
		if(imageX2==211){
			dy2 = -1;
		}
		imageX1 += dx1;
		imageY1 += dy1;
		imageX2 -= dx2;
		imageY2 -= dy2;

	}


	@Override
	//Hier wird gemalt
	protected void paintComponent(Graphics g) {
		super.paintComponent(g); //super-Aufruf, darf nicht vergessen werden
		
		// Hüte zeichnen
		g.drawImage(img, imageX1, imageY1,this);
		g.drawImage(img, imageX2, imageY2,this);
		g.drawImage(img, imageX3, imageY3,this);
		//g.drawImage(img, 358, 150,this);
		
	}


}
```

ich weiß, die absoluten Pfade sind noch drin, das ändere ich noch !

Aber zu meinem Problem, ich habe in meiner Hauptklasse ein JPanel erzeugt, welches meiner  HuetchenBewegungen Klasse zugeordnet ist:
(panel2 ist meine Oberfläche, darauf wird meine HuetchenBEwegung als JPanel geladen)

```
JPanel spielPanel;
...
spielPanel = new HuetchenBewegungen();
...
panel2.add(spielPanel);
```

Das JPanel HuetchenBewegungen wird auch angezeigt, bloß wollte ich, wenn ich einen Button drücke(Button soll auf panel2 sein), das sich die Huetchen aus HuetchenBewegung nun verschieben.

Leider weiß ich nicht wie das geht, hab wohl ein Brett vor dem Kopf! Also ich sehe die Hütchen und wenn ich das HuetchenBewegungen als Frame mache, gehen die BEwegungen. Aber irgendwie wird das HuetchenBewegungen Panel nur einmal auf Panel2 gezeichnet und das wars.

Kann mir da jemand helfen?

Danke im Voraus!

Rich


----------



## javimka (19. Dez 2009)

Zeile 50:  t.start();

Sehe ich das richtig, dass sich das JPanel alle 5 ms selbst neu zeichnen soll? Wenn ja, empfehle ich dir dringen, das anders zu machen, denn du solltest unnötiges zeichen (wenn sich gar nichts geändert hat) vermeiden.
Stattdessen solltest du bei all deinen Methoden, die die Hütchen bewegen, also tauscheLinkRechts() usw. ein repaint() zum Schluss aufrufen. Ich glaube, dann kansnt du dir das ganze run() sparen.


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Zeile 50:  t.start();
> 
> Sehe ich das richtig, dass sich das JPanel alle 5 ms selbst neu zeichnen soll? Wenn ja, empfehle ich dir dringen, das anders zu machen, denn du solltest unnötiges zeichen (wenn sich gar nichts geändert hat) vermeiden.
> Stattdessen solltest du bei all deinen Methoden, die die Hütchen bewegen, also tauscheLinkRechts() usw. ein repaint() zum Schluss aufrufen. Ich glaube, dann kansnt du dir das ganze run() sparen.



Zeile 50 steht bei mir: t.run();

damit wird einmalig die Methode run() aufgerufen, die wiedrerum hat ne While schleife, die solange durchläuft wie test==true ist, ich hab ja dann in der while-schleife ne if abfrage, wo dann ab einer bestimmten bedingung test=false gesetzt wird und dann wird run nicht mehr ausgeführt.

aber solange test==true ist, wird das panel alle 5 ms neugezeichnet, richtig

(5 ms deswegen, wegen der flüssigen bewegung  )


----------



## javimka (19. Dez 2009)

Rich hat gesagt.:


> Zeile 50 steht bei mir: t.run();


Und genau da sollte start() stehen. Wieso solltest du sonst einen neuen Thread erstellen, wenn du ihn dann nicht auch als Thread startest (mit start())?


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Und genau da sollte start() stehen. Wieso solltest du sonst einen neuen Thread erstellen, wenn du ihn dann nicht auch als Thread startest (mit start())?



kannste mir da mal zeigen, wie du das dann mit der t.start() meinst ?

danke dir


----------



## javimka (19. Dez 2009)

```
Thread t = new Thread(this); //Schleife im eigenen Thread
        t.start();
```


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> ```
> Thread t = new Thread(this); //Schleife im eigenen Thread
> t.start();
> ```



 ich meinte was in start() dann stehen muss


```
public void start(){
// was soll hier stehen ?
}
```


----------



## javimka (19. Dez 2009)

Du musst keine neue neue Methode erstellen, sondern das start() von Thread verwenden.

Ganz einfach: Ersetzt "run" durch "start" und fertig


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Du musst keine neue neue Methode erstellen, sondern das start() von Thread verwenden.
> 
> Ganz einfach: Ersetzt "run" durch "start" und fertig



? aber was macht start denn da jetzt?

run() wird ja gar nicht mehr ausgeführt? und in run() stehen ja die ganzen methodenaufrufe ;-) also wie sich die hütchen bewegen sollen ;-)

ne also an dem t.run(); liegt es nicht, ich weiß eben nur nicht, wenn ich das panel Huetchenbewegung, wo ich ja nun geschrieben hab wie ich die hütchen bewegen sollen, wie ich dieses panel zum starten bekomm?
einfaches adden zu dem panel2 scheint ja nicht zu reichen ...


----------



## javimka (19. Dez 2009)

Du machst mich noch fertig :lol:

Was passiert denn, wenn du meine verrückte Idee folgst und start() statt run() aufrufst?

Wenn du t.run() aufrufst wird kein neuer Thread gestartet! Dein run() wird zwar ausgeführt, aber immer noch vom alten Thread. Du musst start() aufrufen! Dann wird ein neuen Thread erstellt, der dann dein run() ausführt.

EDIT: Gefriert dein Fenster eigentlich ein, wenn du run() aufrufst? Ironischerweise sollte es das genau dann, wenn du es richtig programmiert hast, nämlich den konstruktor im Event-Dispatching-Thread (EDT) aufrufen. Aber lassen wir das mal weg.


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Du machst mich noch fertig :lol:
> 
> Was passiert denn, wenn du meine verrückte Idee folgst und start() statt run() aufrufst?
> 
> ...



Wie gesagt, ich bin ein Anfänger ;-) Da kam mir das ein bisschen spanisch vor, das man mit t.start(); auf einmal die run() aufrufen kann ;-) Entschuldigung für das ... 

Ähm einfrieren, nein, tut es nicht, es geht dir while-schleife solange durch bis die if-bedingung in der schleife eintritt und dadurch die schleife nicht mehr aufgerufen wird.

Aber kannst du  mir da helfen wie ich nun die Hütchenbewegungen mir anzeigen lassen kann, wenn ich im Panel2 auf einen Button drücke?

Danke dir

Rich


----------



## javimka (19. Dez 2009)

Hat der Button einen ActionListener? Wie sieht der aus?

Kann es ein, dass deine Hütchen zwar bewegt werden, aber jeweils nur um genau ein Pixel und du es deshalb gar nicht siehst?


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Hat der Button einen ActionListener? Wie sieht der aus?
> 
> Kann es ein, dass deine Hütchen zwar bewegt werden, aber jeweils nur um genau ein Pixel und du es deshalb gar nicht siehst?



mein Actionlistener sieht so aus


```
einsatzSetzeButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae) {
            	
            	
            	//hier weiß ich net was rein soll
            }
        });
```

wie gesagt, ich hab vorher schon spielPanel = new HuetchenBewegungen(); und das spielpanel dem panel2 hinzugefügt (panel2.add(spielPanel)

das Panel mit den Hütchen wird ja angezeigt, aber es läuft nichts ab

und nein, ich hab gestern abend es ausprobeiert und gemacht, das die hütchen sich richtig bewegen, darum die 3 verschiedenen Methoden tauscheLinksMitte(); , tauscheLinkRechts(); und tauscheMitteRechts(); ;-)

das anzeigen und bewegen der Hütchen hat ja super geklappt, aber halt nicht, wenn ich es in ein anderes panel adde


----------



## javimka (19. Dez 2009)

Wenn du dein Panel mit den Hütchen in einem JFrame hinzufügst, funktioniert es, aber wenn du es einem JPanel panel2 hinzufügst funktioniert es nicht? O_O
Hast du das panel2, dem du das SpielPanel hinzugefügt hast, denn auch dem JFrame hinzugefügt?

In deiner ActionPerformed müsste doch etwas stehen wie [c]spielPanel.tauscheLinksMitte();[/c]. Wenn das nicht geht, musst du spielPanel final machen: [c]final HuetchenBewegungen spielPanel = new HuetchenBewegungen();[/c]


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Wenn du dein Panel mit den Hütchen in einem JFrame hinzufügst, funktioniert es, aber wenn du es einem JPanel panel2 hinzufügst funktioniert es nicht? O_O
> Hast du das panel2, dem du das SpielPanel hinzugefügt hast, denn auch dem JFrame hinzugefügt?
> 
> In deiner ActionPerformed müsste doch etwas stehen wie [c]spielPanel.tauscheLinksMitte();[/c]. Wenn das nicht geht, musst du spielPanel final machen: [c]final HuetchenBewegungen spielPanel = new HuetchenBewegungen();[/c]



meinst du so ?

```
einsatzSetzeButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae) {
            	
            	
            	spielPanel.tauscheLinksMitte();
...
```

weil da passiert nichts, und ich musste final [c]HuetchenBewegungen spielPanel = new HuetchenBewegungen();[/c] machen

und ja, panel2 wurde dem JFrame hinzugefügt ;-)

was mir grad auffällt, wenn ich [c]spielPanel.tauscheLinksMitte();[/c] da rein schreibe wird ja nur die method eaufgerufen, da ist ja keien schleife drin usw. da dürfte doch gar nix passieren oder?


----------



## javimka (19. Dez 2009)

Wie ist denn eigentlich der Stand, siehst du das Spiel, also klappt das?

Und dann schreib noch [c]spielPanel.repaint()[/c] nach dem anderen Aufruf im ActionListener hin. Du musst dann gut hinschauen, denn dein Bild wird sich, wenns denn funktioniert, nur um ein einziges Pixel bewegen.

Übrigens ist davon auszugehen, dass deine while-Schleife in run() sofort abbrechen wird. Du initialisierst imageY1 nämlich mit 150 und in deiner Schleife prüfst du imageY1<151, was natürlich sofort true liefern und die Schleife abbrechen wird.


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Wie ist denn eigentlich der Stand, siehst du das Spiel, also klappt das?
> 
> Und dann schreib noch [c]spielPanel.repaint()[/c] nach dem anderen Aufruf im ActionListener hin. Du musst dann gut hinschauen, denn dein Bild wird sich, wenns denn funktioniert, nur um ein einziges Pixel bewegen.
> 
> Übrigens ist davon auszugehen, dass deine while-Schleife in run() sofort abbrechen wird. Du initialisierst imageY1 nämlich mit 150 und in deiner Schleife prüfst du imageY1<151, was natürlich sofort true liefern und die Schleife abbrechen wird.



hehe, also es pixelweise geklappt  weil der speichert ja die postionen imemr noch, also soll ich jetzt am besten die ganzen if-bedingungen und die while-schleife in den actionperformed reinhauen? würde ja sicher auch gehen

ach es ging aber erst richtig, als ich den ganzen inhalt aus run() auskommentiert hab, sonst kam er irgendwie durcheinander...


----------



## javimka (19. Dez 2009)

Ein bisschen problematisch ist dein Konzept halt schon. Ich nehme an, wenn ein Button geklickt wird, sollen jeweils zwei Bilder ihre Positionen vertauschen.

Schreib nicht zu viel in den ActionListener rein. Besser ist es, wenn der einfach die richtige Tausch-Methode aufruft und das Panel das dann selber managed. Die Methode tauscheLinksMitte könnte z.B einen neuen Tread starten, der ein Runnable erhält, welches das ausführt, was du willst.

```
new Thread(new Runnable() {
  public void run() {
    // while ...
    // Positionen neu berechnen
    // repaint(); // WICHTIG!
    // Thread.seep(10);
    // }
  }
}).start(); // start, damit es auch wirklich parallel ausgeführt wird
```

Dann musst du dir noch überlegen, wie du sicherstellst, dass nicht zwei Buttons gleichzeigig gedrückt werden und ein heilloses Chaos mit den Positionen entsteht, aber mach eines nach dem anderen


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Ein bisschen problematisch ist dein Konzept halt schon. Ich nehme an, wenn ein Button geklickt wird, sollen jeweils zwei Bilder ihre Positionen vertauschen.
> 
> Schreib nicht zu viel in den ActionListener rein. Besser ist es, wenn der einfach die richtige Tausch-Methode aufruft und das Panel das dann selber managed. Die Methode tauscheLinksMitte könnte z.B einen neuen Tread starten, der ein Runnable erhält, welches das ausführt, was du willst.
> 
> ...




ahh, also ich kann mir grad gut vorstellen wie du es meinst, ich werd mich mal dran setzen und das ganze dann hier posten 

Wie meinst du das mit 2 Buttons? auf dem Panel sind nur ein paar JLabels und ein paar JTextfields, eins wo der "kontostand" gezeigt wird und eins, wo man den gewünschten betrag setzt ;-) und den button, um die hütchen zu animieren...

muss bloß irgendwie nen zufall reinbekommen, wo er halt zufällig auswählt, welche hütchen grad getauscht werden sollen...


----------



## Steev (19. Dez 2009)

Ich würde einfach die Logik innerhalb des Hauptthreads meines Beispiels schreiben. Mit dem Button verändert man dann nur eine Statusvariable, auf diese dann die Logik entsprechend reagieren muss.
Man sollte sowieso nur so wenige Threads wie möglich aufmachen, da man sonst - und vor allem als Anfänger - sehr schnell auf Probleme wie Deathlocks oder sonst was stößt. Man sollte besser von vorneherein ein klares Konzept entwerfen.


----------



## Rich (19. Dez 2009)

also ich habs jetzt so gelöst:

```
import java.awt.*;

import javax.swing.*;

public class HuetchenBewegungen extends JPanel {

	private static final long serialVersionUID = 1L;

	// JFrame frame; //das Fenster
	int imageX1;
	int imageY1;
	int imageX2;
	int imageY2;
	int imageX3;
	int imageY3;
	int imageWidth;
	int imageHeight;

	boolean bed1 = true;
	boolean bed2 = true;
	boolean bed3 = true;

	Image img = Toolkit.getDefaultToolkit().getImage(
			"C:/Users/sam/Desktop/Hütchenspiel/huetchen.png");

	int dx1 = 1; // Bewegungsänderung in x1
	int dy1 = 1; // Bewegungsänderung in y1
	int dx2 = 1; // Bewegungsänderung in x2
	int dy2 = 1; // Bewegungsänderung in y2
	int dx3 = 1; // Bewegungsänderung in x3
	int dy3 = 1; // Bewegungsänderung in y3

	public HuetchenBewegungen() {

		setBackground(new Color(121, 121, 121));

		imageX1 = 162;
		imageY1 = 150;
		imageX2 = 260;
		imageY2 = 150;
		imageX3 = 358;
		imageY3 = 150;
		imageWidth = 80;
		imageHeight = 88;

	}

	public void tauscheLinksRechts() {

		new Thread(new Runnable() {
			public void run() {
				while (bed1 == true) {

					if (imageX1 == 260) {
						dy1 = -1;
					}
					if (imageX3 == 260) {
						dy3 = -1;
					}

					imageX1 += dx1;
					imageY1 += dy1;
					imageX3 -= dx3;
					imageY3 -= dy3;

					repaint(); // WICHTIG!
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (imageY1 < 151) {
						bed1 = !bed1; // Thread wird bei dieser Bedingung
										// beendet
						imageX1 = 162;
						imageX3 = 358;
					}
				}
			}
		}).start();

	}

	public void tauscheMitteRechts() {

		new Thread(new Runnable() {
			public void run() {
				while (bed2 == true) {

					if (imageX2 == 309) {
						dy2 = -1;
					}

					if (imageX3 == 309) {
						dy3 = -1;
					}
					imageX2 += dx2;
					imageY2 += dy2;
					imageX3 -= dx3;
					imageY3 -= dy3;

					repaint(); // WICHTIG!
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (imageY2 < 151) {
						bed2 = !bed2; // Thread wird bei dieser Bedingung
										// beendet
						imageX2 = 260;
						imageX3 = 358;
					}
				}
			}
		}).start();

	}

	public void tauscheLinksMitte() {

		new Thread(new Runnable() {
			public void run() {
				while (bed3 == true) {

					if (imageX1 == 211) {
						dy1 = -1;
					}

					if (imageX2 == 211) {
						dy2 = -1;
					}
					imageX1 += dx1;
					imageY1 += dy1;
					imageX2 -= dx2;
					imageY2 -= dy2;

					repaint(); // WICHTIG!
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (imageX1 > 259) {
						bed3 = !bed3; // Thread wird bei dieser Bedingung
										// beendet
						imageX1 = 162;
						imageX2 = 260;
					}
				}
			}
		}).start();
	}

	@Override
	// Hier wird gemalt
	protected void paintComponent(Graphics g) {
		super.paintComponent(g); // super-Aufruf, darf nicht vergessen werden

		// Hüte zeichnen
		g.drawImage(img, imageX1, imageY1, this);
		g.drawImage(img, imageX2, imageY2, this);
		g.drawImage(img, imageX3, imageY3, this);
		// g.drawImage(img, 358, 150,this);

	}

}
```

ähm 2 Sachen vllt noch, ich habe zum Beispiel bei tauscheLinksRechts das hier:

```
...
if (imageY1 < 151) {
						bed1 = !bed1; // Thread wird bei dieser Bedingung
										// beendet
						imageX1 = 162;
						imageX3 = 358;
					}
...
```
gemacht, damit danach die Bedingung, also die Schleife, beim nächsten aufruf wieder richtig funzt.

Ein andere Sache noch, wie kann ich hier:

```
einsatzSetzeButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae) {
            	
            	spielPanel.tauscheLinksRechts();
            	//spielPanel.tauscheLinksMitte();
            	//spielPanel.tauscheMitteRechts();
            	            	
            }
        });
```

jetzt dem klar machen, das der per Zufall 5 mal hintereinander irgendeine Methode auswählen soll. Also das 5mal hintereinander sich die Hütchen verschieben sollen.

Ach ja, ich konnte jetzt Runnable und den Hauptthread rausnehmen, @Steev, oder ist das nicht gut?

Danke für die vielen Tipps! hat mich bis jetzt echt weitergebracht!


----------



## javimka (19. Dez 2009)

Ich dachte, da sei je ein Button für jede mögliche Bewegung, aber wenn es nur einer ist, hast du es einfacher. Dann musst du dir nämlich nur die Frage stellen, was passiert, wen diser Button mehrmals schnell nacheinander gedrückt wird und mehrere Tausch-Operationen parallel ausgeführt werden. 
Vermeiden kannst du das, indem du den Button einfach vorübergehen mit setEnabled(false) deaktivierst und wieder aktivierst, wenn der Tausch vollbracht ist.
Oder die Klasse HuetchenBewegung überprüft beim Aufruf einer Tausch-Operation zuerst, ob bereits ein Tausch im Gange ist und verwirft den neuen Tausch oder stellt ihn in die Warteschleife.

So kriegst du auch kein Wirrwar mit den vielen Threads, weil die alle nacheinander laufen und nur parallel zum EDT (für die Graphik) sind.


----------



## javimka (19. Dez 2009)

Nimm das Runnable und run() aus der Klasse Huetchenspiel raus.

Du musst noch sicherstellen, dass deine while-Schleifen zu Beginn immer true auswerten, also bed1, bed2, bed3 müssen zu Beginn auch wirkich true sein. Das realisierst du am einfachsten, indem du beim Start der methode die jeweilige Bedingung auf true setzt.

Zufallszahlen erstellst du mit

```
Random rand = new Random();
int zahl = rand.nextInt(5) // Zahl zwischen 0 und 4
```

Wenn du das jetzt 5-Mal hintereinander ausführen willst, ist das wieder etwas komplizierter. Mein Konzept war natürlich darauf ausgerichtet, dass du pro Buttonklick eine Bewegung ausführst. Vielleicht gibst du deiner Klasse Huetchenspiel eine Methode:
tauscheMehrmals(int t) und diese Methode ruft dann zufällig tauscheLinksRechts oder was auch immer auf und wenn diese Methode fertig ist, ruft diese wieder tauscheMehrmals(t-1) auf, bis t==0 ist. Ist einfach umzusetzen, aber gar nicht schön.

Vielleicht setzt du dich noch etwas mehr mit Threads, wait() und notifyAll() auseinander, wenn du eine sauberere Lösung wünschst.


----------



## Rich (19. Dez 2009)

javimka hat gesagt.:


> Vielleicht setzt du dich noch etwas mehr mit Threads, wait() und notifyAll() auseinander, wenn du eine sauberere Lösung wünschst.



also ich hab echt schon viel Code jetzt angeschaut, aber irgendwie komm ich damit nicht klar, meinste du kannst mir zeigen wie das geht? oder jemand anderes!? an meinem Code wäre natürlich schön, dann kann ich mir das mal anschauen!

Danke Vielmals im Voraus!

Rich


----------



## Rich (30. Dez 2009)

Also irgendwie klappt das nicht, mein Starte-Button ruft nun die Methode "animationStraten()" auf.

In der steht folgendes:

```
public void animationStarten() throws InterruptedException{
                TauscheLinksRechts tlr = new TauscheLinksRechts();
                TauscheMitteRechts tmr = new TauscheMitteRechts();
                tlr.start();
                tlr.join();
                tmr.start();
        }
```

meine Threads habe ich nun in KLassen geschrieben, die wie folgt aussehen:


```
public class TauscheLinksRechts extends Thread {

                public void run() {
                                while (bed1==true) {

                                        if (imageX1 == 260) {
                                                dy1 = -1;
                                        }
                                        if (imageX3 == 260) {
                                                dy3 = -1;
                                        }

                                        imageX1 += dx1;
                                        imageY1 += dy1;
                                        imageX3 -= dx3;
                                        imageY3 -= dy3;

                                        repaint(); // WICHTIG!
                                        try {
                                                Thread.sleep(10);
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                        if (imageY1 < 151) {
                                                bed1=!bed1; // Thread wird bei dieser Bedingung
                                                                                // beendet
                                                imageX1 = 162;
                                                imageX3 = 358;
                                        }
                                }
                        }

        }

        public class TauscheMitteRechts extends Thread {

                public void run() {
                                while (bed2 == true) {

                                        if (imageX2 == 309) {
                                                dy2 = -1;
                                        }

                                        if (imageX3 == 309) {
                                                dy3 = -1;
                                        }
                                        imageX2 += dx2;
                                        imageY2 += dy2;
                                        imageX3 -= dx3;
                                        imageY3 -= dy3;

                                        repaint(); // WICHTIG!
                                        try {
                                                Thread.sleep(10);
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                        if (imageY2 < 151) {
                                                bed2 = !bed2; // Thread wird bei dieser Bedingung
                                                                                // beendet
                                                imageX2 = 260;
                                                imageX3 = 358;
                                        }
                                }
                        }

        }
```

Wenn ich nun nur tlr.start(); aufrufen würde, klappt das ja, aber wenn ich tlr.start();tlr.join(); und tmr.start(); zusammen aufrufe, sehe ich nur noch das endergebnis!

Warum werden meine Hütchen nicht gezeichnet? Warum sehe ich dann nur das Endergebnis?
Und eine Frage noch, ich möchte das die Hütchenpositionen wieder in Ihre Ausgangsposition gesetzt werden, also die X und Y Werte, warum klappt das nicht?(mit imageX1=... und imageX2=... am ende jeder Methode, amache ich das) ich hab mal geschaut, die neuen X und Y werte werden ja zugewiesen. Aber dann müsste doch die Animation wieder von vorne losgehen, wenn ich den Button wieder anklicke!? Oder läuft da irgendwie der Thread noch?

danke schon einmal


----------



## javimka (30. Dez 2009)

Die Methode animationStarten() wird sicherlich vom EDT ausgeführt. Wenn du dann tlr.join() aufrufst, wird dieser eingefroren, bis der tlr Thread fertig ist. In dieser Zeit kann er die Graphik nicht neu zeichnen.

Wenn du es so schreibst, sollte es funktionieren:

```
new Thread(new Runnable() {
    public void run() {
                TauscheLinksRechts tlr = new TauscheLinksRechts();
                TauscheMitteRechts tmr = new TauscheMitteRechts();
                tlr.start();
                tlr.join();
                tmr.start();
    }
}).start();
```

Wenn die run Methode fertig ist, ist der tlr Thread ganz sicher beendet, der tmr Thread könnte noch laufen, weil du ja kein join aufrufst.


----------



## Steev (30. Dez 2009)

Hi,

ich würde so wenige Threads wie möglich verwenden. Ich habe dir mal ein kleines Beispiel geschrieben, damit du verstehst was ich meine. Ist jetzt natürlich kein Lehrbuchcode, aber ich denke, du kommst damit  klar


----------



## Steev (31. Dez 2009)

Moin,

ich habe spaßeshalber den Code mal zu ende geschrieben. Vieleicht ist das ja das, was du brauchst.
Hoffentlich ist der Code einigermaßen verständlich, falls du Fragen hast, kannst du dich ja nochmal melden.

Gruß
Steev


----------



## Rich (6. Jan 2010)

ähm also ich hab jetzt das Hütchenspiel fertig gestellt... aber eine kleine Frage habe ich noch.

Meine ganzen SourceDatein sind in src/default package(also keinem Paket) . Jetzt habe ich ein img Ordner in src erstellt, also src/img.

Jetzt die Frage, ich habe dort 3 Bilder drin, für das Projekt, wenn ich das Prog mit Eclipse öffne findet er die Datein bzw. Grafiken. Aber sobald ich eine "Runnable Jar File" erstelle und die dann öffne, findet er die Grafiken nicht mehr. Geht das nicht oder mache ich was falsch?

Also hier der Link zu den Grafiken innerhalb des Projektes 
	
	
	
	





```
myfile = "src/img/huetchen.gif";
```

danke im voraus...

Wenn das Prob gelöst ist, stell ich mal die Jar Datei rein.


----------



## javimka (6. Jan 2010)

Hast du den Ordner mit den Bildern in den Buildpath eingefügt?
Rechtsklick auf das package->Buil Path->Configure Build Path-> Tab "Source" -> add Folder

Schau doch mal, ob die Bilder wirklich im jar drin sind. Das findest du heraus, wenn du das jar mit WinRar o.ä. öffnest. VORSICHT: Wenn du das jar mit einem anderen Programm als Java öffnest, kreuze auf keinen Fall "immer mit diesem Programm öffnen" an!!!


----------



## Rich (6. Jan 2010)

javimka hat gesagt.:


> Hast du den Ordner mit den Bildern in den Buildpath eingefügt?
> Rechtsklick auf das package->Buil Path->Configure Build Path-> Tab "Source" -> add Folder


also der ordner ist nicht drin, aber dort steht Huetchenspiel/src und darunter Included(All) und wenn ich den Ordner hinzufüge kommt 
	
	
	
	





```
Cannot nest Huetchenspiel/src/img
```



javimka hat gesagt.:


> Schau doch mal, ob die Bilder wirklich im jar drin sind. Das findest du heraus, wenn du das jar mit WinRar o.ä. öffnest. VORSICHT: Wenn du das jar mit einem anderen Programm als Java öffnest, kreuze auf keinen Fall "immer mit diesem Programm öffnen" an!!!


im jar sind die Bilder drinne...


----------



## javimka (6. Jan 2010)

Du solltest die Bilder sowieso aus dem src Ordner nehmen. Erstelle neben src und bin doch noch den Ordner img für die Bilder.
Wenn du das hast, versuch mal folgendes, auch wenn es doof aussieht: Statt alle Bilder in den Ordner img zu schmeissen, eröffne im Ordner img einen weiteren Ordner img und stelle sie da rein. Sonst veränderst du aber nichts und dann versuchst du des nochmals.


----------



## Rich (6. Jan 2010)

javimka hat gesagt.:


> Du solltest die Bilder sowieso aus dem src Ordner nehmen. Erstelle neben src und bin doch noch den Ordner img für die Bilder.
> Wenn du das hast, versuch mal folgendes, auch wenn es doof aussieht: Statt alle Bilder in den Ordner img zu schmeissen, eröffne im Ordner img einen weiteren Ordner img und stelle sie da rein. Sonst veränderst du aber nichts und dann versuchst du des nochmals.



gemacht, getan, leider klappt es immernoch nur in Eclipse, als Jar nicht, aber der img Ordner ist in der jar datei drin, auch die pics dort sind enthalten .... mmmh


----------



## javimka (7. Jan 2010)

Ich bin nicht der Spezialist für Eclipse/jars und Importieren von Bildern, ich kann dir nur sagen, wie es bei mir funktioniert.

Ich habe die Ordner
bin/... - mit allen Binärdateien
src/... - mit allen Source Files
img/img/... - mit allen Ressourcen

Im Build Path unter Source habe ich drin
Projektname/img
Projektname/src
Im Build Path unter Order and Export sind diese beiden Ordner mit blauen Viereck markiert.

Im kreiirten Jar File habe ich dann als Ordner die einzelnen Packetnamen und den Ordner img. Hier sind die Bilder direkt im img-Ordner, es existiert also kein img/img mehr.

Wenn du dein jar in der Konsole startest (java -jar name.jar), kommt dann eine Exception, dass die Bilder nicht gefunden wurden? Gegebenfalls eröffnest du halt einen neuen Thread, dieser hier hat ja schon zig Beiträge, hier schauen wahrscheinlich nicht mehr alle rein, die dir da eher helfen könnten.


----------



## Rich (7. Jan 2010)

javimka hat gesagt.:


> Ich bin nicht der Spezialist für Eclipse/jars und Importieren von Bildern, ich kann dir nur sagen, wie es bei mir funktioniert.
> 
> Ich habe die Ordner
> bin/... - mit allen Binärdateien
> ...



mmmh, also bei mir ist genau alles dasselbe wie bei dir... na dann werd ich mal morgen mal einen neuen Thread eröffnen... aber dir jedenfalls vielen vielen Dank für all deine Mühe!

ich geh jetzt pennen


----------



## Steev (7. Jan 2010)

Guten Mittag,

der Ordner "src" dient nur zur Strukturierung in Eclipse, der Quellcode sollte von den Class-Dateien getrennt werden. Mit der Struktur innerhalb der JAR-Datei hat das nichts zu tun. Daher sollte man einen Resourcenordner auch nicht in den Ordner src stellen. Ich würde den Ordner mit den Bildern direkt unter das Projekt schieben und die Bilder in etwas so ansprechen.


```
BufferedImage img = ImageIO.read(getClass().getResource("img/hat.gif"));
```

In der JAR-Datei (das kannst du mit WinRaR etc. nachprüfen) sollte der Ordner "img" dann direkt unter dem Wurzelverzeichnis zusammen mit den class-Dateien liegen. Das ist wichtig, da die Resourcen relativ zur ausgeführten Main-Klasse gesucht werden.

Gruß
Steev


----------



## Rich (11. Jan 2010)

Also iwi klappt das mit den Grafiken nicht, aber ist ja auch net so schlimm... ich hab ja versprochen das Spiel hier zu posten... damit mach ichs hier... mal sehn ob es euch einigermaßen gefällt. Und ja ich weiß, mega toll ist es nicht, aber für mein erstes Spiel reicht mir das 

Und danke nocheinmal allen!!!


----------



## javimka (11. Jan 2010)

Für das erste Spiel ist es klasse! 
Die Animationen hast du super hingekriegt.


----------



## Rich (11. Jan 2010)

javimka hat gesagt.:


> Für das erste Spiel ist es klasse!
> Die Animationen hast du super hingekriegt.



meinste das ernst? oh danke!

lustig ist nur, wenn ich das hütchenspiel bei mir starte(dual core 2,18ghz und 2,5gb ram) dann ist "schwer" als schwierigkeitsstufe, wirklich schwer bis eigentlich fast unmöglich...

bei nem kumpel, der noch 1 prozessor hat, ist "schwer" als schwierigkeitsstufe so, wie bei mir einfach 

also voll lustig....


----------



## eRaaaa (11. Jan 2010)

Also ich sehe leider gar keine Animation/Becher oder sonst was (habe trotzdem 2 von 3 mal richtig getippt heheh ;D ). Leider aber auch keine Fehlermeldung in der Konsole, so dass ich dir einen Hinweis geben könnte woran das liegen kann. Sourcen habe ich mir jetzt nicht angeschaut, wollts nur mal schnell in den Raum geworfne haben !


----------



## Rich (11. Jan 2010)

eRaaaa hat gesagt.:


> Also ich sehe leider gar keine Animation/Becher oder sonst was (habe trotzdem 2 von 3 mal richtig getippt heheh ;D ). Leider aber auch keine Fehlermeldung in der Konsole, so dass ich dir einen Hinweis geben könnte woran das liegen kann. Sourcen habe ich mir jetzt nicht angeschaut, wollts nur mal schnell in den Raum geworfne haben !



ja dann haste den img ordner nicht oder die images sind net drin... ich weiß, ich wollte es ja mit in die jar datei hauen... aber iwi hat das bei mir net geklappt :noe:

darum ist das ne absolute fehlerquelle, ich weiß :noe:


----------



## eRaaaa (11. Jan 2010)

Ahh! Ja super jetzt klappt`s. Hatte mir nur das jar-File aus dem Archiv gezogen. Sorry!

Dann kann ich ja jetzt auch sagen, dass ich es gelungen finde  Sieht ganz schick aus ^^


----------



## Rich (11. Jan 2010)

eRaaaa hat gesagt.:


> Ahh! Ja super jetzt klappt`s. Hatte mir nur das jar-File aus dem Archiv gezogen. Sorry!
> 
> Dann kann ich ja jetzt auch sagen, dass ich es gelungen finde  Sieht ganz schick aus ^^



 danke ... und wie gesagt, ich weiß das das auf keinen fall optimal gemacht ist mit den pics


----------



## Steev (13. Jan 2010)

Ich finde das Spiel auch sehr gelungen.

Das Problem, mit der Animationsgeschwindigkeit kann mithilfe eines Frame Limiters gelößt werden. Eigendlich misst du nur die Rendergeschwindigkeit und entscheidest dann, ob das Bild neugezeichnet werden muss, oder ob lieber noch eine Weile gewartet werden sollte.
Den Zeitfaktor solltest du auch für Bewegungsberechnungen mit verwenden, da du dann sicher gehst, dass die Bewegung auf allen Rechnern in derselben Zeit abläuft. Ist der Rechner langsamer, so muss die Größe einer Bewegung sehr groß sein, ist ein Rechner schneller, so muss die Größe der Bewegung klein sein.

Gruß
Steev


----------

