Sign in to follow this  

[C++]invalid initializer

This topic is 4214 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm experimenting a little with classes and i've bumped into a wall. gfx.h
#define MAX_PLAYERS 12

class gfx{
  public:
    (functions)
  private:
    static SDL_Surface *sprite[MAX_PLAYERS];
    static SDL_Rect rcSprite[MAX_PLAYERS];
};



gfx.cpp
#include "gfx.h"
SDL_Surface* gfx::sprite[MAX_PLAYERS]=NULL;
SDL_Rect gfx::rcSprite[MAX_PLAYERS]={0,0,0,0};

(functions)



Error: invalid initializer so basicly i'd like to know how to initialize array of data. ty.

Share this post


Link to post
Share on other sites
You can allocate memory for sprite in run-time like this:

private:
SDL_Surface *sprite;

sprite = new SDL_Surface[MAX_PLAYERS];

Share this post


Link to post
Share on other sites
Or, better:
#include <vector>

const int MAX_PLAYERS = 12;

class gfx
{
public:
(functions)
private:
static std::vector<SDL_Surface*> sprites;
static std::vector<SDL_Rect> rcSprites;
};




#include "gfx.h"

std::vector<SDL_Surface*> gfx::sprites(MAX_PLAYERS, NULL);
std::vector<SDL_Rect> gfx::rcSprites(MAX_PLAYERS, SDL_Rect(0,0,0,0));




I assume that SDL_Rect does have a 4-element constructor. However, since here you simply want zeroed-out values, you don't have to specify an intialization element: std::vector will do it for you by default:

#include "gfx.h"

std::vector<SDL_Surface*> gfx::sprites(MAX_PLAYERS);
std::vector<SDL_Rect> gfx::rcSprites(MAX_PLAYERS);








Your problem is that C++ doesn't provide a way to specify how array elements should be initialized "by default", short of actually putting the elements yourself. For your pointer array, you can cheat a bit and write SDL_Surface* gfx::sprite[MAX_PLAYERS]= { NULL };, which is equivalent to SDL_Surface* gfx::sprite[MAX_PLAYERS]= { NULL, 0, 0, 0, 0, more zeros }; and NULL is conveniently zero too. When an array is "partially initialized", C fills the remaining missing values with zeros.

Share this post


Link to post
Share on other sites
To add to that: The {0,0,0,0} thingy is an initializer for arrays and POD structs. It has nothing to do with SDL_Rect specifically. Since you have an *array of* pointers to SDL_Surfaces, you would need to initialize it as an array, specifying null pointers for the array elements. (As it happens, you can shortcut this in the way that Fruny illustrates).

But again as Fruny illustrates, you should generally avoid arrays; they like to prey on n00bs and often aren't really helpful for experienced coders either.

Share this post


Link to post
Share on other sites
okay, i've made it to work with Fruny's suggestion.
but i'd like to try with dynamic allocation now.
so i'm having some troubles again(naturally):

gfx.h

public:
static void Init();
protected:
static void LoadSprite(char PlayerID, char SpriteID);
private:
static SDL_Surface *LoadIMG(char *image_path);

static SDL_Surface *sprite;
static SDL_Rect rcSprite;






gfx.cpp

void gfx::Init()
{
sprite= new SDL_Surface [MAX_PLAYERS];
}

void gfx::LoadSprite(char PlayerID, char SpriteID)
{
switch(SpriteID){
case 0:
sprite[PlayerID] = LoadIMG( "gfx/sprite/0.PNG" ); //line 67
break;
case 1:
sprite[PlayerID] = LoadIMG( "gfx/sprite/1.PNG" );
break;
case 2:
sprite[PlayerID] = LoadIMG( "gfx/sprite/2.PNG" );
break;
case 3:
sprite[PlayerID] = LoadIMG( "gfx/sprite/3.PNG" );
break;
case 4:
sprite[PlayerID] = LoadIMG( "gfx/sprite/4.PNG" );
break;
case 5:
sprite[PlayerID] = LoadIMG( "gfx/sprite/5.PNG" );
break;
case 6:
sprite[PlayerID] = LoadIMG( "gfx/sprite/6.PNG" );
break;
case 7:
sprite[PlayerID] = LoadIMG( "gfx/sprite/7.PNG" );
break;
default:
fprintf(stderr, "SpriteID(%d) not in range(0-7)",SpriteID);
}
}

SDL_Surface* gfx::LoadIMG(char *image_path)
{
//The image that's loaded
SDL_Surface *loadedImage=NULL;
//The optimized image that will be used
SDL_Surface *optimizedImage=NULL;
//Load the image
loadedImage = IMG_Load( image_path );
//Create an optimized image
optimizedImage = SDL_DisplayFormat( loadedImage );
//Map the color key
Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0xFF, 0xFF, 0xFF );
//Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent
SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey );
//Free the old image
SDL_FreeSurface( loadedImage );

return optimizedImage;
}






Error:

Game/gfx.cpp: In static member function `static void gfx::LoadSprite(char, char)':
Game/gfx.cpp:67: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/0.PNG")))'

include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:70: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/1.PNG")))'
include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:73: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/2.PNG")))'

include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:76: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/3.PNG")))'
include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:79: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/4.PNG")))'

include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:82: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/5.PNG")))'
include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:85: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/6.PNG")))'

include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)
Game/gfx.cpp:88: error: no match for 'operator=' in '*((+(((unsigned int)PlayerID) * 60u)) + gfx::sprite) = gfx::LoadIMG(((char*)((const char*)"gfx/sprite/7.PNG")))'
include/SDL/SDL_video.h:88: note: candidates are: SDL_Surface& SDL_Surface::operator=(const SDL_Surface&)





EDIT: oh, and i have a "delete[] sprite;" in some other method.

Share this post


Link to post
Share on other sites
header:

public:
static void Init();
protected:
static void LoadSprite(char PlayerID, char SpriteID);
private:
static SDL_Surface *LoadIMG(char *image_path);

// you want a pointer (the dynamic array) of pointers (the SDL surfaces)
static SDL_Surface **sprite;
// here you want a dynamic array of rects, which is actually a pointer, too
static SDL_Rect *rcSprite;




source:

void gfx::Init()
{
sprite= new SDL_Surface * [MAX_PLAYERS];
rcSprite = new SDL_Rect[MAX_PLAYERS];
}

void gfx::LoadSprite(char PlayerID, char SpriteID)
{
if ( SpriteID >= 0 && SpriteID < 8 ) {
std::stringstream ss;
ss << "gfx/sprite/" << static_cast<int>(SpriteID) << ".PNG";
sprite[PlayerID] = LoadIMG( ss.str().c_str() );
}
else std::cerr << "SpriteID(" << static_cast<int>(SpriteID) << ") not in range(0-7).\n";




HTH,
Pat

Share this post


Link to post
Share on other sites
ok, now i have some new problems regarding dynamically allocating the sprites.

the problem is that i don't know how to allocate _new_ sprites and not override the old "new" sprite.


sprite= new SDL_Surface*;

char imagePath[18];
sprintf(imagePath, "gfx/sprites/%1d.PNG" ,SpriteID);
*sprite = LoadIMG( imagePath );



this function is called twice right on the beginning and after the second call the sprite[0] has the image of the second call, while sprite[1] doesn't exist.

now, it should be like this: after the 1st call the image should be saved in sprite[0], and after the 2nd call the image should be saved in sprite[1].

and a side(relevant) question:

rcSprite= new SDL_Rect;
rcSprite->x = newX;
rcSprite->y = newY;



how could i access rcSprite[0].x or rcSprite[1].x?

thank you!

Share this post


Link to post
Share on other sites
Quote:
Original post by theSecondt
ok, now i have some new problems regarding dynamically allocating the sprites.

the problem is that i don't know how to allocate _new_ sprites and not override the old "new" sprite.

*** Source Snippet Removed ***

this function is called twice right on the beginning and after the second call the sprite[0] has the image of the second call, while sprite[1] doesn't exist.

now, it should be like this: after the 1st call the image should be saved in sprite[0], and after the 2nd call the image should be saved in sprite[1].


The LoadIMG function returns SDL_Surface*'s. So you want to allocate an array of SDL_Surface*'s.

A call to either new or new[] returns a pointer-to- whatever type of thing you're allocating. So it will return an SDL_Surface**, which points at the beginning of the array, assuming you allocate an array.

Then, you set each pointer in the array to the result of a LoadIMG call.

Also, don't use sprintf() for that. C++ provides much nicer tools for string manipulation.


sprite = new SDL_Surface*[NUM_SPRITES];
// Load each sprite in a loop
for (int i = 0; i < NUM_SPRITES; ++i) {
stringstream ss("gfx/sprites/");
ss << i << ".PNG";
sprite[i] = LoadIMG(ss.c_str());
}


Quote:

and a side(relevant) question:
*** Source Snippet Removed ***

how could i access rcSprite[0].x or rcSprite[1].x?

thank you!


Again, you would have to make an array allocation, but then you just do it with the syntax you expect. The array indexing is equivalent to pointer arithmetic upon the pointer returned by new[].

Share this post


Link to post
Share on other sites
Neverminding everything else, the basic structure of the code seems wrong: If you've got a bunch of players, each with their own sprite or whatever, why don't you have something like this?


class cPlayer
{
public:
cPlayer(int playerId) : mPlayerId(playerId) {};
void LoadSprite(void)
{
// Details of loading the sprite here
}

private:
const int mPlayerId;
SDL_Surface *mSprite; // Or use a smart pointer for this...
SDL_Rect mR; // Come up with a more descriptive name for this var
};

class cGame
{
private:
vector<cPlayer *> players;
};


Generally speaking, if you're using the static keyword during the course of normal programming, you're doing something wrong.

The important change between the original code and this example is that, instead of having one centralized class that reaches into the particulars of classes it's supposed to be managing, it encapsulates the knowledge of how to "be a player" into the player class.

Share this post


Link to post
Share on other sites
Sign in to follow this