CrashOverrideX
Sealing v8.1 Subjectively Aware Standard for Hugging Face. Clean Model & Knowledge release.
a3e5f70
from settings import *
from random import uniform
from support import draw_bar
from timer import Timer
# overworld sprites
class Sprite(pygame.sprite.Sprite):
def __init__(self, pos, surf, groups, z = WORLD_LAYERS['main']):
super().__init__(groups)
self.image = surf
self.rect = self.image.get_frect(topleft = pos)
self.z = z
self.y_sort = self.rect.centery
self.hitbox = self.rect.copy()
class BorderSprite(Sprite):
def __init__(self, pos, surf, groups):
super().__init__(pos, surf, groups)
self.hitbox = self.rect.copy()
class TransitionSprite(Sprite):
def __init__(self, pos, size, target, groups):
surf = pygame.Surface(size)
super().__init__(pos, surf, groups)
self.target = target
class CollidableSprite(Sprite):
def __init__(self, pos, surf, groups):
super().__init__(pos, surf, groups)
self.hitbox = self.rect.inflate(0, -self.rect.height * 0.6)
class MonsterPatchSprite(Sprite):
def __init__(self, pos, surf, groups, biome, monsters, level):
self.biome = biome
super().__init__(pos, surf, groups, WORLD_LAYERS['main' if biome != 'sand' else 'bg'])
self.y_sort -= 40
self.biome = biome
self.monsters = monsters.split(',')
self.level = level
class AnimatedSprite(Sprite):
def __init__(self, pos, frames, groups, z = WORLD_LAYERS['main']):
self.frame_index, self.frames = 0, frames
super().__init__(pos, frames[self.frame_index], groups, z)
def animate(self, dt):
self.frame_index += ANIMATION_SPEED * dt
self.image = self.frames[int(self.frame_index % len(self.frames))]
def update(self, dt):
self.animate(dt)
# battle sprites
class MonsterSprite(pygame.sprite.Sprite):
def __init__(self, pos, frames, groups, monster, index, pos_index, entity, apply_attack, create_monster):
# data
self.index = index
self.pos_index = pos_index
self.entity = entity
self.monster = monster
self.frame_index, self.frames, self.state = 0, frames, 'idle'
self.animation_speed = ANIMATION_SPEED + uniform(-1, 1)
self.z = BATTLE_LAYERS['monster']
self.highlight = False
self.target_sprite = None
self.current_attack = None
self.apply_attack = apply_attack
self.create_monster = create_monster
# sprite setup
super().__init__(groups)
self.image = self.frames[self.state][self.frame_index]
self.rect = self.image.get_frect(center = pos)
# timers
self.timers = {
'remove highlight': Timer(300, func = lambda: self.set_highlight(False)),
'kill': Timer(600, func = self.destroy)
}
def animate(self, dt):
self.frame_index += ANIMATION_SPEED * dt
if self.state == 'attack' and self.frame_index >= len(self.frames['attack']):
self.apply_attack(self.target_sprite, self.current_attack, self.monster.get_base_damage(self.current_attack))
self.state = 'idle'
self.adjusted_frame_index = int(self.frame_index % len(self.frames[self.state]))
self.image = self.frames[self.state][self.adjusted_frame_index]
if self.highlight:
white_surf = pygame.mask.from_surface(self.image).to_surface()
white_surf.set_colorkey('black')
self.image = white_surf
def set_highlight(self, value):
self.highlight = value
if value:
self.timers['remove highlight'].activate()
def activate_attack(self, target_sprite, attack):
self.state = 'attack'
self.frame_index = 0
self.target_sprite = target_sprite
self.current_attack = attack
self.monster.reduce_energy(attack)
def delayed_kill(self, new_monster):
if not self.timers['kill'].active:
self.next_monster_data = new_monster
self.timers['kill'].activate()
def destroy(self):
if self.next_monster_data:
self.create_monster(*self.next_monster_data)
self.kill()
def update(self, dt):
for timer in self.timers.values():
timer.update()
self.animate(dt)
self.monster.update(dt)
class MonsterOutlineSprite(pygame.sprite.Sprite):
def __init__(self, monster_sprite, groups, frames):
super().__init__(groups)
self.z = BATTLE_LAYERS['outline']
self.monster_sprite = monster_sprite
self.frames = frames
self.image = self.frames[self.monster_sprite.state][self.monster_sprite.frame_index]
self.rect = self.image.get_frect(center = self.monster_sprite.rect.center)
def update(self, _):
self.image = self.frames[self.monster_sprite.state][self.monster_sprite.adjusted_frame_index]
if not self.monster_sprite.groups():
self.kill()
class MonsterNameSprite(pygame.sprite.Sprite):
def __init__(self, pos, monster_sprite, groups, font):
super().__init__(groups)
self.monster_sprite = monster_sprite
self.z = BATTLE_LAYERS['name']
text_surf = font.render(monster_sprite.monster.name, False, COLORS['black'])
padding = 10
self.image = pygame.Surface((text_surf.get_width() + 2 * padding, text_surf.get_height() + 2 * padding))
self.image.fill(COLORS['white'])
self.image.blit(text_surf, (padding, padding))
self.rect = self.image.get_frect(midtop = pos)
def update(self, _):
if not self.monster_sprite.groups():
self.kill()
class MonsterLevelSprite(pygame.sprite.Sprite):
def __init__(self, entity, pos, monster_sprite, groups, font):
super().__init__(groups)
self.monster_sprite = monster_sprite
self.font = font
self.z = BATTLE_LAYERS['name']
self.image = pygame.Surface((60,26))
self.rect = self.image.get_frect(topleft = pos) if entity == 'player' else self.image.get_frect(topright = pos)
self.xp_rect = pygame.FRect(0,self.rect.height - 2,self.rect.width,2)
def update(self, _):
self.image.fill(COLORS['white'])
text_surf = self.font.render(f'Lvl {self.monster_sprite.monster.level}', False, COLORS['black'])
text_rect = text_surf.get_frect(center = (self.rect.width / 2, self.rect.height / 2))
self.image.blit(text_surf, text_rect)
draw_bar(self.image, self.xp_rect, self.monster_sprite.monster.xp, self.monster_sprite.monster.level_up, COLORS['black'], COLORS['white'], 0)
if not self.monster_sprite.groups():
self.kill()
class MonsterStatsSprite(pygame.sprite.Sprite):
def __init__(self, pos, monster_sprite, size, groups, font):
super().__init__(groups)
self.monster_sprite = monster_sprite
self.image = pygame.Surface(size)
self.rect = self.image.get_frect(midbottom = pos)
self.font = font
self.z = BATTLE_LAYERS['overlay']
def update(self, _):
self.image.fill(COLORS['white'])
for index, (value, max_value) in enumerate(self.monster_sprite.monster.get_info()):
color = (COLORS['red'], COLORS['blue'], COLORS['gray'])[index]
if index < 2: # health and energy
text_surf = self.font.render(f'{int(value)}/{max_value}', False, COLORS['black'])
text_rect = text_surf.get_frect(topleft = (self.rect.width * 0.05,index * self.rect.height / 2))
bar_rect = pygame.FRect(text_rect.bottomleft + vector(0,-2), (self.rect.width * 0.9, 4))
self.image.blit(text_surf, text_rect)
draw_bar(self.image, bar_rect, value, max_value, color, COLORS['black'], 2)
else: # initiative
init_rect = pygame.FRect((0, self.rect.height - 2), (self.rect.width, 2))
draw_bar(self.image, init_rect, value, max_value, color, COLORS['white'], 0)
if not self.monster_sprite.groups():
self.kill()
class AttackSprite(AnimatedSprite):
def __init__(self, pos, frames, groups):
super().__init__(pos, frames, groups, BATTLE_LAYERS['overlay'])
self.rect.center = pos
def animate(self, dt):
self.frame_index += ANIMATION_SPEED * dt
if self.frame_index < len(self.frames):
self.image = self.frames[int(self.frame_index)]
else:
self.kill()
def update(self, dt):
self.animate(dt)
class TimedSprite(Sprite):
def __init__(self, pos, surf, groups, duration):
super().__init__(pos, surf, groups, z = BATTLE_LAYERS['overlay'])
self.rect.center = pos
self.death_timer = Timer(duration, autostart = True, func = self.kill)
def update(self, _):
self.death_timer.update()