123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- # coding: utf-8
- import os
- import typing
-
- import time
-
- import pyglet
- from PIL import Image
- from synergine2.config import Config
- from synergine2.simulation import Subject
- from synergine2_cocos2d.actor import Actor
- from synergine2_xyz.exception import UnknownAnimationIndex
-
- from opencombat.exception import UnknownWeapon
- from opencombat.exception import WrongMode
- from opencombat.exception import UnknownFiringAnimation
- from opencombat.game.animation import ANIMATION_CRAWL
- from opencombat.game.animation import ANIMATION_WALK
- from opencombat.game.const import MODE_MAN_STAND_UP
- from opencombat.game.const import MODE_MAN_CRAWLING
- from opencombat.game.image import TileImageCacheManager
- from opencombat.game.weapon import RIFFLE
- from opencombat.game.weapon import WeaponImageApplier
- from opencombat.user_action import UserAction
-
- if typing.TYPE_CHECKING:
- from opencombat.game.fire import GuiFiringEvent
-
-
- MODE_DEFAULT = 'MODE_DEFAULT'
-
-
- class BaseActor(Actor):
- position_matching = {
- ANIMATION_WALK: MODE_MAN_STAND_UP,
- ANIMATION_CRAWL: MODE_MAN_CRAWLING,
- }
- mode_image_paths = {
- MODE_DEFAULT: 'unknown.png',
- }
- modes = [
- MODE_DEFAULT,
- ]
- weapons_firing_image_scheme = {}
- weapon_image_scheme = {}
- move_for_gui_actions = {}
-
- def __init__(
- self,
- image_path: str,
- config: Config,
- subject: Subject,
- ) -> None:
- self._mode = MODE_MAN_STAND_UP
- self.weapon_image_applier = WeaponImageApplier(config, self)
- self.firing_texture_cache = {} # type: typing.Dict[str, typing.Dict[str, typing.List[pyglet.image.AbstractImage]] # nopep8
- super().__init__(image_path, subject=subject, config=config)
-
- # Firing
- self.last_firing_time = 0
- self.firing_change_image_gap = 0.05 # seconds
-
- def get_image_cache_manager(self) -> TileImageCacheManager:
- return TileImageCacheManager(self, self.config)
-
- def get_default_mode(self) -> str:
- return MODE_DEFAULT
-
- def get_mode_image_path(self, mode: str) -> str:
- return self.mode_image_paths[mode]
-
- def get_modes(self) -> typing.List[str]:
- return self.modes
-
- @property
- def mode(self) -> str:
- return self._mode
-
- @mode.setter
- def mode(self, value) -> None:
- if value not in self.get_modes():
- raise WrongMode('Actor "{}" has no mode "{}" ({})'.format(
- self.__class__.__name__,
- value,
- ', '.join(self.get_modes()),
- ))
-
- self._mode = value
-
- def get_mode_for_gui_action(self, gui_action: str) -> str:
- try:
- return self.move_for_gui_actions[gui_action]
- except KeyError:
- return self.get_default_mode()
-
- @property
- def weapons(self) -> typing.List[str]:
- return []
-
- def build_textures_cache(self) -> None:
- super().build_textures_cache()
- self.build_firing_texture_cache()
-
- def get_default_appliable_images(self) -> typing.List[Image.Image]:
- if not self.weapons:
- return []
-
- return [
- self.weapon_image_applier.get_image_for_weapon(
- self.mode,
- # TODO BS 2018-02-08: Change this when weapon management enhanced
- self.weapons[0],
- )
- ]
-
- def can_rotate_instant(self) -> bool:
- return True
-
- def get_animation_appliable_images(
- self,
- animation_name: str,
- animation_position: int,
- ) -> typing.List[Image.Image]:
- if not self.weapons:
- return []
-
- position = self.position_matching[animation_name]
-
- try:
- return [
- self.weapon_image_applier.get_animation_image_for_weapon(
- position,
- self.weapons[0],
- animation_position,
- )
- ]
- except UnknownWeapon:
- return []
-
- def build_firing_texture_cache(self) -> None:
- cache_dir = self.config.resolve('global.cache_dir_path')
- for mode in self.get_modes():
- for weapon in self.weapons:
- firing_images = self.image_cache_manager.firing_cache.get_list(
- mode,
- weapon,
- )
- for i, firing_image in enumerate(firing_images):
- image_name = '{}_firing_{}_{}_{}.png'.format(
- str(self.subject.id),
- mode,
- weapon,
- i,
- )
- cache_image_path = os.path.join(cache_dir, image_name)
- firing_image.save(cache_image_path)
-
- self.firing_texture_cache\
- .setdefault(mode, {})\
- .setdefault(weapon, [])\
- .append(pyglet.image.load(cache_image_path))
-
- def firing(self, firing: 'GuiFiringEvent') -> None:
- # FIXME: move some code ?
- now = time.time()
- if now - self.last_firing_time >= self.firing_change_image_gap:
- self.last_firing_time = now
- firing.increment_animation_index()
-
- try:
- texture = self.firing_texture_cache\
- [self.mode]\
- [firing.weapon]\
- [firing.animation_index]
- except KeyError:
- self.logger.error(
- 'No firing animation for actor {}({}) for mode "{}"'
- ' and weapon "{}"'.format(
- self.__class__.__name__,
- str(self.subject.id),
- self.mode,
- firing.weapon,
- )
- )
- return # There is no firing animation defined
- except IndexError:
- texture = self.firing_texture_cache\
- [self.mode]\
- [firing.weapon]\
- [0]
- firing.reset_animation_index()
-
- self.update_image(texture)
-
-
- class Man(BaseActor):
- animation_image_paths = {
- ANIMATION_WALK: [
- 'actors/man.png',
- 'actors/man_w1.png',
- 'actors/man_w2.png',
- 'actors/man_w3.png',
- 'actors/man_w4.png',
- 'actors/man_w5.png',
- 'actors/man_w6.png',
- 'actors/man_w7.png',
- ],
- ANIMATION_CRAWL: [
- 'actors/man_c1.png',
- 'actors/man_c2.png',
- 'actors/man_c3.png',
- 'actors/man_c4.png',
- ]
- }
- modes = [
- MODE_MAN_STAND_UP,
- MODE_MAN_CRAWLING,
- ]
- mode_image_paths = {
- MODE_MAN_STAND_UP: 'actors/man.png',
- MODE_MAN_CRAWLING: 'actors/man_c1.png',
- }
- weapon_image_scheme = {
- MODE_MAN_STAND_UP: {
- RIFFLE: [
- 'actors/man_weap1.png'
- ],
- },
- MODE_MAN_CRAWLING: {
- RIFFLE: [
- 'actors/man_c1_weap1.png',
- 'actors/man_c2_weap1.png',
- 'actors/man_c3_weap1.png',
- 'actors/man_c4_weap1.png',
- ],
-
- }
- }
- weapons_firing_image_scheme = {
- MODE_MAN_STAND_UP: {
- RIFFLE: [
- 'actors/man_weap1_firing1.png',
- 'actors/man_weap1_firing2.png',
- 'actors/man_weap1_firing3.png',
- ],
- },
- MODE_MAN_CRAWLING: {
- RIFFLE: [
- 'actors/man_weap1_firing1.png',
- 'actors/man_weap1_firing2.png',
- 'actors/man_weap1_firing3.png',
- ]
- }
- }
- move_for_gui_actions = {
- UserAction.ORDER_MOVE: MODE_MAN_STAND_UP,
- UserAction.ORDER_MOVE_FAST: MODE_MAN_STAND_UP,
- UserAction.ORDER_MOVE_CRAWL: MODE_MAN_CRAWLING,
- }
-
- def __init__(
- self,
- config: Config,
- subject: Subject,
- ) -> None:
- super().__init__('actors/man.png', subject=subject, config=config)
-
- @property
- def weapons(self) -> typing.List[str]:
- # TODO BS 2018-01-26: Will be managed by complex part of code
- return [RIFFLE]
-
- def get_default_mode(self) -> str:
- return MODE_MAN_STAND_UP
-
-
- class HeavyVehicle(BaseActor):
- animation_image_paths = {
- ANIMATION_WALK: [
- 'actors/tank1.png',
- ],
- ANIMATION_CRAWL: [
- 'actors/tank1.png',
- ]
- }
- mode_image_paths = {
- MODE_DEFAULT: 'actors/tank1.png',
- }
-
- def __init__(
- self,
- config: Config,
- subject: Subject,
- ) -> None:
- super().__init__('actors/tank1.png', subject=subject, config=config)
-
- @property
- def weapons(self) -> typing.List[str]:
- # TODO BS 2018-01-26: Will be managed by complex part of code
- return [RIFFLE]
-
- def can_rotate_instant(self) -> bool:
- return False
|