/* Mars, Land of No Mercy 0.2.0 - http://www.marsnomercy.org */ #include #include #include #include "graphic/Blitter.h" #include "graphic/GraphicTracker.h" #include "graphic/Image.h" #include "graphic/MovableImage.h" #include "graphic/Screen.h" #include "graphic/Surface.h" #include "graphic/Text.h" #include "xml/XmlLoader.h" #include "Building.h" #include "DataTypes.h" #include "Functions.h" #include "IsoFow.h" #include "IsoGrid.h" #include "IsoMiniMap.h" #include "IsoMouse.h" #include "IsoObjectsMap.h" #include "IsoTilesMap.h" #include "MiniMapPanel.h" #include "Path.h" #include "Pathfind.h" #include "PathHighlighter.h" #include "PathNode.h" #include "SceneRenderer.h" #include "SelectionHighlighter.h" #include "SelectionData.h" #include "StatisticalValue.h" #include "SceneElement.h" #include "TerrainElement.h" #include "TileSet.h" #include "Timer.h" #include "Unit.h" #include "PlayerContainer.h" #include "Exception.h" #include #include // default data directory #ifndef DATA_DIR #define DATA_DIR "data/" #endif // minimum offset betwenn screen and widgets #define SW_OFFSET 5 // map dimensions #define ROWS 50 #define COLS 50 // transparency value of the mmap #define MM_TRANS 100 using namespace std; using namespace graphic; using namespace xml; Screen * graphic::screen; GraphicTracker * graphic::gtracker; Blitter * graphic::blitter; XmlLoader * xml::XmlHandler; // global directory strings string data_dir; string home_dir; string screens_dir; int main(int argc, char **argv) { // init SDL SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); // init SDL_ttf TTF_Init(); // when exit, execute SDL_Quit and TTF_Quit to restore everything atexit(TTF_Quit); atexit(SDL_Quit); // initializing a data directory string data_dir = DATA_DIR; cout << "data directory is: " << data_dir << endl; // creating a home directory if it does not exist already #ifndef WIN32 home_dir = getenv("HOME") + string("/.mars-lonm"); #else home_dir = DATA_DIR; #endif cout << "home directory is: " << home_dir << endl; #ifndef WIN32 if(!mkdir(home_dir.c_str(), 00755)) cout << "Created " << home_dir << endl; else perror(string("mkdir " + home_dir).c_str()); #endif // creating the home directory tree screens_dir = home_dir + "/screens"; #ifndef WIN32 if (!mkdir(screens_dir.c_str(), 00755)) cout << "Created " << screens_dir << endl; else perror(string("mkdir " + screens_dir).c_str()); #endif // init/load data ==> possible exceptions try { // init screen //screen = new Screen(RIS1_W, RIS1_H, SDL_SWSURFACE| SDL_OPENGL); screen = new Screen(RIS1_W, RIS1_H, SDL_SWSURFACE); } catch(Exception e) { e.PrintError(); exit(-1); } // a new blitter blitter = new Blitter(); // a new grahic tracker gtracker = new GraphicTracker(); // options (resolution & tileset) Options opt; // default res is 800x600 opt.ris.w = RIS1_W; opt.ris.h = RIS1_H; // Init Xml handler XmlHandler = new XmlLoader((data_dir + "xml/xmlconfig.xml").c_str()); // start menu menu(opt); // exit if(!(opt.choice)) { delete screen; delete blitter; return 0; } // change resolution if(opt.ris.w != screen->GetW()) screen->SetResolution(opt.ris.w, opt.ris.h); SDL_Color magenta = {0xFF, 0, 0xFF, 0}; SDL_Color yellow = {0xFF, 0xFF, 0, 0}; SDL_Color orange = {0xFF, 0xCC, 0, 0}; // select tileset to load string dir; if(opt.choice == 1) dir = data_dir + "img/tiles/128x64/terrain_01/"; else if(opt.choice == 2) dir = data_dir + "img/tiles/128x64/terrain_02/"; else if(opt.choice == 3) dir = data_dir + "img/tiles/128x64/terrain_03/"; else if(opt.choice == 4) dir = data_dir + "img/tiles/128x64/terrain_xmas/"; // minimap tiles string dir_mm = data_dir + "img/tiles/minimap/"; // --- ELEMENTS --- // scrolling directions std::bitset<4> arrows; Image * img ,* img2, * img3; Text * txt, * txt2; // pointers used by selection Element * temp_elem = NULL; FactionElement * sel_elem = NULL; Unit * sel_unit = NULL; Building * sel_build = NULL; bool elem_selected = false; // --- END ELEMENTS --- // load the tileset of the map TileSet ts(dir, &magenta, screen->GetGraphicMode()); // load the tileset of the minimap TileSet ts_mm(dir_mm, &magenta, screen->GetGraphicMode()); // random generated tiles map IsoTilesMap tm(ROWS, COLS, &ts); // temporary objects map IsoObjectsMap om(&tm); // --- Begin PlayerContainers --- // playerconatiners load/add/delete elements, also keeps track of this players elements PlayerContainer player1(&om, 1000); PlayerContainer ai1(&om, 2000); PlayerContainer scene(&om, 3000); // Elements loaded from base xml format player1.CreateElements((data_dir + "xml/player.xml").c_str()); player1.ComputeVisibility(); // Load elements in save game / scenario and scene format ai1.CreateElements((data_dir + "xml/enemy.xml").c_str()); scene.CreateElements((data_dir + "xml/elements.xml").c_str()); // --- End PlayerContainers --- // iso Fow try { img = gtracker->GetImage((data_dir + "img/tiles/128x64/black.png").c_str(), magenta, screen->GetGraphicMode()); } catch(Exception e) { e.PrintError(); exit(-1); } IsoFow fow(&tm, img); // iso Grid try { img = gtracker->GetImage((data_dir + "img/grids/128x64/black_grid.png").c_str(), magenta, screen->GetGraphicMode()); img2 = gtracker->GetImage((data_dir + "img/grids/128x64/white_grid.png").c_str(), magenta, screen->GetGraphicMode()); img3 = gtracker->GetImage((data_dir + "img/grids/128x64/white_grid.png").c_str(), magenta, screen->GetGraphicMode()); } catch(Exception e) { e.PrintError(); exit(-1); } IsoGrid grid(&tm, img, img2, img3); // iso Minimap IsoMiniMap mm(&tm, &om, &ts_mm); // -- SELECTION HIGHLIGHTER -- vector< Image * > high_images; try { img = gtracker->GetImage((data_dir + "img/highlighter/01.png").c_str(), magenta, screen->GetGraphicMode()); high_images.push_back(img); img = gtracker->GetImage((data_dir + "img/highlighter/02.png").c_str(), magenta, screen->GetGraphicMode()); high_images.push_back(img); img = gtracker->GetImage((data_dir + "img/highlighter/03.png").c_str(), magenta, screen->GetGraphicMode()); high_images.push_back(img); img = gtracker->GetImage((data_dir + "img/highlighter/04.png").c_str(), magenta, screen->GetGraphicMode()); high_images.push_back(img); } catch(Exception e) { e.PrintError(); exit(-1); } SelectionHighlighter sel(high_images); // -- SELECTION DATA -- vector< Image * > sdata_images; try { img = gtracker->GetImage((data_dir + "img/sel_data/ebar_border.png").c_str(), magenta, screen->GetGraphicMode()); sdata_images.push_back(img); img = gtracker->GetImage((data_dir + "img/sel_data/ebar_good.png").c_str(), screen->GetGraphicMode()); sdata_images.push_back(img); img = gtracker->GetImage((data_dir + "img/sel_data/ebar_bad.png").c_str(), screen->GetGraphicMode()); sdata_images.push_back(img); } catch(Exception e) { e.PrintError(); exit(-1); } SelectionData sel_data(sdata_images); // -- PATH HIGHLIGHTER try { img = gtracker->GetImage((data_dir + "img/tiles/128x64/green.png").c_str(), magenta, screen->GetGraphicMode()); img2 = gtracker->GetImage((data_dir + "img/tiles/128x64/red.png").c_str(), magenta, screen->GetGraphicMode()); img3 = gtracker->GetImage((data_dir + "img/tiles/128x64/yellow.png").c_str(), magenta, screen->GetGraphicMode()); txt = new Text((data_dir + RAP_FONT).c_str(), yellow, RAP_FONT_SIZE, screen->GetGraphicMode()); txt2 = new Text((data_dir + RAP_FONT).c_str(), orange, RAP_FONT_SIZE, screen->GetGraphicMode()); } catch(Exception e) { e.PrintError(); exit(-1); } PathHighlighter path_h(&tm, img, img2, img3, txt, txt2); Pathfind path_finder(&tm); Path * gen_path = NULL; // -- SCENE RENDERER INIT -- SceneRenderer renderer(((tm.GetW() - screen->GetW()) / 2 ), 0, screen->GetW(), screen->GetH(), screen->GetGraphicMode()); renderer.SetLimits(-(screen->GetH() / 2), tm.GetH() - (screen->GetH() / 2), -(screen->GetW() / 2), tm.GetW() - (screen->GetW() / 2)); tm.UseBuffer(); renderer.AddLayer(&tm); fow.UseBuffer(); renderer.AddLayer(&fow); grid.UseBuffer(); renderer.AddLayer(&grid); path_h.Active(false); renderer.AddLayer(&path_h); renderer.AddLayer(&om); sel.Active(false); renderer.AddLayer(&sel); sel_data.Active(false); renderer.AddLayer(&sel_data); // -- END - SCENE RENDERER INIT -- // init the buffer -> first blit renderer.RequestBufferRefresh(); vector < MovableImage * > pointers; // isometric mouse MovableImage * mimg; try { mimg = gtracker->GetMovableImage((data_dir + "img/pointer.png").c_str(), screen->GetGraphicMode()); pointers.push_back(mimg); mimg = gtracker->GetMovableImage((data_dir + "img/pointer2.png").c_str(), screen->GetGraphicMode()); pointers.push_back(mimg); } catch(Exception e) { e.PrintError(); exit(-1); } IsoMouse * mouse = new IsoMouse(pointers, &tm, screen->GetW() / 2, screen->GetH() / 2); mouse->SetView(renderer.GetViewX(), renderer.GetViewY()); // turn the system cursor off SDL_ShowCursor(0); // -- WINDOW MINIMAP -- // minimap window border MovableImage * mm_border_1024, * mm_border_800, * mm_border; // minimap view rect Image * mm_view_1024, * mm_view_800, * mm_view; SDL_Color black = { 0, 0, 0, 0}; SDL_Rect rwindow = { 1, 1, 0, 0}; try { mm_border_1024 = gtracker->GetMovableImage((data_dir + "img/mmap_border_1024.png").c_str(), screen->GetGraphicMode()); mm_border_800 = gtracker->GetMovableImage((data_dir + "img/mmap_border_800.png").c_str(), screen->GetGraphicMode()); mm_view_1024 = gtracker->GetImage((data_dir + "img/mmap_view_1024.png").c_str(), magenta, screen->GetGraphicMode()); mm_view_800 = gtracker->GetImage((data_dir + "img/mmap_view_800.png").c_str(), magenta, screen->GetGraphicMode()); } catch(Exception e) { e.PrintError(); exit(-1); } // default data are for 800x600 if(screen->GetW() == RIS1_W) { mm_border = mm_border_800; mm_view = mm_view_800; } else // resolution changed to 1024x768 { mm_border = mm_border_1024; mm_view = mm_view_1024; } rwindow.w = mm_border->GetW() - 2; rwindow.h = mm_border->GetH() - 2; // set position of the minimap border, bottom-right corner mm_border->SetInitialPosition(screen->GetW() - mm_border->GetW(), screen->GetH() - mm_border->GetH()); // visible limits of the minimap SDL_Rect mm_limit_1024 = { (mm.GetW() - (mm_border_1024->GetW() - 2)) / 2, 0, mm_border_1024->GetW() - 2, mm_border_1024->GetH() - 2 }; SDL_Rect mm_limit_800 = { (mm.GetW() - (mm_border_800->GetW() - 2)) / 2, 0, mm_border_800->GetW() - 2, mm_border_800->GetH() - 2 }; // set position of view rect into the minimap window 800x600 if(screen->GetW() == RIS1_W) mm_view->SetPosition(renderer.GetViewX() / mm.GetScale() - mm_limit_800.x, renderer.GetViewY() / mm.GetScale() - mm_limit_800.y); // set position of view rect into the minimap window 1024x768 else mm_view->SetPosition(renderer.GetViewX()/ mm.GetScale() - mm_limit_1024.x, renderer.GetViewY() / mm.GetScale() - mm_limit_1024.y); // -- END WINDOW MINIMAP -- // --MINIMAP PANEL -- MiniMapPanel * mm_panel_1024, * mm_panel_800, * mm_panel; mm_panel_1024 = new MiniMapPanel(&mm, mm_view_1024, mm_limit_1024); mm_panel_800 = new MiniMapPanel(&mm, mm_view_800, mm_limit_800); if(screen->GetW() == RIS1_W) mm_panel = mm_panel_800; else mm_panel = mm_panel_1024; mm_panel->SetRendererLimits(-(screen->GetH() / 2), tm.GetH() - (screen->GetH() / 2), -(screen->GetW() / 2), tm.GetW() - (screen->GetW() / 2)); // -- WINDOW -- mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); mm_border->SetOpacity(MM_TRANS); // ROTATION FloatPoint * f_origin; int orientation; // MOVEMENT PathNode * cur_pnode = NULL; bool checkp_reached = false; // unit movement destination Sint16 x_dest = 0; Sint16 y_dest = 0; bool done = false; bool active = true; bool unit_moving = false; int rot_cost; // drag movement of the mouse int drag_mov_x, drag_mov_y; IntPoint prev_mouse_pos = { 0, 0 }; // flag that says if mouse has been clicked bool mouse_clicked = false; // flag that says if mouse is dragging bool dragging = false; // flag that says if the minimap window is opaque/ON or transparent/OFF bool mmap_on = false; SDL_Event event; double gamma = 1.0; // timer used for frame control Timer timer(DEFAULT_FPS); timer.Start(); while(!done) { while(SDL_PollEvent(&event)) { switch(event.type) { // exit from the window case SDL_QUIT: done = true; break; case SDL_ACTIVEEVENT: if (event.active.gain == 0) active = false; else if(event.active.state == SDL_APPMOUSEFOCUS) active = true; break; // press a key case SDL_KEYDOWN : switch(event.key.keysym.sym) { case SDLK_ESCAPE: done = true; break; // Alter game Gamma values case SDLK_PLUS: gamma += 0.1; SDL_SetGamma(gamma,gamma,gamma); break; case SDLK_MINUS: gamma -= 0.1; SDL_SetGamma(gamma,gamma,gamma); break; // change mouse pointer case SDLK_1: mouse->SetPointer(0); mouse->UpdateAndBlit(); break; // change mouse pointer case SDLK_2: mouse->SetPointer(1); mouse->UpdateAndBlit(); break; // delete element case SDLK_d: player1.DeleteElement(mouse->GetRow(), mouse->GetCol()); // compute map visibility player1.ComputeVisibility(); // update the minimap mm.UpdateMap(); mm_panel->UpdateView(renderer.GetViewX(), renderer.GetViewY()); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); // delete path if(gen_path != NULL) { delete gen_path; gen_path = NULL; path_h.Active(false); } // request to blit the scene renderer.RequestBufferRefresh(); break; // go in fullscreen mode case SDLK_f: screen->GoFullScreen(); #ifdef WIN32 gtracker->UpdateAllTextures(); #endif // request to blit the scene renderer.RequestBufferRefresh(); break; // switch grid case SDLK_g: if(grid.IsActive()) grid.Active(false); else grid.Active(); // request to blit the scene renderer.RequestBufferRefresh(); break; // VFLIP case SDLK_v: renderer.UpdateViewPosition(tm.GetW() - (renderer.GetViewX() + renderer.GetViewW()), tm.GetH() - (renderer.GetViewY() + renderer.GetViewH())); tm.VFlip(); om.VFlip(); // compute map visibility player1.ComputeVisibility(); // update the minimap mm.UpdateMap(); mm_panel->UpdateView(renderer.GetViewX(), renderer.GetViewY()); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); // flip an existing path if(gen_path != NULL) gen_path->VFlip(tm.GetNumRows(), tm.GetNumCols()); // a unit is moving if(unit_moving) { x_dest = om.GetObjX(sel_unit); y_dest = om.GetObjY(sel_unit); } // flip mouse pointer mouse->VFlip(screen->GetW(), screen->GetH()); // request to blit the scene renderer.RequestBufferRefresh(); break; // go in window mode case SDLK_w: screen->GoWindowed(); #ifdef WIN32 gtracker->UpdateAllTextures(); #endif // request to blit the scene renderer.RequestBufferRefresh(); break; // 800x600 case SDLK_F1: if(screen->GetW() == RIS1_W) break; // update screen dimension screen->SetResolution(RIS1_W, RIS1_H); #ifdef WIN32 gtracker->UpdateAllTextures(); #endif renderer.SetLimits(-(screen->GetH() / 2), tm.GetH() - (screen->GetH() / 2), -(screen->GetW() / 2), tm.GetW() - (screen->GetW() / 2)); // update scene view rect renderer.UpdateViewDimensions(screen->GetW(), screen->GetH()); // MINIMAP // update dimension-related data mm_border = mm_border_800; // set position of minimap window border mm_border->SetInitialPosition(screen->GetW() - mm_border->GetW(), screen->GetH() - mm_border->GetH()); rwindow.w = mm_border->GetW() - 2; rwindow.h = mm_border->GetH() - 2; mm_panel = mm_panel_800; mm_panel->SetRendererLimits(-(screen->GetH() / 2), tm.GetH() - (screen->GetH() / 2), -(screen->GetW() / 2), tm.GetW() - (screen->GetW() / 2)); mm_panel->UpdateView(renderer.GetViewX(), renderer.GetViewY()); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); mmap_on = false; mm_border->SetOpacity(MM_TRANS); break; case SDLK_F2: if(screen->GetW() == RIS2_W) break; // update screen dimension screen->SetResolution(RIS2_W, RIS2_H); #ifdef WIN32 gtracker->UpdateAllTextures(); #endif renderer.SetLimits(-(screen->GetH() / 2), tm.GetH() - (screen->GetH() / 2), -(screen->GetW() / 2), tm.GetW() - (screen->GetW() / 2)); // update scene view rect renderer.UpdateViewDimensions(screen->GetW(), screen->GetH()); // MINIMAP // update dimension-related data mm_border = mm_border_1024; // set position of minimap window border mm_border->SetInitialPosition(screen->GetW() - mm_border->GetW(), screen->GetH() - mm_border->GetH()); rwindow.w = mm_border->GetW() - 2; rwindow.h = mm_border->GetH() - 2; mm_panel = mm_panel_1024; mm_panel->SetRendererLimits(-(screen->GetH() / 2), tm.GetH() - (screen->GetH() / 2), -(screen->GetW() / 2), tm.GetW() - (screen->GetW() / 2)); mm_panel->UpdateView(renderer.GetViewX(), renderer.GetViewY()); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); mmap_on = false; mm_border->SetOpacity(MM_TRANS); break; #ifdef WITH_OPENGL // change graphic mode case SDLK_F3: if(active == false) break; if(screen->GetGraphicMode() == SDL_GRAPHIC) { screen->ChangeGraphicMode(GL_GRAPHIC); gtracker->ChangeGraphicMode(GL_GRAPHIC);; renderer.ChangeGraphicMode(GL_GRAPHIC); } else { screen->ChangeGraphicMode(SDL_GRAPHIC); gtracker->ChangeGraphicMode(SDL_GRAPHIC); renderer.ChangeGraphicMode(SDL_GRAPHIC); } mouse->SetPosition(screen->GetW() / 2, screen->GetH() / 2); // restore the screen and blit mouse->UpdateAndBlit(); break; #endif case SDLK_F4: screen->TakeScreenshot(); break; case SDLK_DOWN: arrows.set(DOWN); break; case SDLK_UP: arrows.set(UP); break; case SDLK_LEFT: arrows.set(LEFT); break; case SDLK_RIGHT: arrows.set(RIGHT); break; // restore Unit Action Points case SDLK_SPACE: if(!unit_moving && sel_unit != NULL) { sel_unit->RestoreCurStat("actionpoints"); // recompute the path to update the remaining AP if(gen_path != NULL) { delete gen_path; gen_path = NULL; // not ask for path blit path_h.Active(false); // make a new path if it's possible if(mouse->IsInsideMap() && (tm.IsWalkable(mouse->GetRow(), mouse->GetCol()) || tm.IsVisible(mouse->GetRow(), mouse->GetCol()) != VISIBLE) ) { gen_path = path_finder.MakePath(sel_unit->GetRow(), sel_unit->GetCol(), mouse->GetRow(), mouse->GetCol(), sel_unit->GetDirection()); path_h.SetPath(gen_path); path_h.SetRemainingAP(sel_unit->GetCurStat("actionpoints") - gen_path->GetTotalCost()); path_h.Active(); } // refresh renderer.RequestBlit(BUFFERED_RENDERING); } } break; default: break; } break; // key released case SDL_KEYUP: switch(event.key.keysym.sym) { case SDLK_DOWN: arrows.set(DOWN, 0); break; case SDLK_UP: arrows.set(UP, 0); break; case SDLK_LEFT: arrows.set(LEFT, 0); break; case SDLK_RIGHT: arrows.set(RIGHT, 0); break; default: break; } break; case SDL_MOUSEMOTION: // store current mouse position mouse->SetPosition(event.button.x, event.button.y, renderer.GetViewX(), renderer.GetViewY()); // cell changed, unit selected and not moving if(mouse->IsCellChanged() && !unit_moving && sel_unit && sel_unit->GetFaction() == F_NGG) { // the mouse is inside the map and the // current cell is walkable or not visible if(mouse->IsInsideMap() && (tm.IsWalkable(mouse->GetRow(), mouse->GetCol()) || tm.IsVisible(mouse->GetRow(), mouse->GetCol()) != VISIBLE) ) { // a path has just been made if(gen_path != NULL) delete gen_path; // made a new path gen_path = path_finder.MakePath(sel_unit->GetRow(), sel_unit->GetCol(), mouse->GetRow(), mouse->GetCol(), sel_unit->GetDirection()); if(gen_path) { // set the path highlighter and ask for blit path_h.SetPath(gen_path); path_h.SetRemainingAP(sel_unit->GetCurStat("actionpoints") - gen_path->GetTotalCost()); path_h.Active(); } // buffered render renderer.RequestBlit(BUFFERED_RENDERING); } // mouse is outside the map or on a not walkable cell => delete the current path else if(gen_path != NULL) { // delete path delete gen_path; gen_path = NULL; // not ask for path blit path_h.Active(false); // buffered render renderer.RequestBlit(BUFFERED_RENDERING); } } // mouse is clicked + motion => dragging if(mouse_clicked) { dragging = true; // !--- IMPORTANT ---! // restore the screen under the mouse pointer so to remove the mouse // image before moving the window mouse->RestoreBackg(); // restore background (screen) under the window mm_border->RestoreBackground(); // compute the movement drag_mov_x = mouse->GetX() - prev_mouse_pos.x; drag_mov_y = mouse->GetY() - prev_mouse_pos.y; // check for boundary exception if((mm_border->GetX() - drag_mov_x) <= SW_OFFSET && drag_mov_x < 0) drag_mov_x = -mm_border->GetX(); if((mm_border->GetX() + mm_border->GetW() + drag_mov_x) >= (screen->GetW() - SW_OFFSET) && drag_mov_x > 0) drag_mov_x = screen->GetW() - (mm_border->GetX() + mm_border->GetW()); if((mm_border->GetY() - drag_mov_y) <= SW_OFFSET && drag_mov_y < 0) drag_mov_y = -mm_border->GetY(); if((mm_border->GetY() + mm_border->GetH() + drag_mov_y) >= (screen->GetH() - SW_OFFSET) && drag_mov_y > 0) drag_mov_y = screen->GetH() - (mm_border->GetY() + mm_border->GetH()); // move border and the window area mm_border->Move(drag_mov_x, drag_mov_y); // save new background (screen) mm_border->SaveBackground(); // blit the window border blitter->Blit(mm_border); // update altered part of screen mm_border->UpdateScreen(); // store previous mouse position prev_mouse_pos.x = mouse->GetX(); prev_mouse_pos.y = mouse->GetY(); // move the mouse and blit mouse->MoveAndBlit(); } else // restore the screen and blit mouse->UpdateAndBlit(); break; // mouse button clicked case SDL_MOUSEBUTTONDOWN: // LEFT click if(event.button.button == SDL_BUTTON_LEFT) { // maybe the first drag click prev_mouse_pos.x = mouse->GetX(); prev_mouse_pos.y = mouse->GetY(); if(mm_border->IsInside(mouse->GetX(), mouse->GetY())) mouse_clicked = true; } break; case SDL_MOUSEBUTTONUP: // LEFT click if(event.button.button == SDL_BUTTON_LEFT) { // click inside the minimap window if(mm_border->IsInside(mouse->GetX(), mouse->GetY())) { // and not dragging if(!dragging) { // minimap window is OFF if(!mmap_on) { mmap_on = true; mm_border->SetOpacity(SDL_ALPHA_OPAQUE); // update the scene renderer.RequestBlit(BUFFERED_RENDERING); } // minimap window is ON else { // manage the click on the minimap panel mm_panel->MouseClicked(mouse->GetX() - (mm_border->GetX() + rwindow.x), mouse->GetY() - (mm_border->GetY() + rwindow.y)); // update the render position according to minimap panel view renderer.UpdateViewPosition(mm_panel->GetViewX(), mm_panel->GetViewY()); // update mouse view mouse->SetView(renderer.GetViewX(), renderer.GetViewY()); renderer.RequestBufferRefresh(); // refresh minimap window mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); } } } // click outside the minimap else { // deactivate the minimap if it's ON if(mmap_on) { mmap_on = false; mm_border->SetOpacity(MM_TRANS); // update the scene renderer.RequestBlit(BUFFERED_RENDERING); } // object selected by the click temp_elem = (Element *)om.SelectObject(mouse->GetAbsX(), mouse->GetAbsY()); // select a cell outside the map or reclick on the selected elem // ==> deselect object if((!mouse->IsInsideMap() || (sel_elem == temp_elem)) && elem_selected && !unit_moving) { elem_selected = false; sel_elem->Deselect(); sel_elem = NULL; sel_unit = NULL; sel_build = NULL; // clear selection sel.ClearSelected(); // clear selection sel_data.ClearSelected(); // update scene sel.Active(false); sel_data.Active(false); renderer.RequestBlit(BUFFERED_RENDERING); if(gen_path != NULL) { delete gen_path; gen_path = NULL; path_h.Active(false); } } // select element else if(temp_elem != NULL && temp_elem->GetType().compare("sceneelement") && temp_elem->GetType().compare("terrainelement") && !unit_moving) { elem_selected = true; if(sel_elem != NULL) sel_elem->Deselect(); // store the pointer sel_elem = dynamic_cast (temp_elem); if(!sel_elem->GetType().compare("unit")) { sel_unit = dynamic_cast (temp_elem); sel_build = NULL; } else { sel_build = dynamic_cast (temp_elem); sel_unit = NULL; } // set the selected flag of the objcet sel_elem->Select(); // set the selected object in the selection layer sel.SetSelected(sel_elem); sel_data.SetSelected(sel_elem); // update scene sel.Active(); sel_data.Active(); renderer.RequestBlit(BUFFERED_RENDERING); if(gen_path != NULL) { delete gen_path; gen_path = NULL; path_h.Active(false); } } // start moving else if(gen_path!= NULL && !unit_moving && sel_unit->GetCurStat("actionpoints") >= gen_path->GetTotalCost() && sel_unit->GetFaction() == F_NGG) unit_moving = true; } // mouse released mouse_clicked = false; // no dragging dragging = false; } // RIGHT click else if(event.button.button == SDL_BUTTON_RIGHT) { // rotate unit if(sel_unit != NULL && !unit_moving && sel_unit->GetFaction() == F_NGG) { // relative origin => center of the unit image f_origin = iso2scr(sel_unit->GetX() + (sel_unit->GetImage()->GetW() / 2), sel_unit->GetY() + (sel_unit->GetImage()->GetH() / 2), tm.GetOriginX(), tm.GetOriginY()); // get orientation orientation = RelDirection((int)round(f_origin->x), (int)round(f_origin->y), (int)round(mouse->GetAbsOrthoX()), (int)round(mouse->GetAbsOrthoY())); delete f_origin; // compute rotation cost if(abs(orientation - sel_unit->GetDirection()) <= (NUM_VIEWS / 2)) rot_cost = ROTATION_COST * abs(orientation - sel_unit->GetDirection()); else rot_cost = ROTATION_COST * (NUM_VIEWS - abs(orientation - sel_unit->GetDirection())); // rotate the unit if(!sel_unit->GetType().compare("unit") && orientation != SELF && orientation != sel_unit->GetDirection() && sel_unit->GetCurStat("actionpoints") >= rot_cost) { sel_unit->SetDirection(orientation); sel_unit->SubCurStat("actionpoints", rot_cost); // compute map visibility player1.ComputeVisibility(); // update the minimap mm.UpdateMap(); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); // update the path if(mouse->IsInsideMap()) { if(tm.IsWalkable(mouse->GetRow(), mouse->GetCol()) || tm.IsVisible(mouse->GetRow(), mouse->GetCol()) != VISIBLE) { if(gen_path != NULL) delete gen_path; gen_path = path_finder.MakePath(sel_unit->GetRow(), sel_unit->GetCol(), mouse->GetRow(), mouse->GetCol(), sel_unit->GetDirection()); path_h.SetPath(gen_path); path_h.SetRemainingAP(sel_unit->GetCurStat("actionpoints") - gen_path->GetTotalCost()); } } renderer.RequestBufferRefresh(); } } } break; default: break; } } if(active) { renderer.ManageScrolling(arrows, mouse->GetX(), mouse->GetY()); // manage scrolling if(renderer.IsScrolling()) { renderer.Scrolling(timer.GetElapsedTime()); // update mouse view mouse->SetView(renderer.GetViewX(), renderer.GetViewY()); // update minimap window mm_panel->UpdateView(renderer.GetViewX(), renderer.GetViewY()); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); } // a unit is moving if(unit_moving) { // not blit selection highlighter sel.Active(false); sel_data.Active(false); // it needs to get the next path node if(cur_pnode == NULL) { cur_pnode = gen_path->PopNode(); if(sel_unit->GetDirection() != cur_pnode->GetDirection()) sel_unit->SetDirection(cur_pnode->GetDirection()); if(gen_path->GetPathLen() == 0) { gen_path = NULL; path_h.Active(false); } // first node if(cur_pnode->GetRow() == sel_unit->GetRow() && cur_pnode->GetCol() == sel_unit->GetCol()) { if(sel_unit->GetDirection() != cur_pnode->GetDirection()) sel_unit->SetDirection(cur_pnode->GetDirection()); checkp_reached = true; } // the current node is not walkable else if(!tm.IsWalkable(cur_pnode->GetRow(), cur_pnode->GetCol())) { delete cur_pnode; cur_pnode = NULL; // stop moving unit_moving = false; delete gen_path; gen_path = NULL; path_h.Active(false); checkp_reached = true; // update the minimap mm.UpdateMap(); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); } // move to the node else { sel_unit->SubCurStat("actionpoints", cur_pnode->GetCost()); checkp_reached = false; om.MoveObject(sel_unit, cur_pnode->GetRow(), cur_pnode->GetCol()); x_dest = om.GetObjX(sel_unit); y_dest = om.GetObjY(sel_unit); // update the minimap mm.UpdateMap(); mm_border->Fill(black, rwindow); mm_panel->Blit(rwindow, mm_border); } // compute map visibility player1.ComputeVisibility(); renderer.RequestBufferRefresh(); } // moving toward the next cell if(!checkp_reached) { checkp_reached = sel_unit->MoveTo(x_dest, y_dest, (int)ceil(MOVE_SPEED * timer.GetElapsedTime())); renderer.RequestBlit(BUFFERED_RENDERING); } // cell reached else { delete cur_pnode; cur_pnode = NULL; checkp_reached = false; // it was the last cell of the path if(gen_path == NULL) { unit_moving = false; path_h.Active(false); // reblit the selection highlighter sel.Active(); sel_data.Active(); renderer.RequestBlit(BUFFERED_RENDERING); } } } // blit the scene if(renderer.NeedBlit()) { renderer.BlitScene(); // -- WINDOW -- // save background (screen) of minimap window mm_border->SaveBackground(); // blit minimap window border blitter->Blit(mm_border); // mouse pointer management mouse->Blit(); screen->Update(); } } // compute elapsed time timer.GoOn(); // delay so to keep constant Frame Rate timer.Delay(); } delete mouse; delete mm_panel_1024; delete mm_panel_800; delete gtracker; delete txt; delete txt2; delete screen; delete blitter; return 0; }