This repository has been archived on 2025-07-12. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
shroom_of_doom/lib/interface.py
2025-02-26 14:40:25 -05:00

300 lines
8.6 KiB
Python

#!~/.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()