# Kreis abfahren



## Movie85 (4. Dez 2009)

Hi Leutz

Ich habe eine simple Frage, eigendlich ganz einfach:
Ich habe einen Punkt, der alle 50tel Sekunden einfach neu gezeichnet wird, und aus vielen punkten wird dann eine Linie...
Vielleicht kennt ja einer von euch IPCourve, das ist ein Spiel, bei dem man einen Punkt steuern kann, der dann eine linie hinter sich her zieht. Ich weiß nicht genau wie ich es erklären soll, hier mal der code, mit dem ich den Punkt streuern kann:


```
if(stat=="rechts")     
      angle += radius*speed;
      else if(stat=="links")      
      angle -= radius*speed;  
     
      x += Math.cos(angle)*speed;
      y += Math.sin(angle)*speed;
     
      g.setColor(Color.green);
      g.fillOval(x-3,y-3,6, 6);
```

wenn man links drückt, dann wird angle um radius*speed vergrößert. Radius soll der Radius eines Kreises sein, an dem die linie sozusagen langfährt.
Durch die funktion soll dann die Bewegung ausgerechnet werden.
Eigendlich sollte sich, wenn man links die ganze zeit drückt, ein Kreis entstehen.
Leider tut sich das aber nicht, jedoch kann ich irgendwie nicht richtig steuern. Wenn ich nach links fahre(heißt: ich fahre vom bildschirm ausgesehen auf die linke seite, egal wie rum(hoch, runter)), dann passt alles, auf der rechten seite gehen jedoch nur horizontale oder 45°-Fahrten.

Rrechnet Java irgendwie anders mit Cos und sin? Die Funktion ist aus dem echten quellcode des spiels

Gruß,

Tom


----------



## javimka (4. Dez 2009)

du solltest Strings nicht mit == vergleichen. verwende dazu stat.equals("links"), bzw, stat.equals("rechts")


----------



## Movie85 (4. Dez 2009)

Hallo javimka,

danke für deine super schnelle Antwort
Das werde ich verbessern, leider löst das nicht das Problem 

Gruß,

Tom


----------



## javimka (4. Dez 2009)

Also am sin und cos liegt es sicher auch nicht, die werden schon richtig berechnet. Vielleicht hilft es, wenn du ein bisschen mehr Code zeigst, ich sehe in deinem Fragment keinen Fehler.


----------



## Movie85 (4. Dez 2009)

Ok, hier der gesamte Code:


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


class WindowClosingAdapter
extends WindowAdapter
{

 

   public void windowClosing(WindowEvent event)
   {
      event.getWindow().setVisible(false);
      event.getWindow().dispose();
      System.exit(0);
   }
}

public class courve
extends Frame
implements KeyListener, ActionListener
{

     boolean links = false;
     boolean rechts = false;
     boolean special = false;

     private Timer t;
     double radius = 1;
     double angle = 3.14;
     int speed = 2;

     
     int x = 100;
     int y = 100;
   
   String stat ="";


         

  
   public static void main(String[] args)
   {
      courve wnd = new courve();
     
     


   }

   public void actionPerformed(ActionEvent event) {
      repaint();
    }
    
    public void update ( Graphics g ) {
        paint(g);
    }

   public courve()
   {
      super("courve");

      addKeyListener(this);
      addWindowListener(new WindowClosingAdapter());
      setBackground(Color.black);
      setSize(600,600);
      setLocation(200,100);
      setVisible(true);
       t = new Timer(50, this);
      t.start();
      
   }

   public void paint(Graphics g)
   {
       stat = getAktion();
      if(stat=="rechts")     
      angle += radius*speed;
     else if(stat=="links")      
      angle -= radius*speed;  
     
      x += Math.cos(angle)*speed;
      y += Math.sin(angle)*speed;
     
      g.setColor(Color.green);
      g.fillOval(x-3,y-3,6, 6);

      g.setColor(Color.black);
      g.fillRect(250,250,300,300);
      g.setColor(Color.green);
      g.drawString("x = " + x, 300, 300);
      g.drawString("y = " + y, 300, 340);
      g.drawString("angle = " + angle, 300, 360); 
 

    }  


public String getAktion() {
		if (rechts) return "rechts";
		else if (links) return "links";
		else if (special) return "special";
		else return "";

}

public void keyPressed(KeyEvent keyEvent) {
       

        if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN)
            rechts = true;
        if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT)
            links = true;
        if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT)
            special = true;
            
          

}

public void keyReleased(KeyEvent keyEvent) {
      
        if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN)
            rechts = false;
        if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT)
            links = false;
        if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT)
            special = false;
           

}
public void keyTyped(KeyEvent keyEvent){

}

}
```


----------



## javimka (4. Dez 2009)

```
if (keyEvent.getKeyCode() == KeyEvent.  VK_DOWN  )
    rechts = true;
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT)
    links = true;
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT)
    special = true;
```

Wieso wird rechts true, wenn man die Pfeiltaste nach unten drückt?

Ich glaube, dein Programm tut schon, was du willst, nur viel schneller. Einmal kurz eine Taste angeschlagen, ändert sich dein Winkel massiv. So kriegst du keine schönen Kurven, sondern ein einziges Zickzack


----------



## Movie85 (4. Dez 2009)

Hi,
das mit dem Pfeil nach unten ist wegen der Steuerung so und stimmt so...
Wenn man nach links will, nach links drücken, wenn man nach rechts will nach unten drücken und special "Gadged" dann mit nach rechts drücken. Die Steuerung hat sich so eingebürgert...

http://movie85.mo.funpic.de/jes.jar

Hier kann man es ausprobieren. Innerhalb der linkenseite schaffe ich locker andere Winkel als 0 und 45°. Wenn man z.B. Links runterdrückt(hält) erkennt man es gut.

Danke,

Tom


----------



## javimka (4. Dez 2009)

Also bei mir sehen die Kurven genau gleich aus, ob ich sie nun links drehe, oder rechts. Was mich ein bisschen wundert ist, dass er immer nach oben links zieht. Wenn ich ständig "Links" drücke, sollte er doch einen Kreis machen. Stattdessen gibt es eine Spirale nach oben links O_O

//EDIT: Rätsel gelöst:
Deine Variabeln x und y sind Integer. Das heisst, es wird ständig abgerundet. Deswegen der Drall nach oben links. Du musst x und y als double definieren und dann mit Math.round runden um zu zeichnen.

```
int xx = (int)Math.round(x);
      int yy = (int)Math.round(y);
      g.setColor(Color.green);
      g.fillOval(xx-3,yy-3,6, 6);
```

//EDIT 2: Dein radius ist zu hoch. Verwende mal 0.1d, das sieht dann viel besser aus.


----------



## Movie85 (4. Dez 2009)

Genau das ist das Problem.
Versuch mal von links nach rechts zu fahren, und dort den winkel zu ändern(z.B. von links  oben nach rechts unten), da kommt immer nur ein 45° Winkel diagonal... Ich finde den Fehler einfach nicht, ist ja auch so ein einfaches stück Code 
Vielleicht irgendwelche Berechnungs Probleme, Zeitprobleme?

Gruß

//Edit:'

Danke!! So kann ich schon viel besser lenken, aber trotzdem bekomme ich keinen Kreis hin 
Aber das ist an sich schonmal ein ansatz!

Gruß


----------



## javimka (4. Dez 2009)

Ich glaube, dein radius ist zu gross und x,y sollten double sein (falls du meine EDIT oben nicht gesehen hast). Bei mir siehts jetzt gut aus.


----------



## Movie85 (4. Dez 2009)

Hi, 

das mit double x, y hatte ich vergessen!!! Super!!! Danke :applaus::applaus::applaus:

Jetzt klappts! Vielen Dank, wie kann ich dir danken?
Ich dachte irgendwie es gibt keine Krummen koordinaten, deswegen int 

Gruß


----------



## javimka (4. Dez 2009)

Die vielen Smilies der Zufriedenheit, sind Dank genug 
Wenn das Spiel fertig ist, kannst du es ja in diesem Forum vorstellen, da freuen wir uns


----------



## Movie85 (4. Dez 2009)

Klaro, werd ich machen 

Noch einen kleinen Gedankenanschubs: 
Nach was muss ich für Kollisionserkennung suchen, in Bezug auf spiele in Java? Also hier Kollision zwischen Linie und Linie (wie bei Snake)

Grüßle,

Tom


----------



## javimka (4. Dez 2009)

Das ist eine schwierige Frage, habe das auch noch nie gemacht. Du könntest natürlich die Pixel analysieren und wenn das bereits grün ist, war es besetzt und es kommt zur Kollision. Bei einer 6 Pixel dicken Linie und geringer Geschwindigkeit, wie bei dir, würde das gehen. Bei höheren Geschwindigkeiten oder dünneren Linien, bestünde die Gefahr, dass sich der Punkt in einem Schritt so weit bewegt, dass er eine Linie gerade überspringt und du nicht bemerkst, dass es eigentlich eine Kollision gegeben haben müsste.
Wenn du nicht die Farben analysiren willst, weil die vielleicht noch komplexer werden, könntest du auch ein boolean Array einführen und dort die Werte auf true setzen, die begangen worden sind. Bei kleinen Feldern ist das kein Problem. Ein 1000x1000 Feld bräuchte 1000*1000 Bytes, also ein Megabyte Speicherplatz. Das geht in der Regel in Ordnung.


----------



## Marco13 (4. Dez 2009)

... wobei sowas wie Line2D (Java 2 Platform SE v1.4.2) dann aber doch oft einfacher und Eleganter ist...


----------



## javimka (5. Dez 2009)

... wobei man dann aber auch das Problem hat, dass Linien unendlich nahe beieinander parallel verlaufen könnten und keine Kollision auslösen würden, obwohl sich die 6-Pixel-dicke Strich touchieren und man bei einem 1000x1000 Feld unter Umständen sehr sehr viele Linien auf Kollision überprüfen muss ... (jetzt du wieder  )


----------



## Marco13 (5. Dez 2009)

Eigentlich muss man doch immer nur die "spitze" der Line auf Überschneidungen/Kollisionen mit "ihrem eigenen Hinterteil" testen? (Und DAS ginge mit der Punkt-Linie-Abstandsfunktion, die auch in Line2D steckt) ????:L


----------



## javimka (5. Dez 2009)

Und dann aufpassen, dass die Distanz zu den gerade erst gezeichneten Linien nicht auch zur Kollision führen. So würds wahrscheinlich auch gehen, ja. Movie85 kann uns dann sagen, wie er es gemach hat


----------



## Movie85 (5. Dez 2009)

Hi,
das sind gute Ideen! Ich finde es aber trotzdem sehr Problematisch...
Ich habe es jetzt einmal mit einem x und y Array versucht, jedoch stimmen die Punkte ja nicht immer mit der Linie überein, d.h. die Linie hat ja auch ihre Dicke! Ich werd mal versuchen mit sin und cos die dicke noch mit einzubeziehen, na das wird lustig.

Eine andere möglichkeit die ich noch probieren werde ist die Pixelfarbe auszulesen, wenn sie nicht schwarz ist dann hat man eine linie berührt.

Das mit Linecollision verstehe ich noch nicht so ganz. Hast du vielleicht ein Beispiel?

Gruß,
Tom


----------



## Marco13 (5. Dez 2009)

Pseudocode, ganz grob aus dem Kopf hingeschrieben:

```
private List<Line2D> lines = ...

private void macheEinenSchritt()
{
   int x0 = alte x-position
   int y0 = alte y-position

   int x1 = x0 + speed * ... // Neue Position ausrechnen
   int y1 = y0 + speed * ... // Neue Position ausrechnen

   // Die Linie, die den letzten Schritt beschreibt
   Line2D newLine = new Line2D(x0,y0,x1,y1);

   // Schauen, ob beim letzten Schritt eine linie überschritten wurde
   for (Line2D oldLine : lines)
   {
        if (newLine.intersects(oldLine)) esGabEineKollision();
   }
    
   // Ggf. noch schauen, ob man nach dem neuen Schritt "nah" an einer alten Linie ist
   for (Line2D oldLine : lines)
   {
        if (oldLine.distanceTo(x1,y1) < 3) esGabEineKollision();
   }

   lines.add(newLine);

}
```


----------



## Movie85 (5. Dez 2009)

Vielen Dank für das stückchen Code, das bring mich echt weiter! Ich hab ein bisschen rumprobiert und ein bisschen herumgelesen, und habe festgestellt, dass es Probleme gibt wenn ich Kurfen fahre, da dann der abstand oft zu klein wird zwischen dem xalt und xneu etc.

Ich werde noch ein bisschen rumprobieren, ich denke ich kann es so schaffen!

Gruß


----------

