//======================================== // NibblesArea.C // // The object displaying the playable area of ZNibbles. // Big grid in which the worms move. // // ZNibbles // Vincent Mallet 1997, 1998 - vmallet@enst.fr //======================================== // $Id: NibblesArea.C,v 1.7 1999/05/12 01:48:08 vmallet Exp $ /* ZNibbles - a small multiplayer game * Copyright (C) 1997, 1998, 1999 Vincent Mallet - vmallet@enst.fr * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "motifutil.H" #include "Map.H" #include "MotifInterface.H" #include "NibblesArea.H" // Constructor NibblesArea::NibblesArea(MotifInterface& _mif) : _map(NULL), _x(0), _y(0), known_colors(0), colors(NULL), mif(_mif), joined(False) { } // Destructor NibblesArea::~NibblesArea() { if (_map) { for (int i = 0; i < _y; i++) delete[] _map[i]; delete[] _map; } if (colors) delete[] colors; } void NibblesArea::make2(int x, int y, Widget top) { _x = x; _y = y; _map = new char * [y]; for (int i = 0; i < y; i++) _map[i] = new char[x]; clear(); Dimension twidth; Dimension theight; Dimension width; Dimension height; XtVaGetValues(top, XmNheight, &theight, XmNwidth, &twidth, NULL); XtVaGetValues(draw, XmNheight, &height, XmNwidth, &width, NULL); theight -= height; twidth -= width; width = x * CELL_SIZE + 4; height = y * CELL_SIZE + 4; twidth += width; theight += height; XtVaSetValues(top, XmNheight, theight, XmNwidth, twidth, NULL); XtVaSetValues(widget, XmNheight, height, XmNwidth, width, NULL); } /* * Clear the NibblesArea */ void NibblesArea::clear() { for (int i = 0; i < _y; i++) for (int j = 0; j < _x; j++) _map[i][j] = '.'; } /* * Draw the NibblesArea from data contained in given map */ void NibblesArea::draw_from_map(Map& map) { win = XtWindow(draw); if (win) for (int i = _y -1; i >= 0; i--) for (int j = _x - 1; j >= 0; j--) draw_at(j, i, map._map[i][j]); } void NibblesArea::redraw2(void) { int x, y = 0; win = XtWindow(draw); if (!win) return; for (int i = 0; i < _y; i++) { x = 0; for (int j = 0; j < _x; j++) { _draw_cell(j, i, x, y); x += CELL_SIZE; } y += CELL_SIZE; } } // mutante la fonction, bah, un gros switch.. // one day I'll take time to clean this up inline void NibblesArea::_draw_cell(int x, int y, int sx, int sy) { int color; int p = _map[y][x]; if (p == '.') { XFillRectangle(dpy, win, gc_background, sx, sy, CELL_SIZEM1, CELL_SIZEM1); return; } if (p >= 100) { color = p - 100; if (color < known_colors) color = colors[color]; else color = 40960; } else { switch(p) { case 'D': case 'U': case 'L': case 'R': case 'B': case 'H': case 'G': case 'T': color = head_color; break; case 'S': case 'X': color = red_color; break; case '*': color = white_color; break; case 'x': color = 3040; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: if (p < known_colors) color = colors[p]; else color = yellow_color; break; default: color = background_color; break; } } XSetForeground(dpy, gc, color); if (p >= 100) { XFillRectangle(dpy, win, gc_background, sx, sy, CELL_SIZEM1, CELL_SIZEM1); XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 0, 360 << 6); } else switch(p) { case 'D': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 300 << 6, 300 << 6); break; case 'U': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 120 << 6, 300 << 6); break; case 'L': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 210 << 6, 300 << 6); break; case 'R': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 30 << 6, 300 << 6); break; case 'B': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 330 << 6, 240 << 6); break; case 'H': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 150 << 6, 240 << 6); break; case 'G': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 240 << 6, 240 << 6); break; case 'T': XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 60 << 6, 240 << 6); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: XFillRectangle(dpy, win, gc_background, sx, sy, CELL_SIZEM1, CELL_SIZEM1); sx++; sy++; XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1 - 2, CELL_SIZEM1 - 2, 0, 360 << 6); break; case 'S': { XFillRectangle(dpy, win, gc_background, sx, sy, CELL_SIZEM1, CELL_SIZEM1); XPoint point[4]; point[0].x = point[2].x = sx + (CELL_SIZEM1 >> 1); point[0].y = sy; point[1].x = sx + CELL_SIZEM1; point[1].y = point[3].y = sy + (CELL_SIZEM1 >> 1); point[2].y = sy + CELL_SIZEM1; point[3].x = sx; XFillPolygon(dpy, win, gc, point, 4, Convex, CoordModeOrigin); } break; case 'X': sx++; sy++; XFillArc(dpy, win, gc, sx, sy, CELL_SIZEM1 - 2, CELL_SIZEM1 - 2, 0, 360 << 6); break; default: XFillRectangle(dpy, win, gc, sx, sy, CELL_SIZEM1, CELL_SIZEM1); break; } } void NibblesArea:: draw_exp_cb(Widget w, XtPointer client_data, XtPointer cbs) { NibblesArea & mythis = * (NibblesArea *) client_data; w = w; cbs = cbs; // warnings if (!mythis.joined) { mythis.mif.join_game(); mythis.joined = True; } mythis.redraw2(); } void NibblesArea::make(Widget parent) { widget = draw = XtVaCreateManagedWidget("NibblesAreaDraw", xmDrawingAreaWidgetClass, parent, NULL); XtAddCallback(draw, XmNexposeCallback, draw_exp_cb, (XtPointer) this); XtAddEventHandler(draw, KeyPressMask, False, key_cb, this); // for the keyress callbacks dpy = XtDisplay(widget); yellow_color = white_color = head_color = BlackPixel(dpy, DefaultScreen(dpy)); get_GC(dpy, &gc); get_GC(dpy, &gc_background); } // void NibblesArea::my_color_alloc(char *name, XColor *col) // { // XColor temp; // if (! XAllocNamedColor(dpy, // DefaultColormapOfScreen(XtScreen(widget)), // name, // col, // &temp)) { // XLookupColor(dpy, // DefaultColormapOfScreen(XtScreen(widget)), // name, // &temp, // col); // } // } // // @@ need to be parametrized // void NibblesArea::set_config() // { // XColor temp; // XColor col; // known_colors = 9; // colors = new unsigned long [known_colors]; // int bad = 0; // char s[50]; // for (int i = 0; i < 255; i++) { // sprintf(s, "#%06x", i); // if (! XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), s, &col, &temp) ) // bad++; // } // cout << "--bad=" << bad << endl; // my_color_alloc("#000040", &col); // background_color = col.pixel; // XSetForeground(dpy, gc_background, background_color); // my_color_alloc("#ffffff", &col); // white_color = col.pixel; // head_color = col.pixel; // my_color_alloc("Yellow", &col); // yellow_color = col.pixel; // my_color_alloc("Red", &col); // red_color = col.pixel; // my_color_alloc("#a000a0", &col); // colors[0] = col.pixel; // my_color_alloc("#00a0a0", &col); // colors[1] = col.pixel; // my_color_alloc("#aaaaaa", &col); // colors[2] = col.pixel; // my_color_alloc("#a00000", &col); // colors[3] = col.pixel; // my_color_alloc("#a0a000", &col); // colors[4] = col.pixel; // my_color_alloc("#00a000", &col); // colors[5] = col.pixel; // my_color_alloc("#Pink", &col); // colors[6] = col.pixel; // my_color_alloc("#0000ff", &col); // colors[7] = col.pixel; // my_color_alloc("#00ff00", &col); // colors[8] = col.pixel; // if (draw) // redraw2(); // } // @@ need to be parametrized void NibblesArea::set_config() { XColor temp; XColor col; known_colors = 9; colors = new unsigned long [known_colors]; // int bad = 0; // char s[50]; // for (int i = 0; i < 255; i++) { // sprintf(s, "#%06x", i); // if (! XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), s, &col, &temp) ) // bad++; // } // cout << "--bad=" << bad << endl; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#000040", &col, &temp); background_color = col.pixel; XSetForeground(dpy, gc_background, background_color); XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#ffffff", &col, &temp); white_color = col.pixel; head_color = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "Yellow", &col, &temp); yellow_color = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "Red", &col, &temp); red_color = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#a000a0", &col, &temp); colors[0] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#00a0a0", &col, &temp); colors[1] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#a00000", &col, &temp); colors[2] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#aaaaaa", &col, &temp); colors[3] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#a0a000", &col, &temp); colors[4] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#00a000", &col, &temp); colors[5] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "Pink", &col, &temp); colors[6] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#0000ff", &col, &temp); colors[7] = col.pixel; XAllocNamedColor(dpy, DefaultColormapOfScreen(XtScreen(widget)), "#00ff00", &col, &temp); colors[8] = col.pixel; if (draw) redraw2(); } // Create GC in Xcopy mode void NibblesArea:: get_GC(Display *display, GC *gc_out) { XGCValues values; unsigned long valuemask; valuemask = GCFunction | /* GCPlaneMask | */ GCForeground | GCLineWidth | GCFillStyle; values.function = GXcopy; values.line_width = 4; values.fill_style = FillSolid; values.foreground = 0x101010; *gc_out = XCreateGC(display, RootWindow(display, DefaultScreen(display)), valuemask, &values); } void NibblesArea::nice_cursor(int shape) { :: nice_cursor(draw, shape); } void NibblesArea::key_cb(Widget w, XtPointer client_data, XEvent *event, char *z) { NibblesArea & mythis = (NibblesArea &) * (NibblesArea *) client_data; XKeyPressedEvent & kevent = (XKeyPressedEvent &) * event; z = (char *) &mythis; // muffle warnings w = w; char buffer; int bufsize=1; // int charcount; KeySym ks; // charcount = XLookupString(&kevent, &buffer, bufsize, &ks, NULL); switch(ks) { case XK_Down: mythis.mif.send_direction(D_DOWN); break; case XK_Up: mythis.mif.send_direction(D_UP); break; case XK_Left: mythis.mif.send_direction(D_LEFT); break; case XK_Right: mythis.mif.send_direction(D_RIGHT); break; case XK_p: mythis.mif.pause_request(PAUSE_GAME); break; case XK_u: mythis.mif.pause_request(UNPAUSE_GAME); break; case XK_P: mythis.mif.pause_request(PAUSE_OWN); break; case XK_U: mythis.mif.pause_request(UNPAUSE_OWN); break; case XK_0: mythis.mif.send_predefined_message(0); break; case XK_1: mythis.mif.send_predefined_message(1); break; case XK_2: mythis.mif.send_predefined_message(2); break; case XK_3: mythis.mif.send_predefined_message(3); break; case XK_4: mythis.mif.send_predefined_message(4); break; case XK_5: mythis.mif.send_predefined_message(5); break; case XK_6: mythis.mif.send_predefined_message(6); break; case XK_7: mythis.mif.send_predefined_message(7); break; case XK_8: mythis.mif.send_predefined_message(8); break; case XK_9: mythis.mif.send_predefined_message(9); break; default: // printf("sym == %04x\n", (int) ks); break; } }