SDL_TTF, Render Modes are identical in quality - c

I have a click based game to code, and It contains some text that need to be rendererd in real-time,I tried to render the text with TTF_RenderText_Solid() , TTF_RenderText_Shaded(),TTF_RenderText_Blended() but they all render the same poor quality text. I have tried to change the BlendMode of the renderer, Surface and Texture, but still the same result, You might think it is because of using the same surface over and over, but I am sure it's not that.
screenshot
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#define Title "Test"
#define font01 "src/fonts/Roboto-Regular.ttf"
#define font01_size 48
typedef struct {
SDL_Texture *txtu;
SDL_Rect rect;
SDL_Color clr;
char* text;
} text_t;
int main(int argc,char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
TTF_Init();
SDL_Window *window = SDL_CreateWindow(Title,SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,480,720,SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_TARGETTEXTURE);
TTF_Font *font1 = TTF_OpenFont(font01,font01_size);
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
SDL_Surface *Load_srfc = NULL;
SDL_SetSurfaceBlendMode(Load_srfc,SDL_BLENDMODE_BLEND);
//SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,480,720);
SDL_SetRenderDrawColor(renderer,0,0,0,255);
SDL_RenderFillRect(renderer,NULL);
SDL_Delay(500);
text_t text1 = {NULL,{0,0,220,60},{255,255,255,240},"015:32.665 ms"};
text_t text2 = {NULL,{20,70,220,60},{255,255,255,240},"015:32.665 ms"};
text_t text3 = {NULL,{40,140,220,60},{255,255,255,240},"015:32.665 ms"};
Load_srfc = TTF_RenderText_Solid(font1,text1.text,text1.clr);
text1.txtu = SDL_CreateTextureFromSurface(renderer,Load_srfc);
SDL_SetTextureBlendMode(text1.txtu,SDL_BLENDMODE_BLEND);
SDL_FreeSurface(Load_srfc); Load_srfc=NULL;
SDL_RenderCopy(renderer,text1.txtu,NULL,&text1.rect);
SDL_RenderPresent(renderer);
SDL_Delay(500);
SDL_Color back = {240,30,50,245};
Load_srfc = TTF_RenderText_Shaded(font1,text2.text,text2.clr,back);
text2.txtu = SDL_CreateTextureFromSurface(renderer,Load_srfc);
SDL_SetTextureBlendMode(text2.txtu,SDL_BLENDMODE_BLEND);
SDL_FreeSurface(Load_srfc); Load_srfc=NULL;
SDL_RenderCopy(renderer,text2.txtu,NULL,&text2.rect);
SDL_RenderPresent(renderer);
SDL_Delay(500);
Load_srfc = TTF_RenderText_Blended(font1,text3.text,text3.clr);
text3.txtu = SDL_CreateTextureFromSurface(renderer,Load_srfc);
SDL_SetTextureBlendMode(text2.txtu,SDL_BLENDMODE_BLEND);
SDL_FreeSurface(Load_srfc); Load_srfc=NULL;
SDL_RenderCopy(renderer,text3.txtu,NULL,&text3.rect);
SDL_RenderPresent(renderer);
bool quit=0;
while(!quit)
{
SDL_Event evt;
while (SDL_PollEvent(&evt))
{
if(evt.type == SDL_QUIT ||
(evt.type == SDL_WINDOWEVENT && evt.window.event == SDL_WINDOWEVENT_CLOSE) ||
(evt.type == SDL_KEYDOWN && evt.key.keysym.sym == SDLK_ESCAPE)) {
quit = 1;
}
}
}
SDL_DestroyTexture(text1.txtu);
SDL_DestroyTexture(text2.txtu);
SDL_DestroyTexture(text3.txtu);
SDL_FreeSurface(Load_srfc);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
}

Related

Cannot get SDL_SetTextureColorMod to work

I am trying to change the color of the image displayed. The image contains characters in black and I want to display them in red. So I am trying to use SDL_SetTextureColorMod but it seems I am doing it wrong since the image rendered is still black. Does someone see the problem with my code?
#include "SDL.h"
#include <stdio.h>
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window;
SDL_Renderer *renderer;
SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer);
SDL_Surface *surface = SDL_LoadBMP("font.bmp");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
int keep_going = 1;
while (keep_going) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
keep_going = 0;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
int ret = SDL_SetTextureColorMod(texture, 255, 0, 0);
if(ret != 0){
printf("%s",SDL_GetError());
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
The image I'm using:

How can I perfectly manage my memory of my C project?

I am working on an object of SDL Tetris. When I ran my code, it first worked fine. But it automatically stopped displaying my text a few minutes later. I guessed there must be some problem on the memory management and I proved that I was right via Task Manager.
I look over my source code but found nothing wrong. (at least I didn't find it) Every heap object I delcared was freed and textures were destroyed. So, what can be the problem?
Here's my source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Surface * text;
TTF_Font* font;
bool running = true;
#define ScreenWidth 60
#define ScreenHeight 30
#define CharWidth 14
#define CharHeight 24
char screen[ScreenHeight][ScreenWidth + 1];
SDL_Color color = {192, 192, 192};
SDL_Rect rect;
int score = 0;
char shapes[7][17];
typedef struct Block {
int type;
char shape[17];
int x, y;
int width, height;
} Block;
Block * newBlock(int type) {
Block * block = malloc(sizeof(Block));
return block;
}
void CheckEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
} else if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_w:
;
break;
case SDLK_a:
;
break;
case SDLK_d:
;
break;
case SDLK_s:
;
break;
case SDLK_SPACE:
;
break;
default:
break;
}
}
}
free(&event);
}
void UpdateBoard() {
for (int i = 0; i < ScreenHeight; ++i) {
for (int j = 0; j < ScreenWidth; ++j) {
screen[i][j] = ' ';
}
}
for (int i = 0; i != 20; ++i) {
screen[i + 2][1] = '#';
screen[i + 2][1 + 10 + 1] = '#';
}
for (int i = 0; i != 10 + 2; ++i) {
screen[22][i + 1] = '#';
}
sprintf(&(screen[0][1]), "Score: %d", score);
for (int i = 0; i != ScreenHeight; i++) {
for (int j = 0; j != ScreenWidth; j++) {
if (screen[i][j] == '\0') {
screen[i][j] = ' ';
}
}
}
}
void UpdateScreen() {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for (int i = 0; i < ScreenHeight; ++i) {
text = TTF_RenderText_Solid(font, screen[i], color);
SDL_Texture * texture;
texture = SDL_CreateTextureFromSurface(renderer, text);
rect.x = 0;
rect.y = i * CharHeight;
rect.w = strlen(screen[i]) * CharWidth;
rect.h = CharHeight;
SDL_RenderCopy(renderer, texture, NULL, &rect);
free(texture);
SDL_DestroyTexture(texture);
}
SDL_RenderPresent(renderer);
}
void Init() {
SDL_Init(SDL_INIT_EVERYTHING);
TTF_Init();
window = SDL_CreateWindow("Tetris", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
ScreenWidth * CharWidth, ScreenHeight * CharHeight, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
font = TTF_OpenFont("s8514oem.fon", 0);
sprintf(shapes[0], "OOOO............");
sprintf(shapes[1], "OO...OO.........");
sprintf(shapes[2], ".OO.OO..........");
sprintf(shapes[3], "O...OOO.........");
sprintf(shapes[4], "..O.OOO.........");
sprintf(shapes[5], "OO..OO..........");
sprintf(shapes[6], "OOO..O..........");
}
int main(int argc, char ** argv) {
Init();
while (running) {
CheckEvents();
UpdateBoard();
UpdateScreen();
SDL_Delay(1000/16);
}
TTF_Quit();
SDL_Quit();
return 0;
}
My Makefile:
tetris:
gcc -std=c99 -Wall -Isrc/include -Lsrc/lib -o Tetris main.c -lSDL2main -lSDL2 -lSDL2_ttf
Several things:
Don't try to free() stack-allocated variables like event:
//free(&event);
text needs to be freed with SDL_FreeSurface() before replacing its pointer value with a new one from TTF_RenderText_Solid():
if(text) {
SDL_FreeSurface(text);
}
text = TTF_RenderText_Solid(font, screen[i], color);
Don't use free() on the textures returned by SDL_CreateTextureFromSurface(), only use SDL_DestroyTexture():
texture = SDL_CreateTextureFromSurface(renderer, text);
...
//free(texture);
SDL_DestroyTexture(texture);

Issue closing window with SDL2 in C

I have this code that is setting up a window, along with the close button functionality.
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
int initialize();
void handle_input();
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
bool running;
int FPS;
int width;
int height;
bool close_requested;
} Game;
Game game = {
.running = true,
.FPS = 60,
.width = 600,
.height = 600,
.close_requested = false,
};
int main(int argc, char* argv[]) {
initialize();
handle_input();
while(game.running) { //Game loop
SDL_SetRenderDrawColor(game.renderer, 255, 0, 0, 255);
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
} //End of game loop
SDL_DestroyRenderer(game.renderer);
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}
int initialize() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { //return 0 on success
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, game.width, game.height, 0); //creates window
if (!window) {
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //creates a renderer
game.renderer = SDL_CreateRenderer(window, -1, render_flags);
if (!game.renderer) {
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
void handle_input() {
SDL_Event event;
while (!game.close_requested) { //close button
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
}
}
}
However, whenever I try to run this program, the window won't even open and I'm getting 0 errors in the console, besides a warning that states control may reach end of non-void function at the initialize() function. What does that warning mean? What is going on with my code? What did I do wrong?
I see 2 issues here:
you call handle_input() in your main before you enter the main loop and it gets stuck there until you exit, so SDL_RenderPresent() is never called.
the initialize function doesn't return anything in case of success, this is why you see the warning.
Try with the following changes, in main() move your input handling inside the loop:
int main(int argc, char* argv[]) {
initialize();
while(game.running && !game.close_requested) {
handle_input(); // <-- move here
SDL_SetRenderDrawColor(game.renderer, 255, 0, 0, 255);
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
}
// the rest...
}
In initialize() add a return 0; at the end.
In handle_input() remove the outer loop:
void handle_input() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
}
}

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)

SDL2 won't display image

I want to use SDL2 to open a window and display an image (a meme, to be precise). For some reason, the image doesn't appear; when I run the program, only a blank window opens.
This is my code:
#include <stdio.h>
#include <SDL2/SDL.h>
#include <time.h>
#include <stdbool.h>
#include "SDL2_image/SDL_image.h"
typedef struct
{
SDL_Texture *meme1;
SDL_Window *window;
SDL_Renderer *renderer;
}Meme;
void load(Meme *meme)
{
SDL_Surface *surface = NULL;
surface = IMG_Load("meme1.jpg");
meme->meme1 = SDL_CreateTextureFromSurface(meme->renderer, surface);
if(surface == NULL)
{
printf("Could not find meme1.jpg\n");
EXIT_FAILURE;
}
if(SDL_CreateTextureFromSurface(meme->renderer, surface) < 0 )
{
printf("\n\n\nSDL_CreateTextureFromSurface failed: %s\n\n\n", SDL_GetError());
}
SDL_FreeSurface(surface);
}
int process()
{
int quit = 0;
SDL_Event quitEvent;
while(quit==0)
{
while(SDL_PollEvent(&quitEvent))
{
if(quitEvent.type == SDL_QUIT)
{
quit = 1;
}
}
}
return quit;
}
void doRender(SDL_Renderer *renderer, Meme *meme)
{
renderer = SDL_CreateRenderer(meme->window, -1, 0);
SDL_RenderCopy(renderer, meme->meme1, NULL, NULL);
SDL_RenderPresent(renderer);
}
int main(int argc, char *argv[])
{
//creates the main window
SDL_Window *window = NULL;
Meme meme;
SDL_Renderer *renderer = NULL;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
0);
if (window == NULL)
{
printf("\nFailed to create window: %s\n", SDL_GetError());
return 1;
}
load(&meme);
int done = 0;
while(!done)
{
done = process();
doRender(renderer, &meme);
}
SDL_DestroyWindow(window);
SDL_DestroyTexture(meme.meme1);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
You should try converting the meme to a bmp image and the using the function SDL_LoadBmp
(use a surface to use this function)
if you need more help or need details check the syntax at
https://wiki.libsdl.org/SDL_LoadBMP
the error comes from the fact that you did not initialize SDL_image
with the function
"IMG_Init (arg)"

Resources