📄 map.cpp
字号:
/*************************************************************************** map.cpp - description ------------------- begin : Sat May 3 2003 copyright : (C) 2003 by Gabor Torok email : cctorok@yahoo.com ***************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************/#include "map.h"//#define DEBUG_MOUSE_POS// only use 1 (disabled) or 0 (enabled)#define LIGHTMAP_ENABLED 1// set to 1 when location cache works#define USE_LOC_CACHE 0#define PI 3.14159f// this is the clockwise order of movementsint Map::dir_index[] = { Constants::MOVE_UP, Constants::MOVE_LEFT, Constants::MOVE_DOWN, Constants::MOVE_RIGHT };const float Map::shadowTransformMatrix[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0.5f, -0.5f, 0, 0, 0, 0, 0, 1 };Map::Map(Scourge *scourge){ zoom = 1.0f; zoomIn = zoomOut = false; x = y = 0; mapx = mapy = 0.0f; selectMode = false; floorOnly = false; selX = selY = selZ = MAP_WIDTH + 1; oldLocatorSelX = oldLocatorSelY = oldLocatorSelZ = selZ; useShadow = false; //alwaysCenter = true; debugX = debugY = debugZ = -1; mapChanged = true; descriptionCount = 0; descriptionsChanged = false; for(int i = 0; i < MAX_DESCRIPTION_COUNT; i++) descriptions[i] = (char*)malloc(120 * sizeof(char)); this->xrot = 0.0f; // if 0, artifacts appear this->yrot = 30.0f; this->zrot = 45.0f; this->xRotating = this->yRotating = this->zRotating = 0.0f; float adjust = (float)scourge->getSDLHandler()->getScreen()->w / 800.0f; this->xpos = (float)(scourge->getSDLHandler()->getScreen()->w) / 2.0f / adjust; this->ypos = (float)(scourge->getSDLHandler()->getScreen()->h) / 2.0f / adjust; this->zpos = 0.0f; this->scourge = scourge; this->debugGridFlag = false; this->drawGridFlag = false; targetWidth = 0.0f; targetWidthDelta = 0.05f / GLShape::DIV; lastTick = SDL_GetTicks(); // initialize shape graph of "in view shapes" for(int x = 0; x < MAP_WIDTH; x++) { for(int y = 0; y < MAP_DEPTH; y++) { floorPositions[x][y] = NULL; for(int z = 0; z < MAP_VIEW_HEIGHT; z++) { pos[x][y][z] = NULL; effect[x][y][z] = NULL; } } } // Init the pos cache for(int x = 0; x < MAX_POS_CACHE; x++) { posCache[x] = NULL; } nbPosCache = -1; // initialize the lightmap for(int x = 0; x < MAP_WIDTH / MAP_UNIT; x++) { for(int y = 0; y < MAP_DEPTH / MAP_UNIT; y++) { lightMap[x][y] = (LIGHTMAP_ENABLED ? 0 : 1); } } lightMapChanged = true; colorAlreadySet = false; selectedDropTarget = NULL; createOverlayTexture(); addDescription(Constants::getMessage(Constants::WELCOME), 1.0f, 0.5f, 1.0f); addDescription("----------------------------------", 1.0f, 0.5f, 1.0f);}Map::~Map(){ for(int xp = 0; xp < MAP_WIDTH; xp++) { for(int yp = 0; yp < MAP_DEPTH; yp++) { for(int zp = 0; zp < MAP_VIEW_HEIGHT; zp++) { if(pos[xp][yp][zp]) { delete pos[xp][yp][zp]; } } } } for(int i = 0; i < MAX_DESCRIPTION_COUNT; i++) free(descriptions[i]);}void Map::center(Sint16 x, Sint16 y, bool force) { Sint16 nx = x - MAP_VIEW_WIDTH / 2; Sint16 ny = y - MAP_VIEW_DEPTH / 2; if(scourge->getUserConfiguration()->getAlwaysCenterMap() || force) { // if(scourge->getUserConfiguration()->getAlwaysCenterMap() || // abs(this->x - nx) > X_CENTER_TOLERANCE || // abs(this->y - ny) > Y_CENTER_TOLERANCE) { // relocate this->x = nx; this->y = ny; this->mapx = nx; this->mapy = ny; }}/** Move and rotate map. Modifiers: -CTRL + arrow keys / mouse at edge of screen: rotate map -arrow keys / mouse at edge of screen: move map fast -SHIFT + arrow keys / mouse at edge of screen: slow move map -SHIFT + CTRL + arrow keys / mouse at edge of screen: slow rotate map */void Map::move(int dir) { if(SDL_GetModState() & KMOD_CTRL) { float rot; if(SDL_GetModState() & KMOD_SHIFT){ rot = 1.5f; } else{ rot = 5.0f; } if(dir & Constants::MOVE_DOWN) setYRot(-1.0f * rot); if(dir & Constants::MOVE_UP) setYRot(rot); if(dir & Constants::MOVE_RIGHT) setZRot(-1.0f * rot); if(dir & Constants::MOVE_LEFT) setZRot(rot); } else if(!scourge->getUserConfiguration()->getAlwaysCenterMap()) { // stop rotating (angle of rotation is kept) setYRot(0); setZRot(0); // normalize z rot to 0-359 float z = getZRot(); if(z < 0) z += 360; if(z >= 360) z -= 360; float zrad = Constants::toRadians(z); // cerr << "-------------------" << endl; // cerr << "x=" << x << " y=" << y << " zrot=" << z << endl; mapChanged = true; float delta = (SDL_GetModState() & KMOD_SHIFT ? 0.5f : 1.0f); if(dir & Constants::MOVE_DOWN) { mapx += delta * sin(zrad); mapy += delta * cos(zrad); } if(dir & Constants::MOVE_UP) { mapx += delta * -sin(zrad); mapy += delta * -cos(zrad); } if(dir & Constants::MOVE_LEFT) { mapx += delta * -cos(zrad); mapy += delta * sin(zrad); } if(dir & Constants::MOVE_RIGHT) { mapx += delta * cos(zrad); mapy += delta * -sin(zrad); } // cerr << "xdelta=" << xdelta << " ydelta=" << ydelta << endl; if(mapy > MAP_DEPTH - MAP_VIEW_DEPTH) mapy = MAP_DEPTH - MAP_VIEW_DEPTH; if(mapy < 0) mapy = 0; if(mapx > MAP_WIDTH - MAP_VIEW_WIDTH) mapx = MAP_WIDTH - MAP_VIEW_WIDTH; if(mapx < 0) mapx = 0; // cerr << "mapx=" << mapx << " mapy=" << mapy << endl; x = (int)rint(mapx); y = (int)rint(mapy); // cerr << "FINAL: x=" << x << " y=" << y << endl; }}/** If 'ground' is true, it draws the ground layer. Otherwise the shape arrays (other, stencil, later) are populated.*/void Map::setupShapes(bool ground) { if(!ground) { laterCount = stencilCount = otherCount = damageCount = 0; mapChanged = false; } int chunkOffsetX = 0; int chunkStartX = (getX() - MAP_OFFSET) / MAP_UNIT; int mod = (getX() - MAP_OFFSET) % MAP_UNIT; if(mod) { chunkOffsetX = -mod; } int chunkEndX = MAP_VIEW_WIDTH / MAP_UNIT + chunkStartX; int chunkOffsetY = 0; int chunkStartY = (getY() - MAP_OFFSET) / MAP_UNIT; mod = (getY() - MAP_OFFSET) % MAP_UNIT; if(mod) { chunkOffsetY = -mod; } int chunkEndY = MAP_VIEW_DEPTH / MAP_UNIT + chunkStartY; Shape *shape; int posX, posY; float xpos2, ypos2, zpos2; for(int chunkX = chunkStartX; chunkX < chunkEndX; chunkX++) { if(chunkX < 0 || chunkX > MAP_WIDTH / MAP_UNIT) continue; for(int chunkY = chunkStartY; chunkY < chunkEndY; chunkY++) { if(chunkY < 0 || chunkY > MAP_DEPTH / MAP_UNIT) continue; int doorValue = 0; if(!lightMap[chunkX][chunkY]) { if(ground) continue; else { // see if a door has to be drawn for(int yp = MAP_UNIT_OFFSET + 1; yp < MAP_UNIT; yp++) { bool found = false; if(chunkX - 1 >= 0 && lightMap[chunkX - 1][chunkY]) { for(int xp = MAP_UNIT - MAP_UNIT_OFFSET; xp < MAP_UNIT; xp++) { posX = (chunkX - 1) * MAP_UNIT + xp + MAP_OFFSET; posY = chunkY * MAP_UNIT + yp + MAP_OFFSET + 1; if(posX >= 0 && posX < MAP_WIDTH && posY >= 0 && posY < MAP_DEPTH && pos[posX][posY][0]) { found = true; break; } } } if(!found) doorValue |= Constants::MOVE_LEFT; found = false; if(chunkX + 1 < MAP_WIDTH / MAP_UNIT && lightMap[chunkX + 1][chunkY]) { for(int xp = 0; xp < MAP_UNIT_OFFSET; xp++) { posX = (chunkX + 1) * MAP_UNIT + xp + MAP_OFFSET; posY = chunkY * MAP_UNIT + yp + MAP_OFFSET + 1; if(posX >= 0 && posX < MAP_WIDTH && posY >= 0 && posY < MAP_DEPTH && pos[posX][posY][0]) { found = true; break; } } } if(!found) doorValue |= Constants::MOVE_RIGHT; } for(int xp = MAP_UNIT_OFFSET; xp < MAP_UNIT - MAP_UNIT_OFFSET; xp++) { bool found = false; if(chunkY - 1 >= 0 && lightMap[chunkX][chunkY - 1]) { for(int yp = MAP_UNIT - MAP_UNIT_OFFSET; yp < MAP_UNIT; yp++) { posX = chunkX * MAP_UNIT + xp + MAP_OFFSET; posY = (chunkY - 1) * MAP_UNIT + yp + MAP_OFFSET + 1; if(posX >= 0 && posX < MAP_WIDTH && posY >= 0 && posY < MAP_DEPTH && pos[posX][posY][0]) { found = true; break; } } } if(!found) doorValue |= Constants::MOVE_UP; found = false; if(chunkY + 1 >= 0 && lightMap[chunkX][chunkY + 1]) { for(int yp = 0; yp < MAP_UNIT_OFFSET; yp++) { posX = chunkX * MAP_UNIT + xp + MAP_OFFSET; posY = (chunkY + 1) * MAP_UNIT + yp + MAP_OFFSET + 1; if(posX >= 0 && posX < MAP_WIDTH && posY >= 0 && posY < MAP_DEPTH && pos[posX][posY][0]) { found = true; break; } } } if(!found) doorValue |= Constants::MOVE_DOWN; } if(doorValue == 0) continue; } } for(int yp = 0; yp < MAP_UNIT; yp++) { for(int xp = 0; xp < MAP_UNIT; xp++) { /** In scourge, shape coordinates are given by their left-bottom corner. So the +1 for posY moves the position 1 unit down the Y axis, which is the unit square's bottom left corner. */ posX = chunkX * MAP_UNIT + xp + MAP_OFFSET; posY = chunkY * MAP_UNIT + yp + MAP_OFFSET + 1; if(ground) { shape = floorPositions[posX][posY]; if(shape) { xpos2 = (float)((chunkX - chunkStartX) * MAP_UNIT + xp + chunkOffsetX) / GLShape::DIV; ypos2 = (float)((chunkY - chunkStartY) * MAP_UNIT - shape->getDepth() + yp + chunkOffsetY) / GLShape::DIV; drawGroundPosition(posX, posY, xpos2, ypos2, shape); } } else { for(int zp = 0; zp < MAP_VIEW_HEIGHT; zp++) { if(lightMap[chunkX][chunkY] && effect[posX][posY][zp]) { xpos2 = (float)((chunkX - chunkStartX) * MAP_UNIT + xp + chunkOffsetX) / GLShape::DIV; ypos2 = (float)((chunkY - chunkStartY) * MAP_UNIT - 1 + yp + chunkOffsetY) / GLShape::DIV; zpos2 = (float)(zp) / GLShape::DIV; setupPosition(posX, posY, zp, xpos2, ypos2, zpos2, effect[posX][posY][zp]->effect->getShape(), NULL, NULL, effect[posX][posY][zp]); } if(pos[posX][posY][zp] && pos[posX][posY][zp]->x == posX && pos[posX][posY][zp]->y == posY && pos[posX][posY][zp]->z == zp) { shape = pos[posX][posY][zp]->shape; // FIXME: this draws more doors than needed... // it should use doorValue to figure out what needs to be drawn if((!lightMap[chunkX][chunkY] && (shape == scourge->getShapePalette()->findShapeByName("NS_DOOR") || shape == scourge->getShapePalette()->findShapeByName("EW_DOOR") || shape == scourge->getShapePalette()->findShapeByName("NS_DOOR_TOP") || shape == scourge->getShapePalette()->findShapeByName("EW_DOOR_TOP") || shape == scourge->getShapePalette()->findShapeByName("DOOR_SIDE"))) || (lightMap[chunkX][chunkY] && shape)) { xpos2 = (float)((chunkX - chunkStartX) * MAP_UNIT + xp + chunkOffsetX) / GLShape::DIV; ypos2 = (float)((chunkY - chunkStartY) * MAP_UNIT - shape->getDepth() + yp + chunkOffsetY) / GLShape::DIV; zpos2 = (float)(zp) / GLShape::DIV; setupPosition(posX, posY, zp, xpos2, ypos2, zpos2, shape, pos[posX][posY][zp]->item, pos[posX][posY][zp]->creature, NULL); } } } } } } } }}void Map::drawGroundPosition(int posX, int posY, float xpos2, float ypos2, Shape *shape) { GLuint name; // encode this shape's map location in its name name = posX + (MAP_WIDTH * posY); glTranslatef( xpos2, ypos2, 0.0f); glPushName( name ); shape->draw(); glPopName(); glTranslatef( -xpos2, -ypos2, 0.0f);}void Map::setupPosition(int posX, int posY, int posZ, float xpos2, float ypos2, float zpos2, Shape *shape, Item *item, Creature *creature, EffectLocation *effect) { GLuint name; name = posX + (MAP_WIDTH * (posY)) + (MAP_WIDTH * MAP_DEPTH * posZ); // special effects if(effect || (creature && creature->isEffectOn())) { damage[damageCount].xpos = xpos2; damage[damageCount].ypos = ypos2; damage[damageCount].zpos = zpos2; damage[damageCount].shape = shape; damage[damageCount].item = item; damage[damageCount].creature = creature; damage[damageCount].effect = effect; damage[damageCount].projectile = NULL; damage[damageCount].name = name; damageCount++; // don't draw shape if it's an area effect if(!creature) return; } if(shape->isStencil()) { stencil[stencilCount].xpos = xpos2; stencil[stencilCount].ypos = ypos2; stencil[stencilCount].zpos = zpos2; stencil[stencilCount].shape = shape; stencil[stencilCount].item = item; stencil[stencilCount].creature = creature; stencil[stencilCount].projectile = NULL; stencil[stencilCount].effect = NULL; stencil[stencilCount].name = name; stencilCount++; } else if(!shape->isStencil()) { if(shape->drawFirst()) { other[otherCount].xpos = xpos2; other[otherCount].ypos = ypos2; other[otherCount].zpos = zpos2; other[otherCount].shape = shape; other[otherCount].item = item; other[otherCount].creature = creature; other[otherCount].projectile = NULL; other[otherCount].effect = NULL; other[otherCount].name = name; otherCount++; } if(shape->drawLater()) { later[laterCount].xpos = xpos2; later[laterCount].ypos = ypos2; later[laterCount].zpos = zpos2; later[laterCount].shape = shape; later[laterCount].item = item;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -