class Button(Rectangle): def __init__(self, x, y, width, height, image=None, caption=None, batch=None, group=None): super(Button, self).__init__(x, y, width, height) self.batch = batch self.group = group self.sprite = None self.label = None if image: self.sprite = Sprite(image.get_region(0, 0, self.width, self.height), batch=self.batch, group=self.group) if caption: self.label = Label(caption, font_name='Arial', font_size=12, anchor_x='center', anchor_y='center', color=(255, 255, 255, 255), batch=self.batch, group=self.group) self.set_position(x, y) def set_position(self, x, y): super(Button, self).set_position(x, y) if self.sprite: self.sprite.x, self.sprite.y = x, y if self.label: self.label.x, self.label.y = self.get_center() def draw(self): if self.sprite: self.sprite.draw() if self.label: self.label.draw()
def draw_text(text, x, y, position, font_size): score = Label( text, font_name='League Gothic', font_size=font_size, x=x, y=y, anchor_x=position) score.draw()
class Label(Control): def __init__(self, text=u'Label', font_size=30, color=(0, 0, 0, 255), x=0, y=0, bold=False, italic=False, *a, **k): self.rawlabel = RawLabel(text=text, font_size=font_size, color=color, x=0, y=0, anchor_x='left', anchor_y='bottom', bold=bold, italic=italic) w, h = self.rawlabel.content_width, self.rawlabel.content_height Control.__init__(self, x=x, y=y, width=w, height=h, *a, **k) def draw(self): self.rawlabel.draw()
class GameOver(): def __init__(self, a_scale, backgroundX, backgroundY): self.game_over = Label('Game Over', font_name='Cracked Johnnie', font_size=56 * a_scale, x=backgroundX + (500 * a_scale), y=backgroundY + (500 * a_scale), color=(140, 0, 0, 0), anchor_x='center', anchor_y='center', align='center') self.restart = Label('Press W To Menu', font_name='Times New Roman', font_size=24 * a_scale, x=backgroundX + (500 * a_scale), y=backgroundY + (440 * a_scale), color=(50, 50, 50, 0), anchor_x='center', anchor_y='center', align='center') def draw(self): self.game_over.draw() self.restart.draw() def make_visible(self): self.game_over.color = (140, 0, 0, 255) self.restart.color = (50, 50, 50, 255)
class GameOverInterface(Interface): game_over_label: Label = None game_over_menu: menus.menu.Menu = None def __init__(self): self.game_over_label = Label('GAME OVER', font_name=press_start_2p, font_size=48) self.game_over_label.anchor_x = 'center' self.game_over_label.anchor_y = 'center' self.game_over_menu = menus.game_over_menu.GameOverMenu() self.resize() window = system.get_window() window.on_key_press = self.game_over_menu.on_key_press self.game_over_menu.focused = True explosion.play() def on_draw(self): self.game_over_label.draw() self.game_over_menu.draw() def resize(self): window = system.get_window() self.game_over_menu.move(window.width / 2, 100) self.game_over_label.x = window.width / 2 self.game_over_label.y = window.height / 2
class QuitScreen(MenuClass): """docstring for QuitScreen""" def __init__(self, *args, **kwargs): super(QuitScreen, self).__init__(*args, **kwargs) self.buttons['quit'] = btn([300, 300], 'yes') self.buttons['dont_quit'] = btn([680, 300], 'no') self.text = 'do you really want to quit?' self.Label = Label(self.text, font_name=font, font_size=36, bold=False, x=640, y=500, anchor_x='center', anchor_y='center') self.Box = Box([340, 200], [600, 400], 2) def handle_clicks(self, key): if key == 'quit': self.send_message('kill_self') if key == 'dont_quit': self.send_message('menu_transition_-') def draw(self): self.Box.draw() for key_, panel in self.buttons.iteritems(): panel.draw() self.Label.draw()
class InstructionsInterface(Interface): title_label: Label = None main_container: LinearLayout = LinearLayout() def __init__(self): self.title_label = Label('HOW TO PLAY', font_name=press_start_2p, font_size=48) # self.title_label.anchor_x = 'center' # self.title_label.anchor_y = 'center' self.step1_label = Label('Dodge Projectiles', font_name=press_start_2p, font_size=48) # self.step1_label.anchor_x = 'center' # self.step1_label.anchor_y = 'center' self.step2_label = Label('Charge Your Energy', font_name=press_start_2p, font_size=48) # self.step2_label.anchor_x = 'center' # self.step2_label.anchor_y = 'center' self.step3_label = Label('Defeat Enemies', font_name=press_start_2p, font_size=48) # self.step3_label.anchor_x = 'center' # self.step3_label.anchor_y = 'center' projectiles = [ ('Homing Projectiles', image.load(join(getcwd(), 'images', 'candy_cane.png'))), ('Staryu', image.load(join(getcwd(), 'images', 'staryu.png'))), ('Meteor', image.load(join(getcwd(), 'images', 'meteor_1.png'))), ] powerups = [ # ('Cookie (Heal)', image.load(join(getcwd(), 'images', 'cookie.png'))) ] self.main_container.append(self.step1_label) self.main_container.append(self.step2_label) self.main_container.append(self.step3_label) def on_draw(self): self.title_label.draw() self.main_container.draw() def on_bind(self): self.resize() def resize(self): window = system.get_window() self.title_label.x = window.width / 2 self.title_label.y = window.height - self.title_label.content_height / 2 self.main_container.width = window.width self.main_container.height = window.height - self.title_label.height self.main_container.x = window.width / 2 self.main_container.y = window.height - self.title_label.content_height self.main_container.render()
class UIHarvestChoose(Panel, InputHandler): def __init__(self, trans, *a, **k): self.trans = trans cards = trans.cards self.inputlet = None w = 20 + (91 + 10) * 4 + 20 h = 20 + 125 + 20 + 125 + 20 + 20 self.lbl = Label( text=u"等待其他玩家操作", x=w//2, y=300, font_size=12, color=(255, 255, 160, 255), shadow=(2, 0, 0, 0, 230), anchor_x='center', anchor_y='bottom' ) Panel.__init__(self, width=1, height=1, zindex=5, *a, **k) parent = self.parent self.x, self.y = (parent.width - w)//2, (parent.height - h)//2 + 20 self.width, self.height = w, h self.update() self.mapping = mapping = {} for i, c in enumerate(cards): y, x = divmod(i, 4) x, y = 20 + (91 + 10) * x, 20 + (125 + 20) * (1 - y) cs = CardSprite(c, parent=self, x=x, y=y) cs.associated_card = c mapping[id(c)] = cs @cs.event def on_mouse_dblclick(x, y, button, modifier, cs=cs): if cs.gray: return ilet = self.inputlet if not ilet: return ilet.set_card(cs.associated_card) ilet.done() def draw(self): Panel.draw(self) self.lbl.draw() def process_user_input_start(self, ilet): self.lbl.text = u'等待%s选择卡牌' % (ilet.actor.ui_meta.name) self.lbl.color = (255, 255, 160, 255) def process_user_input(self, ilet): assert ilet.actor is Game.getgame().me self.inputlet = ilet self.lbl.text = u'请你选择一张卡牌' self.lbl.color = (160, 251, 255, 255) def process_user_input_finish(self, ilet, rst): self.lbl.text = u'等待其他玩家操作' self.lbl.color = (255, 255, 160, 255) self.inputlet = None def on_harvest_choose(self, card): self.mapping[id(card)].gray = True
class MainWindow: def __init__(self, fullscreen): self.fullscreen = fullscreen self.config = Config() self.Instance = vlc.Instance() self.player = self.Instance.media_player_new() media = self.Instance.media_new(self.config.configs['playlist'][1]) self.player.set_media(media) #self.player = media.Player() #track = media.load(self.config.configs['playlist'][1]) #self.player.queue(track) self.texts = ['Movies', 'TV', 'Music', 'Options'] self.index = 0 self.maxIndex = 3 self.mainWindow = Window(fullscreen=self.fullscreen) self.label = Label(self.config.ui['greeting'], font_name='Monospace', font_size=24, x=self.mainWindow.width // 2, y=self.mainWindow.height // 2, anchor_x='center', anchor_y='center') @self.mainWindow.event def on_draw(): self.mainWindow.clear() self.label.draw() # if self.player.get_texture(): # self.player.get_texture().blit(0, 0) @self.mainWindow.event def on_key_press(symbol, modifiers): if symbol == key.UP: if self.index == self.maxIndex: self.index = 0 else: self.index += 1 elif symbol == key.DOWN: if self.index == 0: self.index = self.maxIndex else: self.index -= 1 elif symbol == key.SPACE: #self.player = vlc.MediaPlayer(self.config.configs['playlist'][1]) #self.player.play() self.player.set_xwindow(self.GetHandle()) self.player.play() elif symbol == key.RETURN: self.player.pause() self.label.text = self.texts[self.index] def Run(self): app.run()
class _OneTimeLabel: ''' https://stackoverflow.com/questions/56744840 ''' def __init__(self, viewer, text, **kwargs): self.label = Label(text, **kwargs) viewer.add_onetime(self) def render(self): self.label.draw()
class MusicPanel(Component): def __init__(self, uid: str, x: int, y: int, width: int, height: int, texture: AbstractImage, song_name: str = "", song_artist: str = ""): self.button_logger = logging.getLogger(__name__) Component.__init__(self, uid, x, y, width, height) self._song_data = {"song_name": song_name, "song_artist": song_artist} self._panel_texture = texture self._label_x = self._x + 85 self._name_label_y = self._y + 60 self._artist_label_y = self._y + 35 self.song_name_label = None self.song_artist_label = None self.music_panel_sprite = None self.load_labels() self.load_sprite() self.button_logger.debug("Music Panel Component initiated") def load_labels(self): self.song_name_label = Label(self._song_data["song_name"], font_size=20, font_name="Hydrophilia Iced", x=self._label_x, y=self._name_label_y, anchor_x="left", anchor_y="center") self.song_artist_label = Label(self._song_data["song_artist"], font_size=16, font_name="Hydrophilia Iced", x=self._label_x, y=self._artist_label_y, anchor_x="left", anchor_y="center") def load_sprite(self): self.music_panel_sprite = Sprite(self._panel_texture, self._x, self._y) def draw(self): self.music_panel_sprite.draw() self.song_name_label.draw() self.song_artist_label.draw()
class BaseMenu(object): def __init__(self, heading: str, buttons: List[BaseButton], x, y): self.heading = heading font_size = 50 self.heading_label = Label(heading, font_name='Courier New', font_size=font_size, x=x, y=y + int(font_size / 2)) self.buttons = buttons self.highlightables = list(buttons) self.x = x self.y = y @classmethod def labeled_menu_from_function_names(cls, heading, callables: List[Callable], x, y, font_size=36): height = int(font_size * 1.6) width = int(height * 6) height_spacing = int(height * 1.1) buttons = [] for i, func in enumerate(callables): i += 1 name = func.__name__ if name.startswith("_menu_"): name = name[6:] name = name.capitalize().replace('_', ' ') button = BaseButton.labeled_button(name, font_size=font_size, left=x, right=x + width, bottom=y - height_spacing * i, top=y - height_spacing * i + height, func=func) buttons.append(button) return cls(heading, buttons, x, y) def on_key_press(self, symbol, modifiers): option_id = symbol - key._1 try: self.buttons[option_id].func() except IndexError: pass def on_mouse_press(self, x, y, button, modifiers): for button in self.buttons: if button.inside(x, y): button.func() break def on_mouse_motion(self, x, y, dx, dy): for element in self.highlightables: # if element.inside(x, y) != element.inside(x - dx, y - dy): if element.inside(x, y): element.mouse_enter() else: element.mouse_leave() def draw(self): self.heading_label.draw() for button in self.buttons: button.draw()
def drawLabel(text, pos=(0, 0), center=True, textcolor=(255, 255, 255, 75)): _standard_label = Label(text="standard Label", font_size=200, bold=True, color=textcolor) _standard_label.anchor_x = "center" _standard_label.anchor_y = "center" _standard_label.x = 0 _standard_label.y = 0 _standard_label.text = text glPushMatrix() glTranslated(pos[0], pos[1], 0.0) glScaled(0.3, 0.3, 1) _standard_label.draw() glPopMatrix()
def drawLabel(text, pos=(0,0),center=True,alpha = 75,scale=0.3,red=255,green=255,blue=255): _standard_label = Label(text='standard Label', font_size=200,bold=True, color=(red,green,blue,alpha)) _standard_label.anchor_x = 'left' _standard_label.anchor_y = 'bottom' _standard_label.x = 0 _standard_label.y = 0 _standard_label.text = text glPushMatrix() glTranslated(pos[0], pos[1], 0.0) glScaled(scale,scale,1) _standard_label.draw() glPopMatrix()
def drawLabel(text, pos=(0,0),center=True): _standard_label = Label(text='standard Label', font_size=200,bold=True, color=(255,255,255,75)) _standard_label.anchor_x = 'left' _standard_label.anchor_y = 'bottom' _standard_label.x = 0 _standard_label.y = 0 _standard_label.text = text glPushMatrix() glTranslated(pos[0], pos[1], 0.0) glScaled(0.3,0.3,1) _standard_label.draw() glPopMatrix()
class ShipPartConfigurationView(PartDrydockView): def __init__(self, model: ShipPartModel, mesh=None): self._mode = "keyboard" self.font_size = 60 half_font_size = int(self.font_size / 2) self.infobox = Label("", font_name='Courier New', font_size=self.font_size, y=-half_font_size) super().__init__(model, mesh=mesh) self.update() def set_mode(self, mode): self._mode = mode self.update() @property def mode(self): return self._mode or "keyboard" def update(self): super(ShipPartConfigurationView, self).update() if self.mode == "keyboard": if self._model.keyboard: text = self._model.keyboard elif self._model.mouse: text = "M {}".format(self._model.mouse) else: text = "" elif self.mode == "gamepad": if self._model.axis: text = "{}".format(self._model.axis) elif self._model.button: text = "B{}".format(self._model.button) else: text = "" else: raise AttributeError("Invalid mode") text = str(text) self.infobox.text = text self.infobox.x = -((self.font_size * len(text)) / 2) def _draw_local(self): super(ShipPartConfigurationView, self)._draw_local() glPushMatrix() glRotatef(-self.yaw, 0, 1, 0) glRotatef(-90, 1, 0, 0) glScalef(0.025, 0.025, 0.025) self.infobox.draw() glPopMatrix()
class Label(Control): def __init__(self, text=u'Label', font_size=30, color=(0,0,0,255), x=0, y=0, bold=False, italic=False, *a, **k): self.rawlabel = RawLabel( text=text, font_size=font_size, color=color,x=0,y=0, anchor_x='left', anchor_y='bottom', bold=bold, italic=italic ) w, h = self.rawlabel.content_width, self.rawlabel.content_height Control.__init__(self, x=x, y=y, width=w, height=h, *a, **k) def draw(self): self.rawlabel.draw()
def drawLabel(text, pos=(0, 0), center=True): _standard_label = Label(text='standard Label', font_size=200, bold=True, color=(255, 255, 255, 75)) _standard_label.anchor_x = 'left' _standard_label.anchor_y = 'bottom' _standard_label.x = 0 _standard_label.y = 0 _standard_label.text = text glPushMatrix() glTranslated(pos[0], pos[1], 0.0) glScaled(0.3, 0.3, 1) _standard_label.draw() glPopMatrix()
class Text: def __init__(self, text, pos, size=12, font_name="Helvetica"): self.label = Label(text, font_name=font_name, font_size=size, x=pos[0], y=pos[1], color=Color.get("black"), anchor_x="left", anchor_y="bottom", multiline=True, width=500) def draw(self): self.label.draw()
class App(Window): """ App(self, count) The application object. Parameters ---------- count : int Number of needles to throw """ def __init__(self, count, *args, **kwargs): """ Initialize self. """ super(App, self).__init__(*args, **kwargs) self.world = World((self.width, self.height), count) self.camera = Camera(self, zoom=1.0) self.count = count if system() == 'Windows': self.font = 'Consolas' elif system() == 'Darwin': self.font = 'Monaco' else: self.font = 'Meslo LG M' self.label = Label('', font_name=self.font, font_size=20, x=10, y=self.height - 10, anchor_x='left', anchor_y='top', color=(0, 0, 0, 255)) clock.set_fps_limit(60) def on_draw(self): """ The main loop. """ self.clear() self.camera.world_projection() self.world.draw() self.label.text = '%d out of %d thrown, π = %f' % ( self.count - self.world.count, self.count, 2 / (self.world.crossed / (self.count - self.world.count)) if self.world.crossed > 0 else 0) self.camera.label_projection() self.label.draw()
class Button(pyglet.event.EventDispatcher, Rectangle): def __init__(self, parent, x, y, width, height, image=None, image_highlighted=None, caption=None, batch=None, group=None, label_group=None, font_name=G.DEFAULT_FONT): super(Button, self).__init__(x, y, width, height) parent.push_handlers(self) self.batch, self.group, self.label_group = batch, group, label_group self.sprite = image_sprite(image, self.batch, self.group) self.sprite_highlighted = hidden_image_sprite(image_highlighted, self.batch, self.group) self.highlighted = False self.label = Label(str(caption), font_name, 12, anchor_x='center', anchor_y='center', color=(255, 255, 255, 255), batch=self.batch, group=self.label_group) if caption else None self.position = x, y @property def position(self): return self.x, self.y @position.setter def position(self, position): self.x, self.y = position if hasattr(self, 'sprite') and self.sprite: self.sprite.x, self.sprite.y = position if hasattr(self, 'sprite_highlighted') and self.sprite_highlighted: self.sprite_highlighted.x, self.sprite_highlighted.y = position if hasattr(self, 'label') and self.label: self.label.x, self.label.y = self.center def draw(self): self.draw_sprite() self.draw_label() def draw_sprite(self): if self.sprite and not (self.sprite_highlighted and self.highlighted): self.sprite_highlighted.visible, self.sprite.visible = False, True self.sprite.draw() elif self.sprite_highlighted and self.highlighted: self.sprite_highlighted.visible, self.sprite.visible = True, False self.sprite_highlighted.draw() def draw_label(self): if self.label: self.label.draw() def on_mouse_click(self, x, y, button, modifiers): if self.hit_test(x, y): self.dispatch_event('on_click')
def run(self): self.window.set_visible() self.window.set_mouse_visible(False) self.window.set_exclusive_mouse(True) clock = pyglet.clock.Clock() fps_display = Label(x=0, y=0, anchor_y="top", font_size=14) while not self.window.has_exit: self.window.dispatch_events() self.updateFrame() fps_display.text = f"FPS: {pyglet.clock.get_fps()}" fps_display.draw() self.draw() self.window.flip() dt = clock.tick() print("fps: %d" % clock.get_fps())
def drawLabel(text, pos=(0, 0), **kwargs): kwargs.setdefault('font_size', 16) kwargs.setdefault('center', False) if kwargs.get('center'): kwargs.setdefault('anchor_x', 'center') kwargs.setdefault('anchor_y', 'center') else: kwargs.setdefault('anchor_x', 'left') kwargs.setdefault('anchor_y', 'bottom') del kwargs['center'] temp_label = Label(text, **kwargs) #temp_label.x, temp_label.y = pos glPushMatrix() #glTranslated(-pos[0]-8.5,-pos[1]-8,0) glScaled(0.02, 0.02, 0.02) temp_label.draw() glPopMatrix() return temp_label.content_width
def drawLabel(text, pos=(0,0), **kwargs): kwargs.setdefault('font_size', 16) kwargs.setdefault('center', False) if kwargs.get('center'): kwargs.setdefault('anchor_x', 'center') kwargs.setdefault('anchor_y', 'center') else: kwargs.setdefault('anchor_x', 'left') kwargs.setdefault('anchor_y', 'bottom') del kwargs['center'] temp_label = Label(text, **kwargs) #temp_label.x, temp_label.y = pos glPushMatrix() #glTranslated(-pos[0]-8.5,-pos[1]-8,0) glScaled(0.02,0.02,0.02) temp_label.draw() glPopMatrix() return temp_label.content_width
class LoadScreen(MenuClass): """docstring for LoadScreen""" def __init__(self, *args, **kwargs): super(LoadScreen, self).__init__(*args, **kwargs) self.label = Label('connecting to server', font_name=font, font_size=36, bold=False, x=200, y=550, anchor_x='left', anchor_y='baseline') def draw(self): self.label.draw() def on_connect(self): self.send_message('menu_transition_-') def add_update(self, dt): try: if self.keys[key.ESCAPE] and not self.keys_old[key.ESCAPE]: self.send_message('to_main') except: pass
def draw(self): make_filled_rectangle(self.origin, self.width, self.height, self.color) title = Label(self.title, font_name='Verdana', x=self.origin[0] + self.width * 0.02, y=self.origin[1] + self.height - self.height * 0.02, width=self.width * 0.9, height=self.height * 0.2, anchor_x='left', anchor_y='top') title.draw() info = Label(self.info, font_name='Verdana', x=self.origin[0] + self.width * 0.02, y=self.origin[1] + self.height - 2 * self.height * 0.02 - self.height * 0.2, width=self.width * 0.9, height=self.height * 0.15, anchor_x='left', anchor_y='top') info.draw()
class FridgeLetterAtomic(MTDragable): def __init__(self, **kwargs): kwargs.setdefault("letter", "A") kwargs.setdefault("color", (1, 0, 0, 1)) super(FridgeLetterAtomic, self).__init__(**kwargs) self.letter = Label( font_name="AlphaFridgeMagnets.ttf", font_size=48, bold=True, anchor_x="left", anchor_y="bottom", multiline=False, halign="top", color=map(lambda x: int(x * 255), kwargs.get("color")), text=kwargs.get("letter"), ) self.size = self.letter.content_width, self.letter.content_height def draw(self): self.letter.x, self.letter.y = self.pos self.letter.draw()
class MainInterface(Interface): title_label: Label = None main_menu: Menu = None def __init__(self): window = system.get_window() self.title_label = Label('Headshot', font_name=press_start_2p, font_size=36) self.title_label.anchor_x = 'center' self.title_label.anchor_y = 'center' self.main_menu = MainMenu() self.resize() window.on_key_press = self.main_menu.on_key_press self.main_menu.focused = True def on_draw(self): self.title_label.draw() self.main_menu.draw() def resize(self): window = system.get_window() self.main_menu.move(window.width / 2, 100) self.title_label.x = window.width / 2 self.title_label.y = window.height / 2
class Square: def __init__(self, number: str, point1: Point, point2: Point, color): self.cords = [ point1.x, point1.y, point2.x, point1.y, point2.x, point2.y, point1.x, point2.y ] self.color = deepcopy(color) self.label = Label( number, font_name='Arial', font_size=20, color=(0, 0, 0, 255), x=(point1.x + point2.x) // 2, y=(point1.y + point2.y) // 2, anchor_x='center', anchor_y='center') def draw(self): graphics.draw(4, pyglet.gl.GL_QUADS, ('v2f', self.cords), ('c3B', self.color * int(len(self.cords) / 2))) self.label.draw()
class WinInterface(Interface): win_label: Label = None game_over_menu: menus.menu.Menu = None drawn = False def __init__(self): self.game_over_label = Label('YOU WIN', font_name=press_start_2p, font_size=48) self.game_over_label.anchor_x = 'center' self.game_over_label.anchor_y = 'center' self.game_over_menu = menus.game_over_menu.GameOverMenu() self.game_over_menu.items.pop(0) self.game_over_menu.labels.pop(0) self.resize() window = system.get_window() window.on_key_press = self.game_over_menu.on_key_press self.game_over_menu.focused = True # media.load( # join( # 'sound_FX', # 'freesound.org', # 'win.wav' # ), # streaming=False # ).play() audio.win_music.play() def on_draw(self): self.game_over_label.draw() self.game_over_menu.draw() def resize(self): window = system.get_window() self.game_over_menu.move(window.width / 2, 100) self.game_over_label.x = window.width / 2 self.game_over_label.y = window.height / 2
class UIBaseChooseGirl(Panel, InputHandler): hover_pic = None def __init__(self, trans, *a, **k): self.trans = trans self.pbar = None self.selecting = False g = Game.getgame() choices = trans.mapping[g.me] n_choices = len(choices) cols = 5 if n_choices > 16 else 4 rows = max((n_choices - 1) / cols + 1, 4) w, h = 20 + cols * 160, 51 + rows * 113 + 30 Panel.__init__(self, width=w, height=h, zindex=5, *a, **k) p = self.parent pw, ph = p.width, p.height self.x, self.y = (pw - w) / 2, (ph - h) / 2 self.inputlet = None choices = self.choices = [ c for c in choices if c.char_cls and not getattr(c, 'chosen', False) ] self.selectors = selectors = [] for i, c in enumerate(choices): y, x = divmod(i, cols) x, y = 15 + 160 * x, 45 + 113 * (rows - 1 - y) gs = GirlSelector(c, selectors, parent=self, hover_pic=self.hover_pic, x=x, y=y) @gs.event def on_dblclick(gs=gs): c = gs.choice ilet = self.inputlet if not c.chosen and ilet: ilet.set_choice(c) ilet.done() self.end_selection() selectors.append(gs) self.label = Label(text='等待其他玩家操作', x=w // 2, y=51 + rows * 113, font_size=12, color=(255, 255, 160, 255), shadow=(2, 0, 0, 0, 230), anchor_x='center', anchor_y='bottom') def draw(self): Panel.draw(self) self.label.draw() def on_girl_chosen(self, arg): actor, choice = arg for c in self.selectors: if c.choice is choice: c.disable() break self.parent.update_portraits() def begin_selection(self): self.selecting = True self.pbar and self.pbar.delete() self.pbar = BigProgressBar( parent=self, x=(self.width - 250) // 2, y=9, width=250, ) def on_done(*a): # self.inputlet.done() # FIXME: blindly did this. self.inputlet and self.inputlet.done() self.end_selection() self.pbar.value = LinearInterp( 1.0, 0.0, self.inputlet.timeout, on_done=on_done, ) def end_selection(self): self.inputlet = None self.selecting = False self.pbar.delete()
class PlayScene(Scene): def load(self): self.score = 0 self.combo = 0 self.bonus_score = 0 self.time = 0.5 self.scroll_speed = 30 self.package = self.context.get('song') self.playing_notes = self.package['chart'].copy() self.playing_notes.sort(key=lambda x: x.get_time(), reverse=True) self.judged_notes = [] self.last_hit = None self.lanes_state = [False] * 4 self.score_label = Label(self.build_score_string(), None, font_size=12) self.combo_label = Label(self.build_combo_string(), 'monospace', font_size=Grid.get_unit(1), anchor_x='center') bgm = media.load( str(self.package['meta']['path'] / self.package['meta']['audio'])) clock.schedule_interval(self.scroll, 1 / 120) bgm.play() def draw(self): Grid.draw_grid() factor = Grid.get_unit() columns_position = [3, 6, 9, 12] judgeline_img.blit(*Grid(3, 1)) scorebox_img.blit(*Grid(18, 4)) self.score_label.draw() if self.combo >= 5: self.combo_label.draw() if self.last_hit and self.last_hit.hit_at + 1 > self.time: judge_imgs[self.last_hit.judge].blit(*Grid(4, 4)) if self.last_hit.judge in HAS_DELTA: delta_img = fast_img if self.last_hit.delta < 0 else slow_img delta_img.blit(*Grid(7, 6)) for lane, state in enumerate(self.lanes_state): if state: keypressed_img.blit(*Grid((lane * 3) + 3, 1)) for note in self.playing_notes: note.update(self.time) note_img.blit(*Grid(columns_position[note.key - 1], 1, offset_y=(note.get_time() - self.time) * self.scroll_speed * factor)) if note.force_hit: self.hit(note) def resize(self): note_img.width, note_img.height = Grid(3, 1) judgeline_img.width, judgeline_img.height = Grid(12, 1) for judge in judge_imgs.values(): judge.width, judge.height = Grid(10, 2) fast_img.width, fast_img.height = Grid(4, 1) slow_img.width, slow_img.height = Grid(4, 1) keypressed_img.width, keypressed_img.height = Grid(3, 1) scorebox_img.width, scorebox_img.height = 150, 24 self.score_label.x, self.score_label.y = Grid(18, 4, 16, 6) self.combo_label.x, self.combo_label.y = Grid(9, 30) def on_key_press(self, symbol, modifiers): lane = self.get_key_lane(symbol) if not lane: return self.lanes_state[lane - 1] = True self.keys_hit(lane) def on_key_release(self, symbol, modifiers): lane = self.get_key_lane(symbol) if not lane: return self.lanes_state[lane - 1] = False def scroll(self, delta): self.time += delta def note_delta(self, note): return self.time - note.timing_point.to_seconds() def get_key_lane(self, pressed): mapping = {key.S: 1, key.D: 2, key.K: 3, key.L: 4} if pressed in mapping: return mapping[pressed] return None def keys_hit(self, lane): for note in reversed(self.playing_notes): if not note.is_hittable(): break if note.key == lane: self.hit(note) break def hit(self, note): self.playing_notes.remove(note) note.hit_at = self.time self.last_hit = note self.score += note.judge.SCORE self.bonus_score += note.judge.BONUS_SCORE if note.judge is MISS: self.combo = 0 else: self.combo += 1 self.score_label.text = self.build_score_string() self.combo_label.text = self.build_combo_string() self.judged_notes.append(note) def build_score_string(self): return 'Score: ' + '{0:.1f}'.format(self.score).zfill(6) def build_combo_string(self): return str(self.combo).zfill(4)
class ScrollbarWidget(Control): # style: 0 - vertical, 1 - horizontal def __init__(self, parent, x, y, width, height, sb_width, sb_height, style=0, background_image=None, scrollbar_image=None, caption=None, font_size=12, font_name=G.DEFAULT_FONT, batch=None, group=None, label_group=None, pos=0, on_pos_change=None, *args, **kwargs): super(ScrollbarWidget, self).__init__(parent, *args, **kwargs) parent.push_handlers(self) self.batch = pyglet.graphics.Batch() if not batch else batch self.group = group self.label_group = label_group self.x, self.y, self.width, self.height = x, y, width, height self.sb_width, self.sb_height = sb_width, sb_height self.style = style if self.style == 0: self.sb_width = self.width else: self.sb_height = self.height self.background = image_sprite(background_image, self.batch, self.group) self.background.scale = max(float(self.width) / float(background_image.width), float(self.height) / float(background_image.height)) self.scrollbar = image_sprite(scrollbar_image, self.batch, self.group) self.scrollbar.scale = max(float(self.sb_width) / float(scrollbar_image.width), float(self.sb_height) / float(scrollbar_image.height)) self.pos = pos self.on_pos_change = on_pos_change self.caption = caption self.label = Label(str(caption) + ":" + str(pos) + "%", font_name, 12, anchor_x='center', anchor_y='center', color=(255, 255, 255, 255), batch=self.batch, group=self.label_group) if caption else None self.move_to(x, y) @property def position(self): return self.x, self.y @position.setter def position(self, value): self.move_to(*value) def move_to(self, x, y): self.x, self.y = x, y if hasattr(self, 'background') and self.background: self.background.x, self.background.y = x, y #self.background.scale = max(float(self.width) / float(self.background.width), float(self.height) / float(self.background.height)) if hasattr(self, 'scrollbar') and self.scrollbar: self.scrollbar.x, self.scrollbar.y = x, y #self.scrollbar.scale = max(float(self.sb_width) / float(self.scrollbar.width), float(self.sb_height) / float(self.scrollbar.height)) if hasattr(self, 'label') and self.label: self.label.x, self.label.y = self.center # Recreate the bounding box self.rectangle = Rectangle(self.x, self.y, self.width, self.height) self.update_pos(self.pos) @property def center(self): return self.x + self.width // 2, self.y + self.height // 2 def _on_draw(self): self.background.draw() self.scrollbar.draw() if self.label is not None: self.label.draw() def update_pos(self, new_pos): sb_space = self.width - self.sb_width if self.style == 1 else self.height - self.sb_height offset = sb_space * new_pos // 100 # vertical if self.style == 0: self.scrollbar.y = self.y + self.height self.scrollbar.y -= offset elif self.style == 1: # horizontal self.scrollbar.x = self.x + offset if self.label is not None: self.label.text = self.caption + ':' + str(new_pos) + '%' if self.on_pos_change is not None: self.on_pos_change(new_pos) self.pos = new_pos def coord_to_pos(self, x, y): offset = (self.y + self.height - y) if self.style == 0 else (x - self.x) return int(offset * 100 // (self.height if self.style == 0 else self.width)) def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): if self.visible: x += dx y += dy if self.rectangle.hit_test(x, y): self.update_pos(self.coord_to_pos(x, y)) return pyglet.event.EVENT_HANDLED def on_mouse_release(self, x, y, button, modifiers): if self.visible: if self.rectangle.hit_test(x, y): self.update_pos(self.coord_to_pos(x, y)) return pyglet.event.EVENT_HANDLED
class GameScene(Scene): # Game map constants MAP_START_X, MAP_START_Y = 400, 570 GRID_WIDTH, GRID_HEIGHT = 100, 50 MAP_WIDTH = MAP_HEIGHT = 10 # The modes the game scene can be in NOTIFY, SELECT_MODE, ACTION_MODE, MOVE_TARGET_MODE, ATTACK_TARGET_MODE = range(5) def __init__(self, world): super(GameScene, self).__init__(world) self.map_batch = Batch() self.map = self._generate_map() self.players = self._initialize_teams() self.current_turn = 1 #import knight #knight_x, knight_y = self.map.get_coordinates(5, 5) #self.characters = [knight.Knight.Sprite(knight_x, knight_y, 2, 0, 0.0)] #self.selected = None self.selected = 0, 0 self.selected_character = None self.mode = GameScene.SELECT_MODE # Items for action menu self.text_batch = Batch() self.cursor_pos = 0 self.cursor = Label(">", font_name='Times New Roman', font_size=36, x=10 + self.camera.offset_x, y=140 + self.camera.offset_y, batch=self.text_batch) self.action_menu_texts = [] self.action_menu_items = { "Move" : self._initiate_movement, "Attack" : self._initiate_attack, "Cancel" : self._close_action_menu, } # Sprites which need hilighting from different modes self.movement_hilight = [] self.attack_hilight = [] self.key_handlers = { GameScene.SELECT_MODE : { (key.ESCAPE, 0) : self.game_menu, (key.LEFT, 0) : lambda: self.move_hilight(-1, 0), (key.RIGHT, 0) : lambda: self.move_hilight(1, 0), (key.UP, 0) : lambda: self.move_hilight(0, -1), (key.DOWN, 0) : lambda: self.move_hilight(0, 1), (key.ENTER, 0) : self._open_action_menu, }, GameScene.ACTION_MODE : { (key.ESCAPE, 0) : self._close_action_menu, (key.UP, 0) : lambda: self._move_cursor(1), (key.DOWN, 0) : lambda: self._move_cursor(-1), (key.ENTER, 0) : self._menu_action }, GameScene.MOVE_TARGET_MODE : { (key.LEFT, 0) : lambda: self.move_hilight(-1, 0), (key.RIGHT, 0) : lambda: self.move_hilight(1, 0), (key.UP, 0) : lambda: self.move_hilight(0, -1), (key.DOWN, 0) : lambda: self.move_hilight(0, 1), (key.ENTER, 0) : self._execute_move, (key.ESCAPE, 0) : self._open_action_menu, }, GameScene.ATTACK_TARGET_MODE : { (key.LEFT, 0) : lambda: self.move_hilight(-1, 0), (key.RIGHT, 0) : lambda: self.move_hilight(1, 0), (key.UP, 0) : lambda: self.move_hilight(0, -1), (key.DOWN, 0) : lambda: self.move_hilight(0, 1), (key.ENTER, 0) : self._execute_attack, (key.ESCAPE, 0) : self._open_action_menu, }, } self.change_player() def _all_characters(self): return reduce(lambda chars, player: player + chars, self.players) def _other_characters(self): if self.current_turn: return self.players[0] else: return self.players[1] def change_player(self): old_turn = self.current_turn self.current_turn = (self.current_turn + 1) % 2 if not self.players[self.current_turn]: self.world.transition(VictoryScene, winner=old_turn + 1) else: self.display_turn_notice(self.current_turn) def display_turn_notice(self, current_turn): if hasattr(self, 'turn_notice'): self.turn_notice.delete() self.turn_notice = Label( "Player %s's Turn" % (current_turn + 1), font_name='Times New Roman', font_size=36, x= 500 + self.camera.offset_x, y= 560 + self.camera.offset_y) self.turn_notice.color = 255 - (100 * current_turn), 255 - (100 * ((current_turn + 1) % 2)), 255, 255 def _initialize_teams(self): def load_knight(hue): knight_x, knight_y = self.map.get_coordinates(9 * hue, 9 * hue) direction = hue and Direction.WEST or Direction.SOUTH knight = Knight(knight_x, knight_y, direction) knight.zindex=10 knight.color = 255 - (150 * hue), 255 - (150 * ((hue + 1) % 2)), 255 mage_x, mage_y = self.map.get_coordinates(7 * hue + 1, 7 * hue + 1) mage = Mage(mage_x, mage_y, direction) mage.zindex=10 mage.color = 255 - (150 * hue), 255 - (150 * ((hue + 1) % 2)), 255 return [knight, mage] return [load_knight(i) for i in range(2)] def move_hilight(self, x, y): current_x, current_y = self.selected self.selected = max(0, min(x + current_x, GameScene.MAP_WIDTH - 1)),\ max(0, min(y + current_y, GameScene.MAP_HEIGHT - 1)) newx, newy = self.map.get_coordinates(*self.selected) self.camera.look_at((newx + self.camera.x) / 2, (newy + self.camera.y) / 2) def enter(self): blue = 0.6, 0.6, 1, 0.8 pyglet.gl.glClearColor(*blue) clock.schedule(self._update_characters) def exit(self): clock.unschedule(self._update_characters) def on_draw(self): self.window.clear() selected_x, selected_y = self.map.get_coordinates(*self.selected) # if selected_x <= 100 or selected_x >= 500 \ # or selected_y <= 100 or selected_y >= 700: for sprite in self.map.sprites: if (selected_x, selected_y) == (sprite.x, sprite.y): sprite.color = 100, 100, 100 elif sprite in self.movement_hilight: sprite.color = 100, 100, 255 elif sprite in self.attack_hilight: sprite.color = 255, 100, 100 else: sprite.color = 255, 255, 255 self.map_batch.draw() if hasattr(self, 'turn_notice'): self.turn_notice.x = 500 + self.camera.offset_x self.turn_notice.y = 560 + self.camera.offset_y self.turn_notice.draw() for character in sorted(self._all_characters(), lambda c,d: int(d.y - c.y)): # if (selected_x, selected_y) == (character.x, character.y): # character.color = 100, 100, 100 # else: # character.color = 255, 255, 255 character.draw() # #character.image.blit(character.x, character.y) if self.mode == GameScene.ACTION_MODE: self._draw_action_menu() self.text_batch.draw() self.camera.focus(self.window.width, self.window.height) def _menu_action(self): actions = list(reversed(self.action_menu_items.values())) actions[self.cursor_pos]() def _move_cursor(self, direction): self.cursor_pos = (self.cursor_pos - direction) % len(self.action_menu_items) self.cursor.x = 10 + self.camera.offset_x self.cursor.y = 150 + self.camera.offset_y - 50 * self.cursor_pos def _draw_action_menu(self): pattern = SolidColorImagePattern((0, 0, 150, 200)) overlay_image = pattern.create_image(1000, 200) overlay_image.anchor_x = overlay_image.width / 2 overlay_image.anchor_y = overlay_image.height + 100 overlay = Sprite(overlay_image, self.camera.x, self.camera.y) overlay.draw() self._generate_text() def _generate_text(self): real_cord = lambda x,y: (x + self.camera.offset_x, y + self.camera.offset_y) menu_texts = reversed(self.action_menu_items.keys()) for label in self.action_menu_texts: label.delete() for i, text in enumerate(menu_texts): text_x, text_y = real_cord(40, 150 - 50 * i) self.action_menu_texts.append( Label(text, font_name='Times New Roman', font_size=36, x=text_x, y=text_y, batch=self.text_batch)) # def on_mouse_press(self, x, y, button, modifiers): # real_x, real_y = int(self.camera.offset_x + x),\ # int(self.camera.offset_y + y) # inside_map = self.map.find_sprite(x, y) # inside_chars = [c for c in self.characters if c.contains(real_x, real_y)] # taken = [self.map.get_row_column(c.x, c.y) for c in self.characters] # # # Reset everything # if self.selected: self.selected.color = 255, 255, 255 # for msprite in self.map.sprites: # msprite.color = 255, 255, 255 # # if inside_chars or inside_map: # if inside_chars: # selected = inside_chars[0] # else: # selected = inside_map # last, self.selected = self.selected, selected # self.selected.color = 100, 100, 100 # rx = self.selected.x + self.camera.offset_x # ry = self.selected.y + self.camera.offset_y # column, row = self.map.get_row_column(selected.x, selected.y) # if hasattr(self.selected, "is_player"): # in_range = self._points_in_range(column, row, 4) # for column, row in in_range: # if (column, row) not in taken: # self.map.get_sprite(column, row).color = 100, 100, 255 # elif hasattr(last, "is_player"): # last_column, last_row = self.map.get_row_column(last.x, last.y) # last_pair = last_column, last_row # new_indexes = self.map.get_row_column(selected.x, selected.y) # new_pair = int(selected.x), int(selected.y) # in_range = self._points_in_range(last_column, last_row, 4) # if new_indexes in in_range and new_pair not in taken: # self._schedule_movement(last, new_pair) # else: # self.selected = None def _initiate_movement(self): self.mode = GameScene.MOVE_TARGET_MODE self.movement_hilight = [] character = self.selected_character taken = [self.map.get_row_column(c.x, c.y) for c in self._all_characters()] column, row = self.map.get_row_column(character.x, character.y) in_range = self._points_in_range(column, row, character.speed) for column, row in in_range: if (column, row) not in taken: self.movement_hilight.append(self.map.get_sprite(column, row)) def _execute_move(self): taken = [self.map.get_row_column(c.x, c.y) for c in self._all_characters()] if self.selected not in taken: sprite = self.map.get_sprite(*self.selected) if sprite in self.movement_hilight: last = self.map.get_coordinates(*self.selected) self._schedule_movement(self.selected_character, last) self.movement_hilight = [] self.change_player() self._close_action_menu() def _initiate_attack(self): self.mode = GameScene.ATTACK_TARGET_MODE self.attack_hilight = [] character = self.selected_character column, row = self.map.get_row_column(character.x, character.y) in_range = self._points_in_range(column, row, character.range) in_range.remove(self.selected) for column, row in in_range: self.attack_hilight.append(self.map.get_sprite(column, row)) def _execute_attack(self): sprite = self.map.get_sprite(*self.selected) attacker = self.selected_character attacked = None if sprite in self.attack_hilight: for character in self._other_characters(): char_loc = self.map.get_row_column(character.x, character.y) if char_loc == self.selected: attacked = character if attacked: attack = random.randrange(attacker.strength) defense = random.randrange(attacked.defense) hit = max(1, defense - attack) print "Hit for ", hit attacker.attack_sound.play() attacked.current_health = attacked.current_health - hit if attacked.current_health <= 0: self._other_characters().remove(attacked) attacked.delete() self.attack_hilight = [] self.change_player() self._close_action_menu() def on_key_press(self, button, modifiers): key = (button, modifiers) handler = self.key_handlers[self.mode].get(key, lambda: None) handler() def _generate_map(self): x, y = GameScene.MAP_START_X, GameScene.MAP_START_Y x_offset, y_offset = self.GRID_WIDTH / 2, self.GRID_HEIGHT / 2 columns, rows = GameScene.MAP_WIDTH, GameScene.MAP_HEIGHT column_starts = [(x + i * x_offset, y - i * y_offset) for i in range(columns)] map_points = [[(x - i * x_offset, y - i * y_offset) for i in range(rows)] for x, y in column_starts] map = Map(columns, rows) for i, column in enumerate(map_points): for j, (x, y) in enumerate(column): image = load_sprite_asset("grass") image.anchor_x = image.width / 2 image.anchor_y = image.height / 2 sprite = PixelAwareSprite(image, x, y, batch=self.map_batch, centery=True) sprite.scale = 1 sprite.zindex = 0 map.add_sprite(i, j, sprite) return map def _load_characters(self): # Just load the knight for now knight_north = load_sprite_asset("knight/look_north") knight_west = load_sprite_asset("knight/look_west") knight_walk_west = load_sprite_animation("knight", "walk_west", 8, 0.15) knight_walk_north = load_sprite_animation("knight", "walk_north", 8, 0.15) #knight_walk_west = knight_walk_north = pyglet.image.load_animation("assets/knight/walk_west.gif") # knight_walk_west.anchor_x = knight_walk_west.width / 2 knight_x, knight_y = self.map.get_coordinates(5, 5) knight_faces = faces_from_images(north=knight_north, west=knight_west) knight_walks = [knight_walk_north, knight_walk_west, knight_walk_north, knight_walk_west] knight = MovingSprite(knight_x, knight_y, knight_faces, knight_walks) knight.scale=1 knight.is_player=True knight.zindex=10 knight_x, knight_y = self.map.get_coordinates(5, 0) knight2 = MovingSprite(knight_x, knight_y, knight_faces, knight_walks) knight2.scale=1 knight2.is_player=True knight2.zindex=10 knight2.look(2) return [knight, knight2] def _points_in_range(self, column, row, length): if not 0 <= column < self.MAP_HEIGHT: return [] if length == 0: return [(column, row)] else: return self._points_in_range(column - 1, row, length - 1) +\ [(column, min(max(0, row - length + i), self.MAP_WIDTH - 1)) for i in range(2 * length + 1)] + \ self._points_in_range(column + 1, row, length - 1) def _schedule_movement(self, sprite, pos): end_x, end_y = pos path = find_path(self.map.coordinates, sprite.x, sprite.y, end_x, end_y) for x, y in path: sprite.move_to(x, y, 0.3) def _update_characters(self, dt): for character in self._all_characters(): character.update(dt) def _close_action_menu(self): self.selected_character = None self.mode = GameScene.SELECT_MODE def _open_action_menu(self): if not self.selected_character: selected_x, selected_y = self.map.get_coordinates(*self.selected) for character in self.players[self.current_turn]: if (character.x, character.y) == (selected_x, selected_y): self.selected_character = character if self.selected_character: self.movement_hilight = [] self.attack_hilight = [] self.camera.stop() self.cursor_pos = 0 self.cursor.x = 10 + self.camera.offset_x self.cursor.y = 150 + self.camera.offset_y self.mode = GameScene.ACTION_MODE self.selected = self.map.get_row_column(self.selected_character.x, self.selected_character.y) def game_menu(self): self.camera.stop() self.world.transition(InGameMenuScene, previous=self)
class ShipPartDrydockView(PartDrydockView): def __init__(self, model: ShipPartModel, mesh=None): super().__init__(model, mesh) step = 36 r_step = radians(step) ten_radians = [radians(d) for d in range(0, 360, step)] circle = [(cos(d), sin(d), cos(d + r_step), sin(d + r_step)) for d in ten_radians] circle = [x for x in chain(*circle)] self.circle_v2f = ('v2f', circle) self.circle_n_points = int(len(circle) / 2) self.circle_c4B = ('c4B', [100, 150, 200, 128] * self.circle_n_points) self.circle_c4B_lowlight = ('c4B', [100, 150, 200, 128] * self.circle_n_points) self.circle_c4B_highlight = ('c4B', [200, 220, 255, 128] * self.circle_n_points) self.bbox_v2f = ('v2f', list( chain( *[(l.x1, l.y1, l.x2, l.y2) for l in self._model.bounding_box.lines]))) self.bbox_n_points = len(self._model.bounding_box.lines) * 2 self.bbox_c4f = ('c4f', [1., 1., 1., 1.] * self.bbox_n_points) self._show_circle = False self.font_size = 60 half_font_size = int(self.font_size / 2) self.infobox = Label("", font_name='Courier New', font_size=self.font_size, y=-half_font_size) self.model.observe(self.update_infobox, "working") def update_infobox(self): self.infobox.text = "".join(name[0] for name in self.model.missing_connections) def highlight_circle(self): self.circle_c4B = self.circle_c4B_highlight self._show_circle = True def lowlight_circle(self): self.circle_c4B = self.circle_c4B_lowlight self._show_circle = True def hide_circle(self): self._show_circle = False def _draw_local(self): super(PartDrydockView, self)._draw_local() if self._show_circle: glRotatef(90, 1, 0, 0) draw(self.circle_n_points, GL_LINES, self.circle_v2f, self.circle_c4B) glPushMatrix() glRotatef(-self.yaw, 0, 1, 0) glRotatef(-90, 1, 0, 0) glScalef(0.025, 0.025, 0.025) self.infobox.draw() glPopMatrix() def set_effect_value(self, effect_value): super(ShipPartDrydockView, self).set_effect_value(effect_value) self.set_diffuse_multipliers(1., effect_value, effect_value, 1.) inverse_effect_value = 1 - effect_value self.set_ambience_multipliers(.1 + inverse_effect_value, .1, .1, 1.0)
class MainMenuView(MenuView): def setup(self): self.group = pyglet.graphics.OrderedGroup(3) self.labels_group = pyglet.graphics.OrderedGroup(4) image = frame_image self.layout = VerticalLayout(0, 0) # Custom background self.background = None self.frame_rect = Rectangle(0, 0, self.controller.window.get_size()[0], image.height) self.frame = Rectangle(0, 0, self.controller.window.get_size()[0], image.height) width, height = self.controller.window.width, self.controller.window.height self.label = Label(G.APP_NAME, font_name='ChunkFive Roman', font_size=50, x=width // 2, y=self.frame.y + self.frame.height, anchor_x='center', anchor_y='top', color=(255, 255, 255, 255), batch=self.batch, group=self.labels_group) self.label.width = self.label.content_width self.label.height = self.label.content_height self.layout.add(self.label) button = self.Button(caption=G._("Singleplayer"), on_click=self.controller.start_singleplayer_game) self.layout.add(button) self.buttons.append(button) button = self.Button(caption=G._("Multiplayer"), on_click=self.controller.multiplayer) self.layout.add(button) self.buttons.append(button) button = self.Button(caption=G._("Options..."), on_click=self.controller.game_options) self.layout.add(button) self.buttons.append(button) button = self.Button(caption=G._("Exit game"), on_click=self.controller.exit_game) self.layout.add(button) self.buttons.append(button) # Splash text self.splash_text = 'Hello!' now = datetime.datetime.now() if now.month == 1 and now.day == 1: self.splash_text = 'Happy new year!' self.splash_text_label = Label(self.splash_text, font_name='Arial', font_size=30, x=self.label.x, y=self.label.y, anchor_x='center', anchor_y='top', color=(255, 255, 0, 255), group=self.labels_group) self.on_resize(width, height) # Panorama self.panorama = [ G.texture_pack_list.selected_texture_pack.load_texture( ['title', 'bg', 'panorama' + str(x) + '.png']) for x in range(6) ] self.panorama_timer = 0 pyglet.clock.schedule_interval(self.update_panorama_timer, .05) self.blur_texture = pyglet.image.Texture.create(256, 256) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) def update_panorama_timer(self, dt): self.panorama_timer += 1 def draw_panorama(self): glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() gluPerspective(120.0, 1.0, 0.05, 10.0) glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glColor4f(1.0, 1.0, 1.0, 1.0) glRotatef(180.0, 1.0, 0.0, 0.0) glEnable(GL_BLEND) glDisable(GL_ALPHA_TEST) glDisable(GL_CULL_FACE) glDepthMask(False) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glPushMatrix() glRotatef( sin(float(self.panorama_timer) / 400.0) * 25.0 + 20.0, 1.0, 0.0, 0.0) glRotatef(-float(self.panorama_timer) * 0.1, 0.0, -1.0, 0.0) # 6 faces for i in range(6): glPushMatrix() if i == 1: glRotatef(90.0, 0.0, 1.0, 0.0) elif i == 2: glRotatef(180.0, 0.0, 1.0, 0.0) elif i == 3: glRotatef(-90.0, 0.0, 1.0, 0.0) elif i == 4: glRotatef(90.0, 1.0, 0.0, 0.0) elif i == 5: glRotatef(-90.0, 1.0, 0.0, 0.0) glBindTexture(self.panorama[i].texture.target, self.panorama[i].texture.id) glEnable(self.panorama[i].texture.target) vert_list = [ -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0 ] uv_list = [0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0] l = pyglet.graphics.vertex_list( 4, ('v3f/static', vert_list), ('t2f/static', uv_list), ) l.draw(GL_QUADS) glDisable(self.panorama[i].texture.target) glPopMatrix() glPopMatrix() glColorMask(True, True, True, False) glColorMask(True, True, True, True) glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glDepthMask(True) glEnable(GL_CULL_FACE) glEnable(GL_ALPHA_TEST) glEnable(GL_DEPTH_TEST) def render_to_texture(self): glViewport(0, 0, 256, 256) self.draw_panorama() glBindTexture(GL_TEXTURE_2D, self.blur_texture.id) glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 256, 256, 0) glClearColor(0.0, 0.0, 0.5, 0.5) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glViewport(0, 0, self.controller.window.get_size()[0], self.controller.window.get_size()[1]) def draw_blur(self, times=5): alpha = 0.5 glDisable(GL_TEXTURE_GEN_S) glDisable(GL_TEXTURE_GEN_T) glEnable(GL_TEXTURE_2D) glDisable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE) glBindTexture(GL_TEXTURE_2D, self.blur_texture.id) glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() glOrtho(0, self.controller.window.get_size()[0], self.controller.window.get_size()[1], 0, -1, 1) glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() alphainc = alpha / float(times) spost = 0 width = self.controller.window.get_size()[0] height = self.controller.window.get_size()[1] glBegin(GL_QUADS) for _ in range(times): glColor4f(1.0, 1.0, 1.0, alpha) glTexCoord2f(0, 1) glVertex2f(0, 0) glTexCoord2f(0, 0) glVertex2f(0, height) glTexCoord2f(1, 0) glVertex2f(width, height) glTexCoord2f(1, 1) glVertex2f(width, 0) alpha = alpha - alphainc if alpha < 0: alpha = 0 glEnd() glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glEnable(GL_DEPTH_TEST) glDisable(GL_TEXTURE_2D) glDisable(GL_BLEND) glBindTexture(GL_TEXTURE_2D, 0) def draw_splash_text(self): glPushMatrix() glTranslatef( float(self.controller.window.get_size()[0] / 2 - self.label.content_width / 2), -float(self.controller.window.get_size()[1] / 3), 0.0) glRotatef(20.0, 0.0, 0.0, 1.0) self.splash_text_label.draw() glPopMatrix() def on_resize(self, width, height): MenuView.on_resize(self, width, height) self.label.y = self.frame.y + self.frame.height - 15 self.label.x = width // 2 self.splash_text_label.x = self.label.x self.splash_text_label.y = self.label.y def on_draw(self): self.clear() glColor3d(1, 1, 1) #self.render_to_texture() self.draw_panorama() #self.draw_blur() self.controller.set_2d() self.batch.draw() self.draw_splash_text()
class ClientBlock: """ And here is our ClientBlock! Handles all of the graphical stuff that the GameBlock didn't. """ def __init__(self, client, gameblock): self.gameblock = gameblock self.client = client # You know when you right click on a block how it places a flag? That's # what this is. We have it here and not in the GameBlock because it # only effects the client (weather or not it can be clicked/discovered). self.flagged = False # Here are all the sprites we use for our block. This COULD be optimized # to run faster... but quite frankly, we don't need to (and it's more # complicated). If we had 5000 blocks on the screen we would probably # consider it. self.sprite = rabbyt.Sprite("data/block_hidden.png") self.sprite.x = self.gameblock.x*20 self.sprite.y = self.gameblock.y*20 # I'm not going to go into detail about rabbyt sprites (you can read # the documentation for that) but just so you aren't clueless is tells # the sprite that the anchor point for x and y is on the bottom left # of the sprite and not the center (default). self.sprite.shape.left = 0 self.sprite.shape.bottom = 0 self.sprite2 = rabbyt.Sprite("data/block_discovered.png") self.sprite2.xy = self.sprite.xy self.sprite2.shape = self.sprite.shape if self.gameblock.is_mine: self.minesprite = rabbyt.Sprite("data/mine.png") self.minesprite.xy = self.sprite.xy self.minesprite.shape = self.sprite.shape self.flag_sprite = rabbyt.Sprite("data/flag.png") self.flag_sprite.xy = self.sprite.xy self.flag_sprite.shape = self.sprite.shape # Here we create the number that will be shown on the block when it is # descovered (if it is supposed to have one). # NOTE: Drawing pyglet Text is really slow - it would be better to # render the text onto a rabbyt sprite (which would go really fast) but # we'll just do this for now as that would make this tutorial more # complicated than it needs to be. if not gameblock.is_mine and gameblock.number_adjacent_mines > 0: self.text = Label(str(self.gameblock.number_adjacent_mines), x = self.sprite.x + 5, y = self.sprite.y + 5, color = COLORS[self.gameblock.number_adjacent_mines]) def draw(self): if self.gameblock.discovered: self.sprite2.render() if self.gameblock.is_mine: self.minesprite.render() elif self.gameblock.number_adjacent_mines > 0: self.text.draw() else: self.sprite.render() if self.flagged: self.flag_sprite.render() def hover_in(self): # I was going to do a bit of animation stuff but decided to save it # for a later tutorial as this one is more on structuring a game. self.sprite.alpha = 0.5 def hover_out(self): self.sprite.alpha = 1
class MainMenuView(MenuView): def setup(self): self.group = pyglet.graphics.OrderedGroup(3) self.labels_group = pyglet.graphics.OrderedGroup(4) image = frame_image self.layout = VerticalLayout(0, 0) # Custom background self.background = None self.frame_rect = Rectangle(0, 0, self.controller.window.get_size()[0], image.height) self.frame = Rectangle(0, 0, self.controller.window.get_size()[0], image.height) width, height = self.controller.window.width, self.controller.window.height self.label = Label(G.APP_NAME, font_name='ChunkFive Roman', font_size=50, x=width/2, y=self.frame.y + self.frame.height, anchor_x='center', anchor_y='top', color=(255, 255, 255, 255), batch=self.batch, group=self.labels_group) self.label.height = self.label.content_height self.layout.add(self.label) button = self.Button(caption=G._("Singleplayer"),on_click=self.controller.start_singleplayer_game) self.layout.add(button) self.buttons.append(button) button = self.Button(caption=G._("Multiplayer"),on_click=self.controller.multiplayer) self.layout.add(button) self.buttons.append(button) button = self.Button(caption=G._("Options..."),on_click=self.controller.game_options) self.layout.add(button) self.buttons.append(button) button = self.Button(caption=G._("Exit game"),on_click=self.controller.exit_game) self.layout.add(button) self.buttons.append(button) # Splash text self.splash_text = 'Hello!' now = datetime.datetime.now() if now.month == 1 and now.day == 1: self.splash_text = 'Happy new year!' self.splash_text_label = Label(self.splash_text, font_name='Arial', font_size=30, x=self.label.x, y=self.label.y, anchor_x='center', anchor_y='top', color=(255, 255, 0, 255), group=self.labels_group) self.on_resize(width, height) # Panorama self.panorama = [G.texture_pack_list.selected_texture_pack.load_texture(['title', 'bg', 'panorama' + str(x) + '.png']) for x in range(6)] self.panorama_timer = 0 pyglet.clock.schedule_interval(self.update_panorama_timer, .05) self.blur_texture = pyglet.image.Texture.create(256, 256) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) def update_panorama_timer(self, dt): self.panorama_timer += 1 def draw_panorama(self): glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() gluPerspective(120.0, 1.0, 0.05, 10.0) glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glColor4f(1.0, 1.0, 1.0, 1.0) glRotatef(180.0, 1.0, 0.0, 0.0) glEnable(GL_BLEND) glDisable(GL_ALPHA_TEST) glDisable(GL_CULL_FACE) glDepthMask(False) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glPushMatrix() glRotatef(sin(float(self.panorama_timer) / 400.0) * 25.0 + 20.0, 1.0, 0.0, 0.0) glRotatef(-float(self.panorama_timer) * 0.1, 0.0, -1.0, 0.0) # 6 faces for i in range(6): glPushMatrix() if i == 1: glRotatef(90.0, 0.0, 1.0, 0.0) elif i == 2: glRotatef(180.0, 0.0, 1.0, 0.0) elif i == 3: glRotatef(-90.0, 0.0, 1.0, 0.0) elif i == 4: glRotatef(90.0, 1.0, 0.0, 0.0) elif i == 5: glRotatef(-90.0, 1.0, 0.0, 0.0) glBindTexture(self.panorama[i].texture.target, self.panorama[i].texture.id) glEnable(self.panorama[i].texture.target) vert_list = [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0] uv_list = [0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0] l = pyglet.graphics.vertex_list(4, ('v3f/static', vert_list), ('t2f/static', uv_list), ) l.draw(GL_QUADS) glDisable(self.panorama[i].texture.target) glPopMatrix() glPopMatrix() glColorMask(True, True, True, False) glColorMask(True, True, True, True) glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glDepthMask(True) glEnable(GL_CULL_FACE) glEnable(GL_ALPHA_TEST) glEnable(GL_DEPTH_TEST) def render_to_texture(self): glViewport(0, 0, 256, 256) self.draw_panorama() glBindTexture(GL_TEXTURE_2D, self.blur_texture.id) glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 256, 256, 0) glClearColor(0.0, 0.0, 0.5, 0.5) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glViewport(0, 0, self.controller.window.get_size()[0], self.controller.window.get_size()[1]) def draw_blur(self, times=25, inc=0.02): alpha = 0.2 glDisable(GL_TEXTURE_GEN_S) glDisable(GL_TEXTURE_GEN_T) glEnable(GL_TEXTURE_2D) glDisable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBindTexture(GL_TEXTURE_2D, self.blur_texture.id) alphainc = alpha / float(times) spost = 0 width = self.controller.window.get_size()[0] height = self.controller.window.get_size()[1] glBegin(GL_QUADS) for _ in range(times): glColor4f(1.0, 1.0, 1.0, alpha) glTexCoord2f(0+spost, 1-spost) glVertex2f(0, 0) glTexCoord2f(0+spost, 0+spost) glVertex2f(0, height) glTexCoord2f(1-spost, 0+spost) glVertex2f(width, height) glTexCoord2f(1-spost, 1-spost) glVertex2f(width, 0) spost += inc alpha = alpha - alphainc glEnd() glEnable(GL_DEPTH_TEST) glDisable(GL_TEXTURE_2D) glDisable(GL_BLEND) glBindTexture(GL_TEXTURE_2D, 0) def draw_splash_text(self): glPushMatrix() glTranslatef(float(self.controller.window.get_size()[0] / 2 - self.label.content_width / 2), -float(self.controller.window.get_size()[1] / 3), 0.0) glRotatef(20.0, 0.0, 0.0, 1.0) self.splash_text_label.draw() glPopMatrix() def on_resize(self, width, height): MenuView.on_resize(self, width, height) self.label.y = self.frame.y + self.frame.height - 15 self.label.x = width / 2 self.splash_text_label.x = self.label.x self.splash_text_label.y = self.label.y def on_draw(self): self.clear() glColor3d(1, 1, 1) #self.render_to_texture() self.draw_panorama() #self.draw_blur() self.controller.set_2d() self.batch.draw() self.draw_splash_text()
class UIBaseChooseGirl(Panel, InputHandler): hover_pic = None def __init__(self, trans, *a, **k): self.trans = trans self.pbar = None self.selecting = False g = Game.getgame() choices = trans.mapping[g.me] n_choices = len(choices) cols = 5 if n_choices > 16 else 4 rows = max((n_choices - 1) / cols + 1, 4) w, h = 20 + cols*160, 51 + rows*113 + 30 Panel.__init__(self, width=w, height=h, zindex=5, *a, **k) p = self.parent pw, ph = p.width, p.height self.x, self.y = (pw - w)/2, (ph - h)/2 self.inputlet = None choices = self.choices = [c for c in choices if c.char_cls and not getattr(c, 'chosen', False)] self.selectors = selectors = [] for i, c in enumerate(choices): y, x = divmod(i, cols) x, y = 15 + 160*x, 45 + 113*(rows - 1 - y) gs = GirlSelector(c, selectors, parent=self, hover_pic=self.hover_pic, x=x, y=y) @gs.event def on_dblclick(gs=gs): c = gs.choice ilet = self.inputlet if not c.chosen and ilet: ilet.set_choice(c) ilet.done() self.end_selection() selectors.append(gs) self.label = Label( text='等待其他玩家操作', x=w//2, y=51+rows*113, font_size=12, color=(255, 255, 160, 255), shadow=(2, 0, 0, 0, 230), anchor_x='center', anchor_y='bottom' ) def draw(self): Panel.draw(self) self.label.draw() def on_girl_chosen(self, arg): actor, choice = arg for c in self.selectors: if c.choice is choice: c.disable() break self.parent.update_portraits() def begin_selection(self): self.selecting = True self.pbar and self.pbar.delete() self.pbar = BigProgressBar( parent=self, x=(self.width-250)//2, y=9, width=250, ) def on_done(*a): # self.inputlet.done() # FIXME: blindly did this. self.inputlet and self.inputlet.done() self.end_selection() self.pbar.value = LinearInterp( 1.0, 0.0, self.inputlet.timeout, on_done=on_done, ) def end_selection(self): self.inputlet = None self.selecting = False self.pbar.delete()
class Area(object): def __init__(self, world, name, bounds): self.world = world self.name = name self.lpos = None self.oldlpos = None self.label = Label(name, font_name=FONTNAME, font_size=AREA_LABEL_HEIGHT, italic=True, color=(76,76,128,255), x=0, y=0) self.center = Vec2d((bounds[0] + bounds[2])/2, (bounds[1] + bounds[3])/2) self.cbounds = (bounds[0] + self.label.content_width, bounds[1] + AREA_LABEL_HEIGHT, bounds[2] - self.label.content_width, bounds[3] - AREA_LABEL_HEIGHT) self.candidates = None self.neighbors = None # Cache self.alcf = None self.alrf = None self.ap = None def dist_to_center(self, x): centroid = Vec2d(x[0] + (self.label.content_width / 2), x[1] + (AREA_LABEL_HEIGHT / 2)) return centroid.get_distance(self.center) def move_label(self): # backup self.oldlpos = self.lpos # generate new random positions self.candidates = [] for t in range(CANDIDATEBOUND): self.candidates.append((r.randint(self.cbounds[0], self.cbounds[2]), r.randint(self.cbounds[1], self.cbounds[3]))) # sort candidates by distance to center, increasing valued_candidates = map((lambda x: (self.dist_to_center(x), x)), self.candidates) valued_candidates.sort() # choose the best candidate self.lpos = valued_candidates[0][1] def undo_move_label(self): self.lpos = self.oldlpos # dirty cache self.alcf = None self.alrf = None self.ap = None def get_char_point(self): return self.lpos + Vec2d(0, AREA_LABEL_HEIGHT/2) def get_char_vec(self): return Vec2d(self.label.content_width, 0) def get_bounding_points(self): up = Vec2d(0, AREA_LABEL_HEIGHT) rt = Vec2d(self.label.content_width, 0) qa = self.lpos return qa, qa + rt, qa + up, qa + rt + up def get_bounding_corners(self): qa, qb, qc, qd = self.get_bounding_points() return qa, qd def get_bounding_points_padded(self): qa, qb, qc, qd = self.get_bounding_points() padding = 3 upright = Vec2d(padding,padding) upleft = Vec2d(-padding,padding) return qa-upright, qb-upleft, qc+upleft, qd+upright def get_bounding_corners_padded(self): qa, qb, qc, qd = self.get_bounding_points_padded() return qa, qd def generate_neighbors(self): self.chood = self.world.og.get_full_chood(self.lpos) self.rhood = self.world.og.get_full_rhood(self.lpos) def bootstrap(self): self.move_label() self.generate_neighbors() def draw(self): glLoadIdentity() glTranslatef(self.lpos[0], self.lpos[1], 0.0) self.label.draw() ### AREA METRICS def get_AreaLabelCityFeature(self): if (self.alcf == None or self.world.current_object == self): self.alcf = self.metric_AreaLabelCityFeature() return self.alcf def metric_AreaLabelCityFeature(self): # number of overlaps between area label and point-feature symbols # IDEA: use glyphs instead of bounding box count = 0 pa, pb = self.get_bounding_corners() for c in self.chood: if (point_within(pa, pb, c.pos)): count = count + 1 return count def get_AreaLabelCityLabel(self): return self.metric_AreaLabelCityLabel() def metric_AreaLabelCityLabel(self): # number of overlaps between area label and city labels count = 0 pa, pb = self.get_bounding_corners() for c in self.chood: qa, qb, qc, qd = c.get_bounding_points() if (point_within(pa, pb, qa) or point_within(pa, pb, qb) or point_within(pa, pb, qc) or point_within(pa, pb, qd)): count = count + 1 return count def get_AreaPosition(self): if (self.ap == None or self.world.current_object == self): self.ap = self.metric_AreaPosition() return self.ap def metric_AreaPosition(self): # current centered distance to area center return self.dist_to_center(self.lpos) def get_AreaLabelRiverFeature(self): if (self.alrf == None or self.world.current_object == self): self.alrf = self.metric_AreaLabelRiverFeature() return self.alrf def metric_AreaLabelRiverFeature(self): # number of overlaps between area label and river features p_lo = self.lpos p_hi = self.lpos + Vec2d(0, AREA_LABEL_HEIGHT) right = Vec2d(1,0) pa, pb = self.get_bounding_corners_padded() locross = None hicross = None for seg in self.rhood: q = seg[0] s = -seg[0] + seg[1] cp_lo = crosspoint(p_lo, right, q, s) cp_hi = crosspoint(p_hi, right, q, s) if (cp_lo != None and locross == None): lo_within_label = point_within(pa, pb, cp_lo) lo_within_segment = point_within(seg[0], seg[1], cp_lo) if (lo_within_label and lo_within_segment): locross = cp_lo if (cp_hi != None and hicross == None): hi_within_label = point_within(pa, pb, cp_hi) hi_within_segment = point_within(seg[0], seg[1], cp_hi) if (hi_within_label and hi_within_segment): hicross = cp_hi if (locross == None and hicross == None): return 0 elif (locross == None or hicross == None): return 1 else: dirVec = (-locross + hicross).normalized() res = 1 + (9 * abs(dirVec.dot(right))) return res def get_AreaLabelAreaFeature(self): # return self.metric_AreaLabelAreaFeature() # def metric_AreaLabelAreaFeature(self): # # not applicable currently, areas have no features return 0 def get_AreaLabelAreaLabel(self): # return self.metric_AreaLabelAreaLabel() # def metric_AreaLabelAreaLabel(self): # # not applicable currently, only one area return 0
class PlanetWarsWindow(window.Window): def __init__(self, **kwargs): # rip out the game settings we want players = kwargs.pop('players') gamestate = kwargs.pop('gamestate') self.game = PlanetWars(gamestate) for p in players: self.game.add_player(p) self.max_tick = kwargs.pop('max_game_length') # set and use pyglet window settings kwargs.update({ 'width': 500, 'height': 500, 'vsync': True, 'resizable': False, }) super(PlanetWarsWindow, self).__init__(**kwargs) # create a pyglet window and set glOptions glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glClearColor(0., 0., 0., 1.0) # Grey # current "pen" colour of lines self.pen_color = (1, 0, 0, 1.) self.stroke = 1.0 # - thickness default self.qobj = gluNewQuadric() # gluQuadricDrawStyle(self.qobj, GLU_FILL) #GLU_SILHOUETTE) # prep the fps display and some labels self.fps_display = clock.ClockDisplay() clWhite = (255, 255, 255, 255) self.step_label = Label('STEP', x=5, y=self.height - 20, color=clWhite) self.fps = 0 self.set_fps(20) self.paused = True self.view_id = 0 self.label_type = 'num_ships' # create adaptor to help with drawing self.adaptor = PlanetWarsScreenAdapter(self.game, self.circle) # prep the game (space!) self.reset_space() # add extra event handlers we need self.add_handlers() def reset_space(self): self.adaptor.screen_resize(self.width, self.height) self.adaptor.sync_all(self.view_id, self.label_type) def set_fps(self, fps): self.fps = max(fps, 5) clock.unschedule(self.update) clock.schedule_interval(self.update, 1.0 / self.fps) def update(self, args): # gets called by the scheduler at the step_fps interval set game = self.game if game: if not self.paused: game.update() self.adaptor.sync_all() # update step label msg = 'Step:' + str(game.tick) if self.paused: msg += ' [PAUSED]' msg += ', View:' + str(self.view_id) if self.view_id in game.players: msg += ' ' + game.players[self.view_id].name elif self.view_id == 0: msg += ' All ' msg += str(game.tick) msg += ' Show: ' + self.label_type self.step_label.text = msg # Has the game ended? (Should we close?) if not self.game.is_alive() or self.game.tick >= self.max_tick: self.close() else: self.step_label.text = "---" def add_handlers(self): @self.event def on_resize(cx, cy): self.adaptor.screen_resize(cx, cy) pass @self.event def on_mouse_press(x, y, button, modifiers): pass @self.event def on_key_press(symbol, modifiers): # Single Player View, or All View if symbol == key.BRACKETLEFT: self.view_id = self.view_id - 1 if self.view_id > 1 else len(self.game.players) if symbol == key.BRACKETRIGHT: self.view_id = self.view_id + 1 if self.view_id < len(self.game.players) else 1 # Everyone view elif symbol == key.A: self.view_id = 0 # == "all" # Planet attribute type to show? elif symbol == key.L: i = self.label_type l = ['id','num_ships','vision_age','owner_id'] self.label_type = l[l.index(i)+1] if l.index(i) < (len(l)-1) else l[0] # Reset? elif symbol == key.R: self.reset_space() # Do one step elif symbol == key.N: self.game.update() # Pause toggle? elif symbol == key.P: self.paused = not self.paused # Speed up (+) or slow down (-) the sim elif symbol in [key.PLUS, key.EQUAL]: self.set_fps(self.fps + 5) elif symbol == key.MINUS: self.set_fps(self.fps - 5) self.adaptor.sync_all(self.view_id, self.label_type) @self.event def on_draw(): self.clear() self.fps_display.draw() self.step_label.draw() self.adaptor.draw() def set_pen_color(self, color=None, name=None): if name is not None: color = COLOR_NAMES[name] self.curr_color = color glColor4f(*self.curr_color) def set_stroke(self, stroke): self.stroke = stroke glLineWidth(self.stroke) def circle(self, pos, radius, color=None, filled=True): if color: self.set_pen_color(color) if filled: gluQuadricDrawStyle(self.qobj, GLU_FILL) else: gluQuadricDrawStyle(self.qobj, GLU_SILHOUETTE) glPushMatrix() glTranslatef(pos[0], pos[1], 0.0) gluDisk(self.qobj, 0, radius, 32, 1) glPopMatrix() def line(self, x1=0, y1=0, x2=0, y2=0, pos1=None, pos2=None): ''' Draw a single line. Either with xy values, or two position (that contain x and y values). Uses existing colour and stroke values. ''' if pos1 is not None and pos2 is not None: x1, y1, x2, y2 = pos1[0], pos1[1], pos2[0], pos2[1] glBegin(GL_LINES) glVertex2f(x1, y1) glVertex2f(x2, y2) glEnd()
class Button(Component): def __init__(self, uid: str, x: int, y: int, style: str = "button_blue_large", text: str = "", click_function=None): self.button_logger = logging.getLogger(__name__) self._text = text self._style = style self._sprite = None self._sprite_normal = None self._sprite_hover = None self._texture_normal = None self._texture_hover = None self.load_textures() Component.__init__(self, uid, x, y, self._texture_normal.width, self._texture_normal.height) self._label = None self._label_x = self._x + (self._texture_normal.width // 2) self._label_y = (self._y + (self._texture_normal.height // 2)) + 3 self.is_hovering = False self.load_label() self.load_sprite() if click_function is None: self._click_function = lambda: print("No Function Added") else: self._click_function = click_function self.button_logger.debug("Button Component initiated") def load_label(self): self._label = Label(self._text, font_size=33, font_name="Hydrophilia Iced", x=self._label_x, y=self._label_y, anchor_x="center", anchor_y="center") def load_textures(self): style_path = os.path.normpath( os.path.join(os.path.dirname(__file__), "..", "assets", "user_interface")) self._texture_normal = pyglet.image.load( os.path.join(style_path, f"{ self._style }.png")) self._texture_hover = pyglet.image.load( os.path.join(style_path, f"{ self._style }_hover.png")) def load_sprite(self): self._sprite_normal = Sprite(self._texture_normal, self._x, self._y) self._sprite_hover = Sprite(self._texture_hover, self._x, self._y) self._sprite = self._sprite_normal def on_mouse_enter(self, window: Window, x: int, y: int): self.__handle_hover(window, True) def on_mouse_motion(self, window: Window, x: int, y: int, dx: int, dy: int): self.__handle_hover(window, True) def on_mouse_press(self, window: Window, x: int, y: int, button, modifiers): self._click_function() def on_mouse_leave(self, window: Window, x: int, y: int): self.__handle_hover(window, False) def on_mouse_release(self, window: Window, x: int, y: int, button, modifiers): pass def __handle_hover(self, window: Window, hover: bool): cursor = None if hover: cursor = window.get_system_mouse_cursor(window.CURSOR_HAND) self._sprite = self._sprite_hover else: cursor = window.get_system_mouse_cursor(window.CURSOR_DEFAULT) self._sprite = self._sprite_normal window.set_mouse_cursor(cursor) def draw(self): self._sprite.draw() self._label.draw()
class DefaultObject(HiddenObject): currentScore = None labels = None nameFirst = False hideScores = False ini = None savedScores = None def created(self, data): self.savedPlayers = [0 for _ in xrange(4)] self.scoreCount = data.readShort(True) self.nameLength = data.readShort(True) self.flags = HIGHSCORE_FLAGS.copy() self.flags.setFlags(data.readShort(True)) if self.flags['HideOnStart']: self.parent.visible = False self.hideScores = self.flags['HideScores'] self.nameFirst = self.flags['NameFirst'] or self.hideScores self.font = LogFont(data, old=True) self.color = data.readColor() data.skipBytes(40) name_list = [] score_list = [] for _ in xrange(20): name_list.append(data.readString(41)) for _ in xrange(20): score_list.append(data.readInt()) self.originalScores = [(name_list[i], score_list[i]) for i in xrange(self.scoreCount)] self.scores = self.originalScores[:] self.width = data.readShort(True) self.height = data.readShort(True) self.name = data.readString(260) self.enable_mouse() self.pendingScores = [] self.set_file(self.name or 'Game.ini') if self.flags['CheckOnStart']: for index, item in enumerate(self.player.players.items): if item.score > self.scores[-1][1]: self.pendingScores.insert(0, (item.score, index + 1)) self.nameLabel = Label('Enter your name', color=(0, 0, 0, 255), bold=True, anchor_x='center', anchor_y='center', y=25) self.currentName = Label('', color=(0, 0, 0, 255), anchor_x='center', anchor_y='center', width=BOX_WIDTH - 20) self.labels = labels = [] height = self.height / self.scoreCount y = 0 for name, score in self.scores: label1 = self.create_label(self.font, '', self.color, self.width, self.height) label2 = self.create_label(self.font, '', self.color, self.width, self.height) label2.set_style('align', 'right') for label in (label1, label2): label.y = y labels.append((label1, label2)) y -= height self.update_labels() self.updateEnabled = True self.player.window.push_handlers(on_text_motion=self.on_text_motion, on_text=self.on_text, on_key_press=self.on_key_press) def set_file(self, filename): load = self.ini is None self.ini = ini = FastINI(filename) if load: section = self.player.gameData.name for i in xrange(self.scoreCount): name = ini.get_key(section, 'N%s' % i) score = ini.get_key(section, 'S%s' % i) if score == '': return score = int(score) self.scores[i] = (name, score) def on_key_press(self, symbol, modifiers): if self.currentScore is None: return if symbol == key.ENTER: name = self.currentName.text.encode('windows-1252') self.add_score(name, self.currentScore) self.currentScore = None self.player.resume() def add_score(self, name, score): self.scores.append((name, score)) self.scores.sort(key=lambda x: x[1], reverse=True) self.scores = self.scores[:self.scoreCount] self.scores_changed() def scores_changed(self): self.save() self.update_labels() def update_labels(self): for i, (label1, label2) in enumerate(self.labels): name, score = self.scores[i] if self.nameFirst: label1.text = name label2.text = '%s' % score else: label1.text = '%s' % score label2.text = name def on_text_motion(self, motion): if self.currentScore is None: return if motion == key.MOTION_BACKSPACE: self.currentName.text = self.currentName.text[:-1] def on_text(self, value): if self.currentScore is None: return self.currentName.text += value def update(self): if self.pendingScores and self.currentScore is None: score, player = self.pendingScores.pop() if score > self.scores[-1][1]: self.add_name(score, player) return def add_name(self, score, player): self.currentScore = score self.currentName.text = '' self.nameLabel.text = 'Enter your name, player %s' % player self.player.pause(-2) def draw(self): gl.glPushMatrix() gl.glTranslatef(self.x, self.y, 0) for label1, label2 in self.labels: label1.draw() if not self.hideScores: label2.draw() gl.glPopMatrix() gl.glPushMatrix() width = self.player.realWidth height = self.player.realHeight x = width / 2.0 y = height / 2.0 x1 = x - BOX_WIDTH / 2.0 y1 = y + BOX_HEIGHT / 2.0 if self.currentScore is not None: gl.glDisable(gl.GL_TEXTURE_2D) draw_border(x1, y1, BOX_WIDTH, BOX_HEIGHT) gl.glPushMatrix() gl.glTranslatef(x, y, 0) self.nameLabel.draw() self.currentName.draw() gl.glPopMatrix() gl.glPopMatrix() def on_detach(self): self.player.window.remove_handlers(on_text_motion=self.on_text_motion, on_text=self.on_text, on_key_press=self.on_key_press) def save(self): section = self.player.gameData.name for i, (name, score) in enumerate(self.scores): self.ini.set_key(section, 'N%s' % i, name) self.ini.set_key(section, 'S%s' % i, '%s' % score)
class UI: def __init__(self, window): self.window = window self.buttons = [] self.bars = [] self.progressbars = [] self.combat_text = [] self.auto_target_rings = [] self.target_rings = [] self.target_label = None self.stats = None self.settings = dict( draw_mob_hp=True, allways_draw_mob_hp=False, redraw_time=0.5 ) self.redraw_timer = self.settings["redraw_time"] self.bg_batch = self.window.batches["gui1"] self.fg_batch = self.window.batches["gui2"] self.bar_fg_batch = self.window.batches["gui3"] self.behind_batch = self.window.batches["gui0"] def add_button( self, x, y, text="Default", cb=None, cb_arg=None ): button = Button( self.window, x=x, y=y, text=text, callback=cb, callback_arg=cb_arg, bg_batch=self.bg_batch, fg_batch=self.fg_batch ) self.buttons.append(button) def add_bar( self, x, y, text="Default", width=200, height=30, color="blue", shows="default" ): bar = Bar( self.window, x=x, y=y, text=text, w=width, h=height, c=color, s=shows, bg_batch=self.bg_batch, fg_batch=self.bar_fg_batch ) self.bars.append(bar) def add_progressbar( self, x, y, duration, w=64, h=10, title=None, c="blue", bgc="dblue", tc="black" ): b = ProgressBar( self.window, x=x, y=y, w=w, h=h, c=c, bgc=bgc, tc=tc, duration=duration, fg_batch=self.fg_batch, title=title ) self.progressbars.append(b) def add_stats(self, owner, x, y, width, height): self.stats = Stats( self.window, owner, x=x, y=y, w=width, h=height, bg_batch=self.bg_batch, fg_batch=self.fg_batch, ) def add_combat_text(self, text, x, y, **kwargs): ct = FloatingCombatText( self, text, x, y, batch=self.fg_batch, **kwargs ) self.combat_text.append(ct) def update_bar(self, bartype, value, maxvalue): for b in self.bars: if b.type == bartype: b.update(value, maxvalue) def update_stats(self): if self.stats and self.window.debug: self.stats.update() def check(self, x, y, press=True, dry=False): if dry: for b in self.bars: if b.check(x, y): return True for b in self.buttons: if b.check(x, y): return True if self.stats: if self.stats.check(x, y): return True else: for b in self.bars: if b.check(x, y): return True for b in self.buttons: if press: if b.check(x, y): b.press() return True else: if b.pressed: if b.check(x, y): b.release() return True else: b.release(do_action=False) if self.stats: if self.stats.check(x, y): return True return False def update(self, dt): if self.redraw_timer >= self.settings["redraw_time"]: if self.window.game.player: p = self.window.game.player self.update_bar("hp", int(p.hp), p.max_hp) self.update_bar("mp", int(p.mp), p.max_mp) self.update_bar("sta", int(p.sta), p.max_sta) self.update_stats() self.redraw_timer = 0 else: self.redraw_timer += dt if self.stats: if self.window.debug and self.stats.hidden: self.stats.toggle_hide(False) elif not self.window.debug and not self.stats.hidden: self.stats.toggle_hide(True) p = self.window.game.player if p: if p.cast_object: if not self.progressbars: barpos = self.window.get_windowpos(p.x, p.y + 24) fg_c, bg_c, tc = get_color_scheme_by_type( p.cast_object.ability.ability_attr["magic_type"] ) self.add_progressbar( *barpos, p.cast_object.time, w=40, h=6, c=fg_c, bgc=bg_c, tc=tc, title=p.cast_object.ability.get_name() ) else: for b in self.progressbars: b.update(p.cast_object.timer) else: for b in self.progressbars: b.label.delete() if hasattr(b, "title"): b.title.delete() self.progressbars = [] t = p.target if t: if not self.target_rings: tr = TargetRing( self.window, t.x, t.y, w=t.sprite.width, h=t.sprite.height, batch=self.behind_batch ) self.target_rings.append(tr) else: for r in self.target_rings: r.update(t.x, t.y) if not self.target_label: self.target_label = Label( text=t.name, font_name=None, font_size=12, x=self.window.width // 2, y=100, anchor_x="center", anchor_y="center", color=(0, 0, 0, 255) ) else: self.target_label.text = t.name else: if self.target_rings: for r in self.target_rings: r.sprite.delete() self.target_rings = [] if self.target_label: self.target_label = None else: for b in self.progressbars: b.label.delete() if hasattr(b, "title"): b.title.delete() self.progressbars = [] for ct in self.combat_text: ct.update(dt) def draw(self): if self.settings["draw_mob_hp"]: gl.glColor4f(*lookup_color("red", gl=True)) gl.glLineWidth(3) for e in self.window.game.enemies: if e.hp < e.max_hp or self.settings["allways_draw_mob_hp"]: wpos = self.window.get_windowpos( e.x, e.y + e.sprite.height, check=True, tol=32, precise=True ) if wpos: width = (e.hp / e.max_hp) * e.sprite.width graphics.draw( 2, gl.GL_LINES, ( 'v2f', ( wpos[0] - width / 2, wpos[1], wpos[0] + width / 2, wpos[1]) ) ) # for b in self.buttons: # b.draw() self.bg_batch.draw() if self.window.game.player: for b in self.bars: b.draw() self.bar_fg_batch.draw() if self.stats: self.stats.draw() for b in self.progressbars: b.draw() self.fg_batch.draw() if self.target_label: self.target_label.draw()
class VideoPlayerWindow(Window): def __init__(self, width: int, height: int, src, caption: str, window_fps: int): super().__init__(width=width, height=height, caption=caption, resizable=True) streamer = Streamer(src=src) self.bottom_panel = BottomPanel(relative_x=0, relative_y=0, width=self.width, height=int(self.height * 0.1), parent=self) self.video_panel = VideoPanel(relative_x=0, relative_y=self.bottom_panel.height, width=self.width, height=self.height - self.bottom_panel.height, streamer=streamer, parent=self) self.fps_display = FPSDisplay(self) # Pause Related self.paused = False self.paused_text = Label(text='Paused', font_name='Times New Roman', font_size=30, x=int(0.50 * self.width), y=int(0.98 * self.height), color=tuple([255, 100, 100] + [255]), anchor_x='center', anchor_y='top', bold=True) # Clock Related self.window_fps = window_fps self._frame_fps = self.video_panel.streamer.get_fps() @property def x(self) -> int: return 0 @property def y(self) -> int: return 0 @property def frame_fps(self) -> int: return self._frame_fps def toggle_pause(self): self.paused = not self.paused def on_draw(self): self.clear() self.video_panel.draw() self.bottom_panel.draw() self.fps_display.draw() if self.paused: self.paused_text.draw() def on_key_press(self, symbol, modifiers): if symbol == key.SPACE: self.toggle_pause() elif symbol == key.ESCAPE: self.close() elif symbol == key.RIGHT: self.video_panel.streamer.fastforward(100) self.video_panel.next_frame() elif symbol == key.LEFT: self.video_panel.streamer.rewind(100) self.video_panel.next_frame() def on_key_release(self, symbol, modifiers): pass def on_resize(self, width: int, height: int): self._projection.set(width, height, *self.get_framebuffer_size()) height_prop = self.video_panel._orig_height / ( self.video_panel._orig_height + self.bottom_panel._orig_height) video_panel_height = int(height * height_prop) self.video_panel.shape = (width, video_panel_height) self.bottom_panel.shape = (width, height - video_panel_height) if self.video_panel.frame._image_data is not None: if self.video_panel.frame.orig_aspect_ratio >= width / height: target_width = width target_height = int(target_width / self.video_panel.frame.orig_aspect_ratio) self.video_panel.frame.shape = (target_width, target_height) target_x = 0 target_y = 0.5 * (height - self.bottom_panel.height - target_height) + self.bottom_panel.height self.video_panel.frame.position = (target_x, target_y) else: target_height = height target_width = int(target_height * self.video_panel.frame.orig_aspect_ratio) self.video_panel.frame.shape = (target_width, target_height) target_y = self.bottom_panel.height target_x = int(0.5 * (width - target_width)) self.video_panel.frame.position = (target_x, target_y) def update_frame(self, dt): if not self.paused: self.video_panel.next_frame() else: pass def update_window(self, dt): pass def run(self): pyglet.clock.schedule_interval(self.update_frame, 1 / self.frame_fps) pyglet.clock.schedule_interval(self.update_window, 1 / self.window_fps) pyglet.app.run()
class River(object): def __init__(self, world, width, length, name, segments): # River self.world = world self.width = width self.name = name self.length = length self.segments = segments if (segments[0][0] > segments[-1][0]): self.segments.reverse() # Neighborhoods self.chood = None self.rhood = None # Label self.ltuple = None self.oldltuple = None self.candidates = None self.label = Label(name, font_name=FONTNAME, font_size=RIVER_LABEL_HEIGHT, italic=True, color=(76,76,128,255)) # Glyph data self.glyphs = fontload(FONTNAME, RIVER_LABEL_HEIGHT, italic=True).get_glyphs(self.name) self.label_hiline = map((lambda x: x.vertices[3]), self.glyphs) self.label_loline = map((lambda x: x.vertices[1]), self.glyphs) self.label_swathwidth = int(1.2 * self.label.content_width) self.label_ascent = max(self.label_hiline) self.label_idealdist = self.label_ascent/4.0 + self.width/2.0 # Visualization self.lines = [] for s in self.segments: self.lines.extend([s[0], s[1]]) # Debug self.debugpointsA = [] self.debugpointsB = [] self.debugpointsC = [] # Cache self.rlcf = None self.rlrf = None def __repr__(self): return "\"{} (River)\"".format(self.name) def generate_raw_candidates(self): width = self.label.content_width inc = width / 8.0 # TODO startPoint = self.segments[0] leftover = 0 nexti = 1 raw_candidates = [(0, (-startPoint + self.segments[nexti]))] while (nexti < self.length): # compute the increase elements nextPoint = self.segments[nexti] dirVector = (-startPoint + nextPoint) dirVectorLen = dirVector.get_length() dirVectorUnused = dirVectorLen # compute the increase along the segment list, eat vector while (leftover + dirVectorUnused) > inc: alongDirVector = (inc - leftover) leftover = 0 dirVectorUnused = dirVectorUnused - alongDirVector incVector = dirVector * (alongDirVector / dirVectorLen) # add candidates raw_candidates.append((nexti - 1, incVector)) # raw candidates # update for next round leftover = leftover + dirVectorUnused nexti = nexti + 1 startPoint = nextPoint # tiny river extra position if (len(raw_candidates) == 1): raw_candidates.append((self.length / 2, Vec2d(1,1))) # return raw candidates for next phase return raw_candidates def generate_refined_candidates(self, raw_candidates): unranked = [] for c in range(len(raw_candidates)): i, incVector = raw_candidates[c] startPoint = self.segments[i] incPoint = startPoint + incVector # find the segments between which the baseline roughly lies # IDEA: make less hacky swathVectorStartIndex = (0 if i == 0 else i - 1) swathVectorEndIndex = i def diff(a, b): return self.segments[a].get_distance(self.segments[b]) while ((diff(swathVectorStartIndex, swathVectorEndIndex) < self.label_swathwidth) and (swathVectorEndIndex < self.length - 1) and (swathVectorEndIndex - swathVectorStartIndex < 3*len(self.name)/2.0)): swathVectorEndIndex = swathVectorEndIndex + 1 charindex = (swathVectorEndIndex + swathVectorStartIndex) / 2.0 # for centeredness # compute swath vector swathpoints = map((lambda x: self.segments[x]), range(swathVectorStartIndex, swathVectorEndIndex)) origin = incPoint ws = map((lambda x: x[0]), swathpoints) swathw = sum(ws)/len(ws) hs = map((lambda x: x[1]), swathpoints) swathh = sum(hs)/len(hs) centroid = Vec2d(swathw, swathh) swathVec = 2*(-origin + centroid) verticalVec = swathVec.perpendicular_normal() # compute distances from swathline points_angles = map((lambda p: (p, swathVec.get_angle_between(-origin + p))), swathpoints) abovelens = [0] belowlens = [0] for p,ang in points_angles: h = sin(radians(ang)) * (-origin + p).get_length() if (ang <= 0): abovelens.append(-h) else: belowlens.append(h) bumpabove = self.label_idealdist + max(abovelens) bumpbelow = -(self.label_idealdist + max(belowlens) + RIVER_LABEL_HEIGHT/2) # compute adjusted points and add to collection abovepoint = origin + (verticalVec * bumpabove) belowpoint = origin + (verticalVec * bumpbelow) unranked.append([abovepoint, origin, swathVec, swathpoints, charindex, 0.0]) unranked.append([belowpoint, origin, swathVec, swathpoints, charindex, 1.0]) return unranked def rank_candidates(self, unranked): # IDEA: replace approximates with proper metrics # average def getMetricAvg(basepoint, swathVec, verticalVec, swathpoints): dists = map((lambda x: crosspointdist(basepoint, swathVec * 2, x, verticalVec)), swathpoints) avg = sum(dists)/len(dists) metric_avg = ((avg - self.label_idealdist)**2) / (self.label_idealdist ** 2) return metric_avg # flatness def getMetricFlatness(origin, swathVec, verticalVec, swathpoints): dists = map((lambda x: crosspointdist(origin, swathVec * 2, x, verticalVec)), swathpoints) flatness = sum(dists)/len(dists) metric_flatness = (flatness**2) / (self.label_idealdist ** 2) return metric_flatness # rank all unranked candidates ranked = [] for u in unranked: basepoint, origin, swathVec, swathpoints, charindex, aboveness = u verticalVec = swathVec.perpendicular_normal() # obtain metrics metric_avg = getMetricAvg(basepoint, swathVec, verticalVec, swathpoints) metric_flatness = getMetricFlatness(origin, swathVec, verticalVec, swathpoints) metric_aboveness = aboveness metric_centeredness = abs((2 * (charindex/self.length)) - 1) # decide valuation, directly a composite of the metrics valuation = ((1.0 * metric_avg) + (1.0 * metric_flatness) + (3.0 * metric_centeredness) + (0.25 * metric_aboveness)) ranked.append((valuation, basepoint, swathVec.get_angle())) ranked.sort() self.candidates = [] for r in ranked[:CANDIDATEBOUND]: self.candidates.append(r) def move_label(self): self.oldltuple = self.ltuple self.ltuple = self.candidates[r.randint(0, len(self.candidates) - 1)] def undo_move_label(self): self.ltuple = self.oldltuple # dirty cache self.rlcf = None self.rlrf = None def get_bounding_points(self): valuation, pos, orientation = self.ltuple up = Vec2d(0, RIVER_LABEL_HEIGHT).rotated(orientation) rt = Vec2d(self.label.content_width, 0).rotated(orientation) return pos, pos + rt, pos + up, pos + rt + up def get_full_bounding_points(self): pa, pb, pc, pd = self.get_bounding_points() pe = (pa + pb) / 2 pf = (pa + pc) / 2 pg = (pa + pd) / 2 ph = (pc + pd) / 2 pi = (pb + pd) / 2 return [pa, pb, pc, pd, pe, pf, pg, ph, pi] def get_bounding_corners(self): qa, qb, qc, qd = self.get_bounding_points() return qa, qd def get_centroid(self): qa, qd = self.get_bounding_corners() return (qa + qd) / 2 def get_minmax_points(self): bbox = self.get_bounding_points() xs = map((lambda p: p[0]), bbox) minx, maxx = min(xs), max(xs) ys = map((lambda p: p[1]), bbox) miny, maxy = min(ys), max(ys) return Vec2d(minx,miny), Vec2d(maxx,miny), Vec2d(minx,maxy), Vec2d(maxx,maxy) def get_minmax_corners(self): qa, qb, qc, qd = self.get_minmax_points() return qa, qd def get_character_vector(self): valuation, pos, orientation = self.ltuple rightwards = Vec2d(self.label.content_width, 0).rotated(orientation) upwards = Vec2d(0, self.label.content_height/2).rotated(orientation) point = pos + upwards direction = rightwards return point, direction def generate_candidates(self): raw = self.generate_raw_candidates() unranked = self.generate_refined_candidates(raw) self.rank_candidates(unranked) def bootstrap(self): self.generate_candidates() self.move_label() self.move_label() def drawriver(self): glLoadIdentity() drawgraphics(self.length, pyglet.gl.GL_LINE_STRIP, ("v2i", tuple(self.lines))) def drawriverlabel(self): glLoadIdentity() valuation, pos, orientation = self.ltuple glTranslatef(pos[0], pos[1], 0.0) glRotatef(orientation, 0.0, 0.0, 1.0) self.label.draw() def drawdebug(self): glColor3f(1,0,0) for p in self.debugpointsA: glCircle(p[0], p[1], 2) glColor3f(0,1,0) for p in self.debugpointsB: glCircle(p[0], p[1], 2) glColor3f(0,0,1) for p in self.debugpointsC: glCircle(p[0], p[1], 2) # METRICS def get_RiverPosition(self): # return self.metric_RiverPosition() # def metric_RiverPosition(self): return self.ltuple[0] def get_RiverLabelCityFeature(self): if (self.rlcf == None or self.world.current_object == self): self.rlcf = self.metric_RiverLabelCityFeature() return self.rlcf def metric_RiverLabelCityFeature(self): # river label crosses a city feature valuation, pos, orientation = self.ltuple chood = self.world.og.get_full_chood(pos) count = 0 centroid = self.get_centroid() for c in chood: pa = pos pb = pos + Vec2d(self.label.content_width, 0).rotated(orientation) va = -pa + c.pos vb = -pb + c.pos cp = crosspoint(pa, va, pb, vb) d = cp.get_distance(centroid) if (d < RIVER_LABEL_HEIGHT/2): count = count + 1 return count def get_RiverLabelRiverFeature(self): if (self.rlrf == None or self.world.current_object == self): self.rlrf = self.metric_RiverLabelRiverFeature() return self.rlrf def metric_RiverLabelRiverFeature(self): valuation, pos, orientation = self.ltuple centroid = self.get_centroid() centVec = Vec2d(1,0).rotated(orientation) rhood = self.world.og.get_full_rhood(centroid) count = 0 for s in rhood: segVec = -s[0] + s[1] cp = crosspoint(centroid, centVec, s[0], segVec) if cp == None: continue withinA = point_within(s[0], s[1], cp) cast = (cp - pos).rotated(-orientation) rpoint = Vec2d(self.label.content_width, RIVER_LABEL_HEIGHT) orig = Vec2d(0,0) withinB = point_within(orig, rpoint, cast) if (self.name == "River2"): if (withinA and withinB): count = count + 1 return 0 def get_RiverLabelAreaFeature(self): # return self.metric_RiverLabelAreaFeature() # def metric_RiverLabelAreaFeature(self): # # not currently applicable, no area features return 0 def get_RiverLabelRiverLabel(self): return self.metric_RiverLabelRiverLabel() def metric_RiverLabelRiverLabel(self): # river labels against one another count = 0 valuation, pos, orientation = self.ltuple centroid = self.get_centroid() centVec = Vec2d(1,0).rotated(orientation) hitSelf = False for r in self.world.rivers: # do a < b valuation, not a<b AND b<a if r == self: hitSelf = True; continue if not hitSelf: continue val2, pos2, or2 = r.ltuple centroid2 = r.get_centroid() centVec2 = Vec2d(1,0).rotated(or2) cp = crosspoint(centroid, centVec, centroid2, centVec2) if cp == None: continue orig = Vec2d(0,0) cast = (cp - pos).rotated(-orientation) rpoint = Vec2d(self.label.content_width, RIVER_LABEL_HEIGHT) withinA = point_within(orig, rpoint, cast) cast2 = (cp - pos2).rotated(-or2) rpoint2 = Vec2d(r.label.content_width, RIVER_LABEL_HEIGHT) withinB = point_within(orig, rpoint2, cast2) if (withinA and withinB): count = count + 1 return 0 def get_RiverLabelAreaLabel(self): return self.metric_RiverLabelAreaLabel() def metric_RiverLabelAreaLabel(self): qa, qd = self.world.area.get_bounding_corners() pp = self.get_full_bounding_points() count = 0 for p in pp: wp = point_within(qa, qd, p) if wp: count = count + 1 return count
class DefaultObject(HiddenObject): currentScore = None labels = None nameFirst = False hideScores = False ini = None savedScores = None def created(self, data): self.savedPlayers = [0 for _ in xrange(4)] self.scoreCount = data.readShort(True) self.nameLength = data.readShort(True) self.flags = HIGHSCORE_FLAGS.copy() self.flags.setFlags(data.readShort(True)) if self.flags['HideOnStart']: self.parent.visible = False self.hideScores = self.flags['HideScores'] self.nameFirst = self.flags['NameFirst'] or self.hideScores self.font = LogFont(data, old = True) self.color = data.readColor() data.skipBytes(40) name_list = [] score_list = [] for _ in xrange(20): name_list.append(data.readString(41)) for _ in xrange(20): score_list.append(data.readInt()) self.originalScores = [(name_list[i], score_list[i]) for i in xrange(self.scoreCount)] self.scores = self.originalScores[:] self.width = data.readShort(True) self.height = data.readShort(True) self.name = data.readString(260) self.enable_mouse() self.pendingScores = [] self.set_file(self.name or 'Game.ini') if self.flags['CheckOnStart']: for index, item in enumerate(self.player.players.items): if item.score > self.scores[-1][1]: self.pendingScores.insert(0, (item.score, index + 1)) self.nameLabel = Label('Enter your name', color = (0, 0, 0, 255), bold = True, anchor_x = 'center', anchor_y = 'center', y = 25) self.currentName = Label('', color = (0, 0, 0, 255), anchor_x = 'center', anchor_y = 'center', width = BOX_WIDTH - 20) self.labels = labels = [] height = self.height / self.scoreCount y = 0 for name, score in self.scores: label1 = self.create_label(self.font, '', self.color, self.width, self.height) label2 = self.create_label(self.font, '', self.color, self.width, self.height) label2.set_style('align', 'right') for label in (label1, label2): label.y = y labels.append((label1, label2)) y -= height self.update_labels() self.updateEnabled = True self.player.window.push_handlers( on_text_motion = self.on_text_motion, on_text = self.on_text, on_key_press = self.on_key_press ) def set_file(self, filename): load = self.ini is None self.ini = ini = FastINI(filename) if load: section = self.player.gameData.name for i in xrange(self.scoreCount): name = ini.get_key(section, 'N%s' % i) score = ini.get_key(section, 'S%s' % i) if score == '': return score = int(score) self.scores[i] = (name, score) def on_key_press(self, symbol, modifiers): if self.currentScore is None: return if symbol == key.ENTER: name = self.currentName.text.encode('windows-1252') self.add_score(name, self.currentScore) self.currentScore = None self.player.resume() def add_score(self, name, score): self.scores.append((name, score)) self.scores.sort(key = lambda x: x[1], reverse = True) self.scores = self.scores[:self.scoreCount] self.scores_changed() def scores_changed(self): self.save() self.update_labels() def update_labels(self): for i, (label1, label2) in enumerate(self.labels): name, score = self.scores[i] if self.nameFirst: label1.text = name label2.text = '%s' % score else: label1.text = '%s' % score label2.text = name def on_text_motion(self, motion): if self.currentScore is None: return if motion == key.MOTION_BACKSPACE: self.currentName.text = self.currentName.text[:-1] def on_text(self, value): if self.currentScore is None: return self.currentName.text += value def update(self): if self.pendingScores and self.currentScore is None: score, player = self.pendingScores.pop() if score > self.scores[-1][1]: self.add_name(score, player) return def add_name(self, score, player): self.currentScore = score self.currentName.text = '' self.nameLabel.text = 'Enter your name, player %s' % player self.player.pause(-2) def draw(self): gl.glPushMatrix() gl.glTranslatef(self.x, self.y, 0) for label1, label2 in self.labels: label1.draw() if not self.hideScores: label2.draw() gl.glPopMatrix() gl.glPushMatrix() width = self.player.realWidth height = self.player.realHeight x = width / 2.0 y = height / 2.0 x1 = x - BOX_WIDTH / 2.0 y1 = y + BOX_HEIGHT / 2.0 if self.currentScore is not None: gl.glDisable(gl.GL_TEXTURE_2D) draw_border(x1, y1, BOX_WIDTH, BOX_HEIGHT) gl.glPushMatrix() gl.glTranslatef(x, y, 0) self.nameLabel.draw() self.currentName.draw() gl.glPopMatrix() gl.glPopMatrix() def on_detach(self): self.player.window.remove_handlers( on_text_motion = self.on_text_motion, on_text = self.on_text, on_key_press = self.on_key_press ) def save(self): section = self.player.gameData.name for i, (name, score) in enumerate(self.scores): self.ini.set_key(section, 'N%s' % i, name) self.ini.set_key(section, 'S%s' % i, '%s' % score)
class GameWindowAI(Window): def __init__(self): super().__init__() self.set_size(Const.WIDTH, Const.HEIGHT) self.set_caption('Floppy Bird') self.score = 0 self.population = Population(self) self.tubes = [Tube()] self.background = Sprite(img=Images.BACKGROUND_IMG) self.land = Land() self.score_label = Label(text=f'Score: {self.score}', x=Const.WIDTH - 10, y=Const.HEIGHT - 20, anchor_x='right', bold=True) self.fps_display = FPSDisplay(self) self.fps_display.label.font_size = 12 self.fps_display.label.color = (0, 255, 0, 255) self.fps_display.label.bold = False pyglet.clock.schedule_interval(self.on_timer, Const.FRAME_RATE) def on_draw(self): self.clear() self.background.draw() for tube in self.tubes: tube.draw() self.land.draw() self.population.draw() self.score_label.draw() self.fps_display.draw() def on_timer(self, dt): self.produce_remove_tubes() self.population.check_collisions() self.population.animate(dt) for tube in self.tubes: tube.animate(dt) self.update_score() def update_score(self): tube = self.get_closest_tube() if Const.BIRD_X > tube.center and not tube.crossed and not self.population.is_done: self.score += 1 self.score_label.text = f'Score: {self.score}' tube.crossed = True def produce_remove_tubes(self): tube = self.tubes[0] if tube.half_crossed: tube = self.tubes[1] if tube.bbox[0][0] < Const.WIDTH / 2 and not tube.half_crossed: tube.half_crossed = True tube = Tube() tube.draw() self.tubes.append(tube) for tube in self.tubes: if tube.bottom_head.x + tube.bottom_head.width < 0: self.tubes.remove(tube) def get_closest_tube(self): for tube in self.tubes: if tube.bbox[1][2] > 100: return tube def replay(self): self.tubes = [Tube()] self.score = 0 self.score_label.text = f'Score: {self.score}'
class Renderer(object): def __init__(self, client, map_size, minimap_size) -> None: self._client = client self._window = None self._map_size = map_size self._map_image = None self._minimap_size = minimap_size self._minimap_image = None self._mouse_x, self._mouse_y = None, None self._text_supply = None self._text_vespene = None self._text_minerals = None self._text_score = None self._text_time = None async def render(self, observation): render_data = observation.observation.render_data map_size = render_data.map.size map_data = render_data.map.data minimap_size = render_data.minimap.size minimap_data = render_data.minimap.data map_width, map_height = map_size.x, map_size.y map_pitch = -map_width * 3 minimap_width, minimap_height = minimap_size.x, minimap_size.y minimap_pitch = -minimap_width * 3 if not self._window: from pyglet.window import Window from pyglet.image import ImageData from pyglet.text import Label self._window = Window(width=map_width, height=map_height) self._window.on_mouse_press = self._on_mouse_press self._window.on_mouse_release = self._on_mouse_release self._window.on_mouse_drag = self._on_mouse_drag self._map_image = ImageData(map_width, map_height, 'RGB', map_data, map_pitch) self._minimap_image = ImageData(minimap_width, minimap_height, 'RGB', minimap_data, minimap_pitch) self._text_supply = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 10, y=self._map_size[1] - 10, color=(200, 200, 200, 255)) self._text_vespene = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 130, y=self._map_size[1] - 10, color=(28, 160, 16, 255)) self._text_minerals = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 200, y=self._map_size[1] - 10, color=(68, 140, 255, 255)) self._text_score = Label('', font_name='Arial', font_size=16, anchor_x='left', anchor_y='top', x=10, y=self._map_size[1] - 10, color=(219, 30, 30, 255)) self._text_time = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='bottom', x=self._minimap_size[0] - 10, y=self._minimap_size[1] + 10, color=(255, 255, 255, 255)) else: self._map_image.set_data('RGB', map_pitch, map_data) self._minimap_image.set_data('RGB', minimap_pitch, minimap_data) self._text_time.text = str( datetime.timedelta( seconds=(observation.observation.game_loop * 0.725) // 16)) if observation.observation.HasField('player_common'): self._text_supply.text = "{} / {}".format( observation.observation.player_common.food_used, observation.observation.player_common.food_cap) self._text_vespene.text = str( observation.observation.player_common.vespene) self._text_minerals.text = str( observation.observation.player_common.minerals) if observation.observation.HasField('score'): self._text_score.text = "{} score: {}".format( score_pb._SCORE_SCORETYPE.values_by_number[ observation.observation.score.score_type].name, observation.observation.score.score) await self._update_window() if self._client.in_game and (not observation.player_result ) and self._mouse_x and self._mouse_y: await self._client.move_camera_spatial( Point2((self._mouse_x, self._minimap_size[0] - self._mouse_y))) self._mouse_x, self._mouse_y = None, None async def _update_window(self): self._window.switch_to() self._window.dispatch_events() self._window.clear() self._map_image.blit(0, 0) self._minimap_image.blit(0, 0) self._text_time.draw() self._text_score.draw() self._text_minerals.draw() self._text_vespene.draw() self._text_supply.draw() self._window.flip() def _on_mouse_press(self, x, y, button, modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_release(self, x, y, button, modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): if not buttons & 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y
class World(object): def __init__(self, pmap): # World self.bounds = pmap['bounds'] # Area self.area = Area(self, pmap['areaname'], pmap['bounds']) # Cities self.citycount = pmap['citycount'] self.cities = [] for i in range(self.citycount): rawcity = pmap['cities'][i] c = City(self, rawcity['size'], rawcity['name'], rawcity['pos']) self.cities.append(c) # Rivers self.rivercount = pmap['rivercount'] self.rivers = [] for i in range(self.rivercount): rawriver = pmap['rivers'][i] r = River(self, rawriver['width'], rawriver['length'], rawriver['name'], rawriver['segs']) self.rivers.append(r) # ObjectGrid self.og = ObjectGrid(self) # UI self.ui_current = Label("NULL", font_name=FONTNAME, font_size=UI_LABEL_HEIGHT, color=(150,150,150,255), x=self.bounds[2] - 82, y=5) self.ui_best = Label("NULL", font_name=FONTNAME, font_size=UI_LABEL_HEIGHT, color=(150,150,150,255), x=self.bounds[2] - 82, y=7 + UI_LABEL_HEIGHT) # Execution self.finished = False self.pause = False self.annealing = Annealing(self) self.current_object = None # Visuals self.showgrid = False self.showarea = True self.showcities = True self.showcitylabels = True self.showrivers = True self.showriverlabels = True self.showdebug = True self.showvisuals = True self.showUI = True def update(self): # Call a round of annealing self.annealing.iterate() def draw(self): # White background glClearColor(1.0, 1.0, 1.0, 1.0) glClear(GL_COLOR_BUFFER_BIT) glMatrixMode(GL_MODELVIEW); # Grid glLoadIdentity() if (self.showgrid): self.og.draw() # Cities glLoadIdentity() glColor3f(0, 0, 0) if (self.showcities): for city in self.cities: city.drawcity() if (self.showcitylabels): for city in self.cities: city.drawcitylabel() # Rivers glLoadIdentity() glColor3f(0.3, 0.3, 0.5) if (self.showrivers): for river in self.rivers: river.drawriver() if (self.showriverlabels): for river in self.rivers: river.drawriverlabel() # Area glLoadIdentity() glColor3f(0.25, 0.25, 0.5) if (self.showarea): self.area.draw() # DEBUG glLoadIdentity() if (self.showdebug): # self.area.drawdebug for river in self.rivers: river.drawdebug() for city in self.cities: city.drawdebug() # UI glLoadIdentity() if (self.showUI): self.ui_best.text = str(self.annealing.best) self.ui_best.draw() self.ui_current.text = str(self.annealing.oldE) self.ui_current.draw() def bootstrap(self): self.area.bootstrap() for c in self.cities: c.bootstrap() for r in self.rivers: r.bootstrap() def random_object(self): # return r.sample(self.rivers + [self.area], 1)[0] self.current_object = r.sample(self.cities + self.rivers + [self.area], 1)[0] return self.current_object
class PlanetWarsWindow(window.Window): def __init__(self, **kwargs): # rip out the game settings we want players = kwargs.pop('players') gamestate = kwargs.pop('gamestate') self.game = PlanetWars(gamestate) for p in players: self.game.add_player(p) self.max_tick = kwargs.pop('max_game_length') # set and use pyglet window settings kwargs.update({ 'width': 500, 'height': 500, 'vsync': True, 'resizable': False, }) super(PlanetWarsWindow, self).__init__(**kwargs) # create a pyglet window and set glOptions glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glClearColor(0., 0., 0., 1.0) # Grey # current "pen" colour of lines self.pen_color = (1, 0, 0, 1.) self.stroke = 1.0 # - thickness default self.qobj = gluNewQuadric() # gluQuadricDrawStyle(self.qobj, GLU_FILL) #GLU_SILHOUETTE) # prep the fps display and some labels self.fps_display = clock.ClockDisplay() clWhite = (255, 255, 255, 255) self.step_label = Label('STEP', x=5, y=self.height - 20, color=clWhite) self.fps = 0 self.set_fps(20) self.paused = True self.view_id = 0 self.label_type = 'num_ships' # create adaptor to help with drawing self.adaptor = PlanetWarsScreenAdapter(self.game, self.circle) # prep the game (space!) self.reset_space() # add extra event handlers we need self.add_handlers() def reset_space(self): self.adaptor.screen_resize(self.width, self.height) self.adaptor.sync_all(self.view_id, self.label_type) def set_fps(self, fps): self.fps = max(fps, 5) clock.unschedule(self.update) clock.schedule_interval(self.update, 1.0 / self.fps) def update(self, args): # gets called by the scheduler at the step_fps interval set game = self.game if game: if not self.paused: game.update() self.adaptor.sync_all() # update step label msg = 'Step:' + str(game.tick) if self.paused: msg += ' [PAUSED]' msg += ', View:' + str(self.view_id) if self.view_id in game.players: msg += ' ' + game.players[self.view_id].name elif self.view_id == 0: msg += ' All ' msg += str(game.tick) msg += ' Show: ' + self.label_type self.step_label.text = msg # Has the game ended? (Should we close?) if not self.game.is_alive() or self.game.tick >= self.max_tick: self.close() else: self.step_label.text = "---" def add_handlers(self): @self.event def on_resize(cx, cy): self.adaptor.screen_resize(cx, cy) pass @self.event def on_mouse_press(x, y, button, modifiers): pass @self.event def on_key_press(symbol, modifiers): # Single Player View, or All View if symbol == key.BRACKETLEFT: self.view_id = self.view_id - 1 if self.view_id > 1 else len( self.game.players) if symbol == key.BRACKETRIGHT: self.view_id = self.view_id + 1 if self.view_id < len( self.game.players) else 1 # Everyone view elif symbol == key.A: self.view_id = 0 # == "all" # Planet attribute type to show? elif symbol == key.L: i = self.label_type l = ['id', 'num_ships', 'vision_age', 'owner_id'] self.label_type = l[l.index(i) + 1] if l.index(i) < (len(l) - 1) else l[0] # Reset? elif symbol == key.R: self.reset_space() # Do one step elif symbol == key.N: self.game.update() # Pause toggle? elif symbol == key.P: self.paused = not self.paused # Speed up (+) or slow down (-) the sim elif symbol in [key.PLUS, key.EQUAL]: self.set_fps(self.fps + 5) elif symbol == key.MINUS: self.set_fps(self.fps - 5) self.adaptor.sync_all(self.view_id, self.label_type) @self.event def on_draw(): self.clear() self.fps_display.draw() self.step_label.draw() self.adaptor.draw() def set_pen_color(self, color=None, name=None): if name is not None: color = COLOR_NAMES[name] self.curr_color = color glColor4f(*self.curr_color) def set_stroke(self, stroke): self.stroke = stroke glLineWidth(self.stroke) def circle(self, pos, radius, color=None, filled=True): if color: self.set_pen_color(color) if filled: gluQuadricDrawStyle(self.qobj, GLU_FILL) else: gluQuadricDrawStyle(self.qobj, GLU_SILHOUETTE) glPushMatrix() glTranslatef(pos[0], pos[1], 0.0) gluDisk(self.qobj, 0, radius, 32, 1) glPopMatrix() def line(self, x1=0, y1=0, x2=0, y2=0, pos1=None, pos2=None): ''' Draw a single line. Either with xy values, or two position (that contain x and y values). Uses existing colour and stroke values. ''' if pos1 is not None and pos2 is not None: x1, y1, x2, y2 = pos1[0], pos1[1], pos2[0], pos2[1] glBegin(GL_LINES) glVertex2f(x1, y1) glVertex2f(x2, y2) glEnd()
class City(object): def __init__(self, world, size, name, pos): # City self.world = world self.size = 2 * size # scaling for visualization self.name = name self.pos = pos self.chood = None self.rhood = None # Label self.lpos = None self.oldlpos = None self.lindex = None self.candidates = None self.label = Label(name, font_name=FONTNAME, font_size=CITY_LABEL_HEIGHT, color=(0,0,0,255)) # Cache self.clcf = None self.clrf = None self.cp = None # debug self.debugpointsA = [] self.debugpointsB = [] self.debugpointsC = [] def __repr__(self): return "\"{}\"".format(self.name) def __str__(self): return " {:20} {} {}".format(self.name, self.pos.inttup(), self.lpos.inttup()) def get_centroid(self): qa, qd = self.get_bounding_corners() centroid = (qa + qd) / 2 return centroid, Vec2d(1,0) def get_bounding_points(self): up = Vec2d(0, CITY_LABEL_HEIGHT) rt = Vec2d(self.label.content_width, 0) qa = self.lpos qb = qa + rt qc = qa + up qd = qa + up + rt return qa, qb, qc, qd def get_full_bounding_points(self): pa, pb, pc, pd = self.get_bounding_points() pe = (pa + pb) / 2 pf = (pa + pc) / 2 pg = (pa + pd) / 2 ph = (pc + pd) / 2 pi = (pb + pd) / 2 return [pa, pb, pc, pd, pe, pf, pg, ph, pi] def get_bounding_corners(self): qa, qb, qc, qd = self.get_bounding_points() return qa, qd def get_bounding_points_padded(self): qa, qb, qc, qd = self.get_bounding_points() padding = 3 upright = Vec2d(padding,padding) upleft = Vec2d(-padding,padding) return qa-upright, qb-upleft, qc+upleft, qd+upright def get_bounding_corners_padded(self): qa, qb, qc, qd = self.get_bounding_points_padded() return qa, qd def generate_candidates(self): lw = self.label.content_width label_offset_right = [Vec2d( 3, 6), Vec2d( 3, 4), Vec2d( 3, 2), Vec2d( 3, 0), Vec2d( 3, -2), Vec2d( 3, -4), Vec2d( 3, -6)] label_offset_left = [Vec2d( -3, 6), Vec2d( -3, 4), Vec2d( -3, 2), Vec2d( -3, 0), Vec2d( -3, -2), Vec2d( -3, -4), Vec2d( -3, -6)] label_offset_left = map((lambda p: Vec2d(-lw, 0) + p), label_offset_left) label_offset_updown= [Vec2d(-lw/3.0, 5), Vec2d(-lw/3.0, -10), Vec2d(-2*lw/3.0, 5), Vec2d(-2*lw/3.0, -10), Vec2d(-lw/2.0, 5), Vec2d(-lw/2.0, -10)] left = map((lambda p: self.pos + p), label_offset_left) right = map((lambda p: self.pos + p), label_offset_right) updown = map((lambda p: self.pos + p), label_offset_updown) raw_candidates = left + right + updown def in_bounds(p): pa, pb, pc, pd = self.world.bounds qa = p qd = p + Vec2d(self.label.content_width, CITY_LABEL_HEIGHT) return not ((qa[0] < pa) or (qa[1] < pb) or (pc < qd[0]) or (pd < qd[1])) filtered_candidates = filter(in_bounds, raw_candidates) self.candidates = filtered_candidates def generate_chood(self): self.chood = self.world.og.get_half_chood(self.pos) self.chood.remove(self) def generate_rhood(self): self.rhood = self.world.og.get_full_rhood(self.pos) def bootstrap(self): self.generate_candidates() self.move_label() self.move_label() self.generate_chood() self.generate_rhood() def move_label(self): self.oldlpos = self.lpos self.lindex = r.randint(0, len(self.candidates) - 1) self.lpos = self.candidates[self.lindex] def undo_move_label(self): self.lpos = self.oldlpos # dirty cache self.clcf = None self.clrf = None self.cp = None def drawcity(self): glLoadIdentity() glCircle(self.pos[0], self.pos[1], self.size) def drawcitylabel(self): glLoadIdentity() glTranslatef(self.lpos[0], self.lpos[1], 0.0) self.label.draw() def drawdebug(self): glColor3f(1,0,0) for p in self.debugpointsA: glCircle(p[0], p[1], self.size) glColor3f(0,1,0) for p in self.debugpointsB: glCircle(p[0], p[1], self.size) glColor3f(0,0,1) for p in self.debugpointsC: glCircle(p[0], p[1], self.size) # METRICS def get_CityLabelCityFeature(self): if (self.clcf == None or self.world.current_object == self): self.clcf = self.metric_CityLabelCityFeature() return self.clcf def metric_CityLabelCityFeature(self): # number of overlaps between city label and city feature symbols count = 0 pa, pb = self.get_bounding_corners() for c in self.chood: if (point_within(pa, pb, c.pos)): count = count + 1 return count def get_CityLabelRiverFeature(self): if (self.clrf == None or self.world.current_object == self): self.clrf = self.metric_CityLabelRiverFeature() return self.clrf def metric_CityLabelRiverFeature(self): # number of overlaps between city label and river features # IDEA: currently doesn't see segments parallel to label p_lo = self.lpos p_hi = self.lpos + Vec2d(0, CITY_LABEL_HEIGHT) right = Vec2d(1,0) pa, pb = self.get_bounding_corners_padded() locross = None hicross = None for seg in self.rhood: q = seg[0] s = -seg[0] + seg[1] cp_lo = crosspoint(p_lo, right, q, s) cp_hi = crosspoint(p_hi, right, q, s) if (cp_lo != None and locross == None): lo_within_label = point_within(pa, pb, cp_lo) lo_within_segment = point_within(seg[0], seg[1], cp_lo) if (lo_within_label and lo_within_segment): locross = cp_lo if (cp_hi != None and hicross == None): hi_within_label = point_within(pa, pb, cp_hi) hi_within_segment = point_within(seg[0], seg[1], cp_hi) if (hi_within_label and hi_within_segment): hicross = cp_hi if (locross == None and hicross == None): return 0 elif (locross == None or hicross == None): return 1 else: dirVec = (-locross + hicross).normalized() res = 1 + (9 * abs(dirVec.dot(right))) return res def get_CityLabelAreaFeature(self): # return self.metric_CityLabelAreaFeature() # def metric_CityLabelAreaFeature(self): # # not applicable currently, area(s) have no feature return 0 def get_CityLabelCityLabel(self): return self.metric_CityLabelCityLabel() def metric_CityLabelCityLabel(self): # number of overlaps between city label and other city labels count = 0 pa, pb = self.get_bounding_corners() for c in self.chood: qa, qb, qc, qd = c.get_bounding_points() if (point_within(pa, pb, qa) or point_within(pa, pb, qb) or point_within(pa, pb, qc) or point_within(pa, pb, qd)): count = count + 1 return count def get_CityLabelRiverLabel(self): return self.metric_CityLabelRiverLabel() def metric_CityLabelRiverLabel(self): # number of overlaps between city label and river labels count = 0 centroid, centVec = self.get_centroid() backupVec = -self.pos + centroid orig = Vec2d(0,0) rpoint = Vec2d(self.label.content_width, RIVER_LABEL_HEIGHT) for r in self.world.rivers: val, pos, orientation = r.ltuple centroid2 = r.get_centroid() centVec2 = Vec2d(1,0).rotated(orientation) cp = crosspoint(centroid, centVec, centroid2, centVec2) if cp == None: cp = crosspoint(centroid, backupVec, centroid2, centVec2) cast = (cp - pos).rotated(-orientation) withinA = point_within(orig, rpoint, cast) withinB = point_within(self.lpos, self.lpos + rpoint, cp) if (withinA and withinB): count = count + 1 return 0 def get_CityLabelAreaLabel(self): return self.metric_CityLabelAreaLabel() def metric_CityLabelAreaLabel(self): qa, qd = self.world.area.get_bounding_corners() pp = self.get_full_bounding_points() count = 0 for p in pp: wp = point_within(qa, qd, p) if wp: count = count + 1 return count def get_CityPosition(self): # return self.metric_CityPosition() # def metric_CityPosition(self): # # ranking of possibilities: prefer right to left, above to below and low baseline diff return LPOSVALUES[self.lindex]