1 /*
2 * Frame.c defines the bouncing shapes (qix,bozo, bez, etc) routines
3 * by Jer Johnson (jer@gweep.net)
4 *
5 */
6
7 #include <math.h>
8 #include <X11/X.h>
9 #include <X11/Xlib.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include "trippy.h"
13 #include "lmath.h"
14
15 struct pt
16 {
17 int x, y;
18 int dx,dy;
19 int pixel;
20 struct pt *next, *prev;
21 };
22
23 typedef struct pt PT;
24
25 struct PTList
26 {
27 int size;
28 PT *next, *prev;
29 };
30 typedef struct PTList ptList;
31
32 ptList *head1,*head2,*head3,*head4;
33
34 int HCV;
35 static int inited=0;
36 static XPoint *make_bozo(int,int,int,int,int,int,int,int);
37
38 void
add(ptList * here,int init,int winno)39 add(ptList *here,int init,int winno)
40 {
41 PT *point;
42
43 point=(PT *)malloc(sizeof(PT));
44
45 if(init) /* if we need to create a point, do it here */
46 {
47 point->x=rndm(CX[winno]);
48 point->y=rndm(CY[winno]);
49 point->dx=1;
50 point->dy=1;
51 point->pixel=rndm(numcolors-1)+1;
52 }
53 else /* otherwise, just move an existing point */
54 {
55 int radius = math_dist(head2[winno].next->x,head2[winno].next->y,
56 head1[winno].next->x,head1[winno].next->y);
57 point->x=here->next->x+here->next->dx;
58 point->y=here->next->y+here->next->dy;
59 point->dx=here->next->dx;
60 point->dy=here->next->dy;
61 point->pixel=(here->next->pixel+HCV)%numcolors;
62 if (!rndm((long)(1000)))
63 point->pixel=rndm(numcolors-1)+1;
64 if((point->x<0)|| ((options.mode==circ)&&(point->x<radius)))
65 {
66 point->dx=rndm(7);
67 point->x+=point->dx;
68 }
69 else if((point->x>CX[winno])||
70 ((options.mode==circ)&&(CX[winno]-point->x<radius)))
71 {
72 point->dx= -rndm(7);
73 point->x+=point->dx;
74 }
75 if((point->y<0)|| ((options.mode==circ)&&(point->y<radius)))
76 {
77 point->dy=rndm(7);
78 point->y+=point->dy;
79 }
80 else if((point->y>CY[winno])||
81 ((options.mode==circ)&&(CY[winno]-point->y<radius)))
82 {
83 point->dy= -rndm(7);
84 point->y+=point->dy;
85 }
86 }
87
88 if(here->prev==NULL)
89 here->prev=point;
90 if(here->next==NULL)
91 here->next=point;
92 else
93 {
94 here->next->prev=point;
95 point->next=here->next;
96 point->prev=here->prev;
97 here->next=point;
98 }
99 here->size++;
100 }
101
delete1(ptList * here)102 void delete1(ptList *here)
103 {
104 PT *temp=here->prev->prev;
105 here->next->prev=temp;
106 temp->next=here->next;
107
108 free(here->prev);
109 here->prev=temp;
110
111 here->size--;
112 }
113
114 void
exit_frame(int winno)115 exit_frame(int winno)
116 {
117 int i;
118
119 i = winno;
120 fprintf(stderr,"Exiting frame\n");
121
122 /* for(i=0;i<options.windows;i++) */
123 {
124 while(head1[i].size>0)
125 delete1(&head1[i]);
126 while(head2[i].size>0)
127 delete1(&head2[i]);
128 if(options.mode==bozo || options.mode==bez)
129 {
130 while(head3[i].size>0)
131 delete1(&head3[i]);
132 while(head4[i].size>0)
133 delete1(&head4[i]);
134 }
135 }
136
137 free(head1);
138 free(head2);
139 if(options.mode==bozo || options.mode==bez)
140 {
141 free(head3);
142 free(head4);
143 }
144 inited=0;
145 }
146
147 void
exit_bozo(int winno)148 exit_bozo(int winno)
149 {
150 exit_frame(winno);
151 }
152
153 void
exit_circ(int winno)154 exit_circ(int winno)
155 {
156 exit_frame(winno);
157 }
158
159 void
exit_qix(int winno)160 exit_qix(int winno)
161 {
162 exit_frame(winno);
163 }
164
165 void
exit_qix4(int winno)166 exit_qix4(int winno)
167 {
168 exit_frame(winno);
169 }
170
171 void
exit_bez(int winno)172 exit_bez(int winno)
173 {
174 exit_frame(winno);
175 }
176
177 void
init_frame(int winno)178 init_frame(int winno)
179 {
180 /* make the first level */
181
182 /* fprintf(stderr,"Init'ing frame\n"); */
183
184 /* 4 lists for each window, one for each point */
185
186 if(!inited)
187 {
188
189 head1=(ptList *)calloc(options.windows,sizeof(ptList));
190 head2=(ptList *)calloc(options.windows,sizeof(ptList));
191 if(options.mode==bozo || options.mode==bez)
192 {
193 head3=(ptList *)calloc(options.windows,sizeof(ptList));
194 head4=(ptList *)calloc(options.windows,sizeof(ptList));
195 }
196 inited=1;
197 }
198
199 /* and now the second level */
200
201 /* init the 4 points */
202 head1[winno].prev=NULL;
203 head1[winno].next=NULL;
204 head1[winno].size=0;
205 head2[winno].prev=NULL;
206 head2[winno].next=NULL;
207 head2[winno].size=0;
208 if(options.mode==bozo || options.mode==bez)
209 {
210 head3[winno].prev=NULL;
211 head3[winno].next=NULL;
212 head3[winno].size=0;
213 head4[winno].prev=NULL;
214 head4[winno].next=NULL;
215 head4[winno].size=0;
216 }
217 add(&head1[winno],1,winno);
218 add(&head2[winno],1,winno);
219 if(options.mode==bozo || options.mode==bez)
220 {
221 add(&head3[winno],1,winno);
222 add(&head4[winno],1,winno);
223 }
224
225 if(options.multi)
226 HCV=1;
227 else
228 HCV=0;
229 }
230
231 void
move_frame(int winno)232 move_frame(int winno)
233 {
234 if(head1[winno].size>=options.number)
235 delete1(&head1[winno]);
236 if(head2[winno].size>=options.number)
237 delete1(&head2[winno]);
238 if(options.mode==bozo || options.mode==bez)
239 {
240 if(head3[winno].size>=options.number)
241 delete1(&head3[winno]);
242 if(head4[winno].size>=options.number)
243 delete1(&head4[winno]);
244 }
245 }
246
247 void
bounce(int winno)248 bounce(int winno)
249 {
250 /*#*#* Bouncing Code *#*#*/
251 add(&head1[winno],0,winno);
252 add(&head2[winno],0,winno);
253 if(options.mode==bozo|| options.mode==bez)
254 {
255 add(&head3[winno],0,winno);
256 add(&head4[winno],0,winno);
257 }
258 }
259
260 void
draw_qix(int winno)261 draw_qix(int winno)
262 {
263 XPoint *ptr1,*ptr2,*ptr3,*ptr4;
264 int i;
265
266 ptr1 = mirror(winno, head1[winno].next->x, head1[winno].next->y,
267 options.mirrors+1, options.opt1);
268 ptr2 = mirror(winno, head2[winno].next->x, head2[winno].next->y,
269 options.mirrors+1, options.opt1);
270 ptr3 = mirror(winno, head1[winno].prev->x, head1[winno].prev->y,
271 options.mirrors+1, options.opt1);
272 ptr4 = mirror(winno, head2[winno].prev->x, head2[winno].prev->y,
273 options.mirrors+1, options.opt1);
274
275 for (i=0;i<=options.mirrors;i++)
276 {
277 XDrawLine(display,window[winno],color_gcs[head1[winno].next->pixel],
278 ptr1[i].x, ptr1[i].y, ptr2[i].x,ptr2[i].y);
279
280 XDrawLine(display,window[winno],color_gcs[options.mono],
281 ptr3[i].x, ptr3[i].y, ptr4[i].x,ptr4[i].y);
282
283 }
284
285 free(ptr1);
286 free(ptr2);
287 free(ptr3);
288 free(ptr4);
289 }
290
291 void
draw_qix4(int winno)292 draw_qix4(int winno)
293 {
294
295 XDrawLine(display,window[winno],color_gcs[head1[winno].next->pixel],
296 head1[winno].next->x,head1[winno].next->y,
297 head2[winno].next->x,head2[winno].next->y);
298 XDrawLine(display,window[winno],color_gcs[head1[winno].next->pixel],
299 CX[winno]-head1[winno].next->x,head1[winno].next->y,
300 CX[winno]-head2[winno].next->x,head2[winno].next->y);
301 XDrawLine(display,window[winno],color_gcs[head1[winno].next->pixel],
302 head1[winno].next->x,CY[winno]-head1[winno].next->y,
303 head2[winno].next->x,CY[winno]-head2[winno].next->y);
304 XDrawLine(display,window[winno],color_gcs[head1[winno].next->pixel],
305 CX[winno]-head1[winno].next->x,CY[winno]-head1[winno].next->y,
306 CX[winno]-head2[winno].next->x,CY[winno]-head2[winno].next->y);
307
308 XDrawLine(display,window[winno],color_gcs[options.mono],
309 head1[winno].prev->x,head1[winno].prev->y,
310 head2[winno].prev->x,head2[winno].prev->y);
311 XDrawLine(display,window[winno],color_gcs[options.mono],
312 CX[winno]-head1[winno].prev->x,head1[winno].prev->y,
313 CX[winno]-head2[winno].prev->x,head2[winno].prev->y);
314 XDrawLine(display,window[winno],color_gcs[options.mono],
315 head1[winno].prev->x,CY[winno]-head1[winno].prev->y,
316 head2[winno].prev->x,CY[winno]-head2[winno].prev->y);
317 XDrawLine(display,window[winno],color_gcs[options.mono],
318 CX[winno]-head1[winno].prev->x,CY[winno]-head1[winno].prev->y,
319 CX[winno]-head2[winno].prev->x,CY[winno]-head2[winno].prev->y);
320 }
321
322 void
draw_bozo(int winno)323 draw_bozo(int winno)
324 {
325 /* draw the bozogon (actually just a quadrilateral,
326 ** but that's not as fun a name as 'bozogon' )
327 */
328 XPoint *ptr1,*ptr2,*ptr3,*ptr4,*ptr5,*ptr6,*ptr7,*ptr8;
329 int i;
330
331 ptr1 = mirror(winno, head1[winno].next->x, head1[winno].next->y,
332 options.mirrors+1, options.opt1);
333 ptr2 = mirror(winno, head2[winno].next->x, head2[winno].next->y,
334 options.mirrors+1, options.opt1);
335 ptr3 = mirror(winno, head1[winno].prev->x, head1[winno].prev->y,
336 options.mirrors+1, options.opt1);
337 ptr4 = mirror(winno, head2[winno].prev->x, head2[winno].prev->y,
338 options.mirrors+1, options.opt1);
339 ptr5 = mirror(winno, head3[winno].next->x, head3[winno].next->y,
340 options.mirrors+1, options.opt1);
341 ptr6 = mirror(winno, head4[winno].next->x, head4[winno].next->y,
342 options.mirrors+1, options.opt1);
343 ptr7 = mirror(winno, head3[winno].prev->x, head3[winno].prev->y,
344 options.mirrors+1, options.opt1);
345 ptr8 = mirror(winno, head4[winno].prev->x, head4[winno].prev->y,
346 options.mirrors+1, options.opt1);
347
348 for(i=0; i<=options.mirrors; i++)
349 {
350 XDrawLines(display,window[winno],color_gcs[head1[winno].next->pixel],
351 make_bozo(ptr1[i].x,ptr1[i].y,
352 ptr2[i].x,ptr2[i].y,
353 ptr5[i].x,ptr5[i].y,
354 ptr6[i].x,ptr6[i].y),
355 5,CoordModeOrigin);
356 /* and erase the last one */
357 XDrawLines(display,window[winno],color_gcs[options.mono],
358 make_bozo(ptr3[i].x,ptr3[i].y,
359 ptr4[i].x,ptr4[i].y,
360 ptr7[i].x,ptr7[i].y,
361 ptr8[i].x,ptr8[i].y),
362 5,CoordModeOrigin);
363 }
364 free(ptr1);
365 free(ptr2);
366 free(ptr3);
367 free(ptr4);
368 free(ptr5);
369 free(ptr6);
370 free(ptr7);
371 free(ptr8);
372 }
373
374 void
draw_bez(int winno)375 draw_bez(int winno)
376 {
377 /* draw a Bezier curve (4 control points, 21 points on the curve */
378 int m,i,clr;
379 XPoint *ptr1,*ptr2,*ptr3,*ptr4,*ptr5,*ptr6,*ptr7,*ptr8;
380
381 ptr1 = mirror(winno, head1[winno].next->x, head1[winno].next->y,
382 options.mirrors+1, options.opt1);
383 ptr2 = mirror(winno, head2[winno].next->x, head2[winno].next->y,
384 options.mirrors+1, options.opt1);
385 ptr3 = mirror(winno, head1[winno].prev->x, head1[winno].prev->y,
386 options.mirrors+1, options.opt1);
387 ptr4 = mirror(winno, head2[winno].prev->x, head2[winno].prev->y,
388 options.mirrors+1, options.opt1);
389 ptr5 = mirror(winno, head3[winno].next->x, head3[winno].next->y,
390 options.mirrors+1, options.opt1);
391 ptr6 = mirror(winno, head4[winno].next->x, head4[winno].next->y,
392 options.mirrors+1, options.opt1);
393 ptr7 = mirror(winno, head3[winno].prev->x, head3[winno].prev->y,
394 options.mirrors+1, options.opt1);
395 ptr8 = mirror(winno, head4[winno].prev->x, head4[winno].prev->y,
396 options.mirrors+1, options.opt1);
397
398 for (m=0; m<=options.mirrors;m++)
399 {
400 XPoint* bezi;
401 bezi = Bezier(make_bozo(ptr1[m].x,ptr1[m].y,
402 ptr2[m].x,ptr2[m].y,
403 ptr5[m].x,ptr5[m].y,
404 ptr6[m].x,ptr6[m].y),21);
405
406 clr=head1[winno].next->pixel;
407
408 for(i=0;i<20;i++)
409 {
410 if(options.opt1 == 1)
411 XDrawPoint(display, window[winno], color_gcs[clr],
412 bezi[i].x,bezi[i].y);
413 else
414 XDrawLine(display, window[winno], color_gcs[clr],
415 bezi[i].x, bezi[i].y, bezi[i+1].x, bezi[i+1].y);
416 if(options.multi)
417 clr = (clr+1)%numcolors;
418 }
419
420 /* and erase the last one */
421 bezi = Bezier(make_bozo(ptr3[m].x,ptr3[m].y,
422 ptr4[m].x,ptr4[m].y,
423 ptr7[m].x,ptr7[m].y,
424 ptr8[m].x,ptr8[m].y),21);
425
426 if(options.opt1 == 1)
427 XDrawPoints(display,window[winno],color_gcs[options.mono],bezi,21,
428 CoordModeOrigin);
429 else
430 XDrawLines(display,window[winno],color_gcs[options.mono],bezi,21,
431 CoordModeOrigin);
432
433 }
434 free(ptr1);
435 free(ptr2);
436 free(ptr3);
437 free(ptr4);
438 free(ptr5);
439 free(ptr6);
440 free(ptr7);
441 free(ptr8);
442 }
443
444
445 void
draw_circ(int winno)446 draw_circ(int winno)
447 {
448 XPoint *ptr1,*ptr2,*ptr3,*ptr4;
449 int i;
450
451 ptr1 = mirror(winno, head1[winno].next->x, head1[winno].next->y,
452 options.mirrors+1, options.opt1);
453 ptr2 = mirror(winno, head2[winno].next->x, head2[winno].next->y,
454 options.mirrors+1, options.opt1);
455 ptr3 = mirror(winno, head1[winno].prev->x, head1[winno].prev->y,
456 options.mirrors+1, options.opt1);
457 ptr4 = mirror(winno, head2[winno].prev->x, head2[winno].prev->y,
458 options.mirrors+1, options.opt1);
459
460 for(i=0;i<= options.mirrors; i++)
461 {
462 XDrawArc(display,window[winno],color_gcs[head1[winno].next->pixel],
463 ptr1[i].x,ptr1[i].y,
464 abs(ptr2[i].x-ptr1[i].x),
465 abs(ptr2[i].y-ptr1[i].y),
466 0, 64*360);
467
468
469 /* and erase the last one */
470 XDrawArc(display,window[winno],color_gcs[options.mono],
471 ptr3[i].x,ptr3[i].y,
472 abs(ptr4[i].x-ptr3[i].x),
473 abs(ptr4[i].y-ptr3[i].y),
474 0, 64*360);
475 }
476
477 free(ptr1);
478 free(ptr2);
479 free(ptr3);
480 free(ptr4);
481 }
482
483 void
draw_boxes(int winno)484 draw_boxes(int winno)
485 {
486 XPoint *ptr1,*ptr2,*ptr3,*ptr4;
487 int i;
488
489 ptr1 = mirror(winno, head1[winno].next->x, head1[winno].next->y,
490 options.mirrors+1, options.opt1);
491 ptr2 = mirror(winno, head2[winno].next->x, head2[winno].next->y,
492 options.mirrors+1, options.opt1);
493 ptr3 = mirror(winno, head1[winno].prev->x, head1[winno].prev->y,
494 options.mirrors+1, options.opt1);
495 ptr4 = mirror(winno, head2[winno].prev->x, head2[winno].prev->y,
496 options.mirrors+1, options.opt1);
497
498 /* draw the rectangles */
499 /*
500 I USED to be able to just call 'XDrawRectangle', but apparently X11R5's
501 version of that function doesn't deal with negative widths and heights.
502 So I'm using XDrawLines and an extra XDrawLine *sigh*. If your
503 XDrawRectangle works, uncomment them and use 'em
504 */
505 for(i=0; i<= options.mirrors; i++)
506 {
507 /*
508 XDrawRectangle(display,window[winno],color_gcs[head1[winno].next->pixel],
509 head1[winno].next->x,head1[winno].next->y,
510 head2[winno].next->x-head1[winno].next->x,
511 head2[winno].next->y-head1[winno].next->y );
512 */
513 XDrawLines(display,window[winno],color_gcs[head1[winno].next->pixel],
514 wrecked(ptr1[i].x, ptr1[i].y, ptr2[i].x, ptr2[i].y),
515 4,CoordModeOrigin);
516 XDrawLine(display,window[winno],color_gcs[head1[winno].next->pixel],
517 ptr1[i].x, ptr1[i].y, ptr1[i].x, ptr2[i].y);
518
519 /* and erase the last one */
520 /*
521 XDrawRectangle(display,window[winno],color_gcs[options.mono],
522 head1[winno].prev->x,head1[winno].prev->y,
523 head2[winno].prev->x-head1[winno].prev->x,
524 head2[winno].prev->y-head1[winno].prev->y );
525 */
526 XDrawLines(display,window[winno],color_gcs[options.mono],
527 wrecked(ptr3[i].x, ptr3[i].y, ptr4[i].x, ptr4[i].y),
528 4,CoordModeOrigin);
529 XDrawLine(display,window[winno],color_gcs[options.mono],
530 ptr3[i].x,ptr3[i].y,
531 ptr3[i].x,ptr4[i].y);
532 }
533 free(ptr1);
534 free(ptr2);
535 free(ptr3);
536 free(ptr4);
537 }
538
539 XPoint *
make_bozo(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)540 make_bozo(int x1,int y1, int x2, int y2,
541 int x3,int y3, int x4, int y4)
542 {
543 static XPoint temp[5];
544
545 temp[0].x = x1; temp[0].y = y1;
546 temp[1].x = x2; temp[1].y = y2;
547 temp[2].x = x3; temp[2].y = y3;
548 temp[3].x = x4; temp[3].y = y4;
549 temp[4].x = x1; temp[4].y = y1;
550
551 return temp;
552 }
553