-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathentity.py
144 lines (108 loc) · 4.5 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
'''
An 'entity' is any object that populates the game (AKA, the content).
The 'Entity' class takes an x/y position, it's graphic/symbol, and color
Method:
Entity.move(): Updates entity's x/y position with a new set of coordinates (called after a successful 'move' action)
'''
#_______________________________________________________________________// MODULES
from __future__ import annotations
import copy
from typing import (Optional, Tuple, Type, TypeVar, TYPE_CHECKING)
from render_order import RenderOrder
if TYPE_CHECKING:
from components.ai import BaseAI
from components.fighter import Fighter
from game_map import GameMap
#_______________________________________________________________________// DECLARATION
# The 'Troll' enemy
T = TypeVar("T", bound="Entity")
#_______________________________________________________________________// CLASSES
# The generic object that represents players, enemies, items, etc.
class Entity:
# Initialization
def __init__(
# Set initial values
self,
gamemap: Optional[GameMap] = None,
x: int = 0, # x/y - entity's position
y: int = 0,
char: str = "?", # char - its symbol/sprite
color: Tuple[int, int, int] = (255, 255, 255), # color - an RGB color value
name: str = "<Unnamed>", # name - references the entity
blocks_movement: bool = False, # Walkable or not (enemies aren't, items and NPCs are)
render_order: RenderOrder = RenderOrder.CORPSE # 'corpse' renders first, so its a good default
):
self.x = x
self.y = y
self.char = char
self.color = color
self.name = name
self.blocks_movement= blocks_movement
self.render_order = render_order
if gamemap:
# If a gamemap isn't provided now then it will be set later.
self.gamemap = gamemap
gamemap.entities.add(self)
def spawn(self: T, gamemap: GameMap, x: int, y:int) -> T:
'''
Spawns a copy of this entity instance at a given location.
'''
clone = copy.deepcopy(self)
clone.x = x
clone.y = y
clone.gamemap = gamemap
gamemap.entities.add(clone)
return clone
def place(self, x: int, y: int, gamemap: Optional[GameMap] = None) -> None:
'''
Place this entity at a new location (handles moving between GameMaps).
'''
self.x = x
self.y = y
if gamemap:
# If this entity has a GameMap associated with it:
if hasattr(self, "gamemap"):
self.gamemap.entites.remove(self)
self.gamemap = gamemap
gamemap.entities.add(self)
def move(self, dx: int, dy: int) -> None:
# Move the entity by a given amount
self.x += dx
self.y += dy
class Actor(Entity):
'''
Inherits all the properties/attributes/methods of the 'Entity' class.
'''
def __init__(
self,
*,
x: int = 0,
y: int = 0,
char: str = "?",
color: Tuple[int, int, int] = (255, 255, 255),
name: str = "<Unnamed>",
ai_cls: Type[BaseAI],
fighter: Fighter
):
# Calls the super class '__init__()' function (ie, the parent class / 'Entity' class __init__)
super().__init__(
x = x,
y = y,
char = char,
color = color,
name = name,
blocks_movement = True, # Always pass in 'True' (since all "actors" will block movement)
render_order = RenderOrder.ACTOR
)
# Assign components (each actor needs the ability to move around and deal/take damage)
self.ai: Optional[BaseAI] = ai_cls(self)
self.fighter = fighter
self.fighter.entity = self
@property
def is_alive(self) -> bool:
'''
Returns 'True' as long as this actor has an 'ai'.
- If the entity's '.die()' method gets called, its 'ai' is replaced with 'None', effectively removing its capacity to perform actions.
- Calling 'die(). on this entity will also set this property to return 'False'.
'''
return bool(self.ai)