Укажите на ошибки в коде C небольшой игры (пинг-понг)

Учу C и решил написать небольшую программку - консольный пинг-понг с стенкой. Пытался сделать структуру программы для хорошей расширяемости и без потери скорости работы. Люди знающие C, оцените пожалуйста код по всем поводам. Укажите на ошибки, недочёты, костыли. Судите очень строго. Жду хорошей критики.

#include <stdio.h>
#include <windows.h>
#include <unistd.h>
#include <time.h>
#include <math.h>


#define SIZE_X 60
#define SIZE_Y 20


struct object {
    float coords[2];
    float speed[2];
    int size[2];
};

struct player {
    float player_move[2];
    struct object object;
};


int frame(int size_x, int size_y, struct player player, struct object ball) {
    //Draws one frame
    int last_y = size_y - 1;
    int last_x = size_x - 1;
    char text_frame[(size_x + 1) * size_y * 3 + 1 + 10];
    int index = 0;
    for (int y = 0; y < size_y; y++) {
        for (int x = 0; x < size_x; x++) {
            if (y == 0 || y == last_y) {
                if (x == 0 && y == 0) {
                    memcpy(&text_frame[index], "╔", 3);
                    index += 3;
                }
                else if (x == last_x && y == last_y) {
                    memcpy(&text_frame[index], "╝", 3);
                    index += 3;
                }
                else if (x == last_x && y == 0) {
                    memcpy(&text_frame[index], "╗", 3);
                    index += 3;
                }
                else if (x == 0 && y == last_y) {
                    memcpy(&text_frame[index], "╚", 3);
                    index += 3;
                }
                else {
                    memcpy(&text_frame[index], "═", 3);
                    index += 3;
                }
            }
            else if (x == 0 || x == last_x) {
                memcpy(&text_frame[index], "║", 3);
                index += 3;
            }
            else if (y == round(ball.coords[1]) && x == round(ball.coords[0])) {
                memcpy(&text_frame[index], "●", 3);
                index += 3;
            }
            else if (y == round(player.object.coords[1]) && round(player.object.coords[0]) <= x && x <= round(player.object.coords[0] + player.object.size[0])) {
                memcpy(&text_frame[index], "▄", 3);
                index += 3;
            }
            else {
                memcpy(&text_frame[index], " ", 1);
                index += 1;
            }
        }
        text_frame[index++] = '\n';
    }
    text_frame[index] = '\0';
    printf("\e[1;1H%s", text_frame);
    return 0;
}

int get_player_correct_speed(float result[2], struct player *player, int size_x, int size_y) {
    //Writes to result the correct player velocity vector modified by walls
    if (player->object.speed[0] < 0) {
        if (player->object.coords[0] + player->object.speed[0] < 1) {
            result[0] = 1 - player->object.coords[0];
        }
        else {
            result[0] = player->object.speed[0];
        }
    }
    else if (player->object.speed[0] > 0) {
        if (player->object.coords[0] + player->object.speed[0] + player->object.size[0] > size_x - 2) {
            result[0] = size_x - 2 - player->object.coords[0] - player->object.size[0];
        }
        else {
            result[0] = player->object.speed[0];
        }
    }
    else {
        result[0] = 0;
    }
    result[1] = 0;
    return 0;
}

int get_ball_correct_speed(float result[2], struct object *ball, struct player player, int size_x, int size_y) {
    //Writes to result the correct ball velocity vector modified by walls and player
    if (ball->speed[0] < 0) {
        if (ball->coords[0] + ball->speed[0] < 1) { // left wall
            result[0] = ball->speed[0] - 2 * (1 - ball->coords[0]);
            ball->speed[0] *= -1;
        }
        else {
            result[0] = ball->speed[0];
        }
    }
    else if (ball->speed[0] > 0) {
        if (ball->coords[0] + ball->speed[0] > size_x - 2) { // right wall
            result[0] = ball->speed[0] - 2 * (size_x - 2 - ball->coords[0]);
            ball->speed[0] *= -1;
        }
        else {
            result[0] = ball->speed[0];
        }
    }
    else {
        result[0] = ball->speed[0];
    }

    if (ball->speed[1] < 0) {
        if (ball->coords[1] + ball->speed[1] < 1) { // down wall(teleport on top)
            ball->coords[1] = ball->speed[1] - (player.object.coords[1] + 1 - ball->coords[1]) + size_y + 1;
        }
        else if (ball->coords[1] + ball->speed[1] < player.object.coords[1] + 1 && ball->coords[0] >= player.object.coords[0] && ball->coords[0] <= player.object.coords[0] + player.object.size[0]) { // player
            result[1] = ball->speed[1] - 2 * (player.object.coords[1] + 1 - ball->coords[1]);
            ball->speed[1] *= -1;
            ball->speed[0] += player.object.speed[0] * 0.3;
        }
        else {
            result[1] = ball->speed[1];
        }
    }
    else if (ball->speed[1] > 0) {
        if (ball->coords[1] + ball->speed[1] > size_y - 2) { // top wall
            result[1] = ball->speed[1] - 2 * (size_y - 2 - ball->coords[1]);
            ball->speed[1] *= -1;
        }
        else {
            result[1] = ball->speed[1];
        }
    }
    else {
        result[1] = ball->speed[1];
    }

    return 0;
}

int clear_frame() {
    printf("\e[1;1H\e[2J");
}


int main() {
    int game = 1;
    struct object ball = { { 1, 5 }, { -0.3, -0.1 }, { 1, 1 } };
    struct player player = { { 0, 0 }, { { 1, 3 }, { 0, 0 }, { 5, 1 } } };

    float player_correct_speed[2];
    float ball_correct_speed[2];


    long count = 0;
    time_t start_time = time(NULL);
    time_t last_print_time = start_time;
    double elapsed = 0;
    double loops_per_second;

    system("color");
    system("chcp 65001");
    clear_frame();

    unsigned int is_left_pressed;
    unsigned int is_right_pressed;

    while (game) {
        count++;
        time_t current_time = time(NULL);
        if (current_time - last_print_time >= 1) {
            elapsed = difftime(current_time, start_time);
            loops_per_second = count / elapsed;

            last_print_time = current_time;
        }

        is_left_pressed = GetAsyncKeyState(VK_LEFT) & 0x8000;
        is_right_pressed = GetAsyncKeyState(VK_RIGHT) & 0x8000;

        player.object.speed[0] -= player.player_move[0];
        player.object.speed[1] -= player.player_move[1];

        if (is_left_pressed) {
            if (is_right_pressed) {
                player.player_move[0] = 0;
            }
            else {
                player.player_move[0] = -0.3;
            }
        }
        else if (is_right_pressed) {
            player.player_move[0] = 0.3;
        }
        else {
            player.player_move[0] = 0;
        }

        player.object.speed[0] += player.player_move[0];
        player.object.speed[1] += player.player_move[1];

        get_player_correct_speed(player_correct_speed, &player, SIZE_X, SIZE_Y);
        get_ball_correct_speed(ball_correct_speed, &ball, player, SIZE_X, SIZE_Y);

        player.object.coords[0] += player_correct_speed[0];
        player.object.coords[1] += player_correct_speed[1];

        ball.coords[0] += ball_correct_speed[0];
        ball.coords[1] += ball_correct_speed[1];

        //clear_frame(); // если очистить экран сразу в frame то не будет мигать даже при большом tps
        frame(SIZE_X, SIZE_Y, player, ball);
        printf("\e[KLoops per second:%.2f\tTotal:%ld\n", 
                loops_per_second, count);
        usleep(10000);
    }
    return 0;
}

Ответы (0 шт):