def copySelection(self, mapDocument): currentLayer = mapDocument.currentLayer() if (not currentLayer): return map = mapDocument.map() selectedArea = mapDocument.selectedArea() selectedObjects = mapDocument.selectedObjects() tileLayer = currentLayer copyLayer = None if (not selectedArea.isEmpty() and type(tileLayer)==TileLayer): # Copy the selected part of the layer copyLayer = tileLayer.copy(selectedArea.translated(-tileLayer.x(), -tileLayer.y())) elif (not selectedObjects.isEmpty()): # Create a new object group with clones of the selected objects objectGroup = ObjectGroup() for mapObject in selectedObjects: objectGroup.addObject(mapObject.clone()) copyLayer = objectGroup else: return # Create a temporary map to write to the clipboard copyMap = Map(map.orientation(), copyLayer.width(), copyLayer.height(), map.tileWidth(), map.tileHeight()) copyMap.setRenderOrder(map.renderOrder()) # Resolve the set of tilesets used by this layer for tileset in copyLayer.usedTilesets(): copyMap.addTileset(tileset) copyMap.addLayer(copyLayer) self.setMap(copyMap)
def setCurrentTiles(self, tiles): if (self.mCurrentTiles == tiles): return del self.mCurrentTiles self.mCurrentTiles = tiles # Set the selected tiles on the map document if (tiles): selectedTiles = QList() for y in range(tiles.height()): for x in range(tiles.width()): cell = tiles.cellAt(x, y) if (not cell.isEmpty()): selectedTiles.append(cell.tile) self.mMapDocument.setSelectedTiles(selectedTiles) # Create a tile stamp with these tiles map = self.mMapDocument.map() stamp = Map(map.orientation(), tiles.width(), tiles.height(), map.tileWidth(), map.tileHeight()) stamp.addLayer(tiles.clone()) stamp.addTilesets(tiles.usedTilesets()) self.mEmittingStampCaptured = True self.stampCaptured.emit(TileStamp(stamp)) self.mEmittingStampCaptured = False
def read(self, fileName): uncompressed = QByteArray() # Read data f = QFile(fileName) if (f.open(QIODevice.ReadOnly)): compressed = f.readAll() f.close() uncompressed, length = decompress(compressed, 48 * 48) # Check the data if (uncompressed.count() != 48 * 48): self.mError = self.tr("This is not a valid Droidcraft map file!") return None uncompressed = uncompressed.data() # Build 48 x 48 map # Create a Map -> Create a Tileset -> Add Tileset to map # -> Create a TileLayer -> Fill layer -> Add TileLayer to Map map = Map(Map.Orientation.Orthogonal, 48, 48, 32, 32) mapTileset = Tileset.create("tileset", 32, 32) mapTileset.loadFromImage(QImage(":/tileset.png"), "tileset.png") map.addTileset(mapTileset) # Fill layer mapLayer = TileLayer("map", 0, 0, 48, 48) # Load for i in range(0, 48 * 48): tileFile = int(uncompressed[i]) & 0xff y = int(i / 48) x = i - (48 * y) tile = mapTileset.tileAt(tileFile) mapLayer.setCell(x, y, Cell(tile)) map.addLayer(mapLayer) return map
def read(self, fileName): uncompressed = QByteArray() # Read data f = QFile(fileName) if (f.open(QIODevice.ReadOnly)) : compressed = f.readAll() f.close() uncompressed, length = decompress(compressed, 48 * 48) # Check the data if (uncompressed.count() != 48 * 48) : self.mError = self.tr("This is not a valid Droidcraft map file!") return None uncompressed = uncompressed.data() # Build 48 x 48 map # Create a Map -> Create a Tileset -> Add Tileset to map # -> Create a TileLayer -> Fill layer -> Add TileLayer to Map map = Map(Map.Orientation.Orthogonal, 48, 48, 32, 32) mapTileset = Tileset.create("tileset", 32, 32) mapTileset.loadFromImage(QImage(":/tileset.png"), "tileset.png") map.addTileset(mapTileset) # Fill layer mapLayer = TileLayer("map", 0, 0, 48, 48) # Load for i in range(0, 48 * 48): tileFile = int(uncompressed[i])&0xff y = int(i / 48) x = i - (48 * y) tile = mapTileset.tileAt(tileFile) mapLayer.setCell(x, y, Cell(tile)) map.addLayer(mapLayer) return map
def endCapture(self): if (self.mBrushBehavior != BrushBehavior.Capture): return self.mBrushBehavior = BrushBehavior.Free tileLayer = self.currentTileLayer() # Intersect with the layer and translate to layer coordinates captured = self.capturedArea() captured &= QRect(tileLayer.x(), tileLayer.y(), tileLayer.width(), tileLayer.height()) if (captured.isValid()): captured.translate(-tileLayer.x(), -tileLayer.y()) map = tileLayer.map() capture = tileLayer.copy(captured) stamp = Map(map.orientation(), capture.width(), capture.height(), map.tileWidth(), map.tileHeight()) # Add tileset references to map for tileset in capture.usedTilesets(): stamp.addTileset(tileset) stamp.addLayer(capture) self.stampCaptured.emit(TileStamp(stamp)) else: self.updatePreview()
def copySelection(self, mapDocument): currentLayer = mapDocument.currentLayer() if (not currentLayer): return map = mapDocument.map() selectedArea = mapDocument.selectedArea() selectedObjects = mapDocument.selectedObjects() tileLayer = currentLayer copyLayer = None if (not selectedArea.isEmpty() and type(tileLayer) == TileLayer): # Copy the selected part of the layer copyLayer = tileLayer.copy( selectedArea.translated(-tileLayer.x(), -tileLayer.y())) elif (not selectedObjects.isEmpty()): # Create a new object group with clones of the selected objects objectGroup = ObjectGroup() for mapObject in selectedObjects: objectGroup.addObject(mapObject.clone()) copyLayer = objectGroup else: return # Create a temporary map to write to the clipboard copyMap = Map(map.orientation(), copyLayer.width(), copyLayer.height(), map.tileWidth(), map.tileHeight()) copyMap.setRenderOrder(map.renderOrder()) # Resolve the set of tilesets used by this layer for tileset in copyLayer.usedTilesets(): copyMap.addTileset(tileset) copyMap.addLayer(copyLayer) self.setMap(copyMap)
def toMap(self, variant, mapDir): self.mGidMapper.clear() self.mMapDir = mapDir variantMap = variant orientationString = variantMap.get("orientation", '') orientation = orientationFromString(orientationString) if (orientation == Map.Orientation.Unknown): self.mError = self.tr("Unsupported map orientation: \"%s\""%orientationString) return None staggerAxisString = variantMap.get("staggeraxis", '') staggerAxis = staggerAxisFromString(staggerAxisString) staggerIndexString = variantMap.get("staggerindex", '') staggerIndex = staggerIndexFromString(staggerIndexString) renderOrderString = variantMap.get("renderorder", '') renderOrder = renderOrderFromString(renderOrderString) nextObjectId = variantMap.get("nextobjectid", 0) map = Map(orientation, variantMap.get("width",0), variantMap.get("height",0), variantMap.get("tilewidth",0), variantMap.get("tileheight",0)) map.setHexSideLength(variantMap.get("hexsidelength", 0)) map.setStaggerAxis(staggerAxis) map.setStaggerIndex(staggerIndex) map.setRenderOrder(renderOrder) if (nextObjectId): map.setNextObjectId(nextObjectId) self.mMap = map map.setProperties(self.toProperties(variantMap.get("properties", {}))) bgColor = variantMap.get("backgroundcolor", '') if (bgColor!='' and QColor.isValidColor(bgColor)): map.setBackgroundColor(QColor(bgColor)) for tilesetVariant in variantMap.get("tilesets", []): tileset = self.__toTileset(tilesetVariant) if not tileset: return None map.addTileset(tileset) for layerVariant in variantMap.get("layers", []): layer = self.toLayer(layerVariant) if not layer: return None map.addLayer(layer) return map
def toMap(self, variant, mapDir): self.mGidMapper.clear() self.mMapDir = mapDir variantMap = variant orientationString = variantMap.get("orientation", '') orientation = orientationFromString(orientationString) if (orientation == Map.Orientation.Unknown): self.mError = self.tr("Unsupported map orientation: \"%s\"" % orientationString) return None staggerAxisString = variantMap.get("staggeraxis", '') staggerAxis = staggerAxisFromString(staggerAxisString) staggerIndexString = variantMap.get("staggerindex", '') staggerIndex = staggerIndexFromString(staggerIndexString) renderOrderString = variantMap.get("renderorder", '') renderOrder = renderOrderFromString(renderOrderString) nextObjectId = variantMap.get("nextobjectid", 0) map = Map(orientation, variantMap.get("width", 0), variantMap.get("height", 0), variantMap.get("tilewidth", 0), variantMap.get("tileheight", 0)) map.setHexSideLength(variantMap.get("hexsidelength", 0)) map.setStaggerAxis(staggerAxis) map.setStaggerIndex(staggerIndex) map.setRenderOrder(renderOrder) if (nextObjectId): map.setNextObjectId(nextObjectId) self.mMap = map map.setProperties(self.toProperties(variantMap.get("properties", {}))) bgColor = variantMap.get("backgroundcolor", '') if (bgColor != '' and QColor.isValidColor(bgColor)): map.setBackgroundColor(QColor(bgColor)) for tilesetVariant in variantMap.get("tilesets", []): tileset = self.__toTileset(tilesetVariant) if not tileset: return None map.addTileset(tileset) for layerVariant in variantMap.get("layers", []): layer = self.toLayer(layerVariant) if not layer: return None map.addLayer(layer) return map
def createMap(self): if (self.exec() != QDialog.Accepted): return None mapWidth = self.mUi.mapWidth.value() mapHeight = self.mUi.mapHeight.value() tileWidth = self.mUi.tileWidth.value() tileHeight = self.mUi.tileHeight.value() orientationIndex = self.mUi.orientation.currentIndex() orientationData = self.mUi.orientation.itemData(orientationIndex) orientation = orientationData layerFormat = Map.LayerDataFormat(self.mUi.layerFormat.currentIndex()) renderOrder = Map.RenderOrder(self.mUi.renderOrder.currentIndex()) map = Map(orientation, mapWidth, mapHeight, tileWidth, tileHeight) map.setLayerDataFormat(layerFormat) map.setRenderOrder(renderOrder) gigabyte = 1073741824 memory = mapWidth * mapHeight * 8#sizeof(Cell) # Add a tile layer to new maps of reasonable size if (memory < gigabyte): map.addLayer(TileLayer(self.tr("Tile Layer 1"), 0, 0, mapWidth, mapHeight)) else: gigabytes = memory / gigabyte QMessageBox.warning(self, self.tr("Memory Usage Warning"), self.tr("Tile layers for this map will consume %.2f GB " "of memory each. Not creating one by default."%gigabytes)) # Store settings for next time prefs = preferences.Preferences.instance() prefs.setLayerDataFormat(layerFormat) prefs.setMapRenderOrder(renderOrder) s = preferences.Preferences.instance().settings() s.setValue(ORIENTATION_KEY, orientationIndex) s.setValue(MAP_WIDTH_KEY, mapWidth) s.setValue(MAP_HEIGHT_KEY, mapHeight) s.setValue(TILE_WIDTH_KEY, tileWidth) s.setValue(TILE_HEIGHT_KEY, tileHeight) return MapDocument(map)
def stampFromContext(selectedTool): stamp = TileStamp() stampBrush = dynamic_cast(selectedTool, StampBrush) if stampBrush: # take the stamp from the stamp brush stamp = stampBrush.stamp() else: fillTool = dynamic_cast(selectedTool, BucketFillTool) if fillTool: # take the stamp from the fill tool stamp = fillTool.stamp() else: mapDocument = DocumentManager.instance().currentDocument() if mapDocument: # try making a stamp from the current tile selection tileLayer = dynamic_cast(mapDocument.currentLayer(), TileLayer) if (not tileLayer): return stamp selection = mapDocument.selectedArea() if (selection.isEmpty()): return stamp selection.translate(-tileLayer.position()) copy = tileLayer.copy(selection) if (copy.size().isEmpty()): return stamp map = mapDocument.map() copyMap = Map(map.orientation(), copy.width(), copy.height(), map.tileWidth(), map.tileHeight()) # Add tileset references to map for tileset in copy.usedTilesets(): copyMap.addTileset(tileset) copyMap.setRenderOrder(map.renderOrder()) copyMap.addLayer(copy.take()) stamp.addVariation(copyMap) return stamp
def setTile(self, tile): if type(tile) == list: tile = tile[0] if (self.mTile == tile): return self.mTile = tile self.mMapScene.disableSelectedTool() previousDocument = self.mMapScene.mapDocument() if (tile): self.mMapView.setEnabled(not self.mTile.tileset().isExternal()) map = Map(Map.Orientation.Orthogonal, 1, 1, tile.width(), tile.height()) map.addTileset(tile.sharedTileset()) tileLayer = TileLayer(QString(), 0, 0, 1, 1) tileLayer.setCell(0, 0, Cell(tile)) map.addLayer(tileLayer) objectGroup = None if (tile.objectGroup()): objectGroup = tile.objectGroup().clone() else: objectGroup = ObjectGroup() objectGroup.setDrawOrder(ObjectGroup.DrawOrder.IndexOrder) map.addLayer(objectGroup) mapDocument = MapDocument(map) self.mMapScene.setMapDocument(mapDocument) self.mToolManager.setMapDocument(mapDocument) mapDocument.setCurrentLayerIndex(1) self.mMapScene.enableSelectedTool() mapDocument.undoStack().indexChanged.connect(self.applyChanges) else: self.mMapView.setEnabled(False) self.mMapScene.setMapDocument(None) self.mToolManager.setMapDocument(None) if (previousDocument): previousDocument.undoStack().disconnect() del previousDocument
def setTile(self, tile): if type(tile)==list: tile = tile[0] if (self.mTile == tile): return self.mTile = tile self.mMapScene.disableSelectedTool() previousDocument = self.mMapScene.mapDocument() if (tile): self.mMapView.setEnabled(not self.mTile.tileset().isExternal()) map = Map(Map.Orientation.Orthogonal, 1, 1, tile.width(), tile.height()) map.addTileset(tile.sharedTileset()) tileLayer = TileLayer(QString(), 0, 0, 1, 1) tileLayer.setCell(0, 0, Cell(tile)) map.addLayer(tileLayer) objectGroup = None if (tile.objectGroup()): objectGroup = tile.objectGroup().clone() else: objectGroup = ObjectGroup() objectGroup.setDrawOrder(ObjectGroup.DrawOrder.IndexOrder) map.addLayer(objectGroup) mapDocument = MapDocument(map) self.mMapScene.setMapDocument(mapDocument) self.mToolManager.setMapDocument(mapDocument) mapDocument.setCurrentLayerIndex(1) self.mMapScene.enableSelectedTool() mapDocument.undoStack().indexChanged.connect(self.applyChanges) else: self.mMapView.setEnabled(False) self.mMapScene.setMapDocument(None) self.mToolManager.setMapDocument(None) if (previousDocument): previousDocument.undoStack().disconnect() del previousDocument
class Scene(engine.Module): """Główny ekran gry.""" def __init__(self, _engine): super(Scene, self).__init__(_engine) self._background = pygame.Surface((self._resx, self._resy)) self.surface = self._background.copy() self._actual = [] self._client = _engine.options['client'] = sock.BomberFactory(self._process, self._connectionError) from twisted.internet import reactor from twisted.internet.task import LoopingCall self._gameloop = LoopingCall(self._render) self._network = reactor.connectTCP(_engine.options['host'], _engine.options['port'], self._client) self._play = True self._refresh = True self._submodules = () self._map = None self._playerID = None def __del__(self): self._network.disconnect() def _loadMap(self, _width, _height): self._map = Map(self._engine, self, (_width, _height)) self._heroLayer = ObjectsLayer(self._map) # Warstwa graczy self._mineLayer = ObjectsLayer(self._map) # Warstwa min self._map.addLayer('Hero', 3, self._heroLayer) self._map.addLayer('Mine', 2, self._mineLayer) self._submodules = (self._map,) def isPlaying(self): """Czy gracz nadal gra?""" return self._play def screenUpdated(self): """Aktualizuje obrazy tła i submoduły.""" super(Scene, self).screenUpdated() self._refresh = True self._background = pygame.Surface((self._resx, self._resy)) self.surface = pygame.transform.smoothscale(self.surface, (self._resx, self._resy)) for submodule in self._submodules: submodule.screenUpdated() def show(self): if not self._play: self._engine.previousModule() return self._last = time.time() from twisted.internet import reactor self._gameloop.start(self._engine.getFPS() and 1.0 / self._engine.getFPS() or 0.0) reactor.run() self._gameloop.stop() def _render(self): self._engine.tick() for event in self._engine.events(): if event.type == QUIT: self._play = False elif event.type == KEYDOWN: if event.key == K_ESCAPE: self._engine.runLoop = False from twisted.internet import reactor reactor.stop() return if self._map: if event.key in (K_w, K_UP): self._client.sendAction('u') self._last = time.time() elif event.key in (K_s, K_DOWN): self._client.sendAction('d') self._last = time.time() elif event.key in (K_a, K_LEFT): self._client.sendAction('l') self._last = time.time() elif event.key in (K_d, K_RIGHT): self._client.sendAction('r') self._last = time.time() elif event.key in (K_RETURN, K_RCTRL, K_LCTRL): self._client.sendAction('c') self._last = time.time() elif event.key == K_q: self._client.sendAction('e') self._last = time.time() if self._map and self._last + 1./self._engine.options['fps'] < time.time(): self._client.sendAction('m') self._last = time.time() if not self._map and self._playerID == None: self.surface = self._background.copy() utils.drawText(self.surface, 'Oczekiwanie na graczy!', 20, (255, 255, 255), (self._resx / 2, self._resy / 2)) updated = [] if self._play: for submodule in self._submodules: updated.extend(submodule.update()) submodule.draw(self.surface) if self._refresh: self._engine.show(self.surface) self._refresh = False else: self._engine.show(self.surface, updated) if not self._play: time.sleep(5) self._engine.runLoop = False from twisted.internet import reactor reactor.stop() return def _process(self, obj): if isinstance(obj, protocolObjects.Countdown): return self._countdown(obj) if isinstance(obj, protocolObjects.Result): return self._finish(obj) if isinstance(obj, protocolObjects.Map): return self._update(obj) return self._connectionError(obj) def _connectionError(self, msg): self._play = False utils.drawText(self.surface, str(msg), 10, (255, 255, 255), (self._resx / 2, self._resy - 10)) def _countdown(self, countdown): if not self._map and countdown.number == 1: self._loadMap(countdown.mapSize.x, countdown.mapSize.y) if self._playerID == None: self._playerID = countdown.playerId self.surface = self._background.copy() utils.drawText(self.surface, 'Gracz %d. >%d<' % (countdown.playerId, countdown.number), 30, (255, 255, 255), (self._resx / 2, self._resy / 2)) def _finish(self, result): self.surface = self._background.copy() utils.drawText(self.surface, 'Gra zakonczona!', 40, (255, 255, 255), (self._resx / 2, self._resy / 2)) if len(result.winners) == 1: utils.drawText(self.surface, 'Wygral gracz %d!' % result.winners[0], 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) elif len(result.winners): utils.drawText(self.surface, 'Wygrali gracze %s!' % (', '.join([str(i) for i in result.winners])), 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) self._play = False self._engine.show(self.surface) def _update(self, map): if not self._map: self._play = False return for mine in map.mines: _id = mine.position.x, mine.position.y if not self._mineLayer.get(_id): _mine = ObjectsLayer.Sprite(utils.loadImage('gfx/bomb.png', alpha = True)) self._mineLayer.add(_id, _mine) self._mineLayer.move(_id, _id) for _id, player in enumerate(map.playersPositions): if not self._heroLayer.get(_id): self._heroLayer.add(_id, ObjectsLayer.Sprite(utils.loadImage('gfx/hero/n.png', alpha = True))) _hero = self._heroLayer.get(_id) _pos = _hero.getPos() self._heroLayer.move(_id, (player.x, player.y)) _newpos = _hero.getPos() if _pos[0] > _newpos[0]: _hero.changeImage(utils.loadImage('gfx/hero/w.png', alpha = True)) if _pos[0] < _newpos[0]: _hero.changeImage(utils.loadImage('gfx/hero/e.png', alpha = True)) if _pos[1] > _newpos[1]: _hero.changeImage(utils.loadImage('gfx/hero/n.png', alpha = True)) if _pos[1] < _newpos[1]: _hero.changeImage(utils.loadImage('gfx/hero/s.png', alpha = True)) if _id == self._playerID: _, _, w, h = self._map.getRectangle() self._map.setShift((w / 2 - _newpos[0], h / 2 - _newpos[1]))
class Scene(engine.Module): """Główny ekran gry.""" def __init__(self, _engine): super(Scene, self).__init__(_engine) self._background = pygame.Surface((self._resx, self._resy)) self.surface = self._background.copy() self._actual = [] self._client = _engine.options['client'] = sock.Client( _engine.options['host'], _engine.options['port']) self._play = True self._refresh = True self._submodules = () self._map = None self._playerID = None def _loadMap(self, _width, _height): self._map = Map(self._engine, self, (_width, _height)) self._heroLayer = ObjectsLayer(self._map) # Warstwa graczy self._mineLayer = ObjectsLayer(self._map) # Warstwa min self._map.addLayer('Hero', 3, self._heroLayer) self._map.addLayer('Mine', 2, self._mineLayer) self._submodules = (self._map, ) def isPlaying(self): """Czy gracz nadal gra?""" return self._play def screenUpdated(self): """Aktualizuje obrazy tła i submoduły.""" super(Scene, self).screenUpdated() self._refresh = True self._background = pygame.Surface((self._resx, self._resy)) self.surface = pygame.transform.smoothscale(self.surface, (self._resx, self._resy)) for submodule in self._submodules: submodule.screenUpdated() def show(self): if not self._play: self._engine.previousModule() return try: self._last = time.time() while self._engine.tick(): _upd = self._client.update(.5 / self._engine.options['fps']) if self._play and _upd != True: utils.drawText(self.surface, _upd, 20, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._play = False self._engine.show(self.surface) time.sleep(5) self._engine.previousModule() raise SceneQuit() if self._client.countdown: if not self._map: self._loadMap(self._client.countdown.mapSize.x, self._client.countdown.mapSize.y) if self._playerID == None: self._playerID = self._client.countdown.playerId self.surface = self._background.copy() utils.drawText( self.surface, 'Gracz %d. >%d<' % (self._client.countdown.playerId, self._client.countdown.number), 30, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._engine.show(self.surface) continue if self._client.result: utils.drawText(self.surface, 'Gra zakonczona!', 40, (255, 255, 255), (self._resx / 2, self._resy / 2)) if len(self._client.result.winners) == 1: utils.drawText( self.surface, 'Wygral gracz %d!' % self._client.result.winners[0], 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) elif len(self._client.result.winners): utils.drawText( self.surface, 'Wygrali gracze %s!' % (', '.join( [str(i) for i in self._client.result.winners])), 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) self._play = False self._engine.show(self.surface) time.sleep(10) self._engine.previousModule() raise SceneQuit() if self._client.map: if not self._map: self._engine.previousModule() self._play = False raise SceneQuit() for mine in self._client.map.mines: _id = mine.position.x, mine.position.y if not self._mineLayer.get(_id): _mine = ObjectsLayer.Sprite( utils.loadImage('data/gfx/bomb.png', alpha=True)) self._mineLayer.add(_id, _mine) self._mineLayer.move(_id, _id) for _id, player in enumerate( self._client.map.playersPositions): if not self._heroLayer.get(_id): self._heroLayer.add( _id, ObjectsLayer.Sprite( utils.loadImage('data/gfx/hero/n.png', alpha=True))) _hero = self._heroLayer.get(_id) _pos = _hero.getPos() self._heroLayer.move(_id, (player.x, player.y)) _newpos = _hero.getPos() if _pos[0] > _newpos[0]: _hero.changeImage( utils.loadImage('data/gfx/hero/w.png', alpha=True)) if _pos[0] < _newpos[0]: _hero.changeImage( utils.loadImage('data/gfx/hero/e.png', alpha=True)) if _pos[1] > _newpos[1]: _hero.changeImage( utils.loadImage('data/gfx/hero/n.png', alpha=True)) if _pos[1] < _newpos[1]: _hero.changeImage( utils.loadImage('data/gfx/hero/s.png', alpha=True)) if _id == self._playerID: _, _, w, h = self._map.getRectangle() self._map.setShift( (w / 2 - _newpos[0], h / 2 - _newpos[1])) for event in self._engine.events(): if event.type == QUIT: raise engine.EngineQuit() if event.type == KEYDOWN: if event.key == K_ESCAPE: self._engine.previousModule() raise SceneQuit() if event.key in (K_w, K_UP): self._client.sendAction('u') self._last = time.time() elif event.key in (K_s, K_DOWN): self._client.sendAction('d') self._last = time.time() elif event.key in (K_a, K_LEFT): self._client.sendAction('l') self._last = time.time() elif event.key in (K_d, K_RIGHT): self._client.sendAction('r') self._last = time.time() elif event.key in (K_RETURN, K_RCTRL, K_LCTRL): self._client.sendAction('c') self._last = time.time() elif event.key == K_q: self._client.sendAction('e') self._last = time.time() if self._last + 1. / self._engine.options['fps'] < time.time(): self._client.sendAction('m') self._last = time.time() self.surface = self._background.copy() if not self._map: utils.drawText(self.surface, 'Oczekiwanie na graczy!', 20, (255, 255, 255), (self._resx / 2, self._resy / 2)) updated = [] for submodule in self._submodules: updated.extend(submodule.update()) submodule.draw(self.surface) if self._refresh: self._engine.show(self.surface) self._refresh = False else: self._engine.show(self.surface, updated) except SceneQuit: pass
class Scene(engine.Module): """Główny ekran gry.""" def __init__(self, _engine): super(Scene, self).__init__(_engine) self._background = pygame.Surface((self._resx, self._resy)) self.surface = self._background.copy() self._actual = [] self._client = _engine.options['client'] = sock.Client(_engine.options['host'], _engine.options['port']) self._play = True self._refresh = True self._submodules = () self._map = None self._playerID = None def _loadMap(self, _width, _height): self._map = Map(self._engine, self, (_width, _height)) self._heroLayer = ObjectsLayer(self._map) # Warstwa graczy self._mineLayer = ObjectsLayer(self._map) # Warstwa min self._map.addLayer('Hero', 3, self._heroLayer) self._map.addLayer('Mine', 2, self._mineLayer) self._submodules = (self._map,) def isPlaying(self): """Czy gracz nadal gra?""" return self._play def screenUpdated(self): """Aktualizuje obrazy tła i submoduły.""" super(Scene, self).screenUpdated() self._refresh = True self._background = pygame.Surface((self._resx, self._resy)) self.surface = pygame.transform.smoothscale(self.surface, (self._resx, self._resy)) for submodule in self._submodules: submodule.screenUpdated() def show(self): if not self._play: self._engine.previousModule() return try: self._last = time.time() while self._engine.tick(): _upd = self._client.update(.5/self._engine.options['fps']) if self._play and _upd != True: utils.drawText(self.surface, _upd, 20, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._play = False self._engine.show(self.surface) time.sleep(5) self._engine.previousModule() raise SceneQuit() if self._client.countdown: if not self._map: self._loadMap(self._client.countdown.mapSize.x, self._client.countdown.mapSize.y) if self._playerID == None: self._playerID = self._client.countdown.playerId self.surface = self._background.copy() utils.drawText(self.surface, 'Gracz %d. >%d<' % (self._client.countdown.playerId, self._client.countdown.number), 30, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._engine.show(self.surface) continue if self._client.result: utils.drawText(self.surface, 'Gra zakonczona!', 40, (255, 255, 255), (self._resx / 2, self._resy / 2)) if len(self._client.result.winners) == 1: utils.drawText(self.surface, 'Wygral gracz %d!' % self._client.result.winners[0], 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) elif len(self._client.result.winners): utils.drawText(self.surface, 'Wygrali gracze %s!' % (', '.join([str(i) for i in self._client.result.winners])), 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) self._play = False self._engine.show(self.surface) time.sleep(10) self._engine.previousModule() raise SceneQuit() if self._client.map: if not self._map: self._engine.previousModule() self._play = False raise SceneQuit() for mine in self._client.map.mines: _id = mine.position.x, mine.position.y if not self._mineLayer.get(_id): _mine = ObjectsLayer.Sprite(utils.loadImage('data/gfx/bomb.png', alpha = True)) self._mineLayer.add(_id, _mine) self._mineLayer.move(_id, _id) for _id, player in enumerate(self._client.map.playersPositions): if not self._heroLayer.get(_id): self._heroLayer.add(_id, ObjectsLayer.Sprite(utils.loadImage('data/gfx/hero/n.png', alpha = True))) _hero = self._heroLayer.get(_id) _pos = _hero.getPos() self._heroLayer.move(_id, (player.x, player.y)) _newpos = _hero.getPos() if _pos[0] > _newpos[0]: _hero.changeImage(utils.loadImage('data/gfx/hero/w.png', alpha = True)) if _pos[0] < _newpos[0]: _hero.changeImage(utils.loadImage('data/gfx/hero/e.png', alpha = True)) if _pos[1] > _newpos[1]: _hero.changeImage(utils.loadImage('data/gfx/hero/n.png', alpha = True)) if _pos[1] < _newpos[1]: _hero.changeImage(utils.loadImage('data/gfx/hero/s.png', alpha = True)) if _id == self._playerID: _, _, w, h = self._map.getRectangle() self._map.setShift((w / 2 - _newpos[0], h / 2 - _newpos[1])) for event in self._engine.events(): if event.type == QUIT: raise engine.EngineQuit() if event.type == KEYDOWN: if event.key == K_ESCAPE: self._engine.previousModule() raise SceneQuit() if event.key in (K_w, K_UP): self._client.sendAction('u') self._last = time.time() elif event.key in (K_s, K_DOWN): self._client.sendAction('d') self._last = time.time() elif event.key in (K_a, K_LEFT): self._client.sendAction('l') self._last = time.time() elif event.key in (K_d, K_RIGHT): self._client.sendAction('r') self._last = time.time() elif event.key in (K_RETURN, K_RCTRL, K_LCTRL): self._client.sendAction('c') self._last = time.time() elif event.key == K_q: self._client.sendAction('e') self._last = time.time() if self._last + 1./self._engine.options['fps'] < time.time(): self._client.sendAction('m') self._last = time.time() self.surface = self._background.copy() if not self._map: utils.drawText(self.surface, 'Oczekiwanie na graczy!', 20, (255, 255, 255), (self._resx / 2, self._resy / 2)) updated = [] for submodule in self._submodules: updated.extend(submodule.update()) submodule.draw(self.surface) if self._refresh: self._engine.show(self.surface) self._refresh = False else: self._engine.show(self.surface, updated) except SceneQuit: pass
def read(self, fileName): file = QFile(fileName) if (not file.open(QIODevice.ReadOnly)): self.mError = self.tr("Could not open file for reading.") return None # default to values of the original flare alpha game. map = Map(Map.Orientation.Isometric, 256, 256, 64, 32) stream = QTextStream(file) line = QString() sectionName = QString() newsection = False path = QFileInfo(file).absolutePath() base = 10 gidMapper = GidMapper() gid = 1 tilelayer = None objectgroup = None mapobject = None tilesetsSectionFound = False headerSectionFound = False tilelayerSectionFound = False # tile layer or objects while (not stream.atEnd()): line = stream.readLine() if line == '': continue startsWith = line[0] if (startsWith == '['): sectionName = line[1:line.index(']')] newsection = True continue if (sectionName == "header"): headerSectionFound = True #get map properties epos = line.index('=') if (epos != -1): key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "width"): map.setWidth(Int(value)) elif (key == "height"): map.setHeight(Int(value)) elif (key == "tilewidth"): map.setTileWidth(Int(value)) elif (key == "tileheight"): map.setTileHeight(Int(value)) elif (key == "orientation"): map.setOrientation(orientationFromString(value)) else: map.setProperty(key, value) elif (sectionName == "tilesets"): tilesetsSectionFound = True epos = line.index('=') key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "tileset"): _list = value.split(',') absoluteSource = _list[0] if (QDir.isRelativePath(absoluteSource)): absoluteSource = path + '/' + absoluteSource tilesetwidth = 0 tilesetheight = 0 if len(_list) > 2: tilesetwidth = Int(_list[1]) tilesetheight = Int(_list[2]) tileset = Tileset.create( QFileInfo(absoluteSource).fileName(), tilesetwidth, tilesetheight) ok = tileset.loadFromImage(absoluteSource) if not ok: self.mError = self.tr( "Error loading tileset %s, which expands to %s. Path not found!" % (_list[0], absoluteSource)) return None else: if len(_list) > 4: tileset.setTileOffset( QPoint(Int(_list[3]), Int(_list[4]))) gidMapper.insert(gid, tileset) if len(_list) > 5: gid += Int(_list[5]) else: gid += tileset.tileCount() map.addTileset(tileset) elif (sectionName == "layer"): if (not tilesetsSectionFound): self.mError = self.tr( "No tilesets section found before layer section.") return None tilelayerSectionFound = True epos = line.index('=') if (epos != -1): key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "type"): tilelayer = TileLayer(value, 0, 0, map.width(), map.height()) map.addLayer(tilelayer) elif (key == "format"): if (value == "dec"): base = 10 elif (value == "hex"): base = 16 elif (key == "data"): for y in range(map.height()): line = stream.readLine() l = line.split(',') for x in range(min(map.width(), len(l))): ok = False tileid = int(l[x], base) c, ok = gidMapper.gidToCell(tileid) if (not ok): self.mError += self.tr( "Error mapping tile id %1.").arg( tileid) return None tilelayer.setCell(x, y, c) else: tilelayer.setProperty(key, value) else: if (newsection): if (map.indexOfLayer(sectionName) == -1): objectgroup = ObjectGroup(sectionName, 0, 0, map.width(), map.height()) map.addLayer(objectgroup) else: objectgroup = map.layerAt( map.indexOfLayer(sectionName)) mapobject = MapObject() objectgroup.addObject(mapobject) newsection = False if (not mapobject): continue if (startsWith == '#'): name = line[1].strip() mapobject.setName(name) epos = line.index('=') if (epos != -1): key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "type"): mapobject.setType(value) elif (key == "location"): loc = value.split(',') x, y = 0.0, 0.0 w, h = 0, 0 if (map.orientation() == Map.Orthogonal): x = loc[0].toFloat() * map.tileWidth() y = loc[1].toFloat() * map.tileHeight() if len(loc) > 3: w = Int(loc[2]) * map.tileWidth() h = Int(loc[3]) * map.tileHeight() else: w = map.tileWidth() h = map.tileHeight() else: x = loc[0].toFloat() * map.tileHeight() y = loc[1].toFloat() * map.tileHeight() if len(loc) > 3: w = Int(loc[2]) * map.tileHeight() h = Int(loc[3]) * map.tileHeight() else: w = h = map.tileHeight() mapobject.setPosition(QPointF(x, y)) mapobject.setSize(w, h) else: mapobject.setProperty(key, value) if (not headerSectionFound or not tilesetsSectionFound or not tilelayerSectionFound): self.mError = self.tr( "This seems to be no valid flare map. " "A Flare map consists of at least a header " "section, a tileset section and one tile layer.") return None return map
class Scene(engine.Module): """Główny ekran gry.""" def __init__(self, _engine): super(Scene, self).__init__(_engine) self._background = pygame.Surface((self._resx, self._resy)) self.surface = self._background.copy() self._actual = [] self._client = _engine.options['client'] = sock.BomberFactory(self._process, self._connectionError) from twisted.internet import reactor from twisted.internet.task import LoopingCall self._gameloop = LoopingCall(self._render) self._network = reactor.connectTCP(_engine.options['host'], _engine.options['port'], self._client) self._play = True self._refresh = True self._submodules = () self._map = None self._playerID = None def __del__(self): self._network.disconnect() def _loadMap(self, _width, _height): self._map = Map(self._engine, self, (_width, _height)) self._heroLayer = ObjectsLayer(self._map) # Warstwa graczy self._mineLayer = ObjectsLayer(self._map) # Warstwa min self._map.addLayer('Hero', 3, self._heroLayer) self._map.addLayer('Mine', 2, self._mineLayer) self._submodules = (self._map,) def isPlaying(self): """Czy gracz nadal gra?""" return self._play def screenUpdated(self): """Aktualizuje obrazy tła i submoduły.""" super(Scene, self).screenUpdated() self._refresh = True self._background = pygame.Surface((self._resx, self._resy)) self.surface = pygame.transform.smoothscale(self.surface, (self._resx, self._resy)) for submodule in self._submodules: submodule.screenUpdated() def show(self): if not self._play: self._engine.previousModule() return self._last = time.time() from twisted.internet import reactor self._gameloop.start(self._engine.getFPS() and 1.0 / self._engine.getFPS() or 0.0) reactor.run() self._gameloop.stop() def _render(self): self._engine.tick() for event in self._engine.events(): if event.type == QUIT: self._play = False elif event.type == KEYDOWN: if event.key == K_ESCAPE: self._engine.runLoop = False from twisted.internet import reactor reactor.stop() return if self._map: if event.key in (K_w, K_UP): self._client.sendAction('u') self._last = time.time() elif event.key in (K_s, K_DOWN): self._client.sendAction('d') self._last = time.time() elif event.key in (K_a, K_LEFT): self._client.sendAction('l') self._last = time.time() elif event.key in (K_d, K_RIGHT): self._client.sendAction('r') self._last = time.time() elif event.key in (K_RETURN, K_RCTRL, K_LCTRL): self._client.sendAction('c') self._last = time.time() elif event.key == K_q: self._client.sendAction('e') self._last = time.time() if self._map and self._last + 1./self._engine.options['fps'] < time.time(): self._client.sendAction('m') self._last = time.time() if not self._map and self._playerID == None: self.surface = self._background.copy() utils.drawText(self.surface, 'Oczekiwanie na graczy!', 20, (255, 255, 255), (self._resx / 2, self._resy / 2)) updated = [] if self._play: for submodule in self._submodules: updated.extend(submodule.update()) submodule.draw(self.surface) if self._refresh: self._engine.show(self.surface) self._refresh = False else: self._engine.show(self.surface, updated) if not self._play: time.sleep(5) self._engine.runLoop = False from twisted.internet import reactor reactor.stop() return def _process(self, obj): if isinstance(obj, protocolObjects.Countdown): return self._countdown(obj) if isinstance(obj, protocolObjects.Result): return self._finish(obj) if isinstance(obj, protocolObjects.Map): return self._update(obj) return self._connectionError(obj) def _connectionError(self, msg): self._play = False utils.drawText(self.surface, str(msg), 10, (255, 255, 255), (self._resx / 2, self._resy - 10)) def _countdown(self, countdown): if not self._map and countdown.number == 1: self._loadMap(countdown.mapSize.x, countdown.mapSize.y) if self._playerID == None: self._playerID = countdown.playerId self.surface = self._background.copy() utils.drawText(self.surface, 'Gracz %d. >%d<' % (countdown.playerId, countdown.number), 30, (255, 255, 255), (self._resx / 2, self._resy / 2)) def _finish(self, result): self.surface = self._background.copy() utils.drawText(self.surface, 'Gra zakonczona!', 40, (255, 255, 255), (self._resx / 2, self._resy / 2)) if len(result.winners) == 1: utils.drawText(self.surface, 'Wygral gracz %d!' % result.winners[0], 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) elif len(result.winners): utils.drawText(self.surface, 'Wygrali gracze %s!' % (', '.join([str(i) for i in result.winners])), 40, (255, 255, 255), (self._resx / 2, self._resy / 2 + 40)) self._play = False self._engine.show(self.surface) def _update(self, map): if not self._map: self._play = False return for mine in map.mines: _id = mine.position.x, mine.position.y if not self._mineLayer.get(_id): _mine = ObjectsLayer.Sprite(utils.loadImage('data/gfx/bomb.png', alpha = True)) self._mineLayer.add(_id, _mine) self._mineLayer.move(_id, _id) for _id, player in enumerate(map.playersPositions): if not self._heroLayer.get(_id): self._heroLayer.add(_id, ObjectsLayer.Sprite(utils.loadImage('data/gfx/hero/n.png', alpha = True))) _hero = self._heroLayer.get(_id) _pos = _hero.getPos() self._heroLayer.move(_id, (player.x, player.y)) _newpos = _hero.getPos() if _pos[0] > _newpos[0]: _hero.changeImage(utils.loadImage('data/gfx/hero/w.png', alpha = True)) if _pos[0] < _newpos[0]: _hero.changeImage(utils.loadImage('data/gfx/hero/e.png', alpha = True)) if _pos[1] > _newpos[1]: _hero.changeImage(utils.loadImage('data/gfx/hero/n.png', alpha = True)) if _pos[1] < _newpos[1]: _hero.changeImage(utils.loadImage('data/gfx/hero/s.png', alpha = True)) if _id == self._playerID: _, _, w, h = self._map.getRectangle() self._map.setShift((w / 2 - _newpos[0], h / 2 - _newpos[1]))
def read(self, fileName): # Read data. file = QFile(fileName) if (not file.open(QIODevice.ReadOnly)): self.mError = self.tr("Cannot open Replica Island map file!") return 0 _in = QDataStream(file) _in.setByteOrder(QDataStream.LittleEndian) _in.setFloatingPointPrecision(QDataStream.SinglePrecision) # Parse file header. mapSignature = _in.readUInt8() layerCount = _in.readUInt8() backgroundIndex = _in.readUInt8() if (_in.status() == QDataStream.ReadPastEnd or mapSignature != 96): self.mError = self.tr("Can't parse file header!") return 0 # Create our map, setting width and height to 0 until we load a layer. map = Map(Map.Orientation.Orthogonal, 0, 0, 32, 32) map.setProperty("background_index", QString.number(backgroundIndex)) # Load our Tilesets. typeTilesets = QVector() tileIndexTilesets = QVector() self.loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets) # Load each of our layers. for i in range(layerCount): # Parse layer header. _type = _in.readUInt8() tileIndex = _in.readUInt8() scrollSpeed = _in.readFloat() levelSignature = _in.readUInt8() width = _in.readUInt32() height = _in.readUInt32() if (_in.status() == QDataStream.ReadPastEnd or levelSignature != 42): self.mError = self.tr("Can't parse layer header!") return 0 # Make sure our width and height are consistent. if (map.width() == 0): map.setWidth(width) if (map.height() == 0): map.setHeight(height) if (map.width() != width or map.height() != height): self.mError = self.tr("Inconsistent layer sizes!") return 0 # Create a layer object. layer = TileLayer(self.layerTypeToName(_type), 0, 0, width, height) layer.setProperty("type", QString.number(_type)) layer.setProperty("tile_index", QString.number(tileIndex)) layer.setProperty("scroll_speed", QString.number(scrollSpeed, 'f')) map.addLayer(layer) # Look up the tileset for this layer. tileset = tilesetForLayer(_type, tileIndex, typeTilesets, tileIndexTilesets) # Read our tile data all at once. #tileData = QByteArray(width*height, b'\x00') bytesNeeded = width*height tileData = _in.readRawData(bytesNeeded) bytesRead = len(tileData) if (bytesRead != bytesNeeded): self.mError = self.tr("File ended in middle of layer!") return 0 i = 0 # Add the tiles to our layer. for y in range(0, height): for x in range(0, width): tile_id = tileData[i]&0xff i += 1 if (tile_id != 255): tile = tileset.tileAt(tile_id) layer.setCell(x, y, Cell(tile)) # Make sure we read the entire *.bin file. if (_in.status() != QDataStream.Ok or not _in.atEnd()): self.mError = self.tr("Unexpected data at end of file!") return 0 return map
class MapReaderPrivate(): def tr(self, sourceText, disambiguation='', n=-1): return QCoreApplication.translate('MapReader', sourceText, disambiguation, n) def trUtf8(self, sourceText, disambiguation='', n=-1): return QCoreApplication.translate('MapReader', sourceText, disambiguation, n) def __init__(self, mapReader): self.p = mapReader self.mMap = None self.mError = QString('') self.mReadingExternalTileset = False self.xml = QXmlStreamReader() self.mGidMapper = GidMapper() def readMap(self, device, path): self.mError = QString('') self.mPath = path map = None self.xml.setDevice(device) if (self.xml.readNextStartElement() and self.xml.name() == "map"): map = self.__readMap() else: self.xml.raiseError(self.tr("Not a map file.")) self.mGidMapper.clear() return map def readTileset(self, device, path): self.mError = '' self.mPath = path tileset = None self.mReadingExternalTileset = True self.xml.setDevice(device) if (self.xml.readNextStartElement() and self.xml.name() == "tileset"): tileset = self.__readTileset() else: self.xml.raiseError(self.tr("Not a tileset file.")) self.mReadingExternalTileset = False return tileset def openFile(self, file): if (not file.exists()): self.mError = self.tr("File not found: %s" % file.fileName()) return False elif (not file.open(QFile.ReadOnly | QFile.Text)): self.mError = self.tr("Unable to read file: %s" % file.fileName()) return False return True def errorString(self): if self.mError != '': return self.mError else: return self.tr("%d\n\nLine %d, column %s" % (self.xml.lineNumber(), self.xml.columnNumber(), self.xml.errorString())) def __readUnknownElement(self): qDebug("Unknown element (fixme): " + self.xml.name() + " at line " + self.xml.lineNumber() + ", column " + self.xml.columnNumber()) self.xml.skipCurrentElement() def __readMap(self): atts = self.xml.attributes() mapWidth = Int(atts.value("width")) mapHeight = Int(atts.value("height")) tileWidth = Int(atts.value("tilewidth")) tileHeight = Int(atts.value("tileheight")) hexSideLength = Int(atts.value("hexsidelength")) orientationString = atts.value("orientation") orientation = orientationFromString(orientationString) if (orientation == Map.Orientation.Unknown): self.xml.raiseError( self.tr("Unsupported map orientation: \"%s\"" % orientationString)) staggerAxisString = atts.value("staggeraxis") staggerAxis = staggerAxisFromString(staggerAxisString) staggerIndexString = atts.value("staggerindex") staggerIndex = staggerIndexFromString(staggerIndexString) renderOrderString = atts.value("renderorder") renderOrder = renderOrderFromString(renderOrderString) nextObjectId = Int(atts.value("nextobjectid")) self.mMap = Map(orientation, mapWidth, mapHeight, tileWidth, tileHeight) self.mMap.setHexSideLength(hexSideLength) self.mMap.setStaggerAxis(staggerAxis) self.mMap.setStaggerIndex(staggerIndex) self.mMap.setRenderOrder(renderOrder) if (nextObjectId): self.mMap.setNextObjectId(nextObjectId) bgColorString = atts.value("backgroundcolor") if len(bgColorString) > 0: self.mMap.setBackgroundColor(QColor(bgColorString)) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): self.mMap.mergeProperties(self.__readProperties()) elif (self.xml.name() == "tileset"): self.mMap.addTileset(self.__readTileset()) elif (self.xml.name() == "layer"): self.mMap.addLayer(self.__readLayer()) elif (self.xml.name() == "objectgroup"): self.mMap.addLayer(self.__readObjectGroup()) elif (self.xml.name() == "imagelayer"): self.mMap.addLayer(self.__readImageLayer()) else: self.__readUnknownElement() # Clean up in case of error if (self.xml.hasError()): self.mMap = None return self.mMap def __readTileset(self): atts = self.xml.attributes() source = atts.value("source") firstGid = Int(atts.value("firstgid")) tileset = None if source == '': # Not an external tileset name = atts.value("name") tileWidth = Int(atts.value("tilewidth")) tileHeight = Int(atts.value("tileheight")) tileSpacing = Int(atts.value("spacing")) margin = Int(atts.value("margin")) if (tileWidth < 0 or tileHeight < 0 or (firstGid == 0 and not self.mReadingExternalTileset)): self.xml.raiseError( self.tr("Invalid tileset parameters for tileset '%s'" % name)) else: tileset = Tileset.create(name, tileWidth, tileHeight, tileSpacing, margin) while (self.xml.readNextStartElement()): if (self.xml.name() == "tile"): self.__readTilesetTile(tileset) elif (self.xml.name() == "tileoffset"): oa = self.xml.attributes() x = Int(oa.value("x")) y = Int(oa.value("y")) tileset.setTileOffset(QPoint(x, y)) self.xml.skipCurrentElement() elif (self.xml.name() == "properties"): tileset.mergeProperties(self.__readProperties()) elif (self.xml.name() == "image"): if (tileWidth == 0 or tileHeight == 0): self.xml.raiseError( self. tr("Invalid tileset parameters for tileset '%s'" % name)) tileset.clear() break else: self.__readTilesetImage(tileset) elif (self.xml.name() == "terraintypes"): self.__readTilesetTerrainTypes(tileset) else: self.__readUnknownElement() else: # External tileset absoluteSource = self.p.resolveReference(source, self.mPath) tileset, error = self.p.readExternalTileset(absoluteSource) if (not tileset): self.xml.raiseError( self.tr("Error while loading tileset '%s': %s" % (absoluteSource, error))) self.xml.skipCurrentElement() if (tileset and not self.mReadingExternalTileset): self.mGidMapper.insert(firstGid, tileset) return tileset def __readTilesetTile(self, tileset): atts = self.xml.attributes() id = Int(atts.value("id")) if (id < 0): self.xml.raiseError(self.tr("Invalid tile ID: %d" % id)) return hasImage = tileset.imageSource() != '' if (hasImage and id >= tileset.tileCount()): self.xml.raiseError( self.tr("Tile ID does not exist in tileset image: %d" % id)) return if (id > tileset.tileCount()): self.xml.raiseError( self.tr("Invalid (nonconsecutive) tile ID: %d" % id)) return # For tilesets without image source, consecutive tile IDs are allowed (for # tiles with individual images) if (id == tileset.tileCount()): tileset.addTile(QPixmap()) tile = tileset.tileAt(id) # Read tile quadrant terrain ids terrain = atts.value("terrain") if terrain != '': quadrants = terrain.split(",") if (len(quadrants) == 4): for i in range(4): if quadrants[i] == '': t = -1 else: t = Int(quadrants[i]) tile.setCornerTerrainId(i, t) # Read tile probability probability = atts.value("probability") if probability != '': tile.setProbability(Float(probability)) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): tile.mergeProperties(self.__readProperties()) elif (self.xml.name() == "image"): source = self.xml.attributes().value("source") if source != '': source = self.p.resolveReference(source, self.mPath) tileset.setTileImage(id, QPixmap.fromImage(self.__readImage()), source) elif (self.xml.name() == "objectgroup"): tile.setObjectGroup(self.__readObjectGroup()) elif (self.xml.name() == "animation"): tile.setFrames(self.__readAnimationFrames()) else: self.__readUnknownElement() # Temporary code to support TMW-style animation frame properties if (not tile.isAnimated() and tile.hasProperty("animation-frame0")): frames = QVector() i = 0 while (i >= 0): frameName = "animation-frame" + str(i) delayName = "animation-delay" + str(i) if (tile.hasProperty(frameName) and tile.hasProperty(delayName)): frame = Frame() frame.tileId = tile.property(frameName) frame.duration = tile.property(delayName) * 10 frames.append(frame) else: break i += 1 tile.setFrames(frames) def __readTilesetImage(self, tileset): atts = self.xml.attributes() source = atts.value("source") trans = atts.value("trans") if len(trans) > 0: if (not trans.startswith('#')): trans = '#' + trans tileset.setTransparentColor(QColor(trans)) if len(source) > 0: source = self.p.resolveReference(source, self.mPath) # Set the width that the tileset had when the map was saved width = Int(atts.value("width")) self.mGidMapper.setTilesetWidth(tileset, width) if (not tileset.loadFromImage(self.__readImage(), source)): self.xml.raiseError( self.tr("Error loading tileset image:\n'%s'" % source)) def __readTilesetTerrainTypes(self, tileset): while (self.xml.readNextStartElement()): if (self.xml.name() == "terrain"): atts = self.xml.attributes() name = atts.value("name") tile = Int(atts.value("tile")) terrain = tileset.addTerrain(name, tile) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): terrain.mergeProperties(self.__readProperties()) else: self.__readUnknownElement() else: self.__readUnknownElement() def __readImage(self): atts = self.xml.attributes() source = atts.value("source") format = atts.value("format") if len(source) == 0: while (self.xml.readNextStartElement()): if (self.xml.name() == "data"): atts = self.xml.attributes() encoding = atts.value("encoding") data = self.xml.readElementText().toLatin1() if (encoding == "base64"): data = QByteArray.fromBase64(data) self.xml.skipCurrentElement() return QImage.fromData(data, format.toLatin1()) else: self.__readUnknownElement() else: self.xml.skipCurrentElement() source = self.p.resolveReference(source, self.mPath) image = self.p.readExternalImage(source) if (image.isNull()): self.xml.raiseError( self.tr("Error loading image:\n'%s'" % source)) return image return QImage() def __readLayer(self): atts = self.xml.attributes() name = atts.value("name") x = Int(atts.value("x")) y = Int(atts.value("y")) width = Int(atts.value("width")) height = Int(atts.value("height")) tileLayer = TileLayer(name, x, y, width, height) readLayerAttributes(tileLayer, atts) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): tileLayer.mergeProperties(self.__readProperties()) elif (self.xml.name() == "data"): self.__readLayerData(tileLayer) else: self.__readUnknownElement() return tileLayer def __readLayerData(self, tileLayer): atts = self.xml.attributes() encoding = atts.value("encoding") compression = atts.value("compression") layerDataFormat = 0 if (encoding == ''): layerDataFormat = Map.LayerDataFormat.XML elif (encoding == "csv"): layerDataFormat = Map.LayerDataFormat.CSV elif (encoding == "base64"): if (compression == ''): layerDataFormat = Map.LayerDataFormat.Base64 elif (compression == "gzip"): layerDataFormat = Map.LayerDataFormat.Base64Gzip elif (compression == "zlib"): layerDataFormat = Map.LayerDataFormat.Base64Zlib else: self.xml.raiseError( self.tr("Compression method '%s' not supported" % compression)) return else: self.xml.raiseError(self.tr("Unknown encoding: %s" % encoding)) return self.mMap.setLayerDataFormat(layerDataFormat) x = 0 y = 0 while (self.xml.readNext() != QXmlStreamReader.Invalid): if (self.xml.isEndElement()): break elif (self.xml.isStartElement()): if (self.xml.name() == "tile"): if (y >= tileLayer.height()): self.xml.raiseError( self.tr("Too many <tile> elements")) continue atts = self.xml.attributes() gid = Int(atts.value("gid")) tileLayer.setCell(x, y, self.__cellForGid(gid)) x += 1 if (x >= tileLayer.width()): x = 0 y += 1 self.xml.skipCurrentElement() else: self.__readUnknownElement() elif (self.xml.isCharacters() and not self.xml.isWhitespace()): if (encoding == "base64"): self.__decodeBinaryLayerData(tileLayer, self.xml.text(), layerDataFormat) elif (encoding == "csv"): self.__decodeCSVLayerData(tileLayer, self.xml.text()) def __decodeBinaryLayerData(self, tileLayer, data, format): error = self.mGidMapper.decodeLayerData(tileLayer, data, format) if error == DecodeError.CorruptLayerData: self.xml.raiseError( self.tr("Corrupt layer data for layer '%s'" % tileLayer.name())) return elif error == DecodeError.TileButNoTilesets: self.xml.raiseError(self.tr("Tile used but no tilesets specified")) return elif error == DecodeError.InvalidTile: self.xml.raiseError( self.tr("Invalid tile: %d" % self.mGidMapper.invalidTile())) return elif error == DecodeError.NoError: pass def __decodeCSVLayerData(self, tileLayer, text): trimText = text.strip() tiles = trimText.split(',') if (len(tiles) != tileLayer.width() * tileLayer.height()): self.xml.raiseError( self.tr("Corrupt layer data for layer '%s'" % tileLayer.name())) return for y in range(tileLayer.height()): for x in range(tileLayer.width()): conversionOk = False gid, conversionOk = Int2(tiles[y * tileLayer.width() + x]) if (not conversionOk): self.xml.raiseError( self.tr( "Unable to parse tile at (%d,%d) on layer '%s'" % (x + 1, y + 1, tileLayer.name()))) return tileLayer.setCell(x, y, self.__cellForGid(gid)) ## # Returns the cell for the given global tile ID. Errors are raised with # the QXmlStreamReader. # # @param gid the global tile ID # @return the cell data associated with the given global tile ID, or an # empty cell if not found ## def __cellForGid(self, gid): ok = False result, ok = self.mGidMapper.gidToCell(gid) if (not ok): if (self.mGidMapper.isEmpty()): self.xml.raiseError( self.tr("Tile used but no tilesets specified")) else: self.xml.raiseError(self.tr("Invalid tile: %d" % gid)) return result def __readImageLayer(self): atts = self.xml.attributes() name = atts.value("name") x = Int(atts.value("x")) y = Int(atts.value("y")) width = Int(atts.value("width")) height = Int(atts.value("height")) imageLayer = ImageLayer(name, x, y, width, height) readLayerAttributes(imageLayer, atts) while (self.xml.readNextStartElement()): if (self.xml.name() == "image"): self.__readImageLayerImage(imageLayer) elif (self.xml.name() == "properties"): imageLayer.mergeProperties(self.__readProperties()) else: self.__readUnknownElement() return imageLayer def __readImageLayerImage(self, imageLayer): atts = self.xml.attributes() source = atts.value("source") trans = atts.value("trans") if trans != '': if (not trans.startswith('#')): trans = '#' + trans imageLayer.setTransparentColor(QColor(trans)) source = self.p.resolveReference(source, self.mPath) imageLayerImage = self.p.readExternalImage(source) if (not imageLayer.loadFromImage(imageLayerImage, source)): self.xml.raiseError( self.tr("Error loading image layer image:\n'%s'" % source)) self.xml.skipCurrentElement() def __readObjectGroup(self): atts = self.xml.attributes() name = atts.value("name") x = Int(atts.value("x")) y = Int(atts.value("y")) width = Int(atts.value("width")) height = Int(atts.value("height")) objectGroup = ObjectGroup(name, x, y, width, height) readLayerAttributes(objectGroup, atts) color = atts.value("color") if color != '': objectGroup.setColor(color) if (atts.hasAttribute("draworder")): value = atts.value("draworder") drawOrder = drawOrderFromString(value) if (drawOrder == ObjectGroup.DrawOrder.UnknownOrder): #del objectGroup self.xml.raiseError(self.tr("Invalid draw order: %s" % value)) return None objectGroup.setDrawOrder(drawOrder) while (self.xml.readNextStartElement()): if (self.xml.name() == "object"): objectGroup.addObject(self.__readObject()) elif (self.xml.name() == "properties"): objectGroup.mergeProperties(self.__readProperties()) else: self.__readUnknownElement() return objectGroup def __readObject(self): atts = self.xml.attributes() id = Int(atts.value("id")) name = atts.value("name") gid = Int(atts.value("gid")) x = Float(atts.value("x")) y = Float(atts.value("y")) width = Float(atts.value("width")) height = Float(atts.value("height")) type = atts.value("type") visibleRef = atts.value("visible") pos = QPointF(x, y) size = QSizeF(width, height) object = MapObject(name, type, pos, size) object.setId(id) try: rotation = Float(atts.value("rotation")) ok = True except: ok = False if (ok): object.setRotation(rotation) if (gid): object.setCell(self.__cellForGid(gid)) if (not object.cell().isEmpty()): tileSize = object.cell().tile.size() if (width == 0): object.setWidth(tileSize.width()) if (height == 0): object.setHeight(tileSize.height()) try: visible = int(visibleRef) ok = True except: ok = False if ok: object.setVisible(visible) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): object.mergeProperties(self.__readProperties()) elif (self.xml.name() == "polygon"): object.setPolygon(self.__readPolygon()) object.setShape(MapObject.Polygon) elif (self.xml.name() == "polyline"): object.setPolygon(self.__readPolygon()) object.setShape(MapObject.Polyline) elif (self.xml.name() == "ellipse"): self.xml.skipCurrentElement() object.setShape(MapObject.Ellipse) else: self.__readUnknownElement() return object def __readPolygon(self): atts = self.xml.attributes() points = atts.value("points") pointsList = list(filter(lambda x: x.strip() != '', points.split(' '))) polygon = QPolygonF() ok = True for point in pointsList: try: x, y = point.split(',') except: ok = False break x, ok = Float2(x) if (not ok): break y, ok = Float2(y) if (not ok): break polygon.append(QPointF(x, y)) if (not ok): self.xml.raiseError(self.tr("Invalid points data for polygon")) self.xml.skipCurrentElement() return polygon def __readAnimationFrames(self): frames = QVector() while (self.xml.readNextStartElement()): if (self.xml.name() == "frame"): atts = self.xml.attributes() frame = Frame() frame.tileId = Int(atts.value("tileid")) frame.duration = Int(atts.value("duration")) frames.append(frame) self.xml.skipCurrentElement() else: self.__readUnknownElement() return frames def __readProperties(self): properties = Properties() while (self.xml.readNextStartElement()): if (self.xml.name() == "property"): self.__readProperty(properties) else: self.__readUnknownElement() return properties def __readProperty(self, properties): atts = self.xml.attributes() propertyName = atts.value("name") propertyValue = atts.value("value") while (self.xml.readNext() != QXmlStreamReader.Invalid): if (self.xml.isEndElement()): break elif (self.xml.isCharacters() and not self.xml.isWhitespace()): if (propertyValue.isEmpty()): propertyValue = self.xml.text() elif (self.xml.isStartElement()): self.__readUnknownElement() properties.insert(propertyName, propertyValue)
def read(self, fileName): # Read data. file = QFile(fileName) if (not file.open(QIODevice.ReadOnly)): self.mError = self.tr("Cannot open Replica Island map file!") return 0 _in = QDataStream(file) _in.setByteOrder(QDataStream.LittleEndian) _in.setFloatingPointPrecision(QDataStream.SinglePrecision) # Parse file header. mapSignature = _in.readUInt8() layerCount = _in.readUInt8() backgroundIndex = _in.readUInt8() if (_in.status() == QDataStream.ReadPastEnd or mapSignature != 96): self.mError = self.tr("Can't parse file header!") return 0 # Create our map, setting width and height to 0 until we load a layer. map = Map(Map.Orientation.Orthogonal, 0, 0, 32, 32) map.setProperty("background_index", QString.number(backgroundIndex)) # Load our Tilesets. typeTilesets = QVector() tileIndexTilesets = QVector() self.loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets) # Load each of our layers. for i in range(layerCount): # Parse layer header. _type = _in.readUInt8() tileIndex = _in.readUInt8() scrollSpeed = _in.readFloat() levelSignature = _in.readUInt8() width = _in.readUInt32() height = _in.readUInt32() if (_in.status() == QDataStream.ReadPastEnd or levelSignature != 42): self.mError = self.tr("Can't parse layer header!") return 0 # Make sure our width and height are consistent. if (map.width() == 0): map.setWidth(width) if (map.height() == 0): map.setHeight(height) if (map.width() != width or map.height() != height): self.mError = self.tr("Inconsistent layer sizes!") return 0 # Create a layer object. layer = TileLayer(self.layerTypeToName(_type), 0, 0, width, height) layer.setProperty("type", QString.number(_type)) layer.setProperty("tile_index", QString.number(tileIndex)) layer.setProperty("scroll_speed", QString.number(scrollSpeed, 'f')) map.addLayer(layer) # Look up the tileset for this layer. tileset = tilesetForLayer(_type, tileIndex, typeTilesets, tileIndexTilesets) # Read our tile data all at once. #tileData = QByteArray(width*height, b'\x00') bytesNeeded = width * height tileData = _in.readRawData(bytesNeeded) bytesRead = len(tileData) if (bytesRead != bytesNeeded): self.mError = self.tr("File ended in middle of layer!") return 0 i = 0 # Add the tiles to our layer. for y in range(0, height): for x in range(0, width): tile_id = tileData[i] & 0xff i += 1 if (tile_id != 255): tile = tileset.tileAt(tile_id) layer.setCell(x, y, Cell(tile)) # Make sure we read the entire *.bin file. if (_in.status() != QDataStream.Ok or not _in.atEnd()): self.mError = self.tr("Unexpected data at end of file!") return 0 return map
class Scene(engine.Module): """Główny ekran gry.""" def __init__(self, _engine): super(Scene, self).__init__(_engine) self.side = utils.loadImage('data/gfx/side.png') self._background = pygame.Surface((self._resx, self._resy)) self._background.blit(self.side, (self._resx - 232, self._resy - 1500)) self.surface = self._background.copy() self._actual = [] self._level = utils.loadLevel('data/level.dat') self._map = Map(_engine, self, self._level) self._minimap = Minimap(_engine, self._map) self._cursor = Cursor(_engine, self._map) self._creatureLayer = CreatureLayer(self._map, self._cursor) # Warstwa potworów self._map.addLayer('Creatures', 2, self._creatureLayer) self._map.addLayer('Missiles', 3, MissilesLayer( self._map)) # Warstwa pocisków(strzał, kuli ognia itp.) self._shadow = ShadowLayer(self._map) self._map.addLayer('Shadow', 5, self._shadow) # Mgła wojny self._monsters = [] self._freeobjects = pygame.sprite.Group() # Wolne obiekty na scenie _counter = 0 _start = 0 # szukanie bohatera w lochu for l, storey in enumerate(self._level): for row in storey: for cell in row: if cell.getModifier() & field.MODIFIER_HERO: self._hero = hero.Hero(self._map, cell.getGrid() + (l, )) self._hero.move((0, 0, 0)) self._map.switchStorey(l) _start = l self._creatureLayer.add( 'hero', self._hero.getSprite(self._creatureLayer, 'hero')) break # szukanie potworów for l, storey in enumerate(self._level): for row in storey: for cell in row: if cell.getModifier() & field.MODIFIER_SPIDER: _monster = Spider(self._map, cell.getGrid() + (l, )) self._monsters.append(('spider', _monster)) if l == _start: self._creatureLayer.add( 'spider_' + str(_counter), _monster.getSprite(self._creatureLayer, 'spider_' + str(_counter))) self._actual.append( ('spider_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 elif cell.getModifier() & field.MODIFIER_SKELETON: _monster = Skeleton(self._map, cell.getGrid() + (l, )) self._monsters.append(('skeleton', _monster)) if l == _start: self._creatureLayer.add( 'skeleton_' + str(_counter), _monster.getSprite(self._creatureLayer, 'skeleton_' + str(_counter))) self._actual.append( ('skeleton_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 elif cell.getModifier() & field.MODIFIER_MAGE: _monster = Mage(self._map, cell.getGrid() + (l, )) self._monsters.append(('mage', _monster)) if l == _start: self._creatureLayer.add( 'mage_' + str(_counter), _monster.getSprite(self._creatureLayer, 'mage_' + str(_counter))) self._actual.append( ('mage_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 elif cell.getModifier() & field.MODIFIER_TROLL: _monster = Troll(self._map, cell.getGrid() + (l, )) self._monsters.append(('troll', _monster)) if l == _start: self._creatureLayer.add( 'troll_' + str(_counter), _monster.getSprite(self._creatureLayer, 'troll_' + str(_counter))) self._actual.append( ('troll_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 if not self._hero: raise Exception('Brak bohatera w lochu!?') self._statusbar = StatusBar( _engine, self._hero) # pasek życia/many itp. / statusu self.inventory = Inventory(_engine, self._hero, self._hero.inventory, self._freeobjects) self.chestitems = ChestItems(_engine, self._hero, self._freeobjects) self._submodules = (self._map, self._minimap, self._statusbar, self.inventory, self.chestitems, self._cursor) self._play = True self._refresh = True def isPlaying(self): """Czy gracz nadal gra?""" return self._play def screenUpdated(self): """Aktualizuje obrazy tła i submoduły.""" super(Scene, self).screenUpdated() self._refresh = True self._background = pygame.Surface((self._resx, self._resy)) self._background.blit(self.side, (self._resx - 232, self._resy - 1500)) self.surface = pygame.transform.smoothscale(self.surface, (self._resx, self._resy)) for submodule in self._submodules: submodule.screenUpdated() def show(self): if not self._play: self._engine.previousModule() return try: while self._engine.tick(): for event in self._engine.events(): if event.type == QUIT: raise engine.EngineQuit() if event.type == KEYDOWN: if event.key == K_ESCAPE: self._engine.previousModule() raise SceneQuit() elif event.key in hero.MAGIC_KEYS: self._hero.setSpell(hero.KEY_MAP[event.key]) if event.type in (MOUSEMOTION, MOUSEBUTTONDOWN, MOUSEBUTTONUP): for submodule in self._submodules: if submodule.getRectangle().collidepoint( event.pos): x, y, _, _ = submodule.getRectangle() _pos = event.pos[0] - x, event.pos[1] - y else: _pos = None submodule.mouseEvent(event, _pos) if submodule == self._map and event.type == MOUSEBUTTONDOWN and _pos: # obsługa otwierania skrzynki(głównie) _field = self._map.getLayer('Fields').get( _pos, True) if _field: _field.getLogic().clicked(self, self._hero) if submodule == self._map and event.type == MOUSEBUTTONUP and event.button == 1 and _pos: # upuszczanie przedmiotu _field = self._map.getLayer('Fields').get( _pos, True) if _field: _field = _field.getLogic() if _field and utils.distance( _field.getGrid()[:2], self._hero.getGrid()[:2]) <= 1: for _obj in self._freeobjects: if not _obj.attach(_field): _obj.attach(_obj.getAttached()) else: for _obj in self._freeobjects: _obj.attach(_obj.getAttached()) if submodule == self.inventory and event.type == MOUSEBUTTONUP and event.button == 1 and _pos: # ↑ for _obj in self._freeobjects: if not _obj.attach( self.inventory.getCell(_pos)): _obj.attach(_obj.getAttached()) if submodule == self.chestitems and event.type == MOUSEBUTTONUP and event.button == 1 and _pos: # ↑ for _obj in self._freeobjects: if not self.chestitems.opened or not _obj.attach( self.chestitems.getCell(_pos)): _obj.attach(_obj.getAttached()) for _obj in self._freeobjects: _obj.mouseEvent(event) if event.type == MOUSEBUTTONDOWN and event.button == 3 and self._map.getRectangle( ).collidepoint(event.pos): # rzucanie czaru self._hero.castSpell() if event.type == MOUSEBUTTONDOWN and event.button == 1 and self._map.getRectangle( ).collidepoint(event.pos): # atak self._hero.punch() if self._hero.getGrid()[2] != self._map.getStorey( ): # zmiana poziomu lochu self._map.removeLayer('Missiles') self._map.addLayer('Missiles', 3, MissilesLayer(self._map)) self._map.switchStorey(self._hero.getGrid()[2] - self._map.getStorey()) self._shadow.clear() for _id, _ in self._actual: self._creatureLayer.remove(_id) self._actual = [] _counter = 0 _storey = self._map.getStorey() for _name, _monster in self._monsters: if _monster.getGrid()[2] == _storey: self._creatureLayer.add( _name + '_' + str(_counter), _monster.getSprite(self._creatureLayer, _name + '_' + str(_counter))) self._actual.append( (_name + '_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 else: for key in hero.DIRECTION_KEYS: if pygame.key.get_pressed()[key]: self._hero.move(hero.KEY_MAP[key]) if self._hero.getDestination( ): # przesuwanie mapy za bohaterem x, y = self._hero.getPos() _, _, w, h = self._map.getRectangle() self._map.setShift((w / 2 - x, h / 2 - y)) if not self._hero.getLife(): # przegrana utils.drawText(self.surface, "Game Over", 40, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._play = False self._engine.show(self.surface) time.sleep(3) self._engine.previousModule() raise SceneQuit() if not self._monsters: # wygrana utils.drawText(self.surface, "Win", 50, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._play = False self._engine.show(self.surface) time.sleep(3) self._engine.previousModule() raise SceneQuit() _hero = self._hero.getPos() _shift = self._map.getShift() _hero = _hero[0] + _shift[0], _hero[1] + _shift[1] _mouse = pygame.mouse.get_pos() _mouse = _mouse[0] - _hero[0], _mouse[1] - _hero[1] _angle = utils.vectorAngle((0, 1), _mouse) if -45 <= _angle < 45: self._hero.setDirection('s') elif -135 <= _angle < -45: self._hero.setDirection('e') elif 45 <= _angle < 135: self._hero.setDirection('w') else: self._hero.setDirection('n') self._shadow.reveal(self._hero.getPos()) self.surface = self._background.copy() updated = [] for submodule in self._submodules: updated.extend(submodule.update()) submodule.draw(self.surface) for _obj in self._freeobjects: updated.extend(_obj.update()) _obj.draw(self.surface) if self._refresh: self._engine.show(self.surface) self._refresh = False else: self._engine.show(self.surface, updated) _actual = [] for _id, _monster in self._actual: if _monster.getGrid()[2] != self._map.getStorey(): self._creatureLayer.remove(_id) else: _actual.append((_id, _monster)) self._actual = _actual for _id, _monster in self._monsters: # umierające potwory dodają exp bohaterowi if not _monster.getLife(): self._monsters.remove((_id, _monster)) self._hero.addExperience(_monster.stats['experience']) except SceneQuit: pass
class Scene(engine.Module): """Główny ekran gry.""" def __init__(self, _engine): super(Scene, self).__init__(_engine) self.side = utils.loadImage('data/gfx/side.png') self._background = pygame.Surface((self._resx, self._resy)) self._background.blit(self.side, (self._resx - 232, self._resy - 1500)) self.surface = self._background.copy() self._actual = [] self._level = utils.loadLevel('data/level.dat') self._map = Map(_engine, self, self._level) self._minimap = Minimap(_engine, self._map) self._cursor = Cursor(_engine, self._map) self._creatureLayer = CreatureLayer(self._map, self._cursor) # Warstwa potworów self._map.addLayer('Creatures', 2, self._creatureLayer) self._map.addLayer('Missiles', 3, MissilesLayer(self._map)) # Warstwa pocisków(strzał, kuli ognia itp.) self._shadow = ShadowLayer(self._map) self._map.addLayer('Shadow', 5, self._shadow) # Mgła wojny self._monsters = [] self._freeobjects = pygame.sprite.Group() # Wolne obiekty na scenie _counter = 0 _start = 0 # szukanie bohatera w lochu for l, storey in enumerate(self._level): for row in storey: for cell in row: if cell.getModifier() & field.MODIFIER_HERO: self._hero = hero.Hero(self._map, cell.getGrid() + (l,)) self._hero.move((0, 0, 0)) self._map.switchStorey(l) _start = l self._creatureLayer.add('hero', self._hero.getSprite(self._creatureLayer, 'hero')) break # szukanie potworów for l, storey in enumerate(self._level): for row in storey: for cell in row: if cell.getModifier() & field.MODIFIER_SPIDER: _monster = Spider(self._map, cell.getGrid() + (l,)) self._monsters.append(('spider', _monster)) if l == _start: self._creatureLayer.add('spider_' + str(_counter), _monster.getSprite(self._creatureLayer, 'spider_' + str(_counter))) self._actual.append(('spider_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 elif cell.getModifier() & field.MODIFIER_SKELETON: _monster = Skeleton(self._map, cell.getGrid() + (l,)) self._monsters.append(('skeleton', _monster)) if l == _start: self._creatureLayer.add('skeleton_' + str(_counter), _monster.getSprite(self._creatureLayer, 'skeleton_' + str(_counter))) self._actual.append(('skeleton_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 elif cell.getModifier() & field.MODIFIER_MAGE: _monster = Mage(self._map, cell.getGrid() + (l,)) self._monsters.append(('mage', _monster)) if l == _start: self._creatureLayer.add('mage_' + str(_counter), _monster.getSprite(self._creatureLayer, 'mage_' + str(_counter))) self._actual.append(('mage_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 elif cell.getModifier() & field.MODIFIER_TROLL: _monster = Troll(self._map, cell.getGrid() + (l,)) self._monsters.append(('troll', _monster)) if l == _start: self._creatureLayer.add('troll_' + str(_counter), _monster.getSprite(self._creatureLayer, 'troll_' + str(_counter))) self._actual.append(('troll_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 if not self._hero: raise Exception('Brak bohatera w lochu!?') self._statusbar = StatusBar(_engine, self._hero) # pasek życia/many itp. / statusu self.inventory = Inventory(_engine, self._hero, self._hero.inventory, self._freeobjects) self.chestitems = ChestItems(_engine, self._hero, self._freeobjects) self._submodules = (self._map, self._minimap, self._statusbar, self.inventory, self.chestitems, self._cursor) self._play = True self._refresh = True def isPlaying(self): """Czy gracz nadal gra?""" return self._play def screenUpdated(self): """Aktualizuje obrazy tła i submoduły.""" super(Scene, self).screenUpdated() self._refresh = True self._background = pygame.Surface((self._resx, self._resy)) self._background.blit(self.side, (self._resx - 232, self._resy - 1500)) self.surface = pygame.transform.smoothscale(self.surface, (self._resx, self._resy)) for submodule in self._submodules: submodule.screenUpdated() def show(self): if not self._play: self._engine.previousModule() return try: while self._engine.tick(): for event in self._engine.events(): if event.type == QUIT: raise engine.EngineQuit() if event.type == KEYDOWN: if event.key == K_ESCAPE: self._engine.previousModule() raise SceneQuit() elif event.key in hero.MAGIC_KEYS: self._hero.setSpell(hero.KEY_MAP[event.key]) if event.type in (MOUSEMOTION, MOUSEBUTTONDOWN, MOUSEBUTTONUP): for submodule in self._submodules: if submodule.getRectangle().collidepoint(event.pos): x, y, _, _ = submodule.getRectangle() _pos = event.pos[0] - x, event.pos[1] - y else: _pos = None submodule.mouseEvent(event, _pos) if submodule == self._map and event.type == MOUSEBUTTONDOWN and _pos: # obsługa otwierania skrzynki(głównie) _field = self._map.getLayer('Fields').get(_pos, True) if _field: _field.getLogic().clicked(self, self._hero) if submodule == self._map and event.type == MOUSEBUTTONUP and event.button == 1 and _pos: # upuszczanie przedmiotu _field = self._map.getLayer('Fields').get(_pos, True) if _field: _field = _field.getLogic() if _field and utils.distance(_field.getGrid()[:2], self._hero.getGrid()[:2]) <= 1: for _obj in self._freeobjects: if not _obj.attach(_field): _obj.attach(_obj.getAttached()) else: for _obj in self._freeobjects: _obj.attach(_obj.getAttached()) if submodule == self.inventory and event.type == MOUSEBUTTONUP and event.button == 1 and _pos: # ↑ for _obj in self._freeobjects: if not _obj.attach(self.inventory.getCell(_pos)): _obj.attach(_obj.getAttached()) if submodule == self.chestitems and event.type == MOUSEBUTTONUP and event.button == 1 and _pos: # ↑ for _obj in self._freeobjects: if not self.chestitems.opened or not _obj.attach(self.chestitems.getCell(_pos)): _obj.attach(_obj.getAttached()) for _obj in self._freeobjects: _obj.mouseEvent(event) if event.type == MOUSEBUTTONDOWN and event.button == 3 and self._map.getRectangle().collidepoint(event.pos): # rzucanie czaru self._hero.castSpell() if event.type == MOUSEBUTTONDOWN and event.button == 1 and self._map.getRectangle().collidepoint(event.pos): # atak self._hero.punch() if self._hero.getGrid()[2] != self._map.getStorey(): # zmiana poziomu lochu self._map.removeLayer('Missiles') self._map.addLayer('Missiles', 3, MissilesLayer(self._map)) self._map.switchStorey(self._hero.getGrid()[2] - self._map.getStorey()) self._shadow.clear() for _id, _ in self._actual: self._creatureLayer.remove(_id) self._actual = [] _counter = 0 _storey = self._map.getStorey() for _name, _monster in self._monsters: if _monster.getGrid()[2] == _storey: self._creatureLayer.add(_name + '_' + str(_counter), _monster.getSprite(self._creatureLayer, _name + '_' + str(_counter))) self._actual.append((_name + '_' + str(_counter), _monster)) _monster.move((0, 0, 0)) _counter += 1 else: for key in hero.DIRECTION_KEYS: if pygame.key.get_pressed()[key]: self._hero.move(hero.KEY_MAP[key]) if self._hero.getDestination(): # przesuwanie mapy za bohaterem x, y = self._hero.getPos() _, _, w, h = self._map.getRectangle() self._map.setShift((w / 2 - x, h / 2 - y)) if not self._hero.getLife(): # przegrana utils.drawText(self.surface, "Game Over", 40, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._play = False self._engine.show(self.surface) time.sleep(3) self._engine.previousModule() raise SceneQuit() if not self._monsters: # wygrana utils.drawText(self.surface, "Win", 50, (255, 255, 255), (self._resx / 2, self._resy / 2)) self._play = False self._engine.show(self.surface) time.sleep(3) self._engine.previousModule() raise SceneQuit() _hero = self._hero.getPos() _shift = self._map.getShift() _hero = _hero[0] + _shift[0], _hero[1] + _shift[1] _mouse = pygame.mouse.get_pos() _mouse = _mouse[0] - _hero[0], _mouse[1] - _hero[1] _angle = utils.vectorAngle((0, 1), _mouse) if -45 <= _angle < 45: self._hero.setDirection('s') elif -135 <= _angle < -45: self._hero.setDirection('e') elif 45 <= _angle < 135: self._hero.setDirection('w') else: self._hero.setDirection('n') self._shadow.reveal(self._hero.getPos()) self.surface = self._background.copy() updated = [] for submodule in self._submodules: updated.extend(submodule.update()) submodule.draw(self.surface) for _obj in self._freeobjects: updated.extend(_obj.update()) _obj.draw(self.surface) if self._refresh: self._engine.show(self.surface) self._refresh = False else: self._engine.show(self.surface, updated) _actual = [] for _id, _monster in self._actual: if _monster.getGrid()[2] != self._map.getStorey(): self._creatureLayer.remove(_id) else: _actual.append((_id, _monster)) self._actual = _actual for _id, _monster in self._monsters: # umierające potwory dodają exp bohaterowi if not _monster.getLife(): self._monsters.remove((_id, _monster)) self._hero.addExperience(_monster.stats['experience']) except SceneQuit: pass
class MapReaderPrivate(): def tr(self, sourceText, disambiguation = '', n = -1): return QCoreApplication.translate('MapReader', sourceText, disambiguation, n) def trUtf8(self, sourceText, disambiguation = '', n = -1): return QCoreApplication.translate('MapReader', sourceText, disambiguation, n) def __init__(self, mapReader): self.p = mapReader self.mMap = None self.mError = QString('') self.mReadingExternalTileset = False self.xml = QXmlStreamReader() self.mGidMapper = GidMapper() def readMap(self, device, path): self.mError = QString('') self.mPath = path map = None self.xml.setDevice(device) if (self.xml.readNextStartElement() and self.xml.name() == "map"): map = self.__readMap() else: self.xml.raiseError(self.tr("Not a map file.")) self.mGidMapper.clear() return map def readTileset(self, device, path): self.mError = '' self.mPath = path tileset = None self.mReadingExternalTileset = True self.xml.setDevice(device) if (self.xml.readNextStartElement() and self.xml.name() == "tileset"): tileset = self.__readTileset() else: self.xml.raiseError(self.tr("Not a tileset file.")) self.mReadingExternalTileset = False return tileset def openFile(self, file): if (not file.exists()): self.mError = self.tr("File not found: %s"%file.fileName()) return False elif (not file.open(QFile.ReadOnly | QFile.Text)): self.mError = self.tr("Unable to read file: %s"%file.fileName()) return False return True def errorString(self): if self.mError != '': return self.mError else: return self.tr("%d\n\nLine %d, column %s"%(self.xml.lineNumber(), self.xml.columnNumber(), self.xml.errorString())) def __readUnknownElement(self): qDebug("Unknown element (fixme): "+self.xml.name()+" at line "+self.xml.lineNumber()+", column "+self.xml.columnNumber()) self.xml.skipCurrentElement() def __readMap(self): atts = self.xml.attributes() mapWidth = Int(atts.value("width")) mapHeight = Int(atts.value("height")) tileWidth = Int(atts.value("tilewidth")) tileHeight = Int(atts.value("tileheight")) hexSideLength = Int(atts.value("hexsidelength")) orientationString = atts.value("orientation") orientation = orientationFromString(orientationString) if (orientation == Map.Orientation.Unknown): self.xml.raiseError(self.tr("Unsupported map orientation: \"%s\""%orientationString)) staggerAxisString = atts.value("staggeraxis") staggerAxis = staggerAxisFromString(staggerAxisString) staggerIndexString = atts.value("staggerindex") staggerIndex = staggerIndexFromString(staggerIndexString) renderOrderString = atts.value("renderorder") renderOrder = renderOrderFromString(renderOrderString) nextObjectId = Int(atts.value("nextobjectid")) self.mMap = Map(orientation, mapWidth, mapHeight, tileWidth, tileHeight) self.mMap.setHexSideLength(hexSideLength) self.mMap.setStaggerAxis(staggerAxis) self.mMap.setStaggerIndex(staggerIndex) self.mMap.setRenderOrder(renderOrder) if (nextObjectId): self.mMap.setNextObjectId(nextObjectId) bgColorString = atts.value("backgroundcolor") if len(bgColorString)>0: self.mMap.setBackgroundColor(QColor(bgColorString)) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): self.mMap.mergeProperties(self.__readProperties()) elif (self.xml.name() == "tileset"): self.mMap.addTileset(self.__readTileset()) elif (self.xml.name() == "layer"): self.mMap.addLayer(self.__readLayer()) elif (self.xml.name() == "objectgroup"): self.mMap.addLayer(self.__readObjectGroup()) elif (self.xml.name() == "imagelayer"): self.mMap.addLayer(self.__readImageLayer()) else: self.__readUnknownElement() # Clean up in case of error if (self.xml.hasError()): self.mMap = None return self.mMap def __readTileset(self): atts = self.xml.attributes() source = atts.value("source") firstGid = Int(atts.value("firstgid")) tileset = None if source == '': # Not an external tileset name = atts.value("name") tileWidth = Int(atts.value("tilewidth")) tileHeight = Int(atts.value("tileheight")) tileSpacing = Int(atts.value("spacing")) margin = Int(atts.value("margin")) if (tileWidth < 0 or tileHeight < 0 or (firstGid == 0 and not self.mReadingExternalTileset)): self.xml.raiseError(self.tr("Invalid tileset parameters for tileset '%s'"%name)) else: tileset = Tileset.create(name, tileWidth, tileHeight, tileSpacing, margin) while (self.xml.readNextStartElement()): if (self.xml.name() == "tile"): self.__readTilesetTile(tileset) elif (self.xml.name() == "tileoffset"): oa = self.xml.attributes() x = Int(oa.value("x")) y = Int(oa.value("y")) tileset.setTileOffset(QPoint(x, y)) self.xml.skipCurrentElement() elif (self.xml.name() == "properties"): tileset.mergeProperties(self.__readProperties()) elif (self.xml.name() == "image"): if (tileWidth == 0 or tileHeight == 0): self.xml.raiseError(self.tr("Invalid tileset parameters for tileset '%s'"%name)) tileset.clear() break else: self.__readTilesetImage(tileset) elif (self.xml.name() == "terraintypes"): self.__readTilesetTerrainTypes(tileset) else: self.__readUnknownElement() else: # External tileset absoluteSource = self.p.resolveReference(source, self.mPath) tileset, error = self.p.readExternalTileset(absoluteSource) if (not tileset): self.xml.raiseError(self.tr("Error while loading tileset '%s': %s"%(absoluteSource, error))) self.xml.skipCurrentElement() if (tileset and not self.mReadingExternalTileset): self.mGidMapper.insert(firstGid, tileset) return tileset def __readTilesetTile(self, tileset): atts = self.xml.attributes() id = Int(atts.value("id")) if (id < 0): self.xml.raiseError(self.tr("Invalid tile ID: %d"%id)) return hasImage = tileset.imageSource()!='' if (hasImage and id >= tileset.tileCount()): self.xml.raiseError(self.tr("Tile ID does not exist in tileset image: %d"%id)) return if (id > tileset.tileCount()): self.xml.raiseError(self.tr("Invalid (nonconsecutive) tile ID: %d"%id)) return # For tilesets without image source, consecutive tile IDs are allowed (for # tiles with individual images) if (id == tileset.tileCount()): tileset.addTile(QPixmap()) tile = tileset.tileAt(id) # Read tile quadrant terrain ids terrain = atts.value("terrain") if terrain != '': quadrants = terrain.split(",") if (len(quadrants) == 4): for i in range(4): if quadrants[i]=='': t = -1 else: t = Int(quadrants[i]) tile.setCornerTerrainId(i, t) # Read tile probability probability = atts.value("probability") if probability != '': tile.setProbability(Float(probability)) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): tile.mergeProperties(self.__readProperties()) elif (self.xml.name() == "image"): source = self.xml.attributes().value("source") if source != '': source = self.p.resolveReference(source, self.mPath) tileset.setTileImage(id, QPixmap.fromImage(self.__readImage()), source) elif (self.xml.name() == "objectgroup"): tile.setObjectGroup(self.__readObjectGroup()) elif (self.xml.name() == "animation"): tile.setFrames(self.__readAnimationFrames()) else: self.__readUnknownElement() # Temporary code to support TMW-style animation frame properties if (not tile.isAnimated() and tile.hasProperty("animation-frame0")): frames = QVector() i = 0 while(i>=0): frameName = "animation-frame" + str(i) delayName = "animation-delay" + str(i) if (tile.hasProperty(frameName) and tile.hasProperty(delayName)): frame = Frame() frame.tileId = tile.property(frameName) frame.duration = tile.property(delayName) * 10 frames.append(frame) else: break i += 1 tile.setFrames(frames) def __readTilesetImage(self, tileset): atts = self.xml.attributes() source = atts.value("source") trans = atts.value("trans") if len(trans)>0: if (not trans.startswith('#')): trans = '#' + trans tileset.setTransparentColor(QColor(trans)) if len(source)>0: source = self.p.resolveReference(source, self.mPath) # Set the width that the tileset had when the map was saved width = Int(atts.value("width")) self.mGidMapper.setTilesetWidth(tileset, width) if (not tileset.loadFromImage(self.__readImage(), source)): self.xml.raiseError(self.tr("Error loading tileset image:\n'%s'"%source)) def __readTilesetTerrainTypes(self, tileset): while (self.xml.readNextStartElement()): if (self.xml.name() == "terrain"): atts = self.xml.attributes() name = atts.value("name") tile = Int(atts.value("tile")) terrain = tileset.addTerrain(name, tile) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): terrain.mergeProperties(self.__readProperties()) else: self.__readUnknownElement() else: self.__readUnknownElement() def __readImage(self): atts = self.xml.attributes() source = atts.value("source") format = atts.value("format") if len(source)==0: while (self.xml.readNextStartElement()): if (self.xml.name() == "data"): atts = self.xml.attributes() encoding = atts.value("encoding") data = self.xml.readElementText().toLatin1() if (encoding == "base64"): data = QByteArray.fromBase64(data) self.xml.skipCurrentElement() return QImage.fromData(data, format.toLatin1()) else: self.__readUnknownElement() else: self.xml.skipCurrentElement() source = self.p.resolveReference(source, self.mPath) image = self.p.readExternalImage(source) if (image.isNull()): self.xml.raiseError(self.tr("Error loading image:\n'%s'"%source)) return image return QImage() def __readLayer(self): atts = self.xml.attributes() name = atts.value("name") x = Int(atts.value("x")) y = Int(atts.value("y")) width = Int(atts.value("width")) height = Int(atts.value("height")) tileLayer = TileLayer(name, x, y, width, height) readLayerAttributes(tileLayer, atts) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): tileLayer.mergeProperties(self.__readProperties()) elif (self.xml.name() == "data"): self.__readLayerData(tileLayer) else: self.__readUnknownElement() return tileLayer def __readLayerData(self, tileLayer): atts = self.xml.attributes() encoding = atts.value("encoding") compression = atts.value("compression") layerDataFormat = 0 if (encoding == ''): layerDataFormat = Map.LayerDataFormat.XML elif (encoding == "csv"): layerDataFormat = Map.LayerDataFormat.CSV elif (encoding == "base64"): if (compression == ''): layerDataFormat = Map.LayerDataFormat.Base64 elif (compression == "gzip"): layerDataFormat = Map.LayerDataFormat.Base64Gzip elif (compression == "zlib"): layerDataFormat = Map.LayerDataFormat.Base64Zlib else: self.xml.raiseError(self.tr("Compression method '%s' not supported"%compression)) return else: self.xml.raiseError(self.tr("Unknown encoding: %s"%encoding)) return self.mMap.setLayerDataFormat(layerDataFormat) x = 0 y = 0 while (self.xml.readNext() != QXmlStreamReader.Invalid): if (self.xml.isEndElement()): break elif (self.xml.isStartElement()): if (self.xml.name() == "tile"): if (y >= tileLayer.height()): self.xml.raiseError(self.tr("Too many <tile> elements")) continue atts = self.xml.attributes() gid = Int(atts.value("gid")) tileLayer.setCell(x, y, self.__cellForGid(gid)) x += 1 if (x >= tileLayer.width()): x = 0 y += 1 self.xml.skipCurrentElement() else: self.__readUnknownElement() elif (self.xml.isCharacters() and not self.xml.isWhitespace()): if (encoding == "base64"): self.__decodeBinaryLayerData(tileLayer, self.xml.text(), layerDataFormat) elif (encoding == "csv"): self.__decodeCSVLayerData(tileLayer, self.xml.text()) def __decodeBinaryLayerData(self, tileLayer, data, format): error = self.mGidMapper.decodeLayerData(tileLayer, data, format) if error==DecodeError.CorruptLayerData: self.xml.raiseError(self.tr("Corrupt layer data for layer '%s'"%tileLayer.name())) return elif error==DecodeError.TileButNoTilesets: self.xml.raiseError(self.tr("Tile used but no tilesets specified")) return elif error==DecodeError.InvalidTile: self.xml.raiseError(self.tr("Invalid tile: %d"%self.mGidMapper.invalidTile())) return elif error==DecodeError.NoError: pass def __decodeCSVLayerData(self, tileLayer, text): trimText = text.strip() tiles = trimText.split(',') if (len(tiles) != tileLayer.width() * tileLayer.height()): self.xml.raiseError(self.tr("Corrupt layer data for layer '%s'"%tileLayer.name())) return for y in range(tileLayer.height()): for x in range(tileLayer.width()): conversionOk = False gid, conversionOk = Int2(tiles[y * tileLayer.width() + x]) if (not conversionOk): self.xml.raiseError(self.tr("Unable to parse tile at (%d,%d) on layer '%s'"%(x + 1, y + 1, tileLayer.name()))) return tileLayer.setCell(x, y, self.__cellForGid(gid)) ## # Returns the cell for the given global tile ID. Errors are raised with # the QXmlStreamReader. # # @param gid the global tile ID # @return the cell data associated with the given global tile ID, or an # empty cell if not found ## def __cellForGid(self, gid): ok = False result, ok = self.mGidMapper.gidToCell(gid) if (not ok): if (self.mGidMapper.isEmpty()): self.xml.raiseError(self.tr("Tile used but no tilesets specified")) else: self.xml.raiseError(self.tr("Invalid tile: %d"%gid)) return result def __readImageLayer(self): atts = self.xml.attributes() name = atts.value("name") x = Int(atts.value("x")) y = Int(atts.value("y")) width = Int(atts.value("width")) height = Int(atts.value("height")) imageLayer = ImageLayer(name, x, y, width, height) readLayerAttributes(imageLayer, atts) while (self.xml.readNextStartElement()): if (self.xml.name() == "image"): self.__readImageLayerImage(imageLayer) elif (self.xml.name() == "properties"): imageLayer.mergeProperties(self.__readProperties()) else: self.__readUnknownElement() return imageLayer def __readImageLayerImage(self, imageLayer): atts = self.xml.attributes() source = atts.value("source") trans = atts.value("trans") if trans != '': if (not trans.startswith('#')): trans = '#' + trans imageLayer.setTransparentColor(QColor(trans)) source = self.p.resolveReference(source, self.mPath) imageLayerImage = self.p.readExternalImage(source) if (not imageLayer.loadFromImage(imageLayerImage, source)): self.xml.raiseError(self.tr("Error loading image layer image:\n'%s'"%source)) self.xml.skipCurrentElement() def __readObjectGroup(self): atts = self.xml.attributes() name = atts.value("name") x = Int(atts.value("x")) y = Int(atts.value("y")) width = Int(atts.value("width")) height = Int(atts.value("height")) objectGroup = ObjectGroup(name, x, y, width, height) readLayerAttributes(objectGroup, atts) color = atts.value("color") if color != '': objectGroup.setColor(color) if (atts.hasAttribute("draworder")): value = atts.value("draworder") drawOrder = drawOrderFromString(value) if (drawOrder == ObjectGroup.DrawOrder.UnknownOrder): #del objectGroup self.xml.raiseError(self.tr("Invalid draw order: %s"%value)) return None objectGroup.setDrawOrder(drawOrder) while (self.xml.readNextStartElement()): if (self.xml.name() == "object"): objectGroup.addObject(self.__readObject()) elif (self.xml.name() == "properties"): objectGroup.mergeProperties(self.__readProperties()) else: self.__readUnknownElement() return objectGroup def __readObject(self): atts = self.xml.attributes() id = Int(atts.value("id")) name = atts.value("name") gid = Int(atts.value("gid")) x = Float(atts.value("x")) y = Float(atts.value("y")) width = Float(atts.value("width")) height = Float(atts.value("height")) type = atts.value("type") visibleRef = atts.value("visible") pos = QPointF(x, y) size = QSizeF(width, height) object = MapObject(name, type, pos, size) object.setId(id) try: rotation = Float(atts.value("rotation")) ok = True except: ok = False if (ok): object.setRotation(rotation) if (gid): object.setCell(self.__cellForGid(gid)) if (not object.cell().isEmpty()): tileSize = object.cell().tile.size() if (width == 0): object.setWidth(tileSize.width()) if (height == 0): object.setHeight(tileSize.height()) try: visible = int(visibleRef) ok = True except: ok = False if ok: object.setVisible(visible) while (self.xml.readNextStartElement()): if (self.xml.name() == "properties"): object.mergeProperties(self.__readProperties()) elif (self.xml.name() == "polygon"): object.setPolygon(self.__readPolygon()) object.setShape(MapObject.Polygon) elif (self.xml.name() == "polyline"): object.setPolygon(self.__readPolygon()) object.setShape(MapObject.Polyline) elif (self.xml.name() == "ellipse"): self.xml.skipCurrentElement() object.setShape(MapObject.Ellipse) else: self.__readUnknownElement() return object def __readPolygon(self): atts = self.xml.attributes() points = atts.value("points") pointsList = list(filter(lambda x:x.strip()!='', points.split(' '))) polygon = QPolygonF() ok = True for point in pointsList: try: x, y = point.split(',') except: ok = False break x, ok = Float2(x) if (not ok): break y, ok = Float2(y) if (not ok): break polygon.append(QPointF(x, y)) if (not ok): self.xml.raiseError(self.tr("Invalid points data for polygon")) self.xml.skipCurrentElement() return polygon def __readAnimationFrames(self): frames = QVector() while (self.xml.readNextStartElement()): if (self.xml.name() == "frame"): atts = self.xml.attributes() frame = Frame() frame.tileId = Int(atts.value("tileid")) frame.duration = Int(atts.value("duration")) frames.append(frame) self.xml.skipCurrentElement() else: self.__readUnknownElement() return frames def __readProperties(self): properties = Properties() while (self.xml.readNextStartElement()): if (self.xml.name() == "property"): self.__readProperty(properties) else: self.__readUnknownElement() return properties def __readProperty(self, properties): atts = self.xml.attributes() propertyName = atts.value("name") propertyValue = atts.value("value") while (self.xml.readNext() != QXmlStreamReader.Invalid): if (self.xml.isEndElement()): break elif (self.xml.isCharacters() and not self.xml.isWhitespace()): if (propertyValue.isEmpty()): propertyValue = self.xml.text() elif (self.xml.isStartElement()): self.__readUnknownElement() properties.insert(propertyName, propertyValue)
def read(self, fileName): file = QFile(fileName) if (not file.open (QIODevice.ReadOnly)): self.mError = self.tr("Could not open file for reading.") return None # default to values of the original flare alpha game. map = Map(Map.Orientation.Isometric, 256, 256, 64, 32) stream = QTextStream(file) line = QString() sectionName = QString() newsection = False path = QFileInfo(file).absolutePath() base = 10 gidMapper = GidMapper() gid = 1 tilelayer = None objectgroup = None mapobject = None tilesetsSectionFound = False headerSectionFound = False tilelayerSectionFound = False # tile layer or objects while (not stream.atEnd()): line = stream.readLine() if line == '': continue startsWith = line[0] if (startsWith == '['): sectionName = line[1:line.index(']')] newsection = True continue if (sectionName == "header"): headerSectionFound = True #get map properties epos = line.index('=') if (epos != -1): key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "width"): map.setWidth(Int(value)) elif (key == "height"): map.setHeight(Int(value)) elif (key == "tilewidth"): map.setTileWidth(Int(value)) elif (key == "tileheight"): map.setTileHeight(Int(value)) elif (key == "orientation"): map.setOrientation(orientationFromString(value)) else: map.setProperty(key, value) elif (sectionName == "tilesets"): tilesetsSectionFound = True epos = line.index('=') key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "tileset"): _list = value.split(',') absoluteSource = _list[0] if (QDir.isRelativePath(absoluteSource)): absoluteSource = path + '/' + absoluteSource tilesetwidth = 0 tilesetheight = 0 if len(_list) > 2: tilesetwidth = Int(_list[1]) tilesetheight = Int(_list[2]) tileset = Tileset.create(QFileInfo(absoluteSource).fileName(), tilesetwidth, tilesetheight) ok = tileset.loadFromImage(absoluteSource) if not ok: self.mError = self.tr("Error loading tileset %s, which expands to %s. Path not found!"%(_list[0], absoluteSource)) return None else : if len(_list) > 4: tileset.setTileOffset(QPoint(Int(_list[3]),Int(_list[4]))) gidMapper.insert(gid, tileset) if len(_list) > 5: gid += Int(_list[5]) else : gid += tileset.tileCount() map.addTileset(tileset) elif (sectionName == "layer"): if (not tilesetsSectionFound): self.mError = self.tr("No tilesets section found before layer section.") return None tilelayerSectionFound = True epos = line.index('=') if (epos != -1): key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "type"): tilelayer = TileLayer(value, 0, 0, map.width(),map.height()) map.addLayer(tilelayer) elif (key == "format"): if (value == "dec"): base = 10 elif (value == "hex"): base = 16 elif (key == "data"): for y in range(map.height()): line = stream.readLine() l = line.split(',') for x in range(min(map.width(), len(l))): ok = False tileid = int(l[x], base) c, ok = gidMapper.gidToCell(tileid) if (not ok): self.mError += self.tr("Error mapping tile id %1.").arg(tileid) return None tilelayer.setCell(x, y, c) else : tilelayer.setProperty(key, value) else : if (newsection): if (map.indexOfLayer(sectionName) == -1): objectgroup = ObjectGroup(sectionName, 0,0,map.width(), map.height()) map.addLayer(objectgroup) else : objectgroup = map.layerAt(map.indexOfLayer(sectionName)) mapobject = MapObject() objectgroup.addObject(mapobject) newsection = False if (not mapobject): continue if (startsWith == '#'): name = line[1].strip() mapobject.setName(name) epos = line.index('=') if (epos != -1): key = line[:epos].strip() value = line[epos + 1:].strip() if (key == "type"): mapobject.setType(value) elif (key == "location"): loc = value.split(',') x,y = 0.0, 0.0 w,h = 0, 0 if (map.orientation() == Map.Orthogonal): x = loc[0].toFloat()*map.tileWidth() y = loc[1].toFloat()*map.tileHeight() if len(loc) > 3: w = Int(loc[2])*map.tileWidth() h = Int(loc[3])*map.tileHeight() else : w = map.tileWidth() h = map.tileHeight() else : x = loc[0].toFloat()*map.tileHeight() y = loc[1].toFloat()*map.tileHeight() if len(loc) > 3: w = Int(loc[2])*map.tileHeight() h = Int(loc[3])*map.tileHeight() else : w = h = map.tileHeight() mapobject.setPosition(QPointF(x, y)) mapobject.setSize(w, h) else : mapobject.setProperty(key, value) if (not headerSectionFound or not tilesetsSectionFound or not tilelayerSectionFound): self.mError = self.tr("This seems to be no valid flare map. " "A Flare map consists of at least a header " "section, a tileset section and one tile layer.") return None return map