Browse Source

engulf: cel movement

Bastien Sevajol 7 years ago
parent
commit
814ddaf2dc

+ 6 - 0
requirements.txt View File

@@ -1,5 +1,11 @@
1
+appdirs==1.4.2
1 2
 cocos2d==0.6.4
3
+packaging==16.8
4
+pkg-resources==0.0.0
2 5
 py==1.4.31
3 6
 pyglet==1.2.4
7
+pymlconf==0.7.0
8
+pyparsing==2.1.10
4 9
 pytest==3.0.4
10
+PyYAML==3.12
5 11
 six==1.10.0

+ 60 - 1
sandbox/engulf/behaviour.py View File

@@ -1,8 +1,12 @@
1 1
 # coding: utf-8
2
+from random import randint
3
+
4
+from sandbox.engulf.const import COLLECTION_GRASS
2 5
 from synergine2.simulation import SubjectBehaviour, SimulationMechanism, SimulationBehaviour
3 6
 from synergine2.simulation import Event
4 7
 from synergine2.utils import ChunkManager
5
-from synergine2.xyz_utils import get_around_positions_of_positions
8
+from synergine2.xyz import ProximitySubjectMechanism
9
+from synergine2.xyz_utils import get_around_positions_of_positions, get_around_positions_of
6 10
 
7 11
 
8 12
 class GrassGrownUp(Event):
@@ -115,3 +119,58 @@ class GrassSpawnBehaviour(SimulationBehaviour):
115 119
                 ))
116 120
 
117 121
         return events
122
+
123
+
124
+class EatableDirectProximityMechanism(ProximitySubjectMechanism):
125
+    distance = 1.41  # distance when on angle
126
+    feel_collections = [COLLECTION_GRASS]
127
+
128
+
129
+class MoveTo(Event):
130
+    def __init__(self, subject_id: int, position: tuple, *args, **kwargs):
131
+        super().__init__(*args, **kwargs)
132
+        self.subject_id = subject_id
133
+        self.position = position
134
+
135
+    def repr_debug(self) -> str:
136
+        return '{}: subject_id:{}, position:{}'.format(
137
+            type(self).__name__,
138
+            self.subject_id,
139
+            self.position,
140
+        )
141
+
142
+
143
+class SearchFood(SubjectBehaviour):
144
+    """
145
+    Si une nourriture a une case de distance et cellule non rassasié, move dans sa direction.
146
+    """
147
+    use = [EatableDirectProximityMechanism]
148
+
149
+    def run(self, data):
150
+        pass
151
+
152
+
153
+class Eat(SubjectBehaviour):
154
+    """
155
+    Prduit un immobilisme si sur une case de nourriture, dans le cas ou la cellule n'est as rassasié.
156
+    """
157
+    def run(self, data):
158
+        pass
159
+
160
+
161
+class Explore(SubjectBehaviour):
162
+    """
163
+    Produit un mouvement au hasard (ou un immobilisme)
164
+    """
165
+    use = []
166
+
167
+    def action(self, data) -> [Event]:
168
+        position = self.get_random_around_position()
169
+        return [MoveTo(self.subject.id, position)]
170
+
171
+    def run(self, data):
172
+        return True  # for now, want move every time
173
+
174
+    def get_random_around_position(self):
175
+        around_positions = get_around_positions_of(self.subject.position)
176
+        return around_positions[randint(0, len(around_positions)-1)]

+ 4 - 0
sandbox/engulf/config.yaml View File

@@ -0,0 +1,4 @@
1
+core:
2
+    cycle_duration: 0.5
3
+terminals:
4
+    sync: True

+ 7 - 0
sandbox/engulf/const.py View File

@@ -0,0 +1,7 @@
1
+# coding: utf-8
2
+
3
+
4
+COLLECTION_CELL = 'CELL'
5
+COLLECTION_ALIVE = 'ALIVE'
6
+COLLECTION_EATABLE = 'EATABLE'
7
+COLLECTION_GRASS = 'GRASS'

+ 50 - 11
sandbox/engulf/gui.py View File

@@ -2,31 +2,58 @@
2 2
 from random import randint
3 3
 
4 4
 import cocos
5
+from cocos.actions import MoveTo, Repeat, ScaleBy, Reverse, RotateTo
5 6
 from cocos.sprite import Sprite
6
-from sandbox.engulf.behaviour import GrassGrownUp, GrassSpawn
7
+from sandbox.engulf.behaviour import GrassGrownUp, GrassSpawn, MoveTo as MoveToEvent
7 8
 from sandbox.engulf.subject import Cell, Grass
8 9
 from synergine2.terminals import TerminalPackage
9 10
 from synergine2_cocos2d.gui import Gui, GridLayerMixin
10 11
 from synergine2_cocos2d.gui import MainLayer as BaseMainLayer
11 12
 
13
+cell_scale = ScaleBy(1.1, duration=0.25)
14
+
12 15
 
13 16
 class CellsLayer(GridLayerMixin, BaseMainLayer):
14
-    def __init__(self, *args, **kwargs):
17
+    def __init__(self, game: 'Game', *args, **kwargs):
15 18
         super().__init__(*args, **kwargs)
16
-        self.cells = {}
19
+        self.game = game
20
+        self.cell_positions = {}
21
+        self.cell_ids = {}
22
+
23
+    @property
24
+    def move_duration(self):
25
+        return self.game.cycle_duration
26
+
27
+    @property
28
+    def fake_move_rotate_duration(self):
29
+        return self.move_duration / 3
17 30
 
18
-    def born(self, grid_position):
31
+    def born(self, subject_id: int, grid_position):
19 32
         cell = Sprite('resources/cell.png')
20 33
         cell.rotation = randint(0, 360)
21 34
         self.grid_manager.scale_sprite(cell)
22 35
         self.grid_manager.position_sprite(cell, grid_position)
23
-        self.cells[grid_position] = cell
36
+        self.cell_positions[grid_position] = cell
37
+        self.cell_ids[subject_id] = cell
38
+        cell.do(Repeat(cell_scale + Reverse(cell_scale)))
24 39
         self.add(cell)
25 40
 
41
+    def move(self, subject_id: int, position: tuple):
42
+        cell = self.cell_ids[subject_id]
43
+
44
+        window_position = self.grid_manager.get_window_position(position[0], position[1])
45
+        move_action = MoveTo(window_position, self.move_duration)
46
+
47
+        fake_rotate = RotateTo(randint(0, 360), self.fake_move_rotate_duration)
48
+
49
+        cell.do(move_action)
50
+        cell.do(fake_rotate)
51
+
26 52
 
27 53
 class GrassLayer(GridLayerMixin, BaseMainLayer):
28
-    def __init__(self, *args, **kwargs):
54
+    def __init__(self, game: 'Game', *args, **kwargs):
29 55
         super().__init__(*args, **kwargs)
56
+        self.game = game
30 57
         self.grasses = {}
31 58
 
32 59
     def born(self, subject_id, grid_position, opacity=100):
@@ -43,13 +70,14 @@ class GrassLayer(GridLayerMixin, BaseMainLayer):
43 70
 
44 71
 
45 72
 class MainLayer(GridLayerMixin, BaseMainLayer):
46
-    def __init__(self, terminal, *args, **kwargs):
73
+    def __init__(self, game: 'Game', terminal, *args, **kwargs):
47 74
         super().__init__(terminal, *args, **kwargs)
75
+        self.game = game
48 76
 
49
-        self.cells = CellsLayer(terminal=terminal)
77
+        self.cells = CellsLayer(game=game, terminal=terminal)
50 78
         self.add(self.cells)
51 79
 
52
-        self.grasses = GrassLayer(terminal=terminal)
80
+        self.grasses = GrassLayer(game=game, terminal=terminal)
53 81
         self.add(self.grasses)
54 82
 
55 83
 
@@ -57,9 +85,10 @@ class Game(Gui):
57 85
     def __init__(self, *args, **kwargs):
58 86
         super().__init__(*args, **kwargs)
59 87
 
60
-        self.main_layer = MainLayer(terminal=self.terminal)
88
+        self.main_layer = MainLayer(game=self, terminal=self.terminal)
61 89
         self.main_scene = cocos.scene.Scene(self.main_layer)
62 90
 
91
+        # Event registering
63 92
         self.terminal.register_event_handler(
64 93
             GrassGrownUp,
65 94
             self.on_grass_grown_up,
@@ -68,6 +97,10 @@ class Game(Gui):
68 97
             GrassSpawn,
69 98
             self.on_grass_spawn,
70 99
         )
100
+        self.terminal.register_event_handler(
101
+            MoveToEvent,
102
+            self.on_move_to,
103
+        )
71 104
 
72 105
     def get_main_scene(self):
73 106
         return self.main_scene
@@ -76,7 +109,7 @@ class Game(Gui):
76 109
         if package.subjects:  # It's thirst package
77 110
             for subject in package.subjects:
78 111
                 if isinstance(subject, Cell):
79
-                    self.main_layer.cells.born(subject.position)
112
+                    self.main_layer.cells.born(subject.id, subject.position)
80 113
                 if isinstance(subject, Grass):
81 114
                     self.main_layer.grasses.born(
82 115
                         subject.id,
@@ -96,3 +129,9 @@ class Game(Gui):
96 129
             event.subject_id,
97 130
             event.density,  # TODO: Recupe ces données depuis local plutôt que event ?
98 131
         )
132
+
133
+    def on_move_to(self, event: MoveToEvent):
134
+        self.main_layer.cells.move(
135
+            event.subject_id,
136
+            event.position,
137
+        )

+ 10 - 4
sandbox/engulf/run.py View File

@@ -27,11 +27,12 @@ synergine2_ath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__
27 27
 sys.path.append(synergine2_ath)
28 28
 
29 29
 from random import randint, seed
30
-from sandbox.engulf.behaviour import GrassGrownUp, GrassSpawn, GrassSpawnBehaviour
30
+from sandbox.engulf.behaviour import GrassGrownUp, GrassSpawn, GrassSpawnBehaviour, MoveTo
31 31
 
32 32
 from synergine2.config import Config
33 33
 from synergine2.log import get_default_logger
34
-from sandbox.engulf.subject import Cell, Grass, COLLECTION_GRASS
34
+from sandbox.engulf.subject import Cell, Grass
35
+from sandbox.engulf.const import COLLECTION_GRASS
35 36
 from synergine2.core import Core
36 37
 from synergine2.cycle import CycleManager
37 38
 from synergine2.terminals import TerminalManager, Terminal, TerminalPackage
@@ -50,11 +51,13 @@ class GameTerminal(Terminal):
50 51
     subscribed_events = [
51 52
         GrassGrownUp,
52 53
         GrassSpawn,
54
+        MoveTo,
53 55
     ]
54 56
 
55 57
     def __init__(self, *args, **kwargs):
56 58
         super().__init__(*args, **kwargs)
57 59
         self.gui = None
60
+        self.asynchronous = False  # TODO: config
58 61
 
59 62
     def receive(self, package: TerminalPackage):
60 63
         self.gui.before_received(package)
@@ -63,7 +66,7 @@ class GameTerminal(Terminal):
63 66
 
64 67
     def run(self):
65 68
         from sandbox.engulf import gui
66
-        self.gui = gui.Game(self)
69
+        self.gui = gui.Game(self.config, self.logger, self)
67 70
         self.gui.run()
68 71
 
69 72
 
@@ -145,6 +148,7 @@ def main():
145 148
     simulation.subjects = subjects
146 149
 
147 150
     config = Config()
151
+    config.load_files(['sandbox/engulf/config.yaml'])
148 152
     logger = get_default_logger(level=logging.DEBUG)
149 153
 
150 154
     core = Core(
@@ -160,10 +164,12 @@ def main():
160 164
             config=config,
161 165
             logger=logger,
162 166
             terminals=[GameTerminal(
167
+                config,
168
+                logger,
163 169
                 asynchronous=False,
164 170
             )]
165 171
         ),
166
-        cycles_per_seconds=1,
172
+        cycles_per_seconds=1/config.core.cycle_duration,
167 173
     )
168 174
     core.run()
169 175
 

+ 7 - 6
sandbox/engulf/subject.py View File

@@ -1,13 +1,9 @@
1 1
 # coding: utf-8
2
-from sandbox.engulf.behaviour import GrowUp
2
+from sandbox.engulf.behaviour import GrowUp, SearchFood, Eat, Explore
3
+from sandbox.engulf.const import COLLECTION_CELL, COLLECTION_ALIVE, COLLECTION_EATABLE, COLLECTION_GRASS
3 4
 from synergine2.simulation import Subject
4 5
 from synergine2.xyz import XYZSubjectMixin
5 6
 
6
-COLLECTION_CELL = 'CELL'
7
-COLLECTION_ALIVE = 'ALIVE'
8
-COLLECTION_EATABLE = 'EATABLE'
9
-COLLECTION_GRASS = 'GRASS'
10
-
11 7
 
12 8
 class Cell(XYZSubjectMixin, Subject):
13 9
     collections = [
@@ -15,6 +11,11 @@ class Cell(XYZSubjectMixin, Subject):
15 11
         COLLECTION_ALIVE,
16 12
         COLLECTION_EATABLE,
17 13
     ]
14
+    behaviours_classes = [
15
+        SearchFood,
16
+        Eat,
17
+        Explore,
18
+    ]
18 19
 
19 20
 
20 21
 class Grass(XYZSubjectMixin, Subject):

+ 5 - 1
sandbox/life_game/gui.py View File

@@ -9,6 +9,8 @@ from random import randint
9 9
 from sandbox.life_game.simulation import CellBornEvent
10 10
 from sandbox.life_game.simulation import CellDieEvent, Cell, InvertCellStateBehaviour, \
11 11
     EmptyPositionWithLotOfCellAroundEvent
12
+from synergine2.config import Config
13
+from synergine2.log import SynergineLogger
12 14
 from synergine2.terminals import Terminal
13 15
 from synergine2.terminals import TerminalPackage
14 16
 from synergine2_cocos2d.gui import Gui, GridLayerMixin, MainLayer as BaseMainLayer
@@ -100,10 +102,12 @@ class MainLayer(GridLayerMixin, BaseMainLayer):
100 102
 class LifeGameGui(Gui):
101 103
     def __init__(
102 104
             self,
105
+            config: Config,
106
+            logger: SynergineLogger,
103 107
             terminal: Terminal,
104 108
             read_queue_interval: float=1 / 60.0,
105 109
     ):
106
-        super().__init__(terminal, read_queue_interval)
110
+        super().__init__(config, logger, terminal, read_queue_interval)
107 111
 
108 112
         self.main_layer = MainLayer(terminal=self.terminal)
109 113
         self.main_scene = cocos.scene.Scene(self.main_layer)

+ 9 - 6
sandbox/life_game/run.py View File

@@ -34,8 +34,8 @@ class SimplePrintTerminal(Terminal):
34 34
         CellBornEvent,
35 35
     ]
36 36
 
37
-    def __init__(self):
38
-        super().__init__()
37
+    def __init__(self, *args, **kwargs):
38
+        super().__init__(*args, **kwargs)
39 39
         self._cycle_born_count = 0
40 40
         self._cycle_die_count = 0
41 41
         self.register_event_handler(CellDieEvent, self.record_die)
@@ -86,8 +86,8 @@ class CocosTerminal(Terminal):
86 86
         EmptyPositionWithLotOfCellAroundEvent,
87 87
     ]
88 88
 
89
-    def __init__(self):
90
-        super().__init__()
89
+    def __init__(self, *args, **kwargs):
90
+        super().__init__(*args, **kwargs)
91 91
         self.subjects = None
92 92
         self.gui = None
93 93
 
@@ -98,7 +98,7 @@ class CocosTerminal(Terminal):
98 98
 
99 99
     def run(self):
100 100
         from sandbox.life_game import gui
101
-        self.gui = gui.LifeGameGui(self)
101
+        self.gui = gui.LifeGameGui(self.config, self.logger, self)
102 102
         self.gui.run()
103 103
 
104 104
 
@@ -146,7 +146,10 @@ def main():
146 146
         terminal_manager=TerminalManager(
147 147
             config=config,
148 148
             logger=logger,
149
-            terminals=[CocosTerminal(), SimplePrintTerminal()]
149
+            terminals=[
150
+                CocosTerminal(config, logger),
151
+                SimplePrintTerminal(config, logger),
152
+            ]
150 153
         ),
151 154
     )
152 155
     core.run()

+ 2 - 1
synergine2/config.py View File

@@ -1,5 +1,6 @@
1 1
 # coding: utf-8
2
+from pymlconf import ConfigManager
2 3
 
3 4
 
4
-class Config(dict):
5
+class Config(ConfigManager):
5 6
     pass

+ 8 - 1
synergine2/terminals.py View File

@@ -59,7 +59,14 @@ class Terminal(object):
59 59
     # who are not instance of listed classes
60 60
     subscribed_events = [Event]
61 61
 
62
-    def __init__(self, asynchronous: bool=True):
62
+    def __init__(
63
+        self,
64
+        config: Config,
65
+        logger: SynergineLogger,
66
+        asynchronous: bool=True,
67
+    ):
68
+        self.config = config
69
+        self.logger = logger
63 70
         self._input_queue = None
64 71
         self._output_queue = None
65 72
         self._stop_required = False

+ 7 - 0
synergine2_cocos2d/gui.py View File

@@ -6,6 +6,8 @@ from cocos.director import director
6 6
 from cocos.layer import ScrollableLayer, Layer
7 7
 from cocos.sprite import Sprite
8 8
 
9
+from synergine2.config import Config
10
+from synergine2.log import SynergineLogger
9 11
 from synergine2.terminals import Terminal
10 12
 from synergine2.terminals import TerminalPackage
11 13
 
@@ -106,11 +108,16 @@ class MainLayer(ScrollableLayer):
106 108
 class Gui(object):
107 109
     def __init__(
108 110
             self,
111
+            config: Config,
112
+            logger: SynergineLogger,
109 113
             terminal: Terminal,
110 114
             read_queue_interval: float= 1/60.0,
111 115
     ):
116
+        self.config = config
117
+        self.logger = logger,
112 118
         self._read_queue_interval = read_queue_interval
113 119
         self.terminal = terminal
120
+        self.cycle_duration = self.config.core.cycle_duration
114 121
         cocos.director.director.init()
115 122
 
116 123
     def run(self):