在我开发的过去几个 SDL2 程序中,似乎出现了最奇怪的错误;每当我运行该程序时(经过任意时间后),Linux mint 就会冻结。我无法移动鼠标或对计算机进行任何操作。此时我唯一的选择就是按下电源按钮直到它关闭。我正在使用库 SDL2 和 SDL2_ttf。我假设这是某种类型的图形驱动程序问题(因为我过去遇到过驱动程序问题),所以我将图形驱动程序更新为 xserver-xorg-video-nouveau(开源)。这解决了我之前的图形驱动程序问题。
我的内核版本是 5.8.10。我的 GPU 是 GEforce GT 710。我的电脑是 dell-inspiron 560
如果您需要更多信息,请告诉我!
附言:考虑到错误在多个程序中的一致性,我严重怀疑这是一个代码问题,但如果您有其他想法,请告诉我。
提前感谢您的帮助!
编辑:根据要求,这是我的代码。(我正在尝试制作 2048 ai,但目前游戏尚未完成)
主程序
#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();
}
块
#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;
};
董事会
#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);
}
};
方向.h
enum direction{
left,
right,
up,
down,
none
};
矩形
#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);
}
纹理.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);
}
};