SDL game loop

please can someone help me to correct this code?
i wanted to make an animation of start game that ends just by pressing on the sentence “press HERE to start menu” , but once i move cursor it doesn’t work :pensive:
ps : i couldn’t upload the full file with font and image cuz im a new user sorry

#include <stdio.h>
#include <string.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const int SCROLL_SPEED = 2;
const int ANIMATION_DURATION = 1000 / 30;

SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;

SDL_Texture* imageTexture = NULL;
SDL_Rect spriteRect = {0, 0, 0, 0};

Mix_Music* music = NULL;

TTF_Font* menuFont = NULL;

double oldTime = 0.0;
double newTime = 0.0;
double deltaTime = 0.0;

int spriteXDirection = 1;

float spriteXPosition = 0.0f;
float spriteYPosition = 0.0f;
float spriteMovementSpeed = 300.0f;

int running = 1;

int initSDL() {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("Error: SDL could not initialize! %s\n", SDL_GetError());
        return 0;
    }

    if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) {
        printf("Error: SDL_Image could not initialize. %s\n", IMG_GetError());
        return 0;
    }

    if (TTF_Init() == -1) {
        printf("Error: SDL_TTF could not initialize! %s\n", TTF_GetError());
        return 0;
    }

    if (Mix_Init(MIX_INIT_MP3) != MIX_INIT_MP3) {
        printf("Error: SDL_Mixer could not initialize! %s\n", Mix_GetError());
        return 0;
    }

    window = SDL_CreateWindow("SDL Animation", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
    if (!window) {
        printf("Error: SDL window could not be created! %s\n", SDL_GetError());
        return 0;
    }

    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        printf("Error: SDL renderer could not be created! %s\n", SDL_GetError());
        return 0;
    }

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);

    return 1;
}

void renderText(const char* text, int x, int y, SDL_Color color,int animation1) {
    if(animation1){
    SDL_Surface* surface = TTF_RenderText_Solid(menuFont, text, color);
    SDL_Texture* textexture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_Rect textRect = {x, y, surface->w, surface->h};
    SDL_RenderCopy(renderer, textexture, NULL, &textRect);

    SDL_FreeSurface(surface);
    SDL_DestroyTexture(textexture);
    }
}
void cleanupSDL() {
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    Mix_Quit();
    TTF_Quit();
    IMG_Quit();
    SDL_Quit();
}

int initAssets() {
    SDL_Surface* imageSurface = IMG_Load("imagesdl2.png");
    if (!imageSurface) {
        printf("Error: failed to load image! %s\n", SDL_GetError());
        return 0;
    }
    imageTexture = SDL_CreateTextureFromSurface(renderer, imageSurface);
    SDL_FreeSurface(imageSurface);
    if (!imageTexture) {
        printf("Error: failed to create SDL texture! %s\n", SDL_GetError());
        return 0;
    }

    int textureWidth = 0;
    int textureHeight = 0;
    SDL_QueryTexture(imageTexture, NULL, NULL, &textureWidth, &textureHeight);

    spriteXPosition = (float)((WINDOW_WIDTH * 0.5f) - (textureWidth * 0.5f));
    spriteYPosition = (float)((WINDOW_HEIGHT * 0.5f) - (textureHeight * 0.5f));

    spriteRect.x = (int)spriteXPosition;
    spriteRect.y = (int)spriteYPosition;
    spriteRect.w = textureWidth;
    spriteRect.h = textureHeight;

    menuFont = TTF_OpenFont("ChrustyRock-ORLA.ttf", 45);
    if (!menuFont) {
        printf("Error: failed to load font! %s\n", TTF_GetError());
        return 0;
    }

    return 1;
}
void cleanupAssets() {
    TTF_CloseFont(menuFont);
    menuFont = NULL;

    SDL_DestroyTexture(imageTexture);
    imageTexture = NULL;
}

void update(int animation1) {
    if(animation1){
    if (spriteXDirection == 1) {
        spriteXPosition += spriteMovementSpeed * (float)deltaTime;

        if (spriteXPosition >= (float)(WINDOW_WIDTH - spriteRect.w))
            spriteXDirection = 0;
    } else {
        spriteXPosition -= spriteMovementSpeed * (float)deltaTime;

        if (spriteXPosition <= 0.0f)
            spriteXDirection = 1;
    }
    }
    spriteRect.x = (int)spriteXPosition;
    spriteRect.y = (int)spriteYPosition;
}

void renderanimationtext1(int isMouseOver,int animation1) {
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
     if(animation1){
      if (isMouseOver) {
            renderText("Press ", 90, 470, (SDL_Color){ 255, 0, 0}, animation1);
            renderText(" HERE ", 230, 470, (SDL_Color){ 255, 0, 80}, animation1);
            renderText("to start menu", 385, 470, (SDL_Color){ 255, 0, 0}, animation1);
        } else {
            renderText("Press HERE to start menu", 90, 470, (SDL_Color){255, 0, 0, 80}, animation1);
        }
     }
     isMouseOver = 0;
    SDL_RenderCopy(renderer, imageTexture, NULL, &spriteRect);

    SDL_RenderPresent(renderer);
}

int audioThread(void* data) {
    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);

    Mix_Music* music = Mix_LoadMUS("initjeuaudio.mp3");

    if (music)
        Mix_PlayMusic(music, 0);

    while (Mix_PlayingMusic()) {
        SDL_Delay(1000 / 60);
    }

    if (music)
        Mix_FreeMusic(music);

    Mix_CloseAudio();
    Mix_Quit();

    return 0;
}

typedef struct {
    SDL_Rect rect;
    SDL_Color color;
    char buttontext[50];
    TTF_Font* buttonfont;
    SDL_bool isClicked;
} Button;
// Fonction pour initialiser un bouton
Button createButton(int x, int y, int width, int height, SDL_Color color, const char* buttontext, TTF_Font* buttonfont) {
    Button button;
    button.rect.x = x;
    button.rect.y = y;
    button.rect.w = width;
    button.rect.h = height;
    button.color = color;
    button.isClicked = SDL_FALSE;
    strncpy(button.buttontext, buttontext, sizeof(button.buttontext) - 1);
    button.buttontext[sizeof(button.buttontext) - 1] = '\0'; // S'assurer que la chaîne est terminée
    button.buttonfont = buttonfont;
    return button;
}

// Fonction pour vérifier si les coordonnées (x, y) sont à l'intérieur du bouton
SDL_bool pointInsideRect(int x, int y, SDL_Rect* buttonrect,int animation1) {
    if(animation1 == 0){
    return (x >= buttonrect->x && x < buttonrect->x + buttonrect->w && y >= buttonrect->y && y < buttonrect->y + buttonrect->h);
}
}

// Fonction pour rendre le bouton avec du texte à l'intérieur
void renderButton(SDL_Renderer* renderer, const Button* button) {
    // Rendre le rectangle du bouton

    SDL_SetRenderDrawColor(renderer, button->color.r, button->color.g, button->color.b, button->color.a);
    SDL_RenderFillRect(renderer, &button->rect);

    // Rendre le texte à l'intérieur du bouton
    SDL_Surface* textSurface = TTF_RenderText_Solid(button->buttonfont, button->buttontext, (SDL_Color){255, 255, 255, 255});
    SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

    int textWidth, textHeight;
    SDL_QueryTexture(textTexture, NULL, NULL, &textWidth, &textHeight);

    SDL_Rect textRect = {
        button->rect.x + (button->rect.w - textWidth) / 2,
        button->rect.y + (button->rect.h - textHeight) / 2,
        textWidth,
        textHeight
    };

    SDL_RenderCopy(renderer, textTexture, NULL, &textRect);

    SDL_FreeSurface(textSurface);
    SDL_DestroyTexture(textTexture);
}
int main(int argc, char** argv) {
    if (!initSDL())
        running = 0;

    if (!initAssets())
        running = 0;
TTF_Font* buttonfont = TTF_OpenFont("ChrustyRock-ORLA.ttf", 24);
    SDL_Thread* thread = SDL_CreateThread(audioThread, "Audio", NULL);
       int isMouseOver = 0;
       int mouseX;
       int mouseY;
       int textX;
       int textY;
       int textWidth;
       int textHeight;
       int animation1;
Button Button1 = createButton(170, 350, 200, 50, (SDL_Color){255, 0, 0, 255}, "start!", buttonfont);
Button Button2 = createButton(430, 350, 200, 50, (SDL_Color){255, 0, 0, 255}, "Click me!", buttonfont);
Button Button3 = createButton(170, 450 ,200, 50, (SDL_Color){255, 0, 0, 255}, "Click me!", buttonfont);
Button Button4 = createButton(430, 450, 200, 50, (SDL_Color){255, 0, 0, 255}, "Click me!", buttonfont);
    SDL_Event event;
while(running){
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = 0;
                    break;
                case SDL_MOUSEMOTION:
                     mouseX = event.motion.x;
                     mouseY = event.motion.y;
                     textX = 70;
                     textY = 470;
                     textWidth = 300;
                     textHeight = 30;
                     animation1=1;
                    if (mouseX >= textX && mouseX <= textX + textWidth &&
                        mouseY >= textY && mouseY <= textY + textHeight) {
                        isMouseOver = 1;
                    } else {
                        isMouseOver = 0;
                    }
                    break;
                case SDL_MOUSEBUTTONDOWN:
                    // Vérifier si le clic a eu lieu sur la phrase
                    if (isMouseOver) {

                        printf("Clic sur la phrase!\n");
                        animation1 = 0;
                    }
            }
                    if(animation1 == 0){
                        // Ici, vous pouvez afficher votre menu
                        if (pointInsideRect(mouseX, mouseY, &Button1.rect, animation1)) {

                         Button1.isClicked = SDL_TRUE;
                         printf("Button1 clicked!\n");


                }
                    else if (pointInsideRect(mouseX, mouseY, &Button2.rect, animation1)) {
                    Button2.isClicked = SDL_TRUE;
                    printf("Button2 clicked!\n");

                }

                else if (pointInsideRect(mouseX, mouseY, &Button3.rect, animation1)) {
                     Button3.isClicked = SDL_TRUE;
                    printf("Button3 clicked!\n");
                }
               else if (pointInsideRect(mouseX, mouseY, &Button4.rect, animation1)) {
                    Button4.isClicked = SDL_TRUE;
                    printf("Button4 clicked!\n");
                }
                    }
                    break;
            }

        newTime = (double)SDL_GetTicks();
        deltaTime = (newTime - oldTime) * 0.001;
        oldTime = newTime;
        if(animation1==1){
        update(animation1);

        renderanimationtext1(isMouseOver,animation1);
        SDL_Delay(1);
        }
         SDL_RenderClear(renderer);
         if(animation1 == 0){

         renderButton(renderer, &Button1);
         renderButton(renderer, &Button2);
         renderButton(renderer, &Button3);
         renderButton(renderer, &Button4);
        SDL_RenderPresent(renderer);
         }
         SDL_RenderClear(renderer);

    }

    int threadReturnValue = 0;
    SDL_WaitThread(thread, &threadReturnValue);
    TTF_CloseFont(buttonfont);
    cleanupAssets();
    cleanupSDL();

    return 0;
}
1 Like

Was the code sample I wrote to you in this thread not usable: SDL2 switch animation?

You don’t seem to use that version of the code, since you’re back on using the SDL_RenderClear and SDL_RenderPresent functions multiple times in your current code again, which I adviced on not doing.
One (1) call each to those functions per game loop is enough for most cases.

It won’t solve the issue with your current code though.
I haven’t read through the whole code but you should probably check if the mouse pointer is inside any of the buttons, and if a mouse button is pressed while still inside it, change the application to some menu/screen.

You should look up a term called “game states”. That pattern/code design lets you construct various states the application/game can be in and also lets you traverse between those states, for example a menu state, a settings menu state, a game state etc.

goodmorning , thanks for your reply and sorry i didn’t see the previous reply on my thread “sdlanimation”,i’ve used SDL_RenderClear and SDL_RenderPresent because i thought that it would allow me to close the first animation , clear the window sdl and reset the renderer again to appear the next state on the window , but i guess that i didn’t understand how these functions work , second i want to ask if the pointer to the mousemotion will change depending on the animation or case im working on or not ? and if so how can i use it? because once i move the cursor in the second state which is the menu , it goes back to the state one which is the first animation of the game , knowing that i’ve used the same pointer

I understand the confusion regarding those functions.

In simple terms, the SDL_RenderClear function basically clears the whole window to a color of your choice and SDL_RenderPresent basically updates the window, such that the graphical objects that’s been submitted to the window (with SDL_RenderCopy and various other functions) is rendered/shown.
So in a basic game loop, you usually call SDL_RenderClear, followed by functions for rendering stuff, for example SDL_RenderCopy, and then finally update the window with SDL_RenderPresent, which makes all the submitted graphical objects showing up in the window.

All this usually happens every single frame.

When it comes to rendering some stuff and some not, it basically ends up having different game states. So in one state, you render only some of the buttons and then in another state you render only some other buttons. The buttons in state 2 will then not be rendered in state 1, and vice versa.

I’m not at a computer at the moment so I can’t write any code, but the next time I’m at one, I might have time to write a code example showing a simple usage of game states.

I had some time to write a code example showing a simple state machine, and the usage of it.

Below I’ve attached the code example.
I’ve written some comments that explains what everything does and how it works.
Read through the code and see that you understand it all. Ask for the things that you don’t understand. Hopefully the code is pretty self-explanatory.

You should be able to just take the whole code, paste it into a *.cpp file and then compile and run it.

Code
#include <stdio.h>
#include <string>

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>

#define WINDOW_WIDTH	(800)
#define WINDOW_HEIGHT	(600)

// The different states the application can be in
enum GameState
{
	MENU = 0,
	GAME,
};

struct Button
{
	SDL_Texture* texture = nullptr;
	SDL_Rect rect = {0, 0, 0, 0};
	SDL_Color backgroundColor = {0, 0, 0, 255};
	SDL_Color textColor = {255, 255, 255, 255};
	SDL_Color textColorHovered = {255, 255, 255, 255};
};

SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;

TTF_Font* infoTextFont = nullptr;
TTF_Font* buttonFont = nullptr;

Button* startGameButton = nullptr;
Button* backButton = nullptr;

SDL_Point mousePosition = {0, 0};

SDL_Color buttonBackgroundColor = {0, 0, 0, 255};
SDL_Color buttonTextColor = {255, 255, 255, 255};
SDL_Color buttonTextColorHovered = {255, 0, 0, 255};

Uint32 currentMouseButtonState = 0;
Uint32 lastMouseButtonState = 0;

// The state the application is currently in
GameState currentState = GameState::MENU; 

bool running = true;

bool mouseButtonPressed(const int mouseButton)
{
	return (!(currentMouseButtonState & SDL_BUTTON(mouseButton)) && (lastMouseButtonState & SDL_BUTTON(mouseButton)));
}

bool pointInsideButton(Button* button, const SDL_Point& point)
{
	return (SDL_PointInRect(&point, &button->rect) == SDL_TRUE);
}

Button* createButton(TTF_Font* font, const std::string& text, const SDL_Color& backgroundColor, const SDL_Color& textColor, const SDL_Color& textColorHovered)
{
	SDL_Surface* surface = TTF_RenderText_Blended(font, text.c_str(), {255, 255, 255, 255});

	if(!surface)
		return nullptr;

	SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

	SDL_FreeSurface(surface);
	surface = nullptr;

	if(!texture)
		return nullptr;

	int textureWidth = 0;
	int textureHeight = 0;
	SDL_QueryTexture(texture, nullptr, nullptr, &textureWidth, &textureHeight);

	Button* button = new Button;
	button->texture = texture;
	button->rect = {0, 0, textureWidth, textureHeight};
	button->backgroundColor = backgroundColor;
	button->textColor = textColor;
	button->textColorHovered = textColorHovered;

	return button;
}

void renderButton(Button* button, const SDL_Point& mousePosition)
{
	SDL_SetRenderDrawColor(renderer, button->backgroundColor.r, button->backgroundColor.g, button->backgroundColor.b, button->backgroundColor.a);
	SDL_RenderFillRect(renderer, &button->rect);

	// Used to change the texture's button-text to button->textColorHovered if the button is hovered
	const SDL_Color colorMod = (pointInsideButton(button, mousePosition) ? button->textColorHovered : button->textColor);
	SDL_SetTextureColorMod(button->texture, colorMod.r, colorMod.g, colorMod.b);

	SDL_RenderCopy(renderer, button->texture, nullptr, &button->rect);
}

bool renderText(TTF_Font* font, const std::string& text, const SDL_Point& position, const SDL_Color& color)
{
	SDL_Surface* surface = TTF_RenderText_Solid(font, text.c_str(), color);

	if(!surface)
		return false;

	SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

	SDL_FreeSurface(surface);
	surface = nullptr;

	if(!texture)
		return false;

	int textureWidth = 0;
	int textureHeight = 0;
	SDL_QueryTexture(texture, nullptr, nullptr, &textureWidth, &textureHeight);

	const SDL_Rect dstRect = {position.x, position.y, textureWidth, textureHeight};

	SDL_RenderCopy(renderer, texture, nullptr, &dstRect);

	SDL_DestroyTexture(texture);
	texture = nullptr;

	return true;
}

bool initSDL()
{
	if(SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("Error: SDL could not initialize! %s\n", SDL_GetError());

		return false;
	}

	if(IMG_Init(IMG_InitFlags::IMG_INIT_PNG) != IMG_InitFlags::IMG_INIT_PNG)
	{
		printf("Error: SDL_Image could not initialize. %s\n", IMG_GetError());
		return false;
	}

	if(TTF_Init() == -1)
	{
		printf("Error: SDL_TTF could not initialize! %s\n", TTF_GetError());
		return false;
	}

	if (Mix_Init(MIX_InitFlags::MIX_INIT_MP3) != MIX_InitFlags::MIX_INIT_MP3)
	{
		printf("Error: SDL_Mixer could not initialize! %s\n", Mix_GetError());
		return false;
	}

	window = SDL_CreateWindow("SDL + game states", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
	if(!window)
	{
		printf("Error: SDL window could not be created! %s\n", SDL_GetError());
		return false;
	}

	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
	if(!renderer)
	{
		printf("Error: SDL renderer could not be created! %s\n", SDL_GetError());
		return false;
	}

	SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
	SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);

	SDL_RenderClear(renderer);
	SDL_RenderPresent(renderer);

	SDL_GetMouseState(&mousePosition.x, &mousePosition.y);

	return true;
}

void cleanupSDL()
{
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);

	Mix_Quit();
	TTF_Quit();
	IMG_Quit();
	SDL_Quit();
}

bool initAssets()
{
	infoTextFont = TTF_OpenFont("ChrustyRock-ORLA.ttf", 20); 
	if(!infoTextFont)
	{
		printf("Error: failed to load font! %s\n", TTF_GetError());
		return false;
	}

	buttonFont = TTF_OpenFont("ChrustyRock-ORLA.ttf", 28); 
	if(!buttonFont)
	{
		printf("Error: failed to load font! %s\n", TTF_GetError());
		return false;
	}

	startGameButton = createButton(buttonFont, "Start game", buttonBackgroundColor, buttonTextColor, buttonTextColorHovered);
	if(!startGameButton)
		return false;
	startGameButton->rect.x = (WINDOW_WIDTH	 / 2) - (startGameButton->rect.w / 2);
	startGameButton->rect.y = (WINDOW_HEIGHT / 2) - (startGameButton->rect.h / 2);

	backButton = createButton(buttonFont, "Back", buttonBackgroundColor, buttonTextColor, buttonTextColorHovered);
	if(!backButton)
		return false;
	backButton->rect.x = 10;
	backButton->rect.y = (WINDOW_HEIGHT - backButton->rect.h) - 10;

	return true;
}

void cleanupAssets()
{
	SDL_DestroyTexture(backButton->texture);
	backButton->texture = nullptr;
	delete backButton;
	backButton = nullptr;

	SDL_DestroyTexture(startGameButton->texture);
	startGameButton->texture = nullptr;
	delete startGameButton;
	startGameButton = nullptr;

	TTF_CloseFont(buttonFont);
	buttonFont = nullptr;

	TTF_CloseFont(infoTextFont);
	infoTextFont = nullptr;
}

void update()
{
	// A very simple state machine
	// Only the state that the application is currently in is updated

	// The application is in the menu state so only have to check mouse-button presses against the "start game" button
	if(currentState == GameState::MENU)
	{
		if(pointInsideButton(startGameButton, mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
			currentState = GameState::GAME;
	}

	// The application is in the game state so only have to check mouse-button presses against the "back" button
	else if(currentState == GameState::GAME)
	{
		if(pointInsideButton(backButton, mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
			currentState = GameState::MENU;
	}
}

void render()
{
	// Clear the window with the specified clear color (gray in this case)
	SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255);
	SDL_RenderClear(renderer);

	//////////////////////////////////////////////////////////////////////////

	// Render all the graphical objects here

	// A very simple state machine
	// Only the state that the application is currently in is rendered

	// The application is in the menu state so render only the menu state's graphical objects
	if(currentState == GameState::MENU)
	{
		renderText(infoTextFont, "The application is now in the MENU state", {10, 10}, {255, 255, 255, 255});
		renderText(infoTextFont, "Press the 'Start game' button to change to the GAME state", {10, 50}, {255, 255, 255, 255});
		renderButton(startGameButton, mousePosition);
	}

	// The application is in the game state so render only the game state's graphical objects
	else if(currentState == GameState::GAME)
	{
		renderText(infoTextFont, "The application is now in the GAME state", {10, 10}, {255, 255, 255, 255});
		renderText(infoTextFont, "Press the 'Back' button to change to the MENU state", {10, 50}, {255, 255, 255, 255});
		renderButton(backButton, mousePosition);
	}

	//////////////////////////////////////////////////////////////////////////

	// Update the window so the graphical objects are rendered/shown in the window
	SDL_RenderPresent(renderer);
}

int main(int argc, char** argv)
{
	if(!initSDL())
		return -1;

	if(!initAssets())
		return -1;

	SDL_Event event;
	while(running)
	{
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
				{
					running = false;

					break;
				}

				default:
					break;
			}
		}

		lastMouseButtonState = currentMouseButtonState;

		// Retrieve the current mouse state (for its buttons), and also its position
		currentMouseButtonState = SDL_GetMouseState(&mousePosition.x, &mousePosition.y);

		update();
		render();

		// Let the processor do something else for a short while
		SDL_Delay(1);
	}

	cleanupAssets();
	cleanupSDL();

	return 0;
}

heyyy , thank you so much for helping I COULD MAKE IT !! :sob: :sob: :smiling_face_with_three_hearts:
check the code rn , i just have to change the colors and fonts and also add the animation i made in the previous code but i just wanted to thank u veryyy much :heart:
here is the code

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>
#include<stdbool.h>

#define WINDOW_WIDTH	(800)
#define WINDOW_HEIGHT	(600)

// The different states the application can be in
typedef enum {
    BEGINNING = 0,
    MENU = 1,
    GAME = 2,
    ABOUTUS = 3,
    GUIDEGAME = 4,
    USERSLIST = 5,
    PLAYERMODE = 6,
    COMPUTERMODE = 7,


} GameState;

typedef struct {
    SDL_Texture* texture;
    SDL_Rect rect;
    SDL_Color backgroundColor;
    SDL_Color textColor;
    SDL_Color textColorHovered;
} Button;

SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;

TTF_Font* infoTextFont = NULL;
TTF_Font* buttonFont = NULL;

Button* startGameButton = NULL;
Button* startGameButton2 = NULL;
Button* UserMode = NULL;
Button* ComputerMode = NULL;
Button* backButton = NULL;
Button* AboutUs = NULL;
Button* GuideGame = NULL;
Button* GamersList = NULL;

SDL_Point mousePosition = {0, 0};

SDL_Color buttonBackgroundColor = {0, 0, 0, 255};
SDL_Color buttonTextColor = {255, 255, 255, 255};
SDL_Color buttonTextColorHovered = {255, 0, 0, 255};

Uint32 currentMouseButtonState = 0;
Uint32 lastMouseButtonState = 0;

GameState currentState = BEGINNING;

bool running = true;

bool mouseButtonPressed(const int mouseButton) {
    return (!(currentMouseButtonState & SDL_BUTTON(mouseButton)) && (lastMouseButtonState & SDL_BUTTON(mouseButton)));
}

bool pointInsideButton(Button* button, const SDL_Point* point) {
    return (SDL_PointInRect(point, &button->rect) == SDL_TRUE);
}

Button* createButton(TTF_Font* font, const char* text, const SDL_Color* backgroundColor, const SDL_Color* textColor, const SDL_Color* textColorHovered) {
    SDL_Surface* surface = TTF_RenderText_Blended(font, text, (SDL_Color){255, 255, 255, 255});

    if (!surface)
        return NULL;

    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

    SDL_FreeSurface(surface);
    surface = NULL;

    if (!texture)
        return NULL;

    int textureWidth = 0;
    int textureHeight = 0;
    SDL_QueryTexture(texture, NULL, NULL, &textureWidth, &textureHeight);

    Button* button = (Button*)malloc(sizeof(Button));
    button->texture = texture;
    button->rect = (SDL_Rect){0, 0, textureWidth, textureHeight};
    button->backgroundColor = *backgroundColor;
    button->textColor = *textColor;
    button->textColorHovered = *textColorHovered;

    return button;
}

void renderButton(Button* button, const SDL_Point* mousePosition) {
    SDL_SetRenderDrawColor(renderer, button->backgroundColor.r, button->backgroundColor.g, button->backgroundColor.b, button->backgroundColor.a);
    SDL_RenderFillRect(renderer, &button->rect);

    const SDL_Color colorMod = (pointInsideButton(button, mousePosition) ? button->textColorHovered : button->textColor);
    SDL_SetTextureColorMod(button->texture, colorMod.r, colorMod.g, colorMod.b);

    SDL_RenderCopy(renderer, button->texture, NULL, &button->rect);
}

bool renderText(TTF_Font* font, const char* text, const SDL_Point* position, const SDL_Color* color) {
    SDL_Surface* surface = TTF_RenderText_Solid(font, text, *color);

    if (!surface)
        return false;

    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

    SDL_FreeSurface(surface);
    surface = NULL;

    if (!texture)
        return false;

    int textureWidth = 0;
    int textureHeight = 0;
    SDL_QueryTexture(texture, NULL, NULL, &textureWidth, &textureHeight);

    const SDL_Rect dstRect = {position->x, position->y, textureWidth, textureHeight};

    SDL_RenderCopy(renderer, texture, NULL, &dstRect);

    SDL_DestroyTexture(texture);

    return true;
}

bool initSDL() {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("Error: SDL could not initialize! %s\n", SDL_GetError());
        return false;
    }

    if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) {
        printf("Error: SDL_Image could not initialize. %s\n", IMG_GetError());
        return false;
    }

    if (TTF_Init() == -1) {
        printf("Error: SDL_TTF could not initialize! %s\n", TTF_GetError());
        return false;
    }

    if (Mix_Init(MIX_INIT_MP3) != MIX_INIT_MP3) {
        printf("Error: SDL_Mixer could not initialize! %s\n", Mix_GetError());
        return false;
    }

    window = SDL_CreateWindow("SDL + game states", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
    if (!window) {
        printf("Error: SDL window could not be created! %s\n", SDL_GetError());
        return false;
    }

    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        printf("Error: SDL renderer could not be created! %s\n", SDL_GetError());
        return false;
    }

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);

    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);

    SDL_GetMouseState(&mousePosition.x, &mousePosition.y);

    return true;
}

void cleanupSDL() {
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    Mix_Quit();
    TTF_Quit();
    IMG_Quit();
    SDL_Quit();
}

bool initAssets() {
    infoTextFont = TTF_OpenFont("ChrustyRock-ORLA.ttf", 20);
    if (!infoTextFont) {
        printf("Error: failed to load font! %s\n", TTF_GetError());
        return false;
    }

    buttonFont = TTF_OpenFont("ChrustyRock-ORLA.ttf", 28);
    if (!buttonFont) {
        printf("Error: failed to load font! %s\n", TTF_GetError());
        return false;
    }

    startGameButton = createButton(buttonFont, "Start game", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if (!startGameButton)
        return false;
    startGameButton->rect.x = (WINDOW_WIDTH / 2) - (startGameButton->rect.w / 2);
    startGameButton->rect.y = (WINDOW_HEIGHT / 2) - (startGameButton->rect.h / 2);

     UserMode = createButton(buttonFont, "User Mode", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if (!UserMode)
        return false;
    UserMode->rect.x = 400;
    UserMode->rect.y = (WINDOW_HEIGHT / 2) - (startGameButton->rect.h / 2);

     ComputerMode = createButton(buttonFont, "Computer Mode", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if (!ComputerMode)
        return false;
    ComputerMode->rect.x = 50;
    ComputerMode->rect.y = (WINDOW_HEIGHT / 2) - (startGameButton->rect.h / 2);

    startGameButton2 = createButton(buttonFont, "start",&buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered );
    if (!startGameButton2)
        return false;
    startGameButton2->rect.x = 170;
    startGameButton2->rect.y = 350;

    AboutUs = createButton(buttonFont, "About Us", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if(!AboutUs)
        return false;
    AboutUs->rect.x = 430;
    AboutUs->rect.y = 350;

    GuideGame = createButton(buttonFont, "GuideGame", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if(!GuideGame)
        return false;
    GuideGame->rect.x = 170;
    GuideGame->rect.y = 450;

    GamersList = createButton(buttonFont, "Gamers list", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if(!GamersList)
        return false;
    GamersList->rect.x = 430;
    GamersList->rect.y = 450;

    backButton = createButton(buttonFont, "Back", &buttonBackgroundColor, &buttonTextColor, &buttonTextColorHovered);
    if (!backButton)
        return false;
    backButton->rect.x = 10;
    backButton->rect.y = (WINDOW_HEIGHT - backButton->rect.h) - 10;

    return true;
}

void cleanupAssets() {
    SDL_DestroyTexture(backButton->texture);
    free(backButton);

    SDL_DestroyTexture(startGameButton->texture);
    free(startGameButton);

    SDL_DestroyTexture(startGameButton2->texture);
    free(startGameButton2);
    SDL_DestroyTexture(AboutUs->texture);
    free(AboutUs);
    SDL_DestroyTexture(GuideGame->texture);
    free(GuideGame);
    SDL_DestroyTexture(GamersList->texture);
    free(GamersList);
    TTF_CloseFont(buttonFont);
    TTF_CloseFont(infoTextFont);
}

void update() {
    if (currentState == BEGINNING) {
        if (pointInsideButton(startGameButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
            currentState = MENU;
    } else if (currentState == MENU) {
        if (pointInsideButton(startGameButton2, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
            currentState = GAME;
        }
         else if (pointInsideButton(AboutUs, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
             currentState = ABOUTUS;
        }
        else if (pointInsideButton(GuideGame, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
            currentState = GUIDEGAME;
            }
        else if (pointInsideButton(GamersList, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
            currentState = USERSLIST;}
            }
        else if(currentState == GAME){
            if(pointInsideButton(UserMode, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
                currentState = PLAYERMODE;

            }else if(pointInsideButton(ComputerMode, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
             currentState = COMPUTERMODE;
             }else if(pointInsideButton(backButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT)){
             currentState = MENU;
             }
            }
            else if(currentState == COMPUTERMODE){
            if(pointInsideButton(backButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
               currentState = MENU;
               }
            else if(currentState == PLAYERMODE){
            if(pointInsideButton(backButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
               currentState = MENU;
               }
        else if(currentState == ABOUTUS){
            if(pointInsideButton(backButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
               currentState = MENU;
               }
        else if(currentState == GUIDEGAME){
                if(pointInsideButton(backButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
                   currentState = MENU;
                   }
        else if(currentState == USERSLIST){
            if(pointInsideButton(backButton, &mousePosition) && mouseButtonPressed(SDL_BUTTON_LEFT))
                   currentState = MENU;
        }

    }


void render() {
    SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255);
    SDL_RenderClear(renderer);

    if (currentState == BEGINNING) {
            //render animation
        renderText(infoTextFont, "The application is now in the MENU state", &(SDL_Point){10, 10}, &(SDL_Color){255, 255, 255, 255});
        renderText(infoTextFont, "Press the 'Start game' button to change to the GAME state", &(SDL_Point){10, 50}, &(SDL_Color){255, 255, 255, 255});
        renderButton(startGameButton, &mousePosition);
    } else if (currentState == MENU) {

        renderButton(startGameButton2, &mousePosition);
        renderButton(AboutUs, &mousePosition);
        renderButton(GuideGame, &mousePosition);
        renderButton(GamersList, &mousePosition);

    }else if(currentState == GAME){
        renderText(infoTextFont, "choose one of the modes here :", &(SDL_Point){10, 50}, &(SDL_Color){255, 255, 255, 255});
        renderButton(UserMode, &mousePosition);
        renderButton(ComputerMode, &mousePosition);
        renderButton(backButton, &mousePosition);

    }else if(currentState == ABOUTUS){
        renderText(infoTextFont, "i have to talk here about us and the project", &(SDL_Point){10, 50}, &(SDL_Color){255, 255, 255, 255});
        renderButton(backButton, &mousePosition);

    }else if(currentState == GUIDEGAME){
        renderText(infoTextFont, "i have to talk here about the guide of game in general", &(SDL_Point){10, 50}, &(SDL_Color){255, 255, 255, 255});
        renderButton(backButton, &mousePosition);
    }else if(currentState == USERSLIST){
        renderText(infoTextFont, "there will be a table here for gamers list ", &(SDL_Point){10, 50}, &(SDL_Color){255, 255, 255, 255});
        renderButton(backButton, &mousePosition);
    }else if(currentState == PLAYERMODE){
        renderButton(backButton, &mousePosition);
    }else if(currentState == COMPUTERMODE){
        renderButton(backButton, &mousePosition);
    }
    SDL_RenderPresent(renderer);
}

int main(int argc, char** argv) {
    if (!initSDL())
        return -1;

    if (!initAssets())
        return -1;

    SDL_Event event;
    while (running) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = false;
                    break;

                default:
                    break;
            }
        }

        lastMouseButtonState = currentMouseButtonState;

        currentMouseButtonState = SDL_GetMouseState(&mousePosition.x, &mousePosition.y);

        update();
        render();

        SDL_Delay(1);
    }

    cleanupAssets();
    cleanupSDL();

    return 0;
}

thank you again <3

Did the code example work as you wanted? :slight_smile:

Yess definitely :grin:🫶🏼 thank you very much
I’d like to give you my Instagram account if you ever want to add me to talk about programing and dev in general : https://instagram.com/amarismundus?igshid=OGQ5ZDc2ODk2ZA==

Sorry, I’m not very active on Instagram :slight_smile:

I’m happy it works as intended now, good luck with your project!

heyyy daniel , i hope u’re doing great with the christmas season , i would like to tell you that i’ve finished my part of the project and i wanted to send it to you so you can rate my work but unfortunately i cannot upload the folder zip sooo here is my email acc : abdmfk37@gmail.com , please it would be a pleasure for me to be you rating my work so i look forward for you to contact me , thank you so much and have a good day :heart: :smiling_face: