/* -------------------------------------------------------------------- * * A christmas blanker inspired by xsnow * * This is an advanced but slower version compared to snow * * initialization/cleanup code copied from the dragon module * (dragon module: (C)Alexander Kneer and Michael D. Bayne) * * -------------------------------------------------------------------- */ #include #include #include #include "/includes.h" #define STAGES 2 /* Number of different shapes */ #define BLANKDELAY 100 /* This many snowflakes are displayed before * we check if to continue blanking */ #define COUNTLIMIT 6 /* max. number of moves in one direction */ #define COUNTMIN 1 /* min. number of moves in one direction */ /* random generation function macros */ #define COUNTFUNC RangeRand(COUNTLIMIT-COUNTMIN)+COUNTMIN #define DXFUNC RangeRand(5)-2; #define DYFUNC RangeRand(2)+1; typedef enum { false, true, random } bool; bool BIGFLAKES; int NUMSNOW; bool COLLECT; bool SHOWSTARS; bool SHOWSNOWMEN; bool SHOWTREES; bool SHOWBG; int NUMOBJ; int patx[10] = { -1,-1, 1, 1, 0 , -1, 1, 0, 0, 0 }; int paty[10] = { -1, 1,-1, 1, 0 , 0, 0, 1,-1, 0 }; int *collect; int *starx; int *stary; int starnum; typedef struct { int x,y; /* The current coordinates */ int dx,dy; /* Movement direction is (dx,dy) */ int count; /* How long to keep direction dx */ int stage; /* STAGES different shapes */ short int mem[5]; /* stores the pixels below its shape */ } snowflake; /* Color pens */ #define CBLACK 0 #define CWHITE 1 #define CGREEN 2 #define CBROWN 3 #define CDGREY 5 #define CMGREY 6 #define CLGREY 7 #define CYELLOW 4 Triplet *ColorTable = 0L; #define PR_FLAKE 0 #define PR_BIG 2 #define PR_COLLECT 3 #define PR_STARS 5 #define PR_BG 6 #define PR_SNMAN 8 #define PR_TREE 9 #define PR_OBJ 11 #define PR_MODE 13 VOID Defaults( PrefObject *Prefs ) { Prefs[PR_FLAKE].po_Level = 200; Prefs[PR_BIG].po_Level = 1; Prefs[PR_COLLECT].po_Level = 1; Prefs[PR_STARS].po_Level = 1; Prefs[PR_BG].po_Level = 1; Prefs[PR_SNMAN].po_Level = 1; Prefs[PR_OBJ].po_Level = 20; Prefs[PR_TREE].po_Level = 1; Prefs[PR_MODE].po_ModeID = getTopScreenMode(); } /* Remove a single snowflake's image from the screen */ __inline void undraw(snowflake *flake, struct RastPort *rp) { if (BIGFLAKES) { int *startx = patx + 5*(flake->stage); int *starty = paty + 5*(flake->stage); int i; for (i=0; i<5; i++) { if (flake->mem[i] != -1) { SetAPen(rp,flake->mem[i]); WritePixel(rp,flake->x+(*startx),flake->y+(*starty)); } startx++; starty++; } } else { if (flake->mem[0] != -1) { SetAPen(rp,flake->mem[0]); WritePixel(rp,flake->x,flake->y); } } } __inline void WriteLine(struct RastPort *rp, int width, int height, int x, int y, int scale, int x1, int y1, int x2, int y2) { x1=x1*4*scale; y1=y1*4*scale; x2=x2*4*scale; y2=y2*4*scale; /* all coordinates are now 1.000 times too big */ Move(rp,x+x1/1000,y+y1/1000); Draw(rp,x+x2/1000,y+y2/1000); } void draw_tree(struct RastPort *rp, int width, int height) { int x,y; int scale; x = RangeRand(width-42); y = RangeRand((height*3)/4-42)+height/4; scale = (y*1000)/height; SetAPen(rp,CBROWN); WriteLine(rp,width,height,x,y,scale,4,10,6,10); WriteLine(rp,width,height,x,y,scale,4,10,4,8); WriteLine(rp,width,height,x,y,scale,6,10,6,8); SetAPen(rp,CGREEN); WriteLine(rp,width,height,x,y,scale,0,8,10,8); WriteLine(rp,width,height,x,y,scale,0,8,3,6); WriteLine(rp,width,height,x,y,scale,10,8,7,6); WriteLine(rp,width,height,x,y,scale,3,6,1,6); WriteLine(rp,width,height,x,y,scale,7,6,9,6); WriteLine(rp,width,height,x,y,scale,1,6,3,4); WriteLine(rp,width,height,x,y,scale,9,6,7,4); WriteLine(rp,width,height,x,y,scale,3,4,2,4); WriteLine(rp,width,height,x,y,scale,7,4,8,4); WriteLine(rp,width,height,x,y,scale,2,4,4,2); WriteLine(rp,width,height,x,y,scale,8,4,6,2); WriteLine(rp,width,height,x,y,scale,4,2,3,2); WriteLine(rp,width,height,x,y,scale,6,2,7,2); WriteLine(rp,width,height,x,y,scale,3,2,5,0); WriteLine(rp,width,height,x,y,scale,7,2,5,0); } __inline void WriteBall(struct RastPort *rp, int x, int y, int scale, int x1, int y1, int r) { int i,j; x1=x1*4*scale; y1=y1*4*scale; r=(r*4*scale)/1000; /* all coordinates are now 1.000 times too big */ for (j=1; j 400) WriteLine(rp,width,height,x,y,scale,1,4,7,4);*/ WriteBall(rp,x,y,scale,4,7,3); WriteBall(rp,x,y,scale,4,4,2); WriteBall(rp,x,y,scale,4,2,1); } /* draw a winterly landscape with everything and more :) */ LONG draw_landscape(struct Screen *scr, int width, int height, struct RastPort *rp) { int numobj,i; LONG flg_end; /* first: the landscape */ { if (SHOWBG) { int x,y; int *hei = malloc(sizeof(int)*width); hei[0]=0; for (i=1; i7) val = 7; if (!val) SetAPen(rp,0); else SetAPen(rp,val+8); WritePixel(rp,x,y); } for (i=1; istage); int *starty = paty + 5*(flake->stage); int i; SetAPen(rp,1); for (i=0; i<5; i++) { int xx = flake->x+(*startx); int yy = flake->y+(*starty); flake->mem[i] = ReadPixel(rp,xx,yy); if (flake->mem[i] == CWHITE) { flake->mem[i] = -1; } else WritePixel(rp,xx,yy); startx++; starty++; } } else { flake->mem[0] = ReadPixel(rp,flake->x,flake->y); if (flake->mem[0] == CWHITE) { flake->mem[0] = -1; } else { SetAPen(rp,1); WritePixel(rp,flake->x,flake->y); } } } /* change the position of a snowflake. If it leaves [0..width]x[0..height], * generate a new one with coordinates (,0) */ __inline void update(snowflake *curr, int width, int height, struct RastPort *rp) { bool gen_new; int oldx = curr->x; if (curr->count > 0) { curr->y = curr->y + curr->dy; if (curr->y >= height-1) { gen_new = true; } else { curr->x = curr->x + curr->dx; if (curr->x < 1 || curr->x >= width-1) { gen_new = true; } else { gen_new = false; (curr->count)--; if (curr->count <= 0) { curr->dx = DXFUNC; curr->count = COUNTFUNC; } if (curr->stage) { curr->stage--; } else { curr->stage = STAGES-1; } } } } /* do we have to compute a new flake? */ if (gen_new) { if (collect && curr->y > height-3) { collect[oldx]--; if (collect[oldx]x = oldx; curr->y = collect[oldx]; draw(curr,rp); } curr->x = RangeRand(width-2)+1; curr->y = 1; curr->dx = DXFUNC; curr->dy = DYFUNC; curr->count = COUNTFUNC; curr->stage = RangeRand(STAGES); } } LONG snow(struct Screen *scr, SHORT width, SHORT height) { unsigned int i; LONG flg_end; snowflake *flake,*curr; int blankcount; bool firstpass = true; struct RastPort *rp = &(scr->RastPort); starx = NULL; stary = NULL; /* first draw a winterly landscape */ flg_end = draw_landscape(scr,width,height,rp); if (flg_end != OK) { if (starx) free(starx); if (stary) free(stary); return flg_end; } /* initialize the snow array */ flake = malloc(NUMSNOW*sizeof(snowflake)); curr = flake; for (i=0; ix = RangeRand(width-2)+1; curr->y = RangeRand(height-2)+1; curr->dx = DXFUNC; curr->dy = DYFUNC; curr->count = COUNTFUNC; curr->stage = RangeRand(STAGES); curr++; } /* and the collect array */ if (COLLECT) { collect = malloc(sizeof(int)*width); for (i=0; iViewPort ), 0, 0, 0, 0 ); ColorTable = RainbowPalette( Scr, 0L, 1L, 0L ); SetRGB4(&( Scr->ViewPort ), 1, 15, 15, 15 ); /* white */ SetRGB4(&( Scr->ViewPort ), 2, 0, 10, 0 ); /* green */ SetRGB4(&( Scr->ViewPort ), 3, 8, 5, 4 ); /* brown */ SetRGB4(&( Scr->ViewPort ), 4, 15, 15, 8 ); /* yellow */ SetRGB4(&( Scr->ViewPort ), 5, 4, 4, 4 ); /* dark grey */ SetRGB4(&( Scr->ViewPort ), 6, 8, 8, 8 ); /* mid grey */ SetRGB4(&( Scr->ViewPort ), 7, 12, 12, 12 ); /* light grey */ { int i; for (i=8; i<16; i++) { SetRGB4(&( Scr->ViewPort ), i, i-7, i-7, i-7); /* different gray */ } } Wnd = BlankMousePointer( Scr ); do RetVal = snow( Scr, Scr->Width, Scr->Height ); while( RetVal == OK ); UnblankMousePointer( Wnd ); RainbowPalette( 0L, ColorTable, 1L, 0L ); CloseScreen( Scr ); } else RetVal = FAILED; return RetVal; }