From a475823fee214f0bef2749c39f56a5ab8b15bc47 Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 25 Mar 2019 00:10:57 -0400 Subject: [PATCH] further refine region map editor --- forms/regionmapeditor.ui | 76 +++++--------- include/core/regionmap.h | 3 + include/core/regionmapgenerator.h | 77 -------------- include/ui/regionmapeditor.h | 6 +- porymap.pro | 2 - src/core/regionmap.cpp | 31 ++++++ src/core/regionmapgenerator.cpp | 148 -------------------------- src/ui/regionmapeditor.cpp | 169 ++++++++++++++++++++++-------- src/ui/regionmappixmapitem.cpp | 13 +-- 9 files changed, 197 insertions(+), 328 deletions(-) delete mode 100644 include/core/regionmapgenerator.h delete mode 100644 src/core/regionmapgenerator.cpp diff --git a/forms/regionmapeditor.ui b/forms/regionmapeditor.ui index acd7ceb9..96cd6e10 100644 --- a/forms/regionmapeditor.ui +++ b/forms/regionmapeditor.ui @@ -61,8 +61,8 @@ 0 0 - 384 - 249 + 350 + 225 @@ -182,8 +182,8 @@ 0 0 - 384 - 249 + 350 + 225 @@ -330,10 +330,10 @@ - 0 + 8 0 - 283 - 275 + 278 + 262 @@ -487,6 +487,9 @@ true + + QComboBox::NoInsert + @@ -518,43 +521,11 @@ - - - - 10 - 100 - 138 - 26 - - - - - - - x - - - - - - - - - - y - - - - - - - - 10 - 190 + 100 113 32 @@ -651,8 +622,8 @@ 0 0 - 412 - 249 + 441 + 230 @@ -785,10 +756,10 @@ - 0 + 8 0 - 295 - 283 + 255 + 274 @@ -1076,7 +1047,7 @@ 0 0 829 - 21 + 22 @@ -1101,7 +1072,8 @@ Tools - + + @@ -1160,6 +1132,16 @@ Clear Map Layout + + + Import Region Map Image Tiles... + + + + + Import City Map Image Tiles... + + diff --git a/include/core/regionmap.h b/include/core/regionmap.h index 7300cc60..f2556c78 100644 --- a/include/core/regionmap.h +++ b/include/core/regionmap.h @@ -64,6 +64,7 @@ public: void readLayout(); void save(); + void saveTileImages(); void saveBkgImgBin(); void saveLayout(); void saveOptions(int id, QString sec, QString name, int x, int y); @@ -80,7 +81,9 @@ public: unsigned getTileId(int x, int y); int getMapSquareIndex(int x, int y); QString pngPath(); + void setTemporaryPngPath(QString); QString cityTilesPath(); + void setTemporaryCityTilesPath(QString); QVector getTiles(); void setTiles(QVector tileIds); diff --git a/include/core/regionmapgenerator.h b/include/core/regionmapgenerator.h deleted file mode 100644 index 54539009..00000000 --- a/include/core/regionmapgenerator.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef GUARD_REGIONMAPGENERATOR_H -#define GUARD_REGIONMAPGENERATOR_H - -#include "project.h" -#include "regionmap.h" -#include "map.h" - -#include -#include -#include -#include -#include -#include - -class GeneratorEntry -{ - GeneratorEntry(QString name_, int x_, int y_, int width_, int height_) { - this->name = name_; - this->x = x_; - this->y = y_; - this->width = width_; - this->height = height_; - } - int x; - int y; - int width; - int height; - QString name; - friend class RegionMapGenerator; -public: - friend QDebug operator<<(QDebug, const GeneratorEntry &); -}; - -class RegionMapGenerator -{ - // -public: - // - RegionMapGenerator() = default; - RegionMapGenerator(Project *); - ~RegionMapGenerator() {}; - - Project *project = nullptr; - - QVector map_squares; - - QStack> forks;//? - QSet connections;// - // - - void generate(QString); - - void center();// center the map squares so they arent hanging over - -private: - // - int square_block_width_ = 20; - int square_block_height_ = 20; - - int width_; - int height_; - - //QPoint - - QList entries_; - QMap entries; - - void bfs(int);// breadth first search of a graph - void search(int); - void dfs(int, QVector &);// depth first search - void sort(); - void ts();// topological sort - void populateSquares(); - -}; - -#endif // GUARD_REGIONMAPGENERATOR_H diff --git a/include/ui/regionmapeditor.h b/include/ui/regionmapeditor.h index ee364b83..a684095c 100644 --- a/include/ui/regionmapeditor.h +++ b/include/ui/regionmapeditor.h @@ -83,6 +83,7 @@ private: void displayRegionMapTileSelector(); void displayCityMapTileSelector(); void displayCityMap(QString name); + void importTileImage(bool city = false);//QString path);// what is this path tho? bool createCityMap(QString name); @@ -96,7 +97,8 @@ private slots: void on_action_RegionMap_ClearImage_triggered(); void on_action_RegionMap_ClearLayout_triggered(); void on_action_Swap_triggered(); - void on_action_RegionMap_Generate_triggered(); + void on_action_Import_RegionMap_ImageTiles_triggered(); + void on_action_Import_CityMap_ImageTiles_triggered(); void on_tabWidget_Region_Map_currentChanged(int); void on_pushButton_RM_Options_delete_clicked(); void on_comboBox_RM_ConnectedMap_activated(const QString &text); @@ -106,8 +108,6 @@ private slots: void on_verticalSlider_Zoom_City_Map_valueChanged(int); void on_verticalSlider_Zoom_City_Tiles_valueChanged(int); void on_comboBox_CityMap_picker_currentTextChanged(const QString &text); - void on_spinBox_RM_Options_x_valueChanged(int val); - void on_spinBox_RM_Options_y_valueChanged(int val); void on_lineEdit_RM_MapName_textEdited(const QString &text); void onHoveredRegionMapTileChanged(int x, int y); void onHoveredRegionMapTileCleared(); diff --git a/porymap.pro b/porymap.pro index 754f45f1..b3a19b8d 100644 --- a/porymap.pro +++ b/porymap.pro @@ -29,7 +29,6 @@ SOURCES += src/core/block.cpp \ src/core/tile.cpp \ src/core/tileset.cpp \ src/core/regionmap.cpp \ - src/core/regionmapgenerator.cpp \ src/ui/aboutporymap.cpp \ src/ui/bordermetatilespixmapitem.cpp \ src/ui/collisionpixmapitem.cpp \ @@ -86,7 +85,6 @@ HEADERS += include/core/block.h \ include/core/tile.h \ include/core/tileset.h \ include/core/regionmap.h \ - include/core/regionmapgenerator.h \ include/ui/aboutporymap.h \ include/ui/bordermetatilespixmapitem.h \ include/ui/collisionpixmapitem.h \ diff --git a/src/core/regionmap.cpp b/src/core/regionmap.cpp index 4368c9b3..3968a77c 100644 --- a/src/core/regionmap.cpp +++ b/src/core/regionmap.cpp @@ -32,11 +32,29 @@ void RegionMap::init(Project *pro) { void RegionMap::save() { logInfo("Saving region map data."); + saveTileImages(); saveBkgImgBin(); saveLayout(); porymapConfig.setRegionMapDimensions(this->img_width_, this->img_height_); } +void RegionMap::saveTileImages() { + QFile backgroundTileFile(pngPath()); + if (backgroundTileFile.open(QIODevice::ReadOnly)) { + QByteArray imageData = backgroundTileFile.readAll(); + QImage pngImage = QImage::fromData(imageData); + this->region_map_png_path = project->root + "/graphics/pokenav/region_map.png"; + pngImage.save(pngPath()); + } + QFile cityTileFile(cityTilesPath()); + if (cityTileFile.open(QIODevice::ReadOnly)) { + QByteArray imageData = cityTileFile.readAll(); + QImage cityTilesImage = QImage::fromData(imageData); + this->city_map_tiles_path = project->root + "/graphics/pokenav/zoom_tiles.png"; + cityTilesImage.save(cityTilesPath()); + } +} + void RegionMap::readBkgImgBin() { QFile binFile(region_map_bin_path); if (!binFile.open(QIODevice::ReadOnly)) return; @@ -168,6 +186,11 @@ void RegionMap::saveOptions(int id, QString sec, QString name, int x, int y) { resetSquare(id); int index = getMapSquareIndex(x + this->padLeft, y + this->padTop); if (!sec.isEmpty()) { + // Validate the input section name. + if (!project->mapSectionNameToValue.contains(sec)) { + sec = "MAPSEC_NONE"; + name = QString(); + } this->map_squares[index].has_map = sec == "MAPSEC_NONE" ? false : true; this->map_squares[index].secid = static_cast(project->mapSectionNameToValue.value(sec)); this->map_squares[index].mapsec = sec; @@ -295,10 +318,18 @@ QString RegionMap::pngPath() { return this->region_map_png_path; } +void RegionMap::setTemporaryPngPath(QString path) { + this->region_map_png_path = path; +} + QString RegionMap::cityTilesPath() { return this->city_map_tiles_path; } +void RegionMap::setTemporaryCityTilesPath(QString path) { + this->city_map_tiles_path = path; +} + // From x, y of image. int RegionMap::getMapSquareIndex(int x, int y) { int index = (x + y * img_width_); diff --git a/src/core/regionmapgenerator.cpp b/src/core/regionmapgenerator.cpp deleted file mode 100644 index 5cbabc8c..00000000 --- a/src/core/regionmapgenerator.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "regionmapgenerator.h" - - - -RegionMapGenerator::RegionMapGenerator(Project *project_) { - this->project = project_; -} - -QDebug operator<<(QDebug debug, const GeneratorEntry &entry) -{ - debug.nospace() << "Entry_" << entry.name - << " (" << entry.x << ", " << entry.y << ")" - << " [" << entry.width << " x " << entry.height << "]" - ; - return debug; -} - -// -void RegionMapGenerator::generate(QString mapName) { - // - int i = project->mapNames->indexOf(mapName); - //Map *map = project->loadMap(mapName); - qDebug() << "generating region map from:" << mapName; - search(i); - - populateSquares(); -} - -// use a progress bar because this is rather slow (because loadMap) -// TODO: use custom functions to load only necessary data from maps? -// need connections and dimensions -// maybe use gMapGroup0.numMaps as hint for size of progress -void RegionMapGenerator::bfs(int start) { - // - int size = project->mapNames->size(); - - //* - - QVector visited(size, false); - QList queue; - - visited[start] = true; - queue.append(start); - - while (!queue.isEmpty()) { - start = queue.first(); - - qDebug() << project->mapNames->at(start); - Map *map = project->loadMap(project->mapNames->at(start)); - - if (!map) break; - - this->entries.insert(map->location, { - map->name, 0, 0, map->getWidth() / square_block_width_, map->getHeight() / square_block_height_ - }); - - queue.removeFirst(); - - // get all connected map indexes - // if not visited, mark it visited and insert into queue - for (auto c : map->connections) { - int i = project->mapNames->indexOf(c->map_name); - if (!visited[i] && c->direction != "dive") { - visited[i] = true; - queue.append(i); - } - } - //delete map; - } - //*/ - qDebug() << "search complete";// << entries.keys(); - //return; -} - -// -void RegionMapGenerator::dfs(int start, QVector &visited) { - // - visited[start] = true; - - Map *map = project->loadMap(project->mapNames->at(start)); - //qDebug() << map->name; - this->entries.insert(map->location, { - map->name, 0, 0, map->getWidth() / square_block_width_, map->getHeight() / square_block_height_ - }); - - // place map on the grid? - - for (auto c : map->connections) { - int i = project->mapNames->indexOf(c->map_name); - if (!visited[i] && c->direction != "dive") { - dfs(i, visited); - } - } -} - -void RegionMapGenerator::search(int start) { - // - int size = project->mapNames->size(); - QVector visited(size, false); - - dfs(start, visited); -} - -void RegionMapGenerator::populateSquares() { - // - for (auto entry : entries.values()) { - qDebug() << entry;//.name << entry.width << "x" << entry.height; - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ui/regionmapeditor.cpp b/src/ui/regionmapeditor.cpp index 9efbf014..858abc82 100644 --- a/src/ui/regionmapeditor.cpp +++ b/src/ui/regionmapeditor.cpp @@ -1,13 +1,16 @@ #include "regionmapeditor.h" #include "ui_regionmapeditor.h" -#include "regionmapgenerator.h" +#include "imageexport.h" #include "config.h" +#include "log.h" #include #include #include +#include #include #include +#include #include #include #include @@ -19,7 +22,7 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project_) : this->ui->setupUi(this); this->project = project_; this->region_map = new RegionMap; - this->ui->action_RegionMap_Generate->setVisible(false); + this->ui->action_RegionMap_Resize->setVisible(false); } RegionMapEditor::~RegionMapEditor() @@ -56,8 +59,8 @@ void RegionMapEditor::setCurrentSquareOptions() { this->currIndex, this->ui->comboBox_RM_ConnectedMap->currentText(), this->ui->lineEdit_RM_MapName->text(), - this->ui->spinBox_RM_Options_x->value(), - this->ui->spinBox_RM_Options_y->value() + this->region_map->map_squares[this->currIndex].x, + this->region_map->map_squares[this->currIndex].y ); } } @@ -153,13 +156,6 @@ void RegionMapEditor::displayRegionMapLayoutOptions() { this->ui->frame_RM_Options->setEnabled(true); - this->ui->spinBox_RM_Options_x->setMaximum( - this->region_map->width() - this->region_map->padLeft - this->region_map->padRight - 1 - ); - this->ui->spinBox_RM_Options_y->setMaximum( - this->region_map->height() - this->region_map->padTop - this->region_map->padBottom - 1 - ); - updateRegionMapLayoutOptions(this->currIndex); // TODO: implement when the code is decompiled @@ -168,15 +164,9 @@ void RegionMapEditor::displayRegionMapLayoutOptions() { } void RegionMapEditor::updateRegionMapLayoutOptions(int index) { - this->ui->spinBox_RM_Options_x->blockSignals(true); - this->ui->spinBox_RM_Options_y->blockSignals(true); this->ui->comboBox_RM_ConnectedMap->blockSignals(true); this->ui->lineEdit_RM_MapName->setText(this->project->mapSecToMapHoverName->value(this->region_map->map_squares[index].mapsec)); this->ui->comboBox_RM_ConnectedMap->setCurrentText(this->region_map->map_squares[index].mapsec); - this->ui->spinBox_RM_Options_x->setValue(this->region_map->map_squares[index].x); - this->ui->spinBox_RM_Options_y->setValue(this->region_map->map_squares[index].y); - this->ui->spinBox_RM_Options_x->blockSignals(false); - this->ui->spinBox_RM_Options_y->blockSignals(false); this->ui->comboBox_RM_ConnectedMap->blockSignals(false); } @@ -355,9 +345,6 @@ void RegionMapEditor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, Reg item->select(event); //} else if (event->buttons() & Qt::MiddleButton) {// TODO } else { - item->paint(event); - this->region_map_layout_item->draw(); - this->hasUnsavedChanges = true; if (event->type() == QEvent::GraphicsSceneMouseRelease) { RegionMapHistoryItem *current = history.current(); bool addToHistory = !(current && current->tiles == this->region_map->getTiles()); @@ -367,6 +354,10 @@ void RegionMapEditor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, Reg ); history.push(commit); } + } else { + item->paint(event); + this->region_map_layout_item->draw(); + this->hasUnsavedChanges = true; } } } @@ -388,8 +379,6 @@ void RegionMapEditor::mouseEvent_city_map(QGraphicsSceneMouseEvent *event, CityM if (event->buttons() & Qt::RightButton) {// TODO //} else if (event->buttons() & Qt::MiddleButton) {// TODO } else { - item->paint(event); - this->hasUnsavedChanges = true; if (event->type() == QEvent::GraphicsSceneMouseRelease) { RegionMapHistoryItem *current = history.current(); bool addToHistory = !(current && current->tiles == this->city_map_item->getTiles()); @@ -399,6 +388,9 @@ void RegionMapEditor::mouseEvent_city_map(QGraphicsSceneMouseEvent *event, CityM ); history.push(commit); } + } else { + item->paint(event); + this->hasUnsavedChanges = true; } } } @@ -416,23 +408,9 @@ void RegionMapEditor::on_tabWidget_Region_Map_currentChanged(int index) { } } -void RegionMapEditor::on_spinBox_RM_Options_x_valueChanged(int x) { - int y = this->ui->spinBox_RM_Options_y->value(); - int red = this->region_map->getMapSquareIndex(x + this->region_map->padLeft, y + this->region_map->padTop); - this->region_map_layout_item->highlight(x, y, red); - this->hasUnsavedChanges = true; -} - -void RegionMapEditor::on_spinBox_RM_Options_y_valueChanged(int y) { - int x = this->ui->spinBox_RM_Options_x->value(); - int red = this->region_map->getMapSquareIndex(x + this->region_map->padLeft, y + this->region_map->padTop); - this->region_map_layout_item->highlight(x, y, red); - this->hasUnsavedChanges = true; -} - void RegionMapEditor::on_comboBox_RM_ConnectedMap_activated(const QString &mapsec) { this->ui->lineEdit_RM_MapName->setText(this->project->mapSecToMapHoverName->value(mapsec)); - //this->hasUnsavedChanges = true;// sometimes this is called for unknown reasons + this->hasUnsavedChanges = true;// sometimes this is called for unknown reasons } void RegionMapEditor::on_lineEdit_RM_MapName_textEdited(const QString &text) { @@ -441,6 +419,7 @@ void RegionMapEditor::on_lineEdit_RM_MapName_textEdited(const QString &text) { void RegionMapEditor::on_pushButton_RM_Options_delete_clicked() { this->region_map->resetSquare(this->region_map_layout_item->selectedTile); + updateRegionMapLayoutOptions(this->region_map_layout_item->selectedTile); this->region_map_layout_item->draw(); this->region_map_layout_item->select(this->region_map_layout_item->selectedTile); this->hasUnsavedChanges = true; @@ -526,6 +505,7 @@ void RegionMapEditor::undo() { this->resize(commit->mapWidth, commit->mapHeight); this->region_map->setTiles(commit->tiles); this->region_map_item->draw(); + this->region_map_layout_item->draw(); break; case RegionMapEditorBox::CityMapImage: if (commit->cityMap == this->city_map_item->file) @@ -551,6 +531,7 @@ void RegionMapEditor::redo() { this->resize(commit->mapWidth, commit->mapHeight); this->region_map->setTiles(commit->tiles); this->region_map_item->draw(); + this->region_map_layout_item->draw(); break; case RegionMapEditorBox::CityMapImage: this->city_map_item->setTiles(commit->tiles); @@ -634,6 +615,114 @@ void RegionMapEditor::on_action_RegionMap_ClearLayout_triggered() { } } +void RegionMapEditor::on_action_Import_RegionMap_ImageTiles_triggered() { + importTileImage(false); +} + +void RegionMapEditor::on_action_Import_CityMap_ImageTiles_triggered() { + importTileImage(true); +} + +void RegionMapEditor::importTileImage(bool city) { + QString descriptor = city ? "City Map" : "Region Map"; + + QString infilepath = QFileDialog::getOpenFileName(this, QString("Import %1 Tiles Image").arg(descriptor), + this->project->root, "Image Files (*.png *.bmp *.jpg *.dib)"); + if (infilepath.isEmpty()) { + return; + } + + logInfo(QString("Importing %1 Tiles from '%2'").arg(descriptor).arg(infilepath)); + + // Read image data from buffer so that the built-in QImage doesn't try to detect file format + // purely from the extension name. + QFile file(infilepath); + QImage image; + if (file.open(QIODevice::ReadOnly)) { + QByteArray imageData = file.readAll(); + image = QImage::fromData(imageData); + } else { + QString errorMessage = QString("Failed to open image file: '%1'").arg(infilepath); + logError(errorMessage); + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(errorMessage); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + if (image.width() == 0 || image.height() == 0 || image.width() % 8 != 0 || image.height() % 8 != 0) { + QString errorMessage = QString("The image dimensions (%1 x %2) are invalid. Width and height must be multiples of 8 pixels.") + .arg(image.width()) + .arg(image.height()); + logError(errorMessage); + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(errorMessage); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + + // Validate total number of tiles in image. + int numTilesWide = image.width() / 8; + int numTilesHigh = image.height() / 8; + int totalTiles = numTilesHigh * numTilesWide; + int maxAllowedTiles = 0x100; + if (totalTiles > maxAllowedTiles) { + QString errorMessage = QString("The total number of tiles in the provided image (%1) is greater than the allowed number (%2).") + .arg(maxAllowedTiles) + .arg(totalTiles); + logError(errorMessage); + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(errorMessage); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + + // Validate the image's palette. + QString palMessage = QString(); + bool palError = false; + if (image.colorCount() == 0) { + palMessage = QString("The provided image is not indexed."); + palError = true; + } else if (!city && image.colorCount() != 256) { + palMessage = QString("The provided image has a palette with %1 colors. You must provide an indexed imaged with a 256 color palette.").arg(image.colorCount()); + palError = true; + } else if (city && image.colorCount() != 16) { + palMessage = QString("The provided image has a palette with %1 colors. You must provide an indexed imaged with a 16 color palette.").arg(image.colorCount()); + palError = true; + } + + if (palError) { + logError(palMessage); + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(palMessage); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + + // Use the image from the correct path. + if (city) { + this->region_map->setTemporaryCityTilesPath(infilepath); + } else { + this->region_map->setTemporaryPngPath(infilepath); + } + this->hasUnsavedChanges = true; + + // Redload and redraw images. + displayRegionMap(); + displayCityMap(this->ui->comboBox_CityMap_picker->currentText()); +} + void RegionMapEditor::on_comboBox_CityMap_picker_currentTextChanged(const QString &file) { this->displayCityMap(file); this->cityMapFirstDraw = true; @@ -716,9 +805,3 @@ void RegionMapEditor::on_verticalSlider_Zoom_City_Tiles_valueChanged(int val) { ui->graphicsView_City_Map_Tiles->setMatrix(matrix); ui->graphicsView_City_Map_Tiles->setFixedSize(width + 2, height + 2); } - -void RegionMapEditor::on_action_RegionMap_Generate_triggered() { - RegionMapGenerator generator(this->project); - generator.generate("LittlerootTown"); - this->hasUnsavedChanges = true; -} diff --git a/src/ui/regionmappixmapitem.cpp b/src/ui/regionmappixmapitem.cpp index 5488ca4c..3ca04b06 100644 --- a/src/ui/regionmappixmapitem.cpp +++ b/src/ui/regionmappixmapitem.cpp @@ -20,14 +20,11 @@ void RegionMapPixmapItem::draw() { void RegionMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { if (region_map) { - if (event->type() == QEvent::GraphicsSceneMousePress) { - } else { - QPointF pos = event->pos(); - int x = static_cast(pos.x()) / 8; - int y = static_cast(pos.y()) / 8; - int index = x + y * region_map->width(); - this->region_map->map_squares[index].tile_img_id = this->tile_selector->selectedTile; - } + QPointF pos = event->pos(); + int x = static_cast(pos.x()) / 8; + int y = static_cast(pos.y()) / 8; + int index = x + y * region_map->width(); + this->region_map->map_squares[index].tile_img_id = this->tile_selector->selectedTile; draw(); } }