/*Fractal program by Sam Cox 2001 */ /* This file uses functions from the ALLEGRO game programming library * http://www.talula.demon.co.uk/allegro/ * which runs with the compiler DJGPP * http://www.delorie.com/djgpp * * The program produces fractal images which can be tweaked in many ways. * The user can change the resolution, zoom in and out (up to 1.42 Bazillion times), * change the colours, aswell as modifying parameters used to create the fractals. * If you are familiar with the Mandelbrot Set this means changing the C value in * z[i]= z[i-1]*z[i-1] + c. * Screenshots can be saved aswell. */ #include #include #include #include "allegro.h" #include "img.h" #define LENGTH 1000 // The number of iterations to complete #define LIMIT 10.0 // What is considered infinity (stop when this is reached) BEGIN_GFX_DRIVER_LIST // This removes unused ALLEGRO graphics drivers //GFX_DRIVER_VBEAF //GFX_DRIVER_VGA //GFX_DRIVER_MODEX GFX_DRIVER_VESA3 GFX_DRIVER_VESA2L GFX_DRIVER_VESA2B //GFX_DRIVER_XTENDED //GFX_DRIVER_VESA1 END_GFX_DRIVER_LIST BEGIN_COLOR_DEPTH_LIST // This removes unused colours COLOR_DEPTH_8 // Plain old 256 colour here :) //COLOR_DEPTH_15 //COLOR_DEPTH_16 //COLOR_DEPTH_24 //COLOR_DEPTH_32 END_COLOR_DEPTH_LIST void put_img(BITMAP *buffer, img num, int colour); int sequence(img z0,img c); // This function simply draws a pixel where the imaginary number num is. inline void put_img(BITMAP *buffer, img num, int colour) { putpixel(buffer, (int)((num.r +2.0)*(SCREEN_W/4)), (int)((num.i-1.5)*(-(SCREEN_H/3))), colour); } void draw_zoom(double x1, double y1, double x2, double y2) { rect(screen,(int)((x1 +2.0)*(SCREEN_W/4)),(int)((y1-1.5)*(-(SCREEN_H/3))), (int)((x2 +2.0)*(SCREEN_W/4)),(int)((y2-1.5)*(-(SCREEN_H/3))),255); } // This function uses the formula below with z0 as the first value and iterates LENGTH times or // until LIMIT is reached. The number returned is either the value of i or 0 if LIMIT is never // reached. This means that z0 values that reach LIMIT (infinity) are coloured and ones that // dont are black (colour 0). int sequence(img z0, img c) { img z[LENGTH]; z[0] = z0; for (int i=1;i LIMIT || z[i].r < -LIMIT || z[i].i > LIMIT || z[i].i < -LIMIT ) return i; // Return the value of i when the sequence reached LIMIT. This // then becomes the colour of that point. } return 0; // else return zero (black) } int main() { BITMAP *bmp; // used for screenshots allegro_init(); // Allegro initialisation stuff install_keyboard(); install_timer(); //set_gfx_mode(GFX_VESA3,640, 480, 0, 0); // Uncomment to select screen size //set_gfx_mode(GFX_VESA3,800, 600, 0, 0); set_gfx_mode(GFX_VESA3,1024, 768, 0, 0); //set_gfx_mode(GFX_VESA3,1280, 1024, 0, 0); BITMAP *buffer = create_bitmap(SCREEN_W,SCREEN_H); set_pallete(desktop_pallete); PALLETE pallete; // Create a pallete then fill it with nice colours int col; for (col=0; col<64; col++) { pallete[col].r = col; pallete[col].g = 0; pallete[col].b = 0; } for (col=64; col<128; col++) { pallete[col].r = 127-col; pallete[col].g = col-64; pallete[col].b = 0; } for (col=128; col<192; col++) { pallete[col].r = 0; pallete[col].g = 191-col; pallete[col].b = col-128; } for (col=192; col<256; col++) { pallete[col].r = 0; pallete[col].g = 0; pallete[col].b = 255-col; } pallete[255].r = 255; // Save colour 255 for white pallete[255].g = 255; pallete[255].b = 255; pallete[0].r = 0; // and 0 for black pallete[0].g = 0; pallete[0].b = 0; set_pallete(pallete); text_mode(-1); double zoom = 1.0; // Set to 1.0 for no zoom (NOT ZERO) double xshift = 0.0; // Shift on x axis double yshift = 0.0; // Shift on y axis double increment = .2; // Value of each incrementation double resolution = 0.01; // Initial resolution img c(0.0,0.1); // Initial value of c (for use in sequence()) int colour; // The colour returned by sequence() img shift(xshift*zoom,yshift*zoom); // Just an imaginary representation of the x and y shift (to make it // easier to add to z0 later) double lastzoom = 1.0; // These LAST variables are used for the zoom rectangle double lastxshift = 0.0; double lastyshift = 0.0; static int screen_shot = 1; // The screenshot number textprintf(screen, font, 50,100, 255, "Mandelbrot Set Graphical Viewer"); textprintf(screen, font, 50,110, 255, "Arrow keys move screen"); textprintf(screen, font, 50,120, 255, "Page up/down changes zoom level"); textprintf(screen, font, 50,130, 255, "Comma and full stop change resolution"); textprintf(screen, font, 50,140, 255, "Then press enter to redraw screen"); textprintf(screen, font, 50,150, 255, "Press S for a screen shot"); textprintf(screen, font, 50,160, 255, "Press and hold SPACE to cycle the Colours - VERY COOL!"); textprintf(screen, font, 50,170, 255, "Keys I,K and J,L change the value of C"); do { // Main loop if (key[KEY_ENTER]) { // Press return to redraw shift.r = xshift*zoom; shift.i = yshift*zoom; // Update shift values lastzoom = 1.0; lastxshift = 0.0; lastyshift = 0.0; clear_to_color(screen,0); // Clear screen and buffer clear_to_color(buffer,0); clear_keybuf(); /* The initial (no zoom/shift) position of the screen is from -2 to 2 on the * x (real) axis and -1.5i to 1.5i on the y (imaginary/complex) axis. For each * point in this range, sequence() is run returning a colour for that point. */ for (double i=(-2.0/zoom - xshift);i<(2.0/zoom -xshift);i+=resolution/zoom) { for (double j=-1.5/zoom - yshift;j<1.5/zoom - yshift;j+=resolution/zoom) { img z0(i,j); colour = sequence(c,z0); // Since the screen is already black we dont have to // draw the black points. if (colour != 0) { put_img(buffer, z0*zoom + shift, colour); } } // Now blit the buffer to the screen blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); // Press any key to stop this process. Stop not pause. if (keypressed()) break; } clear_keybuf(); } if (key[KEY_UP] ) { // Shift screen up yshift-= increment/zoom;clear_keybuf(); lastyshift-= increment/lastzoom; blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); draw_zoom(-2.0/lastzoom - lastxshift,-1.5/lastzoom - lastyshift,2.0/lastzoom -lastxshift, 1.5/lastzoom - lastyshift); } if (key[KEY_DOWN] ) { // Shift screen down yshift+= increment/zoom;clear_keybuf(); lastyshift+= increment/lastzoom; blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); draw_zoom(-2.0/lastzoom - lastxshift,-1.5/lastzoom - lastyshift,2.0/lastzoom -lastxshift, 1.5/lastzoom - lastyshift); } if (key[KEY_RIGHT] ) { // Shift screen left xshift-= increment/zoom;clear_keybuf(); lastxshift-= increment/lastzoom; blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); draw_zoom(-2.0/lastzoom - lastxshift,-1.5/lastzoom - lastyshift,2.0/lastzoom -lastxshift, 1.5/lastzoom - lastyshift); } if (key[KEY_LEFT] ) { // Shift screen right xshift+= increment/zoom;clear_keybuf(); lastxshift+= increment/lastzoom; blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); draw_zoom(-2.0/lastzoom - lastxshift,-1.5/lastzoom - lastyshift,2.0/lastzoom -lastxshift, 1.5/lastzoom - lastyshift); } if (key[KEY_PGUP] ) { // Increase zoom by a factor of 10% zoom = zoom*1.1;clear_keybuf(); lastzoom = lastzoom*1.1; blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); draw_zoom(-2.0/lastzoom - lastxshift,-1.5/lastzoom - lastyshift,2.0/lastzoom -lastxshift, 1.5/lastzoom - lastyshift); } if (key[KEY_PGDN] ) { // Decrease zoom by a factor of 10% zoom = zoom/1.1;clear_keybuf(); lastzoom = lastzoom/1.1; blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); draw_zoom(-2.0/lastzoom - xshift,-1.5/lastzoom - yshift,2.0/lastzoom -xshift, 1.5/lastzoom - yshift); } if (key[KEY_STOP] ) { // Increase resolution resolution=resolution+0.001;clear_keybuf(); } if (key[KEY_COMMA] ) { // Decrease resolution resolution=resolution-0.001;clear_keybuf(); if (resolution < 0.002) resolution = 0.002; } if (key[KEY_S]) { // Printscreen routine PALETTE pal; get_palette(pal); char temp[3]; char filename[15] = "ScreenShot"; strcat(filename, strcat(itoa(screen_shot,temp, 10), ".bmp")); blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H); save_bitmap(filename, bmp, pal); destroy_bitmap(bmp); screen_shot++; clear_keybuf(); } while (key[KEY_SPACE]) { // Cycle the pallete to create RGB temp = pallete[254]; // a cool effect for (col=254; col>1; col--) pallete[col] = pallete[col-1]; pallete[1] = temp; set_pallete(pallete); rest(10); } if (key[KEY_I] ) { // Change the value of C c.i+= 0.001;clear_keybuf(); } if (key[KEY_K] ) { c.i-= 0.001;clear_keybuf(); } if (key[KEY_J] ) { c.r+= 0.001;clear_keybuf(); } if (key[KEY_L] ) { c.r-= 0.001;clear_keybuf(); } if (key[KEY_B] ) { blit(buffer, screen, 0,0,0,0,SCREEN_W, SCREEN_H); } text_mode(0); textprintf(screen, font,15, 25, 255, "Zoom: %2.4f",zoom); textprintf(screen, font,15, 35, 255, "xshift: %2.4f",xshift); textprintf(screen, font,15, 45, 255, "yshift: %2.4f",yshift); textprintf(screen, font,15, 55, 255, "resolution: %2.4f",resolution); textprintf(screen, font,15, 65, 255, "C: %2.4f, %2.4fj",c.r, c.i); } while (!key[KEY_ESC]); // Escape to exit destroy_bitmap(buffer); return 0; }