class CityView(layout.Spacer): def __init__(self): super(CityView, self).__init__() self.tileImageLoader = TileImageLoader( gui.config.get('misc', 'TILES_FILE'), TILESIZE, flipTilesVert=True, padding=2) self.tBatch = pyglet.graphics.Batch() self.viewportGroup = ViewportGroup(BG_RENDER_ORDER) self.blinkingGroup = BlinkingGroup(MG_RENDER_ORDER, self.viewportGroup) self.toolCursorGroup = ToolCursorGroup(FG_RENDER_ORDER, self.viewportGroup) self.tileMapRenderer = TileMapRenderer(self.tileImageLoader, self.viewportGroup) self.toolCursor = None self.toolPreview = None self.noPowerIndicators = None self.noPowerIndicatorImg = self.tileImageLoader.getTileImage(tileConstants.LIGHTNINGBOLT) self.keys = microWindow.Keys(self) self.scrollSpeed = gui.config.getInt('misc', 'KEYBOARD_SCROLL_SPEED') def setRenderSize(self, width, height): self.renderWidth = width self.renderHeight = height def size(self, frame): super(CityView, self).size(frame) def layout(self, x, y): super(CityView, self).layout(x, y) self.viewportGroup.setViewportSize( (self.width, self.height), (self.renderWidth, self.renderHeight)) ''' To be called when city engine has changed, to update cityview to new engine. ''' def resetEng(self, eng): self.viewportGroup.setFocus(0, 0) self.toolPreview = None self.deletePowerIndicators() self.deleteToolCursor() self.tileMapRenderer.resetEng(eng) if eng is not None: eng.push_handlers(self) self.mapWidth = eng.getWidth() self.mapHeight = eng.getHeight() self.viewportGroup.setMapSize(self.mapWidth * TILESIZE, self.mapHeight * TILESIZE) self.noPowerIndicators = create2dArray(self.mapWidth, self.mapHeight, None) def deletePowerIndicators(self): if not self.noPowerIndicators: return for y in xrange(self.mapHeight): for x in xrange(self.mapWidth): if self.noPowerIndicators[x][y] is not None: self.noPowerIndicators[x][y].delete() self.noPowerIndicators[x][y] = None self.noPowerIndicators = None ''' modifies tile batch with tilesList ''' def on_map_changed(self, tilesList): for tile in tilesList: x = tile[0] y = tile[1] self.tileMapRenderer.setTile(x, y, tile[2]) def on_power_indicator_changed(self, ind): x = ind[0] y = ind[1] value = ind[2] if value and self.noPowerIndicators[x][y] is None: x2 = x * TILESIZE y2 = y * TILESIZE + TILESIZE self.noPowerIndicators[x][y] = Sprite(self.noPowerIndicatorImg, batch=self.parentFrame.batch, group=self.blinkingGroup, x=x2, y=y2) elif self.noPowerIndicators[x][y] is not None: self.noPowerIndicators[x][y].delete() self.noPowerIndicators[x][y] = None def getHeight(self): return self.height def getWidth(self): return self.width def deleteToolCursor(self): if self.toolCursor is not None: self.toolCursor.vl.delete() self.toolCursor.borderVL.delete() self.toolCursor = None def setToolCursor(self, newCursor): ''' ''' if (self.toolCursor is None and self.toolCursor == newCursor): return self.deleteToolCursor() self.toolCursor = newCursor if self.toolCursor is not None: x, y, x2, y2 = self.expandMapCoords(self.toolCursor.rect) width = x2 - x height = y2 - y self.toolCursor.vl = createRect(x, y, width, height, self.toolCursor.fillColor, self.parentFrame.batch, self.toolCursorGroup) self.toolCursor.borderVL = createHollowRect( x, y, width, height, self.toolCursor.borderColor, self.parentFrame.batch, self.toolCursorGroup) def newToolCursor(self, newRect, tool): ''' ''' if self.toolCursor and self.toolCursor.rect.equals(newRect): return newCursor = ToolCursor() newCursor.rect = newRect borderColor = gui.config.get('tools.bordercolor', tool.name) newCursor.borderColor = list(map(int, tuple(borderColor.split(',')))) bgColor = gui.config.get('tools.bgcolor', tool.name) newCursor.fillColor = list(map(int, tuple(bgColor.split(',')))) self.setToolCursor(newCursor) ''' Shows the given preview's tiles in place. If a preview already exists, resets those tiles. ''' def setToolPreview(self, newPreview): if self.toolPreview is not None: # reset old preview tile sprites: b = self.toolPreview.getBounds() for x in xrange(b.width): for y in xrange(b.height): self.tileMapRenderer.resetTile(x + b.x, y + b.y) if newPreview is not None: # set new preview tile sprites b = newPreview.getBounds() for y in xrange(b.height): for x in xrange(b.width): x2 = x - newPreview.offsetX y2 = y - newPreview.offsetY tNum = newPreview.getTile(x2, y2) if tNum != CLEAR: self.tileMapRenderer.setTile(x2, y2, tNum) self.toolPreview = newPreview ''' world-space coordinates of tile coord ''' @staticmethod def expandMapCoords(rect): x = int(rect.x * TILESIZE) y = int((rect.y - 1) * TILESIZE + TILESIZE) x2 = int(x + rect.width * TILESIZE) y2 = int(y + rect.height * TILESIZE) return x, y, x2, y2 ''' given window-space coords will return CityLocation object through viewportGroup ''' def screenCoordsToCityLocation(self, x, y): return self.viewportGroup.screenCoordsToCityLocation(x, y) def key_release(self, symbol, modifiers): if symbol == key.EQUAL: self.changeZoom(increment=1) if symbol == key.MINUS: self.changeZoom(increment=-1) if symbol == key._0: self.changeZoom(newValue=1.0) ''' random tests: ''' if symbol == key.A: self.viewportGroup.gotoSpot(500, 400, 0.86) if symbol == key.I: self.tileMapRenderer.setTile(3, 3, 56) ''' pass one value but not both. changeZoom increments ''' def changeZoom(self, newValue=None, increment=None): def finishedZoom(): self.tileMapRenderer.setVisibleRegion(*self.viewportGroup.getViewport()) assert newValue or increment and not (newValue and increment) if increment: self.viewportGroup.changeZoom(self.width // 2, self.height // 2, -increment) else: self.viewportGroup.setZoom(self.width // 2, self.height // 2, newValue, callback=finishedZoom) self.tileMapRenderer.setVisibleRegion(*self.viewportGroup.getViewport()) def zoomToPoint(self, x, y, change): self.viewportGroup.changeZoom(x, y, -change) self.tileMapRenderer.setVisibleRegion(*self.viewportGroup.getViewport()) def moveView(self, mx, my): self.viewportGroup.changeFocus(mx, my) self.tileMapRenderer.setVisibleRegion(*self.viewportGroup.getViewport()) def setSpeed(self, speed): pyglet.clock.unschedule(self.tileMapRenderer.update) if speed == speeds['Paused']: self.blinkingGroup.stop() else: self.blinkingGroup.start() pyglet.clock.schedule_interval(self.tileMapRenderer.update, speed.animCoefficient) def _checkScrollKeys(self, dt): # move 12 tiles per second delta = int(self.scrollSpeed * TILESIZE * dt) if self.keys[key.LEFT]: self.moveView(delta, 0) elif self.keys[key.RIGHT]: self.moveView(-delta, 0) if self.keys[key.DOWN]: self.moveView(0, delta) elif self.keys[key.UP]: self.moveView(0, -delta) def update(self, dt): self._checkScrollKeys(dt) self.blinkingGroup.update(dt) self.viewportGroup.update(dt) def draw(self): self.tileMapRenderer.draw()