CrashOverrideX
Sealing v8.1 Subjectively Aware Standard for Hugging Face. Clean Model & Knowledge release.
a3e5f70
from settings import *
from support import check_connections
from timer import Timer
from random import choice
from monster import Monster
class Entity(pygame.sprite.Sprite):
def __init__(self, pos, frames, groups, facing_direction):
super().__init__(groups)
self.z = WORLD_LAYERS['main']
# graphics
self.frame_index, self.frames = 0, frames
self.facing_direction = facing_direction
# movement
self.direction = vector()
self.speed = 250
self.blocked = False
# sprite setup
self.image = self.frames[self.get_state()][self.frame_index]
self.rect = self.image.get_frect(center = pos)
self.hitbox = self.rect.inflate(-self.rect.width / 2, -60)
self.y_sort = self.rect.centery
def animate(self, dt):
self.frame_index += ANIMATION_SPEED * dt
self.image = self.frames[self.get_state()][int(self.frame_index % len(self.frames[self.get_state()]))]
def get_state(self):
moving = bool(self.direction)
if moving:
if self.direction.x != 0:
self.facing_direction = 'right' if self.direction.x > 0 else 'left'
if self.direction.y != 0:
self.facing_direction = 'down' if self.direction.y > 0 else 'up'
return f"{self.facing_direction}{'' if moving else '_idle'}"
def change_facing_direction(self, target_pos):
relation = vector(target_pos) - vector(self.rect.center)
if abs(relation.y) < 30:
self.facing_direction = 'right' if relation.x > 0 else 'left'
else:
self.facing_direction = 'down' if relation.y > 0 else 'up'
def block(self):
self.blocked = True
self.direction = vector(0,0)
def unblock(self):
self.blocked = False
class Character(Entity):
def __init__(self, pos, frames, groups, facing_direction, character_data, player, create_dialog, collision_sprites, radius, nurse, notice_sound):
super().__init__(pos, frames, groups, facing_direction)
self.character_data = character_data
self.player = player
self.create_dialog = create_dialog
self.collision_rects = [sprite.rect for sprite in collision_sprites if sprite is not self]
self.nurse = nurse
self.monsters = {i: Monster(name, lvl) for i, (name, lvl) in character_data['monsters'].items()} if 'monsters' in character_data else None
# movement
self.has_moved = False
self.can_rotate = True
self.has_noticed = False
self.radius = int(radius)
self.view_directions = character_data['directions']
self.timers = {
'look around': Timer(1500, autostart = True, repeat = True, func = self.random_view_direction),
'notice': Timer(500, func = self.start_move)
}
self.notice_sound = notice_sound
def random_view_direction(self):
if self.can_rotate:
self.facing_direction = choice(self.view_directions)
def get_dialog(self):
return self.character_data['dialog'][f"{'defeated' if self.character_data['defeated'] else 'default'}"]
def raycast(self):
if check_connections(self.radius, self, self.player) and self.has_los() and not self.has_moved and not self.has_noticed:
self.player.block()
self.player.change_facing_direction(self.rect.center)
self.timers['notice'].activate()
self.can_rotate = False
self.has_noticed = True
self.player.noticed = True
self.notice_sound.play()
def has_los(self):
if vector(self.rect.center).distance_to(self.player.rect.center) < self.radius:
collisions = [bool(rect.clipline(self.rect.center, self.player.rect.center)) for rect in self.collision_rects]
return not any(collisions)
def start_move(self):
relation = (vector(self.player.rect.center) - vector(self.rect.center)).normalize()
self.direction = vector(round(relation.x), round(relation.y))
def move(self, dt):
if not self.has_moved and self.direction:
if not self.hitbox.inflate(10,10).colliderect(self.player.hitbox):
self.rect.center += self.direction * self.speed * dt
self.hitbox.center = self.rect.center
else:
self.direction = vector()
self.has_moved = True
self.create_dialog(self)
self.player.noticed = False
def update(self, dt):
for timer in self.timers.values():
timer.update()
self.animate(dt)
if self.character_data['look_around']:
self.raycast()
self.move(dt)
class Player(Entity):
def __init__(self, pos, frames, groups, facing_direction, collision_sprites):
super().__init__(pos, frames, groups, facing_direction)
self.collision_sprites = collision_sprites
self.noticed = False
def input(self):
keys = pygame.key.get_pressed()
input_vector = vector()
if keys[pygame.K_UP]:
input_vector.y -= 1
if keys[pygame.K_DOWN]:
input_vector.y += 1
if keys[pygame.K_LEFT]:
input_vector.x -= 1
if keys[pygame.K_RIGHT]:
input_vector.x += 1
self.direction = input_vector.normalize() if input_vector else input_vector
def move(self, dt):
self.rect.centerx += self.direction.x * self.speed * dt
self.hitbox.centerx = self.rect.centerx
self.collisions('horizontal')
self.rect.centery += self.direction.y * self.speed * dt
self.hitbox.centery = self.rect.centery
self.collisions('vertical')
def collisions(self, axis):
for sprite in self.collision_sprites:
if sprite.hitbox.colliderect(self.hitbox):
if axis == 'horizontal':
if self.direction.x > 0:
self.hitbox.right = sprite.hitbox.left
if self.direction.x < 0:
self.hitbox.left = sprite.hitbox.right
self.rect.centerx = self.hitbox.centerx
else:
if self.direction.y > 0:
self.hitbox.bottom = sprite.hitbox.top
if self.direction.y < 0:
self.hitbox.top = sprite.hitbox.bottom
self.rect.centery = self.hitbox.centery
def update(self, dt):
self.y_sort = self.rect.centery
if not self.blocked:
self.input()
self.move(dt)
self.animate(dt)