Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
28 kB
2
Indexable
Never
#include <SDL2/SDL.h>
#include <stdbool.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>


// Screen dimensions
const int SCREEN_WIDTH = 1200;
const int SCREEN_HEIGHT = 600;

// Player dimensions
const int PLAYER_WIDTH = 50;
const int PLAYER_HEIGHT = 100;

// Digit dimensions
const int DIGIT_WIDTH = 30;
const int DIGIT_HEIGHT = 50;

// Power Digit dimensions
const int POWER_DIGIT_WIDTH = 20;
const int POWER_DIGIT_HEIGHT = 40;

// Number of digits in the score
const int numDigits = 0;

// Player 1 initial position
int player1_x = 100;
int player1_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90;
int player1_velocity_y = 0;
int player1_remaining_jumps = 2;

// Player 2 initial position
int player2_x = 1050;
int player2_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90;
int player2_velocity_y = 0;
int player2_remaining_jumps = 2;

// Player 1 and 2 scores
int player1_score = 0;
int player2_score = 0;

// Jumping variables
bool player1_jumping = false;
bool player2_jumping = false;
const int JUMP_HEIGHT = 10000;

// Player speeds
const int PLAYER_SPEED = 4;

float player1_skill_points = 0;
float player2_skill_points = 0;
float skill_point_regeneration_rate = 0.065; // Points per second

// Add gravity and friction constants
const double GRAVITY = 0.2;   // Adjust as needed
const double FRICTION = 0.97; // Adjust as needed

// Ball dimensions
const int BALL_SIZE = 40;

// Ball initial position and velocity
int ball_x = SCREEN_WIDTH / 2 - BALL_SIZE / 2;
int ball_y = SCREEN_HEIGHT / 2 - BALL_SIZE / 2;
double ball_velocity_x = 0.0; // Use double for smoother movement
double ball_velocity_y = 1.0;

// Goal dimensions and positions
const int GOAL_WIDTH = 20;
const int GOAL_HEIGHT = 190;

// Goal Bar dimensions and positions
const int GOAL_BAR_WIDTH = 50;
const int GOAL_BAR_HEIGHT = 20;

// Update left goal position
int left_goal_x = 0; // Update left goal position to be at the left edge of the screen
int left_goal_y = (SCREEN_HEIGHT - GOAL_HEIGHT) - 100;

// Update right goal position
int right_goal_x = SCREEN_WIDTH - GOAL_WIDTH; // Update right goal position to be at the right edge of the screen
int right_goal_y = (SCREEN_HEIGHT - GOAL_HEIGHT) - 100;

const int INVISIBLE_FLOOR = SCREEN_HEIGHT - 90; // Adjust the height as needed

bool gameNeedsReset = false;

// Define game states
enum GameState {
    MAIN_MENU,
    GAME_PLAY,
};

// Main Menu image
SDL_Texture *mainMenuTexture = NULL;
// Background image
SDL_Texture *backgroundTexture = NULL;
// Goal Post image
SDL_Texture *goalPostTexture = NULL;
// Load the player1 image and create a texture for it
SDL_Texture *player1Texture = NULL;
// Load the player2 image and create a texture for it
SDL_Texture *player2Texture = NULL;
// Load the player1_s image and create a texture for it
SDL_Texture *player1sTexture = NULL;
// Load the player2_s image and create a texture for it
SDL_Texture *player2sTexture = NULL;
// Load the ball image and create a texture for it
SDL_Texture *ballTexture = NULL;
// Load the fan image and create a texture for it
SDL_Texture *fanTexture = NULL;
// Load digit images from 0 to 9
SDL_Texture *digitTextures[10];

// Function to reset the game
void resetGame()
{
    // Reset player positions
    player1_x = 100;
    player1_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90;
    player2_x = 1050;
    player2_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90;

    // Reset ball position and velocity to the middle of the screen
    ball_x = SCREEN_WIDTH / 2 - BALL_SIZE / 2;
    ball_y = SCREEN_HEIGHT / 2 - BALL_SIZE / 2;
    ball_velocity_x = 0.0;
    ball_velocity_y = 1.0;
}

// Initialize SDL and create a window
bool init(SDL_Window **window, SDL_Renderer **renderer)
{
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        return false;
    }

    *window = SDL_CreateWindow("Two Players", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (*window == NULL)
    {
        printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
        return false;
    }

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

    return true;
}

// Load PNG image and create texture
bool loadTexture(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture)
{
    SDL_Surface *imageSurface = IMG_Load(imagePath);
    if (imageSurface == NULL)
    {
        printf("Unable to load PNG image! SDL_Image Error: %s\n", IMG_GetError());
        return false;
    }

    *texture = SDL_CreateTextureFromSurface(renderer, imageSurface);
    if (*texture == NULL)
    {
        printf("Unable to create texture from PNG image! SDL Error: %s\n", SDL_GetError());
        return false;
    }

    SDL_FreeSurface(imageSurface);
    return true;
}

// Load digit images and create textures
bool loadDigitImage(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture, int digit)
{
    char digitPath[20];
    sprintf(digitPath, "number/%d.png", digit);

    SDL_Surface *imageSurface = IMG_Load(digitPath);
    if (imageSurface == NULL)
    {
        printf("Unable to load PNG image! SDL_Image Error: %s\n", IMG_GetError());
        return false;
    }

    *texture = SDL_CreateTextureFromSurface(renderer, imageSurface);
    if (*texture == NULL)
    {
        printf("Unable to create texture from PNG image! SDL Error: %s\n", SDL_GetError());
        return false;
    }

    SDL_FreeSurface(imageSurface);
    return true;
}

// Render the score
void renderScore(SDL_Renderer *renderer, SDL_Texture **digitTextures, int score, int x, int y)
{
    int tempScore = score;
    int numDigits = 0;

    // Count the number of digits in the score
    do
    {
        numDigits++;
        tempScore /= 10;
    } while (tempScore > 0);

    // Render the score digits from right to left
    tempScore = score;
    for (int i = numDigits - 1; i >= 0; i--)
    {
        int digit = tempScore % 10;
        SDL_Rect digitRect = {x + i * DIGIT_WIDTH, y, DIGIT_WIDTH, DIGIT_HEIGHT};
        SDL_RenderCopy(renderer, digitTextures[digit], NULL, &digitRect);
        tempScore /= 10;
    }
}

// Render the power
void renderPower(SDL_Renderer *renderer, SDL_Texture **digitTextures, float power, int x, int y)
{
    // Ensure power is within the valid range (0-100)
    if (power < 0)
        power = 0;
    else if (power > 100)
        power = 100;

    int tempPower = (int)power; // Convert power to an integer
    int numDigits = 0;

    // Count the number of digits in the power
    do
    {
        numDigits++;
        tempPower /= 10;
    } while (tempPower > 0);

    // Render the power digits from right to left
    tempPower = (int)power;
    for (int i = numDigits - 1; i >= 0; i--)
    {
        int digit = tempPower % 10;
        SDL_Rect digitRect = {x + i * POWER_DIGIT_WIDTH, y, POWER_DIGIT_WIDTH, POWER_DIGIT_HEIGHT};
        SDL_RenderCopy(renderer, digitTextures[digit], NULL, &digitRect);
        tempPower /= 10;
    }
}

// Draw the players and background on the screen
void draw(SDL_Renderer *renderer)
{
    // Clear the screen
    SDL_RenderClear(renderer);

    // Draw the background
    SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL);

    // Draw the fans
    SDL_RenderCopy(renderer, fanTexture, NULL, NULL);

    // Draw Player 1 score
    renderScore(renderer, digitTextures, player1_score, 50, 50);

    // Draw Player 2 score
    renderScore(renderer, digitTextures, player2_score, SCREEN_WIDTH - 100 - numDigits * DIGIT_WIDTH, 50);

    // Inside your game loop, you can call the renderPower function for each player:
    // Draw Player 1 power
    renderPower(renderer, digitTextures, player1_skill_points, 50, 100);

    // Draw Player 2 power
    renderPower(renderer, digitTextures, player2_skill_points, SCREEN_WIDTH - 100 - numDigits * DIGIT_WIDTH, 100);

    // Draw Player 1 (red rectangle)
    SDL_Rect player1Rect = {player1_x, player1_y, PLAYER_WIDTH, PLAYER_HEIGHT};
    if (player1_skill_points == 100) {
        // Render new images when powerScore is 100
        SDL_RenderCopy(renderer, player1sTexture, NULL, &player1Rect);
    }
    else if (player1_skill_points > 0) {
        // Render different images when powerScore is > 0 and < 100
        SDL_RenderCopy(renderer, player1Texture, NULL, &player1Rect);
    }
    else {
        // Render the default player image when powerScore is 0
        SDL_RenderCopy(renderer, player1Texture, NULL, &player1Rect);
    }

    // Draw Player 2 (blue rectangle)
    SDL_Rect player2Rect = {player2_x, player2_y, PLAYER_WIDTH, PLAYER_HEIGHT};
    if (player2_skill_points == 100) {
        // Render new images when powerScore is 100
        SDL_RenderCopy(renderer, player2sTexture, NULL, &player2Rect);
    }
    else if (player2_skill_points > 0) {
        // Render different images when powerScore is > 0 and < 100
        SDL_RenderCopy(renderer, player2Texture, NULL, &player2Rect);
    }
    else {
        // Render the default player image when powerScore is 0
        SDL_RenderCopy(renderer, player2Texture, NULL, &player2Rect);
    }

    // Draw the ball (yellow circle)
    SDL_Rect ballRect = {ball_x, ball_y, BALL_SIZE, BALL_SIZE};
    SDL_RenderCopy(renderer, ballTexture, NULL, &ballRect);

    // Draw the PNG image (on top of the background)
    SDL_RenderCopy(renderer, goalPostTexture, NULL, NULL);

    // Reset the render draw color
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);  // Reset to black

    // Update the screen
    SDL_RenderPresent(renderer);
}

// Player collisions
bool checkCollision(int x1, int y1, int x2, int y2, int width, int height)
{
    return (x1 < x2 + width &&
            x1 + PLAYER_WIDTH > x2 &&
            y1 < y2 + height &&
            y1 + PLAYER_HEIGHT > y2);
}

// Function to handle ball-wall collisions
void handleBallWallCollision()
{
    if (ball_x <= 0 || ball_x + BALL_SIZE >= SCREEN_WIDTH)
    {
        ball_velocity_x = -ball_velocity_x;
    }

    if (ball_y <= 0) {
        ball_velocity_y = -ball_velocity_y;
    } else if (ball_y + BALL_SIZE >= SCREEN_HEIGHT) {
        if (fabs(ball_velocity_y) < 0.1) {
            ball_velocity_y = 0.0;
        } else {
            ball_velocity_y = -ball_velocity_y * FRICTION;
        }
    }
}

bool checkBallPlayerCollision(int player_x, int player_y)
{
    return (ball_x < player_x + PLAYER_WIDTH &&
            ball_x + BALL_SIZE > player_x &&
            ball_y < player_y + PLAYER_HEIGHT &&
            ball_y + BALL_SIZE > player_y);
}

// Function to handle ball-goal collisions
void handleBallGoalCollision()
{
    int ball_center_x = ball_x + BALL_SIZE / 2;
    int ball_center_y = ball_y + BALL_SIZE / 2;

    // Check if the ball's center crosses the left goal line
    if (ball_center_x <= left_goal_x + GOAL_WIDTH && ball_center_y >= left_goal_y && ball_center_y <= left_goal_y + GOAL_HEIGHT)
    {
        // Ball's center crossed the left goal line, player 2 scores
        printf("Player 2 scores!\n");
        player2_score += 1;
        player1_skill_points += 10;
        printf("Player 2: %d\n", player2_score);
        resetGame();
    }
    // Check if the ball's center crosses the right goal line
    else if (ball_center_x >= right_goal_x && ball_center_y >= right_goal_y && ball_center_y <= right_goal_y + GOAL_HEIGHT)
    {
        // Ball's center crossed the right goal line, player 1 scores
        printf("Player 1 scores!\n");
        player1_score += 1;
        player2_skill_points += 10;
        printf("Player 1: %d\n", player1_score);
        resetGame();
    }
}

// Function to update the ball's position and velocity
void updateBallPosition()
{
    ball_x += ball_velocity_x;
    ball_y += ball_velocity_y;

    // Apply gravity
    ball_velocity_y += GRAVITY;

    // Apply friction
    ball_velocity_x *= FRICTION;
    ball_velocity_y *= FRICTION;

    // Ensure the ball stays above the invisible floor
    if (ball_y + BALL_SIZE >= INVISIBLE_FLOOR)
    {
        ball_y = INVISIBLE_FLOOR - BALL_SIZE;

        // Decrease the velocity over time to simulate slowing down
        ball_velocity_x += 0.02;
        ball_velocity_y -= 0.01;

        // Check if the ball's velocity is very small or zero
        if (fabs(ball_velocity_x) < 0.01 && fabs(ball_velocity_y) < 0.01)
        {
            ball_velocity_x = 0.0;
            ball_velocity_y = 0.0;
        }
    }
}

// Load All Graphics
void loadAllGraphics(SDL_Window* window, SDL_Renderer* renderer){

    if (!loadTexture(renderer, "main_menu.png", &mainMenuTexture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "background.jpg", &backgroundTexture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "Ball.png", &ballTexture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "goalPost.png", &goalPostTexture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "fan.png", &fanTexture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "player1.png", &player1Texture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "player1_s.png", &player1sTexture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "player2.png", &player2Texture))
    {
        return 1;
    }

    if (!loadTexture(renderer, "player2_s.png", &player2sTexture))
    {
        return 1;
    }

    for (int i = 0; i < 10; i++)
    {
        char digitPath[20];
        sprintf(digitPath, "number/%d.png", i);
        if (!loadDigitImage(renderer, digitPath, &digitTextures[i], i))
        {
            return 1;
        }
    }
}

void p1RemainingJumpsDecrease(){
    player1_jumping = true;
    player1_velocity_y = -20;
    player1_remaining_jumps--;
}

extern void p2RemainingJumpsDecrease(void);
extern int p1FWD(int p1x, int pspeed);

void handlePlayer2Jump(int floor, int height){
    player2_y += player2_velocity_y;
    player2_velocity_y += 1;

    // Ensure player 2 stays above the invisible floor
    if (player2_y >= floor - height)
    {
        player2_y = floor - height;
        player2_jumping = false;
        player2_remaining_jumps = 2;
    }
}

int main(int argc, char *argv[])
{
    printf("Welcome to Head Soccer!\n");
    SDL_Window *window = NULL;
    SDL_Renderer *renderer = NULL;

    if (!init(&window, &renderer))
    {
        return 1;
    }

    loadAllGraphics(window, renderer);

    // Initialize the game state as MAIN_MENU
    enum GameState gameState = MAIN_MENU;

    bool quit = false;
    SDL_Event e;

    while (!quit)
    {
        while (SDL_PollEvent(&e) != 0)
        {
            if (e.type == SDL_QUIT)
            {
                quit = true;
            }

            if (gameState == MAIN_MENU)
            {
                if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_RETURN)
                {
                    // Transition to the game state
                    gameState = GAME_PLAY;
                }
            }
            else if (gameState == GAME_PLAY)
            {
                if (e.type == SDL_KEYDOWN)
                {
                    // Player 1 jump
                    if (e.key.keysym.sym == SDLK_w)
                    {
                        if (player1_remaining_jumps > 0)
                        {
                            p1RemainingJumpsDecrease();
                        }
                    }

                    // Player 2 jump
                    if (e.key.keysym.sym == SDLK_UP)
                    {
                        if (player2_remaining_jumps > 0)
                        {
                            p2RemainingJumpsDecrease();
                        }
                    }
                }

                if (player1_score == 5 || player2_score == 5)
                {
                    // Change the game state back to MAIN_MENU
                    gameState = MAIN_MENU;

                    // Reset player scores
                    player1_score = 0;
                    player2_score = 0;
                    player1_skill_points = 0;
                    player2_skill_points = 0;
                }
            }
        }

        if (gameState == MAIN_MENU)
        {
            // Load and display the main menu image
            SDL_Surface *mainMenuSurface = IMG_Load("main_menu.png");
            SDL_Texture *mainMenuTexture = SDL_CreateTextureFromSurface(renderer, mainMenuSurface);
            SDL_RenderCopy(renderer, mainMenuTexture, NULL, NULL);
            SDL_RenderPresent(renderer);

            // Clean up the resources for the main menu image
            SDL_FreeSurface(mainMenuSurface);
            SDL_DestroyTexture(mainMenuTexture);

            gameNeedsReset = true;
            if (gameNeedsReset)
            {
                bool resetGameRequested = false;

                // Wait for the user to press Enter to reset the game
                while (!resetGameRequested)
                {
                    while (SDL_PollEvent(&e) != 0)
                    {
                        if (e.type == SDL_QUIT)
                        {
                            quit = true;
                            break;
                        }

                        if (e.type == SDL_KEYDOWN)
                        {
                            if (e.key.keysym.sym == SDLK_RETURN)
                            {
                                gameState = GAME_PLAY;
                                gameNeedsReset = false;
                                resetGameRequested = true;
                            }
                        }
                    }
                }
            }
        }
        else if (gameState == GAME_PLAY)
        {
            if (player1_score == 5)
                {
                    // Player 1 has won
                    SDL_Surface *player1WonSurface = IMG_Load("Player1_won.png");
                    SDL_Texture *player1WonTexture = SDL_CreateTextureFromSurface(renderer, player1WonSurface);

                    SDL_RenderCopy(renderer, player1WonTexture, NULL, NULL);
                    SDL_RenderPresent(renderer);

                    SDL_FreeSurface(player1WonSurface);
                    SDL_DestroyTexture(player1WonTexture);

                    player1_score = 0;
                    player2_score = 0;
                    player1_skill_points = 0;
                    player2_skill_points = 0;

                    // Set the flag to indicate that the game needs to be reset
                    gameNeedsReset = true;
                }
                else if (player2_score == 5)
                {
                    // Player 2 has won
                    SDL_Surface *player2WonSurface = IMG_Load("Player2_won.png");
                    SDL_Texture *player2WonTexture = SDL_CreateTextureFromSurface(renderer, player2WonSurface);

                    SDL_RenderCopy(renderer, player2WonTexture, NULL, NULL);
                    SDL_RenderPresent(renderer);

                    SDL_FreeSurface(player2WonSurface);
                    SDL_DestroyTexture(player2WonTexture);

                    player1_score = 0;
                    player2_score = 0;
                    player1_skill_points = 0;
                    player2_skill_points = 0;

                    // Set the flag to indicate that the game needs to be reset
                    gameNeedsReset = true;
                }

                if (gameNeedsReset)
                {
                    bool resetGameRequested = false;

                    // Wait for the user to press Enter to reset the game
                    while (!resetGameRequested)
                    {
                        while (SDL_PollEvent(&e) != 0)
                        {
                            if (e.type == SDL_QUIT)
                            {
                                quit = true;
                                break;
                            }

                            if (e.type == SDL_KEYDOWN)
                            {
                                if (e.key.keysym.sym == SDLK_RETURN)
                                {
                                    gameState = MAIN_MENU;
                                    gameNeedsReset = false;
                                    resetGameRequested = true;
                                }
                            }
                        }
                    }
                }

                if (player1_jumping)
                {
                    player1_y += player1_velocity_y;
                    player1_velocity_y += 1;

                    // Ensure player 1 stays above the invisible floor
                    if (player1_y >= INVISIBLE_FLOOR - PLAYER_HEIGHT)
                    {
                        player1_y = INVISIBLE_FLOOR - PLAYER_HEIGHT;
                        player1_jumping = false;
                        player1_remaining_jumps = 2;
                    }
                }

                if (player2_jumping)
                {
                    handlePlayer2Jump(INVISIBLE_FLOOR, PLAYER_HEIGHT);
                }

                const Uint8 *currentKeyStates = SDL_GetKeyboardState(NULL);

                if (checkCollision(player1_x, player1_y, player2_x, player2_y, PLAYER_WIDTH, PLAYER_HEIGHT))
                {
                    if (player1_x < player2_x)
                    {
                        player1_x--;
                        player2_x++;
                    }
                    else
                    {
                        player1_x++;
                        player2_x--;
                    }
                }
                else
                {
                // resetGame;
                if (currentKeyStates[SDL_SCANCODE_ESCAPE])
                {
                    if (currentKeyStates[SDL_SCANCODE_R])
                    {
                        resetGame();
                    }
                }

                // Player 1 movement
                if (currentKeyStates[SDL_SCANCODE_A])
                {
                    player1_x -= PLAYER_SPEED;
                }
                if (currentKeyStates[SDL_SCANCODE_D])
                {
                    // player1_x += PLAYER_SPEED;
                    player1_x = p1FWD(player1_x, PLAYER_SPEED);
                }

                // Player 2 movement
                if (currentKeyStates[SDL_SCANCODE_LEFT])
                {
                    player2_x -= PLAYER_SPEED;
                }
                if (currentKeyStates[SDL_SCANCODE_RIGHT])
                {
                    player2_x += PLAYER_SPEED;
                }

                // Keep players within the screen boundaries
                if (player1_x < 0)
                {
                    player1_x = 0;
                }
                if (player1_x > SCREEN_WIDTH - PLAYER_WIDTH)
                {
                    player1_x = SCREEN_WIDTH - PLAYER_WIDTH;
                }

                if (player2_x < 0)
                {
                    player2_x = 0;
                }
                if (player2_x > SCREEN_WIDTH - PLAYER_WIDTH)
                {
                    player2_x = SCREEN_WIDTH - PLAYER_WIDTH;
                }
            }

            if (checkBallPlayerCollision(player1_x, player1_y) && checkBallPlayerCollision(player2_x, player2_y))
            {
                ball_velocity_y = -ball_velocity_y;
                ball_y += ball_velocity_y;
            } else {
                // Check for collision with Player 1
                if (checkBallPlayerCollision(player1_x, player1_y))
                {
                    // Calculate the direction of the collision
                    int collisionDirection = (ball_x + BALL_SIZE / 2) - (player1_x + PLAYER_WIDTH / 2);

                    // Adjust the ball's velocity based on the collision direction
                    ball_velocity_x = collisionDirection / 5.0; // Use double for smoother adjustment

                    // Move the ball slightly away from the player to avoid getting stuck
                    ball_x += ball_velocity_x * 2.0; // Use double for smoother adjustment
                }

                // Check for collision with Player 2
                if (checkBallPlayerCollision(player2_x, player2_y))
                {
                    // Calculate the direction of the collision
                    int collisionDirection = (ball_x + BALL_SIZE / 2) - (player2_x + PLAYER_WIDTH / 2);

                    // Adjust the ball's velocity based on the collision direction
                    ball_velocity_x = collisionDirection / 5.0; // Use double for smoother adjustment

                    // Move the ball slightly away from the player to avoid getting stuck
                    ball_x += ball_velocity_x * 2.0; // Use double for smoother adjustment
                }

                // Player 1 kick
                if (e.key.keysym.sym == SDLK_s)
                {
                    if (checkBallPlayerCollision(player1_x + 30, player1_y))
                    {
                        int collisionDirection = (ball_x + BALL_SIZE / 2) - (player1_x + PLAYER_WIDTH / 2);

                        ball_velocity_x = collisionDirection / 5.0; // Use double for smoother adjustment

                        // Check for the special ability
                        if (player1_skill_points == 100)
                        {
                            ball_velocity_x *= 1.5; // Double the kick power in the x-axis
                            player1_skill_points = 0;
                        }

                        ball_x += ball_velocity_x * 2.5; // Use double for smoother adjustment

                        ball_velocity_y = -ball_velocity_y * 2;
                        ball_y += ball_velocity_y * 2;
                    }
                }

                // Player 2 kick
                if (e.key.keysym.sym == SDLK_DOWN)
                {
                    if (checkBallPlayerCollision(player2_x - 30, player2_y))
                    {
                        int collisionDirection = (ball_x + BALL_SIZE / 2) - (player2_x + PLAYER_WIDTH / 2);

                        ball_velocity_x = collisionDirection / 5.0; // Use double for smoother adjustment

                        // Check for the special ability
                        if (player2_skill_points == 100)
                        {
                            ball_velocity_x *= 1.5; // Double the kick power in the x-axis
                            player2_skill_points = 0;
                        }

                        ball_x += ball_velocity_x * 5.0; // Use double for smoother adjustment

                        ball_velocity_y = -ball_velocity_y * 2;
                        ball_y += ball_velocity_y * 2;
                    }
                }

                player1_skill_points += skill_point_regeneration_rate;
                player2_skill_points += skill_point_regeneration_rate;

                // In your game loop, after updating skill points
                if (player1_skill_points > 100)
                {
                    player1_skill_points = 100;
                }
                if (player2_skill_points > 100)
                {
                    player2_skill_points = 100;
                }

            }

            // Handle ball-goal collisions
            handleBallGoalCollision();

            // Handle ball-wall collisions
            handleBallWallCollision();

            // Update the ball's position
            updateBallPosition();
        }

        draw(renderer);
    }

    // Cleanup and exit
    SDL_DestroyTexture(backgroundTexture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}