# Jump'n'run Kollision bei Blöcken



## danthe (8. Dez 2011)

Hi,
Wir sollen momentan im Informatik-Leistungskurs ein Jump'n'run-Spiel programmieren. Da ich noch nicht so viel Erfahrung habe und wir meiner Meinung nach noch gar nicht so wirklich bereit dafür sind (andere programmieren auf ziemlich seltsame Weise Applets mit Kugeln, die sich hin und her bewegen), bin ich Quaxlis Tutorial durchgegangen und habe es logischerweise so angepasst, dass man mit einer Figur hin- und herspringt. Die nächste Sache, an der ich momentan hänge, ist die Kollision, und zwar nicht mit Gegnern (Sprites), sondern mit Blöcken. Ich könnte natürlich alles in ewigen If-Bedingungen abfragen oder Sprites für die Blöcke erstellen, aber ist das nicht recht ressourcenfressend? Gibt es vielleicht eine einfache Methode, das alles abzufragen? Benutze zurzeit einen großen Background (als png) der Super Mario Bros. Welt 1-1, der sich glücklicherweise genau in Tiles zu 45x45 Pixeln einteilen lässt, daher wäre es auch kein Problem, Objekte drüberzulegen. 
Habe den Programmcode und eine *.jar-Datei mit einer start.bat (die ihr von *.txt umbenennen müsst) hochgeladen. Den Hintergrundsound habe ich rausgenommen, damit es kleiner wird, ist aber auch absolut unwichtig. Fürs Kommentieren habe ich keine Zeit, aber falls ihr den Programmcode braucht und etwas nicht versteht, erkläre ich es gerne!


----------



## danthe (9. Dez 2011)

Gibt es hier einen Edit-Button? Habe gerade mal den Code rausgenommen, mit dem der Hintergrundsound abgespielt wird, da er ja auch weder in der .zip noch in der .jar ist.

Edit: ^^ Edit gibt es wohl nur bei Nicht-Startposts.


----------



## Lulumann6 (9. Dez 2011)

du könntest ein 2D-Array, dass deinen Tiles entspricht anlegen. 
wenn der eintrag des arrays eine 0 ist, hast du an der stelle luft und das dahinterliegende background-bild kommt zum vorschein. eine 1 wäre dann ein normaler block. eine 2 könnte ein gold-block sein usw...
zum zeichnen gehst du das array durch und wenn der eintrag nicht 0 ist mal du an der entsprechenden stelle, multipliziert mit 45, das bild des tiles an die stelle in dein fenster.
collisionserkennung geht dann ähnlich. du nimmst die eckpunkte deines players teilst die 45 und guckst was im entsprechenden eintrag des arrays steht.


----------



## Quaxli (9. Dez 2011)

Mal ein erster Kommentar:

Was Du da in Deiner Klasse Mario in setHorizontalSpeed reingequetscht hast, gehört da nicht hin.


```
public void setHorizontalSpeed(double d){
    super.setHorizontalSpeed(d);
    
      if(getHorizontalSpeed()>0){
      setLoop(5,7);}
      else if(parent.linkswaspressed==true && !parent.up && !parent.right && !parent.left){
        setLoop(3,3);
        parent.rechtswaspressed=false; parent.linkswaspressed=false;
      }
      else if(parent.rechtswaspressed==true && !parent.up && !parent.right && !parent.left){
        setLoop(4,4);
        parent.rechtswaspressed=false; parent.linkswaspressed=false;
      }
      else if(getHorizontalSpeed()<0){
        setLoop(0,2);
      }
    }
```

Das erklärt auch, warum Mario so ruckelig läuft - Änderungen werden nur vorgenommen, wenn sich die Horizontal-Geschwindigkeit ändert. 
Den ganzen if-Kram solltest Du in der Methode doLogic ansiedeln. Und zwar bei Mario oder im GameLoop.
Außerdem tun die if-Konstrukte in den Augen weh 
Das kann man schöner lösen, z. B. in dem man in der Klasse Mario eine Methode für's Hüpfen einbaut, und Logik dahin auslagert, etc...

Ich guck später nochmal über den Rest und Deine eigentliche Frage. :rtfm:


----------



## danthe (9. Dez 2011)

Lulumann6 hat gesagt.:


> du könntest ein 2D-Array, dass deinen Tiles entspricht anlegen.
> wenn der eintrag des arrays eine 0 ist, hast du an der stelle luft und das dahinterliegende background-bild kommt zum vorschein. eine 1 wäre dann ein normaler block. eine 2 könnte ein gold-block sein usw...
> zum zeichnen gehst du das array durch und wenn der eintrag nicht 0 ist mal du an der entsprechenden stelle, multipliziert mit 45, das bild des tiles an die stelle in dein fenster.
> collisionserkennung geht dann ähnlich. du nimmst die eckpunkte deines players teilst die 45 und guckst was im entsprechenden eintrag des arrays steht.



Aber dann hätte ich ein Array mit ca. 3000 Einträgen, ist das wirklich die Lösung?
Edit: Ich könnte die Stellen für Luft doch einfach ganz auslassen und nur die Positionen der Blöcke hinschreiben, oder?


----------



## Quaxli (9. Dez 2011)

So, ich hab' mal ordentlich dran rum gefrickelt und Dir ein Beispiel gebastelt, das mit einer Schattenkarte arbeitet. Das bedeutet, daß "im Hintergrund" eine Karte mit einfacher Farbgebung vorgehalten wird. In dem Beispiel soll alles was schwarz ist ein Hindernis sein (vgl. shadow.png).

Das Ganze ist noch ziemlich Basic, keineswegs komplett und auch nicht 100% fehlerfrei. Aber es ist ja Deine Hausarbeit, also sollst Du auch noch was machen 
Schau's Dir halt mal an, ich hab's angehängt.

Aktuell ist nur das Hüpfen und Fallen realisiert und der Sprung ist noch ziemlich "komisch".
Außerdem kann Mario noch durch Hindernisse durchlaufen, etc. Hier müsste ebenfalls noch Code rein, wenn Du mit diesem Beispiel weiterarbeiten willst.
Der Code, der ihn vom Fallen abhält, mnüsste halt noch für die Seiten implementiert werden.
Gleiches gilt für's Hüpfen, wenn oberhalb ein Hinderniss ist.

Ich habe Deinen  Code, den ich geändert habe, nur auskommentiert, dadurch wird das Ganze etwas unübersichtlich, dafür siehst Du besser, was ich geändert habe.
Ich habe u. a. kräftig Code verschoben: Das was ich bei Mario reingepackt hätte, ist jetzt dort. Im KeyListener ist auch keine Logic mehr hinterlegt, etc., etc.. 

Wenn Du Mario 1:1 realisieren willst (mit zerstörbaren Ziegelsteinen) ist die von mir gezeigte Vorgehensweise nicht optimal. Du müßtest dann entweder irgendwie noch Objekte generieren oder ganz anders vorgehen.
Für ein einfaches Jump 'n Run tut's der Code aber.

Falls Du Fragen hast,.....


----------



## danthe (9. Dez 2011)

Also das mit der Schattenkarte ist schon mal eine super Idee, auf sowas wäre ich wahrscheinlich nicht gekommen. 
Ich muss mir den Code später mal genauer ansehen, muss leider gleich erstmal weg.


----------



## Lulumann6 (9. Dez 2011)

danthe hat gesagt.:


> Aber dann hätte ich ein Array mit ca. 3000 Einträgen, ist das wirklich die Lösung?
> Edit: Ich könnte die Stellen für Luft doch einfach ganz auslassen und nur die Positionen der Blöcke hinschreiben, oder?



was sind denn schon 3000 bytes. du musst die ja nur einmal von deiner festplatte in den arbeitsspeicher laden und danach musst du ja keine operationen auf das array mehr durchführen. im vergleich bei der schattenlösung lädest du ein 23.764 bytes image in den arbeitsspeicher (was auch kein problem ist)
die schattenlösung halte ich persönlich für nicht optimal, du willst hier schließlich keine pixelgenaue kollision haben, die mariowelt besteht schließlich aus blöcken...
du könntest auch einfach eine liste mit den ganzen positionen deiner blöcke machen, das problem wäre dann nur das mit jedem block kollision überprüfen musst.


----------



## danthe (19. Dez 2011)

So, habe die Sachen angewandt und heute das Programm bei meiner Lehrerin abgegeben. Hoffe auf 15 Punkte.^^
Ich danke euch beiden für die Tipps, das Thema ist eigentlich erledigt. Ich werde wohl noch weiter dran programmieren, zumal die Gegner fehlen, aber auf jeden Fall ist kein Zeitdruck.
Wer will, kann sich den aktuellen Stand des Prgramms anschauen SpeedShare - Download GamePanel.jar
Die Datei habe ich jetzt extern geuploadet, weil die .jars nicht sonderlich groß sein dürfen und alle möglichen Sounds drin sind.
Falls die FPS nicht bei 100 sind oder der PC langsam ist, könnte es sein, dass Mario zu hoch springt etc. 

danthe


----------



## Quaxli (20. Dez 2011)

danthe hat gesagt.:


> ....
> Falls die FPS nicht bei 100 sind oder der PC langsam ist, könnte es sein, dass Mario zu hoch springt etc.
> 
> danthe



Klingt nach einem wilden Konstrukt 
Da wollen wir mal hoffen, daß Deine Lehrerin 100 FPS hat....


----------



## danthe (18. Jan 2012)

So, meine Lehrerin hat das Programm bewertet und ich hab 15 Punkte. 
Hatte ich zwar fast schon erwartet, wenn man mich mit meinen Klassenkameraden vergleicht, aber ich war mir nicht so sicher, obs 14 oder 15 Punkte werden. ^^
Möchte nämlich unbedingt 15 Punkte im Zeugnis.


----------

