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.

712 lines
23KB

  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. from .events import Events
  9. from .resource import ResourceManager
  10. import pygame
  11. class NodeError(Exception):
  12. pass
  13. class Node:
  14. def __init__(self, name="Node", parent=None):
  15. self._NODE_DATA={
  16. "parent":None,
  17. "name":name,
  18. "children":[],
  19. "resource":None
  20. }
  21. if parent is not None:
  22. try:
  23. self.parent = parent
  24. except NodeError as e:
  25. raise e
  26. @property
  27. def parent(self):
  28. return self._NODE_DATA["parent"]
  29. @parent.setter
  30. def parent(self, new_parent):
  31. try:
  32. self.parent_to_node(new_parent)
  33. except NodeError as e:
  34. raise e
  35. @property
  36. def root(self):
  37. if self.parent is None:
  38. return self
  39. return self.parent.root
  40. @property
  41. def name(self):
  42. return self._NODE_DATA["name"]
  43. @name.setter
  44. def name(self, value):
  45. if self.parent is not None:
  46. if self.parent.get_node(value) is not None:
  47. raise NodeError("Parent already contains node named '{}'.".format(name))
  48. self._NODE_DATA["name"] = value
  49. @property
  50. def full_name(self):
  51. if self.parent is None:
  52. return self.name
  53. return self.parent.full_name + "." + self.name
  54. @property
  55. def resource(self):
  56. if self._NODE_DATA["resource"] is None:
  57. # Only bother creating the instance if it's being asked for.
  58. # All ResourceManager instances access same data.
  59. self._NODE_DATA["resource"] = ResourceManager()
  60. return self._NODE_DATA["resource"]
  61. @property
  62. def child_count(self):
  63. return len(this._NODE_DATA["children"])
  64. def get_world_position(self):
  65. if self.parent is None:
  66. return (0,0)
  67. return self.parent.get_world_position()
  68. def parent_to_node(self, parent, allow_reparenting=False):
  69. if not isinstance(value, Node):
  70. raise NodeError("Node may only parent to another Node instance.")
  71. if self.parent is None or self.parent != parent:
  72. if self.parent is not None:
  73. if allow_Reparenting == False:
  74. raise NodeError("Node already assigned a parent Node.")
  75. if self.parent.remove_node(self) != self:
  76. raise NodeError("Failed to remove self from current parent.")
  77. try:
  78. parent.attach_node(self)
  79. except NodeError as e:
  80. raise e
  81. def attach_node(self, node, reparent=False, index=-1):
  82. if node.parent is not None:
  83. if node.parent == self:
  84. return # Nothing to do. Given node already parented to this node.
  85. if reparent == False:
  86. raise NodeError("Node already parented.")
  87. if node.parent.remove_node(node) != node:
  88. raise NodeError("Failed to remove given node from it's current parent.")
  89. if self.get_node(node.name) is not None:
  90. raise NodeError("Node with name '{}' already attached.".format(node.name))
  91. node._NODE_DATA["parent"] = self
  92. children = self._NODE_DATA["children"]
  93. if index < 0 or index >= len(children):
  94. children.append(node)
  95. else:
  96. children.insert(index, node)
  97. def remove_node(self, node):
  98. if isinstance(node, (str, unicode)):
  99. n = self.get_node(node)
  100. if n is not None:
  101. try:
  102. return self.remove_node(n)
  103. except NodeError as e:
  104. raise e
  105. elif isinstance(node, Node):
  106. if node.parent != self:
  107. if node.parent == None:
  108. raise NodeError("Cannot remove an unparented node.")
  109. try:
  110. return node.parent.remove_node(node)
  111. except NodeError as e:
  112. raise e
  113. if node in self._NODE_DATA["children"]:
  114. self._NODE_DATA["children"].remove(node)
  115. node._NODE_DATA["parent"] = None
  116. return node
  117. else:
  118. raise NodeError("Expected a Node instance or a string.")
  119. return None
  120. def get_node(self, name):
  121. if self.child_count <= 0:
  122. return None
  123. subnames = name.split(".")
  124. for c in self._NODE_DATA["children"]:
  125. if c.name == subnames[0]:
  126. if len(subnames) > 1:
  127. return c.get_node(".".join(subnames[1:-1]))
  128. return c
  129. return None
  130. def _update(self, dt):
  131. if hasattr(self, "on_update"):
  132. self.on_update(dt)
  133. for c in self._NODE_DATA["children"]:
  134. c._update(dt)
  135. def _render(self, surface):
  136. for c in self._NODE_DATA["children"]:
  137. c._render(surface)
  138. class Node2D(Node):
  139. def __init__(self, name="Node2D", parent=None):
  140. try:
  141. Node.__init__(self, name, parent)
  142. except NodeError as e:
  143. raise e
  144. self._NODE2D_DATA={
  145. "position":[0.0, 0.0]
  146. }
  147. @property
  148. def position(self):
  149. p = self._NODE2D_DATA["position"]
  150. return (p[0], p[1])
  151. @position.setter
  152. def position(self, pos):
  153. if not isinstance(pos, (list, tuple)):
  154. raise TypeError("Expected a list or tuple.")
  155. if len(pos) != 2:
  156. raise ValueError("Wrong number of values given.")
  157. try:
  158. self.position_x = pos[0]
  159. self.position_y = pos[1]
  160. except Exception as e:
  161. raise e
  162. @property
  163. def position_x(self):
  164. return self._NODE2D_DATA["position"][0]
  165. @position_x.setter
  166. def position_x(self, v):
  167. if not isinstance(v, (int, float)):
  168. raise TypeError("Excepted an number value.")
  169. self._NODE2D_DATA["position"][0] = float(v)
  170. @property
  171. def position_y(self):
  172. return self._NODE2D_DATA["position"][1]
  173. @position_y.setter
  174. def position_y(self, v):
  175. if not isinstance(v, (int, float)):
  176. raise TypeError("Excepted an number value.")
  177. self._NODE2D_DATA["position"][1] = float(v)
  178. def _callOnRender(self, surface):
  179. if hasattr(self, "on_render"):
  180. self._ACTIVE_SURF = surface
  181. self.on_render()
  182. del self._ACTIVE_SURF
  183. def get_world_position(self):
  184. pos = self.position
  185. if self.parent is None:
  186. return pos
  187. ppos = self.parent.get_world_position()
  188. return (pos[0] + ppos[0], pos[1] + ppos[1])
  189. def _render(self, surface):
  190. self._callOnRender(surface)
  191. Node._render(self, surface)
  192. def draw_image(self, img, pos=(0,0), rect=None):
  193. if not hasattr(self, "_ACTIVE_SURF"):
  194. return
  195. self._ACTIVE_SURF.blit(img, pos, rect)
  196. def fill(self, color):
  197. if not hasattr(self, "_ACTIVE_SURF"):
  198. return
  199. self._ACTIVE_SURF.fill(color)
  200. def draw_lines(self, points, color, thickness=1, closed=False):
  201. if not hasattr(self, "_ACTIVE_SURF"):
  202. return
  203. pygame.draw.lines(self._ACTIVE_SURF, color, closed, points, thickness)
  204. def draw_rect(self, rect, color, thickness=1):
  205. if not hasattr(self, "_ACTIVE_SURF"):
  206. return
  207. pygame.draw.rect(self._ACTIVE_SURF, color, rect, thickness)
  208. def draw_ellipse(self, rect, color, thickness=1, fill_color=None):
  209. if not hasattr(self, "_ACTIVE_SURF"):
  210. return
  211. if fill_color is not None:
  212. pygame.draw.ellipse(self._ACTIVE_SURF, fill_color, rect)
  213. if thickness > 0:
  214. pygame.draw.ellipse(self._ACTIVE_SURF, color, rect, thickness)
  215. def draw_circle(self, pos, radius, color, thickness=1, fill_color=None):
  216. if not hasattr(self, "_ACTIVE_SURF"):
  217. return
  218. if fill_color is not None:
  219. pygame.draw.circle(self._ACTIVE_SURF, fill_color, pos, radius)
  220. if thickness > 0:
  221. pygame.draw.circle(self._ACTIVE_SURF, color, pos, radius, thickness)
  222. def draw_polygon(self, points, color, thickness=1, fill_color=None):
  223. if not hasattr(self, "_ACTIVE_SURF"):
  224. return
  225. if fill_color is not None:
  226. pygame.draw.polygon(self._ACTIVE_SURF, fill_color, points)
  227. if thickness >= 1:
  228. pygame.draw.polygon(self._ACTIVE_SURF, color, points, thickness)
  229. class NodeSurface(Node2D):
  230. def __init__(self, name="NodeSurface", parent=None):
  231. try:
  232. Node2D.__init__(self, name, parent)
  233. except NodeError as e:
  234. raise e
  235. # TODO: Update this class to use the _NODE*_DATA={} structure.
  236. self._scale = (1.0, 1.0)
  237. self._scaleToDisplay = False
  238. self._scaleDirty = False
  239. self._keepAspectRatio = False
  240. self._alignCenter = False
  241. self._surface = None
  242. self._tsurface = None
  243. self.set_surface()
  244. def _updateTransformSurface(self):
  245. if self._surface is None:
  246. return
  247. self._scaleDirty = False
  248. if self._scaleToDisplay:
  249. dsize = Display.resolution
  250. ssize = self._surface.get_size()
  251. self._scale = (dsize[0] / ssize[0], dsize[1] / ssize[1])
  252. if self._keepAspectRatio:
  253. if self._scale[0] < self._scale[1]:
  254. self._scale = (self._scale[0], self._scale[0])
  255. else:
  256. self._scale = (self._scale[1], self._scale[1])
  257. if self._scale[0] == 1.0 and self._scale[1] == 1.0:
  258. self._tsurface = None
  259. return
  260. size = self._surface.get_size()
  261. nw = size[0] * self._scale[0]
  262. nh = 0
  263. if self._keepAspectRatio:
  264. nh = size[1] * self._scale[0]
  265. else:
  266. nh = size[1] * self._scale[1]
  267. self._tsurface = pygame.Surface((nw, nh), pygame.SRCALPHA, self._surface)
  268. self._tsurface.fill(pygame.Color(0,0,0,0))
  269. @property
  270. def resolution(self):
  271. if self._surface is None:
  272. return (0,0)
  273. return self._surface.get_size()
  274. @resolution.setter
  275. def resolution(self, res):
  276. try:
  277. self.set_surface(res)
  278. except (TypeError, ValueError) as e:
  279. raise e
  280. @property
  281. def width(self):
  282. return self.resolution[0]
  283. @property
  284. def height(self):
  285. return self.resolution[1]
  286. @property
  287. def scale(self):
  288. return self._scale
  289. @scale.setter
  290. def scale(self, scale):
  291. if self._keepAspectRatio:
  292. if not isinstance(scale, (int, float)):
  293. raise TypeError("Expected number value.")
  294. self._scale = (scale, self._scale[1])
  295. else:
  296. if not isinstance(scale, tuple):
  297. raise TypeError("Expected a tuple")
  298. if len(scale) != 2:
  299. raise ValueError("Expected tuple of length two.")
  300. if not isinstance(scale[0], (int, float)) or not isinstance(scale[1], (int, float)):
  301. raise TypeError("Expected number values.")
  302. self._scale = scale
  303. self._updateTransformSurface()
  304. @property
  305. def keep_aspect_ratio(self):
  306. return self._keepAspectRatio
  307. @keep_aspect_ratio.setter
  308. def keep_aspect_ratio(self, keep):
  309. self._keepAspectRatio = (keep == True)
  310. self._updateTransformSurface()
  311. @property
  312. def align_center(self):
  313. return self._alignCenter
  314. @align_center.setter
  315. def align_center(self, center):
  316. self._alignCenter = (center == True)
  317. @property
  318. def scale_to_display(self):
  319. return self._scaleToDisplay
  320. @scale_to_display.setter
  321. def scale_to_display(self, todisplay):
  322. if todisplay == True:
  323. self._scaleToDisplay = True
  324. Events.listen("VIDEORESIZE", self._OnVideoResize)
  325. else:
  326. self._scaleToDisplay = False
  327. Events.unlisten("VIDEORESIZE", self._OnVideoResize)
  328. self._updateTransformSurface()
  329. def scale_to(self, target_resolution):
  330. if self._surface is not None:
  331. size = self._surface.get_size()
  332. nscale = (float(size[0]) / float(target_resolution[0]), float(size[1]) / float(target_resolution[1]))
  333. self.scale = nscale
  334. def set_surface(self, resolution=None):
  335. dsurf = Display.surface
  336. if resolution is None:
  337. if dsurf is not None:
  338. self._surface = dsurf.convert_alpha()
  339. self._surface.fill(pygame.Color(0,0,0,0))
  340. self._updateTransformSurface()
  341. else:
  342. if not isinstance(resolution, tuple):
  343. raise TypeError("Expected a tuple.")
  344. if len(resolution) != 2:
  345. raise ValueError("Expected a tuple of length two.")
  346. if not isinstance(resolution[0], int) or not isinstance(resolution[1], int):
  347. raise TypeError("Tuple expected to contain integers.")
  348. if dsurf is not None:
  349. self._surface = pygame.Surface(resolution, pygame.SRCALPHA, dsurf)
  350. else:
  351. self._surface = pygame.Surface(resolution, pygame.SRCALPHA)
  352. self._surface.fill(pygame.Color(0,0,0,0))
  353. self._updateTransformSurface()
  354. def _render(self, surface):
  355. if self._surface is None:
  356. self.set_surface()
  357. if self._surface is not None:
  358. if self._scaleDirty:
  359. self._updateTransformSurface()
  360. Node2D._render(self, self._surface)
  361. else:
  362. Node2D._render(self, surface)
  363. self._scale_and_blit(surface)
  364. def _scale_and_blit(self, dest):
  365. dsize = dest.get_size()
  366. src = self._surface
  367. if self._tsurface is not None:
  368. pygame.transform.scale(self._surface, self._tsurface.get_size(), self._tsurface)
  369. src = self._tsurface
  370. ssize = src.get_size()
  371. posx = self.position_x
  372. posy = self.position_y
  373. if self._alignCenter:
  374. if dsize[0] > ssize[0]:
  375. posx += (dsize[0] - ssize[0]) * 0.5
  376. if dsize[1] > ssize[1]:
  377. posy += (dsize[1] - ssize[1]) * 0.5
  378. pos = (int(posx), int(posy))
  379. dest.blit(src, pos)
  380. def _OnVideoResize(self, event, data):
  381. if self._scaleToDisplay:
  382. self._scaleDirty = True
  383. class NodeSprite(Node2D):
  384. def __init__(self, name="NodeSprite", parent=None):
  385. try:
  386. Node2D.__init__(self, name, parent)
  387. except NodeError as e:
  388. raise e
  389. self._NODESPRITE_DATA={
  390. "rect":[0,0,0,0],
  391. "image":"",
  392. "scale":[1.0, 1.0],
  393. "surface":None
  394. }
  395. @property
  396. def image_width(self):
  397. if self._NODESPRITE_DATA["surface"] is None:
  398. return 0
  399. surf = self._NODESPRITE_DATA["surface"]()
  400. return surf.get_width()
  401. @property
  402. def image_height(self):
  403. if self._NODESPRITE_DATA["surface"] is None:
  404. return 0
  405. surf = self._NODESPRITE_DATA["surface"]()
  406. return surf.get_height()
  407. @property
  408. def sprite_width(self):
  409. return int(self.rect_width * self.scale_x)
  410. @property
  411. def sprite_height(self):
  412. return int(self.rect_height * self.scale_y)
  413. @property
  414. def rect(self):
  415. return (self._NODESPRITE_DATA["rect"][0],
  416. self._NODESPRITE_DATA["rect"][1],
  417. self._NODESPRITE_DATA["rect"][2],
  418. self._NODESPRITE_DATA["rect"][3])
  419. @rect.setter
  420. def rect(self, rect):
  421. if not isinstance(rect, (list, tuple)):
  422. raise TypeError("Expected a list or tuple.")
  423. if len(rect) != 4:
  424. raise ValueError("rect value contains wrong number of values.")
  425. try:
  426. self.rect_x = rect[0]
  427. self.rect_y = rect[1]
  428. self.rect_width = rect[2]
  429. self.rect_height = rect[3]
  430. except Exception as e:
  431. raise e
  432. @property
  433. def rect_x(self):
  434. return self._NODESPRITE_DATA["rect"][0]
  435. @rect_x.setter
  436. def rect_x(self, v):
  437. if not isinstance(v, int):
  438. raise TypeError("Expected integer value.")
  439. self._NODESPRITE_DATA["rect"][0] = v
  440. self._NODESPRITE_ValidateRect()
  441. @property
  442. def rect_y(self):
  443. return self._NODESPRITE_DATA["rect"][1]
  444. @rect_y.setter
  445. def rect_y(self, v):
  446. if not isinstance(v, int):
  447. raise TypeError("Expected integer value.")
  448. self._NODESPRITE_DATA["rect"][1] = v
  449. self._NODESPRITE_ValidateRect()
  450. @property
  451. def rect_width(self):
  452. return self._NODESPRITE_DATA["rect"][2]
  453. @rect_width.setter
  454. def rect_width(self, v):
  455. if not isinstance(v, int):
  456. raise TypeError("Expected integer value.")
  457. self._NODESPRITE_DATA["rect"][2] = v
  458. self._NODESPRITE_ValidateRect()
  459. @property
  460. def rect_height(self):
  461. return self._NODESPRITE_DATA["rect"][3]
  462. @rect_height.setter
  463. def rect_height(self, v):
  464. if not isinstance(v, int):
  465. raise TypeError("Expected integer value.")
  466. self._NODESPRITE_DATA["rect"][3] = v
  467. self._NODESPRITE_ValidateRect()
  468. @property
  469. def center(self):
  470. r = self._NODESPRITE_DATA["rect"]
  471. return (int(r[0] + (r[2] * 0.5)), int(r[1] + (r[3] * 0.5)))
  472. @property
  473. def scale(self):
  474. return (self._NODESPRITE_DATA["scale"][0], self._NODESPRITE_DATA["scale"][1])
  475. @scale.setter
  476. def scale(self, scale):
  477. if not isinstance(scale, (list, tuple)):
  478. raise TypeError("Expected a list or tuple.")
  479. if len(scale) != 2:
  480. raise ValueError("Scale contains wrong number of values.")
  481. try:
  482. self.scale_x = scale[0]
  483. self.scale_y = scale[1]
  484. except Exception as e:
  485. raise e
  486. @property
  487. def scale_x(self):
  488. return self._NODESPRITE_DATA["scale"][0]
  489. @scale_x.setter
  490. def scale_x(self, v):
  491. if not isinstance(v, (int, float)):
  492. raise TypeError("Expected number value.")
  493. self._NODESPRITE_DATA["scale"][0] = float(v)
  494. self._NODESPRITE_DATA["scale_dirty"] = True
  495. @property
  496. def scale_y(self):
  497. return self._NODESPRITE_DATA["scale"][1]
  498. @scale_y.setter
  499. def scale_y(self, v):
  500. if not isinstance(v, (int, float)):
  501. raise TypeError("Expected number value.")
  502. self._NODESPRITE_DATA["scale"][1] = float(v)
  503. self._NODESPRITE_DATA["scale_dirty"] = True
  504. @property
  505. def image(self):
  506. return self._NODESPRITE_DATA["image"]
  507. @image.setter
  508. def image(self, src):
  509. src = src.strip()
  510. if self._NODESPRITE_DATA["image"] == src:
  511. return # Nothing to change... lol
  512. if self._NODESPRITE_DATA["image"] != "":
  513. self._NODESPRITE_DATA["surface"] = None # Clear reference to original surface.
  514. if src != "":
  515. rm = self.resource
  516. try:
  517. if not rm.has("graphic", src):
  518. rm.store("graphic", src)
  519. self._NODESPRITE_DATA["image"] = src
  520. self._NODESPRITE_DATA["surface"] = rm.get("graphic", src)
  521. if self._NODESPRITE_DATA["surface"] is None:
  522. self._NODESPRITE_DATA["image"] = ""
  523. self._NODESPRITE_DATA["rect"]=[0,0,0,0]
  524. else:
  525. # Resetting the rect to identity for the new image.
  526. surf = self._NODESPRITE_DATA["surface"]()
  527. size = surf.get_size()
  528. self._NODESPRITE_DATA["rect"]=[0,0,size[0], size[1]]
  529. except Exception as e:
  530. raise e
  531. else:
  532. self._NODESPRITE_DATA["image"] = ""
  533. self._NODESPRITE_DATA["rect"]=[0,0,0,0]
  534. def _render(self, surface):
  535. # Call the on_render() method, if any
  536. Node2D._callOnRender(self, surface)
  537. # Paint the sprite onto the surface
  538. if self._NODESPRITE_DATA["surface"] is not None:
  539. rect = self._NODESPRITE_DATA["rect"]
  540. scale = self._NODESPRITE_DATA["scale"]
  541. surf = self._NODESPRITE_DATA["surface"]()
  542. # Of course, only bother if we have a surface to work with.
  543. if surf is not None:
  544. # Do some prescaling work, if needed.
  545. if self._NODESPRITE_DATA["scale_dirty"]:
  546. self._NODESPRITE_UpdateScaleSurface(scale, surf)
  547. fsurf = surf # Initial assumption that the surface is also the "frame"
  548. # If we have a "frame" surface, however, let's get it and blit the rect into the frame surface.
  549. if "frame_surf" in self._NODESPRITE_DATA:
  550. fsurf = self._NODESPRITE_DATA["frame_surf"]
  551. fsurf.blit(surf, (0, 0), rect)
  552. # If scaling, then transform (scale) the frame surface into the scale surface and set the frame surface to the scale surface.
  553. if "scale_surf" in self._NODESPRITE_DATA:
  554. ssurf = self._NODESPRITE_DATA["scale_surf"]
  555. pygame.transform.scale(fsurf, ssurf.get_size(), ssurf)
  556. fsurf = ssurf
  557. # Place the sprite! WHEEEEE!
  558. pos = self.position
  559. surface.blit(fsurf, pos)
  560. # Call on all children
  561. Node._render(self, surface)
  562. def _NODESPRITE_UpdateScaleSurface(self, scale, surf):
  563. self._NODESPRITE_DATA["scale_dirty"] = False
  564. ssurf = None
  565. if "scale_surf" in self._NODESPRITE_DATA:
  566. ssurf = self._NODESPRITE_DATA["scale_surf"]
  567. if scale[0] == 1.0 and scale[1] == 1.0:
  568. if ssurf is not None:
  569. del self._NODESPRITE_DATA["scale_surf"]
  570. return
  571. nw = int(self.rect_width * scale[0])
  572. nh = int(self.rect_height * scale[1])
  573. if nw != ssurf.get_width() or nh != ssurf.get_height():
  574. ssurf = pygame.Surface((nw, nh), pygame.SRCALPHA, surf)
  575. ssurf.fill(pygame.Color(0,0,0,0))
  576. self._NODESPRITE_DATA["scale_surf"] = ssurf
  577. def _NODESPRITE_ValidateRect(self):
  578. if self._NODESPRITE_DATA["surface"] is None:
  579. self._NODESPRITE_DATA["rect"] = [0,0,0,0]
  580. else:
  581. rect = self._NODESPRITE_DATA["rect"]
  582. isize = (self.image_width, self.image_height)
  583. if rect[0] < 0:
  584. rect[2] += rect[0]
  585. rect[0] = 0
  586. elif rect[0] >= isize[0]:
  587. rect[0] = isize[0]-1
  588. rect[2] = 0
  589. if rect[1] < 0:
  590. rect[3] += rect[1]
  591. rect[1] = 0
  592. elif rect[1] >= isize[1]:
  593. rect[1] = isize[1]-1
  594. rect[3] = 0
  595. if rect[2] < 0:
  596. rect[2] = 0
  597. elif rect[0] + rect[2] > isize[0]:
  598. rect[2] = isize[0] - rect[0]
  599. if rect[3] < 0:
  600. rect[3] = 0
  601. elif rect[1] + rect[3] > isize[1]:
  602. rect[3] = isize[1] - rect[1]
  603. fssize = [0,0]
  604. if rect[2] > 0 and rect[3] > 0:
  605. if rect[2] < isize[0] or rect[1] < isize[1]:
  606. surf = self._NODESPRITE_DATA["surface"]()
  607. self._NODESPRITE_DATA["frame_surf"] = pygame.Surface((rect[2], rect[3]), pygame.SRCALPHA, surf)
  608. if fssize[0] > 0 and fssize[1] > 0:
  609. pass
  610. elif "frame_surf" in self._NODESPRITE_DATA:
  611. del self._NODESPRITE_DATA["frame_surf"]