Question

C++ (Arduino wrapper) question: I'm writing a shoot em up game on an Arduino which has a LCD connected -

I have a base class (Sprite), and from this other classes are derived - Alien, Missile and Player. The constructor of the Alien class also has private member pMissile (a pointer to a Missile class) - 'an object within an object' would be a way to describe this I think. [when an Alien fires a missile, it passes its own (x,y) coordinates to the missile, and the missile has its own method of moving starting from the Alien's coordinates]

My question is: How can I access the coordinates of the missile through the Alien object? Streamlined code is below and I have also drawn a representation of the classes:

// Bass class - has a form/shape, x and y position  
class Sprite
{
  public:
    Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
    virtual void Move() = 0;
    void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
    unsigned int getX()    const { return x; } 
    unsigned int getY()    const { return y; }
  protected:
    unsigned char *spacePtr;
    unsigned int x, y;
};


// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
class Missile : public Sprite
{
public:
   Missile(): Sprite(&spaceMissile[0], 0, 0) {}
   virtual void Move();  // its own method of moving
};

// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
   Alien(); 
   virtual void Move();   // its own method of moving
private:
   Missile *pMissile;
};

Alien::Alien(): Sprite(&spaceAlien[0], random(5, 75), random(4, 10))
{
  Missile MissileArray[MaxAmmoSize];
  pMissile = &MissileArray[0];
}


void Alien::Move()
{ 
  if( random(10) % 2 == 0 )
    x += 1;
  if( random(10) % 3 == 0 )
    y += 1;

  if( (pMissile != NULL) && (random(10) == 1) )
  {
    pMissile->setCoord(x, y);
    pMissile->Move();  // move the missile   
    pMissile++;        // move onto the next missile in the array
  }
  Render();
}

/*****************************************************************************************/
Alien MONSTER;
Player HERO;
Alien *pMONSTER = &MONSTER;

void loop()
{
  display.clearDisplay();
  MONSTER.Move();
  HERO.Move(); 
  pMONSTER->getX(); // this is x location of MONSTER
  **// how does pMONSTER access pMissile(x,y) within MONSTER.** 
  delay(100);
  display.display();
}

enter image description here

Embedded C++ Class interaction

Was it helpful?

Solution

The common way is to add a getter function to Alien:

class Alien {
public:
    Missile* getMissile() { return pMissile; }
}

To use it:

Alien* a = getAlienFromSomewhere();
auto pMissile = a.GetMissile();
if (pMissile != NULL) {
    x = pMissile->getX();
    y = pMissile->getY();
}

OTHER TIPS

I imagine that you want to access your missile position through the alien to test the collision with your hero entity, but if you need to keep the track of your missiles you should not "walk" with your pointer to the next missile as shown in the Alien::Move(). Doing this you will lose the reference of the beginning of the array.

IMHO, I would do something like this in your alien class:

// Bass class - has a form/shape, x and y position  
class Sprite
{
  public:
    Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
    virtual void Move() = 0;
    void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
    unsigned int& getX()    const { return x; } 
    unsigned int& getY()    const { return y; }
  protected:
    unsigned char *spacePtr;
    unsigned int x, y;
};


// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
class Missile : public Sprite
{
public:
   Missile(): Sprite(&spaceMissile[0], 0, 0) {}
   virtual void Move();  // its own method of moving
};

// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
   Alien(); 
   ~Alien(); // a destructor to cleanup your missiles - arduino have almost no memory to handle leaks ;-) 
   virtual void Move();   // its own method of moving

   inline Missile& getMissile(unsigned char n) { return pMissile[n];          }
   inline Missile& operator[](unsigned char n) { return getMissile(n);        }
   inline unsigned int& getX(unsigned char n)  { return getMissile(n).getX(); }
   inline unsigned int& getY(unsigned char n)  { return getMissile(n).getY(); }

private:
   Missile *pMissile;
   // adding the code to handle the count
   unsigned char missileCount;
};

Alien::Alien(): 
  Sprite(&spaceAlien[0], random(5, 75), random(4, 10)),
  missileCount(0)
{
  // this way of allocation creates a local object that is destroyed by the end of this scope
  //Missile MissileArray[MaxAmmoSize];
  //pMissile = &MissileArray[0];

  // so you should do somethin like this
  pMissile = new Missile[MaxAmmoSize];
}

Alien()::~Alien()
{
  delete[] pMissile;
}

void Alien::Move()
{ 
  if( random(10) % 2 == 0 )
    x += 1;
  if( random(10) % 3 == 0 )
    y += 1;

  if( (pMissile != NULL) && (random(10) == 1) )
  {
    // my proposal to fire it up
    Missile& missile = pMissile[missileCount];
    missile->setCoord(x, y);
    missile->Move();  // move the missile   
    missileCount++;   // move onto the next missile in the array
  }
  Render();
}

Using the code like this you could access the locations of your missiles by using:

MONSTER.getX(0) += 1;
MONSTER[0].getY() +=1;
MONSTER.getMissile(1).getX() = 10;

To have some clarity I recommend also the refactoring of the getX() and getY() methods to x() and y(), since they are returning references to the class contents (and doing this, you should also rename your x and y members to something else, or you can get crazy with name conflicts).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top