[Résolu] Image et découpage du code

General

chris-scientist

5 years ago

Bonjour,

J'ai un soucis avec mon code et en particulier avec les images.

Quand j'écris le code suivant pas de soucis :

const uint16_t wallData[] = {
      8,8,1, 0, 0, 0, 
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268
    };
  Image wallI = Image(wallData);
  for(uint16_t i=0 ; i<10 ; i++) {
    gb.display.drawImage(i*8, 0, wallI);
  }


En revanche quand j'essaye de découper mon code en plusieurs fichiers comme dans l'exemple suivant j'ai une erreur qui est :

no matching function for call to 'Gamebuino_Meta::Image::drawImage(int, int, Gamebuino_Meta::Image)'


SpritesManager.h

#ifndef SPRITESMANAGER
#define SPRITESMANAGER

#include <Gamebuino-Meta.h>

class SpritesManager {
  private:
    static Image wall;
    static bool wallInitialized;
  public:
    static Image getWall();
};

#endif


SpritesManager.cpp

#include "SpritesManager.h"

bool SpritesManager::wallInitialized = false;

// Récupérer l'image du mur
Image SpritesManager::getWall() {
  if(! SpritesManager::wallInitialized) {
    const uint16_t wallData[] = {
      8,8,1, 0, 0, 0, 
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268
    };
    SpritesManager::wall = Image(wallData);
    SpritesManager::wallInitialized = true;
  }
  return SpritesManager::wall;
}


Lorsque j'écris le code suivant j'obtiens l'erreur décrite plus haut (évidement j'ai bien inclus SpritesManager.h).

for(uint16_t i=0 ; i<10 ; i++) {
    gb.display.drawImage(i*8, 0, SpritesManager::getWall());
  }


Ce que je cherche à effectuer c'est d'instancier qu'une seule fois l'image car elle ne change pas, es-ce possible ?

chris-scientist

NEW 5 years ago

J'ai essayé avec une allocation dynamique soit le code suivant :

SpritesManager.h

#ifndef SPRITESMANAGER
#define SPRITESMANAGER

#include <Gamebuino-Meta.h>

class SpritesManager {
  private:
    static Image* wall;
    static bool wallInitialized;
  public:
    static Image getWall();
};

#endif


SpritesManager.cpp

#include "SpritesManager.h"

bool SpritesManager::wallInitialized = false;

// Récupérer l'image du mur
Image SpritesManager::getWall() {
  if(! SpritesManager::wallInitialized) {
    const uint16_t wallData[] = {
      8,8,1, 0, 0, 0, 
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268
    };
    SpritesManager::wall = new Image(wallData);
    SpritesManager::wallInitialized = true;
  }
  return *SpritesManager::wall;
}


Le reste du code ne change pas.


Mais l'erreur reste la même :

no matching function for call to 'Gamebuino_Meta::Image::drawImage(int, int, Gamebuino_Meta::Image)'

alxm

NEW 5 years ago

The problem is that drawImage takes a reference to an Image object, but when you call it like drawImage(SpritesManager::getWall()) you end up passing the Image by value instead. You need to assign what getWall returns to a variable first, so that there's something to reference when you call drawImage:

Image wall = SpritesManager::getWall();
drawImage(i*8, 0, wall);

For a nicer fix, you could change SpritesManager::getWall (from your first post) to return a reference to the Image instead, then you'll be able to call drawImage(SpritesManager::getWall()) directly without the intermediary variable:

SpritesManager.h

  public:
    static Image& getWall();

SpritesManager.cpp

#include "SpritesManager.h"

Image SpritesManager::wall;
bool SpritesManager::wallInitialized = false;

// Récupérer l'image du mur
Image& SpritesManager::getWall() {
...

Note that for both fix options you also have to define SpritesManager::wall in the CPP file in order to be able to reference it.

chris-scientist

5 years ago

Hello alxm,

I use your solution but my gamebuino draw an other image with differents pixels of my sprites.

Have you an idea ?

chris-scientist

NEW 5 years ago

alxm alxm

Hello alxm,

I use your solution but my gamebuino draw an other image with differents pixels of my sprites.

Have you an idea ?

alxm

5 years ago

When you create an image like SpritesManager::wall = Image(wallData), the library expects the wallData buffer to exist in Flash memory instead of RAM. However, the way you declare wallData places it in RAM, which causes corruption and eventually a crash when the Image object is destroyed.

You need to add the static keyword to place the data buffer in Flash:

if(! SpritesManager::wallInitialized) {
    static const uint16_t wallData[] = {

I can confirm that your test program works on a real Gamebuino after these two fixes, hope this helps.

alxm

NEW 5 years ago

chris-scientist chris-scientist

When you create an image like SpritesManager::wall = Image(wallData), the library expects the wallData buffer to exist in Flash memory instead of RAM. However, the way you declare wallData places it in RAM, which causes corruption and eventually a crash when the Image object is destroyed.

You need to add the static keyword to place the data buffer in Flash:

if(! SpritesManager::wallInitialized) {
    static const uint16_t wallData[] = {

I can confirm that your test program works on a real Gamebuino after these two fixes, hope this helps.

chris-scientist

5 years ago

Thanks for all alxm !

It's a problem of memory.

The complete solution is :

SpritesManager.h

#ifndef SPRITESMANAGER
#define SPRITESMANAGER

#include <Gamebuino-Meta.h>

class SpritesManager {
  private:
    static bool wallInitialized;
    static Image wall;
  public:
    static Image& getWall();
};

#endif

SpritesManager.cpp

#include "SpritesManager.h"

bool SpritesManager::wallInitialized = false;
Image SpritesManager::wall;

// Récupérer l'image du mur
Image& SpritesManager::getWall() {
  if(! SpritesManager::wallInitialized) {
    static const uint16_t wallData[] = {
      8, 8, 1, 0, 0, 0, 
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268
    };
    SpritesManager::wall = Image(wallData);
    SpritesManager::wallInitialized = true;
  }
  return SpritesManager::wall;
}

Code principale

for(uint16_t i=0 ; i<10 ; i++) {
    gb.display.drawImage(i*8, 0, SpritesManager::getWall());
}

jicehel

NEW 5 years ago

Whoua alxm, you have  good level  ;) I don't yet understand all but i see that you do. Thanks for your support

chris-scientist

NEW 5 years ago

alxm alxm

Thanks for all alxm !

It's a problem of memory.

The complete solution is :

SpritesManager.h

#ifndef SPRITESMANAGER
#define SPRITESMANAGER

#include <Gamebuino-Meta.h>

class SpritesManager {
  private:
    static bool wallInitialized;
    static Image wall;
  public:
    static Image& getWall();
};

#endif

SpritesManager.cpp

#include "SpritesManager.h"

bool SpritesManager::wallInitialized = false;
Image SpritesManager::wall;

// Récupérer l'image du mur
Image& SpritesManager::getWall() {
  if(! SpritesManager::wallInitialized) {
    static const uint16_t wallData[] = {
      8, 8, 1, 0, 0, 0, 
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0xacd0,0xacd0,0xacd0,0x5268,0x5268,0xacd0,0xacd0,0xacd0,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0xacd0,0x5268,
      0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268,0x5268
    };
    SpritesManager::wall = Image(wallData);
    SpritesManager::wallInitialized = true;
  }
  return SpritesManager::wall;
}

Code principale

for(uint16_t i=0 ; i<10 ; i++) {
    gb.display.drawImage(i*8, 0, SpritesManager::getWall());
}