-
Notifications
You must be signed in to change notification settings - Fork 0
/
Entity.py
155 lines (117 loc) · 5.35 KB
/
Entity.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import random
import pygame
from Label import Label
from Vector2D import Vector2D
from typing import Any
from Animation import Animation
from App import App
from EventHandler import EventHandler
from Screen import Screen
from Game import Game
import Scripts
class Entity(Label):
"""Базовый класс существа"""
max_exp, min_exp = 0, 0
"""Статы моба"""
health: int
isLiving: bool = True
STATE_NAMES: list[tuple[str, Any]] = None
"""все возможные имена состояний игрока и их значения по умолчанию (<имя>, <значение>)"""
states: dict[str, Any]
"""состояния игрока в JSON формате"""
currentAnimationState: str = "idling"
"""текущее состояние анимации игрока"""
animations: dict[str, Animation] = None
"""анимации, присущие каждому состоянию"""
animationFix: dict[str, tuple[float, float]]
"""Хранит поправки на координаты анимаций вида {'animationName1-animationName2' : (offsetX, offsetY)}"""
speedVector: Vector2D
"""Вектор скорости"""
app: App = None
damage_senders: set
def __init__(self, position, dims):
super().__init__(position, dims)
self.speedVector = Vector2D()
self.STATE_NAMES = [
("direction", "right"), # направление взгляда существа
]
self.states = {}
self.load_states_from_names()
self.animations = {}
self.animationFix = {}
self.app = EventHandler.DataStash.app
self.damage_senders = set()
self.health = Game.get_health_max(Game.Mob.healthBase, Game.EnvStats.get_any_attr())
self.max_health = self.health
def set_animation_state(self, state: str) -> None:
self.get_animation_by_current_state().reset()
# поправки в координатах между переходами
prev_state = self.get_animation_state()
if f"{prev_state}-{state}" in self.animationFix.keys():
offset = self.animationFix[f"{prev_state}-{state}"]
self.move(offset[0], offset[1])
elif f"{state}-{prev_state}" in self.animationFix.keys():
offset = self.animationFix[f"{state}-{prev_state}"]
self.move(-offset[0], -offset[1])
self.currentAnimationState = state
self.set_dims(self.get_animation_by_current_state().dims)
def get_animation_state(self) -> str:
return self.currentAnimationState
def get_animation_by_current_state(self) -> Animation:
return self.animations[self.currentAnimationState]
def get_animation_by_state(self, state) -> Animation:
return self.animations[state]
def set_image(self, image, transform=True) -> None:
if self.get_state_by_name("direction") == "left":
image = pygame.transform.flip(image, True, False)
super().set_image(image, transform)
def load_states_from_names(self):
"""Загружает в локальный атрибут states значения из STATE_NAMES"""
for name in self.STATE_NAMES:
self.states[name[0]] = name[1]
def get_state_by_name(self, name: str) -> Any:
"""Возвращает состояние из states по имени"""
if name not in self.states.keys():
raise ValueError(f"Нет состояния с именем {name}")
return self.states[name]
def set_state_by_name(self, name: str, state: Any) -> None:
self.states[name] = state
def extend_state_names(self, names: tuple[str, Any] | list[tuple[str, Any]]):
"""Добавляет в атрибут STATE_NAMES другие имена и их значения"""
if isinstance(names, tuple):
self.STATE_NAMES.append(names)
else:
self.STATE_NAMES.extend(names)
"""Перемещение моба"""
def move_by_vector(self):
dt = EventHandler.get_dt() / 1000
self.move(self.speedVector.x * dt, -self.speedVector.y * dt)
def render_image(self):
"""Устанавливает изображение"""
self.set_image(self.get_animation_by_current_state().next_sprite())
def update(self) -> None:
if self.out_of_screen():
self.kill()
def blit_image_by_health(self):
image = Scripts.blit_color_by_precent(self.get_image(), 1 - (self.health / self.max_health))
# костыль
if self.get_state_by_name("direction") == "left":
image = pygame.transform.flip(image, True, False)
self.set_image(image)
def out_of_screen(self):
return self.position[0] + self.dims[0] + 1 < 0
def get_exp(self):
return random.randint(self.min_exp, self.max_exp)
def damage(self, value):
"""Наносит урон"""
self.health -= value
if self.health <= 0:
self.death()
def death(self):
"""Вызывается при естесственной смерти"""
EventHandler.DataStash.player.add_exp(self.get_exp())
self.kill()
def damage_from(self, sender, damage):
if sender not in self.damage_senders:
self.damage(damage)
self.damage_senders.add(sender)