Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

729 lines
24KB

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