# Pacman Kollision von Münzen und Mauern



## setX (11. Jan 2015)

Guten Abend zusammen,

mein Freund und ich verzweifeln derzeit an unserem Informatik-Projekt und wären froh, etwas Hilfe zu erhalten.
Es geht um die Programmierung des Spieleklassikers 'Pacman' mithilfe der Bibliothek GLOOP, mit der wir diverse Objekte und Methoden für unsere Programmierungen in der Schule nutzen können.
Das Spiel soll letztendlich die Kollisionen überprüfen. Das heißt, wenn die Spielerfigur gegen eine Mauer läuft, soll sie nicht dadurch laufen können (derzeit soll er nur verlangsamt durchlaufen können, da die komplette Unterbrechung ebenfalls nicht ganz funktionieren will...
Ebenso soll die Spielerfigur zurückgesetzt werden, wenn sie gegen die sich zufällig bewegenden Monster läuft und nach dem Einsammeln der 4 Münzen in das nächste Level schalten (das weiterschalten soll vorerst zweitrangig sein).
Jedoch werden mittels 'gibX' und 'gibY' nicht wie gewünscht die Koordinaten übergeben, die dann überprüft werden sollen.
Damit der Programmablauf nicht in einer Schleife hängen bleibt haben wir eine Scheife für alle Überprüfungen gemacht, welche wie folgt lautet:

```
import GLOOP.*;
public class ABKSchleife
{
    GLTastatur          tastatur;
    
    Muenzen1             muenzen1;
    Muenzen2             muenzen2;
    Muenzen3             muenzen3;
    Muenzen4             muenzen4;
    Spieler             spieler;
    Monster1            monster1;
    Monster2            monster2;
    Monster3            monster3;
    Monster4            monster4;
    Level1              level1;
    Level2              level2;
    Level3              level3;
    public ABKSchleife()
    {
        tastatur = new GLTastatur();
        
        muenzen1 = new Muenzen1();
        muenzen2 = new Muenzen2();
        muenzen3 = new Muenzen3();
        muenzen4 = new Muenzen4();
        spieler = new Spieler();
        monster1 = new Monster1();
        monster2 = new Monster2();
        monster3 = new Monster3();
        monster4 = new Monster4();
        level1 = new Level1();
        level2 = new Level2();
        level3 = new Level3();
        
        while(!tastatur.esc())
        {                                                 
            //Muenzendrehung
            muenzen1.zyl1.drehe(0,0,10);
            muenzen2.zyl2.drehe(0,0,10);
            muenzen3.zyl3.drehe(0,0,10);
            muenzen4.zyl4.drehe(0,0,10);
            
            //Monster 1-4
            int richtung = (int)(Math.random()*12);
            if (richtung==0 || richtung==4 || richtung==8)
            {
                monster1.vorne();
                monster2.hinten();
                monster3.links();
                monster4.rechts();
            }
            if (richtung==1 || richtung==5 || richtung==9)
            {
                monster1.hinten();
                monster2.links();
                monster3.rechts();
                monster4.vorne();
            }
             if (richtung==2 || richtung==6 || richtung==10)
            {
                monster1.links();
                monster2.rechts();
                monster3.vorne();
                monster4.hinten();
            }
            if (richtung==3 || richtung==7 || richtung==11)
            {
                monster1.rechts();
                monster2.vorne();
                monster3.hinten();
                monster4.links();
            }
            
            //Bewegung
            if(tastatur.oben())
            {
                spieler.steuerungVorne();
            }
            if(tastatur.unten())
            {
                spieler.steuerungHinten();
            }
            if(tastatur.links())
            {
                spieler.steuerungLinks();
            }
            if(tastatur.rechts())
            {
                spieler.steuerungRechts();
            }

            spieler.spieler.gibX();
            spieler.spieler.gibY();
            
            
            muenzen1.zyl1.gibX();
            muenzen2.zyl2.gibX();
            muenzen3.zyl3.gibX();
            muenzen4.zyl4.gibX();
            
            muenzen1.zyl1.gibY();
            muenzen2.zyl2.gibY();
            muenzen3.zyl3.gibY();
            muenzen4.zyl4.gibY();
            
            for(int i=0; i<level1.w.length; i++)
            {               
                level1.w[i].gibX();
            }
            for(int i=0; i<level1.w.length; i++)
            {               
                level1.w[i].gibY();
                if(level1.w[i].gibY()+25 >= spieler.spieler.gibY() && level1.w[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte();
                }
                else
                {
                    continue;
                }
            }
            
            for(int i=0; i<level1.rand.length; i++)
            {               
                level1.rand[i].gibX();
            }
            for(int i=0; i<level1.rand.length; i++)
            {               
                level1.rand[i].gibY();
                if(level1.rand[i].gibY()+25 >= spieler.spieler.gibY() && level1.rand[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte();
                }
                else
                {
                    continue;
                }
            }
            
            
            if(muenzen1.zyl1.gibX() <= spieler.spieler.gibX() || muenzen1.zyl1.gibY() <= spieler.spieler.gibY())
            {
                muenzen1.zyl1.setzeSichtbarkeit(false);
            }
           
            if(muenzen2.zyl2.gibX() <= spieler.spieler.gibX() || muenzen2.zyl2.gibY() <= spieler.spieler.gibY())
            {
                muenzen2.zyl2.setzeSichtbarkeit(false);
            }
            
            if(muenzen3.zyl3.gibX() <= spieler.spieler.gibX() || muenzen3.zyl3.gibY() <= spieler.spieler.gibY())
            {
                muenzen3.zyl3.setzeSichtbarkeit(false);
            }
            
            if(muenzen4.zyl4.gibX() <= spieler.spieler.gibX() || muenzen4.zyl4.gibY() <= spieler.spieler.gibY())
            {
                muenzen4.zyl4.setzeSichtbarkeit(false);
            }
            
            Sys.warte();
        }
    }       
}
```

Die for-Schleife soll einen Array durchlaufen, der alle Koordinaten der 50*50 großen Würfel enthalten soll. Mit einem Radius, in den der Spieler nicht rein läuft, wäre uns schon geholfen, jedoch hakt der ganze Spielablauf und der Spieler kann einfach durch die Objekte durchlaufen (bei erhöhtem Sys.warte() kommt man dennoch hindurch).
Ebenso sollen die Münzen, nachdem sie berührt werden, ihre Sichtbarkeit (vorerst) ausschalten (und später eine Variable hochzählen).
Jedoch scheint immer etwas falsch berechnet zu werden und ein Teil der Münzen ist entweder schon beim Start unsichtbar, oder es setzen mehrere Münzen ihre Sichtbarkeit aus, wenn nur ein berührt wird.

Über Tipps, wie wir die Kollision der Münzen und der Mauern testen können, wären wir mit unseren derzeit nicht sehr großen Java-Kenntnissen sehr dankbar.
Vielen Dank schon für eure Bemühungen, euch mit diesem Thema auseinander zu setzen.

Hier noch ein Klassendiagramm zur Struktur des Projektes




Viele Grüße
Aragorm und setX


----------



## setX (12. Jan 2015)

Guten Abend,

nun haben wir es geschafft, die Kollision der Münzen und der Monster (die nicht in einem Array gespeichert sind) wie gewünscht zu überprüfen.
Es bleibt allerdings noch die for-Schleife für den Array mit etwas 120 Blöcken (+Seitenwände) pro Level, welche nicht wie gewünscht die Koordinaten überprüft...
Der betroffene Code entspricht folgende Zeilen

```
//Kollision Mauern Level1
            for(int i=0; i<level1.w.length; i++)              
            {               
                level1.w[i].gibX();
            }
            for(int i=0; i<level1.w.length; i++)
            {               
                level1.w[i].gibY();
                if(level1.w[i].gibY()+25 >= spieler.spieler.gibY() && level1.w[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte();
                }
                else
                {
                    continue;
                }
            }
            
            for(int i=0; i<level1.rand.length; i++)
            {               
                level1.rand[i].gibX();
            }
            for(int i=0; i<level1.rand.length; i++)
            {               
                level1.rand[i].gibY();
                if(level1.rand[i].gibY()+25 >= spieler.spieler.gibY() && level1.rand[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte();
                }
                else
                {
                    continue;
                }
            }
```

Der überarbeitete Code schaut nun so aus

```
import GLOOP.*;
public class ABKSchleife
{
    GLTastatur          tastatur;
    GLTafel             gewonnen;
    int                 leben;
    int                 muenzzaehler;
    
    Muenzen1            muenzen1;
    Muenzen2            muenzen2;
    Muenzen3            muenzen3;
    Muenzen4            muenzen4;
    Spieler             spieler;
    Monster1            monster1;
    Monster2            monster2;
    Monster3            monster3;
    Monster4            monster4;
    Level1              level1;
    Level2              level2;
    Level3              level3;
    public ABKSchleife()
    {
        tastatur = new GLTastatur();
        int leben = 3;
        int muenzzaehler = 0;
        
        muenzen1 = new Muenzen1();
        muenzen2 = new Muenzen2();
        muenzen3 = new Muenzen3();
        muenzen4 = new Muenzen4();
        spieler = new Spieler();
        monster1 = new Monster1();
        monster2 = new Monster2();
        monster3 = new Monster3();
        monster4 = new Monster4();

        
        while(!tastatur.esc())
        { 
            ////Levelauswahl
            //if (tastatur.istGedrueckt('1'))
            //{
            //   level1 = new Level1();
            //}
            //if (tastatur.istGedrueckt('2'))
            //{
            //    level2 = new Level2();
            //}
            //if (tastatur.istGedrueckt('3'))
            //{
            //    level3 = new Level3();
            //}
            
            //Muenzendrehung
            muenzen1.zyl1.drehe(0,0,10);
            muenzen2.zyl2.drehe(0,0,10);
            muenzen3.zyl3.drehe(0,0,10);
            muenzen4.zyl4.drehe(0,0,10);
            
            //Monster 1-4 Zufallsbewegung
            int richtung = (int)(Math.random()*16);
            if (richtung==0 || richtung==4 || richtung==8 || richtung==12)
            {
                monster1.vorne();
                monster2.hinten();
                monster3.links();
                monster4.rechts();
            }
            if (richtung==1 || richtung==5 || richtung==9 || richtung==13)
            {
                monster1.hinten();
                monster2.links();
                monster3.rechts();
                monster4.vorne();
            }
             if (richtung==2 || richtung==6 || richtung==10 || richtung==14)
            {
                monster1.links();
                monster2.rechts();
                monster3.vorne();
                monster4.hinten();
            }
            if (richtung==3 || richtung==7 || richtung==11 || richtung==15)
            {
                monster1.rechts();
                monster2.vorne();
                monster3.hinten();
                monster4.links();
            }
            
            //Bewegung
            if(tastatur.oben())
            {
                spieler.steuerungVorne();
            }
            if(tastatur.unten())
            {
                spieler.steuerungHinten();
            }
            if(tastatur.links())
            {
                spieler.steuerungLinks();
            }
            if(tastatur.rechts())
            {
                spieler.steuerungRechts();
            }
            
            //Kollision Mauern Level1
            for(int i=0; i<level1.w.length; i++)              
            {               
                level1.w[i].gibX();
            }
            for(int i=0; i<level1.w.length; i++)
            {               
                level1.w[i].gibY();
                if(level1.w[i].gibY()+25 >= spieler.spieler.gibY() && level1.w[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte();
                }
                else
                {
                    continue;
                }
            }
            
            for(int i=0; i<level1.rand.length; i++)
            {               
                level1.rand[i].gibX();
            }
            for(int i=0; i<level1.rand.length; i++)
            {               
                level1.rand[i].gibY();
                if(level1.rand[i].gibY()+25 >= spieler.spieler.gibY() && level1.rand[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte();
                }
                else
                {
                    continue;
                }
            }

            
            //Kollision Muenze1
            double lDist1 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-muenzen1.zyl1.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-muenzen1.zyl1.gibY(),2)
            );
            if (lDist1<50+25){
             muenzen1.zyl1.setzeSichtbarkeit(false);
             muenzzaehler ++;
            }  
            
            //Kollision Muenze2
            double lDist2 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-muenzen2.zyl2.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-muenzen2.zyl2.gibY(),2)
            );
            if (lDist2<50+25){
             muenzen2.zyl2.setzeSichtbarkeit(false);
             muenzzaehler ++;
            }  
            
            //Kollision Muenze3
            double lDist3 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-muenzen3.zyl3.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-muenzen3.zyl3.gibY(),2)
            );
            if (lDist3<50+25){
             muenzen3.zyl3.setzeSichtbarkeit(false);
             muenzzaehler ++;
            }  
            
            //Kollision Muenze4
            double lDist4 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-muenzen4.zyl4.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-muenzen4.zyl4.gibY(),2)
            );
            if (lDist4<50+25){
             muenzen4.zyl4.setzeSichtbarkeit(false);
             muenzzaehler ++;
            } 
            
            
            //Kollision Monster1
            double lDist5 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-monster1.ungeheuer1.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-monster1.ungeheuer1.gibY(),2)
            );
            if (lDist5<50+25){
                spieler.spieler.setzePosition(0,0,0);
                leben --;
            } 
            
            //Kollision Monster2
            double lDist6 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-monster2.ungeheuer2.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-monster2.ungeheuer2.gibY(),2)
            );
            if (lDist6<50+25){
                spieler.spieler.setzePosition(0,0,0);
                leben --;
            } 
            
            //Kollision Monster3
            double lDist7 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-monster3.ungeheuer3.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-monster3.ungeheuer3.gibY(),2)
            );
            if (lDist7<50+25){
                spieler.spieler.setzePosition(0,0,0);
                leben --;
            } 
            
            //Kollision Monster4
            double lDist8 = Math.sqrt(
                Math.pow(spieler.spieler.gibX()-monster4.ungeheuer4.gibX(),2)+
                Math.pow(spieler.spieler.gibY()-monster4.ungeheuer4.gibY(),2)
            );
            if (lDist8<50+25){
                spieler.spieler.setzePosition(0,0,0);
                leben --;
            } 
            
            //Gewonnen
            if(muenzzaehler==4)
            {
               gewonnen = new GLTafel(0,-580,1080, 10,10);
               gewonnen.setzeText("Gewonnen!" ,10);
            }
            
            //Beenden
            if (leben==0)
            {
                Sys.beenden();
            }
            
            Sys.warte();
        }
    }       
}
```

Über Hilfe, die zur Lösung unsere Problems führt wären wir sehr dankbar.


Viele Grüße
Aragorm und setX


----------



## BRoll (13. Jan 2015)

Sieht aus als ob du ne Klammer bei deinen Schleifen verschoben hast.
Du gehst einfach nur 2 Schleifen nacheinander durch, die aber (wegen dem Spielfeld 2D raster) 
verschachtelt laufen sollten!


----------



## setX (13. Jan 2015)

Das haben wir meine ich (bei einem unserer vielen Versuche) auch schon einmal probiert, jedoch wird bei folgendem Programmcode erneut etwas falsch berechnet und im Spiel kann man nicht einmal den Spieler bewegen, noch drehen sich Münzen oder bewegen sich Monster (da er vermutlich dauerhaft Sys.warte(100); wartet).
Die Spielerfigut steht anfangs auch mit keiner Mauer in Kollision und auch bei Ausklammerung der '+25' zu der gibKoordinate stoppt der Spielabablauf automatisch...

```
//Kollision Mauern Level1
            for(int i=0; i<level1.w.length; i++)
            {  
              level1.w[i].gibX();
               for(int j=0; j<level1.w.length; j++)              
               {
                level1.w[j].gibY();
                if(level1.w[j].gibY()+25 >= spieler.spieler.gibY() || level1.w[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte(100);
                }
                else
                {
                    continue;
                }
              }
          }
            
            
          
           for(int i=0; i<level1.rand.length; i++)
           {               
              level1.rand[i].gibX();
             for(int j=0; j<level1.rand.length; j++)
             {               
                level1.rand[j].gibY();
                if(level1.rand[j].gibY()+25 >= spieler.spieler.gibY() || level1.rand[i].gibX()+25 >= spieler.spieler.gibX())
                {
                    Sys.warte(100);
                }
                else
                {
                    continue;
                }
             }
           }
```

VG Aragorm und setX


----------



## BRoll (13. Jan 2015)

Naja dann gibts halt jetzt ein neues Problem dadurch 
Schau den Code genau an, rechne es von Hand mit Beispieldaten nach und teste damit
NUR die Kollisionsabfrage, bis du zu 100% sicher sein kannst, dass die funktioniert.
Dann kannst du nach Fehlern schauen die daraus resultieren weil du was falsch bedacht/gemacht hast.
Ich denke mal wenn es jetzt eine Kollision gibt, wartest du mit Sys.warte(), im nächsten durchlauf wartet er aber gleich wieder weils immer noch eine Kollision hat (der spieler hat sich vielleicht nicht bewegt?).


----------



## setX (13. Jan 2015)

Theoretisch dürfte er keine Kollision haben. Der Spieler startet auf 0,0,0, die Mauern sind aber in erkennbaren Radius darum gestellt...
Hier ein Bild dazu




Ich habe mir nun die for-Schleife nochmal genauer angeschaut, wobei mir folgendes aufgefallen ist.
Das System wartet 1sec, wenn der Spieler durch die Koordinaten der Mauer läuft, d.h. die Koordinaten der Mauer sind größer als die des Spielers.
Der Spieler steht allerdings wie erwähnt auf 0,0,0.
Möglich wäre es nun, dass die Steine, die links vom Spieler sind, den Fehler 'senden'.
Diese befinden sich ja logischerweise im negativen Bereich. Die sollten daher wenn sie ihre Koordinaten geben, kleiner sein als die des Spielers. Denn beispielsweise 0>-50...
->Sys.warte(x);

Wäre es denn nun möglich, dass die for-Schleife die Koordinaten zum Quadrat ausgibt?
Dann gibt die Spielerkoordinate die Koordinate ebenfalls zum Quadrat aus, daraus folgt eine Überprüfung nur positiver Werte (theoretisch).
Wir hatten dies bislang immer mit beispielsweise

```
double lDist1 = Math.pow(-level1.w[i],2);
```
Wenn wir dies aber in die for-Schleife hinuzschreiben, möchte dies nicht ganz funktionieren...
Gibt es da eine andere Methode oder einen anderen Ansatz, die negativen Werte zu umgehen?

Vielen Dank für eure Bemühungen, euch mit dem Thema auseinander zu setzen (besonders natürlich BRoll).


----------



## BRoll (13. Jan 2015)

Also das mit den Quadraten würde ich auch mal lassen, nimm doch einfach die größe der Map 
(ich hoffe mal die ist fix pro level) und setz den nullpunkt nach links oben. Dann hast du nur positive Koordinaten,
und deine Nullkoordinate von vorhin ist einfach halbe breite/höhe der Map. 

Aber Unabhängig von dem Koordinatenaufbau geht es doch auch einfach mit negativen Koordinaten:

wenn alle mapblöcke gleich groß sind, hast du ja einen einfachen rasteraufbau,
wobei der spieler nicht durch felderlaufen kann, die als mauern hinterlegt sind.

Ich würde es so machen: (mal in pseudocode)
(zur vereinfachung ohne z achse, also kannste nacher einfach y=z wenn mans 3d sieht)


```
x = spielerX
y = spielerY
size= blockgröße 
darfgehen=false

...führe gewünschte bewegung mit x/y durch...

.. jetzt abprüfen ob eine mauer berührt werden würde 
for(int bx=0; bx<mapbreite; bx++)
{
for(int by=0; by<maphoehe; by++)
{

if(x>=bx*size&&x<=(bx+1)*size)
{
if(y>=by*size&&y<=(by+1)*size)
{
 //passenden block gefunden => nun schauen ob passierbar
darfgehen = istBlockFrei(bx,by)
return
}
}


}
}

//nun schauen ob wir gehen dürfen
if(darfgehen)
{
//"echte" koordinaten nun setzen, da zug erlaubt
spielerx= x
spielery=y 
}
```

Vielleicht hiflt dir das ja weiter, auch wenns nicht optimal ist.


----------



## setX (15. Jan 2015)

Guten Abend,

vielen Dank für deine Bemühungen BRoll.
Die Verschiebung der Spielerfigur funktioniert so nicht, da die Mauern ja wieder negative Koordinaten hätten. Außerdem ist es uns mit GLOOP nicht bekannt, die ganze Klasse zu verschieben (ohne übertrieben viel Schreibarbeit).

Dein Quellcode haben wir soweit vom Ansatz verstanden, ließ sich bislang aber noch nicht ganz umsetzen. Da wir das Projekt heute abgegeben haben, haben wir uns auf das wesentliche konzentriert und in Sachen Kollision eine Übergangslösung abgegeben.
Interessen tut uns dies aber schon noch, ich/wir werden uns das am Wochenende vielleicht noch einmal genauer anschauen, denn eine Lösung wird es bestimmt irgendwie geben...


----------



## lila00 (9. Mrz 2015)

Klingt sehr interessant. 
Mein Bekannter hatte ein ähnliches Problem vor einiger Zeit. 
Ich glaube auf spielpinguin.com hat er einige Versionen von solchen Spielen 
gefunden die ihm sehr hilfreich waren. 

Versucht es einfach mal. 

MFG


----------



## herzog123 (5. Mai 2019)

könnt ihr bitte alles was ihr von der Programmierung habt schicken ganzen Quellcode


----------



## herzog123 (5. Mai 2019)

könnt ihr bitte den ganzen Quelltext zeigen


----------



## mihe7 (5. Mai 2019)

Da bin ich ja mal gespannt, ob nach vier Jahren jemand noch den Quelltext aus dem Hut zaubert. Was willst Du denn damit?

Google liefert z. B. https://github.com/bpalomino5/Pac-Man


----------

