2017-04-03 4 views
-1

Je fais une demande à l'aide SDL2 qui est destiné à afficher des graphiques dans des fenêtres séparées. Pour ce faire, j'ai une classe appelée figure avec l'en-tête suivant:(SDL2) Laisser un objet rendu lui-même donne écran noir

class figure 
{ 
private: 
    short window_width; 
    short window_height; 
    SDL_Window* window = NULL; 
    SDL_Renderer* renderer = NULL; 
    SDL_Event fig_handler; 
public: 
    figure(short fig_typ); 
    void render(); 
    short figure_type; 
}; 

Et la mise en œuvre suivante:

figure::figure(short fig_typ) 
{ 
    window_width = 840; 
    window_height = 680; 
    window = SDL_CreateWindow("Demo Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_SHOWN); 
    if (window==NULL) 
    { 
     std::cout << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; 
    } 

    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); 
    if (renderer==NULL) 
    { 
     std::cout << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; 
    } 

    // Set default colour to turquise 
    SDL_SetRenderDrawColor(renderer, 45, 164, 132, SDL_ALPHA_OPAQUE); 

    figure_type = fig_typ; 
} 

void figure::render() 
{ 
    while (SDL_PollEvent(&fig_handler)) 
    { 
     if (fig_handler.type == SDL_QUIT) 
     { 
      // Do things here 
     } 
    } 
    SDL_RenderClear(renderer); 
    SDL_RenderPresent(renderer); 
    SDL_Delay(0); 
} 

tout cela fonctionne plutôt bien. Je peux juste écrire while (true) {fig1.render();} et une fenêtre turquoise restera allumée jusqu'à ce que je ferme le programme. Mais dans mon programme, je veux que plusieurs de ces chiffres coexistent, et pour simplifier le processus, j'ai décidé de faire un nouveau modèle de classe pour garder une trace des chiffres.

L'en-tête:

class model 
{ 
public: 
    model(); 
    void add_figure(short index, short fig_typ); 
    bool update(); 
private: 
    std::map<short, figure*> figure_map; 
}; 

La mise en œuvre:

model::model() 
{ 
    // Initialize SDL 
    if(SDL_Init(SDL_INIT_VIDEO) < 0) 
    { 
     std::cout << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; 
    } 
} 

void model::add_figure(short index, short fig_typ) 
{ 
    figure tempFigure(fig_typ); 
    std::pair<short, figure*> tempPair(index, &tempFigure); 
    figure_map.insert(tempPair); 
} 

bool model::update() 
{ 
    for (std::map<short, figure*>::iterator it = figure_map.begin(); it != figure_map.end(); ++it) 
    { 
     it->second->render(); 
    } 
    return true; 
} 

Et mystérieusement, quand je crée un modèle d'objet et lui donner un chiffre, et ensuite appeler while (true) {model_object.update();}, la fenêtre devient noire. Lorsque je supprime la gestion des événements de l'objet figuré (comme je l'avais initialement prévu), SDL ne prend même pas la peine de créer une belle fenêtre: je n'ai qu'une fenêtre blanche ou noire floue, selon les parties de la manipulation que je supprime.

Il semble que SDL ne prend même pas le temps de bien rendre tout. Un autre StackOverflow post a suggéré d'ajouter SDL_Delay (0) quelque part le long des lignes pour faire SDL reprendre son souffle (comme vous pouvez le voir, je l'ai mis dans la figure :: render()), mais jusqu'à présent, il ne fait pas de différence.

Que puis-je faire pour rendre ma fenêtre comme il est censé, mais toujours de maintenir cette structure: une structure dans laquelle un objet appelle une fonction d'un autre objet pour dessiner la fenêtre.

P.s. Je travaille à partir d'un ordinateur portable avec MacOS, et la compilation en utilisant g ++.

Répondre

1

Dans la figure :: vous rendre vous faites ceci:

SDL_RenderClear(renderer); 
SDL_RenderPresent(renderer); 

Vous êtes effacer le moteur de rendu avant de le présenter à l'écran, et donc il est noir. Changez juste l'ordre ici.

+0

Je crains que cela ne fonctionne pas. Quand je change la commande, le programme affiche exactement le même comportement. Effacer d'abord dans SDL2 est destiné à remplir tout le moteur de rendu avec la dernière couleur sélectionnée (turquoise dans mon exemple). C'est l'ordre dans lequel tous les programmes de démonstration fonctionnent (et l'ordre qui fonctionne bien avant d'introduire la classe du modèle). – Heatherfield

0

Vous prenez le pointeur à la variable temporaire et l'enregistrer dans une carte. Une fois que le flux d'exécution quitte cette fonction, cette adresse ne contient plus de données valides et ne peut plus être accédée de manière fiable. Soit utiliser par ex. new ou (mieux) rendre vos objets copiables.

+0

A travaillé comme un charme, en utilisant le nouveau mot-clé. Que voulez-vous dire exactement en rendant l'objet copiable? Voulez-vous dire copier l'objet entier dans la carte std :: map? – Heatherfield

+0

Oui, en rendant l'objet de maintien de carte lui-même (au lieu de pointeur), car l'objet n'est pas trop lourd dans ce cas, et la copier est beaucoup moins cher que 'new'. Vous devez être prudent avec le constructeur/destructeur si. – keltar