rearragned project, removed unneeded game_files folder
This commit is contained in:
1
pocket_friends/elements/__init__.py
Normal file
1
pocket_friends/elements/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Submodule for use in the game. Helps with the drawing of various objects such as sprites and text boxes."""
|
277
pocket_friends/elements/sprites.py
Normal file
277
pocket_friends/elements/sprites.py
Normal file
@@ -0,0 +1,277 @@
|
||||
import pygame
|
||||
import json
|
||||
|
||||
|
||||
class SpriteSheet:
|
||||
"""
|
||||
Class to be used by sprites in order to give them a texture and an animation.
|
||||
|
||||
Attributes:
|
||||
images (list) List of all the sprites in the animation separated from the sprite sheet.
|
||||
"""
|
||||
|
||||
def __init__(self, sprite_sheet, texture_json):
|
||||
"""
|
||||
Creates a sprite sheet given a sprite image and its corresponding JSON file.
|
||||
Args:
|
||||
sprite_sheet (str): The path of the sprite sheet image component.
|
||||
texture_json (str): The path of the sprite sheet JSON component, contains the number of frames in the
|
||||
sprite sheet, and the width and height of an individual sprite from the sprite sheet.
|
||||
"""
|
||||
# Load in whole sprite sheet as one image.
|
||||
sprite_sheet = pygame.image.load(sprite_sheet).convert_alpha()
|
||||
self.images = []
|
||||
|
||||
# Get the sprite sheet json file.
|
||||
with open(texture_json, 'r') as json_file:
|
||||
img_attrib = json.load(json_file)
|
||||
json_file.close()
|
||||
|
||||
# Count for how many images have been added in the image list
|
||||
image_count = 0
|
||||
|
||||
# Get the sprite size as a tuple
|
||||
sprite_size = img_attrib['width'], img_attrib['height']
|
||||
|
||||
# Iterate through every image location on the sprite sheet given the sprite size
|
||||
for i in range(sprite_sheet.get_size()[1] // sprite_size[1]):
|
||||
i *= sprite_size[1]
|
||||
for j in range(sprite_sheet.get_size()[0] // sprite_size[0]):
|
||||
j *= sprite_size[0]
|
||||
|
||||
# Create a new transparent surface
|
||||
sprite = pygame.Surface(sprite_size, pygame.SRCALPHA)
|
||||
# Blit the sprite onto the image
|
||||
sprite.blit(sprite_sheet, (0, 0), (j, i, sprite_size[0], sprite_size[1]))
|
||||
# Add the image to the list of images
|
||||
self.images.append(sprite)
|
||||
|
||||
image_count += 1
|
||||
|
||||
# Break the loop if the specified number of frames has been reached.
|
||||
if image_count >= img_attrib['frames']:
|
||||
break
|
||||
if image_count >= img_attrib['frames']:
|
||||
break
|
||||
|
||||
|
||||
class SelectionEgg(pygame.sprite.Sprite):
|
||||
"""
|
||||
Sprite to render the egg on the egg selection screen.
|
||||
|
||||
Attributes:
|
||||
egg_color (str): The color of the egg (also its name).
|
||||
description (str): The description of the egg to be displayed when selected.
|
||||
contentedness (int): How likely the egg is to stay happy, ranges from 0-5.
|
||||
metabolism (int): How quickly the egg will get hungry, ranges from 0-5.
|
||||
rect (pygame.Rect): Pygame rectangle used to position the egg on screen.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, egg_color, resources_dir):
|
||||
"""
|
||||
Creates a SelectionEgg object given an egg color and a resource location.
|
||||
Args:
|
||||
egg_color (str): The color egg that should be rendered.
|
||||
resources_dir (str): The path of the resources directory.
|
||||
"""
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
|
||||
self.egg_color = egg_color
|
||||
|
||||
# Loads the JSON file of the egg to read in data.
|
||||
with open(resources_dir + '/data/bloop_info/{0}.json'.format(egg_color), 'r') as save_file:
|
||||
json_file = json.load(save_file)
|
||||
save_file.close()
|
||||
|
||||
# Gets the description off the egg from the JSON file.
|
||||
self.description = json_file.get('description')
|
||||
self.contentedness = json_file.get('contentedness')
|
||||
self.metabolism = json_file.get('metabolism')
|
||||
|
||||
# Load the egg from the given color and get the bounding rectangle for the image.
|
||||
sprite_sheet = SpriteSheet(resources_dir + '/images/bloops/{0}/egg.png'.format(self.egg_color),
|
||||
resources_dir + '/images/bloops/{0}/egg.json'.format(self.egg_color))
|
||||
self._images = sprite_sheet.images
|
||||
|
||||
# Get the rectangle from the first image in the list
|
||||
self.rect = self._images[0].get_rect()
|
||||
self._index = 0
|
||||
self.image = self._images[self._index]
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Update the sprite to the next animation frame.
|
||||
"""
|
||||
# Animate the sprite
|
||||
self._index = (self._index + 1) % len(self._images)
|
||||
self.image = self._images[self._index]
|
||||
|
||||
|
||||
class InfoText:
|
||||
"""
|
||||
Class for drawing large amounts of text on the screen at a time
|
||||
"""
|
||||
|
||||
def __init__(self, resources_dir, game_res, text='Test text.'):
|
||||
"""
|
||||
Creates an InfoText object to be used on a surface.
|
||||
Args:
|
||||
resources_dir (str): The full path of the game's resources directory
|
||||
game_res (int): The internal resolution of the game. Used for correct scaling.
|
||||
text (:obj:`str`, optional): The given text to render. Defaults to "Test text."'
|
||||
"""
|
||||
|
||||
self.font = pygame.font.Font(resources_dir + '/fonts/5Pts5.ttf', 10)
|
||||
self.text = [] # Text broken up into a list according to how it will fit on screen.
|
||||
self.max_lines = 6 # Max number of lines to be shown on screen at a time.
|
||||
self.offset = 0
|
||||
self.game_res = game_res
|
||||
|
||||
# Arrow icons to indicate scrolling
|
||||
self.up_arrow = pygame.image.load(resources_dir + '/images/gui/up_arrow.png').convert_alpha()
|
||||
self.down_arrow = pygame.image.load(resources_dir + '/images/gui/down_arrow.png').convert_alpha()
|
||||
|
||||
raw_text = text # Copy the text to a different variable to be cut up.
|
||||
|
||||
margins = 4.5
|
||||
max_line_width = self.game_res - (margins * 2) # The maximum pixel width that drawn text can be.
|
||||
cut_chars = '.,! ' # Characters that will be considered "cuts" aka when a line break can occur.
|
||||
|
||||
# Prevents freezing if the end of the string does not end in a cut character
|
||||
# Will fix eventually more elegantly
|
||||
if raw_text[-1:] not in cut_chars:
|
||||
raw_text += ' '
|
||||
|
||||
# Calculating line breaks.
|
||||
while len(raw_text) > 0:
|
||||
index = 0
|
||||
test_text = '' # Chunk of text to pseudo-render and test the width of.
|
||||
|
||||
# Loops until the testing text has reached the size limit.
|
||||
while True:
|
||||
|
||||
# Break if the current index is larger than the remaining text.
|
||||
if index + 1 > len(raw_text):
|
||||
index -= 1
|
||||
break
|
||||
|
||||
# Add one character to the testing text from the raw text.
|
||||
test_text += raw_text[index]
|
||||
# Get the width of the pseudo-rendered text.
|
||||
text_width = self.font.size(test_text)[0]
|
||||
|
||||
# Break if the text is larger than the defined max width.
|
||||
if text_width > max_line_width:
|
||||
break
|
||||
index += 1
|
||||
pass
|
||||
|
||||
# Gets the chunk of text to be added to the list.
|
||||
text_chunk = raw_text[0:index + 1]
|
||||
# Determines if the chunk of text has any break characters.
|
||||
has_breaks = any(cut_chars in text_chunk for cut_chars in cut_chars)
|
||||
|
||||
# If the text has break characters, start with the last character and go backwards until
|
||||
# one has been found, decreasing the index each time.
|
||||
if has_breaks:
|
||||
while raw_text[index] not in cut_chars:
|
||||
index -= 1
|
||||
text_chunk = raw_text[0:index + 1]
|
||||
# If there are no break characters in the chunk, simply decrease the index by one and insert
|
||||
# a dash at the end of the line to indicate the word continues.
|
||||
else:
|
||||
index -= 1
|
||||
text_chunk = raw_text[0:index + 1]
|
||||
text_chunk += '-'
|
||||
|
||||
# Append the text chunk to the list of text to draw.
|
||||
self.text.append(text_chunk)
|
||||
|
||||
# Cut the text to repeat the process with the new cut string.
|
||||
raw_text = raw_text[index + 1:]
|
||||
|
||||
def draw(self, surface):
|
||||
"""
|
||||
Draw the text on a given surface.
|
||||
Args:
|
||||
surface (:obj:`pygame.Surface`): The surface to draw the text on
|
||||
"""
|
||||
# Constants to help draw the text
|
||||
line_separation = 7
|
||||
left_margin = 3
|
||||
top_margin = 25
|
||||
bottom_margin = 10
|
||||
|
||||
# Draw the lines on the screen
|
||||
for i in range(min(len(self.text), self.max_lines)):
|
||||
text = self.font.render(self.text[i + self.offset], False, (64, 64, 64))
|
||||
surface.blit(text, (left_margin, top_margin + (i * line_separation)))
|
||||
|
||||
# Draw the arrows if there is more text than is on screen.
|
||||
if self.offset != 0:
|
||||
surface.blit(self.up_arrow, ((self.game_res / 2) - (self.up_arrow.get_rect().width / 2), top_margin - 3))
|
||||
if len(self.text) - (self.offset + 1) >= self.max_lines:
|
||||
surface.blit(self.down_arrow,
|
||||
((self.game_res / 2) - (self.down_arrow.get_rect().width / 2), self.game_res - bottom_margin))
|
||||
|
||||
def scroll_down(self):
|
||||
"""
|
||||
Scrolls the text on the screen down.
|
||||
"""
|
||||
# Ensures that the offset cannot be too big as to try to render non-existent lines.
|
||||
if len(self.text) - (self.offset + 1) >= self.max_lines:
|
||||
self.offset += 1
|
||||
|
||||
def scroll_up(self):
|
||||
"""
|
||||
Scrolls the text on the screen up.
|
||||
"""
|
||||
if self.offset > 0: # Ensures a non-zero offset is not possible.
|
||||
self.offset -= 1
|
||||
|
||||
|
||||
class EggInfo:
|
||||
"""
|
||||
Class to draw the contentedness and metabolism value off the egg on the info screen.
|
||||
"""
|
||||
|
||||
def __init__(self, resources_dir, contentedness, metabolism, location):
|
||||
self.contentedness = contentedness
|
||||
self.metabolism = metabolism
|
||||
self.x = location[0]
|
||||
self.y = location[1]
|
||||
|
||||
# Create a new surface to blit onto the other surface
|
||||
self.surface = pygame.Surface((44, 15), pygame.SRCALPHA)
|
||||
|
||||
# Blit the two indicator icons on screen
|
||||
smiley = pygame.image.load(resources_dir + '/images/gui/smiley.png').convert_alpha()
|
||||
self.surface.blit(smiley, (0, 0))
|
||||
apple = pygame.image.load(resources_dir + '/images/gui/apple.png').convert_alpha()
|
||||
self.surface.blit(apple, (1, 9))
|
||||
|
||||
# Draw 5 stars. If the value of the contentedness is less than the current star, make it a blank star.
|
||||
for i in range(5):
|
||||
if i < self.contentedness:
|
||||
star = pygame.image.load(resources_dir + '/images/gui/star.png').convert_alpha()
|
||||
else:
|
||||
star = pygame.image.load(resources_dir + '/images/gui/blank_star.png').convert_alpha()
|
||||
self.surface.blit(star, (11 + (i * 6), 1))
|
||||
|
||||
# Draw 5 stars. If the value of the metabolism is less than the current star, make it a blank star.
|
||||
for i in range(5):
|
||||
if i < self.metabolism:
|
||||
star = pygame.image.load(resources_dir + '/images/gui/star.png').convert_alpha()
|
||||
else:
|
||||
star = pygame.image.load(resources_dir + '/images/gui/blank_star.png').convert_alpha()
|
||||
self.surface.blit(star, (11 + (i * 6), 10))
|
||||
|
||||
def draw(self, surface):
|
||||
"""
|
||||
Draw the info icons on a given surface.
|
||||
Args:
|
||||
surface (:obj:`pygame.Surface`): The surface to draw the text on
|
||||
"""
|
||||
# Blit the info onto the given surface.
|
||||
surface.blit(self.surface, (self.x, self.y))
|
46
pocket_friends/elements/surface.py
Normal file
46
pocket_friends/elements/surface.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Module to aid in the drawing of surfaces to make switching from one screen to another easier."""
|
||||
import pygame
|
||||
from ..io.input_handler import InputHandler
|
||||
|
||||
|
||||
class GameSurface(pygame.Surface):
|
||||
"""
|
||||
Class to be used as the backbone of all game surfaces.
|
||||
Attributes:
|
||||
running (bool): Boolean to tell whether the surface is running or not.
|
||||
next_surface (:obj:`str`): What the next surface should be after halting.
|
||||
resource_dir (:obj:`str`): The path of the game's main resource directory.
|
||||
game_fps (int): How many frames per second the game will run at.
|
||||
additional_args (dict): Additional arguments to send to the next surface after halting.
|
||||
"""
|
||||
def __init__(self, game_res, resources_dir, game_fps):
|
||||
"""
|
||||
Create a GameSurface object.
|
||||
Args:
|
||||
game_res (int): The internal resolution of the surface.
|
||||
resources_dir (:obj:`str`): The path of the game's main resource directory.
|
||||
game_fps: (int): How many frames per second the game will run at.
|
||||
"""
|
||||
super().__init__(game_res, pygame.SRCALPHA)
|
||||
self.running = True
|
||||
self.next_surface = None
|
||||
self.resource_dir = resources_dir
|
||||
self._clock = pygame.time.Clock()
|
||||
self.game_fps = game_fps
|
||||
self._input_handler = InputHandler(self._clock)
|
||||
self.additional_args = {}
|
||||
|
||||
self._bg = pygame.image.load(self.resource_dir + '/images/bg.png').convert_alpha()
|
||||
self.sprites = pygame.sprite.Group()
|
||||
|
||||
def preprocess(self):
|
||||
"""
|
||||
Advance the surface by one frame and draw the background.
|
||||
"""
|
||||
self._clock.tick(self.game_fps)
|
||||
|
||||
self.blit(self._bg, (0, 0))
|
||||
self.sprites.update()
|
||||
self.sprites.draw(self)
|
||||
|
||||
self._input_handler.update()
|
Reference in New Issue
Block a user