gui.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. # coding: utf-8
  2. import cocos
  3. from cocos.actions import ScaleBy, Repeat, Reverse, RotateBy
  4. from cocos.director import director
  5. from cocos.layer import ScrollableLayer, Layer
  6. from cocos.sprite import Sprite
  7. from pyglet.window import key as wkey
  8. from random import randint
  9. from sandbox.life_game.simulation import CellBornEvent
  10. from sandbox.life_game.simulation import CellDieEvent, Cell, InvertCellStateBehaviour, \
  11. EmptyPositionWithLotOfCellAroundEvent
  12. from synergine2.config import Config
  13. from synergine2.log import SynergineLogger
  14. from synergine2.terminals import Terminal
  15. from synergine2.terminals import TerminalPackage
  16. from synergine2_cocos2d.gui import Gui, GridLayerMixin, MainLayer as BaseMainLayer
  17. cell_scale = ScaleBy(1.1, duration=0.25)
  18. cell_rotate = RotateBy(360, duration=30)
  19. flash_flash = ScaleBy(8, duration=0.5)
  20. flash_rotate = RotateBy(360, duration=6)
  21. class Cells(GridLayerMixin, Layer):
  22. def __init__(self):
  23. super().__init__()
  24. self.cells = {}
  25. self.flashs = []
  26. def born(self, grid_position):
  27. if grid_position in self.cells:
  28. return # cell can be added by gui
  29. cell = Sprite('resources/cells_l.png')
  30. cell.rotation = randint(0, 360)
  31. self.grid_manager.scale_sprite(cell)
  32. self.grid_manager.position_sprite(cell, grid_position)
  33. cell.do(Repeat(cell_scale + Reverse(cell_scale)))
  34. cell.do(Repeat(cell_rotate + Reverse(cell_rotate)))
  35. self.cells[grid_position] = cell
  36. self.add(cell)
  37. def die(self, grid_position):
  38. try:
  39. self.remove(self.cells[grid_position])
  40. del self.cells[grid_position]
  41. except KeyError:
  42. pass # Cell can be removed by gui
  43. def flash(self, position):
  44. flash = Sprite('resources/flash.png')
  45. flash.opacity = 40
  46. flash.scale = 0.1
  47. flash.rotation = randint(0, 360)
  48. flash.do(flash_flash + Reverse(flash_flash))
  49. flash.do(Repeat(flash_rotate + Reverse(flash_rotate)))
  50. self.grid_manager.position_sprite(flash, position)
  51. self.flashs.append(flash)
  52. self.add(flash)
  53. class MainLayer(GridLayerMixin, BaseMainLayer):
  54. is_event_handler = True
  55. def __init__(self, *args, **kwargs):
  56. super().__init__(*args, **kwargs)
  57. self.background = Sprite('resources/banner-1711735_640.jpg')
  58. self.background.position = 0, 0
  59. self.background.opacity = 70
  60. self.background.scale = 5
  61. self.add(self.background, z=1)
  62. self.cells = Cells()
  63. self.add(self.cells)
  64. self.cross = Sprite('resources/cross31x31.png')
  65. self.cross.position = 0, 0
  66. self.cross.opacity = 50
  67. self.add(self.cross)
  68. # Set scene center on center of screen
  69. window_size = director.get_window_size()
  70. self.position = window_size[0] // 2, window_size[1] // 2
  71. def on_mouse_press(self, x, y, buttons, modifiers):
  72. x, y = director.get_virtual_coordinates(x, y)
  73. grid_position = self.grid_manager.get_grid_position(x, y)
  74. self.terminal.send(TerminalPackage(
  75. simulation_actions=[(InvertCellStateBehaviour, {'position': grid_position})],
  76. ))
  77. def on_mouse_motion(self, x, y, dx, dy):
  78. x, y = director.get_virtual_coordinates(x, y)
  79. grid_position = self.grid_manager.get_grid_position(x, y)
  80. window_position = self.grid_manager.get_window_position(grid_position[0], grid_position[1])
  81. self.cross.position = window_position
  82. class LifeGameGui(Gui):
  83. def __init__(
  84. self,
  85. config: Config,
  86. logger: SynergineLogger,
  87. terminal: Terminal,
  88. read_queue_interval: float=1 / 60.0,
  89. ):
  90. super().__init__(config, logger, terminal, read_queue_interval)
  91. self.main_layer = MainLayer(terminal=self.terminal)
  92. self.main_scene = cocos.scene.Scene(self.main_layer)
  93. self.positions = {}
  94. self.terminal.register_event_handler(CellDieEvent, self.on_cell_die)
  95. self.terminal.register_event_handler(CellBornEvent, self.on_cell_born)
  96. self.terminal.register_event_handler(
  97. EmptyPositionWithLotOfCellAroundEvent,
  98. self.on_empty_cell_with_lot_of_cell_around,
  99. )
  100. def get_main_scene(self):
  101. return self.main_scene
  102. def before_received(self, package: TerminalPackage):
  103. if package.subjects: # It's thirst package
  104. for subject in package.subjects:
  105. if isinstance(subject, Cell):
  106. self.positions[subject.id] = subject.position
  107. self.main_layer.cells.born(subject.position)
  108. for flash in self.main_layer.cells.flashs[:]:
  109. self.main_layer.cells.flashs.remove(flash)
  110. self.main_layer.cells.remove(flash)
  111. def on_cell_die(self, event: CellDieEvent):
  112. try:
  113. self.main_layer.cells.die(self.positions[event.subject_id])
  114. except KeyError:
  115. pass
  116. def on_cell_born(self, event: CellBornEvent):
  117. if event.subject_id not in self.terminal.subjects:
  118. return
  119. subject = self.terminal.subjects.get(event.subject_id)
  120. self.positions[event.subject_id] = subject.position
  121. self.main_layer.cells.born(subject.position)
  122. def on_empty_cell_with_lot_of_cell_around(self, event: EmptyPositionWithLotOfCellAroundEvent):
  123. self.main_layer.cells.flash(event.position)