# Koordinieren und Essen von Snake - Spiel



## Feeder (17. Jun 2017)

Hey, ich versuche das Spielo Snake nachzuprogrammieren, leider scheinen meine Algorithmen nicht zu funktionieren.

Wenn meine Schlange isst,verlängert sich die Liste von Positionen um die letztere Position, so dass im Nächsten Schritt sich die Schlange neu "aufrollt"...

```
ArrayList<Vector> bodys;
public void addBody() { //wenn sie isst...
        bodys.add(bodys.get(bodys.size()-1));

    }
```


Dannach stept sie wieder

```
ArrayList<Vector> bodys;
public void step(int time) {
        for(int i = 1; bodys.size()-i > 0; ++i ) {
            bodys.get(bodys.size()-i).setLocation(bodys.get(bodys.size()-i-1));
            System.out.println((bodys.size()-i) + " to " + (bodys.size()-i-1) );
        }
        //neue position für den Kopf
        bodys.get(0).add(speed.multiply(time));//speed.multiply time returned neuen Vektor...
```


    }


----------



## mrBrown (17. Jun 2017)

Du fügst den letzten Vektor noch Mals hinzu, in der Liste ist also zwei mal der selbe. Veränderst du einen von beide, veränderst du auch den anderen.


----------



## Feeder (17. Jun 2017)

mrBrown hat gesagt.:


> Du fügst den letzten Vektor noch Mals hinzu, in der Liste ist also zwei mal der selbe. Veränderst du einen von beide, veränderst du auch den anderen.



Entschuldigung, Ich weiß nicht genau, wie du das meinst.
Der 0te Vektor wird einmal hinzugefügt...


----------



## mrBrown (17. Jun 2017)

Hiermit fügst du den jeweils letzten Vektor nochmal der Liste hinzu: `bodys.add(bodys.get(bodys.size()-1));`.
Der hinzugefügte Vektor ist der selbe, wie der schon vorhandenen, er liegt jetzt nur doppelt in der Liste. Da es eben der selbe ist, veränderst immer beide, wenn du einen verändern willst.
Du müsstest eine Kopie des vorhandenen hinzufügen, ohne deine Vector-Klasse zu kennen, kann man da aber nicht mehr zu sagen


----------



## Feeder (17. Jun 2017)

mrBrown hat gesagt.:


> Hiermit fügst du den jeweils letzten Vektor nochmal der Liste hinzu: `bodys.add(bodys.get(bodys.size()-1));`.
> Der hinzugefügte Vektor ist der selbe, wie der schon vorhandenen, er liegt jetzt nur doppelt in der Liste. Da es eben der selbe ist, veränderst immer beide, wenn du einen verändern willst.
> Du müsstest eine Kopie des vorhandenen hinzufügen, ohne deine Vector-Klasse zu kennen, kann man da aber nicht mehr zu sagen


ikr 

VIELEN DANK, ich probier es später aus...!!!


----------



## Feeder (18. Jun 2017)

Habe jetzt wie folgt abgeändert:


```
public void addBody() { //wenn sie isst... 
        Vector v = new Vector(bodys.get(bodys.size()-1).getX(), bodys.get(bodys.size()-1).getY());
        bodys.add(v);

    }
    public void step(int time) {
        for(int i = 1; bodys.size()-i > 0; ++i ) {
            bodys.get(bodys.size()-i).setLocation(bodys.get(bodys.size()-i-1));
            System.out.println((bodys.size()-i) + " to " + (bodys.size()-i-1) );
        }
        //neue position für den Kopf
        bodys.get(0).add(speed.multiply(time));
     
    }

    public void display(Graphics g) {
        g.setColor(Color.cyan);
        for(int i = 0; i < bodys.size(); ++i) {
        g.fillRect((int)Math.round(bodys.get(i).getX()), (int)Math.round(bodys.get(i).getY()), 20, 20);
        }
    }
```

Klappt aber immer noch nicht


----------



## mrBrown (18. Jun 2017)

Und *was* klappt nicht?


----------



## Feeder (18. Jun 2017)

mrBrown hat gesagt.:


> Und *was* klappt nicht?



War gerade am probieren, habe den Code noch etwas abgeändert:


```
public void addBody() { //wenn sie isst...
        Vector v = new Vector(bodys.get(bodys.size()-1).getX(), bodys.get(bodys.size()-1).getY());
        bodys.add(v);

    }
public void step(int time) {
        for(int i = 1; bodys.size()-i > 0; ++i ) {
            Vector v = new Vector(bodys.get(bodys.size()-1-i).getX(), bodys.get(bodys.size()-1-i).getY());
            bodys.set(bodys.size()-i, v);
        }
        double x = bodys.get(0).getX() + speed.getX()*time;
        double y = bodys.get(0).getY() + speed.getY()*time;
        Vector v = new Vector(x, y);
        bodys.set(0, v);

   
    }

public void display(Graphics g) {
        g.setColor(Color.cyan);
        for(int i = 0; i < bodys.size(); ++i) {
        g.fillRect((int)Math.round(bodys.get(i).getX()), (int)Math.round(bodys.get(i).getY()), 20, 20);
        }
    }
```

Er zeigt stets nur ein Körperteil an, es existieren aber mehrere...


----------



## mrBrown (18. Jun 2017)

Zeigst du sie denn auch bei jeder Veränderung neu an?


----------



## Feeder (19. Jun 2017)

Eigentlich schon...


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SnakeGame {
    JFrame frame;
    GamePanel panel;
    JLabel label;
    Snake s;
    Food f;
    long lasttime;
    public SnakeGame() {
        init();
        while(true) {
            calculate();
            repaint();
           
        }
    }

    private void repaint() {
        label.repaint();
        panel.repaint();
        frame.repaint();
       
    }

    private void calculate() {
        long before = System.currentTimeMillis();
        int delta = (int) (System.currentTimeMillis() - lasttime);
        s.step(delta);
        lasttime = before;
        if(f.isEaten(s)) {
            s.addBody();
            f.step();

        }

    }

    private void init() {
        s = new Snake(new Vector(50, 50));
        f = new  Food();
        lasttime = System.currentTimeMillis();
        frame = new JFrame();
        frame.setBounds(0,0,1000,1000);
        frame.setTitle("Snake");
        frame.setVisible(true);
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBackground(Color.BLACK);
        frame.addComponentListener(new ComponentListener() {
           
            @Override
            public void componentShown(ComponentEvent e) {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            public void componentResized(ComponentEvent e) {
                label.setBounds(0, frame.getHeight()-65, 100, 20);

               
            }
           
            @Override
            public void componentMoved(ComponentEvent e) {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            public void componentHidden(ComponentEvent e) {
                // TODO Auto-generated method stub
               
            }
        });
        panel = new GamePanel();
        panel.setBounds(0, 0, 1000, 1000);
        panel.setVisible(true);
        panel.setLayout(null);
        label = new JLabel();
        label.setBounds(0, frame.getHeight()-65, 250, 20);
        label.setBackground(Color.GREEN);
        label.setForeground(Color.WHITE);
        label.setText("Running...");
        label.setOpaque(false);
        panel.add(label);
        frame.add(panel);
        frame.addKeyListener(s);
   
       
   
       
    }
    private class GamePanel extends JPanel {
        public void paintComponent(Graphics g) {
            f.display(g);
            s.display(g);
           
        }
    }
}


import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

public class Snake implements KeyListener{
    ArrayList<Vector> bodys;
    Vector speed;
    public Snake(Vector pos) {
        bodys = new ArrayList<Vector>();
        bodys.add(pos);
        speed = new Vector(0.1,0);
    }
    public void display(Graphics g) {
        g.setColor(Color.cyan);
        for(int i = 0; i < bodys.size(); ++i) {
        g.fillRect((int)Math.round(bodys.get(i).getX()), (int)Math.round(bodys.get(i).getY()), 20, 20);
        }
    }
    public void step(int time) {
        for(int i = 1; bodys.size()-i > 0; ++i ) {
            Vector v = new Vector(bodys.get(bodys.size()-1-i).getX(), bodys.get(bodys.size()-1-i).getY());
            bodys.set(bodys.size()-i, v);
        }
        double x = bodys.get(0).getX() + speed.getX()*time;
        double y = bodys.get(0).getY() + speed.getY()*time;
        Vector v = new Vector(x, y);
        bodys.set(0, v);

      
    }
    @Override
    public void keyPressed(KeyEvent e) {
        int i = e.getKeyCode();
        if(i == KeyEvent.VK_1) {
            if(speed.getX() == 0) {
                speed.setX(0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_2) {
            if(speed.getY() == 0) {
                speed.setY(0.1);
                speed.setX(0);
            }
        }
        if(i == KeyEvent.VK_3) {
            if(speed.getX() == 0) {
                speed.setX(-0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_4) {
            if(speed.getY() == 0) {
                speed.setY(-0.1);
                speed.setX(0);
            }
        }
    }
    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
      
    }
    @Override
    public void keyTyped(KeyEvent e) {
        int i = e.getKeyCode();
        if(i == KeyEvent.VK_1) {
            if(speed.getX() == 0) {
                speed.setX(0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_2) {
            if(speed.getY() == 0) {
                speed.setY(0.1);
                speed.setX(0);
            }
        }
        if(i == KeyEvent.VK_3) {
            if(speed.getX() == 0) {
                speed.setX(-0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_4) {
            if(speed.getY() == 0) {
                speed.setY(-0.1);
                speed.setX(0);
            }
        }
      
    }
    public void addBody() {
        Vector v = new Vector(bodys.get(bodys.size()-1).getX(), bodys.get(bodys.size()-1).getY());
        bodys.add(v);

    }
}
```


----------



## mrBrown (19. Jun 2017)

Der Code ist leider nicht ausführbar.
Spontan: Entweder bewegst du die so schnell, dass sie direkt aus'm Bild ist, oder du rundest irgendwo, sodass der Kopf auf der Stelle steht.


----------



## Feeder (19. Jun 2017)

Der Code ist nicht vollständig.
Ich gebe mal den vorständigen Code:


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SnakeGame {
    JFrame frame;
    GamePanel panel;
    JLabel label;
    Snake s;
    Food f;
    long lasttime;
    public SnakeGame() {
        init();
        while(true) {
            calculate();
            repaint();
           
        }
    }

    private void repaint() {
        label.repaint();
        panel.repaint();
        frame.repaint();
       
    }

    private void calculate() {
        long before = System.currentTimeMillis();
        int delta = (int) (System.currentTimeMillis() - lasttime);
        s.step(delta);
        lasttime = before;
        if(f.isEaten(s)) {
            s.addBody();
            f.step();

        }

    }

    private void init() {
        s = new Snake(new Vector(50, 50));
        f = new  Food();
        lasttime = System.currentTimeMillis();
        frame = new JFrame();
        frame.setBounds(0,0,1000,1000);
        frame.setTitle("Snake");
        frame.setVisible(true);
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBackground(Color.BLACK);
        frame.addComponentListener(new ComponentListener() {
           
            @Override
            public void componentShown(ComponentEvent e) {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            public void componentResized(ComponentEvent e) {
                label.setBounds(0, frame.getHeight()-65, 100, 20);

               
            }
           
            @Override
            public void componentMoved(ComponentEvent e) {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            public void componentHidden(ComponentEvent e) {
                // TODO Auto-generated method stub
               
            }
        });
        panel = new GamePanel();
        panel.setBounds(0, 0, 1000, 1000);
        panel.setVisible(true);
        panel.setLayout(null);
        label = new JLabel();
        label.setBounds(0, frame.getHeight()-65, 250, 20);
        label.setBackground(Color.GREEN);
        label.setForeground(Color.WHITE);
        label.setText("Running...");
        label.setOpaque(false);
        panel.add(label);
        frame.add(panel);
        frame.addKeyListener(s);
   
       
   
       
    }
    private class GamePanel extends JPanel {
        public void paintComponent(Graphics g) {
            f.display(g);
            s.display(g);
           
        }
    }
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

public class Snake implements KeyListener{
    ArrayList<Vector> bodys;
    Vector speed;
    public Snake(Vector pos) {
        bodys = new ArrayList<Vector>();
        bodys.add(pos);
        speed = new Vector(0.1,0);
    }
    public void display(Graphics g) {
        g.setColor(Color.cyan);
        for(int i = 0; i < bodys.size(); ++i) {
        g.fillRect((int)Math.round(bodys.get(i).getX()), (int)Math.round(bodys.get(i).getY()), 20, 20);
        }
    }
    public void step(int time) {
        for(int i = 1; bodys.size()-i > 0; ++i ) {
            Vector v = new Vector(bodys.get(bodys.size()-1-i).getX(), bodys.get(bodys.size()-1-i).getY());
            bodys.set(bodys.size()-i, v);
        }
        double x = bodys.get(0).getX() + speed.getX()*time;
        double y = bodys.get(0).getY() + speed.getY()*time;
        Vector v = new Vector(x, y);
        bodys.set(0, v);

       
    }
    @Override
    public void keyPressed(KeyEvent e) {
        int i = e.getKeyCode();
        if(i == KeyEvent.VK_1) {
            if(speed.getX() == 0) {
                speed.setX(0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_2) {
            if(speed.getY() == 0) {
                speed.setY(0.1);
                speed.setX(0);
            }
        }
        if(i == KeyEvent.VK_3) {
            if(speed.getX() == 0) {
                speed.setX(-0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_4) {
            if(speed.getY() == 0) {
                speed.setY(-0.1);
                speed.setX(0);
            }
        }
    }
    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
       
    }
    @Override
    public void keyTyped(KeyEvent e) {
        int i = e.getKeyCode();
        if(i == KeyEvent.VK_1) {
            if(speed.getX() == 0) {
                speed.setX(0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_2) {
            if(speed.getY() == 0) {
                speed.setY(0.1);
                speed.setX(0);
            }
        }
        if(i == KeyEvent.VK_3) {
            if(speed.getX() == 0) {
                speed.setX(-0.1);
                speed.setY(0);
            }
        }
        if(i == KeyEvent.VK_4) {
            if(speed.getY() == 0) {
                speed.setY(-0.1);
                speed.setX(0);
            }
        }
       
    }
    public void addBody() {
        Vector v = new Vector(bodys.get(bodys.size()-1).getX(), bodys.get(bodys.size()-1).getY());
        bodys.add(v);

    }
}
import java.awt.Color;
import java.awt.Graphics;

public class Food {
    int x,y;
    public Food() {
        x = 20;
        y = 300;
    }
    public void display(Graphics g) {
        g.setColor(Color.GREEN);
        g.fillOval(x, y, 20, 20);
    }
    public boolean isEaten(Snake s) {
        if(this.x < s.bodys.get(0).x && this.x + 20 > s.bodys.get(0).x) {
            if(this.y < s.bodys.get(0).y && this.y + 20 > s.bodys.get(0).y) {
                return true;
            }
        }
        if(this.x < s.bodys.get(0).x+20 && this.x + 20 > s.bodys.get(0).x+20) {
            if(this.y < s.bodys.get(0).y+20 && this.y + 20 > s.bodys.get(0).y+20) {
                return true;
            }
        }
        return false;
    }
    public void step() {
        x = (int) Math.round(500*Math.random());
        y = (int) Math.round(500*Math.random());
       
    }
}


public class Vector {
    double x,y;
    public Vector(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }

    public double getX() {
        // TODO Auto-generated method stub
        return x;
    }

    public double getY() {
        // TODO Auto-generated method stub
        return y;
    }

    public void setLocation(double x, double y) {
        this.x = x;
        this.y = y;
       
    }
    public void rotate(double angle) {
            double rx = (this.x * Math.cos(angle)) - (this.y * Math.sin(angle));
            double ry = (this.x * Math.sin(angle)) + (this.y * Math.cos(angle));
            x = rx;
            y = ry;   
    }
    public void add(Vector v) {
        y = this.y + v.getY();
        x = this.x + v.getX();
   
    }
    public void sub(Vector v) {
        y = this.y - v.getY();
        x = this.x - v.getX();
   
    }
    public void multiply(double d) {
        x = x*d;
        y = y*d;
    }
    public void div(double d) {
        x = x/d;
        y = y/d;
    }
    public double mag() {
          return Math.pow((x*x + y*y), 0.5);
        }
    public void normalize() {
        double m = mag();
        div(m);
    }
   
   

}


public class Vector {
    double x,y;
    public Vector(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }

    public double getX() {
        // TODO Auto-generated method stub
        return x;
    }

    public double getY() {
        // TODO Auto-generated method stub
        return y;
    }

    public void setLocation(double x, double y) {
        this.x = x;
        this.y = y;
       
    }
    public void rotate(double angle) {
           double rx = (this.x * Math.cos(angle)) - (this.y * Math.sin(angle));
           double ry = (this.x * Math.sin(angle)) + (this.y * Math.cos(angle));
           x = rx;
           y = ry;   
    }
    public void add(Vector v) {
        y = this.y + v.getY();
        x = this.x + v.getX();
   
    }
    public void sub(Vector v) {
        y = this.y - v.getY();
        x = this.x - v.getX();
   
    }
    public void multiply(double d) {
        x = x*d;
        y = y*d;
    }
    public void div(double d) {
        x = x/d;
        y = y/d;
    }
    public double mag() {
         return Math.pow((x*x + y*y), 0.5);
        }
    public void normalize() {
        double m = mag();
        div(m);
    }
   
   

}

public class Game {

    public static void main(String[] args) {
        new SnakeGame();

    }

}
```


----------



## Feeder (19. Jun 2017)

mrBrown hat gesagt.:


> Der Code ist leider nicht ausführbar.
> Spontan: Entweder bewegst du die so schnell, dass sie direkt aus'm Bild ist, oder du rundest irgendwo, sodass der Kopf auf der Stelle steht.


Nein, die Körperteile werden nicht hinzu addiert, das erste ist ganz normal


----------



## Meniskusschaden (19. Jun 2017)

Ich glaube die Zeitpunkte zwischen zwei Kopfpositions-Berechnungen liegen so dicht beieinander, dass sich die neue Position kaum oder gar nicht von der vorherigen unterscheidet. Dadurch überlappt der Kopf mit dem Folgeelement (also der vorherigen Kopfposition) teilweise oder vollständig. Ich habe testweise mal Wartephasen eingebaut, um das zu überprüfen. Bei 20ms sieht man, dass die Schlange etwas länger wird. Bei 50ms sieht man es deutlicher und sie bewegt sich noch flüssig. Bei 100ms springt sie schon ziemlich stark.


----------



## Feeder (20. Jun 2017)

Meniskusschaden hat gesagt.:


> Ich glaube die Zeitpunkte zwischen zwei Kopfpositions-Berechnungen liegen so dicht beieinander, dass sich die neue Position kaum oder gar nicht von der vorherigen unterscheidet. Dadurch überlappt der Kopf mit dem Folgeelement (also der vorherigen Kopfposition) teilweise oder vollständig. Ich habe testweise mal Wartephasen eingebaut, um das zu überprüfen. Bei 20ms sieht man, dass die Schlange etwas länger wird. Bei 50ms sieht man es deutlicher und sie bewegt sich noch flüssig. Bei 100ms springt sie schon ziemlich stark.


ikr

Danke, ich probiere es sofort mal aus!!!

Edit: Hey, ich sehe das Problem, werde es denke ich mit einem Modulo Operator, fixen. Ower wie würdet ihr das fixen?

Danke an ALLE!


----------

