# Snake-BlueJ Bewegung



## Thommi (4. Jul 2012)

Hi
Ich versuch schon seit einiger zeit ein Snake-Spiel zu programmieren, bin allerdings ein ziemlicher Anfänger und hab da so meine Probleme mit der Bewegung der Schlange;#

  Vorneweg noch: das ganze ist mit BlueJ programmiert, einer vereinfachten Programmierumgebung für Schüler falls das wichtig ist. 

Ich hab mir gedacht dass es am einfachsten wäre, wenn ich jedes Segment der Schlange einfach auf den Platz des Vorgängers aufrutschen lasse, und so eigentlich immer nur dem vordersten teil der Schlange koordinaten gegeben werden müssen, der Rest "rutscht" ja nach 
Am besten poste ich einfach mal meine 3 Hauptklassen:


```
import java.util.Random;

public class SPIEL implements ITuWas, ITastatur
{   
    private Rechteck Spielfeld;
    private KÖRPER Körper;
    private Taste Pause;
    private Taste Wiederaufnahme;
    private Taste Neustart;
    private Taktgeber takt,takt1,takt2,takt3;
    private int Level;
    private int z;
    private int a,b;
    Bild r;
    SEGMENT ort = new SEGMENT();
    Tastatur t;
    
    public SPIEL()
    {
        Zeichnung.setzeFenstergroesse(1200,1200);
        r = new Bild(300,1, 400, 400 , "snake2.jpg"); 
        r = new Bild(20, 250, 400, 400 , "snake.jpg"); 
        Spielfeld = new Rechteck (300,250,600,600);
        Körper = new KÖRPER();
        a=190;
        b=210;
        
        Level= 400;
        
        takt = new Taktgeber();
        definiereTakt(takt,10);
        takt1 = new Taktgeber();
        definiereTakt(takt1,20);
        takt2 = new Taktgeber();
        definiereTakt(takt2,30);
        takt3 = new Taktgeber();
        definiereTakt(takt3,40);
        
        t= new Tastatur();
        t.setzeLink(this);
        t.meldeAnTaste('w', "up");
        t.meldeAnTaste('a', "left");
        t.meldeAnTaste('s', "down");
        t.meldeAnTaste('d', "right");
        t.meldeAnTaste('+', "lvlup");
        t.meldeAnTaste('-', "lvldown");
        
        StartSchlange();
        z=0;
        
        Pause = new Taste ("Pause", 1000, 400, 150,50);
        Pause.setzeLink(this);
        Pause.setzeID(1000);

        
        Neustart = new Taste ("Neustart", 1000, 500, 150,50);
        Neustart.setzeLink(this);
        Neustart.setzeID(50);
        
        Wiederaufnahme = new Taste ("Fortfahren", 1000, 600, 150,50);
        Wiederaufnahme.setzeLink(this);
        Wiederaufnahme.setzeID(90);
        
         
    }
    
     private void definiereTakt(Taktgeber t, int id)
    {
        t.setzteZeitZwischenAktionen(Level);
        t.setzeLink(this);
        t.setzeID(id);
    }
    
    public void tastenAktion(String r)
       {
        if(r.equals("up"))
        {
           Up();
           z=1;
        }
        if(r.equals("down"))
        {
            Down();
            z=2;
        }
        if(r.equals("left"))
        {
            Left();
            z=3;
        }
        if(r.equals("right"))
        {
            Right();
            z=4;
        }
        if(r.equals("lvlup"))
        {
            if(Level>100)
            {
                Level=Level-100;
            }
        }
        if(r.equals("lvldown"))
        {
            if(Level<1000)
            {
                Level=Level+100;
            }
        }
       }
    
    public void tuWas(int ID)
    {
        if(ID == 10) 
        {
            ticke();
        }
        else if(ID == 20) 
        {
           ticke1();
        }
        else if(ID == 30)
        {
            ticke2();
        }
        else if(ID == 40)
        {
            ticke3();
        }
        else if(ID == 1000)
        {
            Stoppe();
        }
        else if(ID == 50)
        {
            //Neustart();
        }
        else if(ID == 60)
        {
            //SchnickSchnackMethode();
        }
        else if(ID == 70)
        {
           //SchnickSchnackMethode();
        }
        else if(ID == 80)
        {
            //SchnickSchnackMethode();
        }
        else if(ID == 90)
        {
            //Fortfahren();
        }
    }
    
         private void ticke()
       {
         Körper.bewegeO();
         z=1;
       }
       private void ticke1()
       {
         Körper.bewegeU();
         z=2;
       }
       private void ticke2()
       {
         Körper.bewegeL();
         z=3;
       }
       private void ticke3()
       {
         Körper.bewegeR();
         z=4;
       }
    
    public void Up ()
    {
        if(z==1 || z==2 )
       {
       }
        else
       {
            takt1.stop();
            takt2.stop();
            takt3.stop();
            takt.endlos();
       }
    }
    public void Down ()
    {
        if(z==2 || z==1)
       {
       }
        else
      {
            takt.stop();
            takt2.stop();
            takt3.stop();
            takt1.endlos();
       }
    }
    public void Left ()
    {
        
        if(z==3 || z==4)
        {
        }
        else
       {
        takt1.stop();
        takt3.stop();
        takt.stop();
        takt2.endlos();
       }
    }
    
    public void Right ()
    {
       if(z==4 || z==3)
        {
        }
       else
       {takt1.stop();
        takt2.stop();
        takt.stop();
        takt3.endlos();
       }
    }
    
    public void StartSchlange()
    {
        
          for(int i=0; i<5; i++)
         {
             SEGMENT n = new SEGMENT(500-i*10,500,Körper);
             Körper.fuegeSegmentHinzu(n);
        }
    }
    
    public void Wachse ()
    {
            SEGMENT n = new SEGMENT(a,b,Körper);
            Körper.fuegeSegmentHinzu(n);
     }
    
    public void Stoppe()
    {
            takt.stop();
            takt1.stop();
            takt2.stop();
            takt3.stop();
    }
     

}
```

Das ist so ziemlich die Hauptklasse, in dem ich dem ersten Element die Bewegung zu Weise, hier gibt es eigentlich noch keine Probleme;


```
public class KÖRPER
{
    public SEGMENT[] s;
    private int anzahl;
    
    
    public KÖRPER ()
    {
        anzahl = 0;
        s = new SEGMENT[1000];
    
    }
    
    public void fuegeSegmentHinzu (SEGMENT elementNeu)
    {
        if (anzahl < 1000)
        {
         s[anzahl] = elementNeu;
         anzahl = anzahl + 1;
        }
    }
    
    public void bewegeO()
    {
        s[0].bewegeOben();
        //for(int i=0;i<anzahl;i++)
        //{
        //    s[i+1].Krieche(i*2,1+i*2,i+1);
        //}
       s[1].Krieche(0,1,1);
    }
    
    public void bewegeU( )
    {
        s[0].bewegeUnten();
        for(int i=0;i<anzahl;i++)
        {
            s[i+1].Krieche(i*2,1+i*2,i+1);
        }
    }
    
    public void bewegeL( )
    {
        s[0].bewegeLinks();
        for(int i=0;i<anzahl;i++)
        {
            s[i+1].Krieche(i*2,1+i*2,i+1);
        }
    }
    
    public void bewegeR( )
    {
        s[0].bewegeRechts();
        for(int i=0;i<anzahl;i++)
        {
            s[i+1].Krieche(i*2,1+i*2,i+1);
        }
    }
    }
```


```
import java.util.Random;
public class SEGMENT 
{
    private Quadrat q;
    private int x;
    private int y;
    private int[] ort;
    //anzahl der koordinaten
    int b;

      
    public SEGMENT()
    {
        ort=new int[100000];
    
    }
   
    public SEGMENT(int xStart, int yStart, KÖRPER r)
    {
        x= xStart;
        y= yStart;
        q=new Quadrat(x, y, 10);
        
        b=0;
      
    }
    
    public void bewegeOben( )
    {
         
        if(x<600 && y<600 && x>-1 && y>-1) 
        {
         y = y - 10 ;
         q.setzePosition((int)x, (int)y);
            ort[0]=x;
          ort[1]=y+10;
         
        }
    }   
    public void bewegeUnten( )
    {
         if(x<600 && y<600 && x>-1 && y>-1) 
        {
         y = y +10  ;
         q.setzePosition((int)x, (int)y);
          ort[0]=x;
          ort[1]=y-10;
       }
      
    }   
    public void bewegeLinks( )
    {
         if(x<600 && y<600 && x>-1 && y>-1) 
       {
        x = x - 10 ;
        q.setzePosition((int)x, (int)y);
         ort[0]=x+10;
          ort[1]=y;
       }
    }   
    public void bewegeRechts( )
    {
        if(x<600 && y<600 && x>-1 && y>-1) 
       {
        x = x + 10 ;
        q.setzePosition((int)x, (int)y);
        ort[0]=x-10;
          ort[1]=y;
       }
    }  
    
     public void Krieche(int n1, int n2, int p)
     {
        q.setzePosition(ort[n1],ort[n2]);
        ort[n1]=ort[p*2];
        ort[n2]=ort[p*2+1];
     }
    
     }
```

Das ist nun die wichtigste Klasse für mein Problem, hier werden den nachfolgenden Segmenten die Positionen zugewiesen


Starte ich nun das Spiel bekomm ich eine Menge Java.lang.NullpointerExceptions, allerdings hab ich keine Ahnung wieso diese auftreten.

Nur mal als Beispiel:
  Exception in thread "Thread-11" java.lang.NullPointerException
	at SEGMENT.bewegeOben(SEGMENT.java:36)
	at K�RPER.bewegeO(K�RPER.java:25)
	at SPIEL.ticke(SPIEL.java:159)
	at SPIEL.tuWas(SPIEL.java:117)
	at Taktgeber$2.run(Taktgeber.java:69)
	at java.lang.Thread.run(Thread.java:722)


Ich hoffe ihr könnt mir helfen, ich  häng auch nochmal das gesamte Projekt als Anhang dran, falls jemand die Zeit findet sich das mal anzuschauen.

Danke schonmal


----------



## transdenzentral (4. Jul 2012)

```
private int[] ort;
```

wird nicht initialisiert. Das Array ist "null".

Der entsprechende Konstruktor von Segment wird nie aufgerufen.



```
public void bewegeU( )
public void bewegeO( )
public void bewegeR( )
public void bewegeL( )
```

Hier gehen deine Schleifen eins zu lang, wenn Du bei 0 anfängst mit zählen...


----------



## Thommi (4. Jul 2012)

Ok den Konstruktor von Segment hab ich jetzt einfach in den Konstruktor von Spiel reingepackt.

Zu den Schleifen: 

```
for(int i=0;i<(anzahl-1);i++)
        {
            s[i+1].Krieche(i*2,1+i*2,i+1);
        }
```

so ist`s besser oder?

Dann sinds wohl schonmal 2 fehler weniger 

aber leider kommen immer noch die selben fehlermeldungen


----------



## transdenzentral (4. Jul 2012)

Poste doch einfach mal die ganze Fehlermeldung 




> Ok den Konstruktor von Segment hab ich jetzt einfach in den Konstruktor von Spiel reingepackt.



Das ist wohl nicht unbedingt zielführend. Initialisiere dein Array doch einfach in dem Konstruktor, den Du sowieso aufrufst:


```
public SEGMENT(int xStart, int yStart, KÖRPER r)
    {
        x= xStart;
        y= yStart;
        q=new Quadrat(x, y, 10);
//Hier...
        ort=new int[100000];
        b=0;
      
    }
```

Dann sollten eigentlich auch keine NPE mehr fliegen... - ich hab das Grade testweise ausprobiert...


----------



## Thommi (4. Jul 2012)

Aber dieser Konstruktor wird ja jedesmal aufgerufen wenn ich ein neues Segment hinzufüge, wir dann nicht auch jedes mal wieder ein Array erstellt?

Naja ich habs jetzt mal ausprobiert und ...

... es gibt wirklich keine NPE mehr  danke 

das einzige Problem ist jetzt noch dass alle segment anscheinend auf(0|0) springen, woran dass auch liegen mag

aber das war schon mal eine große hilfe 

----> Bin jetzt zu dem Schluss gekommen dass die Segmente genau wegen dem Problem mit dem array auf (0|0) springen, weil jedes Segment jetzt sein eigenes Array hat und die Koordinatenwerte ja nur in das erste Array eingetragen werden. :/ was tun?


----------



## Thommi (5. Jul 2012)

Kann mir irgendjemand vielleicht noch eine Tipp geben wie ich das hinbekomme, das es nicht jedesmla wenn ich ein neues Segment erstell ein neues Array erstellt wird und ich so die Koordinaten nicht richtig aufrufen kann?


----------



## Kevin94 (6. Jul 2012)

Ich würde sagen, das das Array static sein müsste.

Um mal eine Anmerkung zum Algorithmus zu machen: Ich würde es so schreiben, das immer das letzte Elemenent nach vorne an die Spitze versetzt wird, bzw. an die Zweite Stelle wenn du einen Kopf hättest. Da spart man sich viele Verschiebungen.


----------



## Thommi (7. Jul 2012)

Danke für den Tip  Hab es jetzt wirklich so gelöst dass immer das letzte nach vorne "springt".
Jetzt funktioniert soweit alles


----------

