Tetris - Spielstein wird nicht dauerhaft angezeigt

  • Antworten:37
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 55

30.04.2018, 23:30:30 via Website

Hallo,
ich wollte eine Tetris App machen.
In einem Timer werden zufällige Steine nach unten bewegt und sie können mit den Tasten gesteuert werden. Aber immer wenn ein Stein unten ankommt und ich einen neuen Stein erstelle, verschwindet der alte Stein. Wie kann ich den alten Spielstein fest an seine Position setzen?
Schonmal Danke im vorraus.

  class  GameLoop extends TimerTask {
    Random random = new Random();

     @Override
    public void run() {

         mainactivity.runOnUiThread(new TimerTask() {

             @Override
             public void run() {
                 spielFeld.nachUnten(SpielStein); // Stein nach unten bewegne
                 if (spielFeld.nachUntenverschiebar(SpielStein) == false) {
                     SpielStein = neuerStein(); // neuen SpielStein erzeugen
                 }
                 invalidate();
             }
         });
     }

public Stein neuerStein() {
    Stein s = new Stein(random.nextInt(7) + 1);
    return s;
 }
}

— geändert am 01.05.2018, 10:48:27 durch Moderator

Diskutiere mit!
Beste Antwort
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 10:51:39 via Website

Hallo,

du darfst den Speilstein (variable) nicht einfach überschreiben:

 SpielStein = neuerStein(); // neuen SpielStein erzeugen

Hier ordnest du der Variable SpielStein einen neuen SpielStein zu, überschreibst damit den vorherigen.
Java merkt das aktivert den GC und schmeißt den alten SpielStein raus, da darauf ja kein Objekt mehr verweist.
Du solltest deine SpielSteine evtl. in einer Liste verwalten. d.h.
bei einem neuen Stein z.b. SteinListe.add(neuerStein());
und dann immer mit dem letzen Element der Liste arbeiten.
Zudem kommt es dann auch noch darauf an, wie du deinen Steine Zeichnest. Wenn du einen Canvas und eine onDraw hast, musst du alle Steine der Liste immer neu Zeichnen, egal ob dieser isvh bewegt oder nicht.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 483

01.05.2018, 10:44:57 via Website

Hallo,
Du müsstest vielleicht den Stein bevor du einen neuen erstellst Speichen. Dazu wäre wohl eine Methode in deiner "SpielFeld Klasse" sinnvoll.
Ich weiß nicht wie deine Klasse aufgebaut ist, auch nicht wie du das Grafisch umgesetzt hast. So das auch Steine dauerhaft angezeigt werden können oder ob deine Grafik immer von neuen gezeichnet wird.

Hilfreich?
Diskutiere mit!
Beste Antwort
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 10:51:39 via Website

Hallo,

du darfst den Speilstein (variable) nicht einfach überschreiben:

 SpielStein = neuerStein(); // neuen SpielStein erzeugen

Hier ordnest du der Variable SpielStein einen neuen SpielStein zu, überschreibst damit den vorherigen.
Java merkt das aktivert den GC und schmeißt den alten SpielStein raus, da darauf ja kein Objekt mehr verweist.
Du solltest deine SpielSteine evtl. in einer Liste verwalten. d.h.
bei einem neuen Stein z.b. SteinListe.add(neuerStein());
und dann immer mit dem letzen Element der Liste arbeiten.
Zudem kommt es dann auch noch darauf an, wie du deinen Steine Zeichnest. Wenn du einen Canvas und eine onDraw hast, musst du alle Steine der Liste immer neu Zeichnen, egal ob dieser isvh bewegt oder nicht.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

01.05.2018, 21:05:59 via Website

Hallo,
ich habe jetzt folgendes versucht, jetzt bewegt sich der Stein aber nicht mehr nach unten:

     @Override
             public void run() {

                if(SteinListe.isEmpty()) {
                    SteinListe.add(neuerStein());
                }

                 spielFeld.nachUnten(aktuellerStein());

                if (spielFeld.nachUntenverschiebar(aktuellerStein()) == false) {
                    SteinListe.add(neuerStein());
                 }
           invalidate();
              }
         });
     }

public Stein aktuellerStein() {
    return SteinListe.get(0);
}

public Stein neuerStein() {
    Stein s = new Stein(random.nextInt(7) + 1);
    return s;
 }

Die Steine zeichne ich auf ein Canvas, in der onDraw() Methode. Wie kann ich den alle Steine von Liste neuzeichnen?

Hilfreich?
Diskutiere mit!
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 21:09:04 via App

deine aktiellerStein Methode ist falsch.
Der aktuelle Stein ist der letzte in der Liste und du liest immer den an der stelle 0 also der 1. stein.
Fur den letzten:

steinListe.get(Steinliste.size()-1);

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

01.05.2018, 21:25:52 via Website

Ok, danke. Jetzt sehe ich unten in der Konsole immer die Koordinaten von den runterfallenden Steinen, aber auf dem Canvas werden sie nicht neugezeichnet

Hilfreich?
Diskutiere mit!
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 21:35:10 via App

Da braucht du eine Schleife über alle Elemente der Liste und dann das Zeichnen für einen Stein.
Also über eine Schleife für alle Zeichen

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

01.05.2018, 21:57:46 via Website

Eine Schleife die überalle Steine läuft hatte ich eben schon wenn du so etwas meinst:

 for(Stein s: SteinListe)  {
                    invalidate();
                }

Aber ich durchlaufe in meiner onDraw() Methode immer das gesamte SpielFeld und wenn der Wert im Array ungleich 0 ist wird an der entsprechenden Stelle ein Rechteck gefüllt. (in der Steinfarbe)

Hilfreich?
Diskutiere mit!
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 21:59:08 via App

Poste mal den Code ich kann das gersde nicht nachvollziehen...

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

01.05.2018, 22:04:28 via Website

Jeder Stein bekommt ja beim erstellen ein zufälligen Farbcode als Integer und jenachdem wie dieser Wert ist wird dann die Farbe gesetzt.

@Override
protected void onDraw(Canvas canvas) {
    int spielfeld[][] = spielFeld.getSpielFeld();

    super.onDraw(canvas);
    Paint p = new Paint();
    p.setColor(Color.BLUE);

    for (int a = 0; a < höhe; a++) {  // canvas(SpielFeld) durchlaufen
        for (int b = 0; b < breite; b++) {

            if (spielfeld[a][b] == 1) {
                p.setColor(Color.RED);
                canvas.drawRect(b*30, a*30, b*30+30, a*30+30,p);
            }
        if(spielfeld[a][b]==2) {
            p.setColor(Color.GREEN);
            canvas.drawRect(b*30, a*30, b*30+30, a*30+30,p); 
        }
      ... alle 7 Farbcodes

         }
      }
   }

— geändert am 01.05.2018, 22:05:25

Hilfreich?
Diskutiere mit!
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 22:09:03 via App

Und was liefert dir getSpielfeld zurück? Also der Code dahinter?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

01.05.2018, 22:17:07 via Website

Das Array aus meiner SpielFeld Klasse, wo die Steine verschoben und gedreht werden

Hilfreich?
Diskutiere mit!
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 22:19:55 via App

In dem Array müssen alle Steine drin sein.
Ohne deinen kompletten Code zu kennen kann ich dir kaum helfen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

01.05.2018, 22:24:04 via Website

Naja der Stein bleibt oben am Rand hängen und fällt nicht runter.
So wie es am Anfang hatte, wo die Steine nur immer überschrieben wurden hat es ja auch geklappt mit dem runterfallen der Steine.

Hilfreich?
Diskutiere mit!
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.169

01.05.2018, 22:51:30 via App

Dann ist irgenso in deiner Spielfeld Klasse ein Logikfehler...

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 483

02.05.2018, 06:18:44 via Website

Mal eine Frage wo werden denn die Steine in das Spielfeld array eingetragen? Ich vermute das da nur ein Stein drin ist. Die getSpielfeld müßte ein array mit mehreren Steinen Rechtecke liefern. Denke das das nicht so ist. Somit kann auf dem Canvas auch nur eins auf dem Feld angezeigt werden.
Wo speicherst du die Steine? Wie sieht die getSpielfeld Methode aus?
Ist die Spielfeld Klasse auch für mehrere Steine ausgelegt?

So wie deine onDraw Methode aufgebaut ist müssen alle Steine in dem spielfeld[][] Array geladen werden.
somit muss die getSpielfeld Methode alle Steine die am boden liegen und die fallenden Steine enthalten.

Welche eigenschaften werden in der Klasse Stein gehalten?
Wo wird die actuelle Position Lage der Steine gepeichert ?
lg J

— geändert am 02.05.2018, 09:30:23

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

02.05.2018, 16:14:58 via Website

Hallo,
In der Steinklasse werden die Koordinaten gespeichert, Abhängig vom Farbcode:

public Stein(int f) {

    switch(f) { // Quadrat Rot
        case 1:
            x1=0; y1=7; x2=0; y2=8;
            x3=1; y3=7; x4=1; y4=8;
            farbcode=1;
            break;

        case 2:    // Z Teil    Blau
            x1=0; y1=7; x2=0; y2=8;
            x3=1; y3=8; x4=1; y4=9;
            farbcode=2;
            break;

....

In der SpielFeld Klasse sind Methoden um den SpielStein zudrehen und zu verschieben, mit dem aktuellen Stein als Parameter. Mit der getSpielFeld() Methode wird das SpielFeld Array zurückgegeben.

 public void löscheStein(Stein SpielStein) {
    SpielFeld[SpielStein.x1][SpielStein.y1] = 0;
    SpielFeld[SpielStein.x2][SpielStein.y2] = 0;
    SpielFeld[SpielStein.x3][SpielStein.y3] = 0;
    SpielFeld[SpielStein.x4][SpielStein.y4] = 0;
 }

— geändert am 02.05.2018, 16:15:36

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 483

02.05.2018, 16:27:45 via Website

Hallo wenn du bei der getSpielfeld Methode dein Spielfeld löschtst kann ja nur ein Stein sichtbar sein. Wenn sie nach unten gefallen sind müssen sie im Spielfeld bleiben. Du willst sie doch Selber löschen wenn eine Reihe voll ist. Wie sieht dein Spielfeld aus?
Wie groß ist eigentlich dein Spielfeld?
Die Breite und Höhe in der ondraw ist wohl die Bildschirm Auflösung?
Wie speicherst du denn wo ein Stein ist und wie weit erfallen kann.

— geändert am 02.05.2018, 16:33:18

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 55

02.05.2018, 16:31:13 via Website

SpielFeld Aray: int SpielFeld[][]=new int[30][30];
Achso, das löschen der Steine ist nur dafür da um sie dann zuverschieben.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 2.902

02.05.2018, 16:47:17 via Website

Eine Randbemerkung :

Für Deinen Fall solltest du besser Dynamische Arrays verwenden ( z.b. ArrayList) .

Und darin kannst du deine Objekte komplett verwalten und darüber hinaus ,musst du nicht
immer die maximale Anzahl deiner Möglichkeiten statisch allociiern .

Das sieht nämlich Android resp. Java gar nicht gerne

Statische Arrays verwendet man eigentlich nicht mehr.

— geändert am 02.05.2018, 16:49:17

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Diskutiere mit!

Empfohlene Artikel