/* Copyright 2013-2015 Rohit Nirmal This file is part of Clonepoint. Clonepoint 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 3 of the License, or (at your option) any later version. Clonepoint 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 Clonepoint. If not, see . */ #include #include #include "tinyxml/tinyxml.h" #include "entity.h" #include "global.h" #include "map.h" #define LIGHTRADIUS 768 #define TILEDIM 16 Map::Map() { _mapTex = 0; } Map::~Map() { LOGF((stdout, "Running map destructor!\n")); size_t i; bool sniper_active = std::find(_entities.begin(), _entities.end(), _sniper) != _entities.end(); for (i = 0; i < _entities.size(); i++) { delete _entities[i]; } for (i = 0; i < _tutorials.size(); i++) { delete _tutorials[i]; } for (i = 0; i < _collideVols.size(); i++) { delete _collideVols[i]; } for (i = 0; i < _stairDoors.size(); i++) { delete _stairDoors[i]; } for (i = 0; i < _stairwells.size(); i++) { delete _stairwells[i]; } for (i = 0; i < _lights.size(); i++) { delete _lights[i]; } for (i = 0; i < _shafts.size(); i++) { delete _shafts[i]; } if (!sniper_active) { delete _sniper; } _collideVols.clear(); _entities.clear(); _linkableEnts.clear(); _stairDoors.clear(); _stairwells.clear(); _lights.clear(); _shafts.clear(); _enemyIndices.clear(); _tutorials.clear(); glDeleteTextures(1, &_mapTex); } bool Map::loadFromFile(const char* filename, bool savegame) { int i = 0; char* encoding; TiXmlDocument doc(filename); _playerStartPos = vec2f(0, 0); _subwayPos = vec2f(0, 0); _subwayFound = false; _backgroundYOffset = 0; if (!doc.LoadFile()) { LOGF((stderr, "Failed to load map file %s.\n", filename)); return false; } TiXmlHandle hDoc(&doc); TiXmlElement *root, *lvl1, *lvl2, *lvl3; root = doc.FirstChildElement("map"); if(!root) { LOGF((stderr, "Failed to parse map file %s.\n", filename)); return false; } _tilesWide = atoi(root->Attribute("width")); _tilesHigh = atoi(root->Attribute("height")); _mapWidth = _tilesWide * TILEDIM; _mapHeight = _tilesHigh * TILEDIM; lvl1 = root->FirstChildElement("tileset"); while(lvl1) { lvl2 = lvl1->FirstChildElement("image"); while (lvl2) { LOGF((stdout, "lvl2 filename = %s\n", lvl2->Attribute("source"))); if (atoi(lvl1->Attribute("firstgid")) == 1) { std::string fullSource = std::string("data/") + std::string(lvl2->Attribute("source")); _tilesetImage = loadSurfaceFromImage(fullSource.c_str()); } lvl2 = lvl1->NextSiblingElement("image"); } lvl1 = lvl1->NextSiblingElement("tileset"); i++; } i = 0; lvl1 = root->FirstChildElement("layer"); while (lvl1) { lvl2 = lvl1->FirstChildElement("data"); if (lvl2) { encoding = (char*)lvl2->Attribute("encoding"); if (!strcmp(encoding, "csv")) { parseTileLayer((char*)lvl2->GetText()); } } else { LOGF((stderr, "Error. Layer has no data.\n")); } lvl1 = lvl1->NextSiblingElement("layer"); i++; } i = 0; lvl1 = root->FirstChildElement("objectgroup"); while (lvl1) { if (!strcmp(lvl1->Attribute("name"), "Collision")) { lvl2 = lvl1->FirstChildElement("object"); parseCollisionVolume(lvl2); } else if (!strcmp(lvl1->Attribute("name"), "RedLinkable")) { lvl2 = lvl1->FirstChildElement("object"); parseLinkableObject(lvl2, RED); } else if (!strcmp(lvl1->Attribute("name"), "GreenLinkable")) { lvl2 = lvl1->FirstChildElement("object"); parseLinkableObject(lvl2, GREEN); } else if (!strcmp(lvl1->Attribute("name"), "BlueLinkable")) { lvl2 = lvl1->FirstChildElement("object"); parseLinkableObject(lvl2, BLUE); } else if (!strcmp(lvl1->Attribute("name"), "VioletLinkable")) { lvl2 = lvl1->FirstChildElement("object"); parseLinkableObject(lvl2, VIOLET); } else if (!strcmp(lvl1->Attribute("name"), "YellowLinkable")) { lvl2 = lvl1->FirstChildElement("object"); parseLinkableObject(lvl2, YELLOW); } else if (!strcmp(lvl1->Attribute("name"), "Links") && !savegame) { lvl2 = lvl1->FirstChildElement("object"); while (lvl2) { lvl3 = lvl2->FirstChildElement("polyline"); if (lvl3) { parsePolyline(lvl3, atof(lvl2->Attribute("x")), atof(lvl2->Attribute("y")), &_lines); } lvl2 = lvl2->NextSiblingElement("object"); } } else if (!strcmp(lvl1->Attribute("name"), "LightLinks")) { lvl2 = lvl1->FirstChildElement("object"); while (lvl2) { lvl3 = lvl2->FirstChildElement("polyline"); if (lvl3) { parsePolyline(lvl3, atof(lvl2->Attribute("x")), atof(lvl2->Attribute("y")), &_lightLinks); } lvl2 = lvl2->NextSiblingElement("object"); } } else if (!strcmp(lvl1->Attribute("name"), "Entities")) { lvl2 = lvl1->FirstChildElement("object"); parseEntity(lvl2, savegame); } else if (!strcmp(lvl1->Attribute("name"), "Objectives")) { lvl2 = lvl1->FirstChildElement("object"); parseObjective(lvl2); } else if (!strcmp(lvl1->Attribute("name"), "Lights")) { lvl2 = lvl1->FirstChildElement("object"); parseLight(lvl2); } else if (!strcmp(lvl1->Attribute("name"), "Props")) { lvl2 = lvl1->FirstChildElement("object"); parseProp(lvl2); } else if (!strcmp(lvl1->Attribute("name"), "Player")) { lvl2 = lvl1->FirstChildElement("object"); if (!strcmp(lvl2->Attribute("type"), "Player")) { _playerStartPos.x = atoi(lvl2->Attribute("x")); _playerStartPos.y = atoi(lvl2->Attribute("y")); } } lvl1 = lvl1->NextSiblingElement("objectgroup"); i++; } makeElevatorShafts(); setShaftOpenings(); makeStairwells(); calculateStairDirections(); calculateElevatorOrder(); size_t linkableCount = 0; for (size_t j = 0; j < _entities.size(); j++) { if (dynamic_cast(_entities[j])) { linkableCount++; } } Assert((_linkableEnts.size() == linkableCount)); _sniper = new Enemy(0, 0, Left, false, Enemy_Sniper); EnemyGun* eg = new EnemyGun(0, 0, RED); eg->_enemy = _sniper; _sniper->_gun = eg; _entities.push_back(eg); findBackGroundYOffset(filename); return true; } size_t Map::getNumberOfCollideVols() { return _collideVols.size(); } size_t Map::getNumberOfEnts() { return _entities.size(); } size_t Map::getNumberOfStairs() { return _stairDoors.size(); } size_t Map::getNumberOfStairwells() { return _stairwells.size(); } size_t Map::getNumberOfLights() { return _lights.size(); } size_t Map::getNumberOfLines() { return _lines.size(); } size_t Map::getNumberOfLightLinks() { return _lightLinks.size(); } size_t Map::getNumberOfShafts() { return _shafts.size(); } size_t Map::getNumberOfEnemies() { return _enemyIndices.size(); } CollisionVolume Map::getCollideVolAt(int i) { return *_collideVols[i]; } CollisionVolume* Map::getCollideVolPointerAt(int i) { return _collideVols[i]; } Entity* Map::getEntAt(size_t i) { return _entities[i]; } Enemy* Map::getEnemyAt(size_t i) { Entity* ent = _entities[_enemyIndices[i]]; Assert(dynamic_cast(ent)); return static_cast(ent); } Stairs* Map::getStairsAt(size_t i) { return _stairDoors[i]; } Stairwell* Map::getStairwellAt(size_t i) { return _stairwells[i]; } FieldOfView* Map::getLightAt(size_t i) { return _lights[i]; } Line Map::getLineAt(size_t i) { return _lines[i]; } Line Map::getLightLinkAt(size_t i) { return _lightLinks[i]; } ElevatorShaft* Map::getShaftAt(size_t i) { return _shafts[i]; } unsigned int Map::getMapWidth() { return _mapWidth; } unsigned int Map::getMapHeight() { return _mapHeight; } int Map::indexOfCollideVol(CollisionVolume* vol) { unsigned int i; for (i = 0; i < _collideVols.size(); i++) { if (_collideVols[i] == vol) { return (int)i; } } return -1; } int Map::indexOfEntity(Entity* ent) { unsigned int i; for (i = 0; i < _entities.size(); i++) { if (_entities[i] == ent) { return (int)i; } } return -1; } int Map::indexOfFOV(FieldOfView* fov) { unsigned int i; for (i = 0; i < _lights.size(); i++) { if (_lights[i] == fov) { return (int)i; } } return -1; } void Map::parseLinkableObject(TiXmlElement* element, Circuit c) { bool open; bool handscanner; bool facingRight; float r, g, b; TiXmlElement* lvl1, *lvl2; while (element) { if (!element->Attribute("x") || !element->Attribute("y") || !element->Attribute("type")) { LOGF((stderr, "LinkableEntity has null value - ignoring.\n")); } else { int x = atoi(element->Attribute("x")); int y = atoi(element->Attribute("y")); if (!strcmp(element->Attribute("type"), "Switch")) { handscanner = false; lvl1 = element->FirstChildElement("properties"); if (lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "handscanner") && lvl2->Attribute("value") && !strcmp(lvl2->Attribute("value"), "yes")) { handscanner = true; } lvl2 = lvl2->NextSiblingElement("property"); } } LightSwitch* sw = new LightSwitch(x, y - ENTDIM, c, handscanner); _entities.push_back(sw); _linkableEnts.push_back(sw); } else if (!strcmp(element->Attribute("type"), "Door")) { open = false; lvl1 = element->FirstChildElement("properties"); if (lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "open") && lvl2->Attribute("value") && !strcmp(lvl2->Attribute("value"), "yes")) { open = true; } lvl2 = lvl2->NextSiblingElement("property"); } } Door* door = new Door(x, y - ENTDIM, c, open ? true : false, Door_Normal); _collideVols.push_back(door->getCollisionVolume()); _entities.push_back(door); _linkableEnts.push_back(door); } else if (!strcmp(element->Attribute("type"), "TrapDoor")) { Door* td = new Door(x, y - ENTDIM, c, false, Door_Trap); _collideVols.push_back(td->getCollisionVolume()); _entities.push_back(td); _linkableEnts.push_back(td); } else if (!strcmp(element->Attribute("type"), "VaultDoor")) { Door* vd = new Door(x, y - ENTDIM, c, false, Door_Vault); _collideVols.push_back(vd->getCollisionVolume()); _collideVols.push_back(vd->getCollisionVolume2()); _entities.push_back(vd); _linkableEnts.push_back(vd); } else if (!strcmp(element->Attribute("type"), "LightFixture")) { r = g = b = 1.0f; lvl1 = element->FirstChildElement("properties"); if (lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "red") && lvl2->Attribute("value")) { r = atof(lvl2->Attribute("value")); } if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "green") && lvl2->Attribute("value")) { g = atof(lvl2->Attribute("value")); } if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "blue") && lvl2->Attribute("value")) { b = atof(lvl2->Attribute("value")); } lvl2 = lvl2->NextSiblingElement("property"); } } LightFixture* fixture = new LightFixture(x, y - ENTDIM, c, true); FieldOfView* fov = new FieldOfView(x + (ENTDIM / 2) - 8, y - (ENTDIM / 2) + 4, LIGHTRADIUS, 0, 180, true, FOV_LIGHT); fov->_red = r; fov->_green = g; fov->_blue = b; fixture->addFOV(fov); _entities.push_back(fixture); _linkableEnts.push_back(fixture); _lights.push_back(fov); } else if (!strcmp(element->Attribute("type"), "Socket")) { PowerSocket* socket = new PowerSocket(x, y - ENTDIM, c); _entities.push_back(socket); _linkableEnts.push_back(socket); } else if (!strcmp(element->Attribute("type"), "Scanner")) { MotionScanner* scanner = new MotionScanner(x, y - ENTDIM, c); _entities.push_back(scanner); _linkableEnts.push_back(scanner); } else if (!strcmp(element->Attribute("type"), "Elevator")) { ElevatorDoor* ed = new ElevatorDoor(x, y - ENTDIM); ElevatorSwitch* sw = new ElevatorSwitch(x + 32, y - ENTDIM, c); sw->_door = ed; ed->_switch = sw; _entities.push_back(ed); _entities.push_back(sw); _linkableEnts.push_back(sw); } else if (!strcmp(element->Attribute("type"), "SoundDetector")) { SoundDetector* sd = new SoundDetector(x, y - ENTDIM, c); _entities.push_back(sd); _linkableEnts.push_back(sd); } else if (!strcmp(element->Attribute("type"), "SecurityCamera")) { facingRight = false; lvl1 = element->FirstChildElement("properties"); if (lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "direction") && lvl2->Attribute("value") && !strcmp(lvl2->Attribute("value"), "right")) { facingRight = true; } lvl2 = lvl2->NextSiblingElement("property"); } } FieldOfView* fov = new FieldOfView(facingRight ? x + ENTDIM/2 + 8 : x + ENTDIM/2 - 8, y - ENTDIM/2 + 8, LIGHTRADIUS, facingRight ? 27 : -27, 27, true, FOV_CAMERA); fov->_red = 0.5f; fov->_green = 0.5f; fov->_blue = 0.0f; SecurityCamera* cam = new SecurityCamera(x , y - ENTDIM, c, facingRight ? Right : Left, fov); _entities.push_back(cam); _linkableEnts.push_back(cam); _lights.push_back(fov); } else if (!strcmp(element->Attribute("type"), "Alarm")) { Alarm* alarm = new Alarm(x, y - ENTDIM, c); _entities.push_back(alarm); _linkableEnts.push_back(alarm); } } element = element->NextSiblingElement("object"); } } void Map::parseCollisionVolume(TiXmlElement* element) { while (element) { if (!element->Attribute("x") || !element->Attribute("y") || !element->Attribute("width") || !element->Attribute("height")) { LOGF((stderr, "Collision volume has null value - ignoring.\n")); } else { CollisionVolume* vol = new CollisionVolume(); vol->flags = 0; vol->rect.x = atoi(element->Attribute("x")); vol->rect.y = atoi(element->Attribute("y")); vol->rect.w = atoi(element->Attribute("width")); vol->rect.h = atoi(element->Attribute("height")); if (element->Attribute("type") && !strcmp(element->Attribute("type"), "Glass")) { vol->flags |= COLLISION_GLASS; } if (element->Attribute("type") && !strcmp(element->Attribute("type"), "GuardBlock")) { vol->flags |= COLLISION_GUARDBLOCK; } if (!vol->guardblock()) { vol->flags |= COLLISION_ACTIVE; } _collideVols.push_back(vol); } element = element->NextSiblingElement("object"); } } void Map::parseEntity(TiXmlElement* element, bool savegame) { bool facingRight; bool startPatrolling; TiXmlElement* lvl1, *lvl2; while (element) { facingRight = false; startPatrolling = false; if (!element->Attribute("x") || !element->Attribute("y") || !element->Attribute("type")) { LOGF((stderr, "Entity has null value - ignoring.\n")); } else { int x = atoi(element->Attribute("x")); int y = atoi(element->Attribute("y")); lvl1 = element->FirstChildElement("properties"); if (lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "direction") && lvl2->Attribute("value") && !strcmp(lvl2->Attribute("value"), "right")) { facingRight = true; } if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "patrolling") && lvl2->Attribute("value") && !strcmp(lvl2->Attribute("value"), "yes")) { startPatrolling = true; } lvl2 = lvl2->NextSiblingElement("property"); } } if (!strcmp(element->Attribute("type"), "Guard")) { Enemy* guard = new Enemy(x, y - ENTDIM, facingRight ? Right : Left, startPatrolling, Enemy_Guard); _entities.push_back(guard); _enemyIndices.push_back(_entities.size() - 1); EnemyGun* eg = new EnemyGun(x, y, RED); eg->_enemy = guard; guard->_gun = eg; _entities.push_back(eg); _linkableEnts.push_back(eg); } if (!strcmp(element->Attribute("type"), "Enforcer")) { Enemy* enforcer = new Enemy(x, y - ENTDIM, facingRight ? Right : Left, startPatrolling, Enemy_Enforcer); _entities.push_back(enforcer); _enemyIndices.push_back(_entities.size() - 1); EnemyGun* eg = new EnemyGun(x, y, RED); eg->_enemy = enforcer; enforcer->_gun = eg; _entities.push_back(eg); _linkableEnts.push_back(eg); } if (!strcmp(element->Attribute("type"), "Professional")) { Enemy* professional = new Enemy(x, y - ENTDIM, facingRight ? Right : Left, startPatrolling, Enemy_Professional); _entities.push_back(professional); _enemyIndices.push_back(_entities.size() - 1); EnemyGun* eg = new EnemyGun(x, y, RED); eg->_enemy = professional; professional->_gun = eg; _entities.push_back(eg); _linkableEnts.push_back(eg); } if (!strcmp(element->Attribute("type"), "Stairs")) { _stairDoors.push_back(new Stairs(x, y - ENTDIM)); } if (!strcmp(element->Attribute("type"), "CircuitBoxG")) { _entities.push_back(new CircuitBox(x, y - ENTDIM, GREEN)); } if (!strcmp(element->Attribute("type"), "CircuitBoxB")) { _entities.push_back(new CircuitBox(x, y - ENTDIM, BLUE)); } if (!strcmp(element->Attribute("type"), "CircuitBoxY")) { _entities.push_back(new CircuitBox(x, y - ENTDIM, YELLOW)); } if (!strcmp(element->Attribute("type"), "CircuitBoxV")) { _entities.push_back(new CircuitBox(x, y - ENTDIM, VIOLET)); } if (!strncmp(element->Attribute("type"), "tut_", 4)) { StringMessage sm = NUMBER_OF_STRING_MESSAGES; if (!strcmp(element->Attribute("type"), "tut_01")) { sm = SM_Start; } if (!strcmp(element->Attribute("type"), "tut_02")) { sm = SM_Jumping; } if (!strcmp(element->Attribute("type"), "tut_03")) { sm = SM_Falling; } if (!strcmp(element->Attribute("type"), "tut_04")) { sm = SM_Guards1; } if (!strcmp(element->Attribute("type"), "tut_05")) { sm = SM_Guards2; } if (!strcmp(element->Attribute("type"), "tut_06")) { sm = SM_Crosslink1; } if (!strcmp(element->Attribute("type"), "tut_07")) { sm = SM_Crosslink2; } if (!strcmp(element->Attribute("type"), "tut_08")) { sm = SM_Objectives; } if (!strcmp(element->Attribute("type"), "tut_09")) { sm = SM_Elevators; } if (!strcmp(element->Attribute("type"), "tut_10")) { sm = SM_Optional; } if (!strcmp(element->Attribute("type"), "tut_11")) { sm = SM_Circuits; } if (sm < NUMBER_OF_STRING_MESSAGES) { _tutorials.push_back(new TutorialMark(x, y - ENTDIM, sm)); } } } element = element->NextSiblingElement("object"); } } void Map::parseLight(TiXmlElement* element) { int direction, numangles; TiXmlElement* lvl1, *lvl2; while (element) { if (!element->Attribute("x") || !element->Attribute("y")) { LOGF((stderr, "Light has null value - ignoring.\n")); } else { direction = 0; numangles = 180; int x = atoi(element->Attribute("x")); int y = atoi(element->Attribute("y")); lvl1 = element->FirstChildElement("properties"); if (lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "numangles") && lvl2->Attribute("value")) { numangles = atoi(lvl2->Attribute("value")); } if (lvl2->Attribute("name") && !strcmp(lvl2->Attribute("name"), "direction") && lvl2->Attribute("value")) { direction = atoi(lvl2->Attribute("value")); } lvl2 = lvl2->NextSiblingElement("property"); } } FieldOfView* fov = new FieldOfView(x, y + 4, LIGHTRADIUS, direction, numangles, true, FOV_LIGHT); _lights.push_back(fov); } element = element->NextSiblingElement("object"); } } void Map::parseProp(TiXmlElement* element) { std::string prop = ""; while (element) { if (!element->Attribute("x") || !element->Attribute("y")) { LOGF((stderr, "Prop has null value - ignoring.\n")); } else { int x = atoi(element->Attribute("x")); int y = atoi(element->Attribute("y")); if (!strcmp(element->Attribute("type"), "Watercooler")) { prop = "watercooler"; } if (!strcmp(element->Attribute("type"), "Shelf")) { prop = "shelf"; } if (!strcmp(element->Attribute("type"), "Trashcan")) { prop = "trashcan"; } if (!strcmp(element->Attribute("type"), "Couch")) { prop = "couch"; } if (!strcmp(element->Attribute("type"), "Plant1")) { prop = "plant1"; } if (!strcmp(element->Attribute("type"), "Plant2")) { prop = "plant2"; } if (!strcmp(element->Attribute("type"), "SubwaySign")) { prop = "subwaysign"; } if (!strcmp(element->Attribute("type"), "LightPanel")) { prop = "lightpanel"; } if (prop != "") { _entities.push_back(new Entity(x, y, Locator::getSpriteManager()->getIndex("./data/sprites/objects.sprites", prop))); _entities[_entities.size() - 1]->setCollisionRectDimsAndPosition(x, y - ENTDIM, ENTDIM, ENTDIM, ENTDIM); } } element = element->NextSiblingElement("object"); prop = ""; } } void Map::parsePolyline(TiXmlElement* element, float ox, float oy, std::vector* container) { std::string points = std::string(element->Attribute("points")); std::string p1 = points.substr(0, points.find(" ")); std::string p2 = points.substr(points.find(" ") + 1); float x, y; Line line; getPolylineComponent(p1, &x, &y); line.p1 = vec2f(x + ox, y + oy); getPolylineComponent(p2, &x, &y); line.p2 = vec2f(x + ox, y + oy); container->push_back(line); } void Map::getPolylineComponent(std::string point, float* x, float* y) { std::string p1 = point.substr(0, point.find(",")); std::string p2 = point.substr(point.find(",") + 1); *x = atof(p1.c_str()); *y = atof(p2.c_str()); } void Map::parseObjective(TiXmlElement* element) { while (element) { if (!element->Attribute("x") || !element->Attribute("y") || !element->Attribute("type")) { LOGF((stderr, "Objective has null value - ignoring.\n")); } else { int x = atoi(element->Attribute("x")); int y = atoi(element->Attribute("y")); if (!strcmp(element->Attribute("type"), "Terminal")) { _entities.push_back(new MainComputer(x, y - ENTDIM, true)); } else if (!strcmp(element->Attribute("type"), "Subway")) { _subwayPos.x = x; _subwayPos.y = y; _subwayFound = true; } } element = element->NextSiblingElement("object"); } } void Map::makeElevatorShafts() { size_t i; ElevatorDoor* ed; int iShaft; for (i = 0; i < _entities.size(); i++) { if (dynamic_cast(_entities[i])) { ed = (ElevatorDoor*)_entities[i]; iShaft = doesElevatorShaftExist((int)ed->getPosition().x); if (iShaft >= 0) //shaft already exists, just add to that. { _shafts[iShaft]->addDoor(ed); ed->_shaft = _shafts[iShaft]; } else { ElevatorShaft* shaft = new ElevatorShaft((int)ed->getPosition().x); shaft->addDoor(ed); ed->_shaft = shaft; _shafts.push_back(shaft); } } } #if _WIN32 LOGF((stdout, "Created %i elevator shaft(s).\n", _shafts.size())); #else LOGF((stdout, "Created %lu elevator shaft(s).\n", _shafts.size())); #endif } int Map::doesElevatorShaftExist(int x) { size_t i; for (i = 0; i < _shafts.size(); i++) { if (_shafts[i]->_x == x) { return (int)i; } } return -1; } void Map::makeStairwells() { size_t i; Stairs* stairs; int iStairWell; for (i = 0; i < _stairDoors.size(); i++) { stairs = _stairDoors[i]; iStairWell = doesStairwellExist((int)stairs->getPosition().x); if (iStairWell >= 0) //stairwell already exists, just add to that. { _stairwells[iStairWell]->addStairs(stairs); stairs->registerStairwell(_stairwells[iStairWell]); } else { Stairwell* well = new Stairwell((int)stairs->getPosition().x); well->addStairs(stairs); stairs->registerStairwell(well); _stairwells.push_back(well); } } #if _WIN32 LOGF((stdout, "Created %i stairwell(s).\n", _shafts.size())); #else LOGF((stdout, "Created %lu stairwell(s).\n", _shafts.size())); #endif } int Map::doesStairwellExist(int x) { size_t i; for (i = 0; i < _stairwells.size(); i++) { if (_stairwells[i]->getX() == x) { return (int)i; } } return -1; } void Map::calculateStairDirections() { size_t i; for (i = 0; i < _stairwells.size(); i++) { _stairwells[i]->setDirections(_mapHeight); } } void Map::calculateElevatorOrder() { size_t i; for (i = 0; i < _shafts.size(); i++) { _shafts[i]->calculateDoorOrders(_mapHeight); } } void Map::setShaftOpenings() { size_t i; for (i = 0; i < _shafts.size(); i++) { _shafts[i]->setOpenDoorFirst(); } } vec2f Map::getPlayerStartPos() { return _playerStartPos; } void Map::addSavedLink(vec2f start, vec2f end) { Line line = {start, end}; _lines.push_back(line); } void Map::parseTileLayer(char* data) { if (!_tilesetImage) { _mapTex = 0; return; } SDL_Surface* mapImage; SDL_Surface* mapImageCrosslink; #if SDL_BYTEORDER == SDL_BIG_ENDIAN mapImage = SDL_CreateRGBSurface(SDL_SWSURFACE, _mapWidth, _mapHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); mapImageCrosslink = SDL_CreateRGBSurface(SDL_SWSURFACE, _mapWidth, _mapHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); #else mapImage = SDL_CreateRGBSurface(SDL_SWSURFACE, _mapWidth, _mapHeight, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); mapImageCrosslink = SDL_CreateRGBSurface(SDL_SWSURFACE, _mapWidth, _mapHeight, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); #endif SDL_FillRect(mapImage, NULL, 0xFF00FF); SDL_FillRect(mapImageCrosslink, NULL, 0xFF00FF); char* delim = (char*)","; char* token = strtok(data, delim); unsigned int i = 0; int gid; int tileset_col; int tileset_row; SDL_Rect srcrect; SDL_Rect dstrect; unsigned int row; unsigned int col; int endcol; unsigned int tilesetWidthInTiles = _tilesetImage->w / TILEDIM; while (token) { i++; gid = atoi(token); if (gid > 0) { gid--; row = i / _tilesWide; endcol = i - (row * _tilesWide) - 1; if (endcol < 0) { row--; } col = i - (row * _tilesWide) - 1; tileset_col = gid % tilesetWidthInTiles; tileset_row = gid / tilesetWidthInTiles; srcrect.x = TILEDIM * tileset_col; srcrect.y = TILEDIM * tileset_row; srcrect.w = TILEDIM; srcrect.h = TILEDIM; dstrect.x = col * TILEDIM; dstrect.y = row * TILEDIM; dstrect.w = TILEDIM; dstrect.h = TILEDIM; SDL_BlitSurface(_tilesetImage, &srcrect, mapImage, &dstrect); SDL_FillRect(mapImageCrosslink, &dstrect, 0x500000); } if (token) token = strtok(NULL, delim); } _mapTex = createTextureFromSurface(mapImage); _crosslinkTex = createTextureFromSurface(mapImageCrosslink); SDL_FreeSurface(mapImage); SDL_FreeSurface(mapImageCrosslink); SDL_FreeSurface(_tilesetImage); delete [] token; } void Map::findBackGroundYOffset(std::string filename) { TiXmlDocument doc(filename.c_str()); if (!doc.LoadFile()) { LOGF((stderr, "Failed to load map file %s.\n", filename.c_str())); return; } TiXmlHandle hDoc(&doc); TiXmlElement *root, *lvl1, *lvl2; root = doc.FirstChildElement("map"); if(!root) { LOGF((stderr, "Failed to parse map file %s.\n", filename.c_str())); return; } lvl1 = root->FirstChildElement("properties"); while(lvl1) { lvl2 = lvl1->FirstChildElement("property"); while (lvl2) { if (!strcmp(lvl2->Attribute("name"), "backgroundyoff")) { _backgroundYOffset = atof(lvl2->Attribute("value")) * TILEDIM; } lvl2 = lvl2->NextSiblingElement("property"); } lvl1 = lvl1->NextSiblingElement("properties"); } } GLuint Map::getMapTexture() { return _mapTex; } GLuint Map::getCrosslinkTexture() { return _crosslinkTex; } void Map::clearLinks() { _lines.clear(); size_t i; for (i = 0; i < _linkableEnts.size(); i++) { _linkableEnts[i]->unlink(); } } bool Map::subwayFound() { return _subwayFound; } vec2f Map::getSubwayPosition() { return _subwayPos; } void Map::getLinkableIters(std::vector::iterator* begin, std::vector::iterator* end) { *begin = _linkableEnts.begin(); *end = _linkableEnts.end(); } void Map::getTutorialIters(std::vector::iterator* begin, std::vector::iterator* end) { *begin = _tutorials.begin(); *end = _tutorials.end(); } void Map::removeEnemyGun(EnemyGun* gun) { size_t i; int gunIndex = -1; for (i = 0; i < _linkableEnts.size(); i++) { if (_linkableEnts[i] == gun) { gunIndex = i; break; } } if (gunIndex < 0) { return; } _linkableEnts.erase(_linkableEnts.begin() + gunIndex); } void Map::addMissingGuns() { size_t i; EnemyGun* eg; for (i = 0; i < _entities.size(); i++) { if (dynamic_cast(_entities[i])) { eg = static_cast(_entities[i]); if (eg->_enemy->getType() == Enemy_Sniper) { continue; } if (std::find(_linkableEnts.begin(), _linkableEnts.end(), eg) == _linkableEnts.end()) { _linkableEnts.push_back(eg); } } } } void Map::addSniper() { if (_subwayFound && std::find(_entities.begin(), _entities.end(), _sniper) == _entities.end()) { _sniper->setAlive(true); _sniper->loseSightOfPlayer(false, vec2f(0, 0)); _entities.push_back(_sniper); _enemyIndices.push_back(_entities.size() - 1); _sniper->setCollisionRectPosition(_subwayPos.x + ENTDIM - _sniper->getCollisionRect().w, _subwayPos.y - _sniper->getCollisionRect().h); _sniper->alertToPosition(_subwayPos.x - 40, _subwayPos.y, ALERT_RUN, TARGET_PLAYER); } } void Map::removeSniper() { size_t i; int sniperIndex = -1; int indexInIndices = -1; //index in enemyIndices for (i = 0; i < _entities.size(); i++) { if (_entities[i] == _sniper) { sniperIndex = i; break; } } if (sniperIndex == -1) { return; } for (i = 0; i < _enemyIndices.size(); i++) { if (_enemyIndices[i] == (size_t)sniperIndex) { indexInIndices = i; break; } } Assert((indexInIndices >= 0)); _entities.erase(_entities.begin() + sniperIndex); _enemyIndices.erase(_enemyIndices.begin() + indexInIndices); _sniper->changeState(IDLE); } Enemy* Map::getSniper() { return _sniper; } float Map::getBackGroundYOffset() { return _backgroundYOffset; }