I'm having trouble getting my image to display using SDL. I've checked the file path, made sure the image dimensions are compatible with the window size, and verified that the image is not NULL, but it still won't show up. I've been trying to debug this for hours and I'm at a loss. Can someone please take a look at my code and help me figure out what I'm missing? Here's the relevant code:
game.c:
#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "header/game.h"
#include "header/constant.h"
SDL_Rect position, positionPlayer;
// Game.c
void game(/*SDL_Window* window, */SDL_Renderer* renderer){
SDL_Texture *bomber[4]={NULL};
SDL_Texture *bomberCurrent=NULL;
positionPlayer.x=33;
positionPlayer.y=33;
SDL_Event event;
int runningGame=1;
int i=0/*, j=0*/;
bomber[DOWN]=IMG_LoadTexture(renderer,"playerPink1.png");
if (!bomber[DOWN]) {
printf("Error loading image: %s\n", SDL_GetError());
return;
}
int w, h;
SDL_QueryTexture(bomber[DOWN], NULL, NULL, &w, &h);
if (w > 952 || h > 442) {
printf("Error: Image size is larger than window size\n");
return;
}
bomberCurrent = bomber[DOWN];
while(runningGame){
SDL_WaitEvent(&event); // Bloque l'exécution du programme jusqu
while(SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
runningGame = 0;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
position.x=positionPlayer.x*TAILLE_BLOC;
position.y=positionPlayer.y*TAILLE_BLOC;
SDL_RenderCopy(renderer,bomberCurrent,NULL,&position);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
for(i=0;i<4;i++){
SDL_DestroyTexture(bomber[i]);
}
}
game.h:
#ifndef CONSTANT_H_INCLUDED
#define CONSTANT_H_INCLUDED
#define TAILLE_BLOC 34
enum{UP,DOWN,LEFT,RIGHT};
enum{VIDE,WALL,BOMBER};
#endif
main.c:
#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "header/game.h"
int main(){
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *menu = NULL;
SDL_Event event;
SDL_Surface *icon;
int runningGame=1;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Etna Bomber", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 952, 442, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, 0);
icon = IMG_Load("src/favicon.bmp");
SDL_SetWindowIcon(window, icon);
menu = IMG_LoadTexture(renderer, "src/menu.png");
SDL_FreeSurface(icon);
while(runningGame){
SDL_WaitEvent(&event);
switch(event.type){
case SDL_QUIT:
runningGame=0;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
runningGame=0;
break;
case SDLK_SPACE:
game(/*window,*/renderer);
default:
break;
}
break;
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, menu, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(menu);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
constant.h:
#ifndef CONSTANT_H_INCLUDED
#define CONSTANT_H_INCLUDED
#define TAILLE_BLOC 34
enum{UP,DOWN,LEFT,RIGHT};
enum{VIDE,WALL,BOMBER};
#endif
I tried using the SDL_QueryTexture function to check if the dimensions of the image were compatible with the dimensions of the window, and also verified that the image was not NULL after loading it using IMG_LoadTexture. I was expecting the image to be displayed on the window at the specified position, but it is not showing up. I also tried various other methods such as checking the file path and making sure the image is in the correct format, but the problem persists.
Related
when i start the code i get warning: incorrect audio format
i figured out its related to the mp3 file.
whats the problem and how can i fix it?
i already tried to convert the mp3 to a wav file but that also didnt work.
is it possible that 3mb of mp3 is to big? shouldnt be?
Edit: when i let it run without of mp3 the wav files will run just fine
with mp3 the programm will start but no sound at all
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
// Initialize SDL video and audio systems
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
// Initialize SDL mixer
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 3, 2048);
// Load audio files
Mix_Music *backgroundSound = Mix_LoadMUS("portfolio.mp3");
Mix_Chunk *jumpEffect = Mix_LoadWAV("JumpEffect.wav");
Mix_Chunk *laserEffect = Mix_LoadWAV("LaserEffect.wav");
//Mix_Chunk *musicEffect = Mix_LoadWAV("portfolio2.wav");
// Create a SDL window
SDL_Window *window = SDL_CreateWindow("Hello, SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
// Create a renderer (accelerated and in sync with the display refresh rate)
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
// Start the background music
Mix_PlayMusic(backgroundSound, -1);
bool running = true;
SDL_Event event;
while(running)
{
// Process events
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
else if(event.type == SDL_KEYDOWN)
{
// Press "1" and play jump effect
if(event.key.keysym.sym == SDLK_1)
{
Mix_PlayChannel(-1, jumpEffect, 0);
}
// Press "2" and play laser effect
else if(event.key.keysym.sym == SDLK_2)
{
Mix_PlayChannel(-1, laserEffect, 0);
}
}
}
// Clear screen
SDL_RenderClear(renderer);
// Draw
// Show what was drawn
SDL_RenderPresent(renderer);
}
// Release resources
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
Mix_FreeMusic(backgroundSound);
Mix_FreeChunk(jumpEffect);
Mix_FreeChunk(laserEffect);
//Mix_FreeChunk(music);
Mix_CloseAudio();
SDL_Quit();
return 0;
}
So I've recently started to learn SDL2, and I am trying run a simple program, but I don't know what I'm doing wrong. My IDE (Code Blocks) says that the line of code SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); has some kind of error and won't run. What am I missing or doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); // <-Supposed Error
SDL_Window *window = SDL_CreateWindow("Hey\n", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRendererDrawColor(renderer, 255, 0, 0, 255);
bool running = true;
SDL_Event event;
while(running)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
The linker error that I get is:
undefined reference to `SDL_SetRendererDrawColor'
Because this function doesn't exist in SDL2, you must use SDL_SetRenderDrawColor().
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
I'm using the SDL2 library, in C.
I made a test program to open a white window, but I get a segmentation fault with the function SDL_FillRect even though there are no errors or warnings when I build it.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
static const int window_width = 1000;
static const int window_height = 1000;
int main(int argc, char* argv[])
{
//Window
SDL_Window *window = NULL;
//Window Surface where things will be shown
SDL_Surface *surface = NULL;
//Inicializar SDL
if(SDL_Init(SDL_INIT_VIDEO) == -1)
{
printf("Failed to initialize SDL2. SDL Error: %s", SDL_GetError());
}
else
{
window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_SHOWN );
if(window == NULL)
printf("Failed to create SDL2 window. SDL Error: %s", SDL_GetError());
else
{
//Fill window with white color
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0xFF, 0xFF, 0xFF));
//Update surface with new changes
SDL_UpdateWindowSurface(window);
//Wait before closing (parameter in miliseconds)
SDL_Delay(4000);
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
You get Segmentation fault because surface is still NULL
This example code taken directly from the SDL wiki (https://wiki.libsdl.org/SDL_FillRect) shows how to create a SDL_Surface before calling SDL_FillRect()
/* Declaring the surface. */
SDL_Surface *s;
/* Creating the surface. */
s = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
/* Filling the surface with red color. */
SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 255, 0, 0));
I tried create window with gl 3.3 context, but it's eating cpu and lagging when I try to resize it.
My Code:
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <GL/glext.h>
struct _WGelWindowX11{
Display *XDspl;
Window XWin;
Colormap XCMap;
GLXContext glContext;
};
typedef struct _WGelWindowX11 WGelWindowX11;
#define WGEL_WINDOWX11(obj) ((WGelWindowX11*)obj)
int aiAttr[]={
GLX_X_RENDERABLE, True,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_DOUBLEBUFFER, True,
None
};
int aiAttrGL[]={
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
None
};
void *WGelWindowNew(void){
WGelWindowX11 *Result=malloc(sizeof(WGelWindowX11));
Result->XDspl=XOpenDisplay(NULL);
if (!Result->XDspl){
perror("Cannot open display.\n");
return NULL;
}
//Gettin' matchin' framebuffer configuration
int iFBCount;
GLXFBConfig *pFBConf=glXChooseFBConfig(Result->XDspl, DefaultScreen(Result->XDspl), aiAttr, &iFBCount);
if(!pFBConf){
perror("Cannot get FBConfig.\n");
return NULL;
}
int iBestFBC=-1, iWorstFBC=-1, iBestNSampl=-1, iWorstNSampl=999,iSamplBuff, iSampl, i;
for(i=0; i<iFBCount; i++){
XVisualInfo *vi=glXGetVisualFromFBConfig(Result->XDspl, pFBConf[i]);
if (vi){
glXGetFBConfigAttrib(Result->XDspl, pFBConf[i], GLX_SAMPLE_BUFFERS, &iSamplBuff);
glXGetFBConfigAttrib(Result->XDspl, pFBConf[i], GLX_SAMPLES, &iSampl);
if (iBestFBC<0 || iSamplBuff && iSampl>iBestNSampl) iBestFBC=i, iBestNSampl=iSampl;
if (iWorstFBC<0 || !iSamplBuff || iSampl<iWorstNSampl) iWorstFBC=i, iWorstNSampl=iSampl;
}
XFree(vi);
}
GLXFBConfig FBConfBest=pFBConf[iBestFBC];
XFree(pFBConf);
XVisualInfo *XVslnfo=glXGetVisualFromFBConfig(Result->XDspl, FBConfBest);
XSetWindowAttributes XWinAttr;
Result->XCMap=XCreateColormap(Result->XDspl, RootWindow(Result->XDspl, XVslnfo->screen), XVslnfo->visual, AllocNone);
XWinAttr.colormap=Result->XCMap;
XWinAttr.background_pixmap=None;
XWinAttr.border_pixel=0;
XWinAttr.event_mask=StructureNotifyMask|ExposureMask|KeyPressMask;
Atom wmDeleteMessage=XInternAtom(Result->XDspl, "WM_DELETE_WINDOW", FALSE);
Result->XWin=XCreateWindow(Result->XDspl, RootWindow(Result->XDspl, XVslnfo->screen), 0, 0, 300, 300, 0, XVslnfo->depth, InputOutput, XVslnfo->visual, CWBorderPixel|CWColormap|CWEventMask, &XWinAttr);
if(!Result->XWin){
perror("Cannot create window.\n");
return NULL;
}
XFree(XVslnfo);
XStoreName(Result->XDspl, Result->XWin, "WGel Window" );
XSetWMProtocols(Result->XDspl, Result->XWin, &wmDeleteMessage, 1);
XMapWindow(Result->XDspl, Result->XWin);
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB");
Result->glContext=glXCreateContextAttribs(Result->XDspl, FBConfBest, 0, True, aiAttrGL);
if(!Result->glContext){
perror("Cannot create GL 3.3 context\n");
return NULL;
}
glXMakeCurrent(Result->XDspl, Result->XWin, Result->glContext);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
return (void*)Result;}
Display *WGelX11GetDisplay(ptr window){
return WGEL_WINDOWX11(window)->XDspl;}
Window *WGelX11GetWindow(ptr window){
return &(WGEL_WINDOWX11(window)->XWin);
}
int main(void){
ptr frmMain=WGelWindowNew();
Display *dpy=WGelX11GetDisplay(frmMain);
XEvent e;
while(XNextEvent(dpy, &e)>=0){
if ((!XPending(dpy))&&(e.type==Expose)){
glClear(GL_COLOR_BUFFER_BIT);
glXSwapBuffers(dpy, *WGelX11GetWindow(frmMain));
}
if (e.type==ClientMessage){
XDestroyWindow(dpy, e.xclient.window);
break;
}
}
XCloseDisplay(dpy);
return EXIT_SUCCESS;}
GTK+ windows are not lagging that hard when I resize them, so I suppose there should be a way to get rid of that lagging.
Firstly, you have to ignore all Expose event and handle only the last one.
You can do like :
XNextEvent(dpy, &e);
switch (e.type)
{
case Expose:
/* Unless this is the last contiguous expose,
* don’t draw the window */
if (e.xexpose.count == 0)
{
// DRAW THINGS
}
break;
case ClientMessage:
XDestroyWindow(dpy, e.xclient.window);
break;
default:
break;
}
For better handling of Resizing, you have to catch the ConfigureNotify event.
Probably the same reason as I wrote about here: Is there a way to change ConfigureNotify event frequency in X11?
The basic fix: do not repaint at every resize event, your mouse generates events a lot faster than you can repaint the screen.
In SDL2 I want to be able to draw changes to one buffer rather than redraw the whole image to two different buffers as my setup seems to be doing. Below is a really quick test which shows the unwanted behavior:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>
// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
void putPixel(SDL_Renderer *renderer, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderDrawPoint(renderer, x, y);
}
int main(int argc, char* argv[]) {
int width = 640;
int height = 480;
SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
if (window == NULL)
{
return -1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
return -2;
}
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for(int x=0;x<8;x++)
{
for(int y=0;y<10;y++)
{
putPixel(renderer,40+x*10,50+y);
}
SDL_RenderPresent(renderer);
sleep(1);
}
SDL_Quit();
return 0;
}
The output from this is two alternating screens. It is obviously using a double buffer which means I have to clear and redraw to get the output I want. After each cycle of the for...loop I wanted to add a line to the buffer - there should have been 8 lines at the end of the program running. In this case I got 4 on one buffer and 4 on another. I don't want to redraw the previous lines again either, hence the need for one buffer:
This uses a texture as a buffer and copies this to the screen when done.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>
// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
void putPixel(SDL_Renderer *renderer, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderDrawPoint(renderer, x, y);
}
int main(int argc, char* argv[]) {
int width = 640;
int height = 480;
SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
if (window == NULL)
{
return -1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
if (renderer == NULL)
{
return -2;
}
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
/* Create texture for display */
SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
SDL_SetRenderTarget(renderer, display);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for(int x=0;x<8;x++)
{
SDL_SetRenderTarget(renderer, display);
for(int y=0;y<10;y++)
{
putPixel(renderer,40+x*10,50+y);
}
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, display, NULL, NULL);
SDL_RenderPresent(renderer);
sleep(1);
}
SDL_Quit();
return 0;
}
The output from this is below: