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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [demos/] [nxroach/] [nxroach.x] - Rev 174

Compare with Previous | Blame | View Log

/*
    Xroach - A game of skill.  Try to find the roaches under your windows.
    
    Copyright 1991 by J.T. Anderson

    jta@locus.com
    
    This program may be freely distributed provided that all
    copyright notices are retained.

    To build:
      cc -o xroach roach.c -lX11 [-lsocketorwhatever] [-lm] [-l...]

    Dedicated to Greg McFarlane.   (gregm@otc.otca.oz.au)
*/
//#include <X11/Xlib.h>
//#include <X11/Xutil.h>
//#include <X11/Xos.h>

#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#define MWINCLUDECOLORS
#include "nano-X.h"
#include "XtoNX.h"

char Copyright[] = "Xroach\nCopyright 1991 J.T. Anderson";

#include "roachmap.h"

typedef unsigned long Pixel;
typedef int ErrorHandler();

#define SCAMPER_EVENT   99              // LASTEvent+1?

#if !defined(GRAB_SERVER)
#define GRAB_SERVER     0
#endif

STATIC_FUNCTIONS;

Display *display;
int screen;
Window rootWin;
unsigned int display_width, display_height;
int center_x, center_y;
GC gc;
char *display_name = NULL;
Pixel black, white;

int done = 0;
int eventBlock = 0;
int errorVal = 0;

typedef struct Roach {
    RoachMap *rp;
    int index;
    float x;
    float y;
    int intX;
    int intY;
    int hidden;
    int turnLeft;
    int steps;
} Roach;

Roach *roaches;
int maxRoaches = 10;
int curRoaches = 0;
float roachSpeed = 20.0;

Region rootVisible = 0;

void Usage(void);
void SigHandler(int sig);
void AddRoach(void);
void MoveRoach(int Rx);
void DrawRoaches(void);
void CoverRoot(void);
int CalcRootVisible(void);
int MarkHiddenRoaches(void);
//Pixel AllocNamedColor();

int
main(int ac, char **av)
{
    //XGCValues xgcv;
    int ax;
    char *arg;
    RoachMap *rp;
    int rx;
    float angle;
    XEvent ev;
    char *roachColor = "black";
    int nVis;
    int needCalc;
    
    /*
       Process command line options.
    */
    for (ax=1; ax<ac; ax++) {
        arg = av[ax];
        if (strcmp(arg, "-display") == 0) {
            display_name = av[++ax];
        }
        else if (strcmp(arg, "-rc") == 0) {
            roachColor = av[++ax];
        }
        else if (strcmp(arg, "-speed") == 0) {
            roachSpeed = atof(av[++ax]);
        }
        else if (strcmp(arg, "-roaches") == 0) {
            maxRoaches = strtol(av[++ax], (char **)NULL, 0);
        }
        else {
            Usage();
        }
    }

    srand((int)time((long *)NULL));
    
    /*
       Catch some signals so we can erase any visible roaches.
    */
    signal(SIGKILL, SigHandler);
    signal(SIGINT, SigHandler);
    signal(SIGTERM, SigHandler);
    signal(SIGHUP, SigHandler);

    display = XOpenDisplay(display_name);
    if (display == NULL) {
        if (display_name == NULL) display_name = getenv("DISPLAY");
        (void) fprintf(stderr, "%s: cannot connect to server %s\n", av[0],
            display_name ? display_name : "(default)");
        exit(1);
    }

    screen = DefaultScreen(display);
    rootWin = RootWindow(display, screen);
    black = BlackPixel(display, screen);
    white = WhitePixel(display, screen);

    display_width = DisplayWidth(display, screen);
    display_height = DisplayHeight(display, screen);
    center_x = display_width / 2;
    center_y = display_height / 2;
    
    /*
       Create roach pixmaps at several orientations.
    */
    for (ax=0; ax<360; ax+=ROACH_ANGLE) {
        rx = ax / ROACH_ANGLE;
        angle = rx * 0.261799387799;
        rp = &roachPix[rx];
        //rp->pixmap = XCreateBitmapFromData(display, rootWin,
            //rp->roachBits, rp->width, rp->height);
        rp->pixmap = XCreatePixmapFromBitmapData(display, rootWin,
            rp->roachBits, rp->width, rp->height, BLACK, CYAN, 1);      //FIXME
        rp->sine = sin(angle);
        rp->cosine = cos(angle);
    }

    roaches = (Roach *)malloc(sizeof(Roach) * maxRoaches);

    gc = XCreateGC(display, rootWin, 0L, &xgcv);
    //XSetForeground(display, gc, AllocNamedColor(roachColor, black));
    //XSetFillStyle(display, gc, FillStippled);
    
    while (curRoaches < maxRoaches)
        AddRoach();
    
    XSelectInput(display, rootWin, ExposureMask | SubstructureNotifyMask);
    
    needCalc = 1;
    while (!done) {
        if (XPending(display)) {
            XNextEvent(display, &ev);
        }
        else {
            if (needCalc) {
                needCalc = CalcRootVisible();
            }
            nVis = MarkHiddenRoaches();
            if (nVis) {
                ev.type = SCAMPER_EVENT;
            }
            else {
                DrawRoaches();
                GrDelay(100);
                eventBlock = 1;
                XNextEvent(display, &ev);
                eventBlock = 0;
            }
        }
        
        switch (ev.type) {
            
            case SCAMPER_EVENT:
                for (rx=0; rx<curRoaches; rx++) {
                    if (!roaches[rx].hidden)
                        MoveRoach(rx);
                }
                DrawRoaches();
                GrDelay(100);
                XSync(display, False);
                break;
                
            case Expose:
            //case MapNotify:
            //case UnmapNotify:
            case ConfigureNotify:
                needCalc = 1;
                break;
                
        }
    }
    
    CoverRoot();
    
    XCloseDisplay(display);
    return 0;
}

#define USEPRT(msg) fprintf(stderr, msg)

void
Usage(void)
{
    USEPRT("Usage: nxroach [options]\n\n");
    USEPRT("Options:\n");
    USEPRT("       -display displayname\n");
    USEPRT("       -rc      roachcolor\n");
    USEPRT("       -roaches numroaches\n");
    USEPRT("       -speed   roachspeed\n");
    
    exit(1);
}

void
SigHandler(int sig)
{
       
    /*
       If we are blocked, no roaches are visible and we can just bail
       out.  If we are not blocked, then let the main procedure clean
       up the root window.
    */
    if (eventBlock) {
        XCloseDisplay(display);
        exit(0);
    }
    else {
        done = 1;
    }
}

/*
   Generate random integer between 0 and maxVal-1.
*/
int
RandInt(int maxVal)
{
        return rand() % maxVal;
}

/*
   Check for roach completely in specified rectangle.
*/
int
RoachInRect(roach, rx, ry, x, y, width, height)
Roach *roach;
int rx;
int ry;
int x;
int y;
unsigned int width;
unsigned int height;
{
    if (rx < x) return 0;
    if ((rx + roach->rp->width) > (x + width)) return 0;
    if (ry < y) return 0;
    if ((ry + roach->rp->height) > (y + height)) return 0;
    
    return 1;
}

/*
   Check for roach overlapping specified rectangle.
*/
int
RoachOverRect(roach, rx, ry, x, y, width, height)
Roach *roach;
int rx;
int ry;
int x;
int y;
unsigned int width;
unsigned int height;
{
    if (rx >= (x + width)) return 0;
    if ((rx + roach->rp->width) <= x) return 0;
    if (ry >= (y + height)) return 0;
    if ((ry + roach->rp->height) <= y) return 0;
    
    return 1;
}

/*
   Give birth to a roach.
*/
void
AddRoach(void)
{
    Roach *r;
    
    if (curRoaches < maxRoaches) {
        r = &roaches[curRoaches++];
        r->index = RandInt(ROACH_HEADINGS);
        r->rp = &roachPix[r->index];
        r->x = RandInt(display_width - r->rp->width);
        r->y = RandInt(display_height - r->rp->height);
        r->intX = -1;
        r->intY = -1;
        r->hidden = 0;
        r->steps = RandInt(200);
        r->turnLeft = RandInt(100) >= 50;
    }
}

/*
   Turn a roach.
*/
void
TurnRoach(roach)
Roach *roach;
{
    if (roach->index != (roach->rp - roachPix)) return;

    if (roach->turnLeft) {
        roach->index += (RandInt(30) / 10) + 1;
        if (roach->index >= ROACH_HEADINGS)
            roach->index -= ROACH_HEADINGS;
    }
    else {
        roach->index -= (RandInt(30) / 10) + 1;
        if (roach->index < 0)
            roach->index += ROACH_HEADINGS;
    }
}

/*
   Move a roach.
*/
void
MoveRoach(int rx)
{
    Roach *roach;
    Roach *r2;
    float newX;
    float newY;
    int ii;
    
    roach = &roaches[rx];
    newX = roach->x + (roachSpeed * roach->rp->cosine);
    newY = roach->y - (roachSpeed * roach->rp->sine);
    
    if (RoachInRect(roach, (int)newX, (int)newY, 
                            0, 0, display_width, display_height)) {
        
        roach->x = newX;
        roach->y = newY;

        if (roach->steps-- <= 0) {
            TurnRoach(roach);
            roach->steps = RandInt(200);
        }

        for (ii=rx+1; ii<curRoaches; ii++) {
            r2 = &roaches[ii];
            if (RoachOverRect(roach, (int)newX, (int)newY,
                r2->intX, r2->intY, r2->rp->width, r2->rp->height)) {
        
                TurnRoach(roach);
            }
        }
    }
    else {
        TurnRoach(roach);
    }
}
    
/*
   Draw all roaches.
*/
void
DrawRoaches(void)
{
    Roach *roach;
    int rx;
    
    for (rx=0; rx<curRoaches; rx++) {
        roach = &roaches[rx];
        
        if (roach->intX >= 0) {
            XClearArea(display, rootWin, roach->intX, roach->intY,
                roach->rp->width, roach->rp->height, False);
        }
    }
    
    for (rx=0; rx<curRoaches; rx++) {
        roach = &roaches[rx];
        
        if (!roach->hidden) {
            roach->intX = roach->x;
            roach->intY = roach->y;
            roach->rp = &roachPix[roach->index];
    
            //XSetStipple(display, gc, roach->rp->pixmap);
            //XSetTSOrigin(display, gc, roach->intX, roach->intY);
            //XFillRectangle(display, rootWin, gc,
                //roach->intX, roach->intY, roach->rp->width, roach->rp->height);
            GrCopyArea(GR_ROOT_WINDOW_ID, gc, roach->intX, roach->intY,
                roach->rp->width, roach->rp->height, roach->rp->pixmap, 0, 0,
                MWROP_SRCCOPY);
        }
        else {
            roach->intX = -1;
        }
    }
}

/*
   Cover root window to erase roaches.
*/
void
CoverRoot(void)
{
    //XSetWindowAttributes xswa;
    //long wamask;
    Window roachWin;
    
#define CopyFromParent  0
#define InputOutput     0
    //xswa.background_pixmap = ParentRelative;
    //xswa.override_redirect = True;
    //wamask = CWBackPixmap | CWOverrideRedirect;
    roachWin = XCreateWindow(display, rootWin, 0, 0,
                    display_width, display_height, 0, CopyFromParent,
                    InputOutput, CopyFromParent, wamask, &xswa);
    XLowerWindow(display, roachWin);
    XMapWindow(display, roachWin);
    XFlush(display);
}    

#if !GRAB_SERVER

#if 0
int
RoachErrors(dpy, err)
Display *dpy;
XErrorEvent *err;
{
    errorVal = err->error_code;
    
    return 0;
}
#endif
#endif /* GRAB_SERVER */

/*
   Calculate Visible region of root window.
*/
int
CalcRootVisible(void)
{
    Region covered;
    Region visible;
    Window *children;
    int nChildren;
    Window dummy;
    //XWindowAttributes wa;
    int wx;
    XRectangle rect;
    int winX, winY;
    unsigned int winHeight, winWidth;
    unsigned int borderWidth;
    unsigned int depth;
    GR_WINDOW_INFO info;
    
    /*
       If we don't grab the server, the XGetWindowAttribute or XGetGeometry
       calls can abort us.  On the other hand, the server grabs can make for
       some annoying delays.
    */
#if GRAB_SERVER
    //XGrabServer(display);
#else
    //XSetErrorHandler(RoachErrors);
#endif

    /*
       Get children of root.
    */
    XQueryTree(display, rootWin, &dummy, &dummy, &children, &nChildren);
    
    /*
       For each mapped child, add the window rectangle to the covered
       region.
    */
    covered = XCreateRegion();
    for (wx=0; wx<nChildren; wx++) {
        //if (XEventsQueued(display, QueuedAlready)) return 1;
        //errorVal = 0;
        //XGetWindowAttributes(display, children[wx], &wa);
        //if (errorVal) continue;
        GrGetWindowInfo(children[wx], &info);
        //if (wa.map_state == IsViewable) {
        if (info.unmapcount == 0) {
            //XGetGeometry(display, children[wx], &dummy, &winX, &winY,
                //&winWidth, &winHeight, &borderWidth, &depth);
            //if (errorVal) continue;
            rect.x = info.x;
            rect.y = info.y;
            //rect.width = winWidth + (borderWidth * 2);
            //rect.height = winHeight + (borderWidth * 2);
            rect.width = info.width;
            rect.height = info.height;
            XUnionRectWithRegion(&rect, covered, covered);
        }
    }
    XFree((char *)children);

#if GRAB_SERVER
    //XUngrabServer(display);
#else
    //XSetErrorHandler((ErrorHandler *)NULL);
#endif
    
    /*
       Subtract the covered region from the root window region.
    */
    visible = XCreateRegion();
    rect.x = 0;
    rect.y = 0;
    rect.width = display_width;
    rect.height = display_height;
    XUnionRectWithRegion(&rect, visible, visible);
    XSubtractRegion(visible, covered, visible);
    XDestroyRegion(covered);
    
    /*
       Save visible region globally.
    */
    if (rootVisible)
        XDestroyRegion(rootVisible);
    rootVisible = visible;
    
    
    /*
       Mark all roaches visible.
    */
    for (wx=0; wx<curRoaches; wx++) 
        roaches[wx].hidden = 0;

    return 0;
}

/*
   Mark hidden roaches.
*/
int
MarkHiddenRoaches(void)
{
    int rx;
    Roach *r;
    int nVisible;
    
    nVisible = 0;
    for (rx=0; rx<curRoaches; rx++) {
        r = &roaches[rx];
        
        if (!r->hidden) {
            if (r->intX > 0 && XRectInRegion(rootVisible, r->intX, r->intY,
                            r->rp->width, r->rp->height) == RectangleOut) {
                r->hidden = 1;
            }
            else {
                nVisible++;
            }
        }
    }
    
    return nVisible;
}

#if 0
/*
   Allocate a color by name.
*/
Pixel
AllocNamedColor(colorName, dfltPix)
char *colorName;
Pixel dfltPix;
{
        Pixel pix;
        XColor scrncolor;
        XColor exactcolor;

        if (XAllocNamedColor(display, DefaultColormap(display, screen),
                colorName, &scrncolor, &exactcolor)) {
                pix = scrncolor.pixel;
        }
        else {
                pix = dfltPix;
        }

        return pix;
}
#endif

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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