# 2- D Kollision



## HennePro (11. Apr 2015)

Hallo Zusammen, 
ich suche schon seid vielen Stunden den Grund dafür, dass die if-Schleife nicht ausgeführt wird.
Kann mir jemand helfen(bin Einsteiger)?
Handelt sich hierbei um eine Applikation in Android Studio.

```
public class GameView extends SurfaceView {

    public Ball ball;

    public MainActivity ma;
    public int hoehespielflaeche, breitespielflaeche;
    private Monster monster;

    public boolean beruehren =true;


    public GameView(MainActivity ma1) {
        super(ma1);
        ma = ma1;


        //transparenter Hintergrund
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSPARENT);
        ball = new Ball(getResources(), this,200,400);
        monster = new Monster(getResources(), this,150,300);






        //um onDraw Methode aufzurufen
        {
            setWillNotDraw(false);
        }
        //Display ausmessen
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        breitespielflaeche = metrics.widthPixels;
        hoehespielflaeche = metrics.heightPixels;
        if((monster.getX()==150 && monster.getY()==300)){
            beruehren =false;
            if(beruehren =false)
            {
                ma.finish();
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        postInvalidate();
        monster.drawBitmap(canvas);
        ball.drawBitmap(canvas);
        super.onDraw(canvas);
    }


}
```


----------



## Dompteur (11. Apr 2015)

In Zeile 38 machst du keinen Vergleich sondern eine Zuweisung. 
Ersetze das "=" durch ein "==".


----------



## HennePro (11. Apr 2015)

Danke!
Habe die Bedingung jetzt ein wenig verändert und jetzt funktioniert es wieder nicht.

```
if(monster.getX()==ball.getX()&(monster.getY()==ball.getY())){
            beruehren =false;
            if(beruehren ==false)
            {
                ma.finish();
            }
        }
```


----------



## AntiMuffin (11. Apr 2015)

Benutze zu nächst && und nicht &, das sind große Performance unterschiede!
Bei dir ist berühren  jetzt immer False, evtl liegt es daran ? - Die .finish () Methode  wird jetzt immer aufgerufen.

Gruß,
AntiMuffin


----------



## HennePro (11. Apr 2015)

Mit dem && hattest du recht, nur leider wurde das Problem damit nicht behoben.

Hier nochmal alle Code- Schnipsel, die ich bisher habe.

```
package de.example.henne.bewegung;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.Window;
import android.view.WindowManager;


public class MainActivity extends ActionBarActivity implements SensorEventListener {

    private SensorManager sm;
    private Sensor accelerometer;
    private Display dspl;
    private Context context;
    public int x_acc,y_acc;
    public String string10;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = MainActivity.this;
        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

     
        sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        WindowManager mWindowManger = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        dspl = mWindowManger.getDefaultDisplay();
  
        setContentView(new GameView(this));



    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        event.values[0]*=10;
        event.values[1]*=10;
        event.values[2]*=10; 
        switch (dspl.getRotation()) {
            case Surface.ROTATION_0:
                x_acc = (int) -event.values[0];
                y_acc = (int) event.values[1];
                break;
            case Surface.ROTATION_90:
        
                x_acc = (int) event.values[1];
                y_acc = (int) event.values[0];
                break;
            case Surface.ROTATION_180:
             
                x_acc = (int) event.values[0];
                y_acc = (int) -event.values[1];
                break;
            case Surface.ROTATION_270:
                x_acc = (int) -event.values[1];
                y_acc = (int) -event.values[0];
                break;
        }
        onPause();
        onResume();

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }


    @Override
    protected void onPause() {
        super.onPause();
   
        sm.unregisterListener(this);
    }
  
    @Override
    protected void onResume() {
        super.onResume();
       
        sm.registerListener(this, accelerometer,SensorManager.SENSOR_DELAY_GAME);

    }


}
```


```
package de.example.henne.bewegung;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;

public class Monster {
    
    private GameView gameview;
    private Bitmap monsterbitmap;
    public Rect destRect,bitmapRect;
    private MonsterThread monsterthread;
    private int x,y;
    private Ball ball;
    public MainActivity ma;



    public Monster(Resources resources, GameView gameView,int new_x,int new_y) {
        x = new_x;
        y= new_y;
        gameview = gameView;

        ball = ball;

        monsterbitmap = BitmapFactory.decodeResource(resources, R.drawable.monster);
        bitmapRect = new Rect(0,0,monsterbitmap.getWidth(),monsterbitmap.getHeight());
        destRect = new Rect(0,0,monsterbitmap.getWidth(),monsterbitmap.getHeight());
        monsterthread = new MonsterThread(this,gameview);
        monsterthread.start();


    }
    public void drawBitmap(Canvas canvas) {
        destRect.right = destRect.left + monsterbitmap.getWidth();
        destRect.bottom = destRect.top + monsterbitmap.getHeight();
        canvas.drawBitmap(monsterbitmap, bitmapRect,destRect,null);
    }
    public void setY(int value) {
        destRect.top = value;
        destRect.bottom = destRect.top + monsterbitmap.getHeight();
    }
    public void setX(int value) {
        destRect.left = value;
        destRect.right = destRect.left + monsterbitmap.getWidth();
    }

    public void addx(int value) {
        if ((destRect.right+value)>gameview.breitespielflaeche) {
            value = gameview.breitespielflaeche - destRect.right;
        }
        if ((destRect.left+value)<0) {
            value = destRect.left*(-1);
        }
        destRect.left = destRect.left+value;
        destRect.right = destRect.left + monsterbitmap.getWidth();
    }

    public void addy(int value) {//Veränderung hier
        if ((destRect.bottom+value)>gameview.hoehespielflaeche) {
            value = gameview.hoehespielflaeche - destRect.bottom;
        }
        if ((destRect.top+value)<0) {
            value = destRect.top*(-1);
        }
        destRect.top = destRect.top+value;
        destRect.bottom = destRect.top + monsterbitmap.getHeight();
    }

    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }


}
```


```
package de.example.henne.bewegung;

import android.content.Intent;

import java.util.concurrent.TimeUnit;

import static android.support.v4.app.ActivityCompat.startActivity;

public class MonsterThread extends Thread {

    private Monster monster;
    private GameView gameview;
    private int factorx,factory;
    private int monstermittelx,monstermittely;
    private int ballmittelx,ballmittely;
    private int differenzpositionenx,differenzpositioneny;
    public boolean beruehren;


    public String string10;

    public MonsterThread(Monster monster1, GameView gameview1 ) {
        monster = monster1;
        gameview = gameview1;



    }
    @Override
    public void run() {
        try {
            monster.setX(gameview.breitespielflaeche - gameview.breitespielflaeche/2);
            monster.setY(gameview.hoehespielflaeche-gameview.hoehespielflaeche/3);
            while(true) {
                ballmittelx = (gameview.ball.destRect.left + gameview.ball.destRect.right) / 2;
                ballmittely = (gameview.ball.destRect.top + gameview.ball.destRect.bottom) / 2;
                monstermittelx = (monster.destRect.left + monster.destRect.right) / 2;
                monstermittely = (monster.destRect.top + monster.destRect.bottom) / 2;
                differenzpositionenx = ballmittelx - monstermittelx;
                differenzpositioneny = ballmittely - monstermittely;
                if (differenzpositioneny == 0) {
                    factory = 0;
                } else if (differenzpositioneny > 0) {
                    factory = 1;
                } else
                    factory = -1;
                if (differenzpositionenx == 0) {
                    factorx = 0;
                } else if (differenzpositionenx > 0) {
                    factorx = 1;
                } else
                    factorx = -1;
                TimeUnit.MILLISECONDS.sleep(10);
                monster.addx(5 * factorx);
                monster.addy(5 * factory);


            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.run();
    }




}
```


```
private Bitmap ballbitmap;
    public Rect destRect,bitmapRect;
    private GameView gameview;
    private BallThread ballthread;
    public int x,y;

    
    public Ball(Resources resources, GameView gameView1, int new_x, int new_y) {
        gameview = gameView1;
        x = new_x;
        y=new_y;
        ballbitmap = BitmapFactory.decodeResource(resources,R.drawable.ball);
        //bitmapRect = bei mehreren Kostümen in einer Bitmap wird das gewünschte Kostüm ausgewählt
        bitmapRect = new Rect(0,0,ballbitmap.getWidth(),ballbitmap.getHeight());
        //destRect = Bildschirmkoordinaten/Bildschirmbereich wo Bitmap hingezeichnet werden soll
        destRect = new Rect(0,0,ballbitmap.getWidth(),ballbitmap.getHeight());
        ballthread = new BallThread(Ball.this,gameview);
        ballthread.start();
    }
        
    public void drawBitmap(Canvas canvas) {
        destRect.right = destRect.left + ballbitmap.getWidth();
        destRect.bottom = destRect.top + ballbitmap.getHeight();
        canvas.drawBitmap(ballbitmap, bitmapRect,destRect,null);
    }

    public void addx(int value) {
        if ((destRect.right+value)>gameview.breitespielflaeche) {
            value = gameview.breitespielflaeche - destRect.right;
        }
        if ((destRect.left+value)<0) {
            value = destRect.left*(-1);
        }
        destRect.left = destRect.left+value;
        destRect.right = destRect.left + ballbitmap.getWidth();
    }

    public void addy(int value) {
        if ((destRect.bottom+value)>gameview.hoehespielflaeche) {
            value = gameview.hoehespielflaeche - destRect.bottom;
        }
        if ((destRect.top+value)<0) {
            value = destRect.top*(-1);
        }
        destRect.top = destRect.top+value;
        destRect.bottom = destRect.top + ballbitmap.getHeight();
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }

}
```


```
package de.example.henne.bewegung;

import java.util.concurrent.TimeUnit;

public class BallThread extends Thread {
    
    private Ball ball;
    private GameView gameview;

    public BallThread(Ball ball1, GameView gameview1) {
        ball = ball1;
        gameview = gameview1;
    }

    @Override
    public void run() {
        try {
            while(true) {
                TimeUnit.MILLISECONDS.sleep(20);
                try {
                    ball.addx(gameview.ma.x_acc);
                    ball.addy(gameview.ma.y_acc);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```


```
package de.example.henne.bewegung;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.SurfaceView;

public class GameView extends SurfaceView {

    public Ball ball;

    public MainActivity ma;
    public int hoehespielflaeche, breitespielflaeche;
    private Monster monster;

    public boolean beruehren =false;


    public GameView(MainActivity ma1) {
        super(ma1);
        ma = ma1;


        //transparenter Hintergrund
        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSPARENT);
        ball = new Ball(getResources(), this,200,400);
        monster = new Monster(getResources(), this,150,300);






        //um onDraw Methode aufzurufen
        {
            setWillNotDraw(false);
        }
        //Display ausmessen
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        breitespielflaeche = metrics.widthPixels;
        hoehespielflaeche = metrics.heightPixels;
        if((monster.getX()==ball.getX())&&(monster.getY()==ball.getY())){



                ma.finish();

        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        postInvalidate();
        monster.drawBitmap(canvas);
        ball.drawBitmap(canvas);
        super.onDraw(canvas);
    }


}
```


----------



## Gucky (11. Apr 2015)

Ich habe noch etwas und zwar dort.
Was genau ist denn das Problem?
Die if-Bedingung wird nicht ausgeführt? Dann stimmen anscheinend die Bedingungen darin nicht. Lass dir mal die Werte aus der Bedingung mit Sysouts ausgeben. Dann sehen wir weiter.


----------



## HennePro (11. Apr 2015)

Die eigentliche Idee war, dass bei einer Kollision ein "Leben" abgezogen wird(die Lebensanzeige wird noch programmiert). Da ich jedoch keine wirkliche Idee für die Umsetzung hatte, soll jetzt ein Leben abgezogen werden, wenn das Monster und der Ball genau die gleiche Position haben. Um die if-Abfrage auf die Funktionalität zu überprüfen, sollte jetzt erstmal die Aktivität gestoppt werden, was jedoch nicht der Fall ist.


----------



## AntiMuffin (11. Apr 2015)

Noch ein Tipp: 
Teste die Kollision  nicht mit (x1==x2 && y1==y2) sondern in einem bereich (x1>=x2-10&&x1<=x1+10 && y1 ....). Dies solltest du machen, weil x1 fast immer leicht neben x2 liegt und so gut wie nie exakt  darauf !

Gruß,
AntiMuffin


----------



## Gucky (11. Apr 2015)

Exakt dieselbe Position muss Pixelgenau sein. Das wirst du nicht hinbekommen.
Stattdessen solltest du zum Beispiel mit Shapes, mit Rectagles oder mit Polygonen arbeiten.


----------



## HennePro (13. Apr 2015)

Soo, ich habe jetzt mit Rectagles versucht(zum ersten mal).
Nur leider passiert nach der Ausführung nicht(auch keine Fehlermeldung wird angezeigt!)

```
package de.example.henne.bewegung;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.SurfaceView;

public class GameView extends SurfaceView {

    public Ball ball;

    public MainActivity ma;
    public int hoehespielflaeche, breitespielflaeche;
    private Monster monster;
    public int leben=5;

    public GameView(MainActivity ma1) {
        super(ma1);
        ma = ma1;


        setZOrderOnTop(true);
        getHolder().setFormat(PixelFormat.TRANSPARENT);
        ball = new Ball(getResources(), this, 100, 300);
        monster = new Monster(getResources(), this, 200, 400);
        while (leben != 0) {
            if (intersects(monster.destRect, ball.destRect)) {
                leben = leben - 1;

            }
        }
        if (leben == 0) {
            ma.finish();
        }

        {
            setWillNotDraw(false);
        }

        DisplayMetrics metrics = getResources().getDisplayMetrics();
        breitespielflaeche = metrics.widthPixels;
        hoehespielflaeche = metrics.heightPixels;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        postInvalidate();
        monster.drawBitmap(canvas);
        ball.drawBitmap(canvas);
        super.onDraw(canvas);
    }

    public static boolean intersects (Rect a, Rect b ){
        return intersects(a, b);

    }

}
```
Bitte entschuldigt kleine Fehler!


----------



## Gucky (13. Apr 2015)

Kleinere Fehler werden nicht entschuldigt, weil sie dafür verantwortlich sind, dass dein Programm nicht läuft 
Du hast mit intersects (a, b) eine endlose Rekursion gebaut. Es wundert mich, dass du keinen StackOverflowError bekommst.


----------



## HennePro (14. Apr 2015)

Ich muss mal wieder um euren Rat bitten.
Das Programm stürzt immernoch bei der while-Schleife ab.
hat jemand eine Idee wie ich das solven kann?

```
public  void leben2()  {
        while (leben != 0) {

            if (monster.bitmapRect.intersect(ball.bitmapRect)) {
                leben = leben - 1;            }
            
        }
        if (leben == 0) {
            ma.finish();
        }
    }
```


----------



## Gucky (15. Apr 2015)

Du hast eine Endlosschleife gebaut. Prüfe nur bei jeder Bewegung auf Kollision und nicht permanent.


----------



## Androbin (15. Apr 2015)

Gucky hat gesagt.:


> Du hast eine Endlosschleife gebaut. Prüfe nur bei jeder Bewegung auf Kollision und nicht permanent.


Er kann schon auch permanent, dann aber in einem extra Thread und mit zeitlichen Abständen.


----------



## Gucky (15. Apr 2015)

@Androbin
Da hast du wohl recht aber ich dachte mir, dass ich mit derartig komplizierten Konstrukten warte, bis der TO ein höheres Erfahrungslevel erreicht hat weil da kommen dann auch Dinge, wie Synchronisierung, Zugriffsverletzungen (gleichzeitiges Schreiben) und Interthreadkommunikation hinzu.


----------

