/* draw a bouncing ball with variable * coloring, optional trace and size * * -- andrey */ #include #include #include #include #include int minx, miny, maxx, maxy; /* window dimensions */ Point p1; /* center of circle drawn */ void eresized(int new) { /* called whenever a window is resized -- reset dimensions and * restart drawing */ Rectangle r1; if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); r1 = screen->r; minx = r1.min.x; maxx = r1.max.x; miny = r1.min.y; maxy = r1.max.y; /* circle always starts at same point */ p1.x = r1.min.x + 100; p1.y = r1.min.y + 100; /* clean up display */ draw(screen, r1, display->white, nil, ZP); } enum { Msize = 100 }; void main(int argc, char **argv) { Mouse m; Image *img, *imgmask; /* img -- color used for drawing ball * imgmask -- black ball on white, mask for drawing an inverse ball */ int slp = 10; /* interval between drawings */ int osize, size = 10; Point oldp; /* previous location of circle */ uint upx = 1; /* flags for movements, should be enum-ed */ uint upy = 1; uint colors = 0; /* do we draw with random colors */ uint clear = 1; /* do we clean up after the circle */ /* menus for mouse clicks in window */ char *items[] = { "slower", "faster", "exit", nil }; char *items2[] = { "clear", "colors", nil }; char *items3[] = {"bigger", "smaller", nil }; /* ordering does not correspond to mouse buttons -- too lazy to fix */ Menu menu; Menu menu2; Menu menu3; /* setup menus */ menu.item = items; menu.gen = nil; menu2.item = items2; menu2.gen = nil; menu3.item = items3; menu3.gen = nil; srand(0); initdraw(0,0,"whoopty doo"); eresized(0); einit(Emouse); imgmask = allocimage(display, Rect(-Msize-2, -Msize-2, Msize+2, Msize+2), GREY1, 0, DWhite); osize = 0; for(;;){ /* handle mouse clicks if any */ if(ecanmouse()) { m = emouse(); if(m.buttons & 4) { switch(emenuhit(3, &m, &menu)) { case 0: slp += 10; break; case 1: if(slp > 0) slp -= 10; else slp = 0; break; case 2: exits("user abort"); default: ; } //eresized(0); } else if(m.buttons & 2) { switch(emenuhit(2, &m, &menu2)) { case 0: if (clear) clear = 0; else clear = 1; break; case 1: if (colors) colors = 0; else colors = 1; break; default: ; } //eresized(0); } else if(m.buttons & 1) { switch(emenuhit(1, &m, &menu3)) { case 0: if((size += 5) > 100) size = 100; break; case 1: if((size -= 5) < 1) size = 0; break; default: ; } //eresized(0); } } if (colors) /* use some sort of random coloring.. ugly */ img = allocimagemix(display,nrand(256)<<24 | nrand(256) << 16 | nrand(256) <<8 | (256 - nrand(256)),nrand(256)<<24 | nrand(256) << 16 | nrand(256) <<8 | (256 - nrand(256))); else /* just draw a black circle */ img = allocimagemix(display, DBlack, DBlack); /* calculate new position */ if (upx) oldp.x = p1.x++; else oldp.x = p1.x--; if(upy) oldp.y = p1.y++; else oldp.y = p1.y--; /* see if we've reached window limits */ if (p1.x - size < minx) upx = 1; /* start moving upwards */ else if (p1.x + size > maxx) upx = 0; if (p1.y - size < miny) upy = 1; else if (p1.y +size > maxy) upy = 0; /* clean up previous location */ if (osize && clear) { draw(imgmask, imgmask->r, display->black, nil, ZP); // transparent fillellipse(imgmask, subpt(oldp, p1), osize, osize, display->white, ZP); // draw opaque old fillellipse(imgmask, ZP, size, size, display->black, ZP); // cover new draw(screen, rectaddpt(imgmask->r, p1), display->white, imgmask, imgmask->r.min); } /* draw */ fillellipse(screen, p1, size, size, img, ZP); flushimage(display, 1); osize = size; /* deallocate current colour */ freeimage(img); /* slow down the drawing somehow */ sleep(slp); } }