actor.py 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. # coding: utf-8
  2. import io
  3. import os
  4. import typing
  5. import ntpath
  6. import pyglet
  7. import cocos
  8. from cocos import collision_model
  9. from cocos import euclid
  10. from synergine2.config import Config
  11. from synergine2.simulation import Subject
  12. from synergine2_cocos2d.animation import AnimatedInterface
  13. from synergine2_cocos2d.util import PathManager
  14. class Actor(AnimatedInterface, cocos.sprite.Sprite):
  15. animation_image_paths = {} # type: typing.Dict[str, typing.List[str]]
  16. def __init__(
  17. self,
  18. image_path: str,
  19. subject: Subject,
  20. position=(0, 0),
  21. rotation=0,
  22. scale=1,
  23. opacity=255,
  24. color=(255, 255, 255),
  25. anchor=None,
  26. properties: dict=None,
  27. config: Config=None,
  28. **kwargs
  29. ):
  30. # Note: Parameter required, but we want to modify little as possible parent init
  31. assert config, "Config is a required parameter"
  32. self.config = config
  33. self.path_manager = PathManager(config.resolve('global.include_path.graphics'))
  34. default_image_path = self.build_default_image(
  35. subject.id,
  36. self.path_manager.path(image_path),
  37. )
  38. image = pyglet.image.load(os.path.abspath(default_image_path))
  39. self.animation_images = {} # type: typing.Dict[str, typing.List[pyglet.image.TextureRegion]] # nopep8
  40. super().__init__(
  41. image,
  42. position,
  43. rotation,
  44. scale,
  45. opacity,
  46. color,
  47. anchor,
  48. **kwargs
  49. )
  50. self.subject = subject
  51. self.cshape = None # type: collision_model.AARectShape
  52. self.update_cshape()
  53. self.build_animation_images()
  54. self.current_image = image
  55. self.need_update_cshape = False
  56. self.properties = properties or {}
  57. self._freeze = False
  58. def build_default_image(self, subject_id: int, base_image_path: str) -> str:
  59. cache_dir = self.config.resolve('global.cache_dir_path')
  60. with open(base_image_path, 'rb') as base_image_file:
  61. final_name = '_'.join([
  62. str(subject_id),
  63. ntpath.basename(base_image_path),
  64. ])
  65. final_path = os.path.join(cache_dir, final_name)
  66. with open(final_path, 'wb+') as built_image_file:
  67. built_image_file.write(base_image_file.read())
  68. return final_path
  69. def freeze(self) -> None:
  70. """
  71. Set object to freeze mode: No visual modification can be done anymore
  72. """
  73. self._freeze = True
  74. def stop_actions(self, action_types: typing.Tuple[typing.Type[cocos.actions.Action], ...]) -> None:
  75. for action in self.actions:
  76. if isinstance(action, action_types):
  77. self.remove_action(action)
  78. def update_cshape(self) -> None:
  79. self.cshape = collision_model.AARectShape(
  80. euclid.Vector2(self.position[0], self.position[1]),
  81. self.width // 2,
  82. self.height // 2,
  83. )
  84. self.need_update_cshape = False
  85. def update_position(self, new_position: euclid.Vector2) -> None:
  86. if self._freeze:
  87. return
  88. self.position = new_position
  89. self.cshape.center = new_position # Note: if remove: strange behaviour: drag change actor position with anomaly
  90. def build_animation_images(self) -> None:
  91. """
  92. Fill self.animation_images with self.animation_image_paths
  93. :return: None
  94. """
  95. for animation_name, animation_image_paths in self.animation_image_paths.items():
  96. self.animation_images[animation_name] = []
  97. for animation_image_path in animation_image_paths:
  98. final_image_path = self.path_manager.path(animation_image_path)
  99. self.animation_images[animation_name].append(
  100. pyglet.resource.image(
  101. final_image_path,
  102. )
  103. )
  104. def get_images_for_animation(self, animation_name: str) -> typing.List[pyglet.image.TextureRegion]:
  105. return self.animation_images.get(animation_name)
  106. def get_inanimate_image(self) -> pyglet.image.TextureRegion:
  107. return self.current_image
  108. def update_image(self, new_image: pyglet.image.TextureRegion):
  109. if self._freeze:
  110. return
  111. self.image = new_image
  112. self.image_anchor = new_image.width // 2, new_image.height // 2