# Minigolf für Java



## Firemozzi (30. Mai 2010)

Hallo zusammen, ich muss für meine Schule ein Minigolf programmieren, Aber ich hab ein Problem, mein Knopf "Schuss" zeigt keinerlei Reaktion.

Wäre genjal wenn sich einer mal den Code anschauen könnte und mir einen Tipp geben könnte ( Bitte keine zu hohe Java Kentnisse und leicht erklärt, bin noch ein relativer Neuling. ( Den Code habe ich zu 99% aus dem Kopf programmiert...)


```
// Roman Egger
// IPA GIBZ
// Minigolf V.1.0
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
import java.math.*;

import java.math.*;





public class Ball extends Applet
		implements ActionListener,MouseListener {

	int width, height;
	   int mx, my;  // the mouse coordinates
	   boolean isButtonPressed = false;
//Variablendefinition
	private Button Schuss;   //Knopf, für schiessen
	public int x = 80, xV = 1; //x = Ballposition X, xV = Bewegung richtung X
	public int y = 80, yV = 2; //y = Ballposition Y, YV = Bewegung richtung Y
	public int i=0; // i = Eingelocht?, wenn ja 1
	public int durchmesser = 10; // durchmesser des Balls
	public int time=10; // Pausenzeit zwischen den Frames
	public int timme=0; // Erweiterte, unter Pausenzeit, ( time+1 erhöht sich zu schnell)
	public int n=1; // n = Anzahl Durchläufe
	public int testxvxy=1; // Variable, ob der Test, dass die Bewegung nicht zu schnell ist, gelungen ist.
	public int stop=0; // ob der ball angehalten ist?
	private Graphics g; // Hauptgrafik
	public int beweg=1; // Zwischenvariable für das bewegen des Balls
	private float verhaeltnis; //
	public int xkathete;
	public int ykathete;
	
	public int kgvx;
	public int kgvy;
	public int kgvyold;
	public int kgvxold;
	public int kgvtmp;
	public int once = 1;
	
	public int rechteckLinksX = 10, rechteckRechtsX = 100; 		// Definition, der Rechtecke
	public int rechteckObenY = 10, rechteckUntenY = 100;		//      
	//public int rechteckLinksX2 = 61, rechteckRechtsX2 = 140;	//     
	//public int rechteckObenY2 = 101, rechteckUntenY2 = 180;	//
	public void mouseEntered( MouseEvent e ) {
	
	}//Vielleicht werden die MouseEvents später gebraucht.
	
	public void mouseExited( MouseEvent e ) {
	      
	}
	public void mouseClicked( MouseEvent e ) {// Wenn geklickt, dann Positionen aufnehmen.
		   mx = e.getX();
		      my = e.getY();
		      
	}// Englische hilfe
	public void mousePressed( MouseEvent e ) {  // called after a button is pressed down
	
	}
	public void mouseReleased( MouseEvent e ) {  // called after a button is released
	
	}
	public void mouseMoved( MouseEvent e ) {  // called during motion when no buttons are down
	
	}
	public void mouseDragged( MouseEvent e ) {  // called during motion with buttons down
	
	}
	   
	
		public void init(){
			Schuss = new Button("Schuss");
			add(Schuss);
			Schuss.addActionListener(this);
			addMouseListener(this); 
		}

		
		public void actionPerformed(ActionEvent event) {
			if (event.getSource() == Schuss){
				
			
				if (stop==1){//Wenn der Ball stillsteht
					
					stop=0;
					if (x > mx){
						xkathete=x-mx;
					}
					if (x < mx){
						xkathete=mx-x;
					}
					if (y > my){
						ykathete=y-my;
					}
					if (y < my){
						ykathete=my-y;
					}

					 kgvx=x;
					 kgvy=y;
					 kgvxold=x;
					 kgvyold=y;
					 do {
						 kgvtmp = kgvx % kgvy;
						 kgvx = kgvy;
						 kgvy = kgvtmp;
						 
					 } while (kgvtmp != 0);
					 
					 if (xkathete > ykathete){
						 verhaeltnis=xkathete/ykathete;
						 verhaeltnis = Math.round(verhaeltnis);
		
					 xkathete =((kgvxold/kgvx)*kgvy);	
					 xV = xkathete;
					 ykathete = xkathete*(int)verhaeltnis;
					 yV = ykathete;
					 }
					 else
					 {
						 verhaeltnis=ykathete/xkathete;
						 verhaeltnis = Math.round(verhaeltnis);
					ykathete =((kgvxold/kgvx)*kgvy);
					
					 ykathete =((kgvxold/kgvx)*kgvy);	
					 yV = ykathete;
					 xkathete = ykathete*(int)verhaeltnis;
					 xV = xkathete;
					 
					 }
					 
					 paint(g);
							
				}
				
				 stop = 0;
				 i = 0;
				 n = 1;
				 time = 10;
				 timme = 0;
				 testxvxy=1;
			}
			
					}

						
		public void paint(Graphics g){
			g.setColor(Color.green);
			
			g.fillRect(rechteckLinksX, rechteckObenY,rechteckRechtsX - rechteckLinksX,rechteckUntenY - rechteckObenY);//Rechteck 1 Zeichnen
			//g.fillRect(rechteckLinksX2, rechteckObenY2,rechteckRechtsX2 - rechteckLinksX2,rechteckUntenY2 - rechteckObenY2);// Rechteck 2 Zeichnen
			setBackground(Color.gray);
			g.setColor(Color.black);
			if(mx!=0 & my !=0){
				g.drawLine(x+5,y+5,mx,my);
			      repaint();
			     
			     
					  Color hintergrundFarbe = getBackground();
						g.setColor(Color.white);
						g.fillOval(x,y,durchmesser,durchmesser);
				 
			    
			}
			n = 1;
			for (int n = 1; n<1000000; n++) {
				if(i==0){
					Color hintergrundFarbe = getBackground();
					g.setColor(Color.white);
					g.fillOval(x,y,durchmesser,durchmesser);
				}
				if (x>45&&x<55&&y>45&&y<55||i==1){ // Wenn der Ball, im Bereich des Loches ist, dann Alles anhalten
					g.setColor(Color.BLUE);
					g.drawString("EINGELOCHT", 50, 80);
					i=1;
					n=1000001;
					xV=0;
					yV=0;
				}
				else{
		
		if(xV<0){
					for(int beweg=0; beweg>xV; beweg--){
						if(x > rechteckLinksX+1){
							x = x - 1;	
						}
							else {
								xV = -xV;
								beweg=xV;
							}
					}
				}
					else{
						for(int beweg=0; beweg<xV; beweg++){
							if(x < rechteckRechtsX-10){
								x = x + 1;	
							}
								else {
									xV = -xV;
									beweg=xV;
								}
						}
					}
		if(yV<0){
			for(int beweg=0; beweg>yV; beweg--){
				if(y > rechteckObenY+1){
					y = y - 1;	
				}
					else {
						yV = -yV;
						beweg=yV;
					}
			}
		}
			else{
				for(int beweg=0; beweg<yV; beweg++){
					if(y < rechteckUntenY-10){
						y = y + 1;	
					}
						else {
							yV = -yV;
							beweg=yV;
						}
				}
			}
			n=1000001;
			}
			
	
			g.setColor(Color.lightGray);
		g.fillOval(x,y,durchmesser,durchmesser);
		g.setColor(Color.black);
		g.fillOval(50,50,10,10);
		repaint();
		try {
			Thread.currentThread().sleep(time);
			}catch(InterruptedException e){};
			timme=timme+time;
			if(xV!=0&&yV!=0){
			if(timme>=20){
				timme=1;
				time= time+1;
			}
			}
			if(time>100){
				stop=1;
				time=1;
				xV=0;
				yV=0;
				}
			repaint();
			}
	}	
		public void update(Graphics g)
		{
			g.fillOval(x,y,durchmesser,durchmesser);
			g.setColor(Color.black);
			g.fillOval(50,50,10,10);
			repaint();
		      paint(g);
		      repaint();

		} 
		
}
```

Wer sich in den Code reingearbeitet hat, und mit mir Reden möchte kann mich auch bei Skype adden, bin den Ganzen Tag noch online ( @dd firemozzi)

Ich habe Kommentare gemacht, damit man es evtl versteht... Jegliche Tipps wären supernützlich. Ich erwarte nicht von euch, dass ihr den Code überhaupt anschaut, es ist nämlich schon ein richtig dicker Schinken ^^

Danke Schonmal, Gruss Roman


----------



## Marco13 (30. Mai 2010)

Er wirft erstmal eine Exception beim Zeichnen. Das liegt daran, dass du das "Graphics"-Objekt zwischenspeicherst. Nimm' das mal raus. ALLES, was gezeichnet wird, muss von der paint-Methode aus (in das dort übergebene Graphics-Objekt) gezeichnet werden.

Ansonsten wirst du in Schwierigkeiten laufen, weil du alles mit int's berechnest: 

```
public int xkathete;
    public int ykathete;
    ...
                         verhaeltnis=xkathete/ykathete;
```

Wenn z.B. xkathete=100 ist, und ykathete=99, dann wird bei xkathete/ykathete immer 0 rauskommen, weil nur mit ganzen Zahlen gerechnet wird, und man 0.99 damit nicht darstellen kann (das wird dann eben 0). Stell' mal alles, was irgendwie mit Mathematik zu tun hat, auf float oder double um.

Die eigentliche Ursache, warum beim Schuss nichts passiert, konnte ich auf die Schnelle wegen des unübersichlichen Codes nicht nachvollziehen... (und bei sowas wie [c]for (int n = 1; n<1000000; n++) [/c] rollen sich einem halt leicht mal die Fußnägel hoch...  )


----------



## nrg (30. Mai 2010)

nur kurz angekuckt aber müsstest du den mouselistener net auch auf deinen button adden und nicht auf this?


```
public void init(){
            // ....
            Schuss.addActionListener(this);
            addMouseListener(this); // <-
        }
```


----------



## Firemozzi (30. Mai 2010)

Marco13 hat gesagt.:


> Er wirft erstmal eine Exception beim Zeichnen. Das liegt daran, dass du das "Graphics"-Objekt zwischenspeicherst. Nimm' das mal raus. ALLES, was gezeichnet wird, muss von der paint-Methode aus (in das dort übergebene Graphics-Objekt) gezeichnet werden.
> 
> Ansonsten wirst du in Schwierigkeiten laufen, weil du alles mit int's berechnest:
> 
> ...




Das mit dem Exception und Zwischenspeichern etc, habe ich jetz 5 mal genau durchgelesen, aber ich weiss nicht was du damit meinst

Das mit den Int's habe ich jetz mal gemacht, das klärt auch wieso immer 0 rausgekommen bist, thx =)


Der Unübersichtliche Code, muss ich dir leider extrem recht geben xD
Das mit [c]for (int n = 1; n<1000000; n++) [/c] ist nur eine provisorische Zwischenlösung... Man könnte auch machen while (1==1)... ^^
Aber ich muss halt ein *.jar machen ( Applet zum einbinden im Browser) und keine Applikation... ^^


----------



## Firemozzi (30. Mai 2010)

nrg hat gesagt.:


> nur kurz angekuckt aber müsstest du den mouselistener net auch auf deinen button adden und nicht auf this?
> 
> 
> ```
> ...



Danke,
der MouseListener hat ansich nichts mit dem Knopf zu tun : Er soll nur "zuhören" wo geklickt wird, um die Bahn dann zu berechnen,Schaue meinen Screenshot, Vielleicht hilft er auch anderen.

Der ActionListener an sich funktioniert eigentlich schon, aber der Code hat irgendetwas, was verhindert, dass es ausgeführt wird. und ich finde es nicht. bei "Schuss", wird überprüft, ob Stop == 1 ist und wenn das der Fall ist, sollte die Geschwindigkeit modifiziert werden ( xV = Pixelbewegung auf der X Achse, bzw Y Achse ( yV) )
diese Modifizierung wiederum soll den Ball wieder in Bewegung bringen.


----------



## Firemozzi (30. Mai 2010)

Kann nochmal einer anschauen? ;( ich muss bis Mittwoch fertig sein :/


----------



## André Uhres (30. Mai 2010)

In actionPerformed musst du paint(g); unbedingt rausnehmen.
In actionPerformed scheint auch die Berechnung von xV und yV nicht zu stimmen. Beide Variable sind am Ende gleich 0.


----------



## Firemozzi (30. Mai 2010)

André Uhres hat gesagt.:


> In actionPerformed musst du paint(g); unbedingt rausnehmen.
> In actionPerformed scheint auch die Berechnung von xV und yV nicht zu stimmen. Beide Variable sind am Ende gleich 0.



Vielen Dank schonmal, das hat schon was gebracht.

Das mit der xV und yV berechnung scheint nicht zu funktionieren... Die Berechnung dafür ist auch leider verdammt schwer.
Ich glaube sogar, der Code würde funktinieren wenn diese Berechnung richtig wäre...

Am besten ich mache die Berechnung ganz neu.

Ich dachte das könnte funktionieren mit der xKathete und yKathete...

Vielleicht hat jemand eine Idee:

Also, wir haben die Position des Balls, sei
x = 50, und y = 50

Der Ball bleibt stehen, jetzt wird auf das Feld geklickt, ( Mouse Y = my, und Mouse x = mx)
Beispiel my = 80, mx = 80

Dieses Beispiel ist leicht, der Ball muss, um diese Strecke zurücklegen, immer abwechslungsweise ein Pixel nach rechts, und dann einen nach unten, sprich, xV = 1, und yV = 1 (nach rechts wäre xV=-1 und nach oben yV = -1)
wenn jetzt aber my = 90 und mx = 70 wäre, was auch praktisch viel öfters der Fall wird, dass es kein 45° Winkel ist, 
habe ich ein dickes Problem!
Das Programm muss ausrechnen können, wieviel Pixel es nach links / rechts geht, und dann nach oben / unten. Aber wie zum Teufel will man das anstellen :shock:?
;(;(;(


----------



## Marco13 (30. Mai 2010)

Es gibt da unterschiedlich geschickte, unterschiedlich schöne und unterschiedlich "mathelastige" Ansätze. Aber wie schon gesagt wirst du immer in Probleme laufen, wenn du versuchst, alles mit int zu berechnen. Die ganzen Rechnungen (d.h. auch die Ballposition) sollten zumindest float sein. Wenn man die Ballposition am Ende verwendet, um den Ball zu zeichnen, muss man sie eben auf int casten - aber das eben NUR zum Zeichnen - Pseudocode:


```
private float x = 0.0f;
private float y = 0.0f;

void move()
{
    for (int i=0; i<10; i++)
    {
        x = x + 0.1f;
        y = y + 0.4f;
    }
}

void paint(Graphics g)
{
    // NUR zum Zeichnen auf int casten
    int ix = (int)x;
    int iy = (int)y;
    g.drawOval(ix-3, iy-3, 6, ,6);
    ...
}
```


Oder bezogen auf dein Beispiel:

```
float x = 50;
float y = 50;

// wenn jetzt aber my = 90 und mx = 70 ...
float mx = 90;
float my = 70;

int anzahlSchritte = 10;
float änderungProSchrittX = (mx-x)/anzahlSchritte; // Ergibt (90-50)/10 = 0.4
float änderungProSchrittY = (my-y)/anzahlSchritte; // Ergibt (20-50)/10 = 0.2

// Beim Bewegen dann: 
for (int i=0; i<anzahlSchritte; i++)
{
    x = x + änderungProSchrittX;
    y = y + änderungProSchrittY;
}
```


----------



## Firemozzi (30. Mai 2010)

Marco13 hat gesagt.:


> Es gibt da unterschiedlich geschickte, unterschiedlich schöne und unterschiedlich "mathelastige" Ansätze. Aber wie schon gesagt wirst du immer in Probleme laufen, wenn du versuchst, alles mit int zu berechnen. Die ganzen Rechnungen (d.h. auch die Ballposition) sollten zumindest float sein. Wenn man die Ballposition am Ende verwendet, um den Ball zu zeichnen, muss man sie eben auf int casten - aber das eben NUR zum Zeichnen - Pseudocode:
> 
> 
> ```
> ...



Danke schonmal für die Mühe, sehr aufmerksam von dir aber: Du kannst den Ball aber nicht auf Kommastellen von Pixeln bewegen, darum habe ich ja auch einen Int genommen, und wenn man deine Methode wählt, wird der Ball ja gar nicht gezeichnet, bis er deine Rechnung gelaufen ist, d.h. er springt einfach nur zu dem Punkt, wo man klickt, vom Ansatz her schon sehr gut, aber Auch etwas ist kompliziert:
ich meine, es gibt nicht nur so gerade zahlen wie 70:90, sondern vlt auch 1:99, 13:17 oder 28:31, Sprich Primzahlen! oder vlt, wird ausserhalb des Spielfelds geklickt! an sich ein sehr guter Ansatz, aber das Programm selber muss ja Ausrechnen können, wieviel Pixel nach links und nach rechts ( Bei 0:0 zu 13:17 zb müsste es dann so sein: R= rechts, u = unten,  1r1u paint, 1u, paint, 1r1u paint, 1u, paint, 1r1u paint, 1u, paint, 1r1u paint,1r1u paint, <-- hier dann 2 mal, damit es aufgeht, und diese Unregelmässigkeiten machen mir zu schaffen, ich habe mir auch überlegt, einen Art Tachometer zu machen mit einer Auswahl von 8 Winkeln, aber dann kann man natürlich nicht Minigolf spielen! das ist extrem unprofessionell...


----------



## Landei (30. Mai 2010)

Marco hat recht. Wenn du Geld von einer Währung in eine andere tauschst, nimmt die Bank auch den Wechselkurs mit allen 6 oder so Dezimalstellen und rundet erst am Ende, obwohl sie "im Prinzip" ja nur ganze Cents oder so rausgeben kann. Auch alle 3D-Engines verwenden float oder double, obwohl am Ende nur Pixel rauskommen, warum wohl? Verwendest du ints, verlierst du Genauigkeit, Punkt.


----------



## André Uhres (31. Mai 2010)

Firemozzi hat gesagt.:


> Ich dachte das könnte funktionieren mit der xKathete und yKathete...



Nach dieser Schleife:

```
do {
    kgvtmp = kgvx % kgvy;
    kgvx = kgvy;
    kgvy = kgvtmp;
} while (kgvtmp != 0);
```
ist kgvy notgedrungen *immer 0,* weil du kgvy = kgvtmp machst und die Schleife durchläuft bis kgvtmp gleich 0 ist. 

Da du anschließend mit kgvy multiplizierst (also immer mit 0), ist es praktisch schon vorprogrammiert, dass deine Berechnung für xV und yV immer nur 0 liefern kann!
Versuch's vielleicht einfach mal so:

```
do {
    kgvtmp = kgvx % kgvy;
    if(kgvtmp == 0){
        break;
    }
    kgvx = kgvy;
    kgvy = kgvtmp;
} while (true);
```


----------



## Firemozzi (31. Mai 2010)

André Uhres hat gesagt.:


> Nach dieser Schleife:
> 
> ```
> do {
> ...



Ich werde es mir heute mal anschauen wenn ich daheim bin, danke schonmal. (aber klingt(ist!) logisch was du sagst)


----------



## Firemozzi (31. Mai 2010)

Super Geil, vielen Dank Andre, das hat mich schon extrem viel weiter gebracht!!

Der Ball geht manchmal mit perfekter Geschwindigkeit in die richtige Richtung!
aber leider nur, wenn x > 0 und y > 0, ansonsten bugt er wie ein Murmeltier mit Tollwut. der springt zum Teil plötzlich etwa 150 Pixel aufs mal, aber passt sonst schon sehr
Ich habe wieder etwas rumgeknobelt an meiner Engine:

```
if (stop==1){//Wenn der Ball stillsteht
					
					stop=0;
					if (x > mx){
						xkathete=x-mx;
						richtungx=1;
					}
					if (x < mx){
						xkathete=mx-x;
						richtungx=-1;
					}
					if (y > my){
						ykathete=y-my;
						richtungy=1;
					}
					if (y < my){
						ykathete=my-y;
						richtungy=-1;
					}

					 kgvx=x;
					 kgvy=y;
					 kgvxold=x;
					 kgvyold=y;
					 do {
						    kgvtmp = kgvx % kgvy;
						    if(kgvtmp == 0){
						        break;
						    }
						    kgvx = kgvy;
						    kgvy = kgvtmp;
						} while (true);
					 
					 if (xkathete > ykathete){
						 verhaeltnis=xkathete/ykathete;
						 verhaeltnis = Math.round(verhaeltnis);
		
					 xkathete =((kgvxold/kgvx)*kgvy);	
					 xV = (int)xkathete;
					 ykathete = xkathete*(int)verhaeltnis;
					 yV = (int)ykathete;
					 }
					 else
					 {
						 verhaeltnis=ykathete/xkathete;
						 verhaeltnis = Math.round(verhaeltnis);
					ykathete =((kgvxold/kgvx)*kgvy);
					
					 ykathete =((kgvxold/kgvx)*kgvy);	
					 yV = (int)ykathete;
					 xkathete = ykathete*(int)verhaeltnis;
					 xV = (int)xkathete;
					 
					 }
					 
					
						
						xV = xV * richtungx;
						yV = yV * richtungy;
				}
				
				stop = 0;
				 i = 0;
				 n = 1;
				 time = 10;
				 timme = 0;
				 testxvxy=1;
				 
			}
			
					}[/Java]

Wenn ihr nochmal einen Fehler sieht, wäre ich euch sehr dankbar, ich muss übermorgen fertig sein, aber so kann ich es eigentlich schon lassen, vielen Dank euch Leute ihr seid genjal
(Ich habe ihn schon studiert und angepasst, aber ich finde nichts)

Je besser, desto bessere Bewertung bekomme ich natürlich, aber, naja =)

Wie gesagt, wenn ihr noch ein Fehler findet wäre geil :)
Ihr kriegt auch Kekse und Kaffee :)

PS: Das soll nicht heissen, das ihr die ganze Arbeit für mich machen müsst... ich hab jetz 3 Stunden verbessert gerade, das Minigolf ist nicht wiederzuerkennen, hat nurnoch ein paar Bugs, und es lässt sich einbinden
```


----------



## Firemozzi (8. Nov 2013)

Nachtrag: 

Guten Tag Miteinander

Ich hätte es damals vielleicht eher mit dem Float versuchen sollen 
ich habe gerade herzlich über meine etwas unangebrachte Formulierung hier gelacht.

Vielen Dank für eure Hilfe damals, aber ich hatte eine 4 Gekriegt.

Liebe Grüsse, Firemozzi


----------

