Browse Source

Look around mechanism

Bastien Sevajol 6 years ago
parent
commit
6525d86f07

+ 2 - 0
sandbox/tile/const.py View File

6
 FLAG_DE = 'DE'
6
 FLAG_DE = 'DE'
7
 FLAG_URSS = 'URSS'
7
 FLAG_URSS = 'URSS'
8
 
8
 
9
+SIDE = 'SIDE'
10
+
9
 DE_COLOR = (0, 81, 211)
11
 DE_COLOR = (0, 81, 211)
10
 URSS_COLOR = (204, 0, 0)
12
 URSS_COLOR = (204, 0, 0)

+ 50 - 10
sandbox/tile/gui/base.py View File

1
 # coding: utf-8
1
 # coding: utf-8
2
+import typing
2
 
3
 
3
 from pyglet.window import key
4
 from pyglet.window import key
4
 
5
 
5
 from cocos.actions import MoveTo as BaseMoveTo
6
 from cocos.actions import MoveTo as BaseMoveTo
6
-from sandbox.tile.simulation.physics import TilePhysics
7
 from sandbox.tile.user_action import UserAction
7
 from sandbox.tile.user_action import UserAction
8
 from synergine2.config import Config
8
 from synergine2.config import Config
9
 from synergine2.log import SynergineLogger
9
 from synergine2.log import SynergineLogger
10
 from synergine2.terminals import Terminal
10
 from synergine2.terminals import Terminal
11
 from synergine2_cocos2d.actions import MoveTo
11
 from synergine2_cocos2d.actions import MoveTo
12
-# TODO NOW: MOVE
13
 from synergine2_cocos2d.animation import ANIMATION_CRAWL
12
 from synergine2_cocos2d.animation import ANIMATION_CRAWL
14
 from synergine2_cocos2d.animation import ANIMATION_WALK
13
 from synergine2_cocos2d.animation import ANIMATION_WALK
15
 from synergine2_cocos2d.animation import Animate
14
 from synergine2_cocos2d.animation import Animate
15
+from synergine2_cocos2d.gl import draw_line
16
 from synergine2_cocos2d.gui import EditLayer as BaseEditLayer
16
 from synergine2_cocos2d.gui import EditLayer as BaseEditLayer
17
 from synergine2_cocos2d.gui import TMXGui
17
 from synergine2_cocos2d.gui import TMXGui
18
 from synergine2_cocos2d.layer import LayerManager
18
 from synergine2_cocos2d.layer import LayerManager
19
 from synergine2_xyz.move.simulation import FinishMoveEvent
19
 from synergine2_xyz.move.simulation import FinishMoveEvent
20
 from synergine2_xyz.move.simulation import StartMoveEvent
20
 from synergine2_xyz.move.simulation import StartMoveEvent
21
-from synergine2_xyz.physics import Matrixes
21
+from synergine2_xyz.physics import Physics
22
 from synergine2_xyz.utils import get_angle
22
 from synergine2_xyz.utils import get_angle
23
+from sandbox.tile.simulation.event import NewVisibleOpponent
24
+from sandbox.tile.simulation.event import NoLongerVisibleOpponent
23
 
25
 
24
 
26
 
25
 class EditLayer(BaseEditLayer):
27
 class EditLayer(BaseEditLayer):
26
     def __init__(self, *args, **kwargs) -> None:
28
     def __init__(self, *args, **kwargs) -> None:
27
         super().__init__(*args, **kwargs)
29
         super().__init__(*args, **kwargs)
28
-        self.matrixes = Matrixes()
29
-        self.physics = TilePhysics(
30
-            self.config,
31
-            map_file_path='sandbox/tile/maps/003/003.tmx',  # FIXME: HARDCODED
32
-        )
33
 
30
 
34
     def _on_key_press(self, k, m):
31
     def _on_key_press(self, k, m):
35
         if self.selection:
32
         if self.selection:
55
         config: Config,
52
         config: Config,
56
         logger: SynergineLogger,
53
         logger: SynergineLogger,
57
         terminal: Terminal,
54
         terminal: Terminal,
55
+        physics: Physics,
58
         read_queue_interval: float = 1 / 60.0,
56
         read_queue_interval: float = 1 / 60.0,
59
         map_dir_path: str=None,
57
         map_dir_path: str=None,
60
     ):
58
     ):
62
             config,
60
             config,
63
             logger,
61
             logger,
64
             terminal,
62
             terminal,
65
-            read_queue_interval,
66
-            map_dir_path,
63
+            physics=physics,
64
+            read_queue_interval=read_queue_interval,
65
+            map_dir_path=map_dir_path,
67
         )
66
         )
68
 
67
 
69
         self.terminal.register_event_handler(
68
         self.terminal.register_event_handler(
76
             self.start_move_subject,
75
             self.start_move_subject,
77
         )
76
         )
78
 
77
 
78
+        self.terminal.register_event_handler(
79
+            NewVisibleOpponent,
80
+            self.new_visible_opponent,
81
+        )
82
+
83
+        self.terminal.register_event_handler(
84
+            NoLongerVisibleOpponent,
85
+            self.no_longer_visible_opponent,
86
+        )
87
+
79
         # configs
88
         # configs
80
         self.move_duration_ref = float(self.config.resolve('game.move.walk_ref_time'))
89
         self.move_duration_ref = float(self.config.resolve('game.move.walk_ref_time'))
81
         self.move_fast_duration_ref = float(self.config.resolve('game.move.run_ref_time'))
90
         self.move_fast_duration_ref = float(self.config.resolve('game.move.run_ref_time'))
122
         actor.do(move_action)
131
         actor.do(move_action)
123
         actor.do(Animate(animation, duration=move_duration, cycle_duration=cycle_duration))
132
         actor.do(Animate(animation, duration=move_duration, cycle_duration=cycle_duration))
124
         actor.rotation = get_angle(event.from_position, event.to_position)
133
         actor.rotation = get_angle(event.from_position, event.to_position)
134
+
135
+    def new_visible_opponent(self, event: NewVisibleOpponent):
136
+        self.visible_or_no_longer_visible_opponent(event, (153, 0, 153))
137
+
138
+    def no_longer_visible_opponent(self, event: NoLongerVisibleOpponent):
139
+        self.visible_or_no_longer_visible_opponent(event, (255, 102, 0))
140
+
141
+    def visible_or_no_longer_visible_opponent(
142
+        self,
143
+        event: typing.Union[NoLongerVisibleOpponent, NewVisibleOpponent],
144
+        line_color,
145
+    ) -> None:
146
+        if self.layer_manager.debug:
147
+            observer_actor = self.layer_manager.subject_layer.subjects_index[event.observer_subject_id]
148
+            observed_actor = self.layer_manager.subject_layer.subjects_index[event.observed_subject_id]
149
+
150
+            observer_pixel_position = self.layer_manager.grid_manager.get_pixel_position_of_grid_position(
151
+                observer_actor.subject.position,
152
+            )
153
+            observed_pixel_position = self.layer_manager.grid_manager.get_pixel_position_of_grid_position(
154
+                observed_actor.subject.position,
155
+            )
156
+
157
+            def draw_visible_opponent():
158
+                draw_line(
159
+                    observer_pixel_position,
160
+                    observed_pixel_position,
161
+                    line_color,
162
+                )
163
+
164
+            self.layer_manager.edit_layer.append_callback(draw_visible_opponent, 1.0)

+ 1 - 2
sandbox/tile/gui/fire.py View File

31
             obstacle_grid_position = self.layer_manager.edit_layer.physics.get_visibility_obstacle(
31
             obstacle_grid_position = self.layer_manager.edit_layer.physics.get_visibility_obstacle(
32
                 subject=actor.subject,
32
                 subject=actor.subject,
33
                 to_position=mouse_grid_position,
33
                 to_position=mouse_grid_position,
34
-                matrixes=self.layer_manager.edit_layer.matrixes,
35
                 matrix_name='visibility',
34
                 matrix_name='visibility',
36
                 opacity_property_name='opacity',
35
                 opacity_property_name='opacity',
37
             )
36
             )
38
 
37
 
39
             # DEBUG
38
             # DEBUG
40
             if self.layer_manager.debug:
39
             if self.layer_manager.debug:
41
-                grid_paths = self.layer_manager.edit_layer.matrixes.get_path_positions(
40
+                grid_paths = self.layer_manager.edit_layer.physics.matrixes.get_path_positions(
42
                     from_=actor_grid_position,
41
                     from_=actor_grid_position,
43
                     to=mouse_grid_position,
42
                     to=mouse_grid_position,
44
                 )
43
                 )

+ 13 - 11
sandbox/tile/run.py View File

5
 import logging
5
 import logging
6
 from random import seed
6
 from random import seed
7
 
7
 
8
-from sandbox.tile.const import FLAG
8
+synergine2_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../'))
9
+sys.path.append(synergine2_path)
10
+
11
+from sandbox.tile.const import FLAG, SIDE
9
 from sandbox.tile.const import FLAG_DE
12
 from sandbox.tile.const import FLAG_DE
10
 from sandbox.tile.const import DE_COLOR
13
 from sandbox.tile.const import DE_COLOR
11
 from sandbox.tile.const import URSS_COLOR
14
 from sandbox.tile.const import URSS_COLOR
12
 from sandbox.tile.const import FLAG_URSS
15
 from sandbox.tile.const import FLAG_URSS
13
 from synergine2_cocos2d.const import SELECTION_COLOR_RGB
16
 from synergine2_cocos2d.const import SELECTION_COLOR_RGB
14
-
15
-synergine2_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../'))
16
-sys.path.append(synergine2_path)
17
-
18
-from sandbox.tile.simulation.subject import Man
17
+from synergine2_cocos2d.util import get_map_file_path_from_dir
18
+from sandbox.tile.simulation.subject import TileSubject
19
 from sandbox.tile.simulation.base import TileStrategySimulation
19
 from sandbox.tile.simulation.base import TileStrategySimulation
20
 from sandbox.tile.simulation.base import TileStrategySubjects
20
 from sandbox.tile.simulation.base import TileStrategySubjects
21
 from synergine2.log import get_default_logger
21
 from synergine2.log import get_default_logger
33
     config.load_yaml('sandbox/tile/config.yaml')
33
     config.load_yaml('sandbox/tile/config.yaml')
34
     logger = get_default_logger(level=logging.ERROR)
34
     logger = get_default_logger(level=logging.ERROR)
35
 
35
 
36
-    map_file_path = 'sandbox/tile/{}.tmx'.format(os.path.join(map_dir_path, os.path.basename(map_dir_path)))
36
+    map_file_path = get_map_file_path_from_dir(map_dir_path)
37
 
37
 
38
     simulation = TileStrategySimulation(config, map_file_path=map_file_path)
38
     simulation = TileStrategySimulation(config, map_file_path=map_file_path)
39
     subjects = TileStrategySubjects(simulation=simulation)
39
     subjects = TileStrategySubjects(simulation=simulation)
40
 
40
 
41
-    for position in ((0, 2),):
42
-        man = Man(
41
+    for position in ((10, 2),):
42
+        man = TileSubject(
43
             config=config,
43
             config=config,
44
             simulation=simulation,
44
             simulation=simulation,
45
             position=position,
45
             position=position,
46
             properties={
46
             properties={
47
                 SELECTION_COLOR_RGB: DE_COLOR,
47
                 SELECTION_COLOR_RGB: DE_COLOR,
48
                 FLAG: FLAG_DE,
48
                 FLAG: FLAG_DE,
49
+                SIDE: 'AXIS',
49
             }
50
             }
50
         )
51
         )
51
         subjects.append(man)
52
         subjects.append(man)
52
 
53
 
53
-    for position in ((20, 10),):
54
-        man = Man(
54
+    for position in ((30, 14),):
55
+        man = TileSubject(
55
             config=config,
56
             config=config,
56
             simulation=simulation,
57
             simulation=simulation,
57
             position=position,
58
             position=position,
58
             properties={
59
             properties={
59
                 SELECTION_COLOR_RGB: URSS_COLOR,
60
                 SELECTION_COLOR_RGB: URSS_COLOR,
60
                 FLAG: FLAG_URSS,
61
                 FLAG: FLAG_URSS,
62
+                SIDE: 'ALLIES',
61
             }
63
             }
62
         )
64
         )
63
         subjects.append(man)
65
         subjects.append(man)

+ 53 - 0
sandbox/tile/simulation/behaviour.py View File

1
 # coding: utf-8
1
 # coding: utf-8
2
 import time
2
 import time
3
 
3
 
4
+from sandbox.tile.simulation.event import NoLongerVisibleOpponent
5
+from sandbox.tile.simulation.event import NewVisibleOpponent
6
+from sandbox.tile.simulation.mechanism import OpponentVisibleMechanism
4
 from sandbox.tile.user_action import UserAction
7
 from sandbox.tile.user_action import UserAction
5
 from synergine2.config import Config
8
 from synergine2.config import Config
6
 from synergine2.simulation import Simulation
9
 from synergine2.simulation import Simulation
10
+from synergine2.simulation import SubjectBehaviour
11
+from synergine2.simulation import Event
7
 from synergine2.simulation import Subject
12
 from synergine2.simulation import Subject
8
 from synergine2_xyz.move.simulation import MoveToBehaviour as BaseMoveToBehaviour
13
 from synergine2_xyz.move.simulation import MoveToBehaviour as BaseMoveToBehaviour
9
 
14
 
27
             return time.time() - move_to_data['last_intention_time'] >= self._run_duration
32
             return time.time() - move_to_data['last_intention_time'] >= self._run_duration
28
         if move_to_data['gui_action'] == UserAction.ORDER_MOVE_CRAWL:
33
         if move_to_data['gui_action'] == UserAction.ORDER_MOVE_CRAWL:
29
             return time.time() - move_to_data['last_intention_time'] >= self._crawl_duration
34
             return time.time() - move_to_data['last_intention_time'] >= self._crawl_duration
35
+
36
+
37
+class LookAroundBehaviour(SubjectBehaviour):
38
+    """
39
+    Behaviour who permit to reference visible things like enemies
40
+    """
41
+    visible_mechanism = OpponentVisibleMechanism
42
+    use = [visible_mechanism]
43
+    force_action = True
44
+
45
+    def action(self, data) -> [Event]:
46
+        new_visible_subject_events = []
47
+        no_longer_visible_subject_events = []
48
+
49
+        for no_longer_visible_subject_id in data['no_longer_visible_subject_ids']:
50
+            no_longer_visible_subject_events.append(NoLongerVisibleOpponent(
51
+                observer_subject_id=self.subject.id,
52
+                observed_subject_id=no_longer_visible_subject_id,
53
+            ))
54
+            self.subject.visible_opponent_ids.remove(no_longer_visible_subject_id)
55
+
56
+        for new_visible_subject_id in data['new_visible_subject_ids']:
57
+            new_visible_subject_events.append(NewVisibleOpponent(
58
+                observer_subject_id=self.subject.id,
59
+                observed_subject_id=new_visible_subject_id,
60
+            ))
61
+            self.subject.visible_opponent_ids.append(new_visible_subject_id)
62
+
63
+        return new_visible_subject_events + no_longer_visible_subject_events
64
+
65
+    def run(self, data):
66
+        visible_subjects = data[self.visible_mechanism]['visible_subjects']
67
+        visible_subject_ids = [s.id for s in visible_subjects]
68
+        new_visible_subject_ids = []
69
+        no_longer_visible_subject_ids = []
70
+
71
+        for subject_id in self.subject.visible_opponent_ids:
72
+            if subject_id not in visible_subject_ids:
73
+                no_longer_visible_subject_ids.append(subject_id)
74
+
75
+        for subject in visible_subjects:
76
+            if subject.id not in self.subject.visible_opponent_ids:
77
+                new_visible_subject_ids.append(subject.id)
78
+
79
+        return {
80
+            'new_visible_subject_ids': new_visible_subject_ids,
81
+            'no_longer_visible_subject_ids': no_longer_visible_subject_ids,
82
+        }

+ 25 - 0
sandbox/tile/simulation/event.py View File

1
+# coding: utf-8
2
+
3
+
4
+# TODO: Reprendre les events Move, pour les lister tous ici
5
+from synergine2.simulation import Event
6
+
7
+
8
+class NewVisibleOpponent(Event):
9
+    def __init__(
10
+        self,
11
+        observer_subject_id: int,
12
+        observed_subject_id: int,
13
+    ) -> None:
14
+        self.observer_subject_id = observer_subject_id
15
+        self.observed_subject_id = observed_subject_id
16
+
17
+
18
+class NoLongerVisibleOpponent(Event):
19
+    def __init__(
20
+        self,
21
+        observer_subject_id: int,
22
+        observed_subject_id: int,
23
+    ) -> None:
24
+        self.observer_subject_id = observer_subject_id
25
+        self.observed_subject_id = observed_subject_id

+ 14 - 0
sandbox/tile/simulation/mechanism.py View File

1
+# coding: utf-8
2
+import typing
3
+
4
+from sandbox.tile.const import SIDE
5
+from synergine2_xyz.subjects import XYZSubject
6
+from synergine2_xyz.visible.simulation import VisibleMechanism
7
+
8
+
9
+class OpponentVisibleMechanism(VisibleMechanism):
10
+    def reduce_subjects(self, subjects: typing.List[XYZSubject]) -> typing.Iterator[XYZSubject]:
11
+        def is_opponent(subject: XYZSubject) -> bool:
12
+            return self.subject.properties[SIDE] != subject.properties[SIDE]
13
+
14
+        return filter(is_opponent, subjects)

+ 11 - 6
sandbox/tile/simulation/physics.py View File

3
 
3
 
4
 from sandbox.tile.simulation.tmx import TileMap
4
 from sandbox.tile.simulation.tmx import TileMap
5
 from sandbox.tile.simulation.tmx import TerrainTile
5
 from sandbox.tile.simulation.tmx import TerrainTile
6
-from synergine2_xyz.physics import Matrixes
7
 from synergine2_xyz.physics import MoveCostComputer
6
 from synergine2_xyz.physics import MoveCostComputer
8
 from synergine2_xyz.physics import TMXPhysics
7
 from synergine2_xyz.physics import TMXPhysics
9
 from synergine2_xyz.subjects import XYZSubject
8
 from synergine2_xyz.subjects import XYZSubject
10
 
9
 
11
-if False:
10
+if typing.TYPE_CHECKING:
12
     from sandbox.tile.simulation.base import BaseSubject
11
     from sandbox.tile.simulation.base import BaseSubject
12
+    from sandbox.tile.simulation.subject import TileSubject
13
 
13
 
14
 
14
 
15
 class TileMoveCostComputer(MoveCostComputer):
15
 class TileMoveCostComputer(MoveCostComputer):
44
         self,
44
         self,
45
         subject: XYZSubject,
45
         subject: XYZSubject,
46
         to_position: typing.Tuple[int, int],
46
         to_position: typing.Tuple[int, int],
47
-        matrixes: Matrixes,
48
         matrix_name: str,
47
         matrix_name: str,
49
         opacity_property_name: str='opacity',
48
         opacity_property_name: str='opacity',
50
     ) -> typing.Union[None, typing.Tuple[int, int]]:
49
     ) -> typing.Union[None, typing.Tuple[int, int]]:
52
         Return grid position obstacle if any between given subject and given to_position
51
         Return grid position obstacle if any between given subject and given to_position
53
         :param subject: Subject observer
52
         :param subject: Subject observer
54
         :param to_position: position to observe
53
         :param to_position: position to observe
55
-        :param matrixes: Matrixes instance
56
         :param matrix_name: matrix name to use
54
         :param matrix_name: matrix name to use
57
         :param opacity_property_name: name of property containing opacity property
55
         :param opacity_property_name: name of property containing opacity property
58
         :return: obstacle grid position or None if not
56
         :return: obstacle grid position or None if not
59
         """
57
         """
60
         from_x, from_y = subject.position
58
         from_x, from_y = subject.position
61
-        path_positions = matrixes.get_path_positions(from_=(from_x, from_y), to=to_position)
62
-        path_opacities = matrixes.get_values_for_path(
59
+        path_positions = self.matrixes.get_path_positions(from_=(from_x, from_y), to=to_position)
60
+        path_opacities = self.matrixes.get_values_for_path(
63
             matrix_name,
61
             matrix_name,
64
             path_positions=path_positions,
62
             path_positions=path_positions,
65
             value_name=opacity_property_name,
63
             value_name=opacity_property_name,
73
                 return path_positions[i]
71
                 return path_positions[i]
74
 
72
 
75
         return None
73
         return None
74
+
75
+    def subject_see_subject(self, observer: 'TileSubject', observed: 'TileSubject') -> bool:
76
+        return not bool(self.get_visibility_obstacle(
77
+            observer,
78
+            observed.position,
79
+            matrix_name='visibility',
80
+        ))

+ 5 - 1
sandbox/tile/simulation/subject.py View File

2
 from sandbox.tile.const import COLLECTION_ALIVE
2
 from sandbox.tile.const import COLLECTION_ALIVE
3
 from sandbox.tile.simulation.base import BaseSubject
3
 from sandbox.tile.simulation.base import BaseSubject
4
 from sandbox.tile.simulation.behaviour import MoveToBehaviour
4
 from sandbox.tile.simulation.behaviour import MoveToBehaviour
5
+from sandbox.tile.simulation.behaviour import LookAroundBehaviour
6
+from synergine2.share import shared
5
 
7
 
6
 
8
 
7
-class Man(BaseSubject):
9
+class TileSubject(BaseSubject):
8
     start_collections = [
10
     start_collections = [
9
         COLLECTION_ALIVE,
11
         COLLECTION_ALIVE,
10
     ]
12
     ]
11
     behaviours_classes = [
13
     behaviours_classes = [
12
         MoveToBehaviour,
14
         MoveToBehaviour,
15
+        LookAroundBehaviour,
13
     ]
16
     ]
17
+    visible_opponent_ids = shared.create_self('visible_opponent_ids', lambda: [])
14
     # TODO: implement (copied from engulf)
18
     # TODO: implement (copied from engulf)
15
     # behaviour_selector_class = CellBehaviourSelector
19
     # behaviour_selector_class = CellBehaviourSelector

+ 13 - 1
sandbox/tile/terminal/base.py View File

1
 # coding: utf-8
1
 # coding: utf-8
2
-from sandbox.tile.simulation.subject import Man as ManSubject
2
+from sandbox.tile.simulation.event import NewVisibleOpponent
3
+from sandbox.tile.simulation.event import NoLongerVisibleOpponent
4
+from sandbox.tile.simulation.physics import TilePhysics
5
+from sandbox.tile.simulation.subject import TileSubject as ManSubject
3
 from sandbox.tile.gui.actor import Man as ManActor
6
 from sandbox.tile.gui.actor import Man as ManActor
4
 from synergine2_cocos2d.terminal import GameTerminal
7
 from synergine2_cocos2d.terminal import GameTerminal
8
+from synergine2_cocos2d.util import get_map_file_path_from_dir
5
 from synergine2_xyz.move.simulation import FinishMoveEvent
9
 from synergine2_xyz.move.simulation import FinishMoveEvent
6
 from synergine2_xyz.move.simulation import StartMoveEvent
10
 from synergine2_xyz.move.simulation import StartMoveEvent
7
 
11
 
10
     subscribed_events = [
14
     subscribed_events = [
11
         FinishMoveEvent,
15
         FinishMoveEvent,
12
         StartMoveEvent,
16
         StartMoveEvent,
17
+        NewVisibleOpponent,
18
+        NoLongerVisibleOpponent,
13
     ]
19
     ]
14
 
20
 
15
     def __init__(self, *args, asynchronous: bool, map_dir_path: str, **kwargs):
21
     def __init__(self, *args, asynchronous: bool, map_dir_path: str, **kwargs):
16
         super().__init__(*args, **kwargs)
22
         super().__init__(*args, **kwargs)
17
         self.asynchronous = asynchronous
23
         self.asynchronous = asynchronous
24
+        map_file_path = get_map_file_path_from_dir(map_dir_path)
25
+        self.physics = TilePhysics(
26
+            self.config,
27
+            map_file_path=map_file_path,
28
+        )
18
         self.map_dir_path = map_dir_path
29
         self.map_dir_path = map_dir_path
19
 
30
 
20
     def run(self):
31
     def run(self):
25
             self.config,
36
             self.config,
26
             self.logger,
37
             self.logger,
27
             self,
38
             self,
39
+            physics=self.physics,
28
             map_dir_path=self.map_dir_path,
40
             map_dir_path=self.map_dir_path,
29
         )
41
         )
30
 
42
 

+ 4 - 0
synergine2/share.py View File

98
         super().append(p_object)
98
         super().append(p_object)
99
         self.shared.set(self.shared_data.get_final_key(self.instance), list(self))
99
         self.shared.set(self.shared_data.get_final_key(self.instance), list(self))
100
 
100
 
101
+    def remove(self, object_):
102
+        super().remove(object_)
103
+        self.shared.set(self.shared_data.get_final_key(self.instance), list(self))
104
+
101
     # TODO: Cover all methods
105
     # TODO: Cover all methods
102
 
106
 
103
 
107
 

+ 0 - 3
synergine2/simulation.py View File

275
 
275
 
276
 
276
 
277
 class Event(BaseObject):
277
 class Event(BaseObject):
278
-    def __init__(self, *args, **kwargs):
279
-        pass
280
-
281
     def repr_debug(self) -> str:
278
     def repr_debug(self) -> str:
282
         return self.__class__.__name__
279
         return self.__class__.__name__
283
 
280
 

+ 45 - 0
synergine2_cocos2d/gui.py View File

4
 from math import floor
4
 from math import floor
5
 
5
 
6
 import pyglet
6
 import pyglet
7
+import time
7
 from pyglet.window import mouse
8
 from pyglet.window import mouse
8
 
9
 
9
 import cocos
10
 import cocos
26
 from synergine2_cocos2d.middleware import MapMiddleware
27
 from synergine2_cocos2d.middleware import MapMiddleware
27
 from synergine2_cocos2d.middleware import TMXMiddleware
28
 from synergine2_cocos2d.middleware import TMXMiddleware
28
 from synergine2_cocos2d.user_action import UserAction
29
 from synergine2_cocos2d.user_action import UserAction
30
+from synergine2_xyz.physics import Physics
29
 from synergine2_xyz.xyz import XYZSubjectMixin
31
 from synergine2_xyz.xyz import XYZSubjectMixin
30
 
32
 
31
 
33
 
111
         self.vertexes = [(minx, miny), (minx, maxy), (maxx, maxy), (maxx, miny)]
113
         self.vertexes = [(minx, miny), (minx, maxy), (maxx, maxy), (maxx, miny)]
112
 
114
 
113
 
115
 
116
+class FinishedCallback(Exception):
117
+    pass
118
+
119
+
120
+class Callback(object):
121
+    def __init__(
122
+        self,
123
+        func: typing.Callable[[], None],
124
+        duration: float,
125
+    ) -> None:
126
+        self.func = func
127
+        self.duration = duration
128
+        # Started timestamp
129
+        self.started = None  # type: float
130
+
131
+    def execute(self) -> None:
132
+        if self.started is None:
133
+            self.started = time.time()
134
+
135
+        if time.time() - self.started < self.duration:
136
+            self.func()
137
+        else:
138
+            raise FinishedCallback()
139
+
140
+
114
 class EditLayer(cocos.layer.Layer):
141
 class EditLayer(cocos.layer.Layer):
115
     is_event_handler = True
142
     is_event_handler = True
116
 
143
 
201
 
228
 
202
         self.schedule(self.update)
229
         self.schedule(self.update)
203
         self.selectable_actors = []
230
         self.selectable_actors = []
231
+        # TODO: In top level class: to be available in all layers
232
+        self.callbacks = []  # type: typing.List[Callback]
233
+
234
+    def append_callback(self, callback: typing.Callable[[], None], duration: float) -> None:
235
+        self.callbacks.append(Callback(
236
+            callback,
237
+            duration,
238
+        ))
204
 
239
 
205
     def set_selectable(self, actor: Actor) -> None:
240
     def set_selectable(self, actor: Actor) -> None:
206
         self.selectable_actors.append(actor)
241
         self.selectable_actors.append(actor)
214
         self.draw_update_cshapes()
249
         self.draw_update_cshapes()
215
         self.draw_selection()
250
         self.draw_selection()
216
         self.draw_interactions()
251
         self.draw_interactions()
252
+        self.execute_callbacks()
253
+
254
+    def execute_callbacks(self) -> None:
255
+        for callback in self.callbacks[:]:
256
+            try:
257
+                callback.execute()
258
+            except FinishedCallback:
259
+                self.callbacks.remove(callback)
217
 
260
 
218
     def draw_update_cshapes(self) -> None:
261
     def draw_update_cshapes(self) -> None:
219
         for actor in self.selectable_actors:
262
         for actor in self.selectable_actors:
731
         config: Config,
774
         config: Config,
732
         logger: SynergineLogger,
775
         logger: SynergineLogger,
733
         terminal: Terminal,
776
         terminal: Terminal,
777
+        physics: Physics,
734
         read_queue_interval: float = 1 / 60.0,
778
         read_queue_interval: float = 1 / 60.0,
735
         map_dir_path: str=None,
779
         map_dir_path: str=None,
736
     ):
780
     ):
742
             terminal,
786
             terminal,
743
             read_queue_interval,
787
             read_queue_interval,
744
         )
788
         )
789
+        self.physics = physics
745
 
790
 
746
     def get_layer_middleware(self) -> MapMiddleware:
791
     def get_layer_middleware(self) -> MapMiddleware:
747
         return TMXMiddleware(
792
         return TMXMiddleware(

+ 1 - 1
synergine2_cocos2d/layer.py View File

50
 class SubjectLayer(cocos.layer.ScrollableLayer):
50
 class SubjectLayer(cocos.layer.ScrollableLayer):
51
     def __init__(self, parallax: int=1):
51
     def __init__(self, parallax: int=1):
52
         super().__init__(parallax)
52
         super().__init__(parallax)
53
-        self.subjects_index = {}
53
+        self.subjects_index = {}  # type: typing.Dict[int, Actor]
54
 
54
 
55
     def add_subject(self, actor: 'Actor') -> None:
55
     def add_subject(self, actor: 'Actor') -> None:
56
         self.add(actor)
56
         self.add(actor)

+ 7 - 0
synergine2_cocos2d/util.py View File

1
+# coding: utf-8
2
+import os
3
+
4
+
5
+def get_map_file_path_from_dir(map_dir_path: str) -> str:
6
+    # TODO: path is temp here
7
+    return 'sandbox/tile/{}.tmx'.format(os.path.join(map_dir_path, os.path.basename(map_dir_path)))

+ 1 - 1
synergine2_xyz/move/simulation.py View File

150
 
150
 
151
 
151
 
152
 class MoveToBehaviour(SubjectBehaviour):
152
 class MoveToBehaviour(SubjectBehaviour):
153
-    use = [MoveToMechanism]
154
     move_to_mechanism = MoveToMechanism
153
     move_to_mechanism = MoveToMechanism
154
+    use = [move_to_mechanism]
155
 
155
 
156
     def run(self, data):
156
     def run(self, data):
157
         move_to_data = data[self.move_to_mechanism]
157
         move_to_data = data[self.move_to_mechanism]

+ 7 - 2
synergine2_xyz/physics.py View File

6
 
6
 
7
 from synergine2.config import Config
7
 from synergine2.config import Config
8
 from synergine2.share import shared
8
 from synergine2.share import shared
9
-from synergine2_xyz.map import TMXMap, XYZTile
9
+from synergine2_xyz.map import TMXMap
10
+from synergine2_xyz.map import XYZTile
10
 from synergine2_xyz.subjects import XYZSubject
11
 from synergine2_xyz.subjects import XYZSubject
11
 from synergine2_xyz.tmx_utils import fill_matrix
12
 from synergine2_xyz.tmx_utils import fill_matrix
12
 from synergine2_xyz.utils import get_line_xy_path
13
 from synergine2_xyz.utils import get_line_xy_path
147
         self,
148
         self,
148
         config: Config,
149
         config: Config,
149
         map_file_path: str,
150
         map_file_path: str,
151
+        matrixes: Matrixes=None,
150
     ) -> None:
152
     ) -> None:
151
         super().__init__(config)
153
         super().__init__(config)
152
         self.map_file_path = map_file_path
154
         self.map_file_path = map_file_path
153
         self.tmx_map = self.tmx_map_class(map_file_path)
155
         self.tmx_map = self.tmx_map_class(map_file_path)
154
-        self.matrixes = Matrixes()
156
+        self.matrixes = matrixes or Matrixes()
155
 
157
 
156
     def load(self) -> None:
158
     def load(self) -> None:
157
         self.load_graph_from_map(self.map_file_path)
159
         self.load_graph_from_map(self.map_file_path)
190
                 value_structure=properties,
192
                 value_structure=properties,
191
             )
193
             )
192
             fill_matrix(self.tmx_map, self.matrixes, 'terrain', matrix_name, properties)
194
             fill_matrix(self.tmx_map, self.matrixes, 'terrain', matrix_name, properties)
195
+
196
+    def subject_see_subject(self, observer: XYZSubject, observed: XYZSubject) -> bool:
197
+        raise NotImplementedError()

+ 2 - 0
synergine2_xyz/simulation.py View File

21
     def create_physics(self) -> Physics:
21
     def create_physics(self) -> Physics:
22
         return Physics(self.config)
22
         return Physics(self.config)
23
 
23
 
24
+    # TODO: Move into physics
24
     def is_possible_subject_position(self, subject: XYZSubject, position: tuple) -> bool:
25
     def is_possible_subject_position(self, subject: XYZSubject, position: tuple) -> bool:
25
         return self.is_possible_position(position)
26
         return self.is_possible_position(position)
26
 
27
 
28
+    # TODO: Move into physics
27
     def is_possible_position(self, position: tuple) -> bool:
29
     def is_possible_position(self, position: tuple) -> bool:
28
         return True
30
         return True

+ 1 - 0
synergine2_xyz/visible/__init__.py View File

1
+# coding: utf-8

+ 32 - 0
synergine2_xyz/visible/simulation.py View File

1
+# coding: utf-8
2
+import typing
3
+
4
+from synergine2.config import Config
5
+from synergine2.simulation import SubjectMechanism, Simulation, Subject
6
+from synergine2_xyz.simulation import XYZSimulation
7
+from synergine2_xyz.subjects import XYZSubject
8
+
9
+
10
+class VisibleMechanism(SubjectMechanism):
11
+    def __init__(
12
+        self,
13
+        config: Config,
14
+        simulation: Simulation,
15
+        subject: Subject,
16
+    ) -> None:
17
+        super().__init__(config, simulation, subject)
18
+        self.simulation = typing.cast(XYZSimulation, self.simulation)
19
+        self.subject = typing.cast(XYZSubject, self.subject)
20
+
21
+    def reduce_subjects(self, subjects: typing.List[XYZSubject]) -> typing.Iterator[XYZSubject]:
22
+        return subjects
23
+
24
+    def is_visible(self, observed: XYZSubject) -> bool:
25
+        return self.simulation.physics.subject_see_subject(self.subject, observed)
26
+
27
+    def run(self) -> dict:
28
+        subjects_to_parse = self.reduce_subjects(self.simulation.subjects)
29
+        subjects_visible = list(filter(self.is_visible, subjects_to_parse))
30
+        return {
31
+            'visible_subjects': subjects_visible,
32
+        }