def __init__(self, server_scenario): super().__init__() self._cursors = {} self._cursor_not_allowed = {} workforce_action_cursor_settings = server_scenario.get_workforce_action_cursor_settings( ) for workforce_type in workforce_action_cursor_settings: if workforce_type not in self._cursors: self._cursors[workforce_type] = {} self._cursors[workforce_type][ WorkforceAction.MOVE] = QtGui.QCursor( QtGui.QPixmap( constants.extend( constants.GRAPHICS_MAP_ICON_FOLDER, workforce_action_cursor_settings[workforce_type] ['workforce_action_cursor_move']))) self._cursors[workforce_type][ WorkforceAction.DUTY_ACTION] = QtGui.QCursor( QtGui.QPixmap( constants.extend( constants.GRAPHICS_MAP_ICON_FOLDER, workforce_action_cursor_settings[workforce_type] ['workforce_action_cursor_duty_action']))) self._cursor_not_allowed[workforce_type] = QtGui.QCursor( QtGui.QPixmap( constants.extend( constants.GRAPHICS_MAP_ICON_FOLDER, workforce_action_cursor_settings[workforce_type] ['workforce_action_cursor_not_allowed'])))
def __init__(self, server_scenario): super().__init__() workforce_settings = server_scenario.get_workforce_settings() self.pixmaps_stand = {} self.pixmaps_on_duty = {} for workforce_type in workforce_settings: pixmap_stand = QtGui.QPixmap( constants.extend( constants.GRAPHICS_WORKFORCE_FOLDER, workforce_settings[workforce_type] ['texture_filename_stand'])) self.pixmaps_stand[workforce_type] = pixmap_stand.scaled( constants.WORKFORCE_SIZE[0], constants.WORKFORCE_SIZE[1]) duty_image = QtGui.QImage( constants.extend( constants.GRAPHICS_WORKFORCE_FOLDER, workforce_settings[workforce_type] ['texture_filename_on_duty'])) # must be sure that sprite is divided evenly hor_count = int(duty_image.width() / constants.WORKFORCE_SIZE[0]) ver_count = int(duty_image.height() / constants.WORKFORCE_SIZE[1]) width = constants.WORKFORCE_SIZE[0] height = constants.WORKFORCE_SIZE[1] self.pixmaps_on_duty[workforce_type] = [ QtGui.QPixmap.fromImage( duty_image.copy(row * height, col * width, width, height)).scaled( constants.WORKFORCE_SIZE[0], constants.WORKFORCE_SIZE[1]) for row in range(hor_count) for col in range(ver_count) ]
def __init__(self, client): super().__init__() self.setAttribute(QtCore.Qt.WA_StyledBackground) self.setProperty('background', 'black') layout = qt.RelativeLayout(self) start_image = QtGui.QPixmap(constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.background.jpg')) start_image_item = QtWidgets.QGraphicsPixmapItem(start_image) start_image_item.setZValue(1) scene = QtWidgets.QGraphicsScene(self) scene.addItem(start_image_item) view = QtWidgets.QGraphicsView(scene) view.resize(start_image.size()) view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setSceneRect(0, 0, start_image.width(), start_image.height()) view.layout_constraint = qt.RelativeLayoutConstraint().center_horizontal().center_vertical() layout.addWidget(view) subtitle = QtWidgets.QLabel('') subtitle.layout_constraint = qt.RelativeLayoutConstraint((0.5, -0.5, 0), (0.5, -0.5, start_image.height() / 2 + 20)) layout.addWidget(subtitle) actions = {'exit': client.quit, 'help': client.show_help_browser, 'lobby': client.show_game_lobby_dialog, 'editor': client.switch_to_editor_screen, 'options': client.show_preferences_dialog} image_map_file = constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.overlay.info') image_map = utils.read_as_yaml(image_map_file) # security check, they have to be the same if actions.keys() != image_map.keys(): raise RuntimeError('Start screen hot map info file ({}) corrupt.'.format(image_map_file)) for k, v in image_map.items(): # add action from our predefined action dictionary pixmap = QtGui.QPixmap(constants.extend(constants.GRAPHICS_UI_FOLDER, v['overlay'])) map_item = MapItem(view, pixmap, label=subtitle, description=v['label']) map_item.item.setZValue(3) offset = v['offset'] map_item.item.setOffset(QtCore.QPointF(offset[0], offset[1])) map_item.item.signaller.clicked.connect(actions[k]) frame_path = QtGui.QPainterPath() frame_path.addRect(map_item.item.boundingRect()) frame_item = scene.addPath(frame_path, StartScreen.frame_pen) frame_item.setZValue(4) scene.addItem(map_item.item) version_label = QtWidgets.QLabel('<font color=#ffffff>{}</font>'.format(version.__version_full__)) version_label.layout_constraint = qt.RelativeLayoutConstraint().east(20).south(20) layout.addWidget(version_label)
def __init__(self, *args, **kwargs): """ All the necessary initializations. Is shown at the end. """ super().__init__(*args, **kwargs) # set geometry self.setGeometry(tools.get_option(constants.Option.MAINWINDOW_BOUNDS)) # set title self.setWindowTitle('Imperialism Remake') # just a layout but nothing else self.layout = QtWidgets.QHBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.content = None # show in full screen, maximized or normal if tools.get_option(constants.Option.MAINWINDOW_FULLSCREEN): self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint) self.showFullScreen() elif tools.get_option(constants.Option.MAINWINDOW_MAXIMIZED): self.showMaximized() else: self.show() # loading animation # TODO animation right and start, stop in client self.animation = QtGui.QMovie( constants.extend(constants.GRAPHICS_UI_FOLDER, 'loading.gif')) # self.animation.start() self.loading_label = QtWidgets.QLabel( self, flags=QtCore.Qt.FramelessWindowHint | QtCore.Qt.Window) self.loading_label.setAttribute(QtCore.Qt.WA_TranslucentBackground) self.loading_label.setMovie(self.animation)
def __init__(self, *args, **kwargs): """ All the necessary initializations. Is shown at the end. """ super().__init__(*args, **kwargs) # set geometry self.setGeometry(tools.get_option(constants.Option.MAINWINDOW_BOUNDS)) # set icon self.setWindowIcon(tools.load_ui_icon('window.icon.ico')) # set title self.setWindowTitle('Imperialism Remake') # just a layout but nothing else self.layout = QtWidgets.QHBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.content = None # show in full screen, maximized or normal if tools.get_option(constants.Option.MAINWINDOW_FULLSCREEN): self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint) self.showFullScreen() elif tools.get_option(constants.Option.MAINWINDOW_MAXIMIZED): self.showMaximized() else: self.show() # loading animation # TODO animation right and start, stop in client self.animation = QtGui.QMovie(constants.extend(constants.GRAPHICS_UI_FOLDER, 'loading.gif')) # self.animation.start() self.loading_label = QtWidgets.QLabel(self, flags=QtCore.Qt.FramelessWindowHint | QtCore.Qt.Window) self.loading_label.setAttribute(QtCore.Qt.WA_TranslucentBackground) self.loading_label.setMovie(self.animation)
def from_file(file_path): """ Load/deserialize all internal variables from a zipped archive via YAML. """ # TODO what if not a valid scenario file, we should raise an error then scenario = Scenario() reader = utils.ZipArchiveReader(file_path) scenario._properties = reader.read_as_yaml( constants.SCENARIO_FILE_PROPERTIES) scenario._maps = reader.read_as_yaml(constants.SCENARIO_FILE_MAPS) scenario._provinces = reader.read_as_yaml( constants.SCENARIO_FILE_PROVINCES) # TODO check all ids are smaller then len() scenario._nations = reader.read_as_yaml( constants.SCENARIO_FILE_NATIONS) # TODO check all ids are smaller then len() # read rule file # TODO how to specify which rules file apply rule_file = constants.extend( constants.SCENARIO_RULESET_FOLDER, scenario[constants.ScenarioProperty.RULES]) scenario._rules = utils.read_as_yaml(rule_file) return scenario
def create(self, properties): """ Create new scenario (from the create new scenario dialog). :param properties: """ logger.debug('create properties:%s', properties) self.server_scenario = ServerScenario(ServerScenarioBase()) self.server_scenario[constants.ScenarioProperty.TITLE] = properties[ constants.ScenarioProperty.TITLE] self.server_scenario.create_empty_map( properties[constants.ScenarioProperty.MAP_COLUMNS], properties[constants.ScenarioProperty.MAP_ROWS]) # standard rules self.server_scenario[ constants.ScenarioProperty.RULES] = 'standard.rules' # self.scenario.load_rules() # TODO rules as extra? rule_file = constants.extend( constants.SCENARIO_RULESET_FOLDER, self.server_scenario[constants.ScenarioProperty.RULES]) self.server_scenario.get_scenario_base()._rules = utils.read_from_file( rule_file) self._init()
def load_ui_icon(name): """ Loads an icon from a base icon path. :param name: :return: """ file_name = constants.extend(constants.GRAPHICS_UI_FOLDER, name) return QtGui.QIcon(file_name)
def __init__(self, settings, folder, property_filename): super().__init__() self.pixmaps = {} for texture_type in settings: pixmap = QtGui.QPixmap( constants.extend(folder, settings[texture_type][property_filename])) self.pixmaps[texture_type] = pixmap.scaled(constants.TILE_SIZE, constants.TILE_SIZE)
def _draw_towns_and_names(self) -> None: logger.debug("_draw_towns_and_names") # draw towns and names city_pixmap = QtGui.QPixmap( constants.extend(constants.GRAPHICS_MAP_FOLDER, 'city.png')) for nation in self.scenario.server_scenario.nations(): # get all provinces of this nation provinces = self.scenario.server_scenario.provinces_of_nation( nation) for province in provinces: column, row = self.scenario.server_scenario.province_property( province, constants.ProvinceProperty.TOWN_LOCATION) sx, sy = scene_position(column, row) # center city image on center of tile scene_utils.put_pixmap_in_tile_center(self.scene, city_pixmap, sx, sy, 6) # display province name below province_name = self.scenario.server_scenario.province_property( province, constants.ProvinceProperty.NAME) item = self.scene.addSimpleText(province_name) item.setPen(qt.TRANSPARENT_PEN) item.setBrush(QtGui.QBrush(QtCore.Qt.darkRed)) x = (sx + 0.5 ) * constants.TILE_SIZE - item.boundingRect().width() / 2 y = (sy + 1) * constants.TILE_SIZE - item.boundingRect().height() item.setPos(x, y) item.setZValue(6) # display rounded rectangle below province name bx = 8 by = 4 background = QtCore.QRectF( x - bx, y - by, item.boundingRect().width() + 2 * bx, item.boundingRect().height() + 2 * by) path = QtGui.QPainterPath() path.addRoundedRect(background, 50, 50) item = self.scene.addPath(path, pen=qt.TRANSPARENT_PEN, brush=QtGui.QBrush( QtGui.QColor(128, 128, 255, 64))) item.setZValue(5)
def create(self, properties): """ Create new scenario (from the create new scenario dialog). :param properties: """ self.scenario = Scenario() self.scenario[constants.ScenarioProperty.TITLE] = properties[constants.ScenarioProperty.TITLE] self.scenario.create_empty_map(properties[constants.ScenarioProperty.MAP_COLUMNS], properties[constants.ScenarioProperty.MAP_ROWS]) # standard rules self.scenario[constants.ScenarioProperty.RULES] = 'standard.rules' # self.scenario.load_rules() # TODO rules as extra? rule_file = constants.extend(constants.SCENARIO_RULESET_FOLDER, self.scenario[constants.ScenarioProperty.RULES]) self.scenario._rules = utils.read_as_yaml(rule_file) # emit that everything has changed self.changed.emit()
def load_soundtrack_playlist(): """ Loads the play list of the soundtracks and replaces the file name with the full path. A playlist is a list where each entry is a list of two strings: file path, title """ global soundtrack_playlist # create playlist soundtrack_playlist = QtMultimedia.QMediaPlaylist() soundtrack_playlist.setPlaybackMode(QtMultimedia.QMediaPlaylist.Loop) # read information file data = utils.read_as_yaml(constants.SOUNDTRACK_INFO_FILE) # add the soundtrack folder to each file name for entry in data: file = constants.extend(constants.SOUNDTRACK_FOLDER, entry[0]) url = qt.local_url(file) media = QtMultimedia.QMediaContent(url) soundtrack_playlist.addMedia(media)
def from_file(file_path): """ Load/deserialize all internal variables from a zipped archive """ # TODO what if not a valid scenario file, we should raise an error then logger.debug('from_file file: %s', file_path) server_scenario = ServerScenario(ServerScenarioBase()) reader = utils.ZipArchiveReader(file_path) server_scenario.get_scenario_base().properties = reader.read_from_file( constants.SCENARIO_FILE_PROPERTIES) server_scenario.get_scenario_base().maps = reader.read_from_file( constants.SCENARIO_FILE_MAPS) server_scenario.get_scenario_base().provinces = reader.read_from_file( constants.SCENARIO_FILE_PROVINCES) # TODO check all ids are smaller then len() server_scenario.get_scenario_base().nations = reader.read_from_file( constants.SCENARIO_FILE_NATIONS) # TODO check all ids are smaller then len() # read rule file # TODO how to specify which rules file apply rule_file = constants.extend( constants.SCENARIO_RULESET_FOLDER, server_scenario[constants.ScenarioProperty.RULES]) server_scenario.get_scenario_base().rules = utils.read_from_file( rule_file) if ServerScenarioBase.ROAD not in server_scenario._scenario_base.maps: server_scenario._scenario_base.maps[ServerScenarioBase.ROAD] = [] if ServerScenarioBase.STRUCTURE not in server_scenario._scenario_base.maps: server_scenario._scenario_base.maps[ ServerScenarioBase.STRUCTURE] = {} return server_scenario
def from_file(file_name): """ Load/deserialize all internal variables from a zipped archive via YAML. """ scenario = Scenario() reader = utils.ZipArchiveReader(file_name) scenario._properties = reader.read_as_yaml(constants.SCENARIO_FILE_PROPERTIES) scenario._maps = reader.read_as_yaml(constants.SCENARIO_FILE_MAPS) scenario._provinces = reader.read_as_yaml(constants.SCENARIO_FILE_PROVINCES) # TODO check all ids are smaller then len() scenario._nations = reader.read_as_yaml(constants.SCENARIO_FILE_NATIONS) # TODO check all ids are smaller then len() # read rule file # TODO how to specify which rules file apply rule_file = constants.extend(constants.SCENARIO_RULESET_FOLDER, scenario[constants.ScenarioProperty.RULES]) scenario._rules = utils.read_as_yaml(rule_file) return scenario
def __init__(self, client): super().__init__() self.setAttribute(QtCore.Qt.WA_StyledBackground) self.setProperty('background', 'black') layout = qt.RelativeLayout(self) start_image = QtGui.QPixmap( constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.background.jpg')) start_image_item = QtWidgets.QGraphicsPixmapItem(start_image) start_image_item.setZValue(1) scene = QtWidgets.QGraphicsScene(self) scene.addItem(start_image_item) view = QtWidgets.QGraphicsView(scene) view.resize(start_image.size()) view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setSceneRect(0, 0, start_image.width(), start_image.height()) view.layout_constraint = qt.RelativeLayoutConstraint( ).center_horizontal().center_vertical() layout.addWidget(view) subtitle = QtWidgets.QLabel('') subtitle.layout_constraint = qt.RelativeLayoutConstraint( (0.5, -0.5, 0), (0.5, -0.5, start_image.height() / 2 + 20)) layout.addWidget(subtitle) actions = { 'exit': client.quit, 'help': client.show_help_browser, 'lobby': client.show_game_lobby_dialog, 'editor': client.switch_to_editor_screen, 'options': client.show_preferences_dialog } image_map_file = constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.overlay.info') image_map = utils.read_as_yaml(image_map_file) # security check, they have to be the same if list(actions.keys()) != list(image_map.keys()): raise RuntimeError( 'Start screen hot map info file ({}) corrupt.'.format( image_map_file)) for k, v in list(image_map.items()): # add action from our predefined action dictionary pixmap = QtGui.QPixmap( constants.extend(constants.GRAPHICS_UI_FOLDER, v['overlay'])) map_item = MapItem(view, pixmap, label=subtitle, description=v['label']) map_item.item.setZValue(3) offset = v['offset'] map_item.item.setOffset(QtCore.QPointF(offset[0], offset[1])) map_item.item.signaller.clicked.connect(actions[k]) frame_path = QtGui.QPainterPath() frame_path.addRect(map_item.item.boundingRect()) frame_item = scene.addPath(frame_path, StartScreen.frame_pen) frame_item.setZValue(4) scene.addItem(map_item.item) version_label = QtWidgets.QLabel( '<font color=#ffffff>{}</font>'.format(version.__version_full__)) version_label.layout_constraint = qt.RelativeLayoutConstraint().east( 20).south(20) layout.addWidget(version_label)
if __name__ == '__main__': # add source directory to path if needed source_directory = os.path.realpath( os.path.join(os.path.abspath(os.path.dirname(__file__)), os.path.pardir, os.path.pardir, 'source')) if source_directory not in sys.path: sys.path.insert(0, source_directory) from imperialism_remake.base import constants from imperialism_remake.server.scenario import Scenario # load scenario scenario = Scenario.from_file( constants.extend(constants.CORE_SCENARIO_FOLDER, 'Europe1814.scenario')) # nation map columns = scenario[constants.ScenarioProperty.MAP_COLUMNS] rows = scenario[constants.ScenarioProperty.MAP_ROWS] map = [0] * (columns * rows) for nation in scenario.nations(): provinces = scenario.provinces_of_nation(nation) for province in provinces: tiles = scenario.province_property(province, 'tiles') for column, row in tiles: map[row * columns + column] = nation # get outlines for nation in scenario.nations(): visited = [False] * (columns * rows)
def create_start_screen_widget(actions): """ Creates the start screen. :param client: :return: """ screen = QtWidgets.QWidget() screen.setAttribute(QtCore.Qt.WA_StyledBackground, True) screen.setProperty('background', 'black') layout = qt.RelativeLayout(screen) path = constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.background.jpg') start_image = QtGui.QPixmap(path) start_image_item = QtWidgets.QGraphicsPixmapItem(start_image) start_image_item.setZValue(1) scene = QtWidgets.QGraphicsScene(screen) scene.addItem(start_image_item) view = QtWidgets.QGraphicsView(scene) view.resize(start_image.size()) view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setSceneRect(0, 0, start_image.width(), start_image.height()) view.layout_constraint = qt.RelativeLayoutConstraint().center_horizontal()\ .center_vertical() layout.addWidget(view) subtitle = QtWidgets.QLabel('') subtitle.resize(0, 0) # TODO this is below the main image but collides with screens only 768 px high subtitle.layout_constraint = qt.RelativeLayoutConstraint( (0.5, -0.5, 0), (0.5, -0.5, start_image.height() / 2 + 20)) layout.addWidget(subtitle) image_map_file = constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.overlay.info') image_map = utils.read_as_yaml(image_map_file) # security check, they have to be the same if actions.keys() != image_map.keys(): raise RuntimeError( 'Start screen hot map info file ({}) corrupt.'.format( image_map_file)) frame_pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(255, 255, 255, 64)), 6) for k, v in image_map.items(): # add action from our predefined action dictionary pixmap = QtGui.QPixmap( constants.extend(constants.GRAPHICS_UI_FOLDER, v['overlay'])) map_item = MapItem(scene, pixmap, label=subtitle, description=v['label']) map_item.item.setZValue(3) offset = v['offset'] map_item.item.setOffset(QtCore.QPointF(offset[0], offset[1])) map_item.item.signaller.clicked.connect(actions[k]) frame_path = QtGui.QPainterPath() frame_path.addRect(map_item.item.boundingRect()) frame_item = scene.addPath(frame_path, frame_pen) frame_item.setZValue(4) scene.addItem(map_item.item) version_label = QtWidgets.QLabel('<font color=#ffffff>{}</font>'.format( version.__version_full__)) version_label.resize(version_label.sizeHint()) version_label.layout_constraint = qt.RelativeLayoutConstraint().east( 20).south(20) layout.addWidget(version_label) return screen
def create_start_screen_widget(actions): """ Creates the start screen. :param client: :return: """ screen = QtWidgets.QWidget() screen.setAttribute(QtCore.Qt.WA_StyledBackground, True) screen.setProperty('background', 'black') layout = qt.RelativeLayout(screen) path = constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.background.jpg') start_image = QtGui.QPixmap(path) start_image_item = QtWidgets.QGraphicsPixmapItem(start_image) start_image_item.setZValue(1) scene = QtWidgets.QGraphicsScene(screen) scene.addItem(start_image_item) view = QtWidgets.QGraphicsView(scene) view.resize(start_image.size()) view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) view.setSceneRect(0, 0, start_image.width(), start_image.height()) view.layout_constraint = qt.RelativeLayoutConstraint().center_horizontal()\ .center_vertical() layout.addWidget(view) subtitle = QtWidgets.QLabel('') subtitle.resize(0, 0) # TODO this is below the main image but collides with screens only 768 px high subtitle.layout_constraint = qt.RelativeLayoutConstraint( (0.5, -0.5, 0), (0.5, -0.5, start_image.height() / 2 + 20)) layout.addWidget(subtitle) image_map_file = constants.extend(constants.GRAPHICS_UI_FOLDER, 'start.overlay.info') image_map = utils.read_as_yaml(image_map_file) # security check, they have to be the same if actions.keys() != image_map.keys(): raise RuntimeError('Start screen hot map info file ({}) corrupt.' .format(image_map_file)) frame_pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(255, 255, 255, 64)), 6) for k, v in image_map.items(): # add action from our predefined action dictionary pixmap = QtGui.QPixmap(constants.extend(constants.GRAPHICS_UI_FOLDER, v['overlay'])) map_item = MapItem(scene, pixmap, label=subtitle, description=v['label']) map_item.item.setZValue(3) offset = v['offset'] map_item.item.setOffset(QtCore.QPointF(offset[0], offset[1])) map_item.item.signaller.clicked.connect(actions[k]) frame_path = QtGui.QPainterPath() frame_path.addRect(map_item.item.boundingRect()) frame_item = scene.addPath(frame_path, frame_pen) frame_item.setZValue(4) scene.addItem(map_item.item) version_label = QtWidgets.QLabel('<font color=#ffffff>{}</font>' .format(version.__version_full__)) version_label.resize(version_label.sizeHint()) version_label.layout_constraint = qt.RelativeLayoutConstraint().east(20).south(20) layout.addWidget(version_label) return screen
import os, sys from PyQt5 import QtWidgets if __name__ == '__main__': # add source directory to path if needed source_directory = os.path.realpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.path.pardir, os.path.pardir, 'source')) if source_directory not in sys.path: sys.path.insert(0, source_directory) from imperialism_remake.base import constants from imperialism_remake.server.scenario import Scenario # load scenario scenario = Scenario.from_file(constants.extend(constants.CORE_SCENARIO_FOLDER, 'Europe1814.scenario')) # nation map columns = scenario[constants.ScenarioProperty.MAP_COLUMNS] rows = scenario[constants.ScenarioProperty.MAP_ROWS] map = [0] * (columns * rows) for nation in scenario.nations(): provinces = scenario.provinces_of_nation(nation) for province in provinces: tiles = scenario.province_property(province, 'tiles') for column, row in tiles: map[row * columns + column] = nation # get outlines for nation in scenario.nations(): visited = [False] * (columns * rows)
def redraw(self): """ Whenever a scenario is been created or loaded new we need to draw the whole map. """ self.scene.clear() columns = editor_scenario.scenario[constants.ScenarioProperty.MAP_COLUMNS] rows = editor_scenario.scenario[constants.ScenarioProperty.MAP_ROWS] width = (columns + 0.5) * self.TILE_SIZE height = rows * self.TILE_SIZE self.scene.setSceneRect(0, 0, width, height) # TODO should load only once and cache (universal cache), should be soft coded somewhere # load all textures brushes = {0: QtGui.QBrush(QtGui.QColor(64, 64, 255)), 1: QtGui.QBrush(QtGui.QColor(64, 255, 64)), 2: QtGui.QBrush(QtGui.QColor(64, 255, 64)), 3: QtGui.QBrush(QtGui.QColor(64, 255, 64)), 4: QtGui.QBrush(QtGui.QColor(222, 222, 222)), 5: QtGui.QBrush(QtGui.QColor(0, 128, 0)), 6: QtGui.QBrush(QtGui.QColor(222, 222, 0))} # fill the ground layer with ocean item = self.scene.addRect(0, 0, width, height, brush=brushes[0], pen=qt.TRANSPARENT_PEN) item.setZValue(0) # fill plains, hills, mountains, tundra, swamp, desert with texture # go through each position paths = {} for t in range(1, 7): paths[t] = QtGui.QPainterPath() for column in range(0, columns): for row in range(0, rows): t = editor_scenario.scenario.terrain_at(column, row) if t != 0: # not for sea sx, sy = editor_scenario.scenario.scene_position(column, row) paths[t].addRect(sx * self.TILE_SIZE, sy * self.TILE_SIZE, self.TILE_SIZE, self.TILE_SIZE) for t in paths: path = paths[t] path = path.simplified() item = self.scene.addPath(path, brush=brushes[t], pen=qt.TRANSPARENT_PEN) item.setZValue(1) # fill the half tiles which are not part of the map brush = QtGui.QBrush(QtCore.Qt.darkGray) for row in range(0, rows): if row % 2 == 0: item = self.scene.addRect(columns * self.TILE_SIZE, row * self.TILE_SIZE, self.TILE_SIZE / 2, self.TILE_SIZE, pen=qt.TRANSPARENT_PEN) else: item = self.scene.addRect(0, row * self.TILE_SIZE, self.TILE_SIZE / 2, self.TILE_SIZE, pen=qt.TRANSPARENT_PEN) item.setBrush(brush) item.setZValue(1) # draw rivers river_pen = QtGui.QPen(QtGui.QColor(64, 64, 255)) river_pen.setWidth(5) # TODO get rivers via a method (generator) for river in editor_scenario.scenario[constants.ScenarioProperty.RIVERS]: tiles = river['tiles'] path = QtGui.QPainterPath() for tile in tiles: sx, sy = editor_scenario.scenario.scene_position(tile[0], tile[1]) x = (sx + 0.5) * self.TILE_SIZE y = (sy + 0.5) * self.TILE_SIZE if tile == tiles[0]: path.moveTo(x, y) else: path.lineTo(x, y) item = self.scene.addPath(path, pen=river_pen) item.setZValue(2) # draw province and nation borders # TODO the whole border drawing is a crude approximation, implement it the right way province_border_pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.black)) province_border_pen.setWidth(2) nation_border_pen = QtGui.QPen() nation_border_pen.setWidth(4) for nation in editor_scenario.scenario.nations(): # get nation color color = editor_scenario.scenario.nation_property(nation, constants.NationProperty.COLOR) nation_color = QtGui.QColor() nation_color.setNamedColor(color) # get all provinces provinces = editor_scenario.scenario.provinces_of_nation(nation) nation_path = QtGui.QPainterPath() # get all tiles for province in provinces: province_path = QtGui.QPainterPath() tiles = editor_scenario.scenario.province_property(province, constants.ProvinceProperty.TILES) for column, row in tiles: sx, sy = editor_scenario.scenario.scene_position(column, row) province_path.addRect(sx * self.TILE_SIZE, sy * self.TILE_SIZE, self.TILE_SIZE, self.TILE_SIZE) province_path = province_path.simplified() item = self.scene.addPath(province_path, pen=province_border_pen) item.setZValue(4) nation_path.addPath(province_path) nation_path = nation_path.simplified() nation_border_pen.setColor(nation_color) item = self.scene.addPath(nation_path, pen=nation_border_pen) item.setZValue(5) # draw towns and names city_pixmap = QtGui.QPixmap(constants.extend(constants.GRAPHICS_MAP_FOLDER, 'city.png')) for nation in editor_scenario.scenario.nations(): # get all provinces of this nation provinces = editor_scenario.scenario.provinces_of_nation(nation) for province in provinces: column, row = editor_scenario.scenario.province_property(province, constants.ProvinceProperty.TOWN_LOCATION) sx, sy = editor_scenario.scenario.scene_position(column, row) # center city image on center of tile x = (sx + 0.5) * self.TILE_SIZE - city_pixmap.width() / 2 y = (sy + 0.5) * self.TILE_SIZE - city_pixmap.height() / 2 item = self.scene.addPixmap(city_pixmap) item.setOffset(x, y) item.setZValue(6) # display province name below province_name = editor_scenario.scenario.province_property(province, constants.ProvinceProperty.NAME) item = self.scene.addSimpleText(province_name) item.setPen(qt.TRANSPARENT_PEN) item.setBrush(QtGui.QBrush(QtCore.Qt.darkRed)) x = (sx + 0.5) * self.TILE_SIZE - item.boundingRect().width() / 2 y = (sy + 1) * self.TILE_SIZE - item.boundingRect().height() item.setPos(x, y) item.setZValue(6) # display rounded rectangle below province name bx = 8 by = 4 background = QtCore.QRectF(x - bx, y - by, item.boundingRect().width() + 2 * bx, item.boundingRect().height() + 2 * by) path = QtGui.QPainterPath() path.addRoundedRect(background, 50, 50) item = self.scene.addPath(path, pen=qt.TRANSPARENT_PEN, brush=QtGui.QBrush(QtGui.QColor(128, 128, 255, 64))) item.setZValue(5) # draw the grid and the coordinates for column in range(0, columns): for row in range(0, rows): sx, sy = editor_scenario.scenario.scene_position(column, row) # item = self.scene.addRect(sx * self.tile_size, sy * self.tile_size, self.tile_size, self.tile_size) # item.setZValue(1000) text = '({},{})'.format(column, row) item = QtWidgets.QGraphicsSimpleTextItem(text) item.setBrush(QtGui.QBrush(QtCore.Qt.black)) item.setPos((sx + 0.5) * self.TILE_SIZE - item.boundingRect().width() / 2, sy * self.TILE_SIZE) item.setZValue(1001) self.scene.addItem(item) # emit focus changed with -1, -1 self.focus_changed.emit(-1, -1)
import os, sys from PyQt5 import QtWidgets if __name__ == '__main__': # add source directory to path if needed source_directory = os.path.realpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.path.pardir, os.path.pardir, 'source')) if source_directory not in sys.path: sys.path.insert(0, source_directory) from imperialism_remake.base import constants from imperialism_remake.server.server_scenario import ServerScenario # load scenario scenario = ServerScenario.from_file(constants.extend(constants.CORE_SCENARIO_FOLDER, 'Europe1814.scenario')) # nation map columns = scenario[constants.ScenarioProperty.MAP_COLUMNS] rows = scenario[constants.ScenarioProperty.MAP_ROWS] map = [0] * (columns * rows) for nation in scenario.nations(): provinces = scenario.provinces_of_nation(nation) for province in provinces: tiles = scenario.province_property(province, 'tiles') for column, row in tiles: map[row * columns + column] = nation # get outlines for nation in scenario.nations(): visited = [False] * (columns * rows)