⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 map.cpp

📁 S.C.O.U.R.G.E.是一款类似Rogue的游戏
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************                          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 + -