Skip to content

Instantly share code, notes, and snippets.

@Mega-JC
Last active August 26, 2020 13:41
Show Gist options
  • Save Mega-JC/ed7d7039e8cd74da365031032db63ff7 to your computer and use it in GitHub Desktop.
Save Mega-JC/ed7d7039e8cd74da365031032db63ff7 to your computer and use it in GitHub Desktop.
import pygame
from pygame import Surface, Rect
pygame.init()
listtypes = set((list, tuple))
pygame_classes = set((Surface, Rect))
_text0 = "invalid Spritesheet coordinate: "
_text1 = ". Coordinates must be like this: (x, y, width, height)"
default_group_name = "group.000"
default_image_name = "sprite.000"
default_ss_name = "spritesheet.000"
def new_name(name, lead_zeros=3, from_zero=False): # Generates new names by incrementing them
if not name.isspace():
if name != "":
is_num = name.isnumeric()
if is_num:
name = "("+name+")"
num_found = True
end_num = ""
index = len(name)-1
while num_found and index >= 0:
if name[index].isnumeric() == False:
num_found = False
break
if int(name[index]) in range(10):
end_num = name[index] + end_num
index -= 1
else:
num_found = False
if end_num == "":
new_n = name+"."+"0"*(lead_zeros-1)+("0" if from_zero else "1")
if ("(" or ")") in new_n:
new_n = new_n.replace("(", "")
new_n = new_n.replace(")", "")
return new_n
else:
end_num = str(int(end_num)+1)
add_dot = "" if name[index] == "." else "."
new_end_num = add_dot+"0"*max(lead_zeros-len(end_num), 0) + str(int(end_num))
new_n = name[:index+1]+new_end_num
if ("(" or ")") in new_n:
new_n = new_n.replace("(", "")
new_n = new_n.replace(")", "")
return new_n
else:
return name
else:
return name
class Spritesheet():
__slots__ = "_name", "_path", "_colorkey", "_group_name", "_isalpha", "_sprite_coords", "_sprite_images", "_sheet", "_corner_colorkey", "_sheetsize"
def __init__(self, path, name=None, alpha=True, colorkey=None, _=True, _c__=1): # _c__ and _ should be ignored, they are used for copying
self._name = "spritesheet" if not name else name
if _c__:
self._path = path
self._colorkey = colorkey
self._group_name = default_group_name
self._isalpha = alpha
self._sprite_coords = {}
self._sprite_images = {}
if _:
self._config_sheet_1(path, alpha=alpha, colorkey=colorkey)
else:
self._sheet = None
self._corner_colorkey = None
self._colorkey = None
self._sheet = None
self._sheetsize = None
def _config_sheet_1(self, path, alpha=True, colorkey=None):
""" Do not use this method directly, it is neeeded to configure a spritesheet object"""
self._sheet = sheet = pygame.image.load(path)
self._corner_colorkey = self._sheet.get_at((0, 0))
if colorkey is not None:
if colorkey == -1:
sheet.set_colorkey(self._corner_colorkey)
self._colorkey = self._corner_colorkey
else:
sheet.set_colorkey(colorkey)
self._colorkey = colorkey
self._sheet.convert()
elif alpha:
self._sheet = sheet.convert_alpha()
self._sheetsize = sheet.get_size()
def _config_sheet_2(self, alt_sheet):
self._sheet = alt_sheet
def __rcv(self, spritesheet):
"""Do not use this method directly, it is needed for copying Spritesheets."""
sattr = self.__setattr__
s_gattr = spritesheet.__getattribute__
for key in self.__slots__:
v = s_gattr(key)
if v.__class__ in pygame_classes:
sattr(key, v.copy())
elif key == "_sprite_coords":
vd = {}
if v:
for key2 in v.keys():
vd[key2] = [v[key2][i][:] for i in range(len(v[key2]))]
sattr(key, vd)
elif key == "_sprite_images":
vd = {}
if v:
for key2 in v.keys():
vd[key2] = [v[key2][i].copy() for i in range(len(v[key2]))]
sattr(key, vd)
elif key != "_name":
sattr(key, v)
return self
def copy(self):
return Spritesheet(self._path, _c__=0).__rcv(self)
def rename(self, name):
if isinstance(name, str):
self._name = name
def get_name(self):
return self._name
@property
def name(self):
return self._name
def get_ss_colorkey(self):
self._colorkey = self._sheet.get_colorkey()
return self._colorkey
def set_ss_colorkey(self, colorkey):
if colorkey != None:
if colorkey == -1:
self._sheet.set_colorkey(self._corner_colorkey)
else:
self._sheet.set_colorkey(colorkey)
self._colorkey = self._sheet.get_colorkey()
def is_alpha(self):
return self._isalpha
def add_sprite_group_coords(self, group_name, coords=(), reverse=False):
"""add new coordinates to a sprite group. a new group is made if the given group name does not yet exist"""
if group_name in self._sprite_coords.keys():
coords = list(coords)
if reverse:
coords.reverse()
for i in range(len(coords)):
if type(coords[i]) == pygame.Rect:
coords[i] = (coords[i].left, coords[i].top, coords[i].width, coords[i].height)
elif type(coords[i]) not in listtypes or len(coords[i]) != 4:
p = pygame.error(_text0+str(coords[i])+_text1)
raise p
new_subsurface = self._sheet.subsurface
self._sprite_coords[group_name] += coords
self._sprite_images[group_name].extend([new_subsurface(coord) for coord in coords])
else:
self.add_sprite_group(group_name, coords, reverse=reverse)
def group_image_count(self, group_name):
if group_name in self._sprite_coords.keys():
return len(self._sprite_coords[group_name])
def add_sprite_group(self, group_name=None, coords=(), reverse=False):
if group_name is None:
group_name = self._group_name
ks = self._sprite_coords.keys()
if group_name in ks:
group_name = new_name(max(ks)) # this increments the default group_name by one
self._sprite_coords[group_name] = []
self._sprite_images[group_name] = []
self.add_sprite_group_coords(group_name, coords=coords, reverse=reverse)
return group_name
def reverse_sprite_group(self, group_name):
"""reverses the order of images."""
if group_name in self._sprite_coords.keys():
self._sprite_coords[group_name].reverse()
self._sprite_coords[group_name].reverse()
def delete_sprite_group(self, group_name):
"""Deletes a sprite group and all information related to it."""
if group_name in self._sprite_images.keys():
del self._sprite_coords[group_name]
del self._sprite_images[group_name]
#def _get_sprite(self, coord):
# img = pygame.Surface.subsurface(coord)
#
# #img.blit(self._sheet, (0,0), area=coord)
# if not self._isalpha:
# img.set_colorkey(self._colorkey)
# return img
def get_group_image(self, group_name, index, wrap_around=True):
"""Get a surface from a group."""
spr_coords = self._sprite_coords
spr_images = self._sprite_images
if group_name in spr_coords:
if wrap_around:
index %= len(spr_coords[group_name])
try:
return spr_images[group_name][int(index)]
except IndexError as i:
i.args = ("The given index is out of range for the selected group.",)
else:
err = KeyError("The name '"+str(group_name)+"' does not exist in this Spritesheet object.")
raise err
def get_group_coords(self, group_name=None):
"""Returns the dictionary maintaining the group subsurface areas of the spritesheet."""
if group_name is None:
return self._sprite_coords
else:
return self._sprite_coords[group_name][:]
def get_group_images(self, group_name=None):
"""Returns the dictionary maintaining the group subsurfaces of the spritesheet."""
if group_name is None:
return self._sprite_images
else:
return (img.copy() for img in self._sprite_images[group_name])
def get_sheet(self, copy=True):
"""get the underlying spritesheet surface as a copy()"""
if copy:
return self._sheet.copy()
return self._sheet
def __str__(self):
return '<(Spritesheet named "{0}", SHEETSIZE: {1}x{2}, GROUPS: {3})>'.format(self._name, self._sheetsize[0], self._sheetsize[1], list(self._sprite_coords.keys())).replace("[", "").replace("]", "")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment