/* truchetdraw * Chris Lu * gcc -o truchetdraw truchetdraw.c -lSDL */ #include #include #include #define XRES 800 #define YRES 600 #define BLOCK_SIZE 40 #define WIDTH 3 #define COLOR_R 0x00FFFFFF #define COLOR_L 0x00FFFFFF #define DELAY 3300 SDL_Surface *screen; char state[YRES/BLOCK_SIZE][XRES/BLOCK_SIZE]; int randomize = 0; SDL_TimerID timerid; void draw_one_square_l(unsigned int*, int, int); void draw_one_square_r(unsigned int*, int, int); void reset(unsigned int*, int opt); void update(); Uint32 rnd_cb(Uint32, void*); void print_scr() { FILE *file = fopen("truchetdraw.pnm", "w"); if(!file) { printf("Could not open truchetdraw.pnm\n"); return; } fprintf(file, "P6 %d %d 255\n", XRES, YRES); SDL_LockSurface(screen); unsigned int i, *p = screen->pixels; for(i = 0; i < XRES * YRES; i++) { unsigned int pix = p[i]; fprintf(file, "%c%c%c", (char)((pix >> 16) & 0xFF), (char)((pix >> 8) & 0xFF), (char)(pix & 0xFF)); } SDL_UnlockSurface(screen); fclose(file); printf("Saved screenshot to truchetdraw.pnm.\n"); } void handle_event(SDL_Event *ev) { switch(ev->type) { case SDL_QUIT: exit(0); case SDL_KEYUP: { SDL_KeyboardEvent kev = *(SDL_KeyboardEvent*)(ev); switch(kev.keysym.sym) { unsigned int *p; case SDLK_r: SDL_LockSurface(screen); p = screen->pixels; reset(p, 1); SDL_LockSurface(screen); break; case SDLK_l: SDL_LockSurface(screen); p = screen->pixels; reset(p, 0); SDL_LockSurface(screen); break; case SDLK_s: randomize = !randomize; if(randomize) { timerid = SDL_AddTimer(50, rnd_cb, NULL); if(!timerid) { randomize = !randomize; printf("Error setting timer...\n"); } } else SDL_RemoveTimer(timerid); break; case SDLK_p: print_scr(); return; case SDLK_q: printf("Bye!\n"); exit(0); default: break; } update(); return; } case SDL_MOUSEBUTTONUP: { SDL_MouseButtonEvent mev = *(SDL_MouseButtonEvent*)(ev); if(mev.button = SDL_BUTTON_LEFT) { int rx = mev.x/BLOCK_SIZE; int ry = mev.y/BLOCK_SIZE; SDL_LockSurface(screen); unsigned int *p = screen->pixels; if(state[ry][rx]) draw_one_square_l(p, rx, ry); else draw_one_square_r(p, rx, ry); SDL_UnlockSurface(screen); } update(); return; } default: return; } } void draw_one_square_l(unsigned int *pixels, int x, int y) { int i, j; int min = BLOCK_SIZE/2 - WIDTH; int max = BLOCK_SIZE/2 + WIDTH; int x_off = x * BLOCK_SIZE; int y_off = y * BLOCK_SIZE; state[y][x] = 0; for(i = 0; i < BLOCK_SIZE; i++) { for(j = 0; j < BLOCK_SIZE; j++) { int sum = (i + j) % BLOCK_SIZE; int color = sum < max && sum > min ? COLOR_L : 0; pixels[XRES * (y_off + i) + x_off + j] = color; } } } void draw_one_square_r(unsigned int *pixels, int x, int y) { int i, j; int min = BLOCK_SIZE/2 - WIDTH; int max = BLOCK_SIZE/2 + WIDTH; int x_off = x * BLOCK_SIZE; int y_off = y * BLOCK_SIZE; state[y][x] = 1; for(i = 0; i < BLOCK_SIZE; i++) { for(j = 0; j < BLOCK_SIZE; j++) { int sum = (i - j + BLOCK_SIZE) % BLOCK_SIZE; int color = sum < max && sum > min ? COLOR_R : 0; pixels[XRES * (y_off + i) + x_off + j] = color; } } } void reset(unsigned int *p, int opt) { int i, j; for(i = 0; i < XRES / BLOCK_SIZE; i++) { for(j = 0; j < YRES / BLOCK_SIZE; j++) { if(opt) draw_one_square_l(p, i, j); else draw_one_square_r(p, i, j); } } } static inline void do_rnd() { unsigned int *p, xpos, ypos, i; SDL_LockSurface(screen); p = screen->pixels; for(i = 0; i < 6; i++) { xpos = rand() % (XRES / BLOCK_SIZE); ypos = rand() % (YRES / BLOCK_SIZE); if(rand() & 1) draw_one_square_l(p, xpos, ypos); else draw_one_square_r(p, xpos, ypos); } SDL_UnlockSurface(screen); } Uint32 rnd_cb(Uint32 x, void* p) { if(randomize) do_rnd(); update(); return x; } void update() { SDL_Flip(screen); } int main(int argc, char **argv) { int delay; unsigned int *p; SDL_Event ev; screen = NULL; if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { printf("Init failed: %s\n", SDL_GetError()); return 1; } atexit(SDL_Quit); screen = SDL_SetVideoMode(XRES, YRES, 32, SDL_SWSURFACE); if(!screen) { printf("Video mode init failed: %s\n", SDL_GetError()); return 1; } SDL_WM_SetCaption("truchetdraw", "truchetdraw"); printf("click to toggle tile\n" "r: reset\n" "l: reset in other direction\n" "s: toggle randomizing\n" "p: save screenshot\n" "q: quit\n"); atexit(SDL_Quit); srand(time(NULL)); SDL_LockSurface(screen); p = screen->pixels; reset(p, 0); SDL_UnlockSurface(screen); update(); while (SDL_WaitEvent(&ev)) { handle_event(&ev); } return 1; }