Search code examples
c++arrayssfml

The window created by sfml crashes even after a successful compilation


I'm trying to use classes with sfml to have a starting point for a bigger project and I have an issue with my code : it compiles well but when I click the executable, the window closes after ~1s of white. I'll add that I am a beginner in C++ and there is a lot of things about pointer and arrays that I only barely understand thanks to this doc.

I followed this tutorial for the environment setup, and the demonstration script works well, I even tried some things to learn to display other shapes and it works perfectly.

My modified test is about displaying a 2d array which is an attribute of a class I made. The array is supposed to have its size given in the class constructor's parameter, that's why I'm trying to use array of pointers to chars, I've tried multiple things involving going through the array by incrementing a pointer (in this case the window works but nothing is displayed and the cout shows that the color read from the "array" aren't what's they're supposed to be, it has a lot of ' ', a 'H' and a 'B'.

The reason I need this class structure is because I'll try to change the color of individual tiles of the array by clicking on them, again it's to have a starting point for a bigger project.

Here's all the scripts :

Makefile :

main.exe: main.o grid.o
    g++ main.o grid.o -o main -Lsrc\lib -lsfml-graphics -lsfml-window -lsfml-system

main.o: main.cpp
    g++ -Isrc\include -c main.cpp

grid.o: grid.cpp
    g++ -Isrc\include -c grid.cpp

main.cpp :

#include <SFML/Graphics.hpp>
#include "grid.h"

int W = 500, H = 500;

int main()
{
    sf::RenderWindow window(sf::VideoMode(500, 500), "SFML works!");
    grid Grid(5, 4, 'g');

    while (window.isOpen())
    {
        sf::Event evnt;
        while (window.pollEvent(evnt))
        {
            if (evnt.type == sf::Event::Closed)
                window.close();
            else if (evnt.type == sf::Event::Resized)
            {
                sf::FloatRect view(0, 0, evnt.size.width, evnt.size.height);
                window.setView(sf::View(view));
            }
        }

        window.clear();
        Grid.display(&window);
        window.display();
    }

    return 0;
}

grid.h :

#ifndef GRID_H
#define GRID_H

#include <SFML/Graphics.hpp>
#include <vector>

class grid
{
    private:
        int h, w;
        char** colors;
    public:
        grid(const int h, const int w, char defCol);
        void display(sf::RenderWindow* windowPoint);

};

#endif //GRID_H

grid.cpp :

#include "grid.h"
#include <iostream>

grid::grid(const int h, const int w, char defCol)
{
    this->h = h;
    this->w = w;
    char * colorLines [h];

    for (int ii=0; ii<h; ii++){
        char colorLine[w];
        for (int jj=0; jj<w; jj++){
            colorLine[jj] = defCol;
        }
        colorLines[ii] = colorLine;
    }
    colors = colorLines;
}

void grid::display(sf::RenderWindow* windowPoint)
{
    float shapeQ = w/h;
    float pxlW, pxlH;
    sf::Vector2u WinSize(windowPoint->getSize());
    if (WinSize.x/WinSize.y > shapeQ){
        pxlH = WinSize.y/2;
        pxlW = pxlH*shapeQ;
    }
    else {
        pxlW = WinSize.x/2;
        pxlH = pxlW/shapeQ;
    }
    float x0 = (WinSize.x-pxlW)/2, y0 = (WinSize.y-pxlH)/2;

    sf::RectangleShape tile(sf::Vector2f(pxlW, pxlH));
    float deltax = pxlW/w, deltay = pxlH/h;
    for (int x=0; x<w; x++){
        for (int y=0; y<h; y++){
            char color = (colors[y])[x];
            std::cout << "color is " << color << ", ";
            tile.setFillColor(sf::Color::White);
            if (color == 'g'){
                tile.setFillColor(sf::Color::Green);
            }
            else if (color == 'y')
            {
                tile.setFillColor(sf::Color::Yellow);
            }
            else if (color == 'r')
            {
                tile.setFillColor(sf::Color::Red);
            }
            tile.setSize(sf::Vector2f(deltax, deltay));
            tile.setPosition(x0+deltax*x, y0+deltay*y);
            windowPoint->draw(tile);
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

The folder structure of the project is the same as in the tutorial linked higher : a bunch of .dll from SFML, and a src folder with include and lib with everything inside.

I'll also add that I tried to use the debugging tool as advised in other questions but it can't build... It gives a bunch of error looking like undefined reference to `_imp___ZN2sf14RectangleShapeC1ERKNS_7Vector2IfEE'


Solution

  • I found a "working" solution! the attribute 'colors' of the class 'grid' correctly point to a 2d array filled with defCol with this constructor :

    grid::grid(const int h, const int w, char defCol)
    {
        this->h = h;
        this->w = w;
        colors = new char * [h];
        char * colorLine;
    
        for (int y=0; y<h; y++){
            colorLine = new char [w];
            for (int x=0; x<w; x++){
                colorLine[x] = defCol;
            }
            colors[y] = colorLine;
        }
    }
    

    TL.DR : I just learned how to use the keyword 'new'

    PS : The drawing function doesn't work, I checked with the cout.