void TileLayer::draw(SDL_Surface* dst) { const uint16_t tileSize = 25; // Determine the coordinate to draw the tile animation.. uint16_t xp = this->x*tileSize; uint16_t yp = this->y*tileSize; this->getAnimation()->move(xp, yp); this->getAnimation()->blit(dst); PlayModel* playModel = PlayModel::GetInstance(); // Redraw the Key. if (playModel->tileCoordHasKey(TileCoord(this->x, this->y))) { KeyAnim->move(xp, yp); KeyAnim->blit(dst); } // Redraw the Player. if (playModel->tileCoordHasPlayer(TileCoord(this->x, this->y))) { PlayerAnim->move(xp, yp); PlayerAnim->blit(dst); } }
TileCoord goTowards(const TileCoord &from, TileCoord towards) { if (from.row < towards.row) return TileCoord(from.row + 1, from.col); if (from.row > towards.row) return TileCoord(from.row - 1, from.col); if (from.col < towards.col) return TileCoord(from.row, from.col + 1); if (from.col > towards.col) return TileCoord(from.row, from.col - 1); assert(false); }
bool findOnMapRandomTileOfType(const MapTiles &map, const Tile &tile, int numTries, TileCoord *resultingTileLocation) { for (int i = 0; i < numTries; i++) { int row = rand() % (map.getSize().row - 2); int col = rand() % (map.getSize().col - 2); if (map[TileCoord(row, col)] == tile) { *resultingTileLocation = TileCoord(row, col); return true; } } return false; }
bool areaOnMapIsFilledWithTile(const MapTiles &map, const Tile &tile, const Area &area) { if (area.origin.row < 0 || area.origin.row + area.size.row >= map.getSize().row) return false; if (area.origin.col < 0 || area.origin.col + area.size.col >= map.getSize().col) return false; for (int row = area.origin.row; row < area.origin.row + area.size.row; row++) for (int col = area.origin.col; col < area.origin.col + area.size.col; col++) if (map[TileCoord(row, col)] != tile) return false; return true; }
void TileScene::UpdatePreviewTile(int x, int y, TileCoord origin) { if(origin == TileCoord(-1, -1)) { if(previewItems.contains(TileCoord(x, y))) { removeItem(previewItems[TileCoord(x, y)]); delete previewItems[TileCoord(x, y)]; previewItems.remove(TileCoord(x, y)); } return; } TileWidgetItem *tempTile = new TileWidgetItem; tempTile->setFlag(QGraphicsItem::ItemIsSelectable); //update its Pixmap tempTile->SetTilePixmap(tileController->GetTilePixmap(origin)); //set the position tempTile->setPos(x * tileController->GetTileWidth(), y * tileController->GetTileHeight()); previewItems[TileCoord(x, y)] = tempTile; addItem(tempTile); }
void ConveyorAnimation::BuildConveyorAnimations() { ClearConveyors(); PlayModel* playModel = PlayModel::GetInstance(); for (int x = 0; x < PlayModel::GRID_WIDTH; x++) { for (int y = 0; y < PlayModel::GRID_HEIGHT; y++) { TileCoord tileCoord = TileCoord(x, y); if (playModel->isConveyor(tileCoord)) { if (!TileInConveyor(tileCoord)) { // This TileCoord must be part of a Conveyor. Find the // start of the Conveyor. TileCoord q = tileCoord; TileCoord p = q; if (TileInConveyor(tileCoord)) { continue; } Direction conveyDir = playModel->getConveyorDirection(q); // Initialize oppDir to something invalid to pacify // compiler warnings. Direction oppDir = DIRECTION_COUNT; // Determine the opposite direction of this belt. if (conveyDir == DIRECTION_UP) { oppDir = DIRECTION_DOWN; } else if (conveyDir == DIRECTION_DOWN) { oppDir = DIRECTION_UP; } else if (conveyDir == DIRECTION_LEFT) { oppDir = DIRECTION_RIGHT; } else if (conveyDir == DIRECTION_RIGHT) { oppDir = DIRECTION_LEFT; } //std::cout << "\tOppDir: " << oppDir << std::endl; // A circular conveyor is one which stretches from one // border to the other, causing it it wrap-around. We need // to check for this behavior so that we can prevent // infinite looping here. bool circular = false; // Go backwards along the belt until you hit a non-conveyor // tile, or a conveyor tile which is part of another // conveyor, or we find that the current belt is circular. TileCoord prev = p; while ( playModel->isConveyor(p) && playModel->getConveyorDirection(p) == conveyDir && !TileInConveyor(p) && !circular) { prev = p; if (oppDir == DIRECTION_UP) { p = playModel->getTileCoordUp(p); } else if (oppDir == DIRECTION_DOWN) { p = playModel->getTileCoordDown(p); } else if (oppDir == DIRECTION_RIGHT) { p = playModel->getTileCoordRight(p); } else if (oppDir == DIRECTION_LEFT) { p = playModel->getTileCoordLeft(p); } if (p == q) { circular = true; } } TileCoord start = p = prev; std::vector<TileCoord> conveyorTiles; int tileNum = 0; // Now follow the conveyor from its start until a // non-conveyor tile, or a conveyor tile which is part of // another conveyor or if the belt is found to be circular, // the start tile. while ( playModel->isConveyor(p) && playModel->getConveyorDirection(p) == conveyDir && !TileInConveyor(p)) { conveyorTiles.push_back(p); tileNum++; //std::cout << "\ttile #" << tileNum << " " << p->getX() << "," << p->getY() << std::endl; if (conveyDir == DIRECTION_UP) { p = playModel->getTileCoordUp(p); } else if (conveyDir == DIRECTION_DOWN) { p = playModel->getTileCoordDown(p); } else if (conveyDir == DIRECTION_RIGHT) { p = playModel->getTileCoordRight(p); } else if (conveyDir == DIRECTION_LEFT) { p = playModel->getTileCoordLeft(p); } if (circular) { if (p == start) { break; } } } // Creating a ConveyorAnimation causes it to be added to // the ConveyorAnimation array. new ConveyorAnimation(conveyorTiles); } } } } }
MapTiles *generateMap(const GenerateOptions &options) { srand(options.randomSeed); MapTiles *map = new MapTiles(TileCoord(options.numRows, options.numCols), options.wall); int numRoomsGenerated = 0; for (int numTries = 0; numTries < 100 && numRoomsGenerated < options.numRooms; numTries++) { TileCoord roomCenterTileLocation; if (!findOnMapRandomTileOfType(*map, options.wall, 100, &roomCenterTileLocation)) break; Area room(roomCenterTileLocation, TileCoord(1, 1)); assert(areaOnMapIsFilledWithTile(*map, options.wall, room)); // Expand down until we have max room rows + 2 (the +2 is so we can retract later to have nice padding) while (room.size.row < options.maxRoomRows + 2 * options.padding) { Area proposedRoom = room; proposedRoom.size.row++; if (areaOnMapIsFilledWithTile(*map, options.wall, proposedRoom)) room = proposedRoom; else break; } // Expand up until we have max room rows + 2 (we may have already gotten that many in the last while loop, which is fine while (room.size.row < options.maxRoomRows + 2 * options.padding) { Area proposedRoom = room; proposedRoom.origin.row--; proposedRoom.size.row++; if (areaOnMapIsFilledWithTile(*map, options.wall, proposedRoom)) room = proposedRoom; else break; } // Expand down until we have max room cols + 2 (the +2 is so we can retract later to have nice padding) while (room.size.col < options.maxRoomCols + 2 * options.padding) { Area proposedRoom = room; proposedRoom.size.col++; if (areaOnMapIsFilledWithTile(*map, options.wall, proposedRoom)) room = proposedRoom; else break; } // Expand up until we have max room cols + 2 (we may have already gotten that many in the last while loop, which is fine while (room.size.col < options.maxRoomCols + 2 * options.padding) { Area proposedRoom = room; proposedRoom.origin.col--; proposedRoom.size.col++; if (areaOnMapIsFilledWithTile(*map, options.wall, proposedRoom)) room = proposedRoom; else break; } // Retract, so we have a padding of wall around the outside of the room (so no rooms touch) room.origin.row += options.padding; room.origin.col += options.padding; room.size.row -= 2 * options.padding; room.size.col -= 2 * options.padding; if (room.size.row < options.minRoomRows) continue; if (room.size.col < options.minRoomCols) continue; map->fillAreaWithTile(room, options.floor); numRoomsGenerated++; } connectAllRegions(map, options.wall, options.floor); assert(numRoomsGenerated > 0); std::cout << "Map:" << std::endl; for (int row = 0; row < map->getSize().row; row++) { for (int col = 0; col < map->getSize().col; col++) { std::cout << (*map)[TileCoord(row, col)].character; } std::cout << std::endl; } std::cout << "/Map" << std::endl; return map; }
void connectAllRegions(MapTiles *map, const Tile &WALL, const Tile &FLOOR) { Region ***regionsByRowCol = new Region**[map->getSize().row]; for (int row = 0; row < map->getSize().row; row++) { regionsByRowCol[row] = new Region*[map->getSize().col]; for (int col = 0; col < map->getSize().col; col++) { regionsByRowCol[row][col] = NULL; } } std::vector<Region *> regions; // std::cout << "Regions:" << std::endl; for (int row = 0; row < map->getSize().row; row++) { for (int col = 0; col < map->getSize().col; col++) { if ((*map)[TileCoord(row, col)] == FLOOR && regionsByRowCol[row][col] == NULL) { std::set<TileCoord, TileCoord::Before> *newRegion = new std::set<TileCoord, TileCoord::Before>(); // charsByRegion[newRegion] = charsByRegion.size() + '0'; findContiguous(*map, TileCoord(row, col), newRegion); for (Region::iterator i = newRegion->begin(), iEnd = newRegion->end(); i != iEnd; i++) regionsByRowCol[i->row][i->col] = newRegion; regions.push_back(newRegion); } // std::cout << charsByRegion[regionsByRowCol[row][col]]; } // std::cout << std::endl; } // std::cout << "/Regions" << std::endl; // std::cout << "Begin!" << std::endl; // for (int i = 0; i < regions.size(); i++) // std::cout << "region " << regions[i] << " size " << regions[i]->size() << std::endl; while (regions.size() > 1) { int randomRegionsIndex = rand() % (regions.size() - 1); Region *region1 = regions[randomRegionsIndex]; Region *region2 = regions[randomRegionsIndex + 1]; assert(!region1->empty()); assert(!region2->empty()); std::set<TileCoord, TileCoord::Before>::iterator iter = region2->begin(); std::advance(iter, rand() % region2->size()); TileCoord destination = *iter; // std::cout << "digging!" << std::endl; digTowardsButStopWhenHitAnotherRegion(map, regionsByRowCol, region1, destination); // std::cout << "After dig, before flood: " << std::endl; // displayRegions(*map, regionsByRowCol); // for (int i = 0; i < regions.size(); i++) // std::cout << "region " << regions[i] << " size " << regions[i]->size() << std::endl; // std::cout << "flooding!" << std::endl; findContiguous(*map, *region1->begin(), region1); for (Region::iterator i = region1->begin(), iEnd = region1->end(); i != iEnd; i++) { if (regionsByRowCol[i->row][i->col] != NULL && regionsByRowCol[i->row][i->col] != region1) regionsByRowCol[i->row][i->col]->erase(*i); regionsByRowCol[i->row][i->col] = region1; } // std::cout << "After flood:" << std::endl; // for (int i = 0; i < regions.size(); i++) // std::cout << "region " << regions[i] << " size " << regions[i]->size() << std::endl; int numRegionsNowEmpty = 0; for (int i = 0; i < regions.size(); ) { // if (regions[i]->size() == 1) // std::cout << *regions[i]->begin() << std::endl; if (regions[i]->empty()) { regions.erase(regions.begin() + i); numRegionsNowEmpty++; } else i++; } assert(numRegionsNowEmpty); // displayRegions(*map, regionsByRowCol); } }