Untitled

mail@pastecode.io avatar
unknown
c_cpp
a year ago
18 kB
1
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;

// 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;

// Add gravity and friction constants
const double GRAVITY = 0.2;   // Adjust as needed
const double FRICTION = 0.98; // 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 = 3.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;

int left_goal_x = 50; // Update left goal position
int left_goal_y = (SCREEN_HEIGHT - GOAL_HEIGHT) - 100;

int right_goal_x = SCREEN_WIDTH - GOAL_WIDTH - 50; // Update right goal position
int right_goal_y = SCREEN_HEIGHT - GOAL_HEIGHT - 100;

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

// Background image
SDL_Texture *backgroundTexture = NULL;
// Goal Post image
SDL_Texture *goalPostTexture = 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 = 3.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 background image
bool loadBackground(SDL_Renderer *renderer)
{
    SDL_Surface *backgroundSurface = IMG_Load("background.jpg");
    if (backgroundSurface == NULL)
    {
        printf("Unable to load background image! SDL_Image Error: %s\n", IMG_GetError());
        return false;
    }

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

    SDL_FreeSurface(backgroundSurface);
    return true;
}

// Load PNG image and create texture
bool loadGoalPost(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture)
{
    SDL_Surface *imageSurface = IMG_Load("goalPost.png");
    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 fan image and create texture
bool loadFanImage(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture)
{
    SDL_Surface *imageSurface = IMG_Load("fan.png");
    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 ball image and create texture
bool loadBallImage(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture)
{
    SDL_Surface *imageSurface = IMG_Load("Ball.png");
    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;
    }
}

// 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);

    // Draw Player 1 (red rectangle)
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    SDL_Rect player1Rect = {player1_x, player1_y, PLAYER_WIDTH, PLAYER_HEIGHT};
    SDL_RenderFillRect(renderer, &player1Rect);

    // Draw Player 2 (blue rectangle)
    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
    SDL_Rect player2Rect = {player2_x, player2_y, PLAYER_WIDTH, PLAYER_HEIGHT};
    SDL_RenderFillRect(renderer, &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);

    // 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_y + BALL_SIZE >= SCREEN_HEIGHT)
    {
        ball_velocity_y = -ball_velocity_y;
    }
}

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;
        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;
        printf("Player 1: %d\n", player1_score);
        resetGame();
    }
}

// Function to update the ball's position
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;
        // Reverse the ball's vertical velocity to bounce it off the floor
        ball_velocity_y = -ball_velocity_y * FRICTION; // Apply friction when bouncing
    }
}

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;
    }

    if (!loadBackground(renderer))
    {
        return 1;
    }

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

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

    if (!loadFanImage(renderer, "fan.png", &fanTexture))
    {
        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;
        }
    }

    bool quit = false;
    SDL_Event e;

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

            if (e.type == SDL_KEYDOWN)
            {
                // Player 1 jump
                if (e.key.keysym.sym == SDLK_w)
                {
                    if (player1_remaining_jumps > 0)
                    {
                        player1_jumping = true;
                        player1_velocity_y = -20;
                        player1_remaining_jumps--;
                    }
                }

                // Player 2 jump
                if (e.key.keysym.sym == SDLK_UP)
                {
                    if (player2_remaining_jumps > 0)
                    {
                        player2_jumping = true;
                        player2_velocity_y = -20;
                        player2_remaining_jumps--;
                    }
                }
            }
        }

        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)
        {
            player2_y += player2_velocity_y;
            player2_velocity_y += 1;

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

        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;
            }

            // 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
                ball_velocity_y = -ball_velocity_y;         // Reverse the ball's vertical velocity

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

            // 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
                ball_velocity_y = -ball_velocity_y;         // Reverse the ball's vertical velocity

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

        }

        // 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;
}