Totalausfall bei 2 schleifen

Hi

Sobald ich diese Funktion verwende (benutze ich einmalig in setup) geht nichts mehr:

void spielfeldrand()
{
  for(int x = 0; x < 64; x++)
  {
    for(int y = 0; y < 128; y++)
    {
      if(x == 0 || x == 64 - 1)
      {
        field[x][y] = 1; 
      }
      else if(y == 0 || y == 128 - 1) 
      { 
        field[x][y] = 1; 
      }
      else
      {
        field[x][y] = 0;
      }
    }
  }
}

Wenn ich die Funktion im setup aufrufe:

void setup()
{
  Serial.begin(9600);
  LCD.Initialize();
  Serial.println("Initialized");
  spielfeldrand();
}

sollte ja eigentlich "Initialized" geprintet werden, was es aber komischerweise nicht tut. Irgendwie geht garnichts, wenn ich diese Funktion benutze. Lass ich sie weg, geht alles einwandfrei. Ich hab keine ahnung woran das liegen könnte :confused:
(Habe ein Arduino Uno)
Wäre über schnelle Hilfe sehr erfreut :slight_smile:

MFG, Robdeflop®

64*128 = ?

Hi

Hmm, 8192 ^^
Und daran liegt es? Wie kann ich das Problem lösen? Ich benutze ein 64x128 pixel Display, dafür bräuchte ich das Array.

MFG, Robdeflop®

Nun, irgendwann ist der RAM halt voll. Ein ganzes byte (oder gar int) fuer ein pixel...

Lösungsvorschläge:

  • Externes serielles RAM oder FRAM
  • Da die Variable nur einen binären Zustand hat würde sich eine Abspeicherung des Zustands in einem Bit anbieten. Wenn Du alle Bits einer BYTE Typ Variable nimmst dann kannst Du 8 Bit abspeichern und so den Speicherbedarf auf 1kByte reduzieren und zusätzlich einen ATmega2560 nehmen. Der hat 8kByte an RAM.
    grüße Uwe

Hi

Nein, ich brauche int, da ich nicht nur 1 und 0 benutze, sondern auch 2, 3 und 4, für die Schlange, den Kopf der Schlange und das Futter. (Wird das Spiel Snake)
Dann muss ich wohl entweder das Spielfeld verkleinern oder vier oder mehr Pixel zur darstellung der Sachen nehmen :confused:
Werde aber erstmal das Spielfeld verkleinern.

Danke für eure Hilfe :slight_smile: Vielleicht tritt ja noch ein Problem auf.

MFG, Robdeflop®

Logik umkehren. Also nicht dem Spielfeld sagen wo Objekten liegen, sondern den Objekten sagen wo sie sich auf dem (virtuellen) Spielfeld befinden.

sui:
Logik umkehren. Also nicht dem Spielfeld sagen wo Objekten liegen, sondern den Objekten sagen wo sie sich auf dem (virtuellen) Spielfeld befinden.

Bestätige.
Uwe

Hi

Ich dummerle -.- Frag mich warum ich da nich drauf gekommen bin :confused:
Vielen Dank für den Gedankenanstoß :slight_smile: Werds mal versuchen^^

MFG, Robdeflop®

Robdeflop:
Frag mich warum ich da nich drauf gekommen bin :confused:

Wir wissen zwar viel, aber auf diese Fraga hab auch ich keine Antwort. :wink: :wink: :wink:
Oft verbeist man sich in einen Lösungsweg und denkt gar nicht über andere Möglichkeiten nach...
Grüße Uwe

Hallo zusammen,

da ich ebenfalls ein Snakespiel gebastelt habe, würde mich das ebenfalls interessieren.
So wie ich das aber sehe, kommt man nicht darum herum einmal das gesamte Spielfeld in einem Array darzustellen.
Die Schlange kann theoretisch zum Ende des Spiels das gesamte Feld ausfüllen (die Wahrscheinlichkeit bei 8192 einmal außenvor gelassen), dann wäre die Speicherauslastung die selbe.

Damit die Schlange "um die Ecke" kommt, muss man eben jede Position speichern. Für die Kollisionsabfrage habe ich auch zusätzlich noch den Kopf und das Ende seperat gespeichert. (abgesehen davon muss man ja auch die Laufrichtung bestimmen können)

Generell würde ich mich erstmal fragen wie groß das Spielfeld überhaupt Sinn macht um einen Spielspaß zu gewährleisten. Eine Verkleinerung (oder quasi eine andere Auflösung) würde ich daher empfehlen!

Hi

Es klappt :slight_smile:
Und das ohne dieses fette Array^^
Brauche auch keine Extra definitionen für den Kopf oder das Ende der Schlange, sondern nur eindimensionale Arrays für die X und Y Coordinaten der Schlange und des Essens.
Je größer die Arrays für die Schlange, umso länger kann sie werden, im moment ist die maximale Länge auf 100, werd mal erproben was das beste ist. (werds auf jeden fall noch stark erhähen, das Display hat ja alleine 128 Pixel in der Breite)

Hier der Code:

#include "T6963.h"
#include "gfxdata.h"
#include "Times_New_Roman__14.h"

T6963 LCD(128,64,6,8);// 240x64 Pixel and 6x8 Font

#define HOEHE 64
#define BREITE 128
#define TIMER 200


int Anzahl = 10;
int Richtung = 1;
int snakeX[100], snakeY[100];
int apfelX[3], apfelY[3];

int tasteO = 10;
int tasteR = 11;
int tasteU = 12;
int tasteL = 13;



void setup()
{
  Serial.begin(9600);
  LCD.Initialize();
  Serial.println("Initialized");
  pinMode(tasteO, INPUT);
  pinMode(tasteR, INPUT);
  pinMode(tasteU, INPUT);
  pinMode(tasteL, INPUT);
  
  Rand();
  SnakeInit();
  FoodInit();
  DrawSnake();
}

long zeitvorher = 0;

void loop()
{
  RichtungsAbfrage();
  unsigned long AktuelleZeit = millis();
  
  if(AktuelleZeit - zeitvorher > TIMER)
  {
    Snake();
    
    // Darstellen auf dem Display
    LCD.clearGraphic();
    Rand();
    LCD.setPixel(apfelX[0], apfelY[0]);
    LCD.setPixel(apfelX[1], apfelY[1]);
    LCD.setPixel(apfelX[2], apfelY[2]);
    for(int a = 0; a < Anzahl; a++)
    {
        LCD.setPixel(snakeX[a], snakeY[a]);
    }
    
    Apfel();
    zeitvorher = millis();
  }
}

void DrawSnake()
{
    for(int a = 0; a < Anzahl; a++)
    {
        LCD.setPixel(snakeX[a], snakeY[a]);
    }
}

void Rand()
{
  LCD.createLine(0,0,127,0,1);
  LCD.createLine(0,63,127,63,1);
  
  LCD.createLine(0,0,0,63,1);
  LCD.createLine(127,0,127,63,1);
}

int SnakeInit()
{
    snakeX[0] = 12;
    snakeY[0] = HOEHE / 2;
    snakeX[1] = 11;
    snakeY[1] = HOEHE / 2;
    snakeX[2] = 10;
    snakeY[2] = HOEHE / 2;
    snakeX[3] = 9;
    snakeY[3] = HOEHE / 2;
    snakeX[4] = 8;
    snakeY[4] = HOEHE / 2;
    snakeX[5] = 7;
    snakeY[5] = HOEHE / 2;
    snakeX[6] = 6;
    snakeY[6] = HOEHE / 2;
    snakeX[7] = 5;
    snakeY[7] = HOEHE / 2;
    snakeX[8] = 4;
    snakeY[8] = HOEHE / 2;
    snakeX[9] = 3;
    snakeY[9] = HOEHE / 2;
    Anzahl = 10;
}

void FoodInit()
{
  apfelX[0] = random(BREITE);
  apfelY[0] = random(HOEHE);
  
  apfelX[1] = random(BREITE);
  apfelY[1] = random(HOEHE);
  
  apfelX[2] = random(BREITE);
  apfelY[2] = random(HOEHE);
  
  while(apfelX[0] == apfelX[1] || apfelX[0] == apfelX[2] || apfelX[1] == apfelX[2])
  {
    apfelX[0] = random(BREITE);
    apfelX[1] = random(BREITE);
    apfelX[2] = random(BREITE);
  }
}



void Snake()
{
  for(int i = Anzahl - 1; i > 0; i--)
  {
    snakeX[i] = snakeX[i-1];
    snakeY[i] = snakeY[i-1];
  }
  
  switch(Richtung)
  {
    case 3:
    {
      snakeY[0]--;
      break;
    }
    case 2:
    {
      snakeX[0]--;
      break;
    }
    case 4:
    {
      snakeY[0]++;
      break;
    }
    case 1:
    {
      snakeX[0]++;
      break;
    }
  }
}

char string[10];
int Apfel()
{
    if(snakeX[0] == apfelX[0] && snakeY[0] == apfelY[0])
    {
        Anzahl++;
        apfelX[0] = random(BREITE);
        apfelY[0] = random(HOEHE);
        while(apfelX[0] == apfelX[1] || apfelX[0] == apfelX[2] || apfelX[1] == apfelX[2])
        {
            apfelX[0] = random(BREITE);
        }
        sprintf(string, "%d", Anzahl);
        LCD.TextGoTo(1,1);
        LCD.writeString(string);
    }
    if(snakeX[0] == apfelX[1] && snakeY[0] == apfelY[1])
    {
        Anzahl++;
        apfelX[1] = random(BREITE);
        apfelY[1] = random(HOEHE);
        while(apfelX[0] == apfelX[1] || apfelX[0] == apfelX[2] || apfelX[1] == apfelX[2])
        {
            apfelX[1] = random(BREITE);
        }
        sprintf(string, "%d", Anzahl);
        LCD.TextGoTo(1,1);
        LCD.writeString(string);
    }
    if(snakeX[0] == apfelX[2] && snakeY[0] == apfelY[2])
    {
        Anzahl++;
        apfelX[2] = random(BREITE);
        apfelY[2] = random(HOEHE);
        while(apfelX[0] == apfelX[1] || apfelX[0] == apfelX[2] || apfelX[1] == apfelX[2])
        {
            apfelX[2] = random(BREITE);
        }
        sprintf(string, "%d", Anzahl);
        LCD.TextGoTo(1,1);
        LCD.writeString(string);
    }
}


void RichtungsAbfrage()
{
  if(digitalRead(tasteO) == HIGH)
  {
    Serial.println("Hoch");
    if(Richtung != 4)
    {
      Richtung = 3;
    }
  }

  if(digitalRead(tasteL) == HIGH)
  {
    Serial.println("Links");
    if(Richtung != 1)
    {
      Richtung = 2;
    }
  }

  if(digitalRead(tasteU) == HIGH)
  {
    Serial.println("Runter");
    if(Richtung != 3)
    {
      Richtung = 4;
    }
  }

  if(digitalRead(tasteR) == HIGH)
  {
    Serial.println("Rechts");
    if(Richtung != 2)
    {
      Richtung = 1;
    }
  }
}

Benutze das Display von diesem Modul: http://www.pollin.de/shop/downloads/D120296B.PDF

Im moment kann man aber noch nicht verlieren, das muss ich noch machen. Zudem flackern die Pixel ein wenig, da ich immer das ganze display leere, bevor ich es aktualisiere, das dauert ein wenig zu lange. Werd noch ändern dass die Äpfel und das letzte vorherige Schlangenglied einzeln gelöscht wird, dann sollte es flüssiger sein. Die Geschwindigkeit der Schlange kann man mit dem Define TIMER ändern, 200 ist noch zu lam.

Es sind immer 3 Äpfel gleichzeitig auf dem Display, so ist die wahrscheinlichkeit größer dass in der Nähe ein Apfel ist. Oben links lasse ich mir die Anzahl der Schlangenglieder anzeigen, einfach zur übersicht. Werd das aber noch Rechts an den Rand verlegen und das Spielfeld verkleinern, so kann ich auch noch mehr am rand anzeigen lassen, mal schauen was man noch alles damit machen kann.

MFG, Robdeflop®

Du kannst jedes Schlangenglied ja auch 2x2 Pixel breit machen so ist sie bessere sichtbar und das Spielfeld kleiner.
Grüße Uwe

Hi

Das hatte ich schon erwähnt^^ Aber ich lass es erstmal 1x1, wollte es etwas schwerer haben.
Morgen werde ich den Code denke ich ferig machen und posten, könnt damit machen was ihr wollt.
Hab auch noch überlegt Hindernisse in die Map einzubauen, mal schauen was der Abend so bringt.

MFG, Robdeflop®

Eine mögliche Erweiterung:
Ich hatte früher mal ein Worms-Spiel (meiner Meinung nach das beste was es gab), auf dem 8088 glaube ich, das hatte Portale.
Insgesammt 4 Stück.
Wenn Du in eins rein gegangen bist biste bei einem anderen raus gekommen, abhänging von der Richtung aus welcher Du in das Eingangsportal gegangen bist. Die Portale haben sich dann von Zeit zu Zeit in der Position verändert.

Fand ich zumindest sehr lustig.

PS: Der hatte sogar einen Automatikmodus.
Dabei lief er Zeilenweise das Feld ab und ließ links und rechts eine Spallte frei um dann wieder nach unten zu laufen. So hat er es geschafft erst zu sterben wenn das ganze Feld voll war und er sich selber ins Schwantzende gebissen hat.