def __init__(self, rect: pygame.Rect, on_value_changed: Callable[[str], None] = None, on_edit_finished: Callable[[str], None] = None, text: str = "", character_limit: int = 14, style: Style = None, parent: Component = None) -> None: """Create a new Textbox. <rect> is the rectangle representing this component's position and size on the screen. <on_value_changed> is the function called when the textbox's text is changed. <on_edit_finished> is the function called when the textbox's text is done being changed. <text> is the starting text of the textbox. <character_limit> is the maximum number of characters that the textbox can have. <style> dictates the appearence of the component. If None, the default style will be used. <parent> is the component that is immediately above this component in the tree. """ Label.__init__(self, rect, text=text, style=style, parent=parent) self._on_value_changed = on_value_changed self._on_edit_finished = on_edit_finished self._time_since_blink = 0 self._time_for_blink = 500 self._is_blinker_on = False self._cursor_pos = 0 self._selection_end_pos = 0 self._is_selection_finished = True self._character_limit = character_limit
def create_labels(self, root: Component) -> None: """ Create all labels in the settings menu. """ label_style = Style(background_color=(0, 128, 255), primary_color=(255, 255, 255)) self.soundFX = Label(text="Adjust Sound FX", rect=Rect(150, 120, 250, 50), style=label_style, parent=self.soundFx_panel) self.music = Label(text="Music volume", rect=Rect(200, 200, 200, 50), style=label_style, parent=self.music_panel) self.window_mode = Label(text="Window Mode", rect=Rect(200, 300, 200, 100), style=label_style, parent=self.window_mode_panel) size = sm.SceneManager.instance.get_screen_size() title_rect = Rect(400, 45, 250, 50) title_rect.centerx = size[0] / 2 self.menu = Label(text="CHANGE SETTINGS", rect=title_rect, style=label_style, parent=root)
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 initComponents(self): textFont = Fonts.getFont(Fonts.Roboto_Mono, 30) self.label = Label(self.window, self.app.width / 2, 5 * self.app.height / 6, text="", font=textFont) self.label.x = self.app.width / 2 self.label.y = 6 * self.app.height / 7 self.addComponent(self.label)
def drawItemCount(self, amount, rect): font = Fonts.getFont(Fonts.Courier, 20) if amount > 1: window = self.window x, y = rect.bottomright countLabel = Label(window, x, y, str(amount), font, color=Colors.BLACK) countLabel.draw()
def update(self, dt: float) -> None: """Update the blink status. <dt> is the time since last update in milliseconds. """ Label.update(self, dt) if (not self.is_focused()): return self._time_since_blink += dt if (self._time_since_blink >= self._time_for_blink): self._time_since_blink -= self._time_for_blink self._is_blinker_on = not self._is_blinker_on self._redraw()
def initComponents(self): textFont = Fonts.getFont(Fonts.Courier, 30) window = self.window height, width = self.app.height, self.app.width title = Label(window, width/2, 0.5*height/3, font=textFont, text="Load World") self.worldButtons = [] y = [1.8, 2.5, 3.2] for i in range(3): button = Button(window, width/2, y[i]*height/4, font=textFont, text="New World", padding=10, fillColor=Colors.WHITE) button.setOnClickListener(self.loadWorld, i) self.worldButtons.append(button) self.deleteButtons = [] for i in range(3): button = self.worldButtons[i] imgButton = ImageButton(window, width/2 + button.width, y[i]*height/4, Assets.assets["delete"], padding=10, borderWidth=0) imgButton.setOnClickListener(self.deleteWorld, i) self.deleteButtons.append(imgButton) self.addComponents(self.worldButtons) self.addComponents(self.deleteButtons) self.addComponent(title)
def initComponents(self): textFont = Fonts.getFont(Fonts.Courier, 30) window = self.window height, width = self.app.height, self.app.width title = Label(window, width / 2, 1 * height / 3, font=textFont, text="Craft112") startGame = Button(window, width / 2, 1.5 * height / 3, font=textFont, text="Start Game", padding=10) startGame.setOnClickListener(lambda: self.app.changeScene("load_game")) quitGame = Button(window, width / 2, 2 * height / 3, font=textFont, text="Quit Game", padding=10) quitGame.setOnClickListener(self.app.quit) self.addComponents([title, startGame, quitGame])
def __init__(self, rect: Rect, on_click: Callable[[int], None] = None, text: str = "", style: Style = None, parent: Component = None) -> None: """Create a new Button. <rect> is the rectangle representing this component's position and size on the screen. <on_click> is the function called when the button is clicked. <text> is the text to be displayed. <style> dictates the appearence of the component. If None, the default style will be used. <parent> is the component that is immediately above this component in the tree. """ Label.__init__(self, rect, text=text, style=style, parent=parent) if (on_click is not None): self._on_click = on_click
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()
def __init__(self, root: Panel): """Create a new MainMenuScene, creating the gui components to display. """ size = root.get_rect().size title_rect = Rect(0, 0, 500, 70) title_rect.center = (size[0] / 2, size[1] / 2 - 200) # A panel for all the options options_panel = VerticalPanel(rect=Rect(size[0] / 4, size[1] / 2, size[0] / 2, size[1] / 4), expand_height=False, parent=root) # Title label Label(text="BATTLE SHIP!", rect=title_rect, style=Style(background_color=None, border_width=0, font=pygame.font.Font('freesansbold.ttf', 64), primary_color=(255, 255, 255)), parent=root) # A style for all of the menu options button_style = Style(primary_color=(255, 255, 255), background_color=(128, 0, 0), border_width=1, border_color=(0, 0, 0), font=pygame.font.Font('freesansbold.ttf', 32)) # Player vs Computer button Button(rect=Rect(0, 0, 400, 40), on_click=self._pvc_clicked, text="Player vs Computer", style=button_style, parent=options_panel) # Player vs Player button Button(rect=Rect(0, 0, 400, 40), on_click=self._pvp_clicked, text="Player vs Player", style=button_style, parent=options_panel) # Settings button Button(rect=Rect(0, 0, 400, 40), on_click=self._settings_clicked, text="Settings", style=button_style, parent=options_panel) # Quit button Button(rect=Rect(0, 0, 400, 40), on_click=self._quit_clicked, text="Quit", style=button_style, parent=options_panel)
def initText(self): self.label = Label(self.window, self.x, self.y, self.text, self.font, color=self.textColor) rect = self.label.label.get_rect() self.width, self.height = rect.width, rect.height self.width += 2 * self.padding self.height += 2 * self.padding
def set_parent(self, parent: Optional[Component]) -> None: """Set the component's parent. The default style is used if <parent> is None. """ Panel.set_parent(self, parent) if (self._parent is None): return self.set_rect(self._parent.get_rect()) size = self.get_rect().size title_rect = Rect(0, 0, 500, 70) title_rect.center = (size[0] / 2, size[1] / 2 - 200) self.clear_children() self.options_panel = VerticalPanel(rect=Rect(size[0] / 4, size[1] / 2, size[0] / 2, size[1] / 4), expand_height=False, parent=self) self.title_label = Label(text="BATTLE SHIP!", rect=title_rect, style=Style(background_color=None, border_width=0, font=pygame.font.Font( 'freesansbold.ttf', 64), primary_color=(255, 255, 255)), parent=self) button_style = Style(primary_color=(255, 255, 255), background_color=(128, 0, 0), border_width=1, border_color=(0, 0, 0), font=pygame.font.Font('freesansbold.ttf', 32)) self.cont_button = Button(rect=Rect(0, 0, 400, 40), on_click=self._cont_clicked, text="Continue", style=button_style, parent=self.options_panel) self.main_menu_button = Button(rect=Rect(0, 0, 400, 40), on_click=self._main_menu_clicked, text="Main menu", style=button_style, parent=self.options_panel) self.quit_button = Button(rect=Rect(0, 0, 400, 40), on_click=self._quit_clicked, text="Quit", style=button_style, parent=self.options_panel)
def _draw(self, screen: pygame.Surface, changes: List[pygame.Rect]) -> None: """Draw the textbox's visuals to the screen. <change> is a list of rectangles that represent the changed areas of the screen. """ Component._draw(self, screen, changes) text_rect = self._text_image.get_rect() text_rect.center = self._rect.center # Draw Selection Background if (self._has_multi_char_selection()): start = self._style.font.size(self.get_text()[:self._cursor_pos]) end = self._style.font.size( self.get_text()[:self._selection_end_pos]) start_x = min(start[0], end[0]) end_x = max(start[0], end[0]) background_rect = pygame.Rect(text_rect.x + start_x, text_rect.y, end_x - start_x, text_rect.height) changes.append(screen.fill((0, 0, 255), background_rect)) Label._draw_text(self, screen, changes) return # Draw text Label._draw_text(self, screen, changes) # Draw Blinker if (self._is_blinker_on): size = self._style.font.size(self.get_text()[:self._cursor_pos]) cursor_rect = pygame.Rect(text_rect.x + size[0], text_rect.y, 2, text_rect.height) if (self._rect.x < cursor_rect.x < self._rect.right): changes.append( screen.fill(self._style.primary_color, cursor_rect))
class GameScene(Scene): def __init__(self, app): super().__init__(app) self.initNew() self.initGame() self.initComponents() self.initOverlay() self.isPaused = False def initNew(self): self.initWorld() self.initPlayer() def initWorld(self): self.world = World() self.world.generateWorld() def initGame(self): self.player = None self.previewWidth = 10 Constants.blockSize = self.app.width / (self.previewWidth * 2 + 1) self.previewHeight = math.ceil(self.app.height / Constants.blockSize) self.offset = 5 # load outside canvas to hide buffering self.renderOffset = 7.6 self.holdPos = False self.holdPosTickThresh = 30 self.holdPosTick = 0 self.difficulty = 2 self.difficultyLabels = ["Peaceful", "Easy", "Normal", "Hard"] def initPlayer(self): self.player = Player(self.world) sword = ItemStack(Material.SWORD, 1) fire_sword = ItemStack(Material.FIRE_SWORD, 1) ice_sword = ItemStack(Material.ICE_SWORD, 1) pickaxe = ItemStack(Material.PICKAXE, 1) explosive_pickaxe = ItemStack(Material.EXPLOSIVE_PICKAXE, 1) inventory = self.player.getInventory() inventory.addItem(sword) inventory.addItem(fire_sword) inventory.addItem(ice_sword) inventory.addItem(pickaxe) inventory.addItem(explosive_pickaxe) y = self.world.getHighestBlock(0) self.player.position = Vector2D(0, y) self.world.addEntity(self.player) def initComponents(self): textFont = Fonts.getFont(Fonts.Roboto_Mono, 30) self.label = Label(self.window, self.app.width / 2, 5 * self.app.height / 6, text="", font=textFont) self.label.x = self.app.width / 2 self.label.y = 6 * self.app.height / 7 self.addComponent(self.label) def initOverlay(self): textFont = Fonts.getFont(Fonts.Courier, 30) window = self.window width, height = self.app.width, self.app.height unit = height / 4 self.volumeButton = ImageButton(window, 2 * width / 3, 1.6 * unit, Assets.assets["volume_on"], fillColor=Colors.WHITE) self.volumeButton.setOnClickListener(self.toggleVolume) self.respawnButton = Button(window, width / 2, 2 * unit, font=textFont, text="Respawn", fillColor=Colors.WHITE, padding=10) self.respawnButton.setOnClickListener(self.respawnPlayer) self.resumeButton = Button(window, width / 2, 2 * unit, font=textFont, text="Resume Game", fillColor=Colors.WHITE, padding=10) self.resumeButton.setOnClickListener(self.togglePause) self.difficultyButton = Button(window, width / 2, 2.5 * unit, font=textFont, text="Difficulty: Normal", fillColor=Colors.WHITE, padding=10) self.difficultyButton.setOnClickListener(self.cycleDifficulty) self.quitButton = Button(window, width / 2, 3 * unit, font=textFont, text="Main Menu", fillColor=Colors.WHITE, padding=10) self.quitButton.setOnClickListener(self.quit) self.overlayComponents = [ self.resumeButton, self.quitButton, self.respawnButton, self.volumeButton, self.difficultyButton ] for component in self.overlayComponents: component.setEnabled(False) self.addComponents(self.overlayComponents) def drawComponents(self): self.drawBackground() self.drawTerrain() self.drawEntities() self.drawInventory() self.drawOverlay() super().drawComponents() def drawBackground(self): window = self.window player = self.player bg = Assets.assets["game_background"] bgSize = bg.get_size() windowSize = window.get_size() x = windowSize[0] - bgSize[0] / 2 - player.position[0] y = windowSize[1] - bgSize[1] / 2 + player.position[1] window.blit(bg, (x, y)) def drawTerrain(self): world = self.world height, width = self.previewHeight, self.previewWidth player = self.player px, py = player.position offset = self.offset renderOffset = self.renderOffset size = Constants.blockSize for y in range(-height - offset, height + offset): for x in range(-width - offset, width + offset): bx = px + x by = py - y block = world.getBlock((bx, by)) renderX = (x + width) * size renderY = (y + height - renderOffset) * size self.drawBlock(block, (renderX, renderY)) def drawBlock(self, block, position): window = self.window texture = Assets.assets["textures"][block.getType().getId()][0] x, y = position size = Constants.blockSize blockRect = pygame.Rect(0, 0, size, size) blockRect.center = (x + size / 2, y + size / 2) window.blit(texture, blockRect) def drawEntities(self): window = self.window world = self.world px, py = self.player.position cx, cy = self.app.width / 2, self.app.height / 2 for entity in world.entities: x, y = entity.position rx = cx + (x - px) * Constants.blockSize ry = cy + (-y + py) * Constants.blockSize if not isinstance(entity, Player): ry += self.renderOffset entity.draw(window, rx, ry) def drawInventory(self): window = self.window inventory = self.player.getInventory() width = inventory.getDimensions()[0] cellSize = 40 offset = 10 for i in range(width): rect = pygame.Rect(i * cellSize + offset, offset, cellSize, cellSize) borderWidth = 1 if i == self.player.equipIndex: borderWidth = 3 pygame.draw.rect(self.window, Colors.BLACK, rect, borderWidth) item = inventory[0][i] if item.getType() != Material.AIR: id = item.getType().getId() texture = Assets.assets["textures"][id] if item.getType() in Tools.tools: texture = texture[0] else: texture = texture[1] tWidth, tHeight = texture.get_size() tRect = pygame.Rect(0, 0, tWidth, tHeight) tRect.center = rect.center window.blit(texture, tRect) amount = item.getAmount() self.drawItemCount(amount, tRect) def drawItemCount(self, amount, rect): font = Fonts.getFont(Fonts.Courier, 20) if amount > 1: window = self.window x, y = rect.bottomright countLabel = Label(window, x, y, str(amount), font, color=Colors.BLACK) countLabel.draw() def drawOverlay(self): if Constants.FILTER is None: Constants.FILTER = pygame.Surface( (self.app.width, self.app.height)) Constants.FILTER.set_alpha(100) Constants.FILTER.fill((255, 255, 255)) for component in self.overlayComponents: enabled = not self.player.isAlive or self.isPaused component.setEnabled(enabled) if not self.player.isAlive: self.window.blit(Constants.FILTER, (0, 0)) self.resumeButton.setEnabled(False) elif self.isPaused: self.window.blit(Constants.FILTER, (0, 0)) self.respawnButton.setEnabled(False) def onKeyPress(self, keys, mods): super().onKeyPress(keys, mods) if self.isPaused: return player = self.player if keys[pygame.K_a]: player.move(-1, 0, walk=True) elif keys[pygame.K_d]: player.move(1, 0, walk=True) else: if not self.holdPos: player.faceDirection(0, False) player.update() def onKeyDown(self, key): if key == pygame.K_ESCAPE and self.player.isAlive: self.togglePause() if self.isPaused: return player = self.player if key == pygame.K_c: self.world.rngSpawnEntity(self.player, spawn=True) else: for i in range(9): if key == pygame.K_1 + i: player.equipIndex = i break if not player.isJumping and key == pygame.K_SPACE: player.jump() player.update() def onMouseClick(self, mousePos): super().onMouseClick(mousePos) if self.isPaused: return item = self.player.getEquippedItem() if item.getType() in Tools.tools: self.breakBlock(mousePos) elif item.getType() in Weapons.weapons: self.attack(mousePos, item) def onMouseRightClick(self, mousePos): if self.isPaused: return player = self.player type = player.getEquippedItem().getType() if (type not in Tools.tools and type not in Weapons.weapons and type != Material.AIR): _, bx, by = self.getBlockFromMousePos(mousePos) world = self.world item = player.getEquippedItem() world.setBlock(item.getType(), (bx, by)) item.setAmount(item.getAmount() - 1) if item.getAmount() == 0: item.material = Material.AIR item.amount = 1 def onMouseScroll(self, scroll): player = self.player inventory = player.getInventory() player.equipIndex = (player.equipIndex - scroll) % (inventory.width) self.label.setText(player.getEquippedItem().getType().getName()) def onTick(self): if self.isPaused: return self.world.tick() if self.holdPos: self.holdPosTick += 1 if self.holdPosTick == self.holdPosTickThresh: self.holdPosTick = 0 self.holdPos = False if not self.player.isAlive: self.isPaused = True def onLoad(self): if self.isPaused: self.togglePause() self.onMouseScroll(0) self.difficulty = self.world.difficulty def getBlockFromMousePos(self, mousePos): rx, ry = mousePos px, py = self.player.position size = Constants.blockSize height, width = self.previewHeight, self.previewWidth offset = 0.5 x = rx / size - width - offset y = ry / size - height + self.renderOffset - offset bx = px + x by = py - y block = self.world.getBlock((bx, by)) return block, bx, by def breakBlock(self, mousePos): block, bx, by = self.getBlockFromMousePos(mousePos) if block.getType() != Material.AIR: item = self.player.getEquippedItem() radius = Tools.tools[item.getType()] self.destroyBlock((bx, by)) for dx in range(radius): for dy in range(radius): self.destroyBlock((bx + dx, by + dy)) def destroyBlock(self, coordinate): block = self.world.getBlock(coordinate) if block.getType() != Material.AIR: self.player.getInventory().addItem(ItemStack(block.getType(), 1)) self.world.setBlock(Material.AIR, coordinate) def attack(self, mousePos, item): mx = mousePos[0] cx = self.app.width / 2 player = self.player direction = 1 if mx > cx else -1 dead = [] self.player.faceDirection(direction, False) self.holdPos = True weapon = Weapons.weapons[item.getType()] damage = weapon.damage reach = weapon.reach targets = [] for entity in self.world.entities: if isinstance(entity, Enemy): pPos = player.position ePos = entity.position px, ex = pPos[0], ePos[0] relativeDelta = 1 if ex > px else -1 distance = pPos.distance(ePos) if relativeDelta == direction and distance <= reach: knockback = True status = 0 if weapon.getType() == Material.ICE_SWORD: knockback = False status = 1 elif weapon.getType() == Material.FIRE_SWORD: status = 2 targets.append( (entity, damage, relativeDelta, knockback, status)) for entity, damage, relativeDelta, knockback, status in targets: entity.damage(damage, relativeDelta, knockback) if status == 1: entity.freeze() elif status == 2: entity.burn() def togglePause(self): self.isPaused = not self.isPaused self.difficulty = self.world.difficulty def toggleVolume(self): self.app.volumeOn = not self.app.volumeOn if self.app.volumeOn: self.volumeButton.setImage(Assets.assets["volume_on"]) self.app.musicChannel.set_volume(1) else: self.volumeButton.setImage(Assets.assets["volume_off"]) self.app.musicChannel.set_volume(0) def cycleDifficulty(self): self.difficulty = (self.difficulty + 1) % 4 self.world.setDifficulty(self.difficulty) self.difficultyButton.setText( f"Difficulty: {self.difficultyLabels[self.difficulty]}") def respawnPlayer(self): self.player.respawn() self.isPaused = False def quit(self): Utility.save(self.world) pygame.event.wait() self.app.changeScene("main")
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()))
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