OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [mw/] [src/] [demos/] [nxroach/] [nxroach.c] - Blame information for rev 716

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
2
    Xroach - A game of skill.  Try to find the roaches under your windows.
3
    Ported to Nano-X by Greg Haerr
4
 
5
    Copyright 1991 by J.T. Anderson
6
    jta@locus.com
7
 
8
    This program may be freely distributed provided that all
9
    copyright notices are retained.
10
 
11
    Dedicated to Greg McFarlane.   (gregm@otc.otca.oz.au)
12
*/
13
char Copyright[] = "nxroach\nCopyright 1991 J.T. Anderson";
14
 
15
#include <stdio.h>
16
#include <math.h>
17
#include <signal.h>
18
#include <stdlib.h>
19
#include <time.h>
20 716 simons
/* SIMON: we use strcmp */
21
#include <string.h>
22 673 markom
#define MWINCLUDECOLORS
23
#include "nano-X.h"
24
 
25
#define None    0
26
#define Pixmap  GR_WINDOW_ID
27
#include "roachmap.h"
28
 
29
#define SCAMPER_EVENT   99
30
 
31
typedef struct Roach {
32
    RoachMap *rp;
33
    int index;
34
    float x;
35
    float y;
36
    int intX;
37
    int intY;
38
    int hidden;
39
    int turnLeft;
40
    int steps;
41
} Roach;
42
 
43
GR_COORD display_width, display_height;
44
GR_GC_ID gc;
45
GR_COLOR roachColor = BLACK;
46
GR_REGION_ID rootVisible = 0;
47
GR_BOOL done = GR_FALSE;
48
GR_BOOL eventBlock = GR_FALSE;
49
 
50
Roach *roaches;
51
int maxRoaches = 10;
52
int curRoaches = 0;
53
float roachSpeed = 20.0;
54
 
55
void Usage(void);
56
void SigHandler(int sig);
57
void AddRoach(void);
58
void MoveRoach(int Rx);
59
void DrawRoaches(void);
60
void CoverRoot(void);
61
int CalcRootVisible(void);
62
int MarkHiddenRoaches(void);
63
 
64
int
65
main(int ac, char **av)
66
{
67
    int ax;
68
    char *arg;
69
    RoachMap *rp;
70
    int rx;
71
    float angle;
72
    GR_EVENT ev;
73
    int nVis;
74
    int needCalc;
75
    GR_SCREEN_INFO sinfo;
76
 
77
    /*
78
       Process command line options.
79
    */
80
    for (ax=1; ax<ac; ax++) {
81
        arg = av[ax];
82
        if (strcmp(arg, "-rc") == 0) {
83
            roachColor = atoi(av[++ax]);
84
        }
85
        else if (strcmp(arg, "-speed") == 0) {
86
            roachSpeed = atof(av[++ax]);
87
        }
88
        else if (strcmp(arg, "-roaches") == 0) {
89
            maxRoaches = strtol(av[++ax], (char **)NULL, 0);
90
        }
91
        else {
92
            Usage();
93
        }
94
    }
95
 
96
    srand((int)time((long *)NULL));
97
 
98
    /*
99
       Catch some signals so we can erase any visible roaches.
100
    */
101
    signal(SIGKILL, SigHandler);
102
    signal(SIGINT, SigHandler);
103
    signal(SIGTERM, SigHandler);
104
    signal(SIGHUP, SigHandler);
105
 
106
    if (GrOpen() < 0) {
107
        fprintf(stderr, "can't open graphics\n");
108
        exit(1);
109
    }
110
 
111
    GrGetScreenInfo(&sinfo);
112
    display_width = sinfo.cols;
113
    display_height = sinfo.rows;
114
 
115
    /*
116
       Create roach pixmaps at several orientations.
117
    */
118
    for (ax=0; ax<360; ax+=ROACH_ANGLE) {
119
        rx = ax / ROACH_ANGLE;
120
        angle = rx * 0.261799387799;
121
        rp = &roachPix[rx];
122
        rp->pixmap = GrNewPixmapFromData(rp->width, rp->height, WHITE, BLACK,
123
                rp->roachBits, GR_BMDATA_BYTEREVERSE|GR_BMDATA_BYTESWAP);
124
        rp->sine = sin(angle);
125
        rp->cosine = cos(angle);
126
    }
127
 
128
    roaches = (Roach *)malloc(sizeof(Roach) * maxRoaches);
129
 
130
    gc = GrNewGC();
131
 
132
    while (curRoaches < maxRoaches)
133
        AddRoach();
134
 
135
    GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_CHLD_UPDATE);
136
 
137
    needCalc = 1;
138
    while (!done) {
139
        if (GrPeekEvent(&ev))
140
            GrGetNextEvent(&ev);
141
        else {
142
            if (needCalc) {
143
                needCalc = CalcRootVisible();
144
            }
145
            nVis = MarkHiddenRoaches();
146
            if (nVis) {
147
                ev.type = SCAMPER_EVENT;
148
            }
149
            else {
150
                DrawRoaches();
151
                eventBlock = GR_TRUE;
152
                GrGetNextEvent(&ev);
153
                eventBlock = GR_FALSE;
154
            }
155
        }
156
 
157
        switch (ev.type) {
158
            case SCAMPER_EVENT:
159
                for (rx=0; rx<curRoaches; rx++) {
160
                    if (!roaches[rx].hidden)
161
                        MoveRoach(rx);
162
                }
163
                DrawRoaches();
164
                GrDelay(100);
165
                break;
166
 
167
            case GR_EVENT_TYPE_EXPOSURE:
168
            case GR_EVENT_TYPE_CHLD_UPDATE:
169
                needCalc = 1;
170
                break;
171
 
172
        }
173
    }
174
 
175
    CoverRoot();
176
    GrClose();
177
    return 0;
178
}
179
 
180
void
181
Usage(void)
182
{
183
    fprintf(stderr, "Usage: nxroach [options]\n\n");
184
    fprintf(stderr, "Options:\n");
185
    fprintf(stderr, "       -rc      roachcolor\n");
186
    fprintf(stderr, "       -roaches numroaches\n");
187
    fprintf(stderr, "       -speed   roachspeed\n");
188
 
189
    exit(1);
190
}
191
 
192
void
193
SigHandler(int sig)
194
{
195
    /*
196
       If we are blocked, no roaches are visible and we can just bail
197
       out.  If we are not blocked, then let the main procedure clean
198
       up the root window.
199
    */
200
    if (eventBlock) {
201
        GrClose();
202
        exit(0);
203
    }
204
    else {
205
        done = GR_TRUE;
206
    }
207
}
208
 
209
/*
210
   Generate random integer between 0 and maxVal-1.
211
*/
212
int
213
RandInt(int maxVal)
214
{
215
        return rand() % maxVal;
216
}
217
 
218
/*
219
   Check for roach completely in specified rectangle.
220
*/
221
int
222
RoachInRect(Roach *roach, int rx, int ry, int x, int y,
223
        unsigned int width, unsigned int height)
224
{
225
    if (rx < x) return 0;
226
    if ((rx + roach->rp->width) > (x + width)) return 0;
227
    if (ry < y) return 0;
228
    if ((ry + roach->rp->height) > (y + height)) return 0;
229
 
230
    return 1;
231
}
232
 
233
/*
234
   Check for roach overlapping specified rectangle.
235
*/
236
int
237
RoachOverRect(Roach *roach, int rx, int ry, int x, int y,
238
        unsigned int width, unsigned int height)
239
{
240
    if (rx >= (x + width)) return 0;
241
    if ((rx + roach->rp->width) <= x) return 0;
242
    if (ry >= (y + height)) return 0;
243
    if ((ry + roach->rp->height) <= y) return 0;
244
 
245
    return 1;
246
}
247
 
248
/*
249
   Give birth to a roach.
250
*/
251
void
252
AddRoach(void)
253
{
254
    Roach *r;
255
 
256
    if (curRoaches < maxRoaches) {
257
        r = &roaches[curRoaches++];
258
        r->index = RandInt(ROACH_HEADINGS);
259
        r->rp = &roachPix[r->index];
260
        r->x = RandInt(display_width - r->rp->width);
261
        r->y = RandInt(display_height - r->rp->height);
262
        r->intX = -1;
263
        r->intY = -1;
264
        r->hidden = 0;
265
        r->steps = RandInt(200);
266
        r->turnLeft = RandInt(100) >= 50;
267
    }
268
}
269
 
270
/*
271
   Turn a roach.
272
*/
273
void
274
TurnRoach(Roach *roach)
275
{
276
    if (roach->index != (roach->rp - roachPix)) return;
277
 
278
    if (roach->turnLeft) {
279
        roach->index += (RandInt(30) / 10) + 1;
280
        if (roach->index >= ROACH_HEADINGS)
281
            roach->index -= ROACH_HEADINGS;
282
    }
283
    else {
284
        roach->index -= (RandInt(30) / 10) + 1;
285
        if (roach->index < 0)
286
            roach->index += ROACH_HEADINGS;
287
    }
288
}
289
 
290
/*
291
   Move a roach.
292
*/
293
void
294
MoveRoach(int rx)
295
{
296
    Roach *roach;
297
    Roach *r2;
298
    float newX;
299
    float newY;
300
    int ii;
301
 
302
    roach = &roaches[rx];
303
    newX = roach->x + (roachSpeed * roach->rp->cosine);
304
    newY = roach->y - (roachSpeed * roach->rp->sine);
305
 
306
    if (RoachInRect(roach, (int)newX, (int)newY,
307
                            0, 0, display_width, display_height)) {
308
 
309
        roach->x = newX;
310
        roach->y = newY;
311
 
312
        if (roach->steps-- <= 0) {
313
            TurnRoach(roach);
314
            roach->steps = RandInt(200);
315
        }
316
 
317
        for (ii=rx+1; ii<curRoaches; ii++) {
318
            r2 = &roaches[ii];
319
            if (RoachOverRect(roach, (int)newX, (int)newY,
320
                r2->intX, r2->intY, r2->rp->width, r2->rp->height)) {
321
 
322
                TurnRoach(roach);
323
            }
324
        }
325
    }
326
    else {
327
        TurnRoach(roach);
328
    }
329
}
330
 
331
/*
332
   Draw all roaches.
333
*/
334
void
335
DrawRoaches(void)
336
{
337
    Roach *roach;
338
    int rx;
339
 
340
    for (rx=0; rx<curRoaches; rx++) {
341
        roach = &roaches[rx];
342
 
343
        if (roach->intX >= 0) {
344
            GrClearArea(GR_ROOT_WINDOW_ID, roach->intX, roach->intY,
345
                roach->rp->width, roach->rp->height, GR_FALSE);
346
        }
347
    }
348
 
349
    for (rx=0; rx<curRoaches; rx++) {
350
        roach = &roaches[rx];
351
 
352
        if (!roach->hidden) {
353
            int size = roach->rp->width * roach->rp->height;
354
            GR_PIXELVAL roachbuf[size];
355
            GR_PIXELVAL screenbuf[size];
356
            int i;
357
 
358
            roach->intX = roach->x;
359
            roach->intY = roach->y;
360
            roach->rp = &roachPix[roach->index];
361
 
362
            /*
363
            //XSetForeground(display, gc, AllocNamedColor(roachColor, black));
364
            //XSetFillStyle(display, gc, FillStippled);
365
            //XSetStipple(display, gc, roach->rp->pixmap);
366
            //XSetTSOrigin(display, gc, roach->intX, roach->intY);
367
            //XFillRectangle(display, rootWin, gc,
368
                //roach->intX, roach->intY, roach->rp->width, roach->rp->height);
369
            */
370
 
371
            /* read roach bitmap*/
372
            GrReadArea(roach->rp->pixmap, 0, 0,
373
                roach->rp->width, roach->rp->height, roachbuf);
374
 
375
            /* read root window*/
376
            GrReadArea(GR_ROOT_WINDOW_ID, roach->intX, roach->intY,
377
                roach->rp->width, roach->rp->height, screenbuf);
378
 
379
            /* convert fg roach bitmap bits to roach color on root window bits*/
380
            for (i=0; i<size; ++i)
381
                    if (roachbuf[i] != BLACK)
382
                            screenbuf[i] = roachColor;
383
 
384
            /* write root window*/
385
            GrArea(GR_ROOT_WINDOW_ID, gc, roach->intX, roach->intY,
386
                roach->rp->width, roach->rp->height, screenbuf, MWPF_PIXELVAL);
387
        }
388
        else {
389
            roach->intX = -1;
390
        }
391
    }
392
    GrFlush();
393
}
394
 
395
/*
396
   Cover root window to erase roaches.
397
*/
398
void
399
CoverRoot(void)
400
{
401
    GR_WINDOW_ID roachWin;
402
 
403
    roachWin = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, display_width, display_height,
404
                    0, CYAN, BLACK);
405
    GrLowerWindow(roachWin);
406
    GrMapWindow(roachWin);
407
    GrFlush();
408
}
409
 
410
/*
411
   Calculate Visible region of root window.
412
*/
413
int
414
CalcRootVisible(void)
415
{
416
    GR_REGION_ID covered;
417
    GR_REGION_ID visible;
418
    GR_WINDOW_ID parent;
419
    GR_WINDOW_ID *children;
420
    GR_COUNT nChildren;
421
    GR_COUNT wx;
422
    GR_RECT rect;
423
    GR_WINDOW_INFO info;
424
 
425
    /*
426
       Get children of root.
427
    */
428
    GrQueryTree(GR_ROOT_WINDOW_ID, &parent, &children, &nChildren);
429
 
430
    /*
431
       For each mapped child, add the window rectangle to the covered
432
       region.
433
    */
434
    covered = GrNewRegion();
435
    for (wx=0; wx<nChildren; wx++) {
436
        GrGetWindowInfo(children[wx], &info);
437
        if (info.unmapcount == 0) {
438
            rect.x = info.x;
439
            rect.y = info.y;
440
            rect.width = info.width;
441
            rect.height = info.height;
442
            GrUnionRectWithRegion(covered, &rect);
443
        }
444
    }
445
    free(children);
446
 
447
    /*
448
       Subtract the covered region from the root window region.
449
    */
450
    visible = GrNewRegion();
451
    rect.x = 0;
452
    rect.y = 0;
453
    rect.width = display_width;
454
    rect.height = display_height;
455
    GrUnionRectWithRegion(visible, &rect);
456
    GrSubtractRegion(visible, visible, covered);
457
    GrDestroyRegion(covered);
458
 
459
    /*
460
       Save visible region globally.
461
    */
462
    if (rootVisible)
463
        GrDestroyRegion(rootVisible);
464
    rootVisible = visible;
465
 
466
    /*
467
       Mark all roaches visible.
468
    */
469
    for (wx=0; wx<curRoaches; wx++)
470
        roaches[wx].hidden = 0;
471
 
472
    return 0;
473
}
474
 
475
/*
476
   Mark hidden roaches.
477
*/
478
int
479
MarkHiddenRoaches(void)
480
{
481
    int rx;
482
    Roach *r;
483
    int nVisible;
484
 
485
    nVisible = 0;
486
    for (rx=0; rx<curRoaches; rx++) {
487
        r = &roaches[rx];
488
 
489
        if (!r->hidden) {
490
            if (r->intX > 0 && GrRectInRegion(rootVisible, r->intX, r->intY,
491
                            r->rp->width, r->rp->height) == MWRECT_OUT) {
492
                r->hidden = 1;
493
            }
494
            else {
495
                nVisible++;
496
            }
497
        }
498
    }
499
 
500
    return nVisible;
501
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.