/***************************************************************** ** Snake.c - KABjorke 30 March 87 ** ** © 1987, National Pixel Products ** ** Released to the Public Domain for Non-Commercial Purposes. ** ** A variant on the old "bouncing lines" program. ** ** This version uses multiple vertices and Bezier splines. ** *****************************************************************/ #include #include #include #include #include #include #define MAXVERT 15 #define BGPEN 0 #define FGPEN 1 #define LOPEN 2 #define HIPEN 3 /* Event() return codes */ #define DUNNO -1 #define RESIZED 1 #define TRAIL (Trails.Flags&CHECKED) #define POLYS (ShoPoly.Flags&CHECKED) /****************************************************************/ /******* Built-Ins **********************************************/ /****************************************************************/ extern LONG GfxBase; extern LONG IntuitionBase; extern struct Window *OpenWindow(); extern struct IntuiMessage *GetMsg(); /****************************************************************/ /******* Local IntuiJunk ****************************************/ /****************************************************************/ struct Window *w; struct RastPort *rp; struct IntuiMessage *message; USHORT class; struct TextAttr ROMFont8 = { "Topaz80",8,0,0 /* Define text font for our screen */ }; struct IntuiText SText[2] = { {LOPEN,BGPEN,JAM1,CHECKWIDTH,0,&ROMFont8,"Trails",NULL}, {LOPEN,BGPEN,JAM1,CHECKWIDTH,0,&ROMFont8,"Poly", NULL} }; struct MenuItem ShoPoly = { NULL, /* NextItem */ 0,9,(CHECKWIDTH+50), 9, /* Corner, Size */ ITEMTEXT|HIGHCOMP|ISDRAWN|ITEMENABLED|CHECKIT|MENUTOGGLE, /* Flags */ 0L, /* MutualExclude */ (APTR)&SText[1], NULL, /* ItemFill, SelectFill */ '\0', /* Command */ NULL, NULL /* SubItem, NextSelect */ }; struct MenuItem Trails = { &ShoPoly, /* NextItem */ 0,0,(CHECKWIDTH+50), 9, /* Corner, Size */ ITEMTEXT|HIGHCOMP|ISDRAWN|ITEMENABLED|CHECKIT|MENUTOGGLE, /* Flags */ 0L, /* MutualExclude */ (APTR)&SText[0], NULL, /* ItemFill, SelectFill */ '\0', /* Command */ NULL, NULL /* SubItem, NextSelect */ }; struct Menu Options = { NULL, /* NextMenu */ 0,0,(CHECKWIDTH+54),9, /* Corner, Size */ MIDRAWN|MENUENABLED, /* Flags */ "Snake", /* MenuName */ &Trails /* FirstItem */ }; /****************************************************************/ /******* Window *************************************************/ /****************************************************************/ struct NewWindow nw = { 100,50, /* Starting corner */ 300,100, /* Width, Height */ LOPEN,HIPEN, /* DetailPen, BlockPen */ CLOSEWINDOW|NEWSIZE, /* IDCMPFlags (Don't need MENUPICK!) */ WINDOWDEPTH|ACTIVATE|WINDOWDRAG|WINDOWCLOSE| SMART_REFRESH|WINDOWSIZING, /* Flags */ NULL, /* FirstGadget */ NULL, /* Pointer to checkmark */ "Snake", /* title */ NULL, /* Screen */ NULL, /* Bitmap */ 50,50,640,400, /* Size limits */ WBENCHSCREEN /* Type */ }; /****************************************************************/ /******* Spline Vars ********************************************/ /****************************************************************/ float coeffs[4][MAXVERT]; float P[2][4], Pv[2][4], xlf, ylf; SHORT xlim, ylim; SHORT DispVerts[(2*MAXVERT)]; SHORT OldVerts[16][(2*MAXVERT)]; SHORT control[8], oldcont[16][8]; /****************************************************************/ /****** Function Typing *****************************************/ /****************************************************************/ extern VOID AmiSetup(); extern VOID SplineSetup(); extern VOID CalcSnake(); extern SHORT Event(); /****************************************************************/ /******* Execution Begins Here **********************************/ /****************************************************************/ VOID _main() { register UWORD i; register BOOL k; UWORD onward = 0; UWORD SnakeColr = FGPEN; UWORD PolyColr = HIPEN; LONG Iterate = 0L; AmiSetup(); SplineSetup(); xlim = w->Width - 3; ylim = w->Height - 2; xlf = (float)xlim; ylf = (float)ylim; for(i=0;i<4;++i) { P[0][i] = (float)(rand() % (xlim-2) + 1); /* random start */ P[1][i] = (float)(rand() % (ylim-14) + 13); Pv[0][i] = (float)(rand() % 10 + 1); /* and vector */ Pv[1][i] = (float)(rand() % 10 + 1); } class = NULL; do { CalcSnake(); if ((!TRAIL) && (onward)) { SetAPen(rp,BGPEN); /* erase old */ onward = Iterate & 15; Move(rp,OldVerts[onward][0],OldVerts[onward][1]); PolyDraw(rp,MAXVERT,&OldVerts[onward][0]); if (POLYS) { Move(rp,oldcont[onward][0],oldcont[onward][1]); PolyDraw(rp,4,&oldcont[onward][0]); } } SetAPen(rp,SnakeColr); /* Draw new Curve */ Move(rp,DispVerts[0],DispVerts[1]); PolyDraw(rp,MAXVERT,&DispVerts[0]); if (POLYS) { SetAPen(rp,PolyColr); Move(rp,control[0],control[1]); PolyDraw(rp,4,&control[0]); } if((rand() & 127) < 2) { /* new color */ PolyColr = SnakeColr; if (++SnakeColr > 3) SnakeColr = 1; } onward = (10 + Iterate++) & 15; for (i=0; i<(2*MAXVERT); ++i) /* old curve */ OldVerts[onward][i] = DispVerts[i]; for (i=0; i<8; ++i) /* old control points */ oldcont[onward][i] = control[i]; for(i=0;i<4;++i) { /* update control points */ P[0][i] += Pv[0][i]; /* new control points */ P[1][i] += Pv[1][i]; if(P[0][i] < 2.0) { /* clipping */ P[0][i] = 2.0; Pv[0][i] = -Pv[0][i]; } else if(P[0][i] > xlf) { P[0][i] = xlf; Pv[0][i] = -Pv[0][i]; } if(P[1][i] < 10.0) { P[1][i] = 10.0; Pv[1][i] = -Pv[1][i]; } else if(P[1][i] > ylf) { P[1][i] = ylf; Pv[1][i] = -Pv[1][i]; } if(((rand() >> 5) & 127) < 2) { /* change x speed */ k = (Pv[0][i] < 0.0); Pv[0][i] = (rand() >> 5) & 7; if (k) Pv[0][i] = -Pv[0][i]; } if(((rand() >> 5) & 255) < 50) { /* change y speed */ k = (Pv[1][i] < 0.0); Pv[1][i] = (rand() >> 5) & 7; if (k) Pv[1][i] = -Pv[1][i]; } } onward = 1; if(w->UserPort->mp_SigBit) { message = GetMsg(w->UserPort); if(message != NULL) { class = message->Class; ReplyMsg(message); } } } while(Event()); ClearMenuStrip(w); CloseWindow(w); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); } /****************************************************************/ /****** Analyse IDCMP events ************************************/ /****************************************************************/ SHORT Event() { switch(class) { case CLOSEWINDOW: return(NULL); break; case NEWSIZE: class = NULL; xlim = w->Width - 3; ylim = w->Height -2; xlf = (float)xlim; ylf = (float)ylim; return(RESIZED); break; } return(DUNNO); } /****************************************************************/ /****** Set up display & libraries ******************************/ /****************************************************************/ VOID AmiSetup() { if ((GfxBase = OpenLibrary("graphics.library",LIBRARY_VERSION)) == NULL) { Exit(20); } if ((IntuitionBase = OpenLibrary("intuition.library",LIBRARY_VERSION)) == NULL) { CloseLibrary(GfxBase); Exit(20); } if ((w = OpenWindow(&nw)) == NULL) { CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); Exit(20); } rp = w->RPort; SetAPen(rp,HIPEN); SetDrMd(rp,JAM1); SetMenuStrip(w,&Options); } /****************************************************************/ /******* Precalculate Spline Coefficients ***********************/ /****************************************************************/ VOID SplineSetup() { float t; UWORD i; for (i=0; ixlim) xt = xlim; if (yt<12.0) yt = 12.0; if (yt>ylim) yt = ylim; #endif DEBUG DispVerts[ndx++] = (SHORT)xt; DispVerts[ndx++] = (SHORT)yt; } ndx = 0; for (i=0; i<4; ++i) { control[ndx++] = (SHORT)P[0][i]; control[ndx++] = (SHORT)P[1][i]; } } /****************************************************************/ /******************************************************** eof ***/ /****************************************************************/