// 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include #include "smallmap.h" #include "stacklist.h" #include "citylist.h" #include "ruinlist.h" #include "templelist.h" #include "city.h" #include "ruin.h" #include "temple.h" #include "playerlist.h" #include "player.h" #include "GameMap.h" #include "config.h" using namespace std; //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<format; d_staticMap = SDL_CreateRGBSurface(SDL_HWSURFACE, GameMap::getSize()*d_pixels, GameMap::getSize()*d_pixels, fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask); // Draw map SDL_Color c; for(int i = 0; i < GameMap::getSize(); i++) { for(int j = 0; j < GameMap::getSize(); j++) { c = GameMap::getInstance()->getTile(i,j)->getColor(); for (int dx = 0; dx < d_pixels; dx++) for (int dy = 0; dy < d_pixels; dy++) PG_Draw::SetPixel(i*d_pixels + dx, j*d_pixels + dy, PG_Color(c.r, c.g, c.b), d_staticMap); } } restartTimer(); } SmallMap::~SmallMap() { delete d_viewrect; SDL_FreeSurface(d_staticMap); interruptTimer(); } void SmallMap::changeResolution(int x_squares,int y_squares) { delete(d_viewrect); d_viewrect = new PG_Rect(1, 1, x_squares, y_squares); } void SmallMap::eventDraw(SDL_Surface* surface, const PG_Rect& rect) { debug("eventDraw()"); // During the whole drawing stuff, ALWAYS consider that the size of the // widget is GameMap::getSize() + 2 (+2 for the border). So we always // have an offset of 1 between map coordinates and coordinates of the // surface when drawing. I will implcitely assume this during this function. // SDL_mutexP(d_lock); PG_Rect r(1, 1, GameMap::getSize() * d_pixels, GameMap::getSize() * d_pixels); SDL_BlitSurface(d_staticMap, 0, surface, &r); // Draw all cities as 4x4 rectangles around the city location. They consist // of an outer rectangle in black and an inner one in player colors. for (Citylist::iterator it = Citylist::getInstance()->begin(); it != Citylist::getInstance()->end(); it++) { SDL_Color c = (*it).getPlayer()->getColor(); PG_Point pos = (*it).getPos(); DrawRectWH(pos.x*d_pixels, pos.y*d_pixels, 4*d_pixels, 4*d_pixels, PG_Color(0, 0, 0)); DrawRectWH((pos.x+1)*d_pixels, (pos.y+1)*d_pixels, 2*d_pixels, 2*d_pixels, PG_Color(c)); } // Draw ruins as yellow boxes for (Ruinlist::iterator it = Ruinlist::getInstance()->begin(); it != Ruinlist::getInstance()->end(); it++) { PG_Point pos = (*it).getPos(); DrawRectWH(pos.x*d_pixels, pos.y*d_pixels, 3*d_pixels, 3*d_pixels, PG_Color(255, 255, 0)); } // Draw temples as magenta pi's for (Templelist::iterator it = Templelist::getInstance()->begin(); it != Templelist::getInstance()->end(); it++) { PG_Point pos = (*it).getPos(); DrawHLine(pos.x*d_pixels, pos.y*d_pixels, 3*d_pixels, PG_Color(255, 0, 255)); DrawVLine(pos.x*d_pixels, (pos.y+1)*d_pixels, 2*d_pixels, PG_Color(255, 0, 255)); DrawVLine((pos.x+2)*d_pixels, (pos.y+1)*d_pixels, 2*d_pixels, PG_Color(255, 0, 255)); } // Draw stacks as crosses using the player color for (Playerlist::iterator pit = Playerlist::getInstance()->begin(); pit != Playerlist::getInstance()->end(); pit++) { Stacklist* mylist = (*pit)->getStacklist(); SDL_Color c = (*pit)->getColor(); for (Stacklist::iterator it= mylist->begin(); it != mylist->end(); it++) { PG_Point pos = (*it)->getPos(); //don't draw stacks in cities, they could hardly be identified Maptile* mytile = GameMap::getInstance()->getTile(pos.x, pos.y); if (mytile->getBuilding() == Maptile::CITY) continue; DrawHLine(pos.x*d_pixels, (pos.y+1)*d_pixels, 3*d_pixels, PG_Color(c)); DrawVLine((pos.x+1)*d_pixels, pos.y*d_pixels, 3*d_pixels, PG_Color(c)); } } // Draw the border last. This prevents problems when some of the drawings // before have been done over the border. drawViewrect(); // SDL_mutexV(d_lock); } // do some animation of the viewrect void SmallMap::drawViewrect() { if (d_r == 255) d_add = false; if (d_r == 160) d_add = true; if (d_add) {++d_r; ++d_g; ++d_b;} else {--d_r; --d_g; --d_b;} DrawBorder(PG_Rect(0,0,my_width,my_height), 1); // Draw the rectangle that shows the viewed part of the map DrawRectWH(d_viewrect->my_xpos*d_pixels + 1, d_viewrect->my_ypos*d_pixels +1, d_viewrect->my_width*d_pixels, d_viewrect->my_height*d_pixels, PG_Color(d_r, d_g, d_b)); SDL_UpdateRect(GetWidgetSurface(), d_viewrect->my_xpos*d_pixels +1, d_viewrect->my_ypos*d_pixels +1, d_viewrect->my_width*d_pixels, d_viewrect->my_height*d_pixels); } Uint32 SmallMap::eventTimer(ID id, Uint32 interval) { drawViewrect(); Update(); PG_TimerObject::eventTimer(id, interval); return interval; } // Pressed in the drawing area to set viewrect bool SmallMap::eventMouseButtonDown(const SDL_MouseButtonEvent* event) { keycheck = 0; if(event->button == SDL_BUTTON_LEFT) setViewrect(event->x/d_pixels, event->y/d_pixels); return true; } // This eventhandler is called when moving the mouse with pressed button in // the drawing area to move viewrect bool SmallMap::eventMouseMotion(const SDL_MouseMotionEvent* event) { if (event->state == SDL_PRESSED) setViewrect(event->x/d_pixels, event->y/d_pixels); return true; } bool SmallMap::changedViewrect(PG_Widget *widget) { #if 0 debug("changedViewrect()"); SDL_Rect* rect = (SDL_Rect*)clientdata; d_viewrect->my_xpos = rect->x; d_viewrect->my_ypos = rect->y; #endif Redraw(); return true; } void SmallMap::inputFunction(int arrowx, int arrowy) { keycheck = 1; int x = d_viewrect->my_xpos + arrowx; int y = d_viewrect->my_ypos + arrowy; setViewrect(x, y); } void SmallMap::setViewrect(int x, int y) { //the x/y coordinates are absolute to the whole programm, so subtract the //position of the widget and a bit more so the mouse isn't in the top left //corner // This "if" is neccessary ,because a eventKeyDown ( value == 1 ) can't handle the next lines. if (keycheck == 0) // eventMouseButton ( value == 0 ). { x -= 5 + my_xpos; y -= 5 + my_ypos; } if (x < 0) x = 0; if (y < 0) y = 0; if (x > (GameMap::getSize() - d_viewrect->my_width)) x = GameMap::getSize() - d_viewrect->my_width; if (y > (GameMap::getSize() - d_viewrect->my_height)) y = GameMap::getSize() - d_viewrect->my_height; d_viewrect->my_xpos = x; d_viewrect->my_ypos = y; Redraw(); schangingViewrect.emit(true); } void SmallMap::interruptTimer() { if (d_timerID != 0) RemoveTimer(d_timerID); d_timerID = 0; } void SmallMap::restartTimer() { #ifndef FL_NO_TIMERS if (d_timerID == 0) d_timerID = AddTimer(TIMER_SMALLMAP_REFRESH); #else return; #endif }