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.

766 lines
29KB

  1. from . import gbe
  2. import pygame
  3. class NodeOptions(gbe.nodes.Node2D):
  4. def __init__(self, name="Options", parent=None):
  5. try:
  6. gbe.nodes.Node2D.__init__(self, name, parent)
  7. except gbe.nodes.NodeError as e:
  8. raise e
  9. self._options = []
  10. self._oindex = 0
  11. self._color_select = (255,255,0)
  12. self._color_idle = (255,255,255)
  13. def add_option(self, font_src, size, text, event, params={}):
  14. nodeName = "OpText{}".format(len(self._options))
  15. nodeOption = gbe.nodes.NodeText(nodeName, self)
  16. nodeOption.font_src = font_src
  17. nodeOption.size = size
  18. nodeOption.text = text
  19. nodeOption.antialias = False
  20. if len(self._options) == 0:
  21. nodeOption.set_color(*self._color_select)
  22. else:
  23. nodeOption.set_color(*self._color_idle)
  24. li = len(self._options)-1
  25. lp = self._options[li][0].position
  26. ls = self._options[li][0].size
  27. nodeOption.position = (lp[0], lp[1] + ls + 1)
  28. self._options.append([nodeOption, event, params])
  29. def on_start(self):
  30. self.listen("KEYPRESSED", self.on_keypressed)
  31. def on_pause(self):
  32. self.unlisten("KEYPRESSED", self.on_keypressed)
  33. def on_keypressed(self, event, params):
  34. if params["key_name"] == "w":
  35. if self._oindex > 0:
  36. self._options[self._oindex][0].set_color(*self._color_idle)
  37. self._oindex -= 1
  38. self._options[self._oindex][0].set_color(*self._color_select)
  39. elif params["key_name"] == "s":
  40. if self._oindex < len(self._options) - 1:
  41. self._options[self._oindex][0].set_color(*self._color_idle)
  42. self._oindex += 1
  43. self._options[self._oindex][0].set_color(*self._color_select)
  44. elif params["key_name"] in ["enter", "return"]:
  45. if len(self._options) > 0:
  46. op = self._options[self._oindex]
  47. self.emit(op[1], op[2])
  48. elif params["key_name"] == "escape":
  49. self.emit("QUIT")
  50. class NodeGameMap(gbe.nodes.Node2D):
  51. def __init__(self, name="GameMap", parent=None):
  52. try:
  53. gbe.nodes.Node2D.__init__(self, name, parent)
  54. except gbe.nodes.NodeError as e:
  55. raise e
  56. self._renderMode = 0 # 0 = Top-down | 1 = Perspective
  57. self._layer = {}
  58. self._currentLayer = ""
  59. self._res = {
  60. "env_src":"",
  61. "env":None,
  62. "h_index":0,
  63. "g_index":0,
  64. "wall_src":"",
  65. "walls":None,
  66. "wall_index":-1,
  67. "door_index":-1
  68. }
  69. self._topdown = {
  70. "size":8, # Pixels square
  71. "wall_color":pygame.Color(255, 255, 255),
  72. "blocked_color":pygame.Color(255, 0, 0)
  73. }
  74. self._cellpos = [0,0]
  75. self._orientation = "n"
  76. @property
  77. def environment_source(self):
  78. return self._res["env_src"]
  79. @property
  80. def wall_source(self):
  81. return self._res["wall_src"]
  82. @property
  83. def layer_count(self):
  84. return len(self._layer)
  85. @property
  86. def current_layer(self):
  87. return self._currentLayer
  88. @property
  89. def current_layer_width(self):
  90. if self._currentLayer != "":
  91. return self._layer[self._currentLayer]["w"]
  92. return 0
  93. @property
  94. def current_layer_height(self):
  95. if self._currentLayer != "":
  96. return self._layer[self._currentLayer]["h"]
  97. return 0
  98. @property
  99. def layer_names(self):
  100. names = []
  101. for key in self._layer:
  102. names.append(names)
  103. return names
  104. @property
  105. def orientation(self):
  106. return self._orientation
  107. @property
  108. def cell_position(self):
  109. return (self._cellpos[0], self._cellpos[1])
  110. def set_resources(self, env_src, wall_src):
  111. res = self.resource
  112. if env_src != "" and env_src != self._res["env_src"]:
  113. if res.is_valid("json", env_src):
  114. if not res.has("json", env_src):
  115. res.store("json", env_src)
  116. e = res.get("json", env_src)
  117. if e is not None and e() is not None:
  118. self._res["env_src"] = env_src
  119. self._res["env"] = e
  120. # NOTE: Making a lot of assumptions to the structural validity of the data file.
  121. isrc1 = e().data["horizon"]["src"]
  122. isrc2 = e().data["ground"]["src"]
  123. if res.is_valid("graphic", isrc1) and res.is_valid("graphic", isrc2):
  124. if not res.has("graphic", isrc1):
  125. res.store("graphic", isrc1)
  126. if not res.has("graphic", isrc2):
  127. res.store("graphic", isrc2)
  128. if wall_src != "" and wall_src != self._res["wall_src"]:
  129. if res.is_valid("json", wall_src):
  130. if not res.has("json", wall_src):
  131. print("Storing resource {}".format(wall_src))
  132. res.store("json", wall_src)
  133. w = res.get("json", wall_src)
  134. if w is not None and w() is not None:
  135. self._res["wall_src"] = wall_src
  136. self._res["walls"] = w
  137. # NOTE: I'm making a lot of assumptions to the structural validity of the data file, but...
  138. imgsrc = w().data["src"]
  139. if res.is_valid("graphic", imgsrc):
  140. if not res.has("graphic", imgsrc):
  141. res.store("graphic", imgsrc)
  142. else:
  143. print("Failed to get JSON instance {}".format(wall_src))
  144. else:
  145. print("Invalid JSON {}".format(wall_src))
  146. def add_layer(self, name, w, h):
  147. if name == "" or name in self._layer:
  148. return
  149. self._layer[name] = {
  150. "w":w,
  151. "h":h,
  152. "cells":[]
  153. }
  154. for c in range(0, w*h):
  155. self._layer[name]["cells"].append({
  156. "h":0, # Horizon
  157. "g":0, # Ground
  158. "n":[-1, False, -1, None], # North Wall | [<graphic index, -1 = None>, <blocking>, <door index, -1 = None, 0 = closed, 1=open>, <door target>]
  159. "s":[-1, False, -1, None], # South Wall
  160. "e":[-1, False, -1, None], # East Wall
  161. "w":[-1, False, -1, None], # West Wall
  162. })
  163. if self._currentLayer == "":
  164. self._currentLayer = name
  165. def set_active_layer(self, name, x=0, y=0):
  166. if name == "" or not (name in self._layers):
  167. return
  168. layer = self._layers[name]
  169. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  170. self._currentLayer = name
  171. self._cellpos = [x,y]
  172. def set_cell_env(self, x, y, ceiling=-1, ground=-1):
  173. if self._currentLayer == "":
  174. return
  175. layer = self._layer[self._currentLayer]
  176. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  177. index = (y * layer["w"]) + x
  178. cell = layer["cells"]
  179. if ceiling >= 0:
  180. cell[index]["c"] = ceiling
  181. if ground >= 0:
  182. cell[index]["g"] = ground
  183. def fill_cell_env(self, x1, y1, x2, y2, ceiling=-1, ground=-1):
  184. if self._currentLayer == "":
  185. return
  186. for y in range(y1, y2+1):
  187. for x in range(x1, x2+1):
  188. self.set_cell_env(x, y, ceiling, ground)
  189. def set_cell_face(self, x, y, face, gi=-2, blocking=None):
  190. if self._currentLayer == "" or not (face == "n" or face == "s" or face == "w" or face == "e"):
  191. return
  192. layer = self._layer[self._currentLayer]
  193. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  194. index = (y * layer["w"]) + x
  195. cell = layer["cells"]
  196. if gi <= -2:
  197. gi = self._res["wall_index"]
  198. if gi >= -1:
  199. cell[index][face][0] = gi
  200. if blocking is not None:
  201. cell[index][face][1] = (blocking == True)
  202. else:
  203. if gi == -1: # If gi = -1, there is no wall, so, by default, there is no blocking.
  204. cell[index][face][1] = False
  205. else: # Otherwise, blocking is assumed :)
  206. cell[index][face][1] = True
  207. elif blocking is not None:
  208. blocking = (blocking == True) # Forcing a boolean
  209. cell[index][face][1] = blocking
  210. def next_wall(self):
  211. if self._res["walls"] is not None:
  212. w = self._res["walls"]()
  213. if w is not None:
  214. windex = self._res["wall_index"] + 1
  215. if windex >= len(w.data["walls"]):
  216. windex = -1
  217. self._res["wall_index"] = windex
  218. print("Next Wall Index: {}".format(windex))
  219. def prev_wall(self):
  220. if self._res["walls"] is not None:
  221. w = self._res["walls"]()
  222. if w is not None:
  223. windex = self._res["wall_index"] - 1
  224. if windex < -1:
  225. windex = len(w.data["walls"]) - 1
  226. self._res["wall_index"] = windex
  227. print("Prev Wall Index: {}".format(windex))
  228. def turn_left(self):
  229. onum = self._d_s2n(self._orientation)
  230. onum -= 1
  231. if onum < 0:
  232. onum = 3
  233. self._orientation = self._d_n2s(onum)
  234. def turn_right(self):
  235. onum = self._d_s2n(self._orientation)
  236. onum += 1
  237. if onum > 3:
  238. onum = 0
  239. self._orientation = self._d_n2s(onum)
  240. def move_to(self, x, y):
  241. if x >= 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  242. self._cellpos = [x, y]
  243. def move_forward(self, ignore_passible=False):
  244. if ignore_passible or self.is_passible(self._cellpos[0], self._cellpos[1], self._orientation):
  245. x = self._cellpos[0]
  246. y = self._cellpos[1]
  247. if self._orientation == "n":
  248. y -= 1
  249. elif self._orientation == "e":
  250. x += 1
  251. elif self._orientation == "s":
  252. y += 1
  253. elif self._orientation == "w":
  254. x -= 1
  255. self.move_to(x, y)
  256. def move_backward(self, ignore_passible=False):
  257. orient = self._orientation
  258. if self._orientation == "n":
  259. self._orientation = "s"
  260. elif self._orientation == "s":
  261. self._orientation = "n"
  262. elif self._orientation == "e":
  263. self._orientation = "w"
  264. elif self._orientation == "w":
  265. self._orientation = "e"
  266. self.move_forward(ignore_passible)
  267. self._orientation = orient
  268. def is_passible(self, x, y, d):
  269. """
  270. Returns true if it's possible to move forward from the x, y map position in the direction given.
  271. d - 0 = North, 1 = East, 2 = South, 3 = West
  272. """
  273. if self._currentLayer == "" or d < 0 or d >= 4:
  274. return False
  275. layer = self._layer[self._currentLayer]
  276. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  277. index = (y * layer["w"]) + x
  278. d = self._d_n2s(d)
  279. return not layer["cells"][index][d][1]
  280. return False
  281. def toggle_render_mode(self):
  282. if self._renderMode == 0:
  283. self._renderMode = 1
  284. else:
  285. self._renderMode = 0
  286. def set_render_mode(self, mode):
  287. if mode <= 0:
  288. self._renderMode = 0
  289. else:
  290. self._renderMode = 1
  291. def get_render_mode(self):
  292. return self._renderMode
  293. def _d_n2s(self, d): # _(d)irection_(n)umber_to_(s)tring
  294. if d == 0:
  295. return "n"
  296. elif d == 1:
  297. return "e"
  298. elif d == 2:
  299. return "s"
  300. elif d == 3:
  301. return "w"
  302. return ""
  303. def _d_s2n(self, d):
  304. if d == "n":
  305. return 0
  306. elif d == "e":
  307. return 1
  308. elif d == "s":
  309. return 2
  310. elif d == "w":
  311. return 3
  312. return -1
  313. def _indexFromPos(self, x, y):
  314. if x >= 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  315. return (y * self.current_layer_width) + x
  316. return -1
  317. def _getCell(self, x, y):
  318. if x >=- 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  319. index = self._indexFromPos(x, y)
  320. return self._layer[self._currentLayer]["cells"][index]
  321. return None
  322. def _getOrientVec(self):
  323. if self._orientation == "n":
  324. return (0, -1)
  325. elif self._orientation == "s":
  326. return (0, 1)
  327. elif self._orientation == "e":
  328. return (1, 0)
  329. elif self._orientation == "w":
  330. return (-1, 0)
  331. return (0,0)
  332. def _RenderTopDown(self):
  333. cell_size = self._topdown["size"]
  334. size = self.resolution
  335. pos = self._cellpos
  336. lsize = (self.current_layer_width, self.current_layer_height)
  337. hcells = int(size[0] / cell_size)
  338. vcells = int(size[1] / cell_size)
  339. cx = pos[0] - int(hcells * 0.5)
  340. cy = pos[1] - int(vcells * 0.5)
  341. ry = -int(cell_size*0.5)
  342. for j in range(0, vcells+1):
  343. y = cy + j
  344. if y >= 0 and y < lsize[1]:
  345. rx = -int(cell_size*0.5)
  346. for i in range(0, hcells+1):
  347. x = cx + i
  348. if x >= 0 and x < lsize[0]:
  349. cell = self._getCell(x, y)
  350. if cell["n"][0] >= 0:
  351. self.draw_rect((rx, ry, cell_size, 2), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  352. if cell["e"][0] >= 0:
  353. self.draw_rect((rx+(cell_size-2), ry, 2, cell_size), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  354. if cell["s"][0] >= 0:
  355. self.draw_rect((rx, ry+(cell_size-2), cell_size, 2), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  356. if cell["w"][0] >= 0:
  357. self.draw_rect((rx, ry, 2, cell_size), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  358. if cell["n"][1] == True:
  359. self.draw_lines([(rx+1, ry+1), (rx+(cell_size-2), ry+1)], self._topdown["blocked_color"], 1)
  360. if cell["e"][1] == True:
  361. self.draw_lines([(rx+(cell_size-2), ry+1), (rx+(cell_size-2), ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  362. if cell["s"][1] == True:
  363. self.draw_lines([(rx+1, ry+(cell_size-2)), (rx+(cell_size-2), ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  364. if cell["w"][1] == True:
  365. self.draw_lines([(rx+1, ry+1), (rx+1, ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  366. rx += cell_size
  367. ry += cell_size
  368. def _RenderPersFar(self, pos, size, o, orr, orl, wdat, wsurf):
  369. ovec = self._getOrientVec()
  370. fx = pos[0] + (ovec[0]*2)
  371. fy = pos[1] + (ovec[1]*2)
  372. fcell = self._getCell(fx, fy)
  373. if fcell == None:
  374. return # If we can't see the cell directly ahead, the other's won't be visible either!
  375. lcell = llcell = rcell = rrcell = None
  376. if ovec[0] == 0: # Facing North/South
  377. lcell = self._getCell(fx + ovec[1], fy)
  378. llcell = self._getCell(fx + (ovec[1]*2), fy)
  379. rcell = self._getCell(fx - ovec[1], fy)
  380. rrcell = self._getCell(fx - (ovec[1]*2), fy)
  381. else: # Facing East/West
  382. lcell = self._getCell(fx, fy - ovec[0])
  383. llcell = self._getCell(fx, fy - (ovec[0]*2))
  384. rcell = self._getCell(fx, fy + ovec[0])
  385. rrcell = self._getCell(fx, fy + (ovec[0]*2))
  386. hsw = int(size[0]*0.5)
  387. hsh = int(size[1]*0.5)
  388. # Rendering from edges to center
  389. if llcell is not None:
  390. if llcell[o][0] >= 0:
  391. rect = wdat["walls"][llcell[o][0]]["f_far"]
  392. hw = int(rect[2]*0.5)
  393. hh = int(rect[3]*0.5)
  394. self.draw_image(wsurf, (0, hsh-hh), (rect[0], rect[1], hw, rect[3]))
  395. if rrcell is not None:
  396. if rrcell[o][0] >= 0:
  397. rect = wdat["walls"][rrcell[o][0]]["f_far"]
  398. hw = int(rect[2]*0.5)
  399. hh = int(rect[3]*0.5)
  400. self.draw_image(wsurf, (size[0]-hw, hsh-hh), (rect[0]+hw, rect[1], hw, rect[3]))
  401. if lcell is not None:
  402. if lcell[o][0] >= 0:
  403. rect = wdat["walls"][lcell[o][0]]["f_far"]
  404. hw = int(rect[2]*0.5)
  405. hh = int(rect[3]*0.5)
  406. self.draw_image(wsurf, (hw, hsh-hh), (rect[0], rect[1], rect[2], rect[3]))
  407. if lcell[orl][0] >= 0:
  408. rect = wdat["walls"][lcell[orl][0]]["s_far"]
  409. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  410. hh = int(rect[3]*0.5)
  411. self.draw_image(lsurf, (0, hsh-hh))
  412. if rcell is not None:
  413. if rcell[o][0] >= 0:
  414. rect = wdat["walls"][rcell[o][0]]["f_far"]
  415. hw = int(rect[2]*0.5)
  416. hh = int(rect[3]*0.5)
  417. self.draw_image(wsurf, (size[0]-(rect[2]+hw), hsh-hh), (rect[0], rect[1], rect[2], rect[3]))
  418. if rcell[orr][0] >= 0:
  419. rect = wdat["walls"][rcell[orr][0]]["s_far"]
  420. hh = int(rect[3]*0.5)
  421. self.draw_image(wsurf, (size[0]-rect[2], hsh-hh), (rect[0], rect[1], rect[2], rect[3]))
  422. # Rendering the main cell!!
  423. frect = None # This will be used to place walls
  424. if fcell[o][0] >= 0:
  425. frect = wdat["walls"][fcell[o][0]]["f_far"]
  426. hw = int(frect[2]*0.5)
  427. hh = int(frect[3]*0.5)
  428. self.draw_image(wsurf, (hsw-hw, hsh-hh), (frect[0], frect[1], frect[2], frect[3]))
  429. if fcell[orl][0] >= 0:
  430. rect = wdat["walls"][fcell[orl][0]]["s_far"]
  431. if frect is None:
  432. # Kinda cheating in that it's known that all walls are the same size.
  433. frect = wdat["walls"][fcell[orl][0]]["f_far"]
  434. hw = int(frect[2]*0.5)
  435. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  436. self.draw_image(lsurf, (hsw-(hw+rect[2]), hsh-int(rect[3]*0.5)))
  437. if fcell[orr][0] >= 0:
  438. rect = wdat["walls"][fcell[orr][0]]["s_far"]
  439. if frect is None:
  440. frect = wdat["walls"][fcell[orr][0]]["f_far"]
  441. hw = int(frect[2]*0.5)
  442. self.draw_image(wsurf, (hsw+hw, hsh-int(rect[3]*0.5)), (rect[0], rect[1], rect[2], rect[3]))
  443. def _RenderPersMid(self, pos, size, o, orr, orl, wdat, wsurf):
  444. ovec = self._getOrientVec()
  445. fx = pos[0] + ovec[0]
  446. fy = pos[1] + ovec[1]
  447. fcell = self._getCell(fx, fy)
  448. if fcell == None:
  449. return # If we can't see the cell directly ahead, the other's won't be visible either!
  450. lcell = rcell = None
  451. if ovec[0] == 0: # Facing North/South
  452. lcell = self._getCell(fx + ovec[1], fy)
  453. rcell = self._getCell(fx - ovec[1], fy)
  454. else: # Facing East/West
  455. lcell = self._getCell(fx, fy - ovec[0])
  456. rcell = self._getCell(fx, fy + ovec[0])
  457. hsw = int(size[0]*0.5)
  458. hsh = int(size[1]*0.5)
  459. # Render from outside inwards!
  460. if lcell is not None:
  461. if lcell[o][0] >= 0:
  462. rect = wdat["walls"][lcell[o][0]]["f_mid"]
  463. hw = int(rect[2]*0.5)
  464. hh = int(rect[3]*0.5)
  465. self.draw_image(wsurf, (0, hsh-hh), (rect[0]+hw, rect[1], int(rect[2]*0.5), rect[3]))
  466. if rcell is not None:
  467. if rcell[o][0] >= 0:
  468. rect = wdat["walls"][rcell[o][0]]["f_mid"]
  469. hw = int(rect[2]*0.5)
  470. hh = int(rect[3]*0.5)
  471. self.draw_image(wsurf, (size[0]-hw, hsh-hh), (rect[0], rect[1], hw, rect[3]))
  472. # Rendering the main cell!!
  473. frect = None # This will be used to place walls
  474. if fcell[o][0] >= 0:
  475. frect = wdat["walls"][fcell[o][0]]["f_mid"]
  476. hw = int(frect[2]*0.5)
  477. hh = int(frect[3]*0.5)
  478. self.draw_image(wsurf, (hsw-hw, hsh-hh), (frect[0], frect[1], frect[2], frect[3]))
  479. if fcell[orl][0] >= 0:
  480. rect = wdat["walls"][fcell[orl][0]]["s_mid"]
  481. if frect is None:
  482. # Kinda cheating in that it's known that all walls are the same size.
  483. frect = wdat["walls"][fcell[orl][0]]["f_mid"]
  484. hw = int(frect[2]*0.5)
  485. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  486. self.draw_image(lsurf, (hsw-(hw+rect[2]), hsh-int(rect[3]*0.5)))
  487. if fcell[orr][0] >= 0:
  488. rect = wdat["walls"][fcell[orr][0]]["s_mid"]
  489. if frect is None:
  490. frect = wdat["walls"][fcell[orr][0]]["f_mid"]
  491. hw = int(frect[2]*0.5)
  492. self.draw_image(wsurf, (hsw+hw, hsh-int(rect[3]*0.5)), (rect[0], rect[1], rect[2], rect[3]))
  493. def _RenderPersClose(self, pos, size, o, orr, orl, cell, wdat, wsurf):
  494. fcell = self._getCell(pos[0], pos[1])
  495. hsw = int(size[0]*0.5)
  496. hsh = int(size[1]*0.5)
  497. ovec = self._getOrientVec()
  498. lcell = rcell = None
  499. if ovec[0] == 0: # Facing North/South
  500. lcell = self._getCell(pos[0] + ovec[1], pos[1])
  501. rcell = self._getCell(pos[0] - ovec[1], pos[1])
  502. else: # Facing East/West
  503. lcell = self._getCell(pos[0], pos[1] - ovec[0])
  504. rcell = self._getCell(pos[0], pos[1] + ovec[0])
  505. hsw = int(size[0]*0.5)
  506. hsh = int(size[1]*0.5)
  507. # Render from outside inwards!
  508. if lcell is not None:
  509. if lcell[o][0] >= 0:
  510. rect = wdat["walls"][lcell[o][0]]["f_close"]
  511. hw = int(rect[2]*0.5)
  512. hh = int(rect[3]*0.5)
  513. rw = hsw - hw
  514. self.draw_image(wsurf, (0, hsh-hh), (rect[0]+(rect[2]-rw), rect[1], rw, rect[3]))
  515. if rcell is not None:
  516. if rcell[o][0] >= 0:
  517. rect = wdat["walls"][rcell[o][0]]["f_close"]
  518. hw = int(rect[2]*0.5)
  519. hh = int(rect[3]*0.5)
  520. rw = hsw - hw
  521. self.draw_image(wsurf, (size[0]-rw, hsh-hh), (rect[0], rect[1], rw, rect[3]))
  522. # Rendering the main cell!!
  523. frect = None # This will be used to place walls
  524. if fcell[o][0] >= 0:
  525. idx = fcell[o][0]
  526. frect = wdat["walls"][idx]["f_close"]
  527. hw = int(frect[2]*0.5)
  528. hh = int(frect[3]*0.5)
  529. self.draw_image(wsurf, (hsw-hw, hsh-hh), (frect[0], frect[1], frect[2], frect[3]))
  530. if fcell[orl][0] >= 0:
  531. idx = fcell[orl][0]
  532. rect = wdat["walls"][idx]["s_close"]
  533. if frect is None:
  534. # Kinda cheating in that it's known that all walls are the same size.
  535. frect = wdat["walls"][idx]["f_close"]
  536. hw = int(frect[2]*0.5)
  537. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  538. self.draw_image(lsurf, (hsw-(hw+rect[2]), hsh-int(rect[3]*0.5)))
  539. if fcell[orr][0] >= 0:
  540. idx = fcell[orr][0]
  541. rect = wdat["walls"][idx]["s_close"]
  542. if frect is None:
  543. frect = wdat["walls"][idx]["f_close"]
  544. hw = int(frect[2]*0.5)
  545. self.draw_image(wsurf, (hsw+hw, hsh-int(rect[3]*0.5)), (rect[0], rect[1], rect[2], rect[3]))
  546. def _RenderPerspective(self):
  547. # Getting ALL of the core resources
  548. rm = self.resource
  549. edat = self._res["env"]
  550. wdat = self._res["walls"]
  551. if edat is None or wdat is None or edat() is None or wdat() is None:
  552. return
  553. edat = edat().data
  554. wdat = wdat().data
  555. ehsurf = rm.get("graphic", edat["horizon"]["src"])
  556. egsurf = rm.get("graphic", edat["ground"]["src"])
  557. wsurf = rm.get("graphic", wdat["src"])
  558. if ehsurf is None or egsurf is None or wsurf is None:
  559. return
  560. if ehsurf() is None or egsurf() is None or wsurf() is None:
  561. return
  562. oshift = lambda d: d if d >= 0 and d < 4 else (0 if d > 3 else 3)
  563. px = self._cellpos[0]
  564. py = self._cellpos[1]
  565. orl = self._d_n2s(oshift(self._d_s2n(self._orientation) - 1))
  566. orr = self._d_n2s(oshift(self._d_s2n(self._orientation) + 1))
  567. cell = self._getCell(px, py)
  568. # First, output the ground and horizon
  569. # TODO Later, perhaps cut the horizon and ground to represent each possible cell instead of just the current one?
  570. self.draw_image(ehsurf(), (0,0), edat["horizon"]["defs"][cell["h"]]["rect"])
  571. self.draw_image(egsurf(), (0,32), edat["ground"]["defs"][cell["g"]]["rect"])
  572. # Rendering the rest
  573. size = self.resolution
  574. self._RenderPersFar((px, py), size, self._orientation, orr, orl, wdat, wsurf())
  575. self._RenderPersMid((px, py), size, self._orientation, orr, orl, wdat, wsurf())
  576. self._RenderPersClose((px, py), size, self._orientation, orr, orl, cell, wdat, wsurf())
  577. def on_render(self):
  578. if self._renderMode == 0:
  579. self._RenderTopDown()
  580. else:
  581. self._RenderPerspective()
  582. class NodeMapEditor(gbe.nodes.Node2D):
  583. def __init__(self, name="MapEditor", parent=None):
  584. try:
  585. gbe.nodes.Node2D.__init__(self, name, parent)
  586. except gbe.nodes.Node2D as e:
  587. raise e
  588. self._last_orientation = ""
  589. self._size = 0
  590. self._thickness = 1
  591. self._color = pygame.Color(255,255,255)
  592. self._points = None
  593. self.pointer_size = 4
  594. def _getPoints(self, size):
  595. p = self.parent
  596. o = p.orientation
  597. points = self._points[o]
  598. hw = int(size[0]*0.5)
  599. hh = int(size[1]*0.5)
  600. return (
  601. (points[0][0] + hw, points[0][1] + hh),
  602. (points[1][0] + hw, points[1][1] + hh),
  603. (points[2][0] + hw, points[2][1] + hh)
  604. )
  605. @property
  606. def pointer_size(self):
  607. return self._size
  608. @pointer_size.setter
  609. def pointer_size(self, size):
  610. if not isinstance(size, int):
  611. raise TypeError("Size expected to be an integer.")
  612. if size <= 0:
  613. raise ValueError("Size must be greater than zero.")
  614. if size != self._size:
  615. self._size = size
  616. # Now updating all of the pointer... ummm... points
  617. hs = max(1, int(size * 0.5))
  618. self._points = {
  619. "n": ((0,-hs),(hs,hs),(-hs,hs)),
  620. "s": ((0,hs),(hs,-hs),(-hs,-hs)),
  621. "e": ((-hs,hs),(hs,0),(-hs,-hs)),
  622. "w": ((hs,hs),(-hs,0),(hs,-hs))
  623. }
  624. def set_color(self, color):
  625. if isinstance(color, (tuple, list)):
  626. clen = len(color)
  627. if clen == 3 or clen == 4:
  628. iscolor = lambda v : isinstance(v, int) and v >= 0 and v < 256
  629. if iscolor(color[0]) and iscolor(color[1]) and iscolor(color[2]):
  630. if clen == 3:
  631. self._color = pygame.Color(color[0], color[1], color[2])
  632. elif clen == 4 and iscolor(color[3]):
  633. self._color = pygame.Color(color[0], color[1], color[2], color[3])
  634. def get_color(self):
  635. return (self._color.r, self._color.g, self._color.b, self._color.a)
  636. def on_start(self):
  637. self.listen("KEYPRESSED", self.on_keypressed)
  638. def on_pause(self):
  639. self.unlisten("KEYPRESSED", self.on_keypressed)
  640. def on_keypressed(self, event, data):
  641. p = self.parent
  642. if p is None or not isinstance(p, NodeGameMap):
  643. return
  644. if data["key_name"] == "escape":
  645. self.emit("SCENECHANGE", {"scene":"MAIN_MENU", "hold":False})
  646. #self.emit("QUIT")
  647. if data["key_name"] == "tab":
  648. p.toggle_render_mode()
  649. elif data["key_name"] == "w":
  650. p.move_forward(True)
  651. elif data["key_name"] == "s":
  652. p.move_backward(True)
  653. elif data["key_name"] == "a":
  654. p.turn_left()
  655. elif data["key_name"] == "d":
  656. p.turn_right()
  657. elif data["key_name"] == "space":
  658. o = p.orientation
  659. cpos = p.cell_position
  660. p.set_cell_face(cpos[0], cpos[1], o)
  661. elif data["key_name"] == "e":
  662. p.next_wall()
  663. elif data["key_name"] == "q":
  664. p.prev_wall()
  665. def on_render(self):
  666. size = self.resolution
  667. self.draw_lines(self._getPoints(size), self._color, self._thickness, True)