# ///// # Remake of 1869 in python # //// import pyglet import Assets import Labels import Utils import logging # TODO to be implemented from pyglet.window import key from pyglet.window import mouse from pyglet.gl import * from scenes import IntroScreen from scenes import ConfigScreen glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) pyglet.gl.glClearColor(0.1, 0.1, 0.1, 1) """ naming conventions: d_varname = dict s_varname = set l_varname = list t_varname = tuple b_varname = batch og_varname = orderedGroup for z relation of graphics """ class main(pyglet.window.Window): def __init__(self, width=640, height=480, fps=False, *args, **kwargs): super(main, self).__init__(width, height, caption='1869 Remake', *args, **kwargs) self.x = 0 self.y = 0 self.WindowMinWidth = width self.WindowMinHeight = height self.currentWindowWidth = width self.currentWindowHeight = height # self.push_handlers(pyglet.window.event.WindowEventLogger()) # -> gibt aus welche events an das window geschickt wurden -> gut zum finden von events die manipuliert werden sollen self.og_background = pyglet.graphics.OrderedGroup(0) self.og_semi_background = pyglet.graphics.OrderedGroup(1) self.og_semi_foreground = pyglet.graphics.OrderedGroup(2) self.og_foreground = pyglet.graphics.OrderedGroup(3) self.b_sprites = pyglet.graphics.Batch() self.b_labels = pyglet.graphics.Batch() self.b_widgets = pyglet.graphics.Batch() self.mouse_x = 0 self.mouse_y = 0 self.alive = 1 self.activeScene = None self.activeSceneName = None self.sceneTransferPhase = 1 self.d_stopWatch = dict() self.d_active_SpriteAnimations = dict() self.d_active_LabelAnimations = dict() self.d_active_WidgetAnimations = dict() self.targetScene = 'INTRO' self.d_active_sprites = dict() self.d_active_labels = dict() self.d_active_widgets = dict() # TODO check if this widget system for text input can be used to imitate text lieferant from c# code self.text_cursor = self.get_system_mouse_cursor('text') self.focus = None ##### # system funcs ##### def on_resize(self, width, height): width = max(width,self.WindowMinWidth) height = max(height, self.WindowMinHeight) super(main, self).on_resize(width, height) currentScaleFactor_x = width/self.currentWindowWidth currentScaleFactor_y = height/self.currentWindowHeight self.currentWindowWidth = width self.currentWindowHeight = height if self.d_active_sprites is not None: for keys, sprite in self.d_active_sprites.items(): sprite.scale_x = max(width, sprite.image.width)/min(width, sprite.width) sprite.scale_y = max(sprite.image.height, height)/min(sprite.image.height, height) if self.d_active_labels is not None: for keys, label in self.d_active_labels.items(): label.content_width = label.content_width*(max(label.content_width, width)/ min(label.content_width, width)) label.content_height = label.content_height*(max(label.content_height, height)/ min(label.content_height, height)) label.x = label.x* currentScaleFactor_x label.y = label.y* currentScaleFactor_y label.font_size = label.font_size*currentScaleFactor_x if self.d_active_widgets is not None: for keys, widget in self.d_active_widgets.items(): #widget.width = width - 110 pass def on_draw(self): self.render() def render(self): self.clear() self.b_sprites.draw() self.b_labels.draw() self.b_widgets.draw() self.flip() def on_close(self): self.alive = 0 ##### # input Handler Funcs ##### def on_mouse_motion(self, x, y, dx, dy): # forward mouse information to active scene self.activeScene.on_mouse_motion(self, x, y, dx, dy) self.mouse_x = x self.mouse_y = y if self.d_active_widgets is not None: for key,widget in self.d_active_widgets.items(): if widget.hit_test(x, y): self.set_mouse_cursor(self.text_cursor) break else: self.set_mouse_cursor(None) def on_mouse_press(self, x, y, button, modifiers): # forward mouse information to active scene self.activeScene.on_mouse_press(self, x, y, button, modifiers) if button == 1: # Left click pass for key,widget in self.d_active_widgets.items(): if widget.hit_test(x, y): self.set_focus(widget) break else: self.set_focus(None) if self.focus: self.focus.caret.on_mouse_press(x, y, button, modifiers) def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): if self.focus: self.focus.caret.on_mouse_drag(x, y, dx, dy, buttons, modifiers) def on_key_press(self, symbol, modifiers): # forward keypress information to active scene self.activeScene.on_key_press(self, symbol, modifiers) if symbol == key.ESCAPE: self.alive = 0 if symbol == key.TAB: if modifiers & key.MOD_SHIFT: dir = -1 else: dir = 1 if self.focus in self.d_active_widgets: i = self.d_active_widgets.index(self.focus) else: i = 0 dir = 0 self.set_focus(self.d_active_widgets[(i + dir) % len(self.d_active_widgets)]) def on_text(self, text): if self.focus: self.focus.caret.on_text(text) def on_text_motion(self, motion): if self.focus: self.focus.caret.on_text_motion(motion) def on_text_motion_select(self, motion): if self.focus: self.focus.caret.on_text_motion_select(motion) def set_focus(self, focus): if self.focus: self.focus.caret.visible = False self.focus.caret.mark = self.focus.caret.position = 0 print('defocused') self.focus = focus if self.focus: print('focused') self.focus.caret.visible = True self.focus.caret.mark = 0 self.focus.caret.position = len(self.focus.document.text) ##### # stopwatch functions #### def checkStopwatch(self, obj, targetSeconds): """ tracks time based operations for given objects -> targetSeconds: returns true if current Timer is below /reached targetSeconds """ if obj in self.d_stopWatch: if self.d_stopWatch[obj] <= targetSeconds: return True else: return False else: return False def setStopwatch(self, obj, seconds): if obj not in self.d_stopWatch: self.d_stopWatch[obj] = seconds return True else: # not allowed to set a timer on an object twice return False def stopwatch_tick(self): for obj in self.d_stopWatch: self.d_stopWatch[obj] -= 1 def clearStopwatchTask(self, obj): if obj in self.d_stopWatch: self.d_stopWatch.pop(obj) return True else: return False def clearStopwatch(self): self.d_stopWatch.clear() ##### # resource loaders ##### def load_sprites(self): """ load all sprites used in the specific scene """ if isinstance(self.activeScene, IntroScreen.IntroScene): return { 'max_design_intro_sprite': pyglet.sprite.Sprite(Assets.max_design_intro_image, batch=self.b_sprites, group=self.og_background), 'artwork_intro_sprite': pyglet.sprite.Sprite(Assets.artwork_intro_image, batch=self.b_sprites, group=self.og_background), 'programmers_intro_sprite': pyglet.sprite.Sprite(Assets.programmers_intro_image, batch=self.b_sprites, group=self.og_background), 'music_intro_sprite': pyglet.sprite.Sprite(Assets.music_intro_image, batch=self.b_sprites, group=self.og_background), 'title_intro_sprite': pyglet.sprite.Sprite(Assets.title_intro_image, batch=self.b_sprites, group=self.og_background), 'blackscreen': pyglet.sprite.Sprite(Assets.blackScreen, batch=self.b_sprites, group=self.og_foreground), } if isinstance(self.activeScene, ConfigScreen.ConfigScene): return { 'configSprite': pyglet.sprite.Sprite(Assets.configScreen, batch=self.b_sprites, group=self.og_background), 'blackscreen': pyglet.sprite.Sprite(Assets.blackScreen, batch=self.b_sprites, group=self.og_foreground), } def load_labels(self): """ load all labels used in the specific scene """ if isinstance(self.activeScene, IntroScreen.IntroScene): return { 'press_enter': pyglet.text.Label(text="Press Enter", font_name=None, font_size=10, color=(255, 255, 255, 0), x=(self.width*7/10), y=(self.height*2/7), anchor_x='center', batch=self.b_labels, group=self.og_semi_foreground), } if isinstance(self.activeScene, ConfigScreen.ConfigScene): return {}#CONFIG has no preset Labels -> they are created by the scene on demand def load_widgets(self): """ load all widgets used in the specific scene """ if isinstance(self.activeScene, ConfigScreen.ConfigScene): return { 'mainInput': Utils.TextWidget("-TEST TEXT-", x=(self.width/2 )-50, y=self.height/2, width=100 ,batch=self.b_widgets), 'textController':Utils.ControledTextBox(x=(self.width/2 )-50, y=(self.height/2) - 50, width=100 , height = 150, batch=self.b_widgets), } def load_sounds(self): """ load all sound resources -> probably optimize for scenes """ return { } ##### # maintanence funcs ##### def clear_externalLabel(self, target=None): pass def register_externalLabel(self, keyName, text, x, y, width, batch): if keyName in self.d_active_labels: return False else: self.d_active_labels[keyName] def clear_animationLists(self, target=None): if target in [None, 'sprites']: self.d_active_SpriteAnimations.clear() if target in [None, 'labels']: self.d_active_LabelAnimations.clear() if target in [None, 'widgets']: self.d_active_WidgetAnimations.clear() def register_animation(self, anim, wantedAnimation): """ registers anims to be animated by custom animations """ if isinstance(anim, pyglet.sprite.Sprite): if anim in self.d_active_SpriteAnimations: return False else: self.d_active_SpriteAnimations[anim] = wantedAnimation elif isinstance(anim, pyglet.text.Label): if anim in self.d_active_LabelAnimations: return False else: self.d_active_LabelAnimations[anim] = wantedAnimation else: if anim in self.d_active_WidgetAnimations: return False else: self.d_active_WidgetAnimations[anim] = wantedAnimation def run_AnimationManager(self): """ animates all registered animations that are currently active """ l_deactivateAnims = list() for sprite, animationType in self.d_active_SpriteAnimations.items(): # forward sprite animation infos to active scene self.activeScene.maintain_SpriteAnimations(l_deactivateAnims, sprite, animationType) for label, animationType in self.d_active_LabelAnimations.items(): # forward label animation infos to active scene self.activeScene.maintain_LabelAnimations(l_deactivateAnims, label, animationType) for widget, animationType in self.d_active_WidgetAnimations.items(): # forward label animation infos to active scene self.activeScene.maintain_WidgetAnimations(l_deactivateAnims, widget, animationType) # when all anims are played out active anims must be cleared for finished ones for anim in l_deactivateAnims: if isinstance(anim, pyglet.sprite.Sprite): self.d_active_SpriteAnimations.pop(anim, None) if isinstance(anim, pyglet.text.Label): self.d_active_LabelAnimations.pop(anim, None) if isinstance(anim, Utils.TextWidget): self.d_active_WidgetAnimations.pop(anim, None) def activate_scene(self, scene): self.activeScene = scene self.activeSceneName = self.activeScene.sceneName def transferToScene(self, originScene, targetScene): """ transfers from a scene to a scene phase false = no transition phase 1 = origin is deactivated phase 2 = target is loaded """ if self.sceneTransferPhase is False: self.sceneTransferPhase = 1 if self.sceneTransferPhase is 1: if self.activeScene is None : self.sceneTransferPhase = 2 elif self.activeScene.isAlive is False: self.activeScene.killSprites(self,self.d_active_sprites) self.activeScene.killLabels(self,self.d_active_labels) self.activeScene.killWidgets(self,self.d_active_widgets) self.sceneTransferPhase = 2 if self.sceneTransferPhase is 2: if self.targetScene is "INTRO": self.activate_scene(IntroScreen.IntroScene()) if self.targetScene is "CONFIG": self.activate_scene(ConfigScreen.ConfigScene()) self.d_active_sprites = self.load_sprites() self.d_active_labels = self.load_labels() self.d_active_widgets = self.load_widgets() self.activeScene.prepareSprites(self, self.d_active_sprites) self.activeScene.prepareLabels(self, self.d_active_labels) self.activeScene.prepareWidgets(self,self.d_active_widgets) self.targetScene = False self.sceneTransferPhase = False def checkSceneTransfers(self): """ check if any scene transferes have to be made """ #scenetransfer is broken -> repair + more control (e.g. introscene) if self.activeScene is None: self.transferToScene(self.activeScene,self.targetScene) elif self.activeScene.isInTransfer is True or self.sceneTransferPhase is 1: self.transferToScene(self.activeScene,self.targetScene) ##### # main loop ##### def run(self): while self.alive == 1: self.run_AnimationManager() self.checkSceneTransfers() if self.activeScene is not None: self.targetScene = self.activeScene.run(self) self.render() event = self.dispatch_events() # Programm starting point if __name__ == '__main__': game = main(resizable=True) game.run()