Until August 2023, this site was hosted on a raspberry pi taped to a window in my bedroom. I reluctantly moved it to a VPS to mitigate slowness.

I created it in 2021 as an experiment when learning about networking and apache. I was also messing around with the raspberry pi camera module, which led to the creation of the block.html page.

My hope is that the existence of the site will encourage me to finish work that I want to share.

About the background image

The background image was also created in the course of experimentation, in this case with C and SDL. The program was my first attempt to create 3D graphics by translating a fictitious xyz coordinate system (confusingly denoted "real" in the source code, some of which is below) into 2D screen coordinates, adjusting sprite scale to change apparent distance, etc. The sprites are bits of snowy trees from this image. I created the graphics and a series of bitmap frames in C with SDL2, and compiled the gif itself with ImageMagick.

The source code is available here. A code sample demonstrating some of the basic ideas is below.

/* Struct to store information about a given sprite: size, position, real and screen coords */
typedef struct Sprite { 
    SDL_Texture* tex;
    SDL_Rect dest;
    int zreal;
    int xreal;
    int yreal;
    int hreal;
    int wreal;
} Sprite;

/* An array of sprites to be rendered */
Sprite** sprites; 

/* Create a sprite from xyz coords */
int init_sprite(Sprite* sp, char* path, SDL_Renderer* rend, int x, int y, int z)
    SDL_Surface* surface = IMG_Load(path);
    if (!surface) {
    return 1;
    sp->tex = SDL_CreateTextureFromSurface(rend, surface);
    SDL_QueryTexture(sp->tex, NULL, NULL, &sp->dest.w, &sp->dest.h);
    sp->xreal = x;
    sp->yreal = y;
    sp->zreal = z;
    sp->hreal = sp->dest.h;
    sp->wreal = sp->dest.w;
    return 0;

/* Render a sprite */
int render_sprite(Sprite* sp, SDL_Renderer* rend)  
    return SDL_RenderCopy(rend, sp->tex, NULL, &(sp->dest));

/* Get screen coords and size for a sprite */
void real_to_screen(Sprite* sp) {
    sp->dest.w = ((double) sp->wreal * (double) WINDOWHEIGHT) / ((double)sp->zreal);
    sp->dest.h = ((double) sp->hreal * (double) WINDOWHEIGHT) / ((double)sp->zreal);
    sp->dest.y = (((double) sp->yreal * (double) WINDOWHEIGHT) / ((double) sp->zreal)) + WINDOWHEIGHT/2;
    sp->dest.x = (((double) sp->xreal * (double) WINDOWHEIGHT) / ((double) sp->zreal)) + WINDOWWIDTH/2;