-
Notifications
You must be signed in to change notification settings - Fork 0
/
actor.py
252 lines (201 loc) · 7.6 KB
/
actor.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# -*- coding: utf-8 -*-
__author__ = 'Ecialo'
from pyglet.event import EventDispatcher
from cocos import collision_model as cm
from cocos import euclid as eu
import Box2D as b2
import movable_object
from registry.metric import TILE_SIZE_IN_PIXELS
from registry.item import MAIN
from registry.box2d import *
from registry.metric import pixels_to_tiles
from registry.utility import EMPTY_LIST
import collides as coll
from inventory import Inventory
def animate(func):
def decorate(*args, **kwargs):
if args[0].state != func.__name__:
args[0].state = func.__name__
args[0].image = args[0].body.anim[func.__name__]
func(*args, **kwargs)
decorate.__name__ = func.__name__
return decorate
def activity(func):
def decorate(*args, **kwargs):
if args[0].state != func.__name__:
map(args[0].body.recalculate_body_part_position, args[0].body.parts_pos[func.__name__])
func(*args, **kwargs)
decorate.__name__ = func.__name__
return decorate
class Launcher(EventDispatcher):
def __init__(self, master):
EventDispatcher.__init__(self)
self.master = master
self.owner = master
def launch(self, missile):
self.dispatch_event('on_launch_missile', missile)
def destroy_missile(self, missile):
self.dispatch_event('on_remove_missile', missile)
Launcher.register_event_type('on_launch_missile')
Launcher.register_event_type('on_remove_missile')
class Actor(movable_object.Movable_Object):
is_event_handler = True
def __init__(self, body):
cshape = cm.AARectShape(eu.Vector2(0, 0), TILE_SIZE_IN_PIXELS/2, body.img.height/2)
super(Actor, self).__init__(body.img, cshape=cshape)
self.fight_group = -1
self.direction = 1
self.owner = self
self.body = body(self)
self.launcher = Launcher(self)
self.state = 'stand'
self.inventory = Inventory(self)
self.ground_count = 0
self.on_ground = False
self.recovery = 0.0 # Time before moment when acton can be controlled again
height = property(lambda self: self.body.img.height)
width = property(lambda self: self.body.img.width)
def setup_b2body(self):
super(Actor, self).setup_b2body()
pix_to_tile = pixels_to_tiles
rx, ry = pix_to_tile((self.cshape.rx, self.cshape.ry))
self.b2body.CreateFixture(b2.b2FixtureDef(shape=b2.b2PolygonShape(vertices=[(-rx, ry), (-rx, -ry+0.1),
(-rx+0.1, -ry), (rx-0.1, -ry),
(rx, -ry+0.1), (rx, ry)])))
self.b2body.fixtures[-1].filterData.categoryBits = B2SMTH | B2ACTOR
self.b2body.CreateFixture(b2.b2FixtureDef(shape=b2.b2EdgeShape(vertex1=(-rx, -ry), vertex2=(rx, -ry)),
isSensor=True))
self.b2body.fixtures[-1].filterData.categoryBits = B2GNDSENS
self.b2body.fixtures[-1].filterData.maskBits = B2LEVEL | B2ACTOR
self.world.addEventHandler(self.b2body.fixtures[-1], self.on_ground_begin, self.on_ground_end)
def use_item(self, item_type, trigger, args): # MAIN or SECONDARY
if item_type is MAIN:
item = self.inventory.main_item
else:
item = self.inventory.secondary_item
if not item:
return
if trigger and not item.on_use and item.available:
item.start_use(*args)
elif trigger and item.on_use and item.available:
item.continue_use(*args)
elif not trigger and item.on_use and item.available:
item.end_use(*args)
def start_interact_with_item(self, item):
if item and item.item_update:
self.schedule(item.item_update)
def stop_interact_with_item(self, item):
if item and item.item_update:
self.unschedule(item.item_update)
def collide(self, other):
other._collide_actor(self)
def _collide_actor(self, other):
coll.collide_actor_actor(self, other)
def _collide_hit_zone(self, other):
coll.collide_actor_hit_zone(self, other)
def _collide_slash(self, other):
coll.collide_actor_slash(self, other)
def activate_trigger(self, trigger):
self.dispatch_event('on_activate_trigger', trigger, self)
def put_item(self, item):
self.inventory.put_item(item)
def open(self):
self.inventory.open()
def close(self):
self.inventory.close()
def destroy(self):
"""
Remove Actor from level
"""
if self.fight_group > 0:
for armor in filter(lambda x: (x.attached is not None), self.body.body_parts):
armor.attached.drop()
self.fight_group = -1
self.remove_action(self.actions[0])
self.kill()
self.dispatch_event('on_death', self)
def transfer(self):
self.inventory.transfer()
super(Actor, self).transfer()
self.ground_count = 0
self.on_ground = True
#@activity
def move(self, horizontal_direction):
"""
Move Actor in horizontal_direction with his body speed
"""
if self.on_ground:
d = horizontal_direction * self.body.speed
self.b2body.linearVelocity.x = d
if self.direction != horizontal_direction:
self.turn()
@activity
def stand(self):
"""
Do not move Actor
"""
self.b2body.linearVelocity.x = 0
@activity
def sit(self):
self.b2body.linearVelocity.x = 0
def turn(self):
self.direction = -self.direction
self.body.turn()
def push(self, v):
self.b2body.linearVelocity += v
@activity
def jump(self):
"""
Actor jump with his body jump speed.
"""
if self.on_ground:
self.b2body.linearVelocity.y = 11 # TODO сделать по людски
def move_to(self, x, y):
"""
Place Actor to x, y.
"""
old = self.cshape.center.copy()
vec = eu.Vector2(int(x), int(y))
self.position = vec
self.cshape.center = vec
self.b2body.position = pixels_to_tiles((vec.x, vec.y))
#map(lambda hand: hand.attached_move(vec - old), self.hands)
def push_task(self, task):
self.actions[0].task_manager.push_task(task)
def push_inst_task(self, task):
self.actions[0].task_manager.push_instant_task(task)
def on_ground_begin(self, fixture):
self.ground_count += 1
self.on_ground = True
def on_ground_end(self, fixture):
self.ground_count -= 1
if self.ground_count == 0:
self.on_ground = False
def take_hit(self, hit):
"""
Check with every Body_Part is Hit hit or not.
"""
self.body.collide(hit)
def touches_point(self, x, y):
"""
Checks whether the point lies on the actor
"""
return self.cshape.touches_point(x, y)
def show_hitboxes(self):
"""
Show hitboxes of every Body_Part
"""
self.body.show_hitboxes()
def from_self_to_global(self, pos):
"""
Recalculate position from Actors base to Level base
"""
return pos + self.position
def from_global_to_self(self, pos):
"""
Recalculate position from Level base to Actors base
"""
return pos - self.position
Actor.register_event_type('on_activate_trigger')
Actor.register_event_type('on_take_damage')
Actor.register_event_type('on_death')