Skip to content

Instantly share code, notes, and snippets.

@deniska
Created January 30, 2024 17:49
Show Gist options
  • Save deniska/ecd803c129179d1d4448b09291352de2 to your computer and use it in GitHub Desktop.
Save deniska/ecd803c129179d1d4448b09291352de2 to your computer and use it in GitHub Desktop.
pongpong, simple raylib based doodle
#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