//======================================== // NibblesArea.C // // The object displaying the playable area of ZNibbles. // Big grid in which the worms move. GTK version // // ZNibbles // Vincent Mallet 1997, 1998, 1999 - vmallet@enst.fr //======================================== // $Id: NibblesArea.C,v 1.7 1999/05/12 01:48:25 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 "GtkInterface.H" #include "Map.H" #include "Player.H" #include "NibblesArea.H" #define FILL 1 // Constructor NibblesArea::NibblesArea(GtkInterface& _gif) : _map(NULL), _x(0), _y(0), known_colors(0), colors(NULL), gif(_gif), gc(0), gc_background(0), draw(0), win(0), background_color(0), default_color(0), default_color2(0), joined(FALSE) { } // Destructor NibblesArea::~NibblesArea() { if (_map) { for (int i = 0; i < _y; i++) delete[] _map[i]; delete[] _map; } if (colors) delete[] colors; } // construct basic GUI elements of the NibblesArea void NibblesArea::make() { widget = draw = gtk_drawing_area_new (); gtk_signal_connect (GTK_OBJECT (draw), "expose_event", GTK_SIGNAL_FUNC (draw_exp_cb), this); gtk_widget_show(draw); } void NibblesArea::make2(int x, int y) { _x = x; _y = y; _map = new char * [y]; for (int i = 0; i < y; i++) _map[i] = new char[x]; clear(); _width = x * CELL_SIZE + 4; _height = y * CELL_SIZE + 4; gtk_drawing_area_size (GTK_DRAWING_AREA (draw), _width, _height); gtk_widget_set_usize(draw, _width, _height); } // Return the area size, in pixels. void NibblesArea::get_size_pixel(gint *width, gint *height) { *width = _width; *height = _height; } /* * 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 = draw->window; if (win != NULL) 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::redraw(void) { int x, y = 0; win = draw->window; if (win == NULL) return; if (gc == NULL) { set_config(); gc = gdk_gc_new(win); gc_background = gdk_gc_new(win); gdk_gc_set_foreground(gc, default_color); gdk_gc_set_foreground(gc_background, background_color); } 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) { GdkColor * color; int color_idx; int p = _map[y][x]; if (p == '.') { gdk_draw_rectangle (win, gc_background, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1); return; } if (p >= 100) { color_idx = p - 100; if (color_idx < known_colors) color = colors[color_idx]; else color = default_color; } 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 = default_color2; 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; } } gdk_gc_set_foreground(gc, color); if (p >= 100) { gdk_draw_rectangle(win, gc_background, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1); gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 0, 360 << 6); } else switch(p) { case 'D': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 300 << 6, 300 << 6); break; case 'U': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 120 << 6, 300 << 6); break; case 'L': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 210 << 6, 300 << 6); break; case 'R': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 30 << 6, 300 << 6); break; case 'B': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 330 << 6, 240 << 6); break; case 'H': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 150 << 6, 240 << 6); break; case 'G': gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1, 240 << 6, 240 << 6); break; case 'T': gdk_draw_arc(win, gc, FILL, 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: gdk_draw_rectangle(win, gc_background, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1); sx++; sy++; gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1 - 2, CELL_SIZEM1 - 2, 0, 360 << 6); break; case 'S': { gdk_draw_rectangle(win, gc_background, FILL, 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); gdk_draw_rectangle(win, gc, FILL, sx+2, sy+2, CELL_SIZEM1-2, CELL_SIZEM1-2); } break; case 'X': sx++; sy++; gdk_draw_arc(win, gc, FILL, sx, sy, CELL_SIZEM1 - 2, CELL_SIZEM1 - 2, 0, 360 << 6); break; default: gdk_draw_rectangle(win, gc, FILL, sx, sy, CELL_SIZEM1, CELL_SIZEM1); break; } } // static - expose event callback gint NibblesArea::draw_exp_cb(GtkWidget *widget, GdkEventExpose *event, NibblesArea *mythis) { std::cout << "expose !" << std::endl; if (!mythis->joined) { mythis->gif.join_game(); mythis->joined = TRUE; } mythis->redraw(); return FALSE; } // Return a newly allocated color GdkColor * NibblesArea::get_new_color(gushort red, gushort green, gushort blue) { GdkColor * color = (GdkColor *) malloc(sizeof(GdkColor)); color->red = red * (65535/255); color->green = green * (65535/255); color->blue = blue * (65535/255); color->pixel = (gulong) (red*65536 + green*256 + blue); gdk_color_alloc(gtk_widget_get_colormap(widget), color); return color; } // @@ need to be parametrized // Allocate all colors needed during game void NibblesArea::set_config() { known_colors = 9; colors = new GdkColor* [known_colors]; background_color = get_new_color(0x20, 0x20, 0x60); white_color = get_new_color(0xFF, 0xFF, 0xFF); head_color = white_color; default_color = get_new_color(223, 45, 193); default_color2 = get_new_color(45, 223, 193); yellow_color = get_new_color(0xFF, 0xFF, 0x00); red_color = get_new_color(0xFF, 0x00, 0x00); colors[0] = get_new_color(0xa0, 0x00, 0xa0); colors[1] = get_new_color(0x00, 0xa0, 0xa0); colors[2] = get_new_color(0xa0, 0x00, 0x00); colors[3] = get_new_color(0xaa, 0xaa, 0xaa); colors[4] = get_new_color(0xa0, 0xa0, 0x00); colors[5] = get_new_color(0x00, 0xa0, 0x00); colors[6] = get_new_color(0xFF, 0xC0, 0xCB); // Pink colors[7] = get_new_color(0x00, 0x00, 0xff); colors[8] = get_new_color(0x00, 0xff, 0x00); } GdkColor * NibblesArea::get_player_color(Player& player) { if (player.get_number() < known_colors) return colors[player.get_number()]; return default_color; }