Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

362 lines
11KB

  1. '''
  2. Filename nodes.py
  3. Author: Bryan "ObsidianBlk" Miller
  4. Date Created: 8/1/2018
  5. Python Version: 3.7
  6. '''
  7. from .display import Display
  8. class NodeError(Exception):
  9. pass
  10. class Node:
  11. def __init__(self, name="Node", parent=None):
  12. self._parent = None
  13. self._name = name
  14. self._children = []
  15. if parent is not None:
  16. try:
  17. self.parent = parent
  18. except NodeError as e:
  19. raise e
  20. @property
  21. def parent(self):
  22. return self._parent
  23. @parent.setter
  24. def parent(self, new_parent):
  25. try:
  26. self.parent_to_node(new_parent)
  27. except NodeError as e:
  28. raise e
  29. @property
  30. def root(self):
  31. if self._parent is None:
  32. return self
  33. return self._parent.root
  34. @property
  35. def name(self):
  36. return self._name
  37. @name.setter
  38. def name(self, value):
  39. if self._parent is not None:
  40. if self._parent.get_node(value) is not None:
  41. raise NodeError("Parent already contains node named '{}'.".format(name))
  42. self._name = value
  43. @property
  44. def full_name(self):
  45. if self._parent is None:
  46. return self._name
  47. return self._parent.full_name + "." + self._name
  48. @property
  49. def child_count(self):
  50. return len(this._children)
  51. def parent_to_node(self, parent, allow_reparenting=False):
  52. if not isinstance(value, Node):
  53. raise NodeError("Node may only parent to another Node instance.")
  54. if self._parent is None or self._parent != parent:
  55. if self._parent is not None:
  56. if allow_Reparenting == False:
  57. raise NodeError("Node already assigned a parent Node.")
  58. if self._parent.remove_node(self) != self:
  59. raise NodeError("Failed to remove self from current parent.")
  60. try:
  61. parent.attach_node(self)
  62. except NodeError as e:
  63. raise e
  64. def attach_node(self, node, reparent=False, index=-1):
  65. if node.parent is not None:
  66. if node.parent == self:
  67. return # Nothing to do. Given node already parented to this node.
  68. if reparent == False:
  69. raise NodeError("Node already parented.")
  70. if node.parent.remove_node(node) != node:
  71. raise NodeError("Failed to remove given node from it's current parent.")
  72. if self.get_node(node.name) is not None:
  73. raise NodeError("Node with name '{}' already attached.".format(node.name))
  74. node._parent = self
  75. if index < 0 or index >= len(self._children):
  76. self._children.append(node)
  77. else:
  78. self._children.insert(index, node)
  79. def remove_node(self, node):
  80. if isinstance(node, (str, unicode)):
  81. n = self.get_node(node)
  82. if n is not None:
  83. try:
  84. return self.remove_node(n)
  85. except NodeError as e:
  86. raise e
  87. elif isinstance(node, Node):
  88. if node.parent != self:
  89. if node.parent == None:
  90. raise NodeError("Cannot remove an unparented node.")
  91. try:
  92. return node.parent.remove_node(node)
  93. except NodeError as e:
  94. raise e
  95. if node in self._children:
  96. self._children.remove(node)
  97. node._parent = None
  98. return node
  99. else:
  100. raise NodeError("Expected a Node instance or a string.")
  101. return None
  102. def get_node(self, name):
  103. if len(self._children) <= 0:
  104. return None
  105. subnames = name.split(".")
  106. for c in self._children:
  107. if c.name == subnames[0]:
  108. if len(subnames) > 1:
  109. return c.get_node(".".join(subnames[1:-1]))
  110. return c
  111. return None
  112. def _update(self, dt):
  113. if hasattr(self, "on_update"):
  114. self.on_update(dt)
  115. for c in self._children:
  116. c._update(dt)
  117. def _render(self, surface):
  118. for c in self._children:
  119. c._render(surface)
  120. class Node2D(Node):
  121. def __init__(self, name="Node2D", parent=None):
  122. try:
  123. Node.__init__(self, name, parent)
  124. except NodeError as e:
  125. raise e
  126. def _render(self, surface):
  127. Node._render(self, surface)
  128. if hasattr(self, "on_render"):
  129. self._ACTIVE_SURF = surface
  130. self.on_render()
  131. del self._ACTIVE_SURF
  132. def blit(self, img, pos=(0,0), rect=None):
  133. if not hasattr(self, "_ACTIVE_SURF"):
  134. return
  135. self._ACTIVE_SURF.blit(img, pos, rect)
  136. def fill(self, color):
  137. if not hasattr(self, "_ACTIVE_SURF"):
  138. return
  139. self._ACTIVE_SURF.fill(color)
  140. def draw_lines(points, color, thickness=1, closed=False):
  141. if not hasattr(self, "_ACTIVE_SURF"):
  142. return
  143. pygame.draw.lines(self._ACTIVE_SURF, color, closed, points, thickness)
  144. def draw_rect(rect, color, thinkness=1):
  145. if not hasattr(self, "_ACTIVE_SURF"):
  146. return
  147. pygame.draw.rect(self._ACTIVE_SURF, color, rect, thickness)
  148. def draw_ellipse(rect, color, thickness=1, fill_color=None):
  149. if not hasattr(self, "_ACTIVE_SURF"):
  150. return
  151. if fill_color is not None:
  152. pygame.draw.ellipse(self._ACTIVE_SURF, fill_color, rect)
  153. if thickness > 0:
  154. pygame.draw.ellipse(self._ACTIVE_SURF, color, rect, thickness)
  155. def draw_circle(pos, radius, color, thickness=1, fill_color=None):
  156. if not hasattr(self, "_ACTIVE_SURF"):
  157. return
  158. if fill_color is not None:
  159. pygame.draw.circle(self._ACTIVE_SURF, fill_color, pos, radius)
  160. if thickness > 0:
  161. pygame.draw.circle(self._ACTIVE_SURF, color, pos, radius, thickness)
  162. def draw_polygon(points, color, thickness=1, fill_color=None):
  163. if not hasattr(self, "_ACTIVE_SURF"):
  164. return
  165. if fill_color is not None:
  166. pygame.draw.polygon(self._ACTIVE_SURF, fill_color, points)
  167. if thickness >= 1:
  168. pygame.draw.polygon(self._ACTIVE_SURF, color, points, thickness)
  169. class NodeSurface(Node2D):
  170. def __init__(self, name="NodeSurface", parent=None):
  171. try:
  172. Node2D.__init__(self, name, parent)
  173. except NodeError as e:
  174. raise e
  175. self._offset = (0.0, 0.0)
  176. self._scale = (1.0, 1.0)
  177. self._keepAspectRatio = False
  178. self._surface = None
  179. self._tsurface = None
  180. self.set_surface()
  181. def _updateTransformSurface(self):
  182. if self._surface is None:
  183. return
  184. if self._scale[0] == 1.0 and self._scale[1] == 1.0:
  185. self._tsurface = None
  186. size = self._surface.get_size()
  187. nw = size[0] * self._scale[0]
  188. nh = 0
  189. if self._keepAspectRatio:
  190. nh = size[1] * self._scale[0]
  191. else:
  192. nh = size[1] * self._scale[1]
  193. self._tsurface = pygame.Surface((nw, nh), pygame.SRCALPHA, self._surface)
  194. @property
  195. def resolution(self):
  196. if self._surface is None:
  197. return (0,0)
  198. return self._surface.get_size()
  199. @resolution.setter
  200. def resolution(self, res):
  201. try:
  202. self.set_surface(res)
  203. except (TypeError, ValueError) as e:
  204. raise e
  205. @property
  206. def width(self):
  207. return self.resolution[0]
  208. @property
  209. def height(self):
  210. return self.resolution[1]
  211. @property
  212. def offset(self):
  213. return self._offset
  214. @offset.setter(self, offset):
  215. if not isinstance(offset, tuple):
  216. raise TypeError("Expected a tuple")
  217. if len(offset) != 2:
  218. raise ValueError("Expected tuple of length two.")
  219. if not isinstance(offset[0], (int, float)) or not isinstance(offset[1], (int, float)):
  220. raise TypeError("Expected number values.")
  221. self._offset = (float(offset[0]), float(offset[1]))
  222. @property
  223. def offset_x(self):
  224. return self._offset[0]
  225. @offset_x.setter
  226. def offset_x(self, x):
  227. if not isinstance(x, (int, float)):
  228. raise TypeError("Expected number value.")
  229. self._offset = (x, self._offset[1])
  230. @property
  231. def offset_y(self):
  232. return self._offset[1]
  233. @offset_y.setter
  234. def offset_y(self, y):
  235. if not isinstance(y, (int, float)):
  236. raise TypeError("Expected number value.")
  237. self._offset = (self._offset[0], y)
  238. @property
  239. def scale(self):
  240. return self._scale
  241. @scale.setter
  242. def scale(self, scale):
  243. if self._keepAspectRatio:
  244. if not isinstance(scale, (int, float)):
  245. raise TypeError("Expected number value.")
  246. self._scale = (scale, self._scale[1])
  247. else:
  248. if not isinstance(scale, tuple):
  249. raise TypeError("Expected a tuple")
  250. if len(scale) != 2:
  251. raise ValueError("Expected tuple of length two.")
  252. if not isinstance(scale[0], (int, float)) or not isinstance(scale[1], (int, float)):
  253. raise TypeError("Expected number values.")
  254. self._scale = scale
  255. self._updateTransformSurface()
  256. @property
  257. def keep_aspect_ratio(self):
  258. return self._keepAspectRatio
  259. @keep_aspect_ratio.setter
  260. def keep_aspect_ratio(self, keep):
  261. self._keepAspectRatio = (keep == True)
  262. self._updateTransformSurface()
  263. def scale_to(self, target_resolution):
  264. if self._surface is not None:
  265. size = self._surface.get_size()
  266. nscale = (float(size[0]) / float(target_resolution[0]), float(size[1]) / float(target_resolution[1]))
  267. self.scale = nscale
  268. def set_surface(self, resolution=None):
  269. dsurf = Display.surface
  270. if resolution is None:
  271. if dsurf is not None:
  272. self._surface = dsurf.convert_alpha()
  273. self._updateTransformSurface()
  274. else:
  275. if not isinstance(r, tuple):
  276. raise TypeError("Expected a tuple.")
  277. if len(r) != 2:
  278. raise ValueError("Expected a tuple of length two.")
  279. if not isinstance(r[0], int) or not isinstance(r[1], int):
  280. raise TypeError("Tuple expected to contain integers.")
  281. if dsurf is not None:
  282. self._surface = pygame.Surface(resolution, pygame.SRCALPHA, dsurf)
  283. else:
  284. self._surface = pygame.Surface(resolution, pygame.SRCALPHA)
  285. self._updateTransformSurface()
  286. def _render(self, surface):
  287. if self._surface is None:
  288. self.set_surface()
  289. if self._surface is not None:
  290. Node2D._render(self, self._surface)
  291. else:
  292. Node2D._render(self, surface)
  293. self._scale_and_blit(surface)
  294. def _scale_and_blit(self, dest):
  295. dsize = dest.get_size()
  296. pos = (int(self._offset[0]), int(self._offset[1]))
  297. src = self._surface
  298. if self._tsurface is not None:
  299. pygame.transform.scale(self._surface, self._tsurface.get_size(), self._tsurface)
  300. src = self._tsurface
  301. if ssize[0] == dsize[0] and ssize[1] == dsize[1]:
  302. dest.blit(src, pos)