PROCESSING- Layer festlegen und undurchlässige objekte erstellen?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet
ist es möglich das ich verschiedene laye festlege, also das die röhren über dem character liegen, diesen also verdecken?

Ja. Alles hängt von der Reihenfolge ab, in der du zeichnest. Wenn du z.B. einen Punkt P(10/20) zeichnest und danach einen Punkt Q(10/20), überdeckt Letzterer den ersten Punkt bzw. überzeichnet ihn.

wie bekomme ich diese platformen solide?

Mittels Kollisionsabfrage. Wenn der Spieler fällt, muss geprüft werden, ob sich unter ihm eine Plattform befindet. Das heißt, der Spieler muss sich innerhalb eines bestimmten horizontalen Bereichs befinden (den Eckpunkte der Plattform) und die untere Kante des Spielers muss die obere Kante der Plattform berühren. Skizziere es dir ruhig.

Wenn die Anforderung erfüllt ist, muss seine vertikale Bewegung gestoppt werden (Fallgeschwindigkeit = 0 bzw. der y-Wert des Spielers entspricht der Differenz aus obiger Plattformkante und Höhe des Spielers; sofern man von der linken oberen Ecke des Spielervierecks ausgeht).

Damit die Kollisionsabfrage stets möglich ist, solltest du dir die Daten aller Plattformen merken. Eine Helferklasse wäre da ganz praktisch (oder du verwendest dafür PImage).

class Platform {
  int x;
  int y;
  int height;
  int width;

  void draw() {
    rect(x, y, width, height);
  }
}

Von der könnte man dann ein Array anlegen, in dem alle Plattformen gespeichert werden.

Platform[] platforms = new Platform[3];
platforms[0] = new Platform();
platforms[0].width = 100;
print(platforms[0].width);

Für die Kollisionsprüfungen iteriert man über das Array und untersucht jedes Element im Hinblick auf die Lage zum Spieler.

Zuletzt noch bezüglich deines Quellcodes ein paar Ratschläge:

  • Verzichte auf mehrere aufeinanderfolgende Leerzeilen. Du streckst den Code damit nur unnötig.
  • Vergib eindeutige, aussagekräftige Namen für deine Code-Elemente. Der Zweck hinter einer Variable, die nof, f, k oder movel heißt, ist beim Lesen nicht ersichtlich. Der Mix aus Deutsch und Englisch (jump, rohr, mover, rechts) erschwert es zusätzlich.
Grebo 
Fragesteller
 30.12.2021, 13:17

Wow. Vielen Dank für diese super ausführliche Antwort und die Tipps!!

Ich werde es jetzt mal probieren und dann melde ich mich nochmal.

Aber vielen viel Dank schonmal für die Mühe!! :D

0
Grebo 
Fragesteller
 30.12.2021, 20:27

soo Hallo nochmal...

die punkte zur Verbesserung des Quellcodes habe ich schonmal alle umgesetzt und ich kann mich echt schon besser orientieren.. danke!

da wir Class und Array in der schule noch nicht behandelt hatten habe ich mich vorher ein bisschen eigelesen und ein paar einfache dinge dazu ausprobiert, allerdings war ich etwas verwirrt als ich versucht habe das in meinen eigentlichen Code einzubauen.

da bei mir die Platformen png Dateien sind habe ich es mal so versucht:

class Platform {
  int x;               //0
  int y;               //490
  int height;          //56
  int width ;          //260
  PImage platform;

//void setup() {
loadImage ("platform.png"); 
 (da war ich mir nicht sicher ob das hier auch gebraucht wird)

  void draw() {
    image (platform,x,y,width,height);
  }
  }

im Hauptsketch habe ich dann die passenden daten hinzugefügt

 Platform[] platforms;
  platforms = new Platform[2];
  platforms[0] = new Platform();
  platforms[0].width = 260;
  platforms[0].height = 56;


   platforms[1] = new Platform();
  platforms[1].width = 150;
  platforms[1].height = 30;

wir haben von der schule eine Seite gesagt bekommen bei der alle befehle und Funktionen ausführlich erklärt werden, allerdings wurden dort Beispiele verwendet die ich mit meinem vorhaben nicht in Verbindung bringen kann.

ich glaube ich mache den Fehler das ich nicht alles Stück Für Stück lerne, sondern einiges überspringe um schneller zu Ergebnissen zu kommen.

aber egal, was ich fragen wollte ist:

  1. ob das was ich jetzt probiert habe bis dahin richtig ist?
  2. ob ich die PNG Datei für eine Plattform ganz normal bei meinem Code in void draw schreiben kann oder ob ich das auch in (den?!) Array einbauen kann?
  3. ob (der?!) Array in den normalen Quellcode kommt oder in class (Platform)

wenn ich das richtig verstanden habe ist Array ja nur dafür da die daten (also länge breite e.t.c.) von Objekten zu speichern und nicht um diese dann auch zu platzieren.

ich hoffe ich mache ihnen nicht zu viel mühe, ich könnte sonst bestimmt auch bei meinem Lehrer nachfragen wenn wir am 7. wieder schule haben..

und ich hoffe auch das ich nicht alles komplett missverstanden habe, ich widme mich dann die nächsten tage nochmal den ganzen Dingen die ich übersprungen hatte... 😅

0
regex9  30.12.2021, 21:55
@Grebo

Ok, da hätte ich in meiner Antwort mehr erklären müssen.

Die Klasse dient zunächst dazu, einen eigenen Datentyp zu definieren (es ist der Bauplan für den neuen Datentyp). Von dem man dann eigene Instanzen (= Objekte) anlegen kann.

Beispiel:

class Dog {
  boolean isHungry;

  void run() {
    print("run");
  }
}

void setup() {
  Dog odie = new Dog(); // create instance of Dog
  odie.isHungry = true;
  odie.run();
}

Innerhalb einer Klasse kannst du Variablen deklarieren (Fachbegriff: Felder) und Funktionen (Fachbegriff: Methoden) aufführen. Was für und wie viele Felder/Methoden, ist nahezu dir überlassen (also nicht mit den vorgegebenen Funktionen setup/draw verwechseln, ich hätte die Methode in Platform ebenso einfach paint nennen können). Sinnigerweise sollten sie aber zu dem Typ passen, den man da gerade beschreiben möchte. Eine Methode drive wäre bei einer Klasse Dog bspw. ziemlich unlogisch.

Jede Instanz, die du von dem Typ erstellst, hat ihren eigenen Zustand. Das heißt, wenn ich zwei Dog-Instanzen anlege und das Feld eines der beiden im Wert ändere, hat dies nur Einfluss auf diese Instanz. Die andere bleibt davon unberührt, denn sie hat ihren eigenen Zustand.

Dog odie = new Dog();
Dog lassie = new Dog();
odie.isHungry = true;

print(odie.isHungry); // true
print(lassie.isHungry); // false

Wenn du eine Methode einer Instanz aufrufen möchtest, musst du stets die Instanz mit angeben:

odie.run();

Die Definition der Felder kannst du übrigens noch abkürzen, indem du einen Konstruktor definierst. Das ist eine magische Funktion, die beim Anlegen einer Instanz immer aufgerufen wird.

Das obige Beispiel modifiziert:

class Dog {
  boolean isHungry;

  Dog(boolean isHungry) { // constructor
    this.isHungry = isHungry;
  }

  void run() {
    print("run");
  }
}

void setup() {
  Dog odie = new Dog(true); // create instance of Dog
  odie.run();
}

Hinter dem new-Operator wird der Konstruktor aufgerufen. Wenn es in deiner Klasse keine Konstruktordefinition gibt, wird automatisch ein parameterloser Konstruktor generiert. Wenn du einen eigenen Konstruktor definierst, musst du beim Anlegen der Instanz die Parameterliste deines Konstruktors bedienen. Im obigen Snippet wird der neuen Dog-Instanz der Wert true mitgegeben. Dieser Wert wird in den Parameter isHungry gespeichert und im Körper des Konstruktors erfolgt die Zuweisung des Werts an das Feld isHungry. Das this, was du dort siehst, ist ein Schlüsselwort. Es ist ein Platzhalter/Vertreter für die Instanz, die du gerade veränderst (odie). Damit es zu keinen Namensverwechslungen kommt (Parameter und Feld heißen ja beide isHungry), muss das Feld über this angesprochen werden. Alternativ könntest du den Parameternamen auch anders benennen:

Dog(boolean xy) {
  isHungry = xy;
}

Das würde ich aber nur machen, wenn mir für den Parameter ein ordentlicher Name einfallen würde. 😉

Soweit nur eine Kurzerklärung zu Konstruktoren.

Zurück zu den Plattformen. Deine Klasse könnte so aussehen:

class Platform {
  int x;
  int y;
  int height;
  int width;
  PImage spriteImage;

  Platform(int x, int y, int width, int height, String imageSource) {
    this.x = x;
    this.y = y;
    // etc. ...
    spriteImage = loadImage(imageSource);
  }

  void paint() {
    image(spriteImage, x, y, width, height);
  }
}

Die Methode zum Zeichnen habe ich diesmal paint genannt. 😜

Und wenn man dazu nun ein Array mit bspw. zwei Plattformen anlegen möchte:

Platform[] platforms = new Platform[2];

void setup() {
  platforms[0] = new Platform(10, 10, 150, 50, "platform1.jpg");
  platforms[1] = new Platform(200, 120, 100, 50, "platform2.jpg");
}

void draw() {
  for (int index = 0; index < platforms.length; ++index) {
    platforms[index].paint();
  }
}

Das Array wird als globale Variable angelegt und in setup befüllt. In der draw-Funktion wiederum läuft eine Schleife über das Array und ruft je Element (was ja ein Platform-Objekt ist) dessen draw-Methode auf.

Ganz klar möchte ich dazu sagen: Array und Klasse sind nur ein Lösungsvorschlag. Sie ersparen dir etwas Schreibarbeit. Aber wenn du mit diesen Elementen nicht gut zurecht kommst, kannst du das Problem auch nur mit einfachen Variablen lösen.

Der Vorteil der Klasse ist, dass du nicht extrem viele Variablen anlegen musst:

int platform1Width;
int platform1Height;

int platform2Width;
int platform2Height;

// etc. ...

Der Vorteil des Arrays ist, dass du über mehrere Elemente auf einmal via Schleife iterieren kannst, um sie bspw. reihenweise an eine Funktion zu verfüttern, o.ä..

1