Created
January 30, 2024 17:49
-
-
Save deniska/ecd803c129179d1d4448b09291352de2 to your computer and use it in GitHub Desktop.
pongpong, simple raylib based doodle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <raylib.h> | |
#include <raymath.h> | |
const int SCREEN_WIDTH = 600; | |
const int SCREEN_HEIGHT = 600; | |
const int BOX_SIZE = 30; | |
#define BALL_SIZE (BOX_SIZE/3) | |
const COLOR_COUNT = 4; | |
const Color COLORS[] = {BROWN, LIME, LIGHTGRAY, SKYBLUE}; | |
typedef struct { | |
Vector2 pos; | |
Vector2 vel; | |
int v; | |
} Ball; | |
#define BALL_COUNT 4 | |
Ball balls[BALL_COUNT]; | |
int *world; | |
int world_width; | |
int world_height; | |
int sim_speed = 1; | |
void world_set(int x, int y, int v) { | |
if (x < 0 || x >= world_width || y < 0 || y >= world_height) return; | |
world[y * world_width + x] = v; | |
} | |
Vector2 random_velocity(void) { | |
Vector2 result = {.x = 1, .y = 0}; | |
int rand_value = GetRandomValue(0, 10000); | |
float rand_angle = ((float) rand_value) / 10000.0f * PI * 2; | |
return Vector2Rotate(result, rand_angle); | |
} | |
void randomize_velocities(void) { | |
for (int i = 0; i < BALL_COUNT; i++) { | |
balls[i].vel = random_velocity(); | |
} | |
} | |
void init_world(void) { | |
balls[0].pos.x = SCREEN_WIDTH / 4; | |
balls[0].pos.y = SCREEN_HEIGHT / 4; | |
balls[0].v = 0; | |
balls[1].pos.x = SCREEN_WIDTH / 4 * 3; | |
balls[1].pos.y = SCREEN_HEIGHT / 4; | |
balls[1].v = 1; | |
balls[2].pos.x = SCREEN_WIDTH / 4; | |
balls[2].pos.y = SCREEN_HEIGHT / 4 * 3; | |
balls[2].v = 2; | |
balls[3].pos.x = SCREEN_WIDTH / 4 * 3; | |
balls[3].pos.y = SCREEN_HEIGHT / 4 * 3; | |
balls[3].v = 3; | |
randomize_velocities(); | |
world_width = SCREEN_WIDTH / BOX_SIZE; | |
world_height = SCREEN_HEIGHT / BOX_SIZE; | |
world = calloc(world_width*world_height, sizeof(int)); | |
for (int y = 0; y < world_height / 2; y++) { | |
for (int x = world_width / 2; x < world_width; x++) { | |
world_set(x, y, 1); | |
} | |
} | |
for (int y = world_height / 2; y < world_height; y++) { | |
for (int x = 0; x < world_width / 2; x++) { | |
world_set(x, y, 2); | |
} | |
} | |
for (int y = world_height / 2; y < world_height; y++) { | |
for (int x = world_width / 2; x < world_width; x++) { | |
world_set(x, y, 3); | |
} | |
} | |
} | |
Rectangle world_rect(int wx, int wy) { | |
Rectangle rect = { | |
.x = wx * BOX_SIZE, | |
.y = wy * BOX_SIZE, | |
.width = BOX_SIZE, | |
.height = BOX_SIZE, | |
}; | |
return rect; | |
} | |
int world_get(int x, int y) { | |
if (x < 0 || x >= world_width || y < 0 || y >= world_height) return -1; | |
return world[y * world_width + x]; | |
} | |
bool world_collides(Ball *ball, int wx, int wy) { | |
return CheckCollisionCircleRec(ball->pos, BALL_SIZE, world_rect(wx, wy)) | |
&& ball->v != world_get(wx, wy); | |
} | |
void update_ball(Ball *ball) { | |
int grid_x = ball->pos.x / BOX_SIZE; | |
int grid_y = ball->pos.y / BOX_SIZE; | |
if (world_get(grid_x, grid_y) != ball->v) { | |
world_set(grid_x, grid_y, ball->v); | |
} | |
Vector2 old_pos = ball->pos; | |
ball->pos = Vector2Add(ball->pos, ball->vel); | |
grid_x = ball->pos.x / BOX_SIZE; | |
grid_y = ball->pos.y / BOX_SIZE; | |
int sign_x = ball->vel.x > 0 ? 1 : -1; | |
int sign_y = ball->vel.y > 0 ? 1 : -1; | |
if (world_collides(ball, grid_x + sign_x, grid_y)) { | |
ball->pos.x = old_pos.x; | |
ball->vel.x = -ball->vel.x; | |
world_set(grid_x + sign_x, grid_y, ball->v); | |
} | |
if (world_collides(ball, grid_x, grid_y + sign_y)) { | |
ball->pos.y = old_pos.y; | |
ball->vel.y = -ball->vel.y; | |
world_set(grid_x, grid_y + sign_y, ball->v); | |
} | |
} | |
void update(void) { | |
for (int s = 0; s < sim_speed; s++) { | |
for (int i = 0; i < BALL_COUNT; i++) { | |
update_ball(&balls[i]); | |
} | |
} | |
} | |
void draw(void) { | |
ClearBackground(BLACK); | |
for (int y = 0; y < world_height; y++) { | |
for (int x = 0; x < world_width; x++) { | |
int v = world_get(x, y); | |
Color c = COLORS[v]; | |
DrawRectangleRec(world_rect(x, y), c); | |
} | |
} | |
for (int i = 0; i < BALL_COUNT; i++) { | |
Color c = COLORS[(balls[i].v + 1) % COLOR_COUNT]; | |
DrawCircleV(balls[i].pos, BALL_SIZE, c); | |
} | |
} | |
int main(int argc, char **argv) { | |
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "PongPong"); | |
SetExitKey(0); | |
SetWindowState(FLAG_WINDOW_RESIZABLE); | |
init_world(); | |
SetTargetFPS(60); | |
while (!WindowShouldClose()) { | |
float zoom = fminf(GetScreenWidth(), GetScreenHeight()) / SCREEN_WIDTH * 0.95f; | |
Camera2D camera = { | |
.zoom = zoom, | |
.offset = {GetScreenWidth() / 2, GetScreenHeight() / 2}, | |
.target = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2}, | |
}; | |
if (IsKeyPressed(KEY_R)) randomize_velocities(); | |
if (IsKeyPressed(KEY_UP) && sim_speed < 100) { | |
if (sim_speed == 0) { | |
sim_speed = 1; | |
} else { | |
sim_speed *= 2; | |
} | |
} | |
if (IsKeyPressed(KEY_DOWN) && sim_speed > 0) sim_speed /= 2; | |
update(); | |
BeginDrawing(); | |
BeginMode2D(camera); | |
draw(); | |
EndMode2D(); | |
EndDrawing(); | |
} | |
CloseWindow(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment