File indexing completed on 2025-02-16 06:57:54
0001 /* 0002 SPDX-FileCopyrightText: 2003 Russell Steffen <rsteffen@bayarea.net> 0003 SPDX-FileCopyrightText: 2003 Stephan Zehetner <s.zehetner@nevox.org> 0004 SPDX-FileCopyrightText: 2006 Dmitry Suzdalev <dimsuz@gmail.com> 0005 SPDX-FileCopyrightText: 2006 Inge Wallin <inge@lysator.liu.se> 0006 SPDX-FileCopyrightText: 2006 Pierre Ducroquet <pinaraf@gmail.com> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "mapscene.h" 0012 0013 #include <QGraphicsItem> 0014 #include <QPainter> 0015 0016 #include "map.h" 0017 #include "mapitems.h" 0018 #include "../sector.h" 0019 #include "../images.h" 0020 #include "../game.h" 0021 #include "../planet.h" 0022 0023 0024 MapScene::MapScene (Game *game) 0025 : QGraphicsScene(game), 0026 m_game(game), 0027 m_selectedPlanetItem(nullptr), 0028 m_planetInfoItem(nullptr), 0029 m_width(width()), 0030 m_height(height()) 0031 { 0032 m_renderer = new QSvgRenderer(IMAGES_SVG); 0033 m_imageCache = new KImageCache(QStringLiteral("konquest-pixmaps"), 100000); 0034 } 0035 0036 0037 MapScene::~MapScene () 0038 { 0039 delete m_imageCache; 0040 delete m_renderer; 0041 } 0042 0043 0044 void 0045 MapScene::resizeScene(const QRectF& rect) 0046 { 0047 m_width = rect.width(); 0048 m_height = rect.height(); 0049 0050 setSceneRect(rect); 0051 } 0052 0053 0054 void 0055 MapScene::selectPlanet(Planet *planet) 0056 { 0057 unselectPlanet(); 0058 for (PlanetItem *item : std::as_const(m_planetItems)) { 0059 if (item->sector() == planet->sector()) { 0060 item->select(); 0061 m_selectedPlanetItem = item; 0062 break; 0063 } 0064 } 0065 } 0066 0067 0068 void 0069 MapScene::clearMap() 0070 { 0071 QGraphicsItem *item; 0072 while (items().count() > 0) { 0073 item = items()[0]; 0074 removeItem(item); 0075 delete item; 0076 } 0077 m_planetItems.clear(); 0078 m_planetInfoItem = nullptr; 0079 m_selectedPlanetItem = nullptr; 0080 } 0081 0082 0083 void 0084 MapScene::mapUpdate() 0085 { 0086 Sector *sector; 0087 0088 clearMap(); 0089 if(m_game->isRunning()) { 0090 for (int i = 0 ; i < map()->rows() ; i++) { 0091 for (int j = 0 ; j < map()->columns() ; j++) { 0092 sector = map()->sector(Coordinate(j, i)); 0093 if (sector->hasPlanet()) { 0094 PlanetItem *item = new PlanetItem(this, sector, m_game); 0095 connect(item, &PlanetItem::planetItemSelected, this, &MapScene::planetItemSelected); 0096 item->setZValue(1.0); 0097 addItem(item); 0098 m_planetItems.append(item); 0099 } 0100 } 0101 } 0102 } 0103 } 0104 0105 0106 void 0107 MapScene::unselectPlanet() 0108 { 0109 if (m_selectedPlanetItem) { 0110 m_selectedPlanetItem->unselect(); 0111 m_selectedPlanetItem = nullptr; 0112 } 0113 } 0114 0115 0116 void 0117 MapScene::planetItemSelected (PlanetItem *item) 0118 { 0119 if (m_selectedPlanetItem) 0120 unselectPlanet(); 0121 m_selectedPlanetItem = item; 0122 0123 Q_EMIT planetSelected(item->sector()->planet()); 0124 } 0125 0126 0127 void 0128 MapScene::drawBackground ( QPainter * painter, const QRectF & /*rect*/ ) 0129 { 0130 qreal sectorSize = getSectorSize(); 0131 qreal horizontalOffset = itemsHorizontalOffset(); 0132 qreal verticalOffset = itemsVerticalOffset(); 0133 0134 qreal mapWidth = map()->columns()*sectorSize; 0135 qreal mapHeight = map()->rows()*sectorSize; 0136 0137 QPen pen = painter->pen(); 0138 pen.setColor(Qt::black); 0139 pen.setWidth(1); 0140 pen.setStyle(Qt::SolidLine); 0141 painter->setPen(pen); 0142 painter->fillRect(0, 0, m_width, m_height, Qt::black); 0143 m_renderer->render(painter, QStringLiteral("background"), QRectF(0, 0, m_width, m_height)); 0144 0145 m_renderer->render(painter, QStringLiteral("screen"), QRectF(horizontalOffset, verticalOffset, mapWidth, mapHeight)); 0146 painter->setOpacity(0.5); 0147 qreal lastLine = mapWidth + horizontalOffset; 0148 for (qreal i = horizontalOffset ; i <= lastLine ; i += sectorSize) { 0149 painter->drawLine(QPointF(i, verticalOffset), QPointF(i, mapHeight + verticalOffset)); 0150 } 0151 lastLine = mapHeight + verticalOffset; 0152 for (qreal j = verticalOffset ; j <= lastLine ; j += sectorSize) { 0153 painter->drawLine(QPointF(horizontalOffset, j), QPointF(mapWidth + horizontalOffset, j)); 0154 } 0155 } 0156 0157 0158 void 0159 MapScene::displayPlanetInfo(Planet *planet) 0160 { 0161 if (!planet) { 0162 if (m_planetInfoItem) { 0163 m_planetInfoItem->hide(); 0164 } 0165 0166 return; 0167 } 0168 0169 /** 0170 * @todo Figure out why coord.y and coord.x seem to be used the other way 0171 * around. 0172 */ 0173 0174 QPointF pos( 0175 planet->sector()->coord().y() * getSectorSize() + itemsHorizontalOffset(), 0176 planet->sector()->coord().x() * getSectorSize() + itemsVerticalOffset() 0177 ); 0178 0179 displayPlanetInfo(planet, pos); 0180 } 0181 0182 0183 void 0184 MapScene::displayPlanetInfo (Planet *planet, const QPointF &pos) 0185 { 0186 if (!planet) { 0187 if (m_planetInfoItem) { 0188 m_planetInfoItem->hide(); 0189 } 0190 0191 return; 0192 } 0193 0194 if (!m_planetInfoItem) { 0195 m_planetInfoItem = new PlanetInfoItem(m_game); 0196 addItem(m_planetInfoItem); 0197 } 0198 0199 m_planetInfoItem->show(); 0200 m_planetInfoItem->setPlanet(planet); 0201 m_planetInfoItem->setZValue(1.5); 0202 m_planetInfoItem->moveBy( 0203 pos.x() - m_planetInfoItem->x(), 0204 pos.y() - m_planetInfoItem->y() 0205 ); 0206 0207 // Move to stay in the game field. 0208 0209 if (pos.x() > m_width / 2) { 0210 m_planetInfoItem->moveBy(-m_planetInfoItem->boundingRect().width(), 0); 0211 } 0212 0213 if (pos.y() > m_height / 2) { 0214 m_planetInfoItem->moveBy(0, -m_planetInfoItem->boundingRect().height()); 0215 } 0216 0217 update(); 0218 } 0219 0220 0221 qreal 0222 MapScene::getSectorSize() 0223 { 0224 qreal s_w = m_width / map()->columns(); 0225 qreal s_h = m_height / map()->rows(); 0226 0227 return qMin(s_w, s_h); 0228 } 0229 0230 0231 qreal 0232 MapScene::itemsHorizontalOffset() 0233 { 0234 return (m_width - map()->columns() * getSectorSize()) / 2; 0235 } 0236 0237 0238 qreal 0239 MapScene::itemsVerticalOffset() 0240 { 0241 return (m_height - map()->rows() * getSectorSize()) / 2; 0242 } 0243 0244 #include "moc_mapscene.cpp"