gameobj_factor.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. # Flexlay - A Generic 2D Game Editor
  2. # Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. from typing import Any, Callable, Optional, Type
  17. import os
  18. import logging
  19. from collections import OrderedDict
  20. from flexlay.object_brush import ObjectBrush
  21. from flexlay.util.config import Config
  22. from flexlay.math import Pointf
  23. from supertux.gameobj import GameObj
  24. from supertux.badguys import badguy_sprites
  25. from supertux.gameobjs import (
  26. AmbientSound,
  27. Background,
  28. BadGuy,
  29. BonusBlock,
  30. Camera,
  31. Candle,
  32. Climbable,
  33. Coin,
  34. DartTrap,
  35. Decal,
  36. Dispenser,
  37. Door,
  38. Flame,
  39. GhostFlame,
  40. Gradient,
  41. InfoBlock,
  42. InvisibleWall,
  43. LevelTime,
  44. ParticleSystem,
  45. Platform,
  46. Powerup,
  47. Pushbutton,
  48. ResetPoint,
  49. ScriptTrigger,
  50. ScriptedObject,
  51. SecretArea,
  52. SequenceTrigger,
  53. SimpleObject,
  54. SimpleTileObject,
  55. SpawnPoint,
  56. Switch,
  57. Torch,
  58. Trampoline,
  59. Tux,
  60. WeakBlock,
  61. WilloWisp,
  62. Wind,
  63. )
  64. from supertux.worldmap_object import (
  65. SpecialTile,
  66. WorldmapLevel,
  67. WorldmapSpawnpoint,
  68. )
  69. from supertux.sprite import SuperTuxSprite
  70. def format_sprite_name(name: str) -> str:
  71. """
  72. sprite_name -> Sprite Name
  73. """
  74. name = name.replace("_", " ")
  75. name = name.title()
  76. return name
  77. class SuperTuxGameObjFactory:
  78. """
  79. identifier: section in the .stl file, used for load and save, most of the time, also for Drag&drop
  80. sprite: used in the object selection and/or in the ObjMapSpriteObject
  81. functor: creates the object
  82. ObjectBrush(sprite, metadata)
  83. See editor/supertux-editor/LevelObjects/Objects.cs
  84. """
  85. def __init__(self) -> None:
  86. self.objects: OrderedDict[str, tuple[str, Callable[[], GameObj]]] = OrderedDict()
  87. # List of (identifier, image, tag)
  88. self.badguys: list[tuple[str, str, Optional[str]]] = []
  89. self.init_factories()
  90. def create_gameobj_at(self, identifier: str, pos: Pointf) -> Optional[GameObj]:
  91. data = self.objects.get(identifier)
  92. if data is None:
  93. logging.warning("couldn't create: %r at %s" % (identifier, pos))
  94. return None
  95. else:
  96. _, constructor = data
  97. obj: GameObj = constructor()
  98. assert obj.objmap_object is not None
  99. obj.objmap_object.pos = pos
  100. return obj
  101. def create_gameobj(self, identifier: str, sexpr: Any) -> Optional[GameObj]:
  102. data = self.objects.get(identifier)
  103. if data is None:
  104. logging.warning("couldn't create: %r" % identifier)
  105. return None
  106. else:
  107. _, constructor = data
  108. obj = constructor()
  109. obj.read(sexpr)
  110. obj.update()
  111. return obj
  112. def create_object_brushes(self) -> list[ObjectBrush]:
  113. """Creates Object Brushes for each sprite"""
  114. assert Config.current is not None
  115. # print("Creating object brushes...")
  116. brushes = []
  117. for identifier, (sprite_path, constructor) in self.objects.items():
  118. if sprite_path is not None:
  119. supertux_sprite = SuperTuxSprite.from_file(os.path.join(Config.current.datadir, sprite_path))
  120. assert supertux_sprite is not None
  121. sprite = supertux_sprite.get_sprite()
  122. assert sprite is not None
  123. brush = ObjectBrush(sprite, identifier)
  124. brushes.append(brush)
  125. return brushes
  126. def add_object(self, gameobj_class: Type[GameObj]) -> None:
  127. assert gameobj_class.identifier is not None
  128. self.objects[gameobj_class.identifier] = (gameobj_class.sprite, gameobj_class)
  129. def add_badguy(self, identifier: str, sprite_path: str, tag: Optional[str] = None) -> None:
  130. assert identifier not in self.objects, f"identifier already present: '{identifier}'"
  131. self.objects[identifier] = (sprite_path, lambda: BadGuy(identifier, sprite_path))
  132. if tag:
  133. self.badguys.append((identifier, sprite_path, tag))
  134. else:
  135. self.badguys.append((identifier, sprite_path, None))
  136. def add_simple_object(self, identifier: str, sprite: str) -> None:
  137. self.objects[identifier] = (sprite, lambda: SimpleObject(identifier, sprite))
  138. def add_simple_tile(self, identifier: str, sprite: str) -> None:
  139. self.objects[identifier] = (sprite, lambda: SimpleTileObject(identifier, sprite))
  140. def add_particle_system(self, identifier: str, sprite: str, kind: str) -> None:
  141. self.objects[identifier] = (sprite, lambda: ParticleSystem(kind, sprite))
  142. def init_factories(self) -> None:
  143. self.add_simple_object("point", "images/engine/editor/point.png")
  144. self.add_simple_object("rock", "images/tiles/blocks/block11.png")
  145. self.add_simple_object("heavycoin", "images/objects/coin/heavy_coin.png")
  146. self.add_simple_tile("unstable_tile", "images/objects/unstable_tile/crumbling-1.png")
  147. self.add_object(AmbientSound)
  148. self.add_object(Background)
  149. self.add_object(Camera)
  150. self.add_object(Coin)
  151. self.add_object(Decal)
  152. self.add_object(Dispenser)
  153. self.add_object(SequenceTrigger)
  154. self.add_object(ScriptTrigger)
  155. self.add_object(BonusBlock)
  156. self.add_object(Candle)
  157. self.add_object(DartTrap)
  158. self.add_object(Door)
  159. self.add_object(GhostFlame)
  160. self.add_object(Flame)
  161. self.add_object(Gradient)
  162. self.add_object(InfoBlock)
  163. self.add_object(InvisibleWall)
  164. self.add_object(LevelTime)
  165. self.add_object(Platform)
  166. self.add_object(Powerup)
  167. self.add_object(Pushbutton)
  168. self.add_object(ResetPoint)
  169. self.add_object(ScriptedObject)
  170. self.add_object(Climbable)
  171. self.add_object(SecretArea)
  172. self.add_object(SpawnPoint)
  173. self.add_object(Switch)
  174. self.add_object(Torch)
  175. self.add_object(Tux)
  176. self.add_object(Trampoline)
  177. self.add_object(WeakBlock)
  178. self.add_object(WilloWisp)
  179. self.add_object(Wind)
  180. self.add_object(WorldmapLevel)
  181. self.add_object(WorldmapSpawnpoint)
  182. self.add_object(SpecialTile)
  183. for identifier, sprite_path in badguy_sprites:
  184. self.add_badguy(identifier, sprite_path)
  185. self.add_particle_system("particles-clouds", "images/engine/editor/clouds.png", "clouds")
  186. self.add_particle_system("particles-rain", "images/engine/editor/rain.png", "rain")
  187. self.add_particle_system("particles-snow", "images/engine/editor/snow.png", "snow")
  188. supertux_gameobj_factory = SuperTuxGameObjFactory()
  189. # EOF #