#!~/.pyenv/versions/3.11.6/bin/python # # Copyright (c) 2024 Cutieguwu | Olivia Brooks # # -*- coding:utf-8 -*- # @Title: Interface Items. # @Author: Cutieguwu | Olivia Brooks # @Email: owen.brooks77@gmail.com | obroo2@ocdsb.ca # @Description: Interface items for menus and scenes in a pygame game. # # @Script: interface.py # @Date Created: 22 Mar, 2024 # @Last Modified: 13 Jun, 2024 # @Last Modified by: Cutieguwu | Olivia Brooks # ---------------------------------------------------------- import pygame from lib.system import FEATURES class Button(): """ Creates a button on a window. """ def __init__(self, game, name, x, y, image_neutral, image_hover, function, args=None): self.TYPE = "button" width = image_neutral.get_width() # Can use neutral image as all images should have identical sizes. height = image_neutral.get_height() self.GAME = game self.WINDOW = self.GAME.WINDOW scale = self.GAME.SCALE.scaleUi self.function = function self.functionArgs = args self.ID = name self.IMAGES = { "neutral": pygame.transform.scale(image_neutral, (width * scale, height * scale)), "hover": pygame.transform.scale(image_hover, (width * scale, height * scale)) } Interface_Functions.convert_images(self) self.rect = self.IMAGES["neutral"].get_rect() self.rect.topleft = (x * scale, y * scale) # Cannot overwrite rect.collidepoint with Interface_Functions.collidepoint. self.time_delay = 0 self.GAME.gameInteractables.append(self) # Add to button to refresh. def draw(self): """ Draws button on screen. """ Interface_Functions.draw(self) def is_hovered(self): """ Checks if button is hovered. """ return Interface_Functions.collidepoint(self, pygame.mouse.get_pos()) def remove(self): """ Clears button from screen. """ Interface_Functions.destroy(self) class Progress_bar(): """ Creates a progress bar that updates based on a scale. """ def __init__(self, game, x, y, barWidth:int, bobberImages:list, barImageLeft, barImageRight, barImageClear, barImageFill): """ x: distance in percent from window origin. y: distance in percent from window origin. barWidth: Percent of window width filled. """ self.GAME = game self.WINDOW = self.GAME.WINDOW self.x = (x / 100) * self.WINDOW.width self.y = (y / 100) * self.WINDOW.height for image in bobberImages: image.convert_alpha() self.bobberImages = bobberImages self.barImages = { "left": barImageLeft.convert_alpha(), "right": barImageRight.convert_alpha(), "clear": barImageClear.convert_alpha(), "fill": barImageFill.convert_alpha() } self.bobberState = 0 self.bobberStateRange = len(bobberImages) self.widthLeft = self.barImages["left"].get_width() self.widthRight = self.barImages["right"].get_width() self.barFillWidth = int("%.0f" % ((self.WINDOW.width * (barWidth / 100)) - (self.widthLeft + self.widthRight))) self.barHeight = self.barImages["left"].get_height() self.bobberHeight = self.bobberImages[self.bobberState].get_height() self.barCenterOffset = (self.barHeight / 2) - (self.barImages["clear"].get_height() / 2) self.bobberTimer = 0 def draw(self, rangeComplete, rangeTotal, framerate=30): self.bobberTimer = self.bobberTimer + 1 rangeComplete = int("%.0f" % (rangeComplete * self.barFillWidth / rangeTotal)) self.WINDOW.window.blit(self.barImages["left"], (self.x, self.y)) self.WINDOW.window.blit(self.barImages["right"], (self.x + self.widthLeft + self.barFillWidth, self.y)) for i in range(0, rangeComplete): self.WINDOW.window.blit(self.barImages["fill"], (self.x + self.widthLeft + i, self.y + self.barCenterOffset)) for i in range(rangeComplete, self.barFillWidth): self.WINDOW.window.blit(self.barImages["clear"], (self.x + self.widthLeft + i, self.y + self.barCenterOffset)) if (self.bobberTimer / framerate) > 0.25: self.bobberTimer = 0 if self.bobberState == self.bobberStateRange - 1: self.bobberState = 0 else: self.bobberState = self.bobberState + 1 self.WINDOW.window.blit(self.bobberImages[self.bobberState], (self.x + rangeComplete, self.y - (self.bobberHeight / 2))) class Checkbox(): """ Creates a Checkbox on a window. """ def __init__(self, game, name, x, y, image_neutral, image_hover, image_active, condition, function=None, args=None): self.TYPE = "checkbox" width = image_neutral.get_width() # Can use neutral image as all images should have identical sizes. height = image_neutral.get_height() self.GAME = game self.WINDOW = self.GAME.WINDOW scale = self.GAME.SCALE.scaleUi self.function = function self.functionArgs = args self.ID = name self.IMAGES = { "neutral": pygame.transform.scale(image_neutral, (width * scale, height * scale)), "hover": pygame.transform.scale(image_hover, (width * scale, height * scale)), "active": pygame.transform.scale(image_active, (width * scale, height * scale)) } Interface_Functions.convert_images(self) self.rect = self.image_neutral.get_rect() self.rect.topleft = (x * scale, y * scale) self.time_delay = 0 self.condition = condition self.GAME.gameInteractables.append(self) # Add to checkbox to refresh. def draw(self): """ Draws checkbox on screen. """ Interface_Functions.draw(self) def is_hovered(self): """ Checks if checkbox is hovered. """ return Interface_Functions.is_hovered(self) def remove(self): """ Clears checkbox from screen. """ Interface_Functions.destroy(self) class Interface_Functions(): """ All functions called by interface objects. """ def __init__(self, game): self.GAME = game def convert_images(object): """ Converts the object's images to pygame format increasing performance. """ temp = {} for image in object.IMAGES.items(): temp[image[0]] = image[1].convert_alpha() object.IMAGES = temp def destroy(object): """ Destroys the interface object. """ temp = [] for interactable in object.GAME.gameInteractables: if interactable != object: temp.append(interactable) object.GAME.gameInteractables = temp del object def draw(object): """ Draws interface object. """ if object.TYPE == "checkbox" and object.condition(): object.WINDOW.window.blit(object.IMAGES["active"], (object.rect.x, object.rect.y)) elif object.is_hovered(): object.WINDOW.window.blit(object.IMAGES["hover"], (object.rect.x, object.rect.y)) else: object.WINDOW.window.blit(object.IMAGES["neutral"], (object.rect.x, object.rect.y)) def enter_fullscreen(self): """ Enters Fullscreen if possible. """ if self.GAME.WINDOW.toggle_fullscreen(): FEATURES["Fullscreen"]["is_active"] = True def exit_to_desktop(self): self.GAME.levelOn = False self.GAME.menuOn = False self.GAME.sceneOn = False self.GAME.gameOn = False def collidepoint(object, coords:tuple): """ Rewritten version of pygame rect.collidepoint. """ x, y, width, height = object.rect dx = width + x dy = height + y if coords[0] in range(x, dx + 1) and coords[1] in range(y, dy + 1): return True else: return False def is_hovered(object): """ Checks if mouse is hovering interface object. """ return Interface_Functions.collidepoint(object, pygame.mouse.get_pos()) def return_to_game(self): """ Exits a pause state. """ for button in self.GAME.LEVEL.layout.INTERACTABLES: button.remove() self.GAME.menuOn = False self.GAME.LEVEL.load_level_state()