C + Raylib: Random Walk visualization
Introduction
Yada yada yada...yeah it's visualizing Random Walk using Raylib. This post is actually not related to gamedev, but it uses Raylib which is a famous gamedev library. We are using Raylib to draw some colorful lines on random paths!
Random Walk
A mathematical concept that describes a path that consists of a sequence of random steps. It's when something moves in a random way, like a person walking in a random direction. Each step is different and not planned.
In my main domain (financial markets), it is used to try explain or model the random fluctuations of stock prices. So the most used application would be: modeling stock prices, portfolio optimization, and risk management.
Now I won't bore you to death with those things, we are here to code and visualize using King C and Raylib!!
Note: apologize if the writing format is too similar to my previous Raylib / gamedev posts, I just want to put it here as documentation.
#1 Libraries
#include "raylib.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#2 Consts, structs and global vars
#define RUNS 7
size_t WWIDTH;
size_t WHEIGHT;
typedef struct {
size_t x;
size_t y;
} Point;
#3 Function declaration
There is no function declaration coz it's not that much. I only put a separate function declaration when it gets too much and confusing to track.
#4 The random_walk function
Generates a random path with a specified number of steps.
Point *random_walk(size_t number_steps)
{
Point *pts = malloc(sizeof(Point) * number_steps);
if (pts == NULL) {
return NULL;
}
pts[0] = (Point) {0, 0};
for (size_t i=1; i<number_steps; i++) {
Point p = pts[i-1];
int r = GetRandomValue(0, 3);
switch (r) {
case 0:
// Right
p.x += 1;
break;
case 1:
// Left
p.x -= 1;
break;
case 2:
// Down
p.y += 1;
break;
case 3:
// Up
p.y -= 1;
break;
}
pts[i] = p;
}
return pts;
}
#5 Initialize
Sets up the window with a specified size and title.
void initialize_window(void)
{
WWIDTH = 800;
WHEIGHT = 600;
SetTargetFPS(60);
SetExitKey(KEY_ESCAPE);
SetRandomSeed(time(NULL));
InitWindow(WWIDTH, WHEIGHT, "Random Walk Simulation");
}
#6 Let's draw some stuff!
- Clears the background with a gray color.
- Draws multiple random paths on the screen.
- Draws additional shapes and text on the screen.
void draw_background(void)
{
Color color = {51, 51, 51, 255};
ClearBackground(color);
}
void draw_random_walks(Point **p_pts, size_t number_steps, size_t step_size, Color *colors)
{
for (size_t k=0; k<RUNS; k++) {
Point *pts = p_pts[k];
for (size_t i=0; i<number_steps-1; i++) {
Point p1 = pts[i];
Point p2 = pts[i + 1];
DrawLine((WWIDTH/2 + step_size * p1.x),
(WHEIGHT/2 + step_size * p1.y),
(WWIDTH/2 + step_size * p2.x),
(WHEIGHT/2 + step_size * p2.y),
colors[k]);
}
}
}
void draw_additional_elements(void)
{
DrawCircle(WWIDTH/2, WHEIGHT/2 + 250, 25, WHITE);
DrawCircle(WWIDTH/2, WHEIGHT/2 + 250, 15, BLACK);
DrawText("C + Raylib", 10, 10, 20, WHITE);
}
#7 Most important: don't forget to free the memory!
Frees the memory allocated for the random paths. You don't want to have memory leaks in your program, do you?!
void free_memory(Point **p_pts)
{
for (size_t i=0; i<RUNS; i++) {
if (p_pts[i]) {
free(p_pts[i]);
p_pts[i] = NULL;
}
}
if (p_pts) {
free(p_pts);
}
}
#8 Main
The main function that runs the program, initializes the window, generates random paths, and draws them on the screen.
int main(void)
{
initialize_window();
Color colors[RUNS] = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, GRAY};
Point **p_pts = malloc(sizeof(Point *) * RUNS);
size_t number_steps = 5000;
size_t step_size = 5;
for (size_t i=0; i<RUNS; i++) {
p_pts[i] = random_walk(number_steps);
}
while (!WindowShouldClose()) {
BeginDrawing();
draw_background();
draw_random_walks(p_pts, number_steps, step_size, colors);
draw_additional_elements();
EndDrawing();
}
free_memory(p_pts);
CloseWindow();
return 0;
}
Result
Everytime you run the program, you'll get different visualization.
random-walk-0
random-walk-1
Quirk
In writing all my C programs I always utilize compiler flags and address sanitizer, here's mine:
gcc -ggdb -Wall -Werror -Wextra -fsanitize=address -fno-omit-frame-pointer
What?? We got memory leak? I thought we have freed the memory? Yes we did free the memory properly, this leak is likely came from the GPU driver or GLFW library and it is a well known issue as discussed: