Objektorientierte Programmierung anhand Beispiel

Hallo,

ich versuche mich derzeit an einem echten kleinen Projekt mit einem Arduino Uno 3 und einem Display: AsteroidShooter. Schritt 1 soll dabei eine einfache Simulation sein, in der Asteroiden von oben gerade nach unten wandern und dann oben wieder neu positioniert werden.

Ich bin jetzt auf einige Probleme in der OOP gestoßen. Ich sollte vielleicht erwähnen, dass ich aus der bequemen Welt des C#.NET komme.

Der Einfachheit habe das Programm um die Verwendung von Klassen bereinigt und die Daten innerhalb mehrdimensionalen Arrays gehalten.

Klappt leider auch nicht. Der Interpreter wirft mir nebenbei Fehler mit Zeilennummern, die nichts mit der beschriebenen Stelle zu tun haben bzw. höher als die Anzahl an Zeilen in den Dateien o.O

Ich arbeite bei beiden Versuchen sehr intensiv mit folgendem Buch:
http://openbook.rheinwerk-verlag.de/c++

Kann ich bitte einen konkreten Ansatz erhalten, welchen Fehler ich mache?

Für die Anzeige verwende ich folgende Bibliotheken:

Im folgenden meine Codes und die Fehlermeldungen.
asteroid.ino

#include <registers.h>
#include <pin_magic.h>

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library

int particelMovementWith = 10; //Versatz um Pixel bei Bewegung
int particlePositions[10][3][2]; //Partikel->3 Ecken->X;Y
int particleMovements[10][2]; //Partikel->Millisekunden bis Bewegung;Standardzeit

unsigned long _lastMillis = 0;

int tftWidth = 100;
int tftHeight = 100;

/////////////////////////////
//Vorbereitung des Displays//
/////////////////////////////

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).

// Assign human-readable names to some common 16-bit color values:
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

zLogic.ino

void setup()
{
	Serial.begin(9600);
	Serial.println(F("Asteroid"));

  //Display initialisieren
	tft.reset();
	uint16_t identifier = tft.readID();
	tft.begin(identifier);

  //Größe des Displays auslesen
	tftWidth = tft.width();
	tftHeight = tft.height();

  //10 Asteroiden vorbereiten
	for (int particleIndex = 0; particleIndex < 10; particleIndex++)
	{
    //Basisposition, um die die 3 Punkte für das Dreieck ermitteln werden
		int basePosition[2] = { int(random(0, tftWidth)), int(random(-10, 10)) };
    //Die 3 Punkte ermitteln
		//int currentParticle[3][2] = {
    particlePositions[particleIndex] = {
			{ basePosition[0] + int(random(-10, 10)), basePosition[1] + int(random(-10, 10)) },
			{ basePosition[0] + int(random(-10, 10)), basePosition[1] + int(random(-10, 10)) },
			{ basePosition[0] + int(random(-10, 10)), basePosition[1] + int(random(-10, 10)) }
		};
		//*particlePositions[particleIndex] = *currentParticle;
	}

}

void loop()
{
  //Vergangene Zeit seit des letzten Loopbeginns...
	unsigned long milli = millis();
	int passedMillis = int(milli - _lastMillis);

  //Die Asteroiden auf Bewegung und Neupositionierung prüfen.
  //Wenn sich der Asteroid in diesem Loop bewegt, dann wird er neu gemalt.
	for (int particleIndex = 0; particleIndex < 10; particleIndex++)
	{
    //AstteroidenPosition laden
		int particlePosition = particlePositions[particleIndex];
    //Asteroidenzustand zur nächsten Bewegung
		int particleMovement = particleMovements[particleIndex];
    //Wird im nachfolgenden Check auf TRUE gesetzt, wenn der Asteroid unten den Boden berührt.
    bool displaingTriangleExceeded = false;

    //Wenn die Zeit bis zur nächsten Bewegung abgelaufen ist, dann
    // - den Timer wieder auf die Standardzeit setzen
    // - den alten Asteroid schwarz übermalen
    // - prüfen, ob den Asteroid oben neu positionieren
		if (particleMovement[0] <= 0) {
      //Standardzeit
			particleMovement[0] = particleMovement[1];
      
      //altes Dreieck schwarz übermalen
			tft.drawTriangle(
        particlePosition[0][0],
        particlePosition[0][1],
        particlePosition[1][0],
        particlePosition[1][1],
        particlePosition[2][0],
        particlePosition[2][1],
        BLACK
			);
      //Prüfen, ob neu positionieren:
      //Muss neu positioniert werden, wenn ein Punkt am Boden des Displays angekommen ist
      for(int sideIndex = 0; sideIndex < 3; sideIndex++) {
        int particlePositionPoint = particlePosition[sideIndex];

        particlePositionPoint[1] += particelMovementWith;
        if(particlePositionPoint[1] > tftHeight) {
          displaingTriangleExceeded = true;
          break;
        }
      }
      
      //Neue Position ermitteln, wenn unten angelangt
      if(displaingTriangleExceeded){
        int basePosition[2] = { int(random(0, tftWidth)), int(random(-10, 10)) };
        //int currentParticle[3][2]
        particlePositions[particleIndex] = {
          { basePosition[0] + int(random(-10, 10)), basePosition[1] + int(random(-10, 10)) },
          { basePosition[0] + int(random(-10, 10)), basePosition[1] + int(random(-10, 10)) },
          { basePosition[0] + int(random(-10, 10)), basePosition[1] + int(random(-10, 10)) }
        };
        //particlePositions[particleIndex] = currentParticle;
      }
      
      //aktuellen Zustand des Asteroids malen
      tft.drawTriangle(
        particlePosition[0][0],
        particlePosition[0][1],
        particlePosition[1][0],
        particlePosition[1][1],
        particlePosition[2][0],
        particlePosition[2][1],
        WHITE
      );
		}
   
    particleMovement[0] -= passedMillis;
	}

	_lastMillis = milli;
}

Fehlermeldung

Documents\Arduino\asteroid_noObjects\asteroid\zLogic.ino: In function ‘void setup()’:

zLogic:79: error: assigning to an array from an initializer list

}

^

Documents\Arduino\asteroid_noObjects\asteroid\zLogic.ino: In function ‘void loop()’:

zLogic:100: error: invalid conversion from ‘int (*)[2]’ to ‘int’ [-fpermissive]

particlePosition[2][1],

^

zLogic:102: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]

);

^

zLogic:110: error: invalid types ‘int[int]’ for array subscript

[…]

zLogic:160: error: invalid types ‘int[int]’ for array subscript

exit status 1
assigning to an array from an initializer list

asteroid.zip (2.17 KB)

Das hat nur insofern was mit OOP zu tun, als dass in C++ Arrays keine Objekte sind

Du kannst Arrays nur einmal gleich bei der Deklaration mit { } initialisieren. Danach nicht mehr. Sagt der Fehler ja eindeutig aus:

assigning to an array from an initializer list

Genau das geht an der Stelle nicht

Leider sind die angegebenen Zeilennummern ziemlich unbrauchbar, da die IDE erst mal Deinen Sketch in gültiges C++ umwandeln muß (fehlende #include...), bevor sie der Compiler zu sehen bekommt.

Vielleicht hilft es, die Funktionen (unter anderen Namen) in eine *.cpp Datei (zLogic.cpp) zu verschieben, und sie vom Sketch aus aufzurufen. Die *.cpp werden unverändert an den Compiler übergeben, da sollten dann die Zeilennummern der Fehlermeldungen stimmen.

Hallo,

der Thread ist bereits etwas alt, für mich dennoch present. Ich hatte eine Menge Reallife um die Ohren. :wink:

Ich haben den Denkanstoß, Arrays zu initialisieren, umgesetzt und freue mich akutell über ein funktionierendes, simples Asteroid-Spiel auf meinem Arduino mit TFT (im Anhang zu finden).


Wie genau binde ich zLogic als cpp-Datei ein (bzw. wo)?

Ich benötige noch etwas Hilfe beim Einsatz von Referenzen.

Bitte schaut über die !noObjects Version drüber.

Danke euch!!

asteroid_noObjects.zip (574 KB)

asteroid.zip (20.4 KB)