What Causes SDL_Renderer to be invalid? - c++

I'm trying to make a 2D game where the background is a hockey rink. The error handler said the Render-er didn't initialize thus making the texture not initialize. I know the BMP loads because I don't get an error for that. Don't worry about the camera stuff. The background is supposed to scroll. I just need the background to render. The code may not be the best, but corrections are always appreciated.
#include <SDL/SDL.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int fps = 60;
SDL_Window *window;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
int x = 0, y = 0;
SDL_Surface *screen;
SDL_Surface *background = SDL_LoadBMP("hockeyrink.bmp");
if(background == NULL)
{
SDL_ShowSimpleMessageBox(0, "Background init error", SDL_GetError(), window);
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
SDL_ShowSimpleMessageBox(0, "Renderer init error", SDL_GetError(), window);
}
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,background);
if(texture == NULL)
{
SDL_ShowSimpleMessageBox(0, "Texture init error", SDL_GetError(), window);
}
const int speed = 5;
SDL_Rect camera;
camera.x = 0;
camera.y = 0;
camera.w = 800;
camera.h = 600;
bool b[2] = {0,0};
Uint32 start;
window = SDL_CreateWindow("", 300, 100, 1024, 800, SDL_WINDOW_OPENGL);
if (window == NULL)
{
cout << ("could not create window: %s/n", SDL_GetError());
return 1;
}
bool running = true;
while (running)
{
start = SDL_GetTicks();
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running = false;
SDL_DestroyTexture(texture);
SDL_FreeSurface(background);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=1;
break;
case SDLK_LEFT:
b[1]=1;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=0;
break;
case SDLK_LEFT:
b[1]=0;
break;
}
break;
}
}
if(b[0])
{
x+=speed;
camera.y+=speed;
if (camera.y > 3000-800)
{
camera.y=0;
}
}
else if(b[1])
{
x-=speed;
camera.y-=speed;
if (camera.y <= 0)
{
camera.y = 2000-800;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
if(1000/fps>SDL_GetTicks()-start)
{
SDL_Delay(1000/fps-(SDL_GetTicks() - start));
}
}
return 0;
}

When you create renderer, the window pointer does not point to anything(i.e. it is uninitialized).
You must create the window before creating the renderer.
So put the lines:
window = SDL_CreateWindow("", 300, 100, 1024, 800, SDL_WINDOW_OPENGL);
if (window == NULL)
{
cout << ("could not create window: %s/n", SDL_GetError());
return 1;
}
before the line: SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);

Related

Texture not displaying SDL2 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 months ago.
Improve this question
I'm trying to make a game in C++ with SDL2, and I can't even get a texture displaying. SDL_GetError() returns nothing.
I'm on a windows 10 pro using Visual Studio.
Here are my 3 files:
main.cpp
#include "Classes.h"
int MouseX = 0;
int MouseY = 0;
int PlayerX = 0;
int PlayerY = 0;
SDL_Renderer* renderer;
Tile tile = Tile({10, 10, TileTypes::Tile_Grass}, renderer);
EventReturns HandleEvent(SDL_Event* event) {
switch (event->type) {
case SDL_QUIT:
return EventReturns::Event_QUIT;
case SDL_KEYDOWN:
switch (event->key.keysym.sym) {
case SDLK_ESCAPE:
return EventReturns::Event_TryQuit;
default:
return EventReturns::Event_None;
}
default:
return EventReturns::Event_None;
}
}
int mainLoop(EventReturns eventReturn) {
SDL_GetMouseState(&MouseX, &MouseY);
if (eventReturn == EventReturns::Event_QUIT || eventReturn == EventReturns::Event_TryQuit) {
return 1;
}
return 0;
}
void render() {
SDL_SetRenderDrawColor(renderer, 100, 200, 200, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
tile.SetPos(0, 0);
if (tile.Draw(renderer) != 0) {
SDL_ShowSimpleMessageBox(0, "ERROR", "ERROR: Rect in tile has 0x0 size, Please close this with the task manager", NULL);
}
SDL_RenderPresent(renderer);
}
int main(int argc, char* argv[]) {
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 2880, 1600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
bool running = true;
EventReturns eventReturn = EventReturns::Event_None;
SDL_Event event;
int quit = 0;
while (running) {
while (SDL_PollEvent(&event)) {
eventReturn = HandleEvent(&event);
}
quit = mainLoop(eventReturn);
render();
if (quit == 1) {
running = false;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Classes.h
#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
#define SpriteSizeMult 1
enum class EventReturns {
Event_QUIT,
Event_None,
Event_TryQuit
};
enum class TileTypes {
Tile_Grass
};
struct TileStruct {
int x;
int y;
TileTypes type;
};
class Tile {
public:
Tile(int x, int y, char* TexturePath, SDL_Renderer* renderer);
Tile(TileStruct structure, SDL_Renderer* renderer);
Tile();
int Draw(SDL_Renderer* renderer);
void SetPos(int x, int y);
private:
int x = 0;
int y = 0;
int TextureWidth = 0;
int TextureHeight = 0;
SDL_Texture* texture;
SDL_Rect rect;
};
SDL_Point getsize(SDL_Texture* texture);
Classes.cpp
#include "Classes.h"
SDL_Point getsize(SDL_Texture* texture) {
SDL_Point size;
SDL_QueryTexture(texture, NULL, NULL, &size.x, &size.y);
return size;
}
Tile::Tile(int x, int y, char* TexturePath, SDL_Renderer* renderer)
{
this->x = x;
this->y = y;
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load(TexturePath));
if (this->texture == nullptr) {
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/MissingTexture.png"));
std::cout << IMG_GetError();
}
SDL_Point point = getsize(this->texture);
this->TextureHeight = point.y;
this->TextureWidth = point.x;
this->rect = {this->x - ((this->TextureWidth * SpriteSizeMult) / 2), this->y - ((this->TextureHeight * SpriteSizeMult) / 2), this->TextureWidth * SpriteSizeMult, this->TextureHeight * SpriteSizeMult};
}
Tile::Tile(TileStruct structure, SDL_Renderer* renderer)
{
this->x = structure.x;
this->y = structure.y;
switch (structure.type) {
case TileTypes::Tile_Grass:
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/Tiles/Grass.png"));
default:
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/MissingTexture.png"));
}
if (this->texture == NULL) {
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/MissingTexture.png"));
if (this->texture == NULL) {
SDL_ShowSimpleMessageBox(0, "ERROR", "Failed to load texture", NULL);
SDL_ShowSimpleMessageBox(0, "ERROR", IMG_GetError(), NULL);
}
}
SDL_Point point = getsize(this->texture);
this->TextureHeight = point.y;
this->TextureWidth = point.x;
this->rect = { this->x - ((this->TextureWidth * SpriteSizeMult) / 2), this->y - ((this->TextureHeight * SpriteSizeMult) / 2), this->TextureWidth * SpriteSizeMult, this->TextureHeight * SpriteSizeMult };
}
Tile::Tile()
{
}
int Tile::Draw(SDL_Renderer* renderer)
{
if (rect.w == 0 || rect.h == 0) {
return -1;
}
this->rect.x = 0;
this->rect.y = 0;
SDL_RenderCopy(renderer, this->texture, NULL, &rect);
return 0;
}
void Tile::SetPos(int x, int y)
{
this->x = x;
this->y = y;
}
I'm sorry for the sheer amount of code that is, but I'd really appreciate the help. If there's any more info I need to put here, just let me know.
I'm fully aware that I should make a Minimal Reproducible Example, but as far as I'm aware, all the code listed here is necessary.
Finally, in case I've been unclear, when running the code the Missing Texture image that should appear isn't showing up.
I can't see SDL_INIT function in your code.
You should add this in the beginning of your main function.
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
return 1;
You are initialising tile before creating a renderer so the constructor is trying to create a texture without a renderer.
SDL_Renderer* renderer;
Tile tile = Tile({10, 10, TileTypes::Tile_Grass}, renderer);
You should do something like this
#include "Classes.h"
int MouseX = 0;
int MouseY = 0;
int PlayerX = 0;
int PlayerY = 0;
SDL_Renderer* renderer;
EventReturns HandleEvent(SDL_Event* event) {
switch (event->type) {
case SDL_QUIT:
return EventReturns::Event_QUIT;
case SDL_KEYDOWN:
switch (event->key.keysym.sym) {
case SDLK_ESCAPE:
return EventReturns::Event_TryQuit;
default:
return EventReturns::Event_None;
}
default:
return EventReturns::Event_None;
}
}
int mainLoop(EventReturns eventReturn) {
SDL_GetMouseState(&MouseX, &MouseY);
if (eventReturn == EventReturns::Event_QUIT || eventReturn == EventReturns::Event_TryQuit) {
return 1;
}
return 0;
}
void render(Tile tile) {
SDL_SetRenderDrawColor(renderer, 100, 200, 200, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
tile.SetPos(0, 0);
if (tile.Draw(renderer) != 0) {
SDL_ShowSimpleMessageBox(0, "ERROR", "ERROR: Rect in tile has 0x0 size, Please close this with the task manager", NULL);
}
SDL_RenderPresent(renderer);
}
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
return 1;
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 2880, 1600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
Tile tile = Tile({ 10, 10, TileTypes::Tile_Grass }, renderer);
bool running = true;
EventReturns eventReturn = EventReturns::Event_None;
SDL_Event event;
int quit = 0;
while (running) {
while (SDL_PollEvent(&event)) {
eventReturn = HandleEvent(&event);
}
quit = mainLoop(eventReturn);
render(tile);
if (quit == 1) {
running = false;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

How to use SDL_KeyCode to handle a key press each time?

I'm trying to generate a rectangle into a new position whenever I press the Right arrow key, I was able to get the 1st rectangle but now stuck at the 2nd one. As this is not a case of SDL_GetKeyboardState (to move the rectangle when key is pressed continuously), I'm completely clueless on how this should proceed. To create array for rectangles and pass it to poll event?
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
SDL_Window *window = NULL;
SDL_Surface *screen = NULL;
SDL_Renderer *renderer;
SDL_Event e;
SDL_Rect one, two;
bool quit = false;
void init(){
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Testing", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
screen = SDL_GetWindowSurface(window);
}
void draw(){
SDL_SetRenderDrawColor(renderer,255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255);
SDL_RenderFillRect( renderer, &one);
SDL_SetRenderDrawColor( renderer, 0, 66, 255, 255);
SDL_RenderFillRect( renderer, &two);
SDL_RenderPresent(renderer);
}
void logic(){
Uint8 *state;
while (SDL_PollEvent(&e) !=0) {
if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_RIGHT:
one = {2,2,124,124};
//two = {130,2,124,124};
break;
case SDLK_LEFT:
one = {0,0,0,0};
break;
}
}
else if (e.type == SDL_QUIT)
{
quit = true;
}
}
}
int main(int argc, char* args[]){
init();
while (!quit)
{
logic();
draw();
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
renderer = NULL;
window = NULL;
SDL_Quit();
return 0;
}

General SDL2 problems. MacOS, Xode

What I'm trying to do is make an SDL program that can write special symbols to a window I created. The keyboard can change between 4 layers each registering 32 keys. I just can't figure out how to actually make something appear on the screen and have no idea what I'm doing wrong.
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, const char * argv[])
{
//Setup
bool quit = false;
SDL_Event event;
int z = 0; //Layer
int x = 0;
int y = 0;
//Init
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * window = SDL_CreateWindow("TPKB", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 640, SDL_WINDOW_SHOWN);
SDL_Rect rect = {x, y, 32, 32};
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface * A_srf = SDL_LoadBMP("A.bmp"); SDL_Texture * A = SDL_CreateTextureFromSurface(renderer, A_srf); SDL_FreeSurface(A_srf);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//Events
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_KEYUP:
{
if(z == 0)
{
switch(event.key.keysym.sym)
{
//case SDLK_1: SDL_BlitSurface(A_srf, NULL, surface, srfrect); break;
case SDLK_2: SDL_RenderCopy(renderer, A, NULL, &rect); if(x == 928){x = 0; y += 32;} else{x += 32;} rect.x = x; rect.y = y; SDL_RenderClear(renderer); SDL_RenderPresent(renderer); break;
case SDLK_LEFT: z = 1; std::cout << "1"; break;
}
}
if(z == 1)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: z = 0; std::cout << "0"; break;
}
}
}
}
}
//Cleanup
SDL_DestroyRenderer(renderer);
SDL_DestroyTexture(A);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I've tried moving the render clear render present stuff around but it hasn't seemed to be activating at all.

Utilisation of SDL_KEYDOWN

My program generates an image. I want to close the window by clicking on any key or by clicking with my pointer on the window cross.
It works only by clicking on the cross (Use of SDL_QUIT) but not with SDL_KEYDOWN. I tried also with SDL_SPACE, SDL_KEYUP but the result is the same.
So what am I missing in my code ?
I am using xcode.
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL, *zozor = NULL;
SDL_Rect positionFond, positionZozor;
SDL_Event event;
int continuer = 1;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
imageDeFond = SDL_LoadBMP("lac_en_montagne.bmp");
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
SDL_Flip(ecran);
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_KEYDOWN:
{
printf("use of SDL_KEYDOWN");
continuer=0;
break;
}
case SDL_QUIT:
{
printf("use of SDL_QUIT");
continuer = 0;
break;
}
}
}
SDL_FreeSurface(imageDeFond);
SDL_Quit();
return EXIT_SUCCESS;
}

SDL, How can I make the background picture render?

I had a render problem, but I fixed that. The problem is, is that the picture won't actually show up. I know the picture gets loaded because I have an error handler if it isn't loaded. I know the code is messy, but I just need the picture to show up.
#include <SDL/SDL.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int fps = 60;
SDL_Window *window;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("", 300, 100, 1024, 800, SDL_WINDOW_OPENGL);
if (window == NULL)
{
cout << ("could not create window: %s/n", SDL_GetError());
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
int x = 0, y = 0;
SDL_Surface *screen;
SDL_Surface *background = SDL_LoadBMP("hockeyrink.bmp");
if(background == NULL)
{
SDL_ShowSimpleMessageBox(0, "Background init error", SDL_GetError(), window);
}
if(renderer == NULL)
{
SDL_ShowSimpleMessageBox(0, "Renderer init error", SDL_GetError(), window);
}
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,background);
if(texture == NULL)
{
SDL_ShowSimpleMessageBox(0, "Texture init error", SDL_GetError(), window);
}
const int speed = 5;
SDL_Rect camera;
camera.x = 0; //Don't worry about this camera, I need this after i get the background working.
camera.y = 0;
camera.w = 800;
camera.h = 600;
bool b[2] = {0,0};
Uint32 start;
bool running = true;
while (running)
{
start = SDL_GetTicks();
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running = false;
SDL_DestroyTexture(texture);
SDL_FreeSurface(background);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=1;
break;
case SDLK_LEFT:
b[1]=1;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=0;
break;
case SDLK_LEFT:
b[1]=0;
break;
}
break;
}
}
if(b[0])
{
x+=speed;
camera.y+=speed;
if (camera.y > 3000-800)
{
camera.y=0;
}
}
else if(b[1])
{
x-=speed;
camera.y-=speed;
if (camera.y <= 0)
{
camera.y = 2000-800;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
if(1000/fps>SDL_GetTicks()-start)
{
SDL_Delay(1000/fps-(SDL_GetTicks() - start));
}
}
return 0;
}
You have initialized b[1] to 0 and the texture is rendered only when b[1] is 1 as in your code.
You should either put the lines:
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
before the loop,
or press the left key of your keyboard(i.e. SDLK_LEFT)
to render and present the image on the screen.
It works in my system, so it should work in yours, too.