300 lines
8.6 KiB
Python
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() |