SDL2 doesn't render multiple viewports - c

I'm working through Lazy Foo's SDL2 tutorials and stuck trying to render multiple viewports. The idea is to load a PNG as a texture, create SDL_Rect structs for 3 different viewports (top left, top right, bottom), then copy the texture onto each viewport, and finally render all 3 viewports. My code is only rendering the first viewport.
I've tried changing the order - in every case, whichever viewport is defined first is the only one that renders.
I also tried changing the viewport dimensions, in case overlap was the issue - same problem.
The only question I found about multiple viewports didn't point me in the right direction. But it did start me thinking - my code is written in C, the tutorial in C++. Although I think I'm translating everything correctly (the other lessons work fine), maybe I'm missing something obvious here?
I'm compiling with CFLAGS = -Wall -Wextra -pedantic -std=c99 - no warnings or errors.
Edit: I tried rendering filled rectangles instead of a loaded PNG, but the issue is the same - only the first one renders.
Here's my code:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
int init_renderer();
int load_media();
SDL_Texture *load_texture(char *);
void close_renderer();
SDL_Window *g_window = NULL;
SDL_Renderer *g_renderer = NULL;
SDL_Texture *g_texture = NULL;
int main()
{
if (init_renderer() != 1) {
return -1;
}
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
printf("Warning: Linear texture filtering not enabled!\n");
}
if (load_media() != 1) {
return -1;
}
int quit = 0;
SDL_Event e;
while (quit != 1) {
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT || e.key.keysym.sym == SDLK_q) {
quit = 1;
}
}
SDL_SetRenderDrawColor(g_renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(g_renderer);
SDL_Rect top_left_vp;
top_left_vp.x = 0;
top_left_vp.y = 0;
top_left_vp.w = SCREEN_WIDTH / 2;
top_left_vp.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport(g_renderer, &top_left_vp);
SDL_RenderCopy(g_renderer, g_texture, NULL, NULL);
SDL_Rect top_right_vp;
top_right_vp.x = SCREEN_WIDTH / 2;
top_right_vp.y = 0;
top_right_vp.w = SCREEN_WIDTH / 2;
top_right_vp.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport(g_renderer, &top_right_vp);
SDL_RenderCopy(g_renderer, g_texture, NULL, NULL);
SDL_Rect bottom_vp;
bottom_vp.x = 0;
bottom_vp.y = SCREEN_HEIGHT / 2;
bottom_vp.w = SCREEN_WIDTH;
bottom_vp.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport(g_renderer, &bottom_vp);
SDL_RenderCopy(g_renderer, g_texture, NULL, NULL);
SDL_RenderPresent(g_renderer);
}
close_renderer();
return 0;
}
int init_renderer()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Failed to initialize SDL. Error: %s\n", SDL_GetError());
return 0;
}
g_window = SDL_CreateWindow("SDL Tuts",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
if (g_window == NULL) {
printf("Failed to create window. Error: %s\n", SDL_GetError());
return 0;
}
g_renderer = SDL_CreateRenderer(g_window, -1, SDL_RENDERER_ACCELERATED);
if (g_renderer == NULL) {
printf("Failed to create renderer. Error: %s\n", SDL_GetError());
return 0;
}
SDL_SetRenderDrawColor(g_renderer, 0x29, 0xAB, 0x87, 0xFF);
int img_flags = IMG_INIT_PNG;
if (!(IMG_Init(img_flags) & img_flags)) {
printf("Failed to initialize SDL Image. SDL_Image Error: %s\n", IMG_GetError());
return 0;
}
return 1;
}
int load_media()
{
g_texture = load_texture("assets/texture.png");
if (g_texture == NULL) {
return 0;
}
return 1;
}
SDL_Texture *load_texture(char *path)
{
SDL_Texture *new_texture = NULL;
SDL_Surface *loaded_surface = IMG_Load(path);
if (loaded_surface == NULL) {
printf("Failed to load image. SDL_Image Error: %s\n", IMG_GetError());
} else {
new_texture = SDL_CreateTextureFromSurface(g_renderer, loaded_surface);
if (new_texture == NULL) {
printf("Failed to create texture from %s. Error: %s\n", path, SDL_GetError());
}
SDL_FreeSurface(loaded_surface);
}
return new_texture;
}
void close_renderer()
{
SDL_DestroyTexture(g_texture);
g_texture = NULL;
SDL_DestroyRenderer(g_renderer);
SDL_DestroyWindow(g_window);
g_renderer = NULL;
g_window = NULL;
IMG_Quit();
SDL_Quit();
}

To check for more errors, you should see what the calls to SDL_RenderSetViewPort are returning. According to the docs, it returns an int, which is 0 on success or a negative int if there's an error. It's entirely possible that something deeper in SDL is having a fit.
Additional pro tips: you can define the SDL_Rect structs outside of your while loop to save a miniscule margin of processing power. And to spare yourself some typing, you can initialize a SDL_Rect using a list constructor instead of manually punching each property. E.G.:
SDL_Rect top_left_vp;
top_left_vp.x = 0;
top_left_vp.y = 0;
top_left_vp.w = SCREEN_WIDTH / 2;
top_left_vp.h = SCREEN_HEIGHT / 2;
is more simply
SDL_Rect top_left_vp = {
0,
0,
SCREEN_WIDTH / 2,
SCREEN_HEIGHT / 2
};

Related

How do I remove the Terminal Output in C

Situation
I am working on an SDL2 program and I want to remove the black terminal window that shows up everytime I fire the program,
its kinda annoying to have a black window randomly in my screen :/
What I've Tried
I've tried looking up in Google but nothing actually shows up that can fix my situation
Here's The Rest Of My Code
#include <stdio.h>
#include <SDL.h>
int main(int argc, char **args) {
// SDL Window Declaration
SDL_Surface* screen;
SDL_Window* window;
SDL_Rect plrBox;
SDL_Rect plrMot;
plrMot.x = 1;
plrMot.y = 1;
plrBox.x = 0;
plrBox.y = 0;
plrBox.w = 10;
plrBox.h = 10;
// SDL Initialization
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
printf("Fail At SDL_Init()\n");
return 1;
}
// Window Creation
window = SDL_CreateWindow(
"Paint",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
400,
300,
SDL_WINDOW_SHOWN
);
if (!window) {
printf("Fail at SDL_CreateWindow\n");
}
// Surface Creation
screen = SDL_GetWindowSurface(window);
if (!screen) {
printf("Fail at Screen\n");
return 1;
}
int run = 1;
while (run) {
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
SDL_FillRect(screen, &plrBox, SDL_MapRGB(screen->format, 0, 0, 0));
plrBox.x += plrMot.x;
plrBox.y += plrMot.y;
if (plrBox.y > 300) {
plrMot.y = -plrMot.y;
}
if (plrBox.x > 400) {
plrMot.x = -plrMot.x;
}
if (plrBox.y < 0) {
plrMot.y = -plrMot.y;
}
if (plrBox.x < 0) {
plrMot.x = -plrMot.x;
}
SDL_Event events;
while (SDL_PollEvent(&events)){
switch (events.type) {
case SDL_QUIT:
run = 0;
}
}
SDL_UpdateWindowSurface(window);
}
// Quit
window = NULL;
screen = NULL;
SDL_Quit();
return 0;
}
I use mingw for all the comments out there

How to change direction smoothly using SDL2 and how to keep moving when I press shift after holding a key?

It's my Code, it's a very simple tank games, I have 2 problems:
use WSAD to move with speed 4, when I pressing and holding shift, the speed change to 8, when I release shift, speed back to 4. But, with my code, when I press shift after holding WSAD, the tank stop, I must repress the key to move it.
When I press WSAD, the tank just change the direction, but not move,so when I holding d, the tank first change it's direction to right for about 0.5 second, then start to move. How to get it move smoothly?
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
const int WINDOW_WIDTH = 960; //窗体宽度
const int WINDOW_HEIGHT = 640; //窗体高度
//使用旋转角度定义方向
const int UP = 0;
const int DOWN = 180;
const int LEFT = 270;
const int RIGHT = 90;
//-------------------
typedef struct {
int x;
int y;
int width;
int height;
int direction;
SDL_Texture *texture;
} Player;
void RenderPlayer(Player player, SDL_Renderer *renderer) {
SDL_Rect srcRect = {.x = 0, .y = 0, .w = player.width, .h = player.height};
SDL_Rect destRect = {.x = player.x, .y = player.y, .w = player.width / 2, .h = player.height / 2};
SDL_RenderCopyEx(renderer, player.texture, &srcRect, &destRect, player.direction, NULL, SDL_FLIP_NONE);
}
int main(int argc, char *argv[]) {
SDL_Window *window;
SDL_Renderer *renderer;
if (SDL_Init(SDL_INIT_EVERYTHING)) {
printf("SDL对象初始化失败!\n");
return -1;
}
if (!(window = SDL_CreateWindow("坦克大战", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL))) {
printf("窗体创建失败!\n");
return -1;
}
if (!(renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE))) {
printf("渲染器创建失败!\n");
return -1;
}
SDL_SetRenderDrawColor(renderer, 76, 110, 150, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Surface *surface = IMG_Load("Tank01.png");
if (!surface) {
printf("像素集创建失败:%s\n", IMG_GetError());
return -1;
}
printf("宽度:%d\n高度:%d\n", surface->w, surface->h);
Player player1 = {(WINDOW_WIDTH - surface->w) / 2, WINDOW_HEIGHT - surface->h, surface->w, surface->h, UP, SDL_CreateTextureFromSurface(renderer, surface)};
int speed;
const Uint8 *state = SDL_GetKeyboardState(NULL);
SDL_Event sdlEvent;
while (1) {
int flag1 = 0;
while (SDL_PollEvent(&sdlEvent)) {
speed = 4;
switch (sdlEvent.type) {
case SDL_KEYDOWN:
if (state[SDL_SCANCODE_LSHIFT] && (state[SDL_SCANCODE_W] || state[SDL_SCANCODE_S] || state[SDL_SCANCODE_A] || state[SDL_SCANCODE_D])) {
speed = 8;
}
switch (sdlEvent.key.keysym.sym) {
case SDLK_w:
if (player1.y > 0) {
player1.y -= speed;
}
player1.direction = UP;
break;
case SDLK_s:
if (player1.y < WINDOW_HEIGHT - player1.height / 2) {
player1.y += speed;
}
player1.direction = DOWN;
break;
case SDLK_a:
if (player1.x > 0) {
player1.x -= speed;
}
player1.direction = LEFT;
break;
case SDLK_d:
if (player1.x < WINDOW_WIDTH - player1.width / 2) {
player1.x += speed;
}
player1.direction = RIGHT;
break;
case SDLK_ESCAPE:
SDL_Quit();
flag1 = 1;
break;
}
break;
case SDL_QUIT:
SDL_Quit();
flag1 = 1;
break;
}
}
SDL_RenderClear(renderer);
RenderPlayer(player1, renderer);
SDL_RenderPresent(renderer); //使用渲染器更新窗体
if (flag1) {
break;
}
}
return 0;
}
I couldn't reproduce your first problem with the code you provided, if I hold any of wasd and press shift the tank keeps moving.
The problem here is a bit hard to understand, but you're basically moving the tank only on SDL_Pressed events, meaning that the only reason your tank is moving at all is because SDL repeats the same events over and over, and because it doesn't do this very fast (polling events is kinda slow), your movement is choppy/laggy/steppy whatever you want to call it.
A fix for this is to remove the actual movement step outside your SDL_Event loop, also you should filter out repeat events since you've already checked them.
Meaning your code should look should be something like this
while (1) {
while (SDL_Event(e)) {
if (event is repeated)
skip event
if (UP Key is pressed)
up_state = 1;
if (UP key is released)
up_state = 0;
// etc..
}
// Outside the event loop
if (up_state == 1) // if its 0 we don't add anything
player.x -= speed;
// and so on..
}
For this to work properly you'll also need to read about how to implement a delta time in your loop, because this will run as fast as your processor can meaning that your speed wont be regular, it might add more or less speed depending on how fast is running, which is bad.
Here is your code with these problems fixed, except the delta time, since I actually don't which platform you're on and I was too lazy to do it in C, I capped the framerate at 60fps with a sleep at the end, which is a very bad idea.
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// I don't know if you're on windows or linux
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
const int WINDOW_WIDTH = 960; //窗体宽度
const int WINDOW_HEIGHT = 640; //窗体高度
//使用旋转角度定义方向
const int UP = 0;
const int DOWN = 180;
const int LEFT = 270;
const int RIGHT = 90;
//-------------------
typedef struct {
int x;
int y;
int width;
int height;
int direction;
SDL_Texture *texture;
} Player;
int m_up = 0;
int m_down = 0;
int m_left = 0;
int m_right = 0;
void RenderPlayer(Player player, SDL_Renderer *renderer) {
SDL_Rect srcRect = {.x = 0, .y = 0, .w = player.width, .h = player.height};
SDL_Rect destRect = {.x = player.x,
.y = player.y,
.w = player.width / 2,
.h = player.height / 2};
SDL_RenderCopyEx(renderer, player.texture, &srcRect, &destRect,
player.direction, NULL, SDL_FLIP_NONE);
}
int main(int argc, char *argv[]) {
SDL_Window *window;
SDL_Renderer *renderer;
if (SDL_Init(SDL_INIT_EVERYTHING)) {
return -1;
}
if (!(window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH,
WINDOW_HEIGHT, SDL_WINDOW_OPENGL))) {
return -1;
}
if (!(renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_TARGETTEXTURE))) {
return -1;
}
SDL_SetRenderDrawColor(renderer, 76, 110, 150, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Surface *surface = IMG_Load("tank.png");
if (!surface) {
return -1;
}
Player player1 = {(WINDOW_WIDTH - surface->w) / 2,
WINDOW_HEIGHT - surface->h,
surface->w,
surface->h,
UP,
SDL_CreateTextureFromSurface(renderer, surface)};
int speed = 4;
SDL_Event sdlEvent;
int run = 1;
while (run) {
while (SDL_PollEvent(&sdlEvent)) {
// Now we skip over repeat events
if ((sdlEvent.type == SDL_KEYDOWN || sdlEvent.type == SDL_KEYUP) &&
sdlEvent.key.repeat == 0) {
SDL_Keycode key = sdlEvent.key.keysym.sym;
int is_pressed = sdlEvent.key.state == SDL_PRESSED;
if (key == SDLK_LSHIFT && is_pressed) {
speed = 8;
} else if (key == SDLK_LSHIFT && !is_pressed) {
speed = 4;
}
if (key == SDLK_w && is_pressed) {
m_up = 1;
} else if (key == SDLK_w) {
m_up = 0;
}
if (key == SDLK_s && is_pressed) {
m_down = 1;
} else if (key == SDLK_s) {
m_down = 0;
}
if (key == SDLK_a && is_pressed) {
m_left = 1;
} else if (key == SDLK_a) {
m_left = 0;
}
if (key == SDLK_d && is_pressed) {
m_right = 1;
} else if (key == SDLK_d) {
m_right = 0;
}
if (key == SDLK_ESCAPE) {
run = 0;
}
if (sdlEvent.type == SDL_QUIT) {
run = 0;
}
}
}
// Handle the movement outside the event loop
if (m_up && player1.y > 0)
player1.y -= speed;
if (m_down && player1.y < WINDOW_HEIGHT - player1.height / 2)
player1.y += speed;
if (m_left && player1.x > 0)
player1.x -= speed;
if (m_right && player1.x < WINDOW_WIDTH - player1.width / 2)
player1.x += speed;
SDL_RenderClear(renderer);
RenderPlayer(player1, renderer);
SDL_RenderPresent(renderer);
#ifdef _WIN32
sleep(0.016); // asume 60 fps, horrible idea
#else
usleep(16000);
#endif
}
SDL_Quit();
return 0;
}
the test image I was using as 'tank.png' https://i.imgur.com/qlUagLp.png

C SDL VS Code image is not displaying

I have recently started learning game programming in C. I am using a virtual studio code on linux Ubuntu, and image star.png is not displaying on the screen, there are no errors or problems reported by vs code. I have tried reinstalling sdl2-dev and sdl2-image-dev libraries. Maybe it is a problem with SDL, or maybe with my code (it was written in 2013).
The code should draw a white ractangl, which i can move around, on a blue screen and place a star in upper left corner of a window. It does everything except placing a star.
The code: (doesn't show "Cannot dinf star.png!" so I guess it is not that)
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
typedef struct
{
int x, y;
short life;
char *name;
}Man;
typedef struct
{
//players
Man man;
//image
SDL_Texture *star;
} GameState;
/////////////////////////////////////////////////////////////////////processEvents
int processEvents(SDL_Window *window , GameState *game)
{
SDL_Event event;
int done = 0;
//Check for events
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_WINDOWEVENT_CLOSE:
{
if (window)
{
SDL_DestroyWindow(window);
window = NULL;
done = 1;
}
}
break;
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
done = 1;
break;
}
}
break;
case SDL_QUIT:
done = 1;
break;
}
}
const Uint8 *state = SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_LEFT])
{
game->man.x -= 1;
}
if(state[SDL_SCANCODE_RIGHT])
{
game->man.x += 1;
}
if(state[SDL_SCANCODE_UP])
{
game->man.y -= 1;
}
if(state[SDL_SCANCODE_DOWN])
{
game->man.y += 1;
}
SDL_Delay(10);
return done;
}
/////////////////////////////////////////////////////////////////////////////////////doRender
void doRedner(SDL_Renderer *renderer, GameState *game)
{
SDL_SetRenderDrawColor(renderer , 0, 0, 255, 255); //blue
//screen clean up into blue
SDL_RenderClear(renderer);
//set color
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Rect rect = {game->man.x, game->man.y, 80, 80};
SDL_RenderFillRect(renderer, &rect);
//draw a star
SDL_Rect starRect = { 50, 50, 64, 64 };
SDL_RenderCopy(renderer, game->star, NULL, &starRect);
SDL_RenderPresent(renderer);
}
/////////////////////////////////////////////////////////////////////////////////////main funkction
int main(int argc, char *argv[])
{
GameState gameState;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Surface *starSurface = NULL;
SDL_Init(SDL_INIT_VIDEO);
gameState.man.x = 340-40;
gameState.man.y = 240-40;
window = SDL_CreateWindow("Game Widnow",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
0
);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
//load image
starSurface = IMG_Load("star.png");
if(starSurface = NULL)
{
printf("Cannot find star.png!\n\n");
SDL_Quit();
return 1;
}
gameState.star = SDL_CreateTextureFromSurface(renderer, starSurface);
SDL_FreeSurface(starSurface);
int done = 0;
while(!done)
{
//check events
done = processEvents(window, &gameState);
//render
doRedner(renderer, &gameState);
}
SDL_Delay(1000);
//exit game and free memory
SDL_DestroyTexture(gameState.star);
//destroy and close window
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
TL;DR: Your intention is to perform a comparison, but you are using the assignment operator (i.e., =) instead of the comparison operator ==.
The conditional expression in your if statement:
if(starSurface = NULL)
{
...
}
does not check whether starSurface is NULL. The expression starSurface = NULL assigns NULL to starSurface and evaluates to NULL. Therefore, the condition evaluates to false and no error message is displayed.
Instead, you should write (note the double = below):
if (starSurface == NULL)
or just:
if (!starSurface)

Invalid renderer SDL2

I am looking through the code and i cant find solution for the problem of invalid renderer. I am beginner with SDL2 and i have to write code in pure C.
I think that in my code there is more errors but because of this one i cant go further. Code is half in polish language so if u cant get what is where i can rewrite this a bit . Problem occure when in main i try to load function"Odczyt_z_Pliku". Probably somewhere there is a problem.
SDL_GetError() says" invalid renderer.
#include<SDL.h>
#include<stdio.h>
#include<SDL_image.h>
#pragma warning(disable : 4996)
#define WYSOKOSC_EKRANU 768
#define SZEROKOSC_EKRANU 1024
typedef enum bool{
false,true
}bool;
typedef struct sTekstura {
int wysokosc;
int szerokosc;
SDL_Texture *Tekstura;
}sTekstura;
void IniTekstury(sTekstura T)
{
T.wysokosc = 0;
T.szerokosc = 0;
T.Tekstura = NULL;
}
void free(sTekstura T)
{
//Free texture if it exists
if (T.Tekstura != NULL)
{
SDL_DestroyTexture(T.Tekstura);
T.Tekstura = NULL;
T.szerokosc = 0;
T.wysokosc = 0;
}
}
int Odczyt_z_Pliku(char nazwa[50],sTekstura T,SDL_Renderer* Renderer)
{
free(T);
SDL_Texture* nTekstura = NULL;
//Load image at specified path
SDL_Surface* Powierzchnia = IMG_Load(nazwa);
if (Powierzchnia == NULL)
{
printf("Unable to load image %s! SDL_image Error: %s\n", nazwa, IMG_GetError());
}
else
{
SDL_SetColorKey(Powierzchnia, SDL_TRUE, SDL_MapRGB(Powierzchnia->format, 0xFF, 0xFF, 0xFF));
//Create texture from surface pixels
nTekstura = SDL_CreateTextureFromSurface(Renderer, Powierzchnia);
if (nTekstura == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", nazwa, SDL_GetError());
}
else
{
//Get image dimensions
T.szerokosc = Powierzchnia->w;
T.wysokosc = Powierzchnia->h;
}
//Get rid of old loaded surface
SDL_FreeSurface(Powierzchnia);
}
//Return success
T.Tekstura = nTekstura;
if (T.Tekstura != NULL)
{
return 1;
}
else
{
return 0;
}
}
bool Inicjalizacja(SDL_Window *Okno,SDL_Renderer *Renderer)
{
//Initialization flag
bool success = true;
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
printf("Warning: Linear texture filtering not enabled!");
}
//Create window
Okno = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SZEROKOSC_EKRANU, WYSOKOSC_EKRANU, SDL_WINDOW_SHOWN);
if (Okno == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create renderer for window
Renderer = SDL_CreateRenderer(Okno, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (Renderer == NULL)
{
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor(Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
success = false;
}
}
}
}
return success;
}
void setBlendMode(sTekstura T, SDL_BlendMode blending) //MK: Funkcja ustawiająca przezroczystosc
{
//Set blending function
SDL_SetTextureBlendMode(T.Tekstura, blending);
}
void setAlpha(sTekstura T,Uint8 alpha) //MK: Funkcja ustawiająca przezroczystość
{
//Modulate texture alpha
SDL_SetTextureAlphaMod(T.Tekstura, alpha);
}
void render(int x, int y,sTekstura T,SDL_Renderer *Renderer)
{
//Set rendering space and render to screen
SDL_Rect renderQuad = { x, y, T.szerokosc, T.wysokosc };
SDL_RenderCopy(Renderer, T.Tekstura, NULL, &renderQuad);
}
int main(int argc, char *argv[])
{
SDL_Window * Okno = NULL;
SDL_Renderer* Renderer = NULL;
sTekstura TloMenu;
TloMenu.szerokosc = 0;
TloMenu.wysokosc = 0;
TloMenu.Tekstura = NULL;
sTekstura TloGra;
TloGra.szerokosc = 0;
TloGra.wysokosc = 0;
TloGra.Tekstura = NULL;
sTekstura Pudlo;
Pudlo.szerokosc = 0;
Pudlo.wysokosc = 0;
Pudlo.Tekstura = NULL;
sTekstura Sciana;
Sciana.szerokosc = 0;
Sciana.wysokosc = 0;
Sciana.Tekstura = NULL;
sTekstura StartGry;
StartGry.szerokosc = 0;
StartGry.wysokosc = 0;
StartGry.Tekstura = NULL;
sTekstura KoniecGry;
KoniecGry.szerokosc = 0;
KoniecGry.wysokosc = 0;
KoniecGry.Tekstura = NULL;
SDL_Event e;
//Start up SDL and create window
if (!Inicjalizacja(Okno,Renderer))
{
printf("Failed to initialize!\n");
}
else
{
if(!Odczyt_z_Pliku("MENU BOMBERMAN.png", Sciana, Renderer))
{
puts("Nie wczytano kostki");
return 0;
}
if (!Odczyt_z_Pliku("pudlo3.bmp", Pudlo, Renderer))
{
puts("Nie wczytano pudla");
return 0;
}
if (!Odczyt_z_Pliku("MenuBomberman.bmp", TloMenu, Renderer))
{
puts("Nie wczytano menu");
return 0;
}
if (!Odczyt_z_Pliku("Mapa.bmp", TloGra, Renderer))
{
puts("Nie wczytano mapy");
return 0;
}
if (!Odczyt_z_Pliku("NEW GAME.bmp", StartGry, Renderer))
{
puts("Nie wczytano napisu nowej gry");
return 0;
}
else
{
//Set standard alpha blending
setBlendMode(StartGry, SDL_BLENDMODE_BLEND);
}
if (!Odczyt_z_Pliku("exitgimp.bmp", KoniecGry, Renderer))
{
puts("Nie wczytano napisu koniec gry");
return 0;
}
else
{
//Set standard alpha blending
setBlendMode(StartGry, SDL_BLENDMODE_BLEND);
}
//Main loop flag
bool quit = false;
//Modulation component
Uint8 AlphaStartu = 255;
Uint8 AlphaKonca = 127;
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
//Handle key presses
else if (e.type == SDL_KEYDOWN)
{
//Increase alpha on w
if (e.key.keysym.sym == SDLK_w)
{
AlphaKonca = 127;
AlphaStartu = 255;
}
//Decrease alpha on s
else if (e.key.keysym.sym == SDLK_s)
{
AlphaKonca = 256;
AlphaStartu = 127;
}
}
}
//Clear screen
SDL_SetRenderDrawColor(Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(Renderer);
//Render background
render(0, 0, TloMenu, Renderer);
//Render front blended
setAlpha(KoniecGry,AlphaKonca);
setAlpha(StartGry, AlphaStartu);
render(0, 0,StartGry,Renderer);
render(0, 0,KoniecGry,Renderer);
//Update screen
SDL_RenderPresent(Renderer);
}
}
//Free resources and close SDL
close();
return 0;
}
When you get to Odczyt_z_Pliku, Renderer is still a NULL pointer.
As it stands, in your main() function you have a variable Renderer of type SDL_Renderer* (initialized to NULL). You then pass that value NULL into SDL_Renderer* which also takes an argument of type SDL_Renderer*.
However, in C this is just a pass by copy of the value of the pointer itself (not the value pointed to by the pointer). In other words, the argument Renderer to your function just creates a local variable in that function. So in Odczyt_z_Pliku when you do Renderer = SDL_CreateRenderer(...); that may return a new pointer but it's only assigning it to the local variable Renderer, but this has no effect on the Renderer variable in your main() function.
In C, the way to write a function that sets the value of a pointer that is a local variable in the calling function is to use a double pointer. That is, change the signature of Inicjalizacja to
bool Inicjalizacja(SDL_Window **Okno, SDL_Renderer **Renderer)
then in main() (or wherever else) call it like:
SDL_Window * Okno = NULL;
SDL_Renderer* Renderer = NULL;
...
if (!Inicjalizacja(&Okno, &Renderer)) {
...
}
and so on. (Note: You made the same mistake with the SDL_Window Okno as well, and possibly elsewhere--I haven't read the full code).
The syntax &Okno means pass the address of (i.e. a pointer to) the variable Okno. Since Okno is itself a pointer, the address of the pointer is a double pointer.
Then in Inicjalizacja write:
*Renderer = SDL_CreateRenderer(...);
and similarly with Okno. The *Renderer syntax (which I find somewhat confusing) means the value pointed to by a pointer. Since Renderer here is a double pointer, this means assign the single pointer (of type Renderer*) into the pointer pointed to by Renderer. Now the Renderer* pointer in your main() function will be properly initialized.
Note, similarly you should change the following check to:
if (*Renderer == NULL) {...}
and so on. We know Renderer != NULL since it's a pointer to a local variable allocated in our main() function. The interesting question is what value SDL_CreateRenderer returned, so we want to look at *Renderer.

My code won't display sprite SDL2

The screen is always black. Tell me how to display the sprites correctly.
This is my code:
#define SHAPE_SIZE 32
void aff_map(SDL_Renderer *renderer)
{
SDL_Surface *img;
SDL_Texture *Tfloor
int x = 0;
int y = 0;
int map[4][8] = {{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0}};
SDL_Rect SrcR;
SDL_Rect DestR;
DestR.x = 0;
DestR.y = 0;
DestR.w = SHAPE_SIZE;
DestR.h = SHAPE_SIZE;
img = IMG_Load("floor.bmp");
Tfloor = SDL_CreateTextureFromSurface(renderer, img);
while (y < 4)
{
x = 0;
while (x < 8)
{
if (map[y][x] == 0)
SDL_RenderCopy(renderer, Tfloor, NULL, &DestR);
x++;
DestR.x = DestR.x + 32;
}
DestR.x = 0;
DestR.y = DestR.y + 32;
y++;
}
SDL_RenderPresent(renderer);
}
int main()
{
SDL_Window *screen;
SDL_Event evenements;
SDL_Renderer *renderer;
screen = SDL_CreateWindow("Zappy", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 8 * SHAPE_SIZE -32, 4 * SHAPE_SIZE, 0);
renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
SDL_RenderClear(renderer);
while (42)
{
SDL_WaitEvent(&evenements);
if (evenements.window.event == SDL_WINDOWEVENT_CLOSE ||
evenements.key.keysym.sym == SDLK_ESCAPE)
{
SDL_DestroyWindow(screen);
SDL_Quit();
break;
}
aff_map(renderer);
}
return 0;
}
The error message is explicit.
It says that the "floor.bmp" has not been converted to a surface.
It means that 'img' parameter is NULL.
Try the following :
Specify the full path to your picture in IMG_Load(), for example "/home/quentin/floor.bmp"
Check the return value of IMG_Load().

Resources