gui.py 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import cocos
  2. from cocos.actions import ScaleBy, Repeat, Reverse, RotateBy
  3. from cocos.director import director
  4. from cocos.layer import ScrollableLayer, Layer
  5. from cocos.sprite import Sprite
  6. from pyglet.window import key as wkey
  7. from random import randint
  8. from sandbox.life_game.simulation import CellDieEvent, Cell
  9. from sandbox.life_game.simulation import CellBornEvent
  10. from synergine2.gui import Gui
  11. from synergine2.terminals import TerminalPackage
  12. from synergine2.terminals import Terminal
  13. cell_scale = ScaleBy(1.1, duration=0.25)
  14. cell_rotate = RotateBy(360, duration=30)
  15. class GridManager(object):
  16. def __init__(
  17. self,
  18. layer: Layer,
  19. square_width: int,
  20. border: int=0,
  21. ):
  22. self.layer = layer
  23. self.square_width = square_width
  24. self.border = border
  25. @property
  26. def final_width(self):
  27. return self.square_width + self.border
  28. def scale_sprite(self, sprite: Sprite):
  29. sprite.scale_x = self.final_width / sprite.image.width
  30. sprite.scale_y = self.final_width / sprite.image.height
  31. def position_sprite(self, sprite: Sprite, grid_position):
  32. grid_x = grid_position[0]
  33. grid_y = grid_position[1]
  34. sprite.position = grid_x * self.final_width, grid_y * self.final_width
  35. def get_window_position(self, grid_position_x, grid_position_y):
  36. grid_x = grid_position_x
  37. grid_y = grid_position_y
  38. return grid_x * self.final_width, grid_y * self.final_width
  39. def get_grid_position(self, window_x, window_y, z=0) -> tuple:
  40. window_size = director.get_window_size()
  41. window_center_x = window_size[0] // 2
  42. window_center_y = window_size[1] // 2
  43. window_relative_x = window_x - window_center_x
  44. window_relative_y = window_y - window_center_y
  45. real_width = self.final_width * self.layer.scale
  46. return int(window_relative_x // real_width),\
  47. int(window_relative_y // real_width),\
  48. z
  49. class Cells(Layer):
  50. def __init__(self):
  51. super().__init__()
  52. self.cells = {}
  53. self.grid_manager = GridManager(self, 32, border=2)
  54. def born(self, grid_position):
  55. if grid_position in self.cells:
  56. return # cell can be added by gui
  57. cell = Sprite('resources/cells_l.png')
  58. cell.rotation = randint(0, 360)
  59. self.grid_manager.scale_sprite(cell)
  60. self.grid_manager.position_sprite(cell, grid_position)
  61. cell.do(Repeat(cell_scale + Reverse(cell_scale)))
  62. cell.do(Repeat(cell_rotate + Reverse(cell_rotate)))
  63. self.cells[grid_position] = cell
  64. self.add(cell)
  65. def die(self, grid_position):
  66. try:
  67. self.remove(self.cells[grid_position])
  68. del self.cells[grid_position]
  69. except KeyError:
  70. pass # Cell can be removed by gui
  71. class MainLayer(ScrollableLayer):
  72. is_event_handler = True
  73. def __init__(self):
  74. super().__init__()
  75. self.scroll_step = 100
  76. self.grid_manager = GridManager(self, 32, border=2)
  77. self.background = Sprite('resources/banner-1711735_640.jpg')
  78. self.background.position = 0, 0
  79. self.background.opacity = 70
  80. self.background.scale = 5
  81. self.add(self.background, z=1)
  82. self.cells = Cells()
  83. self.add(self.cells)
  84. self.cross = Sprite('resources/cross31x31.png')
  85. self.cross.position = 0, 0
  86. self.cross.opacity = 50
  87. self.add(self.cross)
  88. # Set scene center on center of screen
  89. window_size = director.get_window_size()
  90. self.position = window_size[0] // 2, window_size[1] // 2
  91. def on_key_press(self, key, modifiers):
  92. if key == wkey.LEFT:
  93. self.position = (self.position[0] + self.scroll_step, self.position[1])
  94. if key == wkey.RIGHT:
  95. self.position = (self.position[0] - self.scroll_step, self.position[1])
  96. if key == wkey.UP:
  97. self.position = (self.position[0], self.position[1] - self.scroll_step)
  98. if key == wkey.DOWN:
  99. self.position = (self.position[0], self.position[1] + self.scroll_step)
  100. if key == wkey.A:
  101. if self.scale >= 0.3:
  102. self.scale -= 0.2
  103. if key == wkey.Z:
  104. if self.scale <= 4:
  105. self.scale += 0.2
  106. def on_mouse_press(self, x, y, buttons, modifiers):
  107. x, y = director.get_virtual_coordinates(x, y)
  108. grid_position = self.grid_manager.get_grid_position(x, y)
  109. # TODO: Have to inject in simulation ...
  110. if self.cells.cells.get(grid_position):
  111. self.cells.die(grid_position)
  112. else:
  113. self.cells.born(grid_position)
  114. def on_mouse_motion(self, x, y, dx, dy):
  115. x, y = director.get_virtual_coordinates(x, y)
  116. grid_position = self.grid_manager.get_grid_position(x, y)
  117. window_position = self.grid_manager.get_window_position(grid_position[0], grid_position[1])
  118. self.cross.position = window_position
  119. class LifeGameGui(Gui):
  120. def __init__(
  121. self,
  122. terminal: Terminal,
  123. read_queue_interval: float = 1 / 60.0,
  124. ):
  125. super().__init__(terminal, read_queue_interval)
  126. self.main_layer = MainLayer()
  127. self.main_scene = cocos.scene.Scene(self.main_layer)
  128. self.positions = {}
  129. self.terminal.register_event_handler(CellDieEvent, self.on_cell_die)
  130. self.terminal.register_event_handler(CellBornEvent, self.on_cell_born)
  131. def get_main_scene(self):
  132. return self.main_scene
  133. def before_received(self, package: TerminalPackage):
  134. if package.subjects: # It's thirst package
  135. for subject in package.subjects:
  136. if isinstance(subject, Cell):
  137. self.positions[subject.id] = subject.position
  138. self.main_layer.cells.born(subject.position)
  139. def on_cell_die(self, event: CellDieEvent):
  140. self.main_layer.cells.die(self.positions[event.subject_id])
  141. def on_cell_born(self, event: CellBornEvent):
  142. # TODO: La position peut evoluer dans un autre programme
  143. # resoudre cette problematique de données subjects qui évolue
  144. subject = self.terminal.subjects.get(event.subject_id)
  145. self.positions[event.subject_id] = subject.position
  146. self.main_layer.cells.born(subject.position)