class Main(): def __init__(self): # -- Inicio modulos pygame.init() # -- Obtencion de info del hardware self._info = pygame.display.Info() # -- Se crea un display utilizando la info self._display = pygame.display.set_mode([self._info.current_w, self._info.current_h], pygame.FULLSCREEN | pygame.HWSURFACE) # -- Se definen los controles self._fuente_top_label = pygame.font.Font(None, 48) self._fuente_board = pygame.font.Font(None, 30) self._top_label = Label(self._fuente_top_label, "Butia Control Dashboard v1.0", (255, 255, 255), (0, 0, 0)) self._boton = Button(Label(self._fuente_top_label, "Salir", (255, 255, 255), (0, 0, 0)), Label(self._fuente_top_label, "Salir", (0, 0, 0), (255, 255, 255))) self._boton_pausar = Button(Label(self._fuente_top_label, "Pausar", (255, 255, 255), (0, 0, 0)), Label(self._fuente_top_label, "Pausar", (0, 0, 0), (255, 255, 255))) self._boton.set_rect(self._info.current_w/2 - self._boton.get_rect().width / 2, self._info.current_h - (self._boton.get_rect().height + 10)) self._boton_pausar.set_rect(self._info.current_w/2 - self._boton_pausar.get_rect().width / 2, self._info.current_h / 4 * 3 - (self._boton_pausar.get_rect().height / 2)) self._label_estado = Label(self._fuente_board, "Estado:", (255, 255, 255), (0, 0, 0)) self._label_estado_informacion = Label(self._fuente_board, "", (255, 255, 255), (0, 0, 0)) self._label_tarea = Label(self._fuente_board, "Tarea:", (255, 255, 255), (0, 0, 0)) self._label_tarea_informacion = Label(self._fuente_board, "", (255, 255, 255), (0, 0, 0)) self._label_error_butia = Label(self._fuente_board, "Revise la conexion con el butia (!)", (255, 255, 255), (0, 0, 0)) self._label_error_nxt = Label(self._fuente_board, "Revise la conexion con el nxt (!)", (255, 255, 255), (0, 0, 0)) self._cursor = Cursor() # -- Se definen las variables self._butia_error = True self._nxt_error = True self._salir = False self._reloj = pygame.time.Clock() self._chronometer = Chronometer(1) self._timer = None self._ready = True self._times = 0 self._pause = False # -- Se crean las instancias de butia y nxt self._butia = Butia() self._nxt = Nxt() # -- Se definen los sensores nxt # -- DEFINICION DEL GAMELOOP def update(self): # -- Se actualizan los parametros # -- Deteccion de eventos for event in pygame.event.get(): if event.type == pygame.KEYDOWN: self._salir = True if event.type == pygame.MOUSEBUTTONDOWN: btn1, btn2, btn3 = pygame.mouse.get_pressed() if btn1: if self._boton.on_click(self._cursor): self._salir = True if self._boton_pausar.on_click(self._cursor): if self._pause: self._pause = False elif not self._pause: self._pause = True # -- Obtencion del info del entorno # -- Comprobacion de conexiones if self._butia.get_butia().getFirmwareVersion() == -1: self._butia_error = True else: self._butia_error = False if not self._nxt.get_nxt(): self._nxt_error = True else: self._nxt_error = False # -- Se corre el seguidor solo si la conexion funciona if not self._pause: if not self._butia_error and not self._nxt_error: if self._butia.get_butia().getGray(5) < 14000 and self._butia.get_butia().getGray(2) < 40000: self._butia.get_butia().set2MotorSpeed(1, 600, 1, 600) elif self._butia.get_butia().getGray(5) < 14000 and self._butia.get_butia().getGray(2) > 40000: self._butia.get_butia().set2MotorSpeed(1, 600, 0, 600) elif self._butia.get_butia().getGray(5) > 14000 and self._butia.get_butia().getGray(2) < 40000: self._butia.get_butia().set2MotorSpeed(0, 600, 1, 600) if self._nxt.get_nxt().get_port(1).getSample() < 20: if self._ready: self._label_tarea_informacion.set_text("Recogiendo muestras") self._label_tarea_informacion.update(self._display, self._info.current_w/4 + self._label_estado.get_rect().width + 20, self._info.current_h/3 + 10 + self._label_estado_informacion.get_rect().height) self.accionar_mecanismo() self._label_tarea_informacion.set_text("Recorriendo el mundo") self._label_tarea_informacion.set_text("Ninguna") else: self._label_tarea_informacion.set_text("Pausado") self._butia.get_butia().set2MotorSpeed(0, 0, 0, 0) def accionar_mecanismo(self): # -- Secuencia que realiza la pala # -- Ajustar valores de rotacion para alcanzar la medida exacta self._ready = False self._butia.get_butia().set2MotorSpeed(0, 0, 0, 0) self._nxt.get_nxt().get_port("a").turn(-20, 160) self._nxt.get_nxt().get_port("b").turn(20, 640) try: self._nxt.get_nxt().get_port("a").turn(20, 220) except Exception: self._nxt.get_nxt().get_port("b").turn(-20, 10) self._nxt.get_nxt().get_port("a").turn(20, 110) self._nxt.get_nxt().get_port("b").turn(-20, 320) self._nxt.get_nxt().get_port("a").turn(-20, 110) self._nxt.get_nxt().get_port("b").turn(-20, 320) #self.motorA.turn(-20, 110) self._nxt.get_nxt().get_port("a").turn(20, 90) self._times += 1 if self._times < 3: self.motorC.turn(-20, 450) else: self._nxt.get_nxt("a").turn(-20, 50) self._nxt.get_nxt("c").turn(20, 450*2) self._nxt.get_nxt("a").turn(20, 50) self._times = 0 self._timer = Timer(5) def render(self): # -- Se redibuja la pantalla con las actualizaciones pertinentes self._display.fill((0, 0, 0)) self._boton.on_collide(self._display, self._cursor) self._boton_pausar.on_collide(self._display, self._cursor) self._cursor.update() self._top_label.update(self._display, self._info.current_w/2 - self._top_label.get_rect().width/2, 10) self._label_estado.update(self._display, self._info.current_w/4, self._info.current_h/3) self._label_estado_informacion.update(self._display, self._info.current_w/4 + self._label_estado.get_rect().width + 20, self._info.current_h/3) self._label_tarea.update(self._display, self._info.current_w/4, self._info.current_h/3 + 10 + self._label_estado.get_rect().height) self._label_tarea_informacion.update(self._display, self._info.current_w/4 + self._label_estado.get_rect().width + 20, self._info.current_h/3 + 10 + self._label_estado_informacion.get_rect().height) if not self._butia_error and not self._nxt_error: self._label_estado_informacion.set_text("Activo") if self._butia_error and self._chronometer.get_value(): self._label_error_butia.update(self._display, self._info.current_w/5 * 3, self._info.current_h/3) self._label_estado_informacion.set_text("Error") if self._nxt_error and self._chronometer.get_value(): self._label_error_nxt.update(self._display, self._info.current_w/5 * 3, self._info.current_h/3 + 10 + self._label_error_nxt.get_rect().height) self._label_estado_informacion.set_text("Error") pygame.display.flip() def sleep(self): # -- Se espera self._reloj.tick(100) def run(self): while not self._salir: self.update() self.render() self.sleep() def set_ready(self): self._ready = True
class SceneManager(object): """A Singleton that manages all scenes and tracks the appilcation's running state. The static instance variable can be used to access this object. This class must be created atleast once. The game loop will run until the application closes. === Private Attributes === _screen_size: The size of the screen in pixels. _screen: The surface that represents the screen. _clock: A object that records the time inbettween calls to its tick function. _fps_counter: A label that displays the current framerate. _scenes: A list of all available scenes. _running: Whether or not the application is currently running. _is_fullscreen: Whether or not the application is currently in fullscreen mode. _active_scene_index: The currently active scene's index. _active_scene: The currently active scene. """ instance = None _screen_size: Tuple[int, int] _screen: pygame.Surface _clock: pygame.time.Clock _fps_counter: Component _scenes: List _running: bool _is_fullscreen: bool _active_scene_index: int _active_scene: object def __init__(self) -> None: """Create a new SceneManager and setup the static instance variable.""" if (SceneManager.instance is None): SceneManager.instance = self # Tell pygame to center the window os.environ['SDL_VIDEO_CENTERED'] = '1' pygame.font.init() self._screen_size = (0, 0) self._is_fullscreen = True self._clock = pygame.time.Clock() self._scenes = [MainMenuScene, SettingsScene, GameScene] self._running = True self._setup_screen() # Always visible components self._root = Panel(self._screen.get_rect(), style=Style(background_color=(255, 0, 0), border_width=0)) self._fps_counter = Label(text="Calculating", rect=pygame.Rect(0, 25, 75, 20), style=Style(background_color=(255, 0, 0), border_width=0, primary_color=(255, 255, 255)), parent=self._root) self._rest_fps_counter_position() # Start the game self.change_scene(0) self._run_game_loop() def set_screen_size(self, size: Tuple[int, int]) -> None: """Set the screen size. This method re-creates the active scene.""" em.EventManager.instance.set_invalid() if (self._is_fullscreen): self._screen_size = (0, 0) else: self._screen_size = (max(size[0], MINIMUM_SCREEN_SIZE[0]), max(size[1], MINIMUM_SCREEN_SIZE[1])) self._setup_screen() self._root.set_rect(self._screen.get_rect()) self._rest_fps_counter_position() self.change_scene(self._active_scene_index) def _setup_screen(self) -> None: """Create the screen object.""" pygame.display.init() pygame.display.set_caption("Battleships") pygame.key.set_repeat(250, 50) flags = pygame.RESIZABLE if (self._is_fullscreen): flags |= pygame.FULLSCREEN self._screen = pygame.display.set_mode(self._screen_size, flags) self._screen_size = self._screen.get_rect().size def is_fullscreen(self) -> bool: """Whether or not the the application is in fullscreen mode.""" return self._is_fullscreen def toggle_fullscreen(self) -> None: """Toggles the application mode between fullscreen and windowed.""" self._is_fullscreen = not self._is_fullscreen pygame.display.quit() if (self._is_fullscreen): self.set_screen_size((0, 0)) else: self.set_screen_size(DEFAULT_WINDOWED_MODE_SIZE) def _rest_fps_counter_position(self): """Sets the position of the fps counter.""" fps_rect = self._fps_counter.get_rect() fps_rect.right = self._screen_size[0] - 25 self._fps_counter.set_rect(fps_rect) def get_screen_size(self) -> Tuple[int, int]: """Get the size of the screen in pixels.""" return self._screen_size def get_root(self) -> Component: """Get the topmost component.""" return self._root def change_scene(self, scene_index: int) -> None: """Switch the current scene to the scene at index <scene_index>.""" self._root.clear_children() self._active_scene_index = scene_index self._active_scene = self._scenes[scene_index](self._root) self._root.add_child(self._fps_counter) em.EventManager.instance.set_invalid() def quit_game(self) -> None: """Close the application.""" self._running = False def _run_game_loop(self) -> None: """Run the game loop until the application closes""" while self._running: # Handle Events em.EventManager.instance.update() # Update self._root.update(self._clock.tick()) # Framerate Limit if (self._clock.get_fps() != float("inf")): self._fps_counter.set_text(str(int(self._clock.get_fps()))) else: self._fps_counter.set_text("Infinity") # Draw changed = [] self._root.render(self._screen, changed) pygame.display.update(changed) pygame.quit()
def set_text(self, text: str) -> None: """Set the textbox's text.""" Label.set_text(self, text) if (not self.is_focused()): self._set_cursor_pos(len(self.get_text()))