📄 map.cpp
字号:
pos[x + xp][y - yp][z + zp] = NULL; } } } } return shape;}void Map::setItem(Sint16 x, Sint16 y, Sint16 z, Item *item) { if(item) { if(item->getShape()) { mapChanged = true; for(int xp = 0; xp < item->getShape()->getWidth(); xp++) { for(int yp = 0; yp < item->getShape()->getDepth(); yp++) { for(int zp = 0; zp < item->getShape()->getHeight(); zp++) { if(!pos[x + xp][y - yp][z + zp]) { pos[x + xp][y - yp][z + zp] = new Location(); } pos[x + xp][y - yp][z + zp]->item = item; pos[x + xp][y - yp][z + zp]->shape = item->getShape(); pos[x + xp][y - yp][z + zp]->creature = NULL; pos[x + xp][y - yp][z + zp]->x = x; pos[x + xp][y - yp][z + zp]->y = y; pos[x + xp][y - yp][z + zp]->z = z; } } } } }}Item *Map::removeItem(Sint16 x, Sint16 y, Sint16 z) { Item *item = NULL; if(pos[x][y][z] && pos[x][y][z]->item && pos[x][y][z]->x == x && pos[x][y][z]->y == y && pos[x][y][z]->z == z) { mapChanged = true; item = pos[x][y][z]->item; for(int xp = 0; xp < item->getShape()->getWidth(); xp++) { for(int yp = 0; yp < item->getShape()->getDepth(); yp++) { for(int zp = 0; zp < item->getShape()->getHeight(); zp++) { delete pos[x + xp][y - yp][z + zp]; pos[x + xp][y - yp][z + zp] = NULL; } } } } return item;}// drop items above this onevoid Map::dropItemsAbove(int x, int y, int z, Item *item) { int count = 0; Location drop[100]; for(int tx = 0; tx < item->getShape()->getWidth(); tx++) { for(int ty = 0; ty < item->getShape()->getDepth(); ty++) { for(int tz = z + item->getShape()->getHeight(); tz < MAP_VIEW_HEIGHT; tz++) { Location *loc2 = pos[x + tx][y - ty][tz]; if(loc2 && loc2->item) { drop[count].x = loc2->x; drop[count].y = loc2->y; drop[count].z = loc2->z - item->getShape()->getHeight(); drop[count].item = loc2->item; count++; removeItem(loc2->x, loc2->y, loc2->z); tz += drop[count - 1].item->getShape()->getHeight() - 1; } } } } for(int i = 0; i < count; i++) { cerr << "item " << drop[i].item->getItemName() << " new z=" << drop[i].z << endl; setItem(drop[i].x, drop[i].y, drop[i].z, drop[i].item); }}void Map::setCreature(Sint16 x, Sint16 y, Sint16 z, Creature *creature) { char message[120]; if(creature) { if(creature->getShape()) { mapChanged = true; while(true) { for(int xp = 0; xp < creature->getShape()->getWidth(); xp++) { for(int yp = 0; yp < creature->getShape()->getDepth(); yp++) { for(int zp = 0; zp < creature->getShape()->getHeight(); zp++) { // cerr <<"adding pos " << x + xp << "," << y - yp << "," << z + zp; if(!pos[x + xp][y - yp][z + zp]) { if(!USE_LOC_CACHE || nbPosCache < 0){ // cerr << " no cache available!" << endl; pos[x + xp][y - yp][z + zp] = new Location(); } else{ // cerr << " cache number : " << nbPosCache << endl; pos[x + xp][y - yp][z + zp] = posCache[nbPosCache]; //posCache[nbPosCache] = NULL; nbPosCache--; } } else if(pos[x + xp][y - yp][z + zp]->item) { // creature picks up non-blocking item (this is the only way to handle // non-blocking items. It's also very 'roguelike'. Item *item = pos[x + xp][y - yp][z + zp]->item; removeItem(pos[x + xp][y - yp][z + zp]->x, pos[x + xp][y - yp][z + zp]->y, pos[x + xp][y - yp][z + zp]->z); creature->addInventory(item); sprintf(message, "%s picks up %s.", creature->getName(), item->getItemName()); addDescription(message); // since the above will have removed some locations, try adding the creature again continue; } pos[x + xp][y - yp][z + zp]->item = NULL; pos[x + xp][y - yp][z + zp]->shape = creature->getShape(); pos[x + xp][y - yp][z + zp]->creature = creature; pos[x + xp][y - yp][z + zp]->x = x; pos[x + xp][y - yp][z + zp]->y = y; pos[x + xp][y - yp][z + zp]->z = z; //creature->moveTo(x, y, z); } } } break; } } }}Creature *Map::removeCreature(Sint16 x, Sint16 y, Sint16 z) { Creature *creature = NULL; if(pos[x][y][z] && pos[x][y][z]->creature && pos[x][y][z]->x == x && pos[x][y][z]->y == y && pos[x][y][z]->z == z) { mapChanged = true; creature = pos[x][y][z]->creature; // cout<<"width : "<< creature->getShape()->getWidth()<<endl; // cout<<"depth: "<< creature->getShape()->getDepth()<<endl; // cout<<"height: "<< creature->getShape()->getHeight()<<endl; for(int xp = 0; xp < creature->getShape()->getWidth(); xp++) { for(int yp = 0; yp < creature->getShape()->getDepth(); yp++) { for(int zp = 0; zp < creature->getShape()->getHeight(); zp++) { // cerr <<"deleting pos " << x + xp << "," << y - yp << "," << z + zp; if(!USE_LOC_CACHE || nbPosCache >= MAX_POS_CACHE - 1){ // cerr << " no cache available!" << endl; delete pos[x + xp][y - yp][z + zp]; pos[x + xp][y - yp][z + zp] = NULL; } else{ nbPosCache++; // cerr << " cache number : " << nbPosCache << endl; posCache[nbPosCache] = pos[x + xp][y - yp][z + zp]; pos[x + xp][y - yp][z + zp] = NULL; } } } } } return creature;}// FIXME: only uses x,y for now// return false if there is any hole in the wallsbool Map::isWallBetweenShapes(int x1, int y1, int z1, Shape *shape1, int x2, int y2, int z2, Shape *shape2) { for(int x = x1; x < x1 + shape1->getWidth(); x++) { for(int y = y1; y < y1 + shape1->getDepth(); y++) { for(int xx = x2; xx < x2 + shape2->getWidth(); xx++) { for(int yy = y2; yy < y2 + shape2->getDepth(); yy++) { if(!isWallBetween(x, y, z1, xx, yy, z2)) return false; } } } } return true; }// FIXME: only uses x,y for nowbool Map::isWallBetween(int x1, int y1, int z1, int x2, int y2, int z2) { if(x1 == x2 && y1 == y2) return isWall(x1, y1, z1); if(x1 == x2) { if(y1 > y2) SWAP(y1, y2); for(int y = y1; y <= y2; y++) { if(isWall(x1, y, z1)) return true; } return false; } if(y1 == y2) { if(x1 > x2) SWAP(x1, x2); for(int x = x1; x <= x2; x++) { if(isWall(x, y1, z1)) return true; } return false; } // fprintf(stderr, "Checking for wall: from: %d,%d to %d,%d\n", x1, y1, x2, y2); bool ret = false; bool yDiffBigger = (abs(y2 - y1) > abs(x2 - x1)); float m = (float)(y2 - y1) / (float)(x2 - x1); int steps = (yDiffBigger ? abs(y2 - y1) : abs(x2 - x1)); float x = x1; float y = y1; for(int i = 0; i < steps; i++) { // fprintf(stderr, "\tat=%f,%f\n", x, y); if(isWall((int)x, (int)y, z1)) { //fprintf(stderr, "wall at %f, %f\n", x, y); ret = true; break; } if(yDiffBigger) { if(y1 < y2) y += 1.0f; else y -= 1.0f; if(x1 < x2) x += 1.0f / abs((int)m); else x += -1.0f / abs((int)m); } else { if(x1 < x2) x += 1.0f; else x -= 1.0f; if(y1 < y2) y += abs((int)m); else y += -1.0 * abs((int)m); } } // fprintf(stderr, "wall in between? %s\n", (ret ? "TRUE": "FALSE")); return ret;}bool Map::isWall(int x, int y, int z) { Location *loc = getLocation((int)x, (int)y, z); return (loc && (!loc->item || loc->item->getShape() != loc->shape) && (!loc->creature || loc->creature->getShape() != loc->shape));}// FIXME: only uses x, y for nowbool Map::shapeFits(Shape *shape, int x, int y, int z) { for(int tx = 0; tx < shape->getWidth(); tx++) { for(int ty = 0; ty < shape->getDepth(); ty++) { if(getLocation(x + tx, y - ty, 0)) { return false; } } } return true;}// FIXME: only uses x, y for nowLocation *Map::getBlockingLocation(Shape *shape, int x, int y, int z) { for(int tx = 0; tx < shape->getWidth(); tx++) { for(int ty = 0; ty < shape->getDepth(); ty++) { Location *loc = getLocation(x + tx, y - ty, 0); if(loc) return loc; } } return NULL;}/** Return the drop location, or NULL if none */Location *Map::getDropLocation(Shape *shape, int x, int y, int z) { for(int tx = 0; tx < shape->getWidth(); tx++) { for(int ty = 0; ty < shape->getDepth(); ty++) { Location *loc = getLocation(x + tx, y - ty, z); if(loc) { return loc; } } } return NULL;}// the world has changed...void Map::configureLightMap() { lightMapChanged = false; // draw nothing at first 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); } } if(!LIGHTMAP_ENABLED) return; int chunkX = (scourge->getParty()->getPlayer()->getX() + (scourge->getParty()->getPlayer()->getShape()->getWidth() / 2) - MAP_OFFSET) / MAP_UNIT; int chunkY = (scourge->getParty()->getPlayer()->getY() - (scourge->getParty()->getPlayer()->getShape()->getDepth() / 2) - MAP_OFFSET) / MAP_UNIT; traceLight(chunkX, chunkY);}void Map::traceLight(int chunkX, int chunkY) { if(chunkX < 0 || chunkX >= MAP_WIDTH / MAP_UNIT || chunkY < 0 || chunkY >= MAP_DEPTH / MAP_UNIT) return; // already visited? if(lightMap[chunkX][chunkY]) return; // let there be light lightMap[chunkX][chunkY] = 1; // can we go N? int x, y; bool blocked = false; x = chunkX * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); for(y = chunkY * MAP_UNIT + MAP_OFFSET - (MAP_UNIT / 2); y < chunkY * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); y++) { if(isLocationBlocked(x, y, 0)) { blocked = true; break; } } if(!blocked) traceLight(chunkX, chunkY - 1); // can we go E? blocked = false; y = chunkY * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); for(x = chunkX * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); x < chunkX * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2) + MAP_UNIT; x++) { if(isLocationBlocked(x, y, 0)) { blocked = true; break; } } if(!blocked) traceLight(chunkX + 1, chunkY); // can we go S? blocked = false; x = chunkX * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); for(y = chunkY * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); y < chunkY * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2) + MAP_UNIT; y++) { if(isLocationBlocked(x, y, 0)) { blocked = true; break; } } if(!blocked) traceLight(chunkX, chunkY + 1); // can we go W? blocked = false; y = chunkY * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); for(x = chunkX * MAP_UNIT + MAP_OFFSET - (MAP_UNIT / 2); x < chunkX * MAP_UNIT + MAP_OFFSET + (MAP_UNIT / 2); x++) { if(isLocationBlocked(x, y, 0)) { blocked = true; break; } } if(!blocked) traceLight(chunkX - 1, chunkY);}bool Map::isLocationBlocked(int x, int y, int z) { if(x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_DEPTH && z >= 0 && z < MAP_VIEW_HEIGHT) { Location *pos = getLocation(x, y, z); if(pos == NULL || pos->item || pos->creature || !( ((GLShape*)(pos->shape))->isLightBlocking()) ) { return false; } } return true;}void Map::drawCube(float x, float y, float z, float r) { glBegin(GL_QUADS); // front glNormal3f(0.0, 0.0, 1.0); glVertex3f(-r+x, -r+y, r+z); glVertex3f(r+x, -r+y, r+z); glVertex3f(r+x, r+y, r+z); glVertex3f(-r+x, r+y, r+z); // back glNormal3f(0.0, 0.0, -1.0); glVertex3f(r+x, -r+y, -r+z); glVertex3f(-r+x, -r+y, -r+z); glVertex3f(-r+x, r+y, -r+z); glVertex3f(r+x, r+y, -r+z); // top glNormal3f(0.0, 1.0, 0.0); glVertex3f(-r+x, r+y, r+z); glVertex3f(r+x, r+y, r+z); glVertex3f(r+x, r+y, -r+z); glVertex3f(-r+x, r+y, -r+z); // bottom glNormal3f(0.0, -1.0, 0.0); glVertex3f(-r+x, -r+y, -r+z); glVertex3f(r+x, -r+y, -r+z); glVertex3f(r+x, -r+y, r+z); glVertex3f(-r+x, -r+y, r+z); // left glNormal3f(-1.0, 0.0, 0.0); glVertex3f(-r+x, -r+y, -r+z); glVertex3f(-r+x, -r+y, r+z); glVertex3f(-r+x, r+y, r+z); glVertex3f(-r+x, r+y, -r+z); // right glNormal3f(1.0, 0.0, 0.0); glVertex3f(r+x, -r+y, r+z); glVertex3f(r+x, -r+y, -r+z); glVertex3f(r+x, r+y, -r+z); glVertex3f(r+x, r+y, r+z); glEnd(); }/** * Find the creatures in this area and add them to the targets array. * Returns the number of creatures found. (0 if none.) * It's the caller responsibility to create the targets array. */int Map::getCreaturesInArea(int x, int y, int radius, Creature *targets[]) { int count = 0; for(int xx = x - radius; xx < x + radius && xx < MAP_WIDTH; xx++) { for(int yy = y - radius; yy < y + radius && yy < MAP_DEPTH; yy++) { Location *loc = pos[xx][yy][0]; if(loc && loc->creature) { bool alreadyFound = false; for(int i = 0; i < count; i++) { if(targets[i] == loc->creature) { alreadyFound = true; break; } } if(!alreadyFound) { targets[count++] = loc->creature; } } } } return count;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -