0

In the past couple SDL2 programs I've been developing the strangest error seems to pop up; whenever I run the program-- after an arbitrary amount of time has passed-- Linux mint freezes. I can't move my mouse or do anything with the computer. My only option at that point is to push the power button until it turns off. I'm using the libraries SDL2 and SDL2_ttf. I assumed this was some type of graphics driver issue (as I've had driver issues in the past), so I updated the graphics driver to xserver-xorg-video-nouveau (open-source). This solved my previous graphics driver issues.

My kernel version is 5.8.10. My GPU is GEforce GT 710. My computer is a dell-inspiron 560

If you need any more information, let me know!

PS: I seriously doubt this is a code issue, considering the consistency of the error throughout several programs, but if you think otherwise please let me know.

Thank you in advance for the help!

EDIT: per request, here is my code. (I'm attempting to make a 2048 ai, as of now the game is incomplete)

main.cpp

#include "board.h"
#include <time.h>

int main(int argc, char* argv[]) {
    srand(time(NULL));

    SDL_Init(SDL_INIT_EVERYTHING);
    TTF_Init();

    SDL_Window* window = SDL_CreateWindow("template", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 276, 276, SDL_WINDOW_RESIZABLE);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    SDL_RenderSetLogicalSize(renderer, 276, 276);

    board b(renderer);
    direction dir;

    bool isFullscreen = false;
    bool running = true;

    Uint64 now = SDL_GetPerformanceCounter();
    Uint64 last = 0;

    double dt = 0;

    while (running) {
        last = now;
        now = SDL_GetPerformanceCounter();
        dt = ((now - last)/(double)SDL_GetPerformanceFrequency());

        dir = none;

        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                running = false;
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym) {
                case SDLK_ESCAPE:
                    running = false;
                    break;
                case SDLK_F11:
                    if (!isFullscreen) SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
                    else SDL_SetWindowFullscreen(window, NULL);
                    isFullscreen = !isFullscreen;
                    break;
                case SDLK_RIGHT:
                    dir = right;
                    break;
                case SDLK_LEFT:
                    dir = left;
                    break;
                case SDLK_UP:
                    dir = up;
                    break;
                case SDLK_DOWN:
                    dir = down;
                    break;
                }
                break;
            }
        }

        b.update(dir);

        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        SDL_RenderClear(renderer);

        b.draw();

        SDL_RenderPresent(renderer);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    TTF_Quit();
    SDL_Quit();
}

block.h

#include <stdlib.h>
#include "texture.h"
#include "rect.h"

class block{
public:
    block(){
        value = 2 * (rand() % 2 + 1);
        switch(value){
        case 2:
            color = {238, 228, 218, 255};
            break;
        case 4:
            color = {237, 224, 200, 255};
            break;
        }
    }
    block(const block &b){
        value = b.value;
        switch(value){
        case 2:
            color = {238, 228, 218, 255};
            break;
        case 4:
            color = {237, 224, 200, 255};
            break;
        case 8:
            color = {242, 177, 121, 255};
            break;
        case 16:
            color = {245, 149, 99, 255};
            break;
        case 32:
            color = {246, 124, 95, 255};
            break;
        case 64:
            color = {246, 94, 59, 255};
            break;
        case 128:
            color = {237, 207, 114, 255};
            break;
        case 256:
            color = {237, 204, 97, 255};
            break;
        case 512:
            color = {237, 200, 80, 255};
            break;
        case 1024:
            color = {237, 197, 63, 255};
            break;
        case 2048:
            color = {237, 194, 46, 255};
            break;
        }
    }
    block operator=(const block &b2){
        value = b2.value;
        switch(value){
        case 2:
            color = {238, 228, 218, 255};
            break;
        case 4:
            color = {237, 224, 200, 255};
            break;
        case 8:
            color = {242, 177, 121, 255};
            break;
        case 16:
            color = {245, 149, 99, 255};
            break;
        case 32:
            color = {246, 124, 95, 255};
            break;
        case 64:
            color = {246, 94, 59, 255};
            break;
        case 128:
            color = {237, 207, 114, 255};
            break;
        case 256:
            color = {237, 204, 97, 255};
            break;
        case 512:
            color = {237, 200, 80, 255};
            break;
        case 1024:
            color = {237, 197, 63, 255};
            break;
        case 2048:
            color = {237, 194, 46, 255};
            break;
        }
        return *this;
    }
    bool operator==(const block &b2){
        return (b2.value == value);
    }
    bool operator!=(const block &b2){
        return (b2.value != value);
    }
    void setVal(int val){
        value = val;
        switch(value){
        case 2:
            color = {238, 228, 218, 255};
            break;
        case 4:
            color = {237, 224, 200, 255};
            break;
        case 8:
            color = {242, 177, 121, 255};
            break;
        case 16:
            color = {245, 149, 99, 255};
            break;
        case 32:
            color = {246, 124, 95, 255};
            break;
        case 64:
            color = {246, 94, 59, 255};
            break;
        case 128:
            color = {237, 207, 114, 255};
            break;
        case 256:
            color = {237, 204, 97, 255};
            break;
        case 512:
            color = {237, 200, 80, 255};
            break;
        case 1024:
            color = {237, 197, 63, 255};
            break;
        case 2048:
            color = {237, 194, 46, 255};
            break;
        }
    }
    int getVal(){ return value; }
    SDL_Color getCol(){ return color; }
private:
    SDL_Color color;
    int value;
};

board.h

#pragma once
#include "block.h"
#include "direction.h"
#include <vector>

class board{
public:
    board(SDL_Renderer* renderer){
        rend = renderer;
        blocks = {
            {NULL, NULL, NULL, NULL},
            {NULL, NULL, NULL, NULL},
            {NULL, NULL, NULL, NULL},
            {NULL, NULL, NULL, NULL},
        };
        vec2 pos1(rand() % 4, rand() % 4);
        blocks[pos1.y][pos1.x] = new block();
        vec2 pos2(rand() % 4, rand() % 4);
        while(pos1 == pos2) { pos2 = vec2(rand() % 4, rand() % 4); }
        blocks[pos2.y][pos2.x] = new block();
    }
    void update(direction d){
        vec2 strt, end, dir;
        if(d == up || d == left){
            strt = vec2(0, 0);
            end = vec2(4, 4);
            dir = vec2(1, 1);
        }
        else if(d == down){
            strt = vec2(0, 3);
            end = vec2(4, -1);
            dir = vec2(1, -1);
        }
        else if(d == right){
            strt = vec2(3, 0);
            end = vec2(-1, 4);
            dir = vec2(-1, 1);
        }
        else return;

        for(int y = strt.y; y != end.y; y += dir.y){
            for(int x = strt.x; x != end.x; x += dir.x){
                if(blocks[y][x]) moveBlock(x, y, d);
            }
        }
        vec2 newPos(rand() % 4, rand() % 4);
        while(blocks[newPos.y][newPos.x]){ newPos = vec2(rand() % 4, rand() % 4); }
        blocks[newPos.y][newPos.x] = new block();
    }
    void draw(){
        SDL_Rect background = {0, 0, 276, 276};
        SDL_SetRenderDrawColor(rend, 73, 68, 63, 255);
        SDL_RenderFillRect(rend, &background);
        for(int y = 0; y < blocks.size(); y++){
            for(int x = 0; x < blocks[y].size(); x++){
                SDL_Rect r = {x * 64 + 4 * (x+1), y * 64 + 4 * (y + 1), 64, 64};
                SDL_Color col;
                text t(50, rend);
                if(blocks[y][x]){
                    t.updateText(std::to_string(blocks[y][x]->getVal()), 50);
                    col = blocks[y][x]->getCol();
                }
                else{
                    col = {80, 76, 71, 255};
                }
                SDL_SetRenderDrawColor(rend, col.r, col.g, col.b, col.a);
                SDL_RenderFillRect(rend, &r);
                t.draw(r.x + 32 - t.getWidth() / 2, r.y + 32 - t.getHeight() / 2);
            }
        }
    }
private:
    std::vector<std::vector<block*>> blocks;
    SDL_Renderer* rend;
    void moveBlock(int x, int y, direction d){
        int dir;
        bool canMove;
        do{
            if(d == left || d == right){
                if(d == left) dir = -1;
                else dir = 1;

                try{
                    bool blockIsNull;
                    bool isSameValue;
                    if(blocks.at(y).at(x + dir)){
                        blockIsNull = false;
                        isSameValue = blocks.at(y).at(x + dir)->getVal() == blocks.at(y).at(x)->getVal();
                    }
                    else{
                        blockIsNull = true;
                        isSameValue = false;
                    }
                    if(blockIsNull || isSameValue){
                        block* b = blocks[y][x];
                        if(isSameValue) if(blocks[y][x + dir]->getVal() == b->getVal()) b->setVal(b->getVal() * 2);
                        blocks[y][x] = NULL;
                        blocks[y][x + dir] = b;

                        x += dir;

                        try{
                            if(blocks.at(y).at(x + dir)){
                                canMove = !blocks.at(y).at(x + dir) || blocks.at(y).at(x + dir)->getVal() == blocks.at(y).at(x)->getVal();
                            }
                            else{
                                canMove = !blocks.at(y).at(x + dir);
                            }
                        }
                        catch(const std::out_of_range& e){
                            canMove = false;
                        }
                    }
                }
                catch(const std::out_of_range& e){
                   canMove = false;
                }
            }
            else if(d == up || d == down){
                if(d == up) dir = -1;
                else dir = 1;

                try{
                    bool blockIsNull;
                    bool isSameValue;
                    if(blocks.at(y + dir).at(x)){
                        blockIsNull = false;
                        isSameValue = blocks.at(y + dir).at(x)->getVal() == blocks.at(y).at(x)->getVal();
                    }
                    else{
                        blockIsNull = true;
                        isSameValue = false;
                    }
                    if(blockIsNull || isSameValue){
                        block* b = blocks[y][x];
                        if(isSameValue) if(blocks[y + dir][x]->getVal() == b->getVal()) b->setVal(b->getVal() * 2);
                        blocks[y][x] = NULL;
                        blocks[y + dir][x] = b;

                        y += dir;

                        try{
                            if(blocks.at(y).at(x + dir)){
                                canMove = !blocks.at(y + dir).at(x) || blocks.at(y+ dir).at(x )->getVal() == blocks.at(y).at(x)->getVal();
                            }
                            else{
                                canMove = !blocks.at(y + dir).at(x);
                            }
                        }
                        catch(const std::out_of_range& e){
                            canMove = false;
                        }
                    }
                }
                catch(const std::out_of_range& e){
                   canMove = false;
                }
            }
            else canMove = false;
        }while(canMove);
    }
};

direction.h

enum direction{
    left,
    right,
    up,
    down,
    none
};

rect.h

#pragma once
#include "vec2.h"
#include <vector>

class rect{
public:
  rect(){
    min = vec2();
    max = vec2();
    w = h = 0;
  }
  rect(double x, double y, double width, double height){
    min = vec2(x, y);
    max = vec2(x + width, y + height);
    w = width;
    h = height;
  }
  void updatePos(vec2 pos){
    min = pos;
    max = pos + vec2(w, h);
  }
  double getWidth(){
    return w;
  }
  double getHeight(){
    return h;
  }
  vec2 getPos(){
    return min;
  }
  rect operator+(vec2 t){
    rect temp = *this;
    temp.updatePos(temp.min + t);
    return temp;
  }
  rect operator-(vec2 t){
    rect temp = *this;
    temp.updatePos(temp.min - t);
    return temp;
  }
private:
  vec2 min;
  vec2 max;
  double w;
  double h;
  friend bool rectVrect(rect r1, rect r2);
  friend bool rectVpt(rect r, vec2 pt);
  friend void drawRect(SDL_Renderer* renderer, rect r);
};

bool rectVpt(rect r, vec2 pt){
  return (pt.x < r.max.x && pt.x > r.min.x && pt.y < r.max.y && pt.y > r.min.y);
}

bool rectVrect(rect r1, rect r2){
  if(r1.max.x < r2.min.x || r1.min.x > r2.max.x) return false;
  if(r1.max.y < r2.min.y || r1.min.y > r2.max.y) return false;
  return true;
}

void drawRect(SDL_Renderer* renderer, rect r){
  SDL_Rect rect = {(int)r.min.x, (int)r.min.y, (int)r.w, (int)r.h};
  SDL_RenderFillRect(renderer, &rect);
}

texture.h

#pragma once
#include <SDL.h>
#include <SDL2/SDL_ttf.h>
#include <iostream>
#include <string>
#include "arial.h"

class text{
public:
  text(int fontSize, SDL_Renderer* rend){
    t = "";
    f = TTF_OpenFont("assets/arial.ttf", fontSize);
    renderer = rend;
    c =  {0, 0, 0};
    textre = NULL;
    w = h = 0;
    destRct.h = h;
    destRct.w = w;
  }
  text(std::string txt, int fontSize, SDL_Renderer* rend){
    t = txt;
    SDL_RWops* fontRW = SDL_RWFromConstMem(arial, 1036584);
    f = TTF_OpenFontRW(fontRW, 0, fontSize);
    renderer = rend;
    c =  {0, 0, 0};
    SDL_Surface* surf = TTF_RenderText_Solid(f, txt.c_str(), c);
    textre = SDL_CreateTextureFromSurface(renderer, surf);
    SDL_QueryTexture(textre, NULL, NULL, &w, &h);
    destRct.h = h;
    destRct.w = w;
    SDL_FreeSurface(surf);
  }
  void draw(int x, int y){
    destRct.x = x;
    destRct.y = y;
    if(textre) SDL_RenderCopyEx(renderer, textre, NULL, &destRct, 0, NULL, SDL_FLIP_NONE);
  }
  void clean(){
    t.clear();
    if(textre) SDL_DestroyTexture(textre);
    destRct.h = destRct.w = 0;
  }
  void updateText(std::string txt, int fontSize){
    TTF_CloseFont(f);
    SDL_RWops* fontRW = SDL_RWFromConstMem(arial, 1036584);
    f = TTF_OpenFontRW(fontRW, 0, fontSize);
    if(textre) SDL_DestroyTexture(textre);
    t = txt;
    SDL_Surface* surf = TTF_RenderText_Solid(f, txt.c_str(), c);
    textre = SDL_CreateTextureFromSurface(renderer, surf);
    SDL_QueryTexture(textre, NULL, NULL, &w, &h);
    destRct.h = h;
    destRct.w = w;
  }
  int getWidth(){ return w; }
  int getHeight(){ return h; }
  SDL_Renderer* getRenderer(){ return renderer; }
  ~text(){
    SDL_DestroyTexture(textre);
  }
private:
  std::string t;
  SDL_Renderer* renderer;
  SDL_Texture* textre;
  SDL_Color c;
  TTF_Font* f;
  SDL_Rect destRct;
  int w, h;
};

vec2.h

#pragma once
#include <SDL.h>

class vec2{
public:
    vec2(){
        x = 0;
        y = 0;
    }
    vec2(double X, double Y){
        x = X;
        y = Y;
    }
  SDL_Point getSDLpoint(){
    SDL_Point p;
    p.x = x;
    p.y = y;
    return p;
  }
    double x;
    double y;
    vec2 operator+(vec2 v){
        return vec2(x+v.x, y+v.y);
    }
    vec2 operator-(vec2 v){
        return vec2(x-v.x, y-v.y);
    }
    vec2 operator*(vec2 v){
        return vec2(x*v.x, y*v.y);
    }
    vec2 operator*(double v){
        return vec2(x*v, y*v);
    }
  vec2 operator/(vec2 v){
        return vec2(x/v.x, y/v.y);
    }
  vec2 operator/(double v){
        return vec2(x/v, y/v);
    }
    vec2 operator+=(vec2 v){
        x += v.x;
        y += v.y;
        return *this;
    }
    vec2 operator-=(vec2 v){
        x -= v.x;
        y -= v.y;
        return *this;
    }
    vec2 operator*=(vec2 v){
        x *= v.x;
        y *= v.y;
        return *this;
    }
    vec2 operator*=(double v){
        x *= v;
        y *= v;
        return *this;
    }
  vec2 operator/=(vec2 v){
        x /= v.x;
        y /= v.y;
        return *this;
    }
  vec2 operator/=(double v){
    x /= v;
    y /= v;
    return *this;
  }
  bool operator==(vec2 v){
      return (v.x == x && v.y == y);
  }
  bool operator!=(vec2 v){
      return (v.x != x || v.y != y);
  }
};
Jcsq6
  • 103
  • 4
  • I was also having the same problem but there was problem with my code. Can you share your code here? – Kapil Sep 21 '20 at 05:21
  • @Kapil I added the code, although I don't see how that could be a problem... however I am still new so I am probably wrong – Jcsq6 Sep 21 '20 at 13:28

0 Answers0