Укажите на ошибки в коде 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;
}