#define SDL_DISABLE_IMMINTRIN_H #include #include #include #include #define WINDOW_W 800 #define WINDOW_H 600 #define MARGIN 20 #define PLAYER_W 10 #define PLAYER_H 100 #define PLAYER_V 5 #define BALL_SIZE 10 typedef struct { float x, y; char dir; int score; int stuck; } Player; typedef struct { float x, y; float vx, vy; } Ball; void initBall(Ball *b) { b->x = WINDOW_W / 2; b->y = WINDOW_H / 2; b->vx = 2 * (rand() % 2 ? 1 : -1); b->vy = 2 * (rand() % 2 ? 1 : -1); } int abs(int n) { return (n >= 0 ? n : -n); } void limit(float *n, float min, float max) { if (abs(*n) > max) *n = *n > 0 ? max : -max; else if (abs(*n) < min) *n = *n > 0 ? min : -min; } float randfloat(float from, float to) { return from + (to - from) * ((float)rand()/INT_MAX); } void collision(Ball *b, Player *p) { if (b->x + BALL_SIZE >= p->x && b->x <= p->x + PLAYER_W && b->y + BALL_SIZE >= p->y && b->y <= p->y + PLAYER_H) { if (!p->stuck) { b->vx = -b->vx; b->vx *= randfloat(0.5, 1.5); limit(&b->vx, 4, 8); b->vy += randfloat(0.2, 0.8) * p->dir; limit(&b->vy, 2, 8); p->stuck = 1; } } else { p->stuck = 0; } } void move(Player *p, float n) { if (n > 0) p->dir = 1; else if (n < 0) p->dir = -1; p->y += n; if (p->y > WINDOW_H - PLAYER_H) { p->y = WINDOW_H - PLAYER_H; p->dir = 0; } else if (p->y < 0) { p->y = 0; p->dir = 0; } } void input(Player *p) { const Uint8 *state = SDL_GetKeyboardState(0); if (state[SDL_SCANCODE_UP]) move(p, -PLAYER_V); else if (state[SDL_SCANCODE_DOWN]) move(p, PLAYER_V); else p->dir = 0; } void ai(Ball *b, Player *p) { if (abs(b->x - p->x) < 300) { if (b->y - p->y > PLAYER_H - 10 - BALL_SIZE) move(p, PLAYER_V); else if (b->y - p->y < 10) move(p, -PLAYER_V); } else { if (p->y >= WINDOW_H * 5 / 6 - PLAYER_H) { p->dir = -1; } else if (p->y <= WINDOW_H / 6) { p->dir = 1; } move(p, p->dir * PLAYER_V); } } void update(Ball *b, Player *p1, Player *p2) { b->x += b->vx; b->y += b->vy; if (b->y < 0 || b->y + BALL_SIZE > WINDOW_H) b->vy = -b->vy; if (b->x < 0) { p2->score++; initBall(b); } if (b->x + BALL_SIZE > WINDOW_W) { p1->score++; initBall(b); } if (p1->score > 5 || p2->score > 5) { p1->score = 0; p2->score = 0; } collision(b, p1); collision(b, p2); input(p1); ai(b, p2); } void render(SDL_Renderer *r, Ball *b, Player *p1, Player *p2) { SDL_SetRenderDrawColor(r, 0, 0, 0, 255); SDL_RenderClear(r); SDL_SetRenderDrawColor(r, 40, 40, 40, 255); SDL_Rect canvas = {0, 0, WINDOW_W, WINDOW_H}; SDL_RenderFillRect(r, &canvas); SDL_SetRenderDrawColor(r, 255, 255, 255, 255); SDL_Rect net[10]; for (int i = 0; i < 10; i++) { net[i].x = WINDOW_W / 2; net[i].y = i * (WINDOW_H / 10) + 10; net[i].w = 10; net[i].h = WINDOW_H / 10 - 20; } SDL_RenderFillRects(r, net, 10); SDL_SetRenderDrawColor(r, 255, 255, 255, 255); SDL_Rect ball_r = {b->x, b->y, BALL_SIZE, BALL_SIZE}; SDL_RenderFillRect(r, &ball_r); int p1factor = 255 - p1->score * 50; SDL_SetRenderDrawColor(r, 255, p1factor, p1factor, 255); SDL_Rect p1_r = {p1->x, p1->y, PLAYER_W, PLAYER_H}; SDL_RenderFillRect(r, &p1_r); int p2factor = 255 - p2->score * 50; SDL_SetRenderDrawColor(r, 255, p2factor, p2factor, 255); SDL_Rect p2_r = {p2->x, p2->y, PLAYER_W, PLAYER_H}; SDL_RenderFillRect(r, &p2_r); SDL_RenderPresent(r); SDL_Delay(10); } int main() { srand(time(0)); SDL_Init(SDL_INIT_VIDEO); SDL_Window *w; SDL_Renderer *r; SDL_CreateWindowAndRenderer(WINDOW_W, WINDOW_H, SDL_WINDOW_RESIZABLE, &w, &r); SDL_RenderSetLogicalSize(r, WINDOW_W, WINDOW_H); Player p1, p2; Ball b; p1.x = MARGIN; p1.y = WINDOW_H / 2; p2.x = WINDOW_W - MARGIN - PLAYER_W; p2.y = WINDOW_H / 2; p1.score = p2.score = 0; p1.stuck = p2.stuck = 0; p1.dir = p2.dir = 0; initBall(&b); SDL_Event e; while (e.type != SDL_QUIT) { SDL_PollEvent(&e); update(&b, &p1, &p2); render(r, &b, &p1, &p2); } SDL_DestroyRenderer(r); SDL_DestroyWindow(w); SDL_Quit(); return 0; }